aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--.gitmodules9
-rw-r--r--Makefile166
-rw-r--r--README.md163
-rwxr-xr-xbin/debug14
-rwxr-xr-xbin/dfu16
-rwxr-xr-xbin/flash-target6
-rwxr-xr-xbin/reset6
m---------libraries/libcli0
-rw-r--r--libraries/libcli/Makefile24
m---------libraries/libhal0
-rw-r--r--libraries/libhal/Makefile8
-rw-r--r--libraries/libhal/tests/Makefile4
-rw-r--r--libraries/libhal/utils/Makefile4
-rw-r--r--libraries/libprof/Makefile24
-rw-r--r--libraries/libprof/README.md65
-rw-r--r--libraries/libprof/gmon.c261
-rw-r--r--libraries/libprof/gmon.h148
-rw-r--r--libraries/libprof/memfunc.c127
-rwxr-xr-xlibraries/libprof/profile-runner.py73
-rw-r--r--libraries/libprof/profiler.S28
-rw-r--r--libraries/libtfm/Makefile71
-rw-r--r--libraries/libtfm/fp_to_unsigned_bin.c62
-rw-r--r--libraries/libtfm/tomsfastmath/Makefile4
-rw-r--r--libraries/mbed/Makefile4
-rw-r--r--libraries/mbed/rtos/Makefile40
-rw-r--r--libraries/mbed/rtos/rtos/rtos_idle.c51
-rw-r--r--libraries/mbed/rtos/rtos/rtos_idle.h37
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/HAL_CM.c170
-rwxr-xr-xlibraries/mbed/rtos/rtx/TARGET_CORTEX_M/RTX_CM_lib.h537
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/RTX_Conf.h72
-rwxr-xr-xlibraries/mbed/rtos/rtx/TARGET_CORTEX_M/RTX_Conf_CM.c342
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_GCC/HAL_CM4.S405
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_GCC/SVC_Table.S56
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/cmsis_os.h774
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/os_tcb.h51
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_CMSIS.c1887
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Event.c190
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Event.h46
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_HAL_CM.h276
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_List.c320
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_List.h67
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mailbox.c292
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mailbox.h48
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_MemBox.c166
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_MemBox.h46
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mutex.c197
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mutex.h44
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Robin.c84
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Robin.h45
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Semaphore.c183
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Semaphore.h46
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_System.c299
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_System.h52
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Task.c339
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Task.h73
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Time.c94
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Time.h47
-rw-r--r--libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_TypeDef.h128
-rw-r--r--libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/STM32F429BI.ld52
-rw-r--r--libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/startup_stm32f429xx.S9
-rw-r--r--libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h2
-rw-r--r--libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c17
-rw-r--r--libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_it.c139
-rw-r--r--libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_ll_fmc.c101
m---------libraries/thirdparty/libtfm0
-rw-r--r--projects/board-test/Makefile5
-rw-r--r--projects/board-test/fmc-perf.c39
-rw-r--r--projects/board-test/fmc-probe.c25
-rw-r--r--projects/board-test/fmc-test.c83
-rw-r--r--projects/board-test/keystore-perf.c197
-rw-r--r--projects/board-test/led-test.c1
-rw-r--r--projects/board-test/rtc-test.c75
-rw-r--r--projects/board-test/short-test.c1
-rw-r--r--projects/board-test/spiflash-perf.c249
-rw-r--r--projects/board-test/uart-test.c1
-rw-r--r--projects/bootloader/Makefile18
-rw-r--r--projects/bootloader/bootloader.c77
-rw-r--r--projects/bootloader/crc32.c62
-rw-r--r--projects/bootloader/dfu.c128
-rw-r--r--projects/bootloader/log.c68
-rw-r--r--projects/bootloader/startup_stm32f429xx.S564
-rw-r--r--projects/bootloader/stm-init.c7
-rw-r--r--projects/cli-test/Makefile27
-rw-r--r--projects/cli-test/cli-test.c99
-rw-r--r--projects/cli-test/crc32.c62
-rwxr-xr-xprojects/cli-test/filetransfer20
-rw-r--r--projects/cli-test/mgmt-cli.c220
-rw-r--r--projects/cli-test/mgmt-cli.h47
-rw-r--r--projects/cli-test/mgmt-dfu.c44
-rw-r--r--projects/cli-test/mgmt-dfu.h12
-rw-r--r--projects/cli-test/mgmt-fpga.c69
-rw-r--r--projects/cli-test/mgmt-fpga.h1
-rw-r--r--projects/cli-test/mgmt-keystore.c412
-rw-r--r--projects/cli-test/mgmt-keystore.h42
-rw-r--r--projects/cli-test/mgmt-keywrap.c316
-rw-r--r--projects/cli-test/mgmt-keywrap.h42
-rw-r--r--projects/cli-test/mgmt-masterkey.c225
-rw-r--r--projects/cli-test/mgmt-masterkey.h42
-rw-r--r--projects/cli-test/mgmt-misc.c164
-rw-r--r--projects/cli-test/mgmt-misc.h7
-rw-r--r--projects/cli-test/mgmt-show.c96
-rw-r--r--projects/cli-test/mgmt-show.h3
-rw-r--r--projects/cli-test/mgmt-test.c95
-rw-r--r--projects/cli-test/test-fmc.c217
-rw-r--r--projects/cli-test/test-fmc.h43
-rw-r--r--projects/cli-test/test-mkmif.c166
-rw-r--r--projects/cli-test/test_mkmif.h40
-rw-r--r--projects/cli-test/test_sdram.c1
-rw-r--r--projects/hsm/Makefile50
-rwxr-xr-xprojects/hsm/cryptech_miniterm45
-rwxr-xr-xprojects/hsm/cryptech_probe158
-rwxr-xr-xprojects/hsm/cryptech_upload385
-rw-r--r--projects/hsm/hsm.c522
-rw-r--r--projects/hsm/log.c68
-rw-r--r--projects/hsm/main.c226
-rw-r--r--projects/hsm/mgmt-bootloader.c89
-rw-r--r--projects/hsm/mgmt-bootloader.h51
-rw-r--r--projects/hsm/mgmt-cli.c220
-rw-r--r--projects/hsm/mgmt-cli.h49
-rw-r--r--projects/hsm/mgmt-firmware.c75
-rw-r--r--projects/hsm/mgmt-firmware.h42
-rw-r--r--projects/hsm/mgmt-fpga.c194
-rw-r--r--projects/hsm/mgmt-fpga.h49
-rw-r--r--projects/hsm/mgmt-keystore.c408
-rw-r--r--projects/hsm/mgmt-keystore.h42
-rw-r--r--projects/hsm/mgmt-masterkey.c244
-rw-r--r--projects/hsm/mgmt-masterkey.h42
-rw-r--r--projects/hsm/mgmt-misc.c259
-rw-r--r--projects/hsm/mgmt-misc.h47
-rw-r--r--projects/hsm/mgmt-task.c136
-rw-r--r--projects/hsm/mgmt-task.h42
-rw-r--r--projects/libhal-test/Makefile11
-rw-r--r--projects/libhal-test/gettimeofday.c2
-rw-r--r--projects/libhal-test/main.c12
-rw-r--r--projects/libhal-test/printf.c6
-rw-r--r--projects/rtos-test/Makefile18
-rw-r--r--projects/rtos-test/mutex-test.c40
-rw-r--r--projects/rtos-test/semaphore-test.c34
-rw-r--r--projects/rtos-test/thread-test.c24
-rw-r--r--spiflash_n25q128.c412
-rw-r--r--spiflash_n25q128.h30
-rw-r--r--stm-flash.c51
-rw-r--r--stm-flash.h8
-rw-r--r--stm-fmc.c149
-rw-r--r--stm-fmc.h33
-rw-r--r--stm-fpgacfg.c64
-rw-r--r--stm-fpgacfg.h15
-rw-r--r--stm-init.c213
-rw-r--r--stm-init.h44
-rw-r--r--stm-keystore.c64
-rw-r--r--stm-keystore.h19
-rw-r--r--stm-rtc.c24
-rw-r--r--stm-rtc.h3
-rw-r--r--stm-sdram.c483
-rw-r--r--stm-sdram.h112
-rw-r--r--stm-uart.c170
-rw-r--r--stm-uart.h53
-rw-r--r--syscalls.c11
-rw-r--r--task.c450
-rw-r--r--task.h89
161 files changed, 9455 insertions, 9860 deletions
diff --git a/.gitignore b/.gitignore
index b8b0ae3..25ec77d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,9 +1,10 @@
*.a
-*.o
-*.mo
*.bin
*.elf
*.hex
*.lst
*.map
+*.mo
+*.o
*~
+libraries/libtfm/tfm.h
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index d3946e7..0000000
--- a/.gitmodules
+++ /dev/null
@@ -1,9 +0,0 @@
-[submodule "libhal"]
- path = libraries/libhal
- url = git@git.cryptech.is:sw/libhal.git
-[submodule "thirdparty/libtfm"]
- path = libraries/thirdparty/libtfm
- url = git@git.cryptech.is:sw/thirdparty/libtfm.git
-[submodule "libraries/libcli"]
- path = libraries/libcli
- url = git@git.cryptech.is:user/ft/libcli
diff --git a/Makefile b/Makefile
index 87cc787..69a764a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,6 @@
-# Copyright (c) 2015-2016, NORDUnet A/S
-# All rights reserved.
+# Copyright (c) 2015-2017, NORDUnet A/S All rights reserved.
+# Copyright: 2020, The Commons Conservancy Cryptech Project
+# SPDX-License-Identifier: BSD-3-Clause
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
@@ -11,9 +12,9 @@
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
-# - Neither the name of the NORDUnet nor the names of its contributors may
-# be used to endorse or promote products derived from this software
-# without specific prior written permission.
+# - Neither the name of the copyright holder nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -27,27 +28,48 @@
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# A couple features that can be enabled at build time, but are not turned on
+# by default:
+# DO_PROFILING: Enable gmon profiling. See libraries/libprof/README.md for
+# more details.
+# DO_TASK_METRICS: Enable task metrics - average/max time between yields. This
+# can be helpful when experimentally adding yields to improve responsiveness.
+#
+# To enable, run `make DO_PROFILING=1 DO_TASK_METRICS=1`
+# (or DO_PROFILING=xyzzy - `make` just cares that the symbol is defined)
+
+# export all variables to child processes by default
+.EXPORT_ALL_VARIABLES:
+
# absolute path, because we're going to be passing things to sub-makes
-export TOPLEVEL = $(shell pwd)
+TOPLEVEL = $(abspath .)
+CRYPTECH_ROOT = $(abspath ../..)
# define board: dev-bridge or alpha
BOARD = TARGET_CRYPTECH_ALPHA
-# Location of the Libraries folder from the STM32F4 Standard Peripheral Library
LIBS_DIR = $(TOPLEVEL)/libraries
MBED_DIR = $(LIBS_DIR)/mbed
CMSIS_DIR = $(MBED_DIR)/targets/cmsis/TARGET_STM/TARGET_STM32F4
BOARD_DIR = $(CMSIS_DIR)/$(BOARD)
-RTOS_DIR = $(MBED_DIR)/rtos
-export LIBTFM_DIR = $(LIBS_DIR)/thirdparty/libtfm
-export LIBHAL_DIR = $(LIBS_DIR)/libhal
-export LIBCLI_DIR = $(LIBS_DIR)/libcli
-export LIBS = $(MBED_DIR)/libstmf4.a $(RTOS_DIR)/librtos.a
+LIBHAL_SRC = $(CRYPTECH_ROOT)/sw/libhal
+LIBHAL_BLD = $(LIBS_DIR)/libhal
+
+LIBCLI_SRC = $(CRYPTECH_ROOT)/user/paul/libcli
+LIBCLI_BLD = $(LIBS_DIR)/libcli
+
+LIBTFM_SRC = $(CRYPTECH_ROOT)/sw/thirdparty/libtfm
+LIBTFM_BLD = $(LIBS_DIR)/libtfm
+
+LIBPROF_SRC = $(LIBS_DIR)/libprof
+LIBPROF_BLD = $(LIBS_DIR)/libprof
+
+LIBS = $(MBED_DIR)/libstmf4.a
# linker script
-export LDSCRIPT = $(BOARD_DIR)/TOOLCHAIN_GCC_ARM/STM32F429BI.ld
-export BOOTLOADER_LDSCRIPT = $(BOARD_DIR)/TOOLCHAIN_GCC_ARM/STM32F429BI_bootloader.ld
+LDSCRIPT = $(BOARD_DIR)/TOOLCHAIN_GCC_ARM/STM32F429BI.ld
+BOOTLOADER_LDSCRIPT = $(BOARD_DIR)/TOOLCHAIN_GCC_ARM/STM32F429BI_bootloader.ld
# board-specific objects, to link into every project
BOARD_OBJS = \
@@ -68,35 +90,50 @@ BOARD_OBJS += \
$(TOPLEVEL)/stm-sdram.o \
$(TOPLEVEL)/stm-flash.o
endif
-export BOARD_OBJS
# cross-building tools
PREFIX=arm-none-eabi-
-export CC=$(PREFIX)gcc
-export AS=$(PREFIX)as
-export AR=$(PREFIX)ar
-export OBJCOPY=$(PREFIX)objcopy
-export OBJDUMP=$(PREFIX)objdump
-export SIZE=$(PREFIX)size
+CC=$(PREFIX)gcc
+AS=$(PREFIX)as
+AR=$(PREFIX)ar
+OBJCOPY=$(PREFIX)objcopy
+OBJDUMP=$(PREFIX)objdump
+SIZE=$(PREFIX)size
+
+# The Alpha is a development platform, so set GCC optimization to a
+# level suitable for debugging. Recent versions of GCC have a special
+# optimization setting -Og for exactly this purpose, so we use it,
+# along with the flag to enable gdb symbols. Note that some libraries
+# (in particular, libtfm) may need different optimization settings,
+# which is why this needs to remain a separate makefile variable.
+#
+# If you really want optimization without debugging support, try -O2
+# or -O3.
+
+STM32_CFLAGS_OPTIMIZATION ?= -ggdb -Og
# whew, that's a lot of cflags
-CFLAGS = -ggdb -O2 -Wall -Warray-bounds #-Wextra
+CFLAGS = $(STM32_CFLAGS_OPTIMIZATION) -Wall -Warray-bounds -Wextra
CFLAGS += -mcpu=cortex-m4 -mthumb -mlittle-endian -mthumb-interwork
CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
CFLAGS += -DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F429xx
CFLAGS += -D__CORTEX_M4 -DTARGET_STM -DTARGET_STM32F4 -DTARGET_STM32F429ZI -DTOOLCHAIN_GCC -D__FPU_PRESENT=1 -D$(BOARD)
+CFLAGS += -DENABLE_WEAK_FUNCTIONS
CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections
CFLAGS += -std=c99
-CFLAGS += -I $(TOPLEVEL)
-CFLAGS += -I $(MBED_DIR)/api
-CFLAGS += -I $(MBED_DIR)/rtos/rtos
-CFLAGS += -I $(MBED_DIR)/rtos/rtx/TARGET_CORTEX_M
-CFLAGS += -I $(MBED_DIR)/targets/cmsis
-CFLAGS += -I $(MBED_DIR)/targets/cmsis/TARGET_STM/TARGET_STM32F4
-CFLAGS += -I $(MBED_DIR)/targets/cmsis/TARGET_STM/TARGET_STM32F4/$(BOARD)
-CFLAGS += -I $(MBED_DIR)/targets/hal/TARGET_STM/TARGET_STM32F4
-CFLAGS += -I $(MBED_DIR)/targets/hal/TARGET_STM/TARGET_STM32F4/$(BOARD)
-export CFLAGS
+CFLAGS += -I$(TOPLEVEL)
+CFLAGS += -I$(MBED_DIR)/api
+CFLAGS += -I$(MBED_DIR)/targets/cmsis
+CFLAGS += -I$(MBED_DIR)/targets/cmsis/TARGET_STM/TARGET_STM32F4
+CFLAGS += -I$(MBED_DIR)/targets/cmsis/TARGET_STM/TARGET_STM32F4/$(BOARD)
+CFLAGS += -I$(MBED_DIR)/targets/hal/TARGET_STM/TARGET_STM32F4
+CFLAGS += -I$(MBED_DIR)/targets/hal/TARGET_STM/TARGET_STM32F4/$(BOARD)
+ifdef DO_TASK_METRICS
+CFLAGS += -DDO_TASK_METRICS
+endif
+ifdef DO_TIMING
+CFLAGS += -DDO_TIMING
+endif
%.o : %.c
$(CC) $(CFLAGS) -c -o $@ $<
@@ -104,59 +141,72 @@ export CFLAGS
%.o : %.S
$(CC) $(CFLAGS) -c -o $@ $<
-all: board-test cli-test libhal-test hsm
-
-init:
- git submodule update --init --recursive --remote
+ifdef DO_PROFILING
+CFLAGS += -pg -DDO_PROFILING
+LIBS += $(LIBPROF_BLD)/libprof.a
+all: hsm
+else
+all: board-test cli-test libhal-test hsm bootloader
+endif
-$(MBED_DIR)/libstmf4.a:
+$(MBED_DIR)/libstmf4.a: .FORCE
$(MAKE) -C $(MBED_DIR)
-board-test: $(BOARD_OBJS) $(LIBS)
+board-test: $(BOARD_OBJS) $(LIBS) .FORCE
$(MAKE) -C projects/board-test
-cli-test: $(BOARD_OBJS) $(LIBS) $(LIBCLI_DIR)/libcli.a
+cli-test: $(BOARD_OBJS) $(LIBS) $(LIBCLI_BLD)/libcli.a $(LIBHAL_BLD)/libhal.a .FORCE
$(MAKE) -C projects/cli-test
-$(RTOS_DIR)/librtos.a:
- $(MAKE) -C $(RTOS_DIR)
+$(LIBTFM_BLD)/libtfm.a: .FORCE
+ $(MAKE) -C $(LIBTFM_BLD) PREFIX=$(PREFIX)
-rtos-test: $(RTOS_OBJS) $(LIBS)
- $(MAKE) -C projects/rtos-test
+$(LIBHAL_BLD)/libhal.a: $(LIBTFM_BLD)/libtfm.a .FORCE
+ $(MAKE) -C $(LIBHAL_BLD) IO_BUS=fmc RPC_MODE=server RPC_TRANSPORT=serial KS=flash HASH_CORES=yes libhal.a
-$(LIBTFM_DIR)/libtfm.a:
- $(MAKE) -C $(LIBTFM_DIR) PREFIX=$(PREFIX)
+$(LIBCLI_BLD)/libcli.a: .FORCE
+ $(MAKE) -C $(LIBCLI_BLD)
-$(LIBHAL_DIR)/libhal.a: $(LIBTFM_DIR)/libtfm.a
- $(MAKE) -C $(LIBHAL_DIR) IO_BUS=fmc RPC_SERVER=yes RPC_TRANSPORT=serial KS=volatile libhal.a
+$(LIBPROF_BLD)/libprof.a: .FORCE
+ $(MAKE) -C $(LIBPROF_BLD)
-$(LIBCLI_DIR)/libcli.a:
- $(MAKE) -C $(LIBCLI_DIR)
-
-libhal-test: $(BOARD_OBJS) $(LIBS) $(LIBHAL_DIR)/libhal.a
+libhal-test: $(BOARD_OBJS) $(LIBS) $(LIBHAL_BLD)/libhal.a .FORCE
$(MAKE) -C projects/libhal-test
-hsm: $(BOARD_OBJS) $(LIBS) $(LIBHAL_DIR)/libhal.a
+hsm: $(BOARD_OBJS) $(LIBS) $(LIBHAL_BLD)/libhal.a $(LIBCLI_BLD)/libcli.a .FORCE
$(MAKE) -C projects/hsm
-bootloader: $(BOARD_OBJS) $(LIBS)
+bootloader: $(BOARD_OBJS) $(LIBS) $(LIBHAL_BLD)/libhal.a .FORCE
$(MAKE) -C projects/bootloader
+modexpng-test: $(BOARD_OBJS) $(LIBS) .FORCE
+ $(MAKE) -C projects/modexpng-test
+
# don't automatically delete objects, to avoid a lot of unnecessary rebuilding
.SECONDARY: $(BOARD_OBJS)
-.PHONY: board-test rtos-test libhal-test cli-test
+.PHONY: board-test libhal-test cli-test hsm bootloader
+
+# We don't (and shouldn't) know enough about libraries and projects to
+# know whether they need rebuilding or not, so we let their Makefiles
+# decide that. Which means we always need to run all the sub-makes.
+# We could do this with .PHONY (which is supposedly more "efficient")
+# but using a .FORCE target is simpler once one takes inter-library
+# dependency specifications into account.
+
+.FORCE: # (sic)
clean:
rm -f $(BOARD_OBJS)
+ $(MAKE) -C $(LIBHAL_BLD) clean
$(MAKE) -C projects/board-test clean
$(MAKE) -C projects/cli-test clean
- $(MAKE) -C projects/rtos-test clean
$(MAKE) -C projects/libhal-test clean
$(MAKE) -C projects/hsm clean
+ $(MAKE) -C projects/bootloader clean
distclean: clean
$(MAKE) -C $(MBED_DIR) clean
- $(MAKE) -C $(RTOS_DIR) clean
- $(MAKE) -C $(LIBHAL_DIR) clean
- $(MAKE) -C $(LIBTFM_DIR) clean
+ $(MAKE) -C $(LIBTFM_BLD) clean
+ $(MAKE) -C $(LIBCLI_BLD) clean
+ $(MAKE) -C $(LIBPROF_BLD) clean
diff --git a/README.md b/README.md
index 6d813ef..e2c10a8 100644
--- a/README.md
+++ b/README.md
@@ -1,80 +1,127 @@
-STM32 software for dev-bridge/Alpha board
-=========================================
+STM32 firmware for Cryptech Alpha board
+=======================================
-The dev-bridge board is a daughterboard for the Novena, which talks to the
-Novena's FPGA through the high-speed expansion connector.
+The Alpha board is our first full prototype for an open-source hardware
+security module (HSM). It is a custom board with an STM32 Cortex-M4
+microcontroller and an Artix-7 FPGA, flash-based keystore, separate memory
+for the Key Encryption Key, etc. See the `hardware` repository for
+schematics and production files. See the wiki for design documents.
-The Alpha board is a stand-alone board with an Artix-7 FPGA, a STM32 Cortex-M4
-microcontroller, two USB interfaces etc.
-
-See user/ft/stm32-dev-bridge/hardware/rev01 for schematics of the bridge
-board. There will be more information on the wiki shortly.
+The code in this repository builds the firmware that provides the HSM
+functionality on the Alpha board.
+There is some residual code here to support the "dev-bridge" board, a
+daughterboard for the Novena, which talks to the Novena's FPGA through the
+high-speed expansion connector. Only a few of these boards were ever made,
+and all development/testing ceased as soon as the Alpha became available,
+so the dev-bridge should be considered deprecated, and support may be
+removed in the future.
Copyrights
==========
The license for all work done on this in the CrypTech project is a
-3-clause BSD license (see LICENSE.txt for details). Some files have
-been generated using the STMicroelectronics initialization code
-generator STM32CubeMX and thus have additional copyright header(s).
+3-clause BSD license.
+
+Third-party components, as well as code generated using the
+STMicroelectronics initialization code generator STM32CubeMX, or adapted
+from STM example/support code, may have different licensing, detailed
+below.
+
+Components
+==========
+
+Libraries
+---------
+
+* `mbed` - A stripped down copy of the ARM CMSIS library, copied from the
+ mbed github (see `libraries/mbed/README.txt` for details). The bulk of
+ this library is covered under 3-clause BSD licenses from either ARM or
+ STMicroelectronics, but one file is covered under an Apache license from
+ ARM.
+
+* `libhal` - Build directory for our own Hardware Adaption Library
+ (hardware-independent Cryptech components). Source is expected to be in
+ `sw/libhal`.
+
+* `libtfm` - Build directory for "Tom's Fast Math", which is used heavily
+ for bignum math in the RSA and ECDSA code. This code is covered under an
+ unrestricted public domain license, and source is expected to be in
+ `sw/thirdparty/libtfm`.
+
+* `libcli` - Build directory for a third-party Command Line Interface
+ library. The source is not currently under `sw/thirdparty` because the
+ license is LGPLv2.1; we are negotiating to see if we can get a
+ BSD-compatible license for it.
+
+* `libprof` - A port of the `gmon` profiling package, to be used in
+ development only, not in production code (obviously). The licensing is a
+ mix of BSD and "Cygwin license", which now seems to be LGPLv3.
+
+Projects
+--------
-The "Noise generator" and "Amplifier" parts of the circuit diagram are
-copied from Benedikt Stockebrand's ARRGH project. ARRGH copyright
-statement is included in LICENSE.txt.
+These directories build different firmware images for the Alpha board.
-A stripped down copy of the ARM CMSIS library version 3.20 is included
-in the Drivers/CMSIS/ directory. Unused parts (and documentation etc.)
-have been removed, but every attempt have been made to keep any
-licensing information intact. See in particular the file
-Drivers/CMSIS/CMSIS END USER LICENCE AGREEMENT.pdf.
+* `hsm` - Firmware providing HSM functionality. Clients communicate via
+ RPC requests on the USER USB port, or interactively on the MGMT USB
+ port.
-A full copy of the STM32F4xx HAL Drivers is included in the
-Drivers/STM32F4xx_HAL_Driver/ directory.
+* `bootloader` - The first thing that runs on the device. It either starts
+ the primary firmware, or installs new firmware.
+* `board-test` - Tests of hardware components.
+
+* `cli-test` - Test of the CLI itself, plus some interactive tests of
+ hardware components. Duplicates way too much of the HSM CLI.
+
+* `libhal-test` - A framework for running the libhal component
+ tests. Hasn't been run in a while, probably still works.
Building
========
-The following packages need to be installed (on Ubuntu 14.04):
+Our primary build environments are Debian and Ubuntu, but this should work
+on any system with Gnu tools installed.
- apt-get install gcc-arm-none-eabi gdb-arm-none-eabi openocd
+The following packages need to be installed:
-To build the source code, issue "make" from the top level directory
-(where this file is). The first time, this will build the complete STM
-CMSIS library. A subsequent "make clean" will *not* clean away the CMSIS
-library, but a "make distclean" will.
+ $ apt-get install gcc-arm-none-eabi gdb-arm-none-eabi openocd
+The Makefile assumes that all Cryptech repositories have been fetched into
+a canonical directory structure, e.g. `libhal` and `thirdparty` are
+siblings to this directory, under `sw`.
+
+To build the source code, issue `make` from the top level directory
+(where this file is). The first time, this will build the complete STM
+CMSIS library. A subsequent `make clean` will *not* clean away the CMSIS
+library, but a `make distclean` will.
Installing
==========
-Do "bin/flash-target" from the top level directory (where this file is)
+Do `bin/flash-target` from the top level directory (where this file is)
to flash a built image into the microcontroller. See the section ST-LINK
below for information about the actual hardware programming device needed.
-Example loading the bootloader and the led-test firmware to get some LEDs
-flashing:
+Example loading the HSM firmware:
- $ make bootloader board-test
- $ ./bin/flash-target projects/board-test/led-test
- $ ./bin/flash-target projects/bootloader/bootloader
+ $ make hsm
+ $ ./bin/flash-target projects/hsm/hsm
At this point, the STM32 will reset into the bootloader which flashes the
-blue LED five times in one second, and then execution of the LED test
-firmware will begin. The LED test firmware will flash the green, yellow,
-red and blue LEDs in order until the end of time.
+blue LED five times in one second, and then jumps to the primary firmware.
Once the bootloader is installed, regular firmware can be loaded without
an ST-LINK cable like this:
- $ ./bin/dfu projects/board-test/led-test.bin
+ $ cryptech_upload --firmware -i projects/hsm/hsm.bin
Then reboot the Alpha board.
-
ST-LINK
-=======
+-------
+
To program the MCU, an ST-LINK adapter is used. The cheapest way to get
one is to buy an evaluation board with an ST-LINK integrated, and pinouts
to program external chips. This should work with any evaluation board from
@@ -86,7 +133,7 @@ printed on the circuit board. The pin-outs is shown on the circuit board
(follow the thin white line from J1 to the white box with STM32_SWD
written in it). From left to right, the pins are
- 3V3, CLK, GND, I/O, NRST and N/C
+ 3V3, CLK, GND, I/O, NRST and N/C
This matches the pin-out on the DISCO and NUCLEO boards we have tried.
@@ -94,34 +141,30 @@ First remove the pair of ST-LINK jumpers (CN4 on the DISCO, CN2 on the
NUCLEO). Then find the 6-pin SWD header on the left of the STM board (CN2
on the DISCO, CN4 on the NUCLEO), and connect them to the Alpha board:
- NUCLEO / DISCO CRYPTECH ALPHA
- -------------- --------------
-* 1 VDD_TARGET <-> 3V3
-* 2 SWCLK / T_JTCK <-> CLK
-* 3 GND <-> GND
-* 4 SWDIO / T_JTMS <-> IO
-* 5 NRST / T_NRST <-> NRST
-
-N/C (pin 6) means Not Connected.
+ NUCLEO / DISCO CRYPTECH ALPHA
+ -------------- --------------
+ * 1 VDD_TARGET <-> 3V3
+ * 2 SWCLK / T_JTCK <-> CLK
+ * 3 GND <-> GND
+ * 4 SWDIO / T_JTMS <-> IO
+ * 5 NRST / T_NRST <-> NRST
+ * 6 N/C
The Alpha board should be powered on before attempting to flash it.
-
Debugging the firmware
-======================
-
-This site shows several ways to use various debuggers to debug the
-firmware in an STM32:
+----------------------
- http://fun-tech.se/stm32/OpenOCD/gdb.php
+[This site](http://fun-tech.se/stm32/OpenOCD/gdb.php) shows several ways
+to use various debuggers to debug the firmware in an STM32.
There is a shell script called 'bin/debug' that starts an OpenOCD server
and GDB. Example:
- $ ./bin/debug projects/board-test/led-test
+ $ ./bin/debug projects/hsm/hsm
-Once in GDB, issue "monitor reset halt" to reset the STM32 before debugging.
+Once in GDB, issue `monitor reset halt` to reset the STM32 before debugging.
Remember that the first code to run will be the bootloader, but if you do
-e.g. "break main" and "continue" you will end up in led-test main() after
-the bootloader has jumped there.
+e.g. `break main` and `continue` you will end up in main() after the
+bootloader has jumped there.
diff --git a/bin/debug b/bin/debug
index f87a3b5..5553270 100755
--- a/bin/debug
+++ b/bin/debug
@@ -6,11 +6,21 @@ OPENOCD=openocd
OPENOCD_BOARD_DIR=/usr/share/openocd/scripts/board
OPENOCD_PROC_FILE=stm32f4discovery.cfg
if [ "x`lsusb -d 0483:374b`" != "x" ]; then
- OPENOCD_PROC_FILE=st_nucleo_f4.cfg
+ for fn in st_nucleo_f4.cfg st_nucleo_f401re.cfg; do
+ if [ -f "$OPENOCD_BOARD_DIR/$fn" ]; then
+ OPENOCD_PROC_FILE="$fn"
+ fi
+ done
fi
$OPENOCD -f $OPENOCD_BOARD_DIR/$OPENOCD_PROC_FILE &
-GDB=arm-none-eabi-gdb
+for gdb in gdb-multiarch arm-none-eabi-gdb; do
+ if command -v $gdb &>/dev/null; then
+ GDB=$gdb
+ break
+ fi
+done
+
$GDB -ex "target remote localhost:3333" -ex "set remote hardware-breakpoint-limit 6" -ex "set remote hardware-watchpoint-limit 4" $PROJ.elf
kill -9 $(pidof $OPENOCD)
diff --git a/bin/dfu b/bin/dfu
index e270438..fd783e0 100755
--- a/bin/dfu
+++ b/bin/dfu
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
#
# Copyright (c) 2016, NORDUnet A/S All rights reserved.
#
@@ -43,7 +43,7 @@ import struct
import serial
import argparse
-from binascii import crc32
+from binascii import crc32, hexlify
CHUNK_SIZE = 4096
@@ -77,23 +77,23 @@ def parse_args():
def _write(dst, data):
for i in range(len(data)):
- dst.write(data[i])
+ dst.write(data[i:i+1])
time.sleep(0.1)
if len(data) == 4:
- print("Wrote 0x{:02x}{:02x}{:02x}{:02x}".format(ord(data[0]), ord(data[1]), ord(data[2]), ord(data[3])))
+ print("Wrote 0x{}".format(hexlify(data).decode("ascii")))
else:
print("Wrote {!r}".format(data))
def _read(dst, verbose=False):
- res = ''
+ res = b''
while True:
x = dst.read(1)
if not x:
break
res += x
if res and verbose:
- print ("Read {!r}".format(res))
+ print("Read {!r}".format(res))
return res
@@ -111,7 +111,7 @@ def send_file(filename, args):
except serial.SerialException:
time.sleep(0.2)
continue
- dst.write('\r')
+ dst.write(b'\r')
response = _read(dst, args.verbose)
if 'OK' in response:
dst.timeout=2
@@ -137,7 +137,7 @@ def send_file(filename, args):
if len(ack_bytes) == 4:
break
print('ERROR: Did not receive an ACK, got {!r}'.format(ack_bytes))
- dst.write('\r') # eventually get back to the CLI prompt
+ dst.write(b'\r') # eventually get back to the CLI prompt
ack = struct.unpack('<I', ack_bytes)[0]
if ack != counter + 1:
print('ERROR: Did not receive the expected counter as ACK (got {!r}/{!r}, not {!r})'.format(ack, ack_bytes, counter))
diff --git a/bin/flash-target b/bin/flash-target
index 0d60c85..336bae1 100755
--- a/bin/flash-target
+++ b/bin/flash-target
@@ -22,7 +22,11 @@ OPENOCD_BOARD_DIR=/usr/share/openocd/scripts/board
#
OPENOCD_PROC_FILE=stm32f4discovery.cfg
if [ "x`lsusb -d 0483:374b`" != "x" ]; then
- OPENOCD_PROC_FILE=st_nucleo_f4.cfg
+ for fn in st_nucleo_f4.cfg st_nucleo_f401re.cfg; do
+ if [ -f "$OPENOCD_BOARD_DIR/$fn" ]; then
+ OPENOCD_PROC_FILE="$fn"
+ fi
+ done
fi
$OPENOCD -f $OPENOCD_BOARD_DIR/$OPENOCD_PROC_FILE -c "program $PROJ.elf verify reset exit"
diff --git a/bin/reset b/bin/reset
index 1c57f97..8190805 100755
--- a/bin/reset
+++ b/bin/reset
@@ -21,7 +21,11 @@ OPENOCD_BOARD_DIR=/usr/share/openocd/scripts/board
#
OPENOCD_PROC_FILE=stm32f4discovery.cfg
if [ "x`lsusb -d 0483:374b`" != "x" ]; then
- OPENOCD_PROC_FILE=st_nucleo_f4.cfg
+ for fn in st_nucleo_f4.cfg st_nucleo_f401re.cfg; do
+ if [ -f "$OPENOCD_BOARD_DIR/$fn" ]; then
+ OPENOCD_PROC_FILE="$fn"
+ fi
+ done
fi
$OPENOCD -f $OPENOCD_BOARD_DIR/$OPENOCD_PROC_FILE -c "init" -c "reset run" -c "exit"
diff --git a/libraries/libcli b/libraries/libcli
deleted file mode 160000
-Subproject 1a5727c568e36b927ef2088b2b02bae4c84933f
diff --git a/libraries/libcli/Makefile b/libraries/libcli/Makefile
new file mode 100644
index 0000000..6bc805a
--- /dev/null
+++ b/libraries/libcli/Makefile
@@ -0,0 +1,24 @@
+vpath %.c ${LIBCLI_SRC}
+vpath %.h ${LIBCLI_SRC}
+
+CFLAGS += \
+ -DDO_CRYPT=0 \
+ -DDO_FILE=0 \
+ -DDO_FILTER=0 \
+ -DDO_IDLE_TIMEOUT=0 \
+ -DDO_MALLOC=0 \
+ -DDO_PRINT_BUFFERED=0 \
+ -DDO_REGULAR=0 \
+ -DDO_SOCKET=0 \
+ -DDO_TAB_COMPLETION=1 \
+ -DDO_TELNET=0 \
+ -DCLI_MAX_LINE_WORDS=36
+CFLAGS += -Wno-unused-parameter
+
+all: libcli.a
+
+libcli.a: libcli.o
+ $(AR) rcs $@ $^
+
+clean:
+ rm -f libcli.[ao]
diff --git a/libraries/libhal b/libraries/libhal
deleted file mode 160000
-Subproject 60cce0124f2fc3eddca03ed3950da9238247a61
diff --git a/libraries/libhal/Makefile b/libraries/libhal/Makefile
new file mode 100644
index 0000000..950e620
--- /dev/null
+++ b/libraries/libhal/Makefile
@@ -0,0 +1,8 @@
+vpath %.c ${LIBHAL_SRC}
+vpath %.h ${LIBHAL_SRC}
+
+CFLAGS += -Wno-missing-field-initializers -Wno-unused-parameter
+CFLAGS += -DHAL_STATIC_CLIENT_STATE_BLOCKS=25
+CFLAGS += -DHAL_IO_TIMEOUT=10000000
+
+include ${LIBHAL_SRC}/Makefile
diff --git a/libraries/libhal/tests/Makefile b/libraries/libhal/tests/Makefile
new file mode 100644
index 0000000..e148174
--- /dev/null
+++ b/libraries/libhal/tests/Makefile
@@ -0,0 +1,4 @@
+vpath %.c ${LIBHAL_SRC}/tests
+vpath %.h ${LIBHAL_SRC}/tests
+
+include ${LIBHAL_SRC}/tests/Makefile
diff --git a/libraries/libhal/utils/Makefile b/libraries/libhal/utils/Makefile
new file mode 100644
index 0000000..6f21c2f
--- /dev/null
+++ b/libraries/libhal/utils/Makefile
@@ -0,0 +1,4 @@
+vpath %.c ${LIBHAL_SRC}/utils
+vpath %.h ${LIBHAL_SRC}/utils
+
+include ${LIBHAL_SRC}/utils/Makefile
diff --git a/libraries/libprof/Makefile b/libraries/libprof/Makefile
new file mode 100644
index 0000000..28bedea
--- /dev/null
+++ b/libraries/libprof/Makefile
@@ -0,0 +1,24 @@
+LIB = libprof.a
+
+OBJS = gmon.o profiler.o memfunc.o
+
+# Don't profile the profiling code, because that way lies madness (and recursion).
+CFLAGS := $(subst -pg,,$(CFLAGS))
+
+all: $(LIB)
+
+# But do profile the mem functions
+memfunc.o: memfunc.c
+ $(CC) $(CFLAGS) -pg -c -o $@ $<
+
+%.o : %.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+%.o : %.S
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+$(LIB): $(OBJS)
+ $(AR) -r $@ $^
+
+clean:
+ rm -f $(OBJS) $(LIB)
diff --git a/libraries/libprof/README.md b/libraries/libprof/README.md
new file mode 100644
index 0000000..d464644
--- /dev/null
+++ b/libraries/libprof/README.md
@@ -0,0 +1,65 @@
+Profiling the Cryptech Alpha
+============================
+
+Origin
+------
+
+This code was copied from https://github.com/ErichStyger/mcuoneclipse.git,
+directory `Examples/KDS/FRDM-K64F120M/FRDM-K64F_Profiling/Profiling`, commit
+9b7eedddd8b24968128582aedc63be95b61f782c, dated Mon Jan 9 16:56:17 2017 +0100.
+
+References
+----------
+
+I recommend reading both of these to understand how the profiling code works.
+
+1. [Tutorial: Using GNU Profiling (gprof) with ARM Cortex-M](https://mcuoneclipse.com/2015/08/23/tutorial-using-gnu-profiling-gprof-with-arm-cortex-m/)
+
+2. [Semihosting with ARM, GCC, and OpenOCD](http://bgamari.github.io/posts/2014-10-31-semihosting.html)
+
+How to build
+------------
+
+From the top level, run
+
+ $ make DO_PROFILING=1 hsm
+
+By default, all code is profiled, *except* the profiling code itself,
+because that would cause fatal recursion.
+
+How to run
+----------
+
+You need to start OpenOCD on the host, and enable semihosting, at least
+before you try to use it as a remote file system.
+
+I recommend executing the following in the `projects/hsm` directory, so that
+`gmon.out` ends up in the same directory as `hsm.elf`.
+
+Start the debugger:
+
+ $ ../../bin/debug hsm
+
+In another window, connect to OpenOCD:
+
+ $ telnet localhost 4444
+
+In the OpenOCD console, enable semihosting:
+
+ > arm semihosting enable
+ > exit
+
+Then connect to the Cryptech management console:
+
+ $ cryptech_console
+
+In the Cryptech console, type `profile start`, then start the unit test or
+whatever will be exercising the hsm. Afterwards, in the console, type
+`profile stop`.
+
+After invoking `profile stop`, it can take several minutes to write
+`gmon.out` over OpenOCD to the host.
+
+In the `projects/hsm` directory, run `gprof` to analyse the `gmon.out` file:
+
+ $ gprof hsm.elf >gprof.txt
diff --git a/libraries/libprof/gmon.c b/libraries/libprof/gmon.c
new file mode 100644
index 0000000..a34f1a2
--- /dev/null
+++ b/libraries/libprof/gmon.c
@@ -0,0 +1,261 @@
+/*-
+ * Copyright (c) 1983, 1992, 1993
+ * The Regents of the University of California. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * This file is taken from Cygwin distribution. Please keep it in sync.
+ * The differences should be within __MINGW32__ guard.
+ */
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include "gmon.h"
+
+#define bzero(ptr,size) memset (ptr, 0, size);
+#define ERR(s) write(2, s, sizeof(s))
+
+/* profiling frequency. (No larger than 1000) */
+/* Note this doesn't set the frequency, but merely describes it. */
+#define PROF_HZ 1000
+
+struct gmonparam _gmonparam = { off, NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, 0};
+
+void monstartup(size_t lowpc, size_t highpc)
+{
+ static char already_setup = 0;
+ struct gmonparam *p = &_gmonparam;
+
+ if (already_setup) {
+ /* reinitialize counters and arcs */
+ bzero(p->kcount, p->kcountsize);
+ bzero(p->froms, p->fromssize);
+ bzero(p->tos, p->tossize);
+ p->state = on;
+ return;
+ }
+ already_setup = 1;
+
+ /* enable semihosting, for eventual output */
+ extern void initialise_monitor_handles(void);
+ initialise_monitor_handles();
+
+ /*
+ * round lowpc and highpc to multiples of the density we're using
+ * so the rest of the scaling (here and in gprof) stays in ints.
+ */
+ p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER));
+ p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER));
+ p->textsize = p->highpc - p->lowpc;
+ p->kcountsize = p->textsize / HISTFRACTION;
+ p->fromssize = p->textsize / HASHFRACTION;
+ p->tolimit = p->textsize * ARCDENSITY / 100;
+ if (p->tolimit < MINARCS) {
+ p->tolimit = MINARCS;
+ } else if (p->tolimit > MAXARCS) {
+ p->tolimit = MAXARCS;
+ }
+ p->tossize = p->tolimit * sizeof(struct tostruct);
+
+ extern void *hal_allocate_static_memory(const size_t size);
+ void *cp = hal_allocate_static_memory(p->kcountsize + p->fromssize + p->tossize);
+ if (cp == NULL) {
+ ERR("monstartup: out of memory\n");
+ return;
+ }
+
+ bzero(cp, p->kcountsize + p->fromssize + p->tossize);
+ p->kcount = (unsigned short *)cp; cp += p->kcountsize;
+ p->froms = (unsigned short *)cp; cp += p->fromssize;
+ p->tos = (struct tostruct *)cp;
+
+ p->state = on;
+}
+
+void _mcleanup(void)
+{
+ static const char gmon_out[] = "gmon.out";
+ int fd;
+ struct gmonparam *p = &_gmonparam;
+
+ if (p->state == err) {
+ ERR("_mcleanup: tos overflow\n");
+ }
+
+ fd = open(gmon_out , O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0666);
+ if (fd < 0) {
+ perror( gmon_out );
+ return;
+ }
+
+ struct gmonhdr hdr = {
+ .lpc = p->lowpc,
+ .hpc = p->highpc,
+ .ncnt = p->kcountsize + sizeof(struct gmonhdr),
+ .version = GMONVERSION,
+ .profrate = PROF_HZ
+ };
+ write(fd, &hdr, sizeof(hdr));
+
+ write(fd, p->kcount, p->kcountsize);
+
+ for (size_t fromindex = 0; fromindex < p->fromssize / sizeof(*p->froms); fromindex++) {
+ size_t frompc = p->lowpc + fromindex * HASHFRACTION * sizeof(*p->froms);
+ for (size_t toindex = p->froms[fromindex]; toindex != 0; toindex = p->tos[toindex].next) {
+ struct rawarc arc = {
+ .frompc = frompc,
+ .selfpc = p->tos[toindex].selfpc,
+ .count = p->tos[toindex].count
+ };
+ write(fd, &arc, sizeof(arc));
+ }
+ }
+
+ close(fd);
+}
+
+void _mcount_internal(size_t frompc, size_t selfpc)
+{
+ register unsigned short *fromptr;
+ register struct tostruct *top;
+ register unsigned short toindex;
+ struct gmonparam *p = &_gmonparam;
+
+ /*
+ * check that we are profiling and that we aren't recursively invoked.
+ * check that frompc is a reasonable pc value.
+ */
+ if (p->state != on || (frompc -= p->lowpc) > p->textsize) {
+ return;
+ }
+
+ fromptr = &p->froms[frompc / (HASHFRACTION * sizeof(*p->froms))];
+ toindex = *fromptr; /* get froms[] value */
+
+ if (toindex == 0) { /* we haven't seen this caller before */
+ toindex = ++p->tos[0].next; /* index of the last used record in the array */
+ if (toindex >= p->tolimit) { /* more tos[] entries than we can handle! */
+ overflow:
+ p->state = err; /* halt further profiling */
+#define TOLIMIT "mcount: tos overflow\n"
+ write (2, TOLIMIT, sizeof(TOLIMIT));
+ return;
+ }
+ *fromptr = toindex; /* store new 'to' value into froms[] */
+ top = &p->tos[toindex];
+ top->selfpc = selfpc;
+ top->count = 1;
+ top->next = 0;
+ }
+
+ else { /* we've seen this caller before */
+ top = &p->tos[toindex];
+ if (top->selfpc == selfpc) {
+ /*
+ * arc at front of chain; usual case.
+ */
+ top->count++;
+ }
+
+ else {
+ /*
+ * have to go looking down chain for it.
+ * top points to what we are looking at,
+ * prevtop points to previous top.
+ * we know it is not at the head of the chain.
+ */
+ while (1) {
+ if (top->next == 0) {
+ /*
+ * top is end of the chain and none of the chain
+ * had top->selfpc == selfpc.
+ * so we allocate a new tostruct
+ * and put it at the head of the chain.
+ */
+ toindex = ++p->tos[0].next;
+ if (toindex >= p->tolimit) {
+ goto overflow;
+ }
+ top = &p->tos[toindex];
+ top->selfpc = selfpc;
+ top->count = 1;
+ top->next = *fromptr;
+ *fromptr = toindex;
+ break;
+ }
+
+ else {
+ /*
+ * otherwise, check the next arc on the chain.
+ */
+ register struct tostruct *prevtop = top;
+ top = &p->tos[top->next];
+ if (top->selfpc == selfpc) {
+ /*
+ * there it is.
+ * increment its count
+ * move it to the head of the chain.
+ */
+ top->count++;
+ toindex = prevtop->next;
+ prevtop->next = top->next;
+ top->next = *fromptr;
+ *fromptr = toindex;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return; /* normal return restores saved registers */
+}
+
+#include <stdint.h>
+#include "stm32f4xx_hal.h" /* __get_MSP */
+
+/* called from the SysTick handler */
+void profil_callback(void)
+{
+ struct gmonparam *p = &_gmonparam;
+
+ if (p->state == on) {
+ /* The interrupt mechanism pushes xPSR, PC, LR, R12, and R3-R0 onto the
+ * stack, so PC is the 6th word from the top at that point. However, the
+ * normal function entry code pushes registers as well, so the stack
+ * offset right now depends on the call tree that got us here.
+ */
+ size_t pc = (size_t)((uint32_t *)__get_MSP())[6 + 6];
+ if ((pc -= p->lowpc) < p->textsize) {
+ size_t idx = pc / (HISTFRACTION * sizeof(*p->kcount));
+ p->kcount[idx]++;
+ }
+ }
+}
diff --git a/libraries/libprof/gmon.h b/libraries/libprof/gmon.h
new file mode 100644
index 0000000..9016502
--- /dev/null
+++ b/libraries/libprof/gmon.h
@@ -0,0 +1,148 @@
+/* $OpenBSD: gmon.h,v 1.3 1996/04/21 22:31:46 deraadt Exp $ */
+/* $NetBSD: gmon.h,v 1.5 1996/04/09 20:55:30 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1982, 1986, 1992, 1993
+ * The Regents of the University of California. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)gmon.h 8.2 (Berkeley) 1/4/94
+ */
+
+/*
+ * This file is taken from Cygwin distribution. Please keep it in sync.
+ * The differences should be within __MINGW32__ guard.
+ */
+
+#ifndef _SYS_GMON_H_
+#define _SYS_GMON_H_
+
+/*
+ * Structure prepended to gmon.out profiling data file.
+ */
+struct gmonhdr {
+ size_t lpc; /* base pc address of sample buffer */
+ size_t hpc; /* max pc address of sampled buffer */
+ int ncnt; /* size of sample buffer (plus this header) */
+ int version; /* version number */
+ int profrate; /* profiling clock rate */
+ int spare[3]; /* reserved */
+};
+#define GMONVERSION 0x00051879
+
+/*
+ * histogram counters are unsigned shorts (according to the kernel).
+ */
+#define HISTCOUNTER unsigned short
+
+/*
+ * fraction of text space to allocate for histogram counters here, 1/2
+ */
+//#define HISTFRACTION 2
+#define HISTFRACTION 1
+
+/*
+ * Fraction of text space to allocate for from hash buckets.
+ * The value of HASHFRACTION is based on the minimum number of bytes
+ * of separation between two subroutine call points in the object code.
+ * Given MIN_SUBR_SEPARATION bytes of separation the value of
+ * HASHFRACTION is calculated as:
+ *
+ * HASHFRACTION = MIN_SUBR_SEPARATION / (2 * sizeof(short) - 1);
+ *
+ * For example, on the VAX, the shortest two call sequence is:
+ *
+ * calls $0,(r0)
+ * calls $0,(r0)
+ *
+ * which is separated by only three bytes, thus HASHFRACTION is
+ * calculated as:
+ *
+ * HASHFRACTION = 3 / (2 * 2 - 1) = 1
+ *
+ * Note that the division above rounds down, thus if MIN_SUBR_FRACTION
+ * is less than three, this algorithm will not work!
+ *
+ * In practice, however, call instructions are rarely at a minimal
+ * distance. Hence, we will define HASHFRACTION to be 2 across all
+ * architectures. This saves a reasonable amount of space for
+ * profiling data structures without (in practice) sacrificing
+ * any granularity.
+ */
+//#define HASHFRACTION 2
+#define HASHFRACTION 1
+
+/*
+ * percent of text space to allocate for tostructs with a minimum.
+ */
+#define ARCDENSITY 2 /* this is in percentage, relative to text size! */
+#define MINARCS 50
+#define MAXARCS ((1 << (8 * sizeof(HISTCOUNTER))) - 2)
+
+struct tostruct {
+ size_t selfpc; /* callee address. The caller address is in froms[] array which points to tos[] array */
+ unsigned long count; /* how many times it has been called */
+ unsigned short next; /* next entry in hash table. For tos[0] this is the index of the last used entry */
+ unsigned short pad; /* additional padding bytes, to have entries 4byte aligned */
+};
+
+/*
+ * a raw arc, with pointers to the calling site and
+ * the called site and a count.
+ */
+struct rawarc {
+ size_t frompc;
+ size_t selfpc;
+ long count;
+};
+
+/*
+ * general rounding functions.
+ */
+#define ROUNDDOWN(x,y) (((x)/(y))*(y))
+#define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y))
+
+/*
+ * The profiling data structures are housed in this structure.
+ */
+struct gmonparam {
+ enum { off, on, err } state;
+ unsigned short *kcount; /* histogram PC sample array */
+ size_t kcountsize; /* size of kcount[] array in bytes */
+ unsigned short *froms; /* array of hashed 'from' addresses. The 16bit value is an index into the tos[] array */
+ size_t fromssize; /* size of froms[] array in bytes */
+ struct tostruct *tos; /* to struct, contains arc counters */
+ size_t tossize; /* size of tos[] array in bytes */
+ size_t tolimit;
+ size_t lowpc; /* low program counter of area */
+ size_t highpc; /* high program counter */
+ size_t textsize; /* code size */
+};
+extern struct gmonparam _gmonparam;
+
+void _mcleanup(void); /* routine to be called to write gmon.out file */
+
+#endif /* !_SYS_GMONH_ */
diff --git a/libraries/libprof/memfunc.c b/libraries/libprof/memfunc.c
new file mode 100644
index 0000000..fc908e1
--- /dev/null
+++ b/libraries/libprof/memfunc.c
@@ -0,0 +1,127 @@
+#include <stdint.h>
+#include <string.h>
+
+/*
+ * Profilable substitutes for mem*(), lacking libc_p.a
+ *
+ * This code was written with reference to newlib, and was recently
+ * brought closer into line with newlib, to make profiling more accurate.
+ *
+ * Newlib is maintained by Cygwin, which is Red Hat. There is no copyright
+ * statement in the corresponding newlib source files, nor is there a
+ * COPYING file in newlib/libc/string or newlib/libc. Consider this file
+ * to be covered under one or more of the 50 copyright notices in
+ * newlib/COPYING, most of which are BSD. In any case, this file is only
+ * used for profiling, and is not used in production builds.
+ */
+
+#define is_word_aligned(x) (((size_t)(x) & 3) == 0)
+
+void *memcpy(void *dst, const void *src, size_t n)
+{
+ uint8_t *d8 = (uint8_t *)dst;
+ uint8_t *s8 = (uint8_t *)src;
+
+ if (n >= sizeof(uint32_t) && is_word_aligned(src) && is_word_aligned(dst)) {
+ uint32_t *d32 = (uint32_t *)dst;
+ uint32_t *s32 = (uint32_t *)src;
+ while (n >= 4 * sizeof(uint32_t)) {
+ *d32++ = *s32++;
+ *d32++ = *s32++;
+ *d32++ = *s32++;
+ *d32++ = *s32++;
+ n -= 4 * sizeof(uint32_t);
+ }
+ while (n >= sizeof(uint32_t)) {
+ *d32++ = *s32++;
+ n -= sizeof(uint32_t);
+ }
+ d8 = (uint8_t *)d32;
+ s8 = (uint8_t *)s32;
+ }
+ while (n-- > 0) {
+ *d8++ = *s8++;
+ }
+
+ return dst;
+}
+
+void *memset(void *dst, int c, size_t n)
+{
+ uint8_t *d8 = (uint8_t *)dst;
+ uint8_t c8 = (uint8_t)c;
+
+ while (!is_word_aligned(d8)) {
+ if (n--)
+ *d8++ = c8;
+ else
+ return dst;
+ }
+ if (n >= sizeof(uint32_t)) {
+ uint32_t *d32 = (uint32_t *)d8;
+ uint32_t c32 = (c8 << 24) | (c8 << 16) | (c8 << 8) | (c8);
+ while (n >= 4 * sizeof(uint32_t)) {
+ *d32++ = c32;
+ *d32++ = c32;
+ *d32++ = c32;
+ *d32++ = c32;
+ n -= 4 * sizeof(uint32_t);
+ }
+ while (n >= sizeof(uint32_t)) {
+ *d32++ = c32;
+ n -= sizeof(uint32_t);
+ }
+ d8 = (uint8_t *)d32;
+ }
+ while (n-- > 0) {
+ *d8++ = c8;
+ }
+
+ return dst;
+}
+
+int memcmp(const void *dst, const void *src, size_t n)
+{
+ uint8_t *d8 = (uint8_t *)dst;
+ uint8_t *s8 = (uint8_t *)src;
+
+ if (n >= sizeof(uint32_t) && is_word_aligned(src) && is_word_aligned(dst)) {
+ uint32_t *d32 = (uint32_t *)dst;
+ uint32_t *s32 = (uint32_t *)src;
+ while (n >= sizeof(uint32_t)) {
+ if (*d32 != *s32)
+ break;
+ d32++;
+ s32++;
+ n -= sizeof(uint32_t);
+ }
+ d8 = (uint8_t *)d32;
+ s8 = (uint8_t *)s32;
+ }
+ while (n-- > 0) {
+ if (*d8 != *s8)
+ return (*d8 - *s8);
+ d8++;
+ s8++;
+ }
+
+ return 0;
+}
+
+void *memmove(void *dst, const void *src, size_t n)
+{
+ uint8_t *d8 = (uint8_t *)dst;
+ uint8_t *s8 = (uint8_t *)src;
+
+ if ((s8 < d8) && (d8 < s8 + n)) {
+ /* Destructive overlap...have to copy backwards */
+ s8 += n;
+ d8 += n;
+ while (n-- > 0) {
+ *--d8 = *--s8;
+ }
+ return dst;
+ }
+
+ return memcpy(dst, src, n);
+}
diff --git a/libraries/libprof/profile-runner.py b/libraries/libprof/profile-runner.py
new file mode 100755
index 0000000..b96d6b6
--- /dev/null
+++ b/libraries/libprof/profile-runner.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python3
+
+"""
+Tool to run some test code under the profiler on the Cryptech Alpha.
+
+This assumes that the HSM code was built with DO_PROFILING=1, and
+requires an ST-LINK programmer and the Python pexpect package.
+"""
+
+import subprocess
+import argparse
+import pexpect
+import atexit
+import time
+import sys
+import os
+
+parser = argparse.ArgumentParser(description = __doc__,
+ formatter_class = argparse.ArgumentDefaultsHelpFormatter)
+parser.add_argument("--hsm-elf",
+ default = os.path.expanduser("~/git.cryptech.is/sw/stm32/projects/hsm/hsm.elf"),
+ help = "where you keep the profiled hsm.elf binary")
+parser.add_argument("--openocd-config",
+ default = "/usr/share/openocd/scripts/board/st_nucleo_f401re.cfg",
+ help = "OpenOCD ST-LINK configuration file ")
+parser.add_argument("--gmon-output",
+ default = "profile-runner.gmon",
+ help = "where to leave raw profiler output")
+parser.add_argument("--gprof-output", type = argparse.FileType("w"),
+ default = "profile-runner.gprof",
+ help = "where to leave profiler output after processing with gprof")
+parser.add_argument("--user",
+ default = "wheel",
+ help = "user name for logging in on the HSM console")
+parser.add_argument("--pin",
+ default = "fnord",
+ help = "PIN for logging in on the HSM console")
+parser.add_argument("command", nargs = 1,
+ help = "test program to run with profiling")
+parser.add_argument("arguments", nargs = argparse.REMAINDER,
+ help = argparse.SUPPRESS)
+args = parser.parse_args()
+
+openocd = subprocess.Popen(("openocd", "-f", args.openocd_config))
+atexit.register(openocd.terminate)
+
+time.sleep(5)
+
+telnet = pexpect.spawn("telnet localhost 4444")
+telnet.expect(">")
+telnet.sendline("arm semihosting enable")
+telnet.expect(">")
+telnet.sendline("exit")
+
+console = pexpect.spawn("cryptech_console")
+console.sendline("")
+if console.expect(["cryptech>", "Username:"]):
+ console.sendline(args.user)
+ console.expect("Password:")
+ console.sendline(args.pin)
+ console.expect("cryptech>")
+console.sendline("profile start")
+console.expect("cryptech>")
+
+cmd = args.command + args.arguments
+sys.stderr.write("Running command: {}\n".format(" ".join(cmd)))
+subprocess.check_call(cmd)
+
+console.sendline("profile stop")
+console.expect("cryptech>", timeout = 900)
+os.rename("gmon.out", args.gmon_output)
+
+subprocess.check_call(("gprof", args.hsm_elf, args.gmon_output), stdout = args.gprof_output)
diff --git a/libraries/libprof/profiler.S b/libraries/libprof/profiler.S
new file mode 100644
index 0000000..1aa5c97
--- /dev/null
+++ b/libraries/libprof/profiler.S
@@ -0,0 +1,28 @@
+/*
+ * profiler.S
+ * Implements the gprof profiler arc counting function.
+ * Created on: 06.08.2015
+ * Author: Erich Styger
+ */
+
+ .syntax unified
+ .arch armv7-m
+
+.globl __gnu_mcount_nc
+.type __gnu_mcount_nc, %function
+
+__gnu_mcount_nc:
+#if 0 /* dummy version, doing nothing */
+ mov ip, lr
+ pop { lr }
+ bx ip
+#else
+ push {r0, r1, r2, r3, lr} /* save registers */
+ bic r1, lr, #1 /* R1 contains callee address, with thumb bit cleared */
+ ldr r0, [sp, #20] /* R0 contains caller address */
+ bic r0, r0, #1 /* clear thumb bit */
+ bl _mcount_internal /* jump to internal _mcount() implementation */
+ pop {r0, r1, r2, r3, ip, lr} /* restore saved registers */
+ bx ip /* return to caller */
+#endif
+
diff --git a/libraries/libtfm/Makefile b/libraries/libtfm/Makefile
new file mode 100644
index 0000000..aa5031f
--- /dev/null
+++ b/libraries/libtfm/Makefile
@@ -0,0 +1,71 @@
+
+# This duplicates more of sw/thirdparty/libtfm/Makefile than I
+# would like, but it does the job. Prettier makefiles can wait for another day.
+
+# vpath %.c ${LIBTFM_SRC}
+# vpath %.h ${LIBTFM_SRC}
+
+BITS := 4096
+
+HDR := ${LIBTFM_SRC}/tomsfastmath/src/headers/tfm.h
+LIB := tomsfastmath/libtfm.a
+
+# See sw/thirdparty/libtfm/Makefile for compilation options. Note
+# that libtfm platform-specific assembly code has opinions on the
+# optimization level (and appears to be best tested with -O3).
+
+# Using $(subst...) here is a kludge. A cleaner approach might be for
+# sw/stm32/Makefile to build up the non-variant parts of CFLAGS in a
+# different variable before merging the variant and non-variant parts
+# into CFLAGS, which would give us a clean copy of the non-variant
+# parts to use when constructing our own CFLAGS. Later.
+
+# The ARM assembly code in libtfm still generates a lot of warnings of the form:
+#
+# warning: matching constraint does not allow a register [enabled by default]
+#
+# This is just a warning, the resulting library appears to work
+# correctly, and the fix appears to require a nasty intervention in
+# the guts of the libtfm assembly code, so we live with the warning
+# for now, at least until we confirm that it hasn't already been fixed
+# in a newer version of libtfm.
+
+ifdef DO_PROFILING
+# arm-none-eabi-gcc: error: -pg and -fomit-frame-pointer are incompatible
+STM32_LIBTFM_CFLAGS_OPTIMIZATION := -O3 -funroll-loops
+else
+STM32_LIBTFM_CFLAGS_OPTIMIZATION := -O3 -funroll-loops -fomit-frame-pointer
+endif
+
+CFLAGS := $(subst ${STM32_CFLAGS_OPTIMIZATION},${STM32_LIBTFM_CFLAGS_OPTIMIZATION},${CFLAGS})
+CFLAGS += -DTFM_ARM -DENDIAN_LITTLE -Dasm=__asm__ -Wa,-mimplicit-it=thumb
+CFLAGS += -I${LIBTFM_SRC}/tomsfastmath/src/headers
+CFLAGS += -DFP_MAX_SIZE="(${BITS}*2+(8*DIGIT_BIT))"
+CFLAGS += -Wall -W -Wshadow -Wno-uninitialized
+
+TARGETS := $(notdir ${HDR} ${LIB})
+
+REPLACE = fp_to_unsigned_bin.o
+
+all: ${TARGETS}
+
+clean:
+ rm -rf ${TARGETS} $(notdir ${HDR}.tmp) ${LIB} tomsfastmath/src ${REPLACE}
+
+distclean: clean
+ rm -f TAGS
+
+$(notdir ${HDR}): ${HDR}
+ echo >$@.tmp '/* Configure size of largest bignum we want to handle -- see notes in tfm.pdf */'
+ echo >>$@.tmp '#define FP_MAX_SIZE (${BITS}*2+(8*DIGIT_BIT))'
+ echo >>$@.tmp ''
+ cat >>$@.tmp $^
+ mv -f $@.tmp $@
+
+$(notdir ${LIB}): ${LIB}
+ ln -f $^ $@
+
+${LIB}: ${HDR} ${REPLACE}
+ (cd ${LIBTFM_SRC} && find tomsfastmath/src -type d) | xargs mkdir -p
+ cd tomsfastmath; ${MAKE} CFLAGS='${CFLAGS}'
+ ar r ${LIB} ${REPLACE}
diff --git a/libraries/libtfm/fp_to_unsigned_bin.c b/libraries/libtfm/fp_to_unsigned_bin.c
new file mode 100644
index 0000000..618167d
--- /dev/null
+++ b/libraries/libtfm/fp_to_unsigned_bin.c
@@ -0,0 +1,62 @@
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short. That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@gmail.com
+ */
+#include <tfm_private.h>
+
+void fp_to_unsigned_bin(fp_int *a, unsigned char *b)
+{
+ /* If we know the endianness of this architecture, and we're using
+ 32-bit fp_digits, we can optimize this */
+#if (defined(ENDIAN_LITTLE) || defined(ENDIAN_BIG)) && !defined(FP_64BIT)
+ /* But not for both simultaneously */
+#if defined(ENDIAN_LITTLE) && defined(ENDIAN_BIG)
+#error Both ENDIAN_LITTLE and ENDIAN_BIG defined.
+#endif
+ {
+ int c = fp_unsigned_bin_size(a);
+ unsigned char *pd = (unsigned char *)a->dp;
+
+ /* read the bytes out */
+#ifdef ENDIAN_BIG
+ {
+ /* Use Duff's device to unroll the loop. */
+ int idx = (c - 1) & ~3;
+ switch (c % 4) {
+ case 0: do { b[idx+0] = *pd++;
+ case 3: b[idx+1] = *pd++;
+ case 2: b[idx+2] = *pd++;
+ case 1: b[idx+3] = *pd++;
+ idx -= 4;
+ } while ((c -= 4) > 0);
+ }
+ }
+#else
+ for (c -= 1; c >= 0; c -= 1) {
+ b[c] = *pd++;
+ }
+#endif
+ }
+#else
+ int x;
+ fp_int t;
+
+ fp_init_copy(&t, a);
+
+ x = 0;
+ while (fp_iszero (&t) == FP_NO) {
+ b[x++] = (unsigned char) (t.dp[0] & 255);
+ fp_div_2d (&t, 8, &t, NULL);
+ }
+ fp_reverse (b, x);
+#endif
+}
+
+/* $Source$ */
+/* $Revision$ */
+/* $Date$ */
diff --git a/libraries/libtfm/tomsfastmath/Makefile b/libraries/libtfm/tomsfastmath/Makefile
new file mode 100644
index 0000000..695aa92
--- /dev/null
+++ b/libraries/libtfm/tomsfastmath/Makefile
@@ -0,0 +1,4 @@
+vpath %.c ${LIBTFM_SRC}/tomsfastmath
+vpath %.h ${LIBTFM_SRC}/tomsfastmath
+
+include ${LIBTFM_SRC}/tomsfastmath/makefile
diff --git a/libraries/mbed/Makefile b/libraries/mbed/Makefile
index 9d68e92..eb2bd2b 100644
--- a/libraries/mbed/Makefile
+++ b/libraries/mbed/Makefile
@@ -1,9 +1,11 @@
CC=arm-none-eabi-gcc
AR=arm-none-eabi-ar
+CFLAGS += -Wno-unused-parameter
+
###########################################
-vpath %.c targets/cmsis/TARGET_STM/TARGET_STM32F4 targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_DEV_BRIDGE
+vpath %.c $(CMSIS_DIR) $(BOARD_DIR)
SRCS = stm32f4xx_hal.c \
stm32f4xx_hal_adc.c \
diff --git a/libraries/mbed/rtos/Makefile b/libraries/mbed/rtos/Makefile
deleted file mode 100644
index 496791c..0000000
--- a/libraries/mbed/rtos/Makefile
+++ /dev/null
@@ -1,40 +0,0 @@
-CC=arm-none-eabi-gcc
-AR=arm-none-eabi-ar
-
-###########################################
-
-vpath %.c rtx/TARGET_CORTEX_M
-vpath %.S rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_GCC
-
-SRCS = rtos/rtos_idle.c \
- HAL_CM.c \
- rt_CMSIS.c \
- rt_Event.c \
- rt_List.c \
- rt_Mailbox.c \
- rt_MemBox.c \
- rt_Mutex.c \
- rt_Robin.c \
- rt_Semaphore.c \
- rt_System.c \
- rt_Task.c \
- rt_Time.c \
- RTX_Conf_CM.c \
- HAL_CM4.S \
- SVC_Table.S
-
-OBJS = $(patsubst %.S,%.o, $(patsubst %.c,%.o, $(SRCS)))
-
-all: librtos.a
-
-%.o : %.c
- $(CC) $(CFLAGS) -c -o $@ $<
-
-%.o : %.S
- $(CC) $(CFLAGS) -c -o $@ $<
-
-librtos.a: $(OBJS)
- $(AR) -r $@ $(OBJS)
-
-clean:
- rm -f $(OBJS) librtos.a
diff --git a/libraries/mbed/rtos/rtos/rtos_idle.c b/libraries/mbed/rtos/rtos/rtos_idle.c
deleted file mode 100644
index 1edef6e..0000000
--- a/libraries/mbed/rtos/rtos/rtos_idle.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/* mbed Microcontroller Library
- * Copyright (c) 2006-2012 ARM Limited
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include "rtos_idle.h"
-
-static void default_idle_hook(void)
-{
- /* Sleep: ideally, we should put the chip to sleep.
- Unfortunately, this usually requires disconnecting the interface chip (debugger).
- This can be done, but it would break the local file system.
- */
- // sleep();
-}
-static void (*idle_hook_fptr)(void) = &default_idle_hook;
-
-void rtos_attach_idle_hook(void (*fptr)(void))
-{
- //Attach the specified idle hook, or the default idle hook in case of a NULL pointer
- if (fptr != NULL) {
- idle_hook_fptr = fptr;
- } else {
- idle_hook_fptr = default_idle_hook;
- }
-}
-
-void rtos_idle_loop(void)
-{
- //Continuously call the idle hook function pointer
- while (1) {
- idle_hook_fptr();
- }
-}
diff --git a/libraries/mbed/rtos/rtos/rtos_idle.h b/libraries/mbed/rtos/rtos/rtos_idle.h
deleted file mode 100644
index 851f5f7..0000000
--- a/libraries/mbed/rtos/rtos/rtos_idle.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* mbed Microcontroller Library
- * Copyright (c) 2006-2012 ARM Limited
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#ifndef RTOS_IDLE_H
-#define RTOS_IDLE_H
-
-#include <stddef.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void rtos_attach_idle_hook(void (*fptr)(void));
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/HAL_CM.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/HAL_CM.c
deleted file mode 100644
index efbe04c..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/HAL_CM.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: HAL_CM.C
- * Purpose: Hardware Abstraction Layer for Cortex-M
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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 "rt_TypeDef.h"
-#include "RTX_Conf.h"
-#include "rt_HAL_CM.h"
-
-
-/*----------------------------------------------------------------------------
- * Global Variables
- *---------------------------------------------------------------------------*/
-
-#ifdef DBG_MSG
-BIT dbg_msg;
-#endif
-
-/*----------------------------------------------------------------------------
- * Functions
- *---------------------------------------------------------------------------*/
-
-
-/*--------------------------- rt_init_stack ---------------------------------*/
-
-void rt_init_stack (P_TCB p_TCB, FUNCP task_body) {
- /* Prepare TCB and saved context for a first time start of a task. */
- U32 *stk,i,size;
-
- /* Prepare a complete interrupt frame for first task start */
- size = p_TCB->priv_stack >> 2;
-
- /* Write to the top of stack. */
- stk = &p_TCB->stack[size];
-
- /* Auto correct to 8-byte ARM stack alignment. */
- if ((U32)stk & 0x04) {
- stk--;
- }
-
- stk -= 16;
-
- /* Default xPSR and initial PC */
- stk[15] = INITIAL_xPSR;
- stk[14] = (U32)task_body;
-
- /* Clear R4-R11,R0-R3,R12,LR registers. */
- for (i = 0; i < 14; i++) {
- stk[i] = 0;
- }
-
- /* Assign a void pointer to R0. */
- stk[8] = (U32)p_TCB->msg;
-
- /* Initial Task stack pointer. */
- p_TCB->tsk_stack = (U32)stk;
-
- /* Task entry point. */
- p_TCB->ptask = task_body;
-
- /* Set a magic word for checking of stack overflow.
- For the main thread (ID: 0x01) the stack is in a memory area shared with the
- heap, therefore the last word of the stack is a moving target.
- We want to do stack/heap collision detection instead.
- */
- if (p_TCB->task_id != 0x01)
- p_TCB->stack[0] = MAGIC_WORD;
-}
-
-
-/*--------------------------- rt_ret_val ----------------------------------*/
-
-static __inline U32 *rt_ret_regs (P_TCB p_TCB) {
- /* Get pointer to task return value registers (R0..R3) in Stack */
-#if (__TARGET_FPU_VFP)
- if (p_TCB->stack_frame) {
- /* Extended Stack Frame: R4-R11,S16-S31,R0-R3,R12,LR,PC,xPSR,S0-S15,FPSCR */
- return (U32 *)(p_TCB->tsk_stack + 8*4 + 16*4);
- } else {
- /* Basic Stack Frame: R4-R11,R0-R3,R12,LR,PC,xPSR */
- return (U32 *)(p_TCB->tsk_stack + 8*4);
- }
-#else
- /* Stack Frame: R4-R11,R0-R3,R12,LR,PC,xPSR */
- return (U32 *)(p_TCB->tsk_stack + 8*4);
-#endif
-}
-
-void rt_ret_val (P_TCB p_TCB, U32 v0) {
- U32 *ret;
-
- ret = rt_ret_regs(p_TCB);
- ret[0] = v0;
-}
-
-void rt_ret_val2(P_TCB p_TCB, U32 v0, U32 v1) {
- U32 *ret;
-
- ret = rt_ret_regs(p_TCB);
- ret[0] = v0;
- ret[1] = v1;
-}
-
-
-/*--------------------------- dbg_init --------------------------------------*/
-
-#ifdef DBG_MSG
-void dbg_init (void) {
- if ((DEMCR & DEMCR_TRCENA) &&
- (ITM_CONTROL & ITM_ITMENA) &&
- (ITM_ENABLE & (1UL << 31))) {
- dbg_msg = __TRUE;
- }
-}
-#endif
-
-/*--------------------------- dbg_task_notify -------------------------------*/
-
-#ifdef DBG_MSG
-void dbg_task_notify (P_TCB p_tcb, BOOL create) {
- while (ITM_PORT31_U32 == 0);
- ITM_PORT31_U32 = (U32)p_tcb->ptask;
- while (ITM_PORT31_U32 == 0);
- ITM_PORT31_U16 = (create << 8) | p_tcb->task_id;
-}
-#endif
-
-/*--------------------------- dbg_task_switch -------------------------------*/
-
-#ifdef DBG_MSG
-void dbg_task_switch (U32 task_id) {
- while (ITM_PORT31_U32 == 0);
- ITM_PORT31_U8 = task_id;
-}
-#endif
-
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
-
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/RTX_CM_lib.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/RTX_CM_lib.h
deleted file mode 100755
index 23697ef..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/RTX_CM_lib.h
+++ /dev/null
@@ -1,537 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RTX_CM_LIB.H
- * Purpose: RTX Kernel System Configuration
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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 "mbed_error.h"
-
-#if defined (__CC_ARM)
-#pragma O3
-#define __USED __attribute__((used))
-#elif defined (__GNUC__)
-#pragma GCC optimize ("O3")
-#define __USED __attribute__((used))
-#elif defined (__ICCARM__)
-#define __USED __root
-#endif
-
-
-/*----------------------------------------------------------------------------
- * Definitions
- *---------------------------------------------------------------------------*/
-
-#define _declare_box(pool,size,cnt) uint32_t pool[(((size)+3)/4)*(cnt) + 3]
-#define _declare_box8(pool,size,cnt) uint64_t pool[(((size)+7)/8)*(cnt) + 2]
-
-#define OS_TCB_SIZE 48
-#define OS_TMR_SIZE 8
-
-#if defined (__CC_ARM) && !defined (__MICROLIB)
-
-typedef void *OS_ID;
-typedef uint32_t OS_TID;
-typedef uint32_t OS_MUT[3];
-typedef uint32_t OS_RESULT;
-
-#define runtask_id() rt_tsk_self()
-#define mutex_init(m) rt_mut_init(m)
-#define mutex_wait(m) os_mut_wait(m,0xFFFF)
-#define mutex_rel(m) os_mut_release(m)
-
-extern OS_TID rt_tsk_self (void);
-extern void rt_mut_init (OS_ID mutex);
-extern OS_RESULT rt_mut_release (OS_ID mutex);
-extern OS_RESULT rt_mut_wait (OS_ID mutex, uint16_t timeout);
-
-#define os_mut_wait(mutex,timeout) _os_mut_wait((uint32_t)rt_mut_wait,mutex,timeout)
-#define os_mut_release(mutex) _os_mut_release((uint32_t)rt_mut_release,mutex)
-
-OS_RESULT _os_mut_release (uint32_t p, OS_ID mutex) __svc_indirect(0);
-OS_RESULT _os_mut_wait (uint32_t p, OS_ID mutex, uint16_t timeout) __svc_indirect(0);
-
-#endif
-
-
-/*----------------------------------------------------------------------------
- * Global Variables
- *---------------------------------------------------------------------------*/
-
-#if (OS_TIMERS != 0)
-#define OS_TASK_CNT (OS_TASKCNT + 1)
-#else
-#define OS_TASK_CNT OS_TASKCNT
-#endif
-
-uint16_t const os_maxtaskrun = OS_TASK_CNT;
-uint32_t const os_rrobin = (OS_ROBIN << 16) | OS_ROBINTOUT;
-uint32_t const os_trv = OS_TRV;
-uint8_t const os_flags = OS_RUNPRIV;
-
-/* Export following defines to uVision debugger. */
-__USED uint32_t const os_clockrate = OS_TICK;
-__USED uint32_t const os_timernum = 0;
-
-/* Stack for the os_idle_demon */
-unsigned int idle_task_stack[OS_IDLESTKSIZE];
-unsigned short const idle_task_stack_size = OS_IDLESTKSIZE;
-
-#ifndef OS_FIFOSZ
- #define OS_FIFOSZ 16
-#endif
-
-/* Fifo Queue buffer for ISR requests.*/
-uint32_t os_fifo[OS_FIFOSZ*2+1];
-uint8_t const os_fifo_size = OS_FIFOSZ;
-
-/* An array of Active task pointers. */
-void *os_active_TCB[OS_TASK_CNT];
-
-/* User Timers Resources */
-#if (OS_TIMERS != 0)
-extern void osTimerThread (void const *argument);
-osThreadDef(osTimerThread, (osPriority)(OS_TIMERPRIO-3), 4*OS_TIMERSTKSZ);
-osThreadId osThreadId_osTimerThread;
-osMessageQDef(osTimerMessageQ, OS_TIMERCBQS, void *);
-osMessageQId osMessageQId_osTimerMessageQ;
-#else
-osThreadDef_t os_thread_def_osTimerThread = { NULL };
-osThreadId osThreadId_osTimerThread;
-osMessageQDef(osTimerMessageQ, 0, void *);
-osMessageQId osMessageQId_osTimerMessageQ;
-#endif
-
-
-/*----------------------------------------------------------------------------
- * RTX Optimizations (empty functions)
- *---------------------------------------------------------------------------*/
-
-#if OS_ROBIN == 0
- void rt_init_robin (void) {;}
- void rt_chk_robin (void) {;}
-#endif
-
-#if OS_STKCHECK == 0
- void rt_stk_check (void) {;}
-#endif
-
-
-/*----------------------------------------------------------------------------
- * Standard Library multithreading interface
- *---------------------------------------------------------------------------*/
-
-#if defined (__CC_ARM) && !defined (__MICROLIB)
- static OS_MUT std_libmutex[OS_MUTEXCNT];
- static uint32_t nr_mutex;
-
- /*--------------------------- _mutex_initialize -----------------------------*/
-
-int _mutex_initialize (OS_ID *mutex) {
- /* Allocate and initialize a system mutex. */
-
- if (nr_mutex >= OS_MUTEXCNT) {
- /* If you are here, you need to increase the number OS_MUTEXCNT. */
- error("Not enough stdlib mutexes\n");
- }
- *mutex = &std_libmutex[nr_mutex++];
- mutex_init (*mutex);
- return (1);
-}
-
-
-/*--------------------------- _mutex_acquire --------------------------------*/
-
-__attribute__((used)) void _mutex_acquire (OS_ID *mutex) {
- /* Acquire a system mutex, lock stdlib resources. */
- if (runtask_id ()) {
- /* RTX running, acquire a mutex. */
- mutex_wait (*mutex);
- }
-}
-
-
-/*--------------------------- _mutex_release --------------------------------*/
-
-__attribute__((used)) void _mutex_release (OS_ID *mutex) {
- /* Release a system mutex, unlock stdlib resources. */
- if (runtask_id ()) {
- /* RTX running, release a mutex. */
- mutex_rel (*mutex);
- }
-}
-
-#endif
-
-
-/*----------------------------------------------------------------------------
- * RTX Startup
- *---------------------------------------------------------------------------*/
-
-/* Main Thread definition */
-extern int main (void);
-osThreadDef_t os_thread_def_main = {(os_pthread)main, osPriorityNormal, 0, NULL};
-
-// This define should be probably moved to the CMSIS layer
-#if defined(TARGET_LPC1768)
-#define INITIAL_SP (0x10008000UL)
-
-#elif defined(TARGET_LPC11U24)
-#define INITIAL_SP (0x10002000UL)
-
-#elif defined(TARGET_LPC11U35_401) || defined(TARGET_LPC11U35_501) || defined(TARGET_LPCCAPPUCCINO)
-#define INITIAL_SP (0x10002000UL)
-
-#elif defined(TARGET_LPC1114)
-#define INITIAL_SP (0x10001000UL)
-
-#elif defined(TARGET_LPC812)
-#define INITIAL_SP (0x10001000UL)
-
-#elif defined(TARGET_LPC824) || defined(TARGET_SSCI824)
-#define INITIAL_SP (0x10002000UL)
-
-#elif defined(TARGET_KL25Z)
-#define INITIAL_SP (0x20003000UL)
-
-#elif defined(TARGET_KL26Z)
-#define INITIAL_SP (0x20003000UL)
-
-#elif defined(TARGET_K64F)
-#define INITIAL_SP (0x20030000UL)
-
-#elif defined(TARGET_K22F)
-#define INITIAL_SP (0x20010000UL)
-
-#elif defined(TARGET_KL46Z)
-#define INITIAL_SP (0x20006000UL)
-
-#elif defined(TARGET_KL43Z)
-#define INITIAL_SP (0x20006000UL)
-
-#elif defined(TARGET_KL05Z)
-#define INITIAL_SP (0x20000C00UL)
-
-#elif defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM)
-#define INITIAL_SP (0x10010000UL)
-
-#elif defined(TARGET_LPC4330)
-#define INITIAL_SP (0x10008000UL)
-
-#elif defined(TARGET_LPC4337)
-#define INITIAL_SP (0x10008000UL)
-
-#elif defined(TARGET_LPC1347)
-#define INITIAL_SP (0x10002000UL)
-
-#elif defined(TARGET_STM32F100RB) || defined(TARGET_STM32F051R8)
-#define INITIAL_SP (0x20002000UL)
-
-#elif defined(TARGET_DISCO_F303VC)
-#define INITIAL_SP (0x2000A000UL)
-
-#elif defined(TARGET_STM32F407) || defined(TARGET_F407VG)
-#define INITIAL_SP (0x20020000UL)
-
-#elif defined(TARGET_STM32F401RE)
-#define INITIAL_SP (0x20018000UL)
-
-#elif defined(TARGET_LPC1549)
-#define INITIAL_SP (0x02009000UL)
-
-#elif defined(TARGET_LPC11U68)
-#define INITIAL_SP (0x10008000UL)
-
-#elif defined(TARGET_STM32F411RE)
-#define INITIAL_SP (0x20020000UL)
-
-#elif defined(TARGET_STM32F410RB)
-#define INITIAL_SP (0x20008000UL)
-
-#elif defined(TARGET_STM32F103RB) || defined(TARGET_STM32L073RZ)
-#define INITIAL_SP (0x20005000UL)
-
-#elif defined(TARGET_STM32F302R8)
-#define INITIAL_SP (0x20004000UL)
-
-#elif defined(TARGET_STM32F334R8)
-#define INITIAL_SP (0x20003000UL)
-
-#elif defined(TARGET_STM32F334C8)
-#define INITIAL_SP (0x20003000UL)
-
-#elif defined(TARGET_STM32F405RG)
-#define INITIAL_SP (0x20020000UL)
-
-#elif defined(TARGET_STM32F429ZI)
-#define INITIAL_SP (0x20030000UL)
-
-#elif defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8)
-#define INITIAL_SP (0x20002000UL)
-
-#elif defined(TARGET_STM32F072RB)
-#define INITIAL_SP (0x20004000UL)
-
-#elif defined(TARGET_STM32F091RC)
-#define INITIAL_SP (0x20008000UL)
-
-#elif defined(TARGET_STM32F401VC)
-#define INITIAL_SP (0x20010000UL)
-
-#elif defined(TARGET_STM32F303RE)
-#define INITIAL_SP (0x20010000UL)
-
-#elif defined(TARGET_STM32F303K8)
-#define INITIAL_SP (0x20003000UL)
-
-#elif (defined(TARGET_STM32F746NG) || defined(TARGET_STM32F746ZG))
-#define INITIAL_SP (0x20050000UL)
-
-#elif defined(TARGET_MAX32610) || defined(TARGET_MAX32600)
-#define INITIAL_SP (0x20008000UL)
-
-#elif defined(TARGET_TEENSY3_1)
-#define INITIAL_SP (0x20008000UL)
-
-#elif defined(TARGET_STM32L152RE)
-#define INITIAL_SP (0x20014000UL)
-
-#elif defined(TARGET_NZ32_SC151)
-#define INITIAL_SP (0x20008000UL)
-
-#elif (defined(TARGET_STM32F446RE) || defined(TARGET_STM32F446VE))
-#define INITIAL_SP (0x20020000UL)
-
-#elif defined(TARGET_STM32F070RB) || defined(TARGET_STM32F030R8)
-#define INITIAL_SP (0x20002000UL)
-
-#elif defined(TARGET_STM32L476VG)
-#define INITIAL_SP (0x20018000UL)
-
-#elif defined(TARGET_STM32L476RG)
-#define INITIAL_SP (0x20018000UL)
-
-#elif defined(TARGET_STM32F469NI)
-#define INITIAL_SP (0x20050000UL)
-
-#elif defined(TARGET_STM32L152RC)
-#define INITIAL_SP (0x20008000UL)
-
-
-#else
-#error "no target defined"
-
-#endif
-
-#ifdef __CC_ARM
-extern uint32_t Image$$RW_IRAM1$$ZI$$Limit[];
-#define HEAP_START (Image$$RW_IRAM1$$ZI$$Limit)
-#elif defined(__GNUC__)
-extern uint32_t __end__[];
-#define HEAP_START (__end__)
-#elif defined(__ICCARM__)
-#pragma section="HEAP"
-#define HEAP_START (void *)__section_begin("HEAP")
-#endif
-
-void set_main_stack(void) {
- // That is the bottom of the main stack block: no collision detection
- os_thread_def_main.stack_pointer = HEAP_START;
-
- // Leave OS_SCHEDULERSTKSIZE words for the scheduler and interrupts
- os_thread_def_main.stacksize = (INITIAL_SP - (unsigned int)HEAP_START) - (OS_SCHEDULERSTKSIZE * 4);
-}
-
-#if defined (__CC_ARM)
-#ifdef __MICROLIB
-void _main_init (void) __attribute__((section(".ARM.Collect$$$$000000FF")));
-void _main_init (void) {
- osKernelInitialize();
- set_main_stack();
- osThreadCreate(&os_thread_def_main, NULL);
- osKernelStart();
- for (;;);
-}
-#else
-
-/* The single memory model is checking for stack collision at run time, verifing
- that the heap pointer is underneath the stack pointer.
-
- With the RTOS there is not only one stack above the heap, there are multiple
- stacks and some of them are underneath the heap pointer.
-*/
-#pragma import(__use_two_region_memory)
-
-__asm void __rt_entry (void) {
-
- IMPORT __user_setup_stackheap
- IMPORT __rt_lib_init
- IMPORT os_thread_def_main
- IMPORT osKernelInitialize
- IMPORT set_main_stack
- IMPORT osKernelStart
- IMPORT osThreadCreate
- IMPORT exit
-
- BL __user_setup_stackheap
- MOV R1,R2
- BL __rt_lib_init
- BL osKernelInitialize
- BL set_main_stack
- LDR R0,=os_thread_def_main
- MOVS R1,#0
- BL osThreadCreate
- BL osKernelStart
- BL exit
-
- ALIGN
-}
-#endif
-
-#elif defined (__GNUC__)
-
-#ifdef __CS3__
-
-/* CS3 start_c routine.
- *
- * Copyright (c) 2006, 2007 CodeSourcery Inc
- *
- * The authors hereby grant permission to use, copy, modify, distribute,
- * and license this software and its documentation for any purpose, provided
- * that existing copyright notices are retained in all copies and that this
- * notice is included verbatim in any distributions. No written agreement,
- * license, or royalty fee is required for any of the authorized uses.
- * Modifications to this software may be copyrighted by their authors
- * and need not follow the licensing terms described here, provided that
- * the new terms are clearly indicated on the first page of each file where
- * they apply.
- */
-
-#include "cs3.h"
-
-extern void __libc_init_array (void);
-
-__attribute ((noreturn)) void __cs3_start_c (void){
- unsigned regions = __cs3_region_num;
- const struct __cs3_region *rptr = __cs3_regions;
-
- /* Initialize memory */
- for (regions = __cs3_region_num, rptr = __cs3_regions; regions--; rptr++) {
- long long *src = (long long *)rptr->init;
- long long *dst = (long long *)rptr->data;
- unsigned limit = rptr->init_size;
- unsigned count;
-
- if (src != dst)
- for (count = 0; count != limit; count += sizeof (long long))
- *dst++ = *src++;
- else
- dst = (long long *)((char *)dst + limit);
- limit = rptr->zero_size;
- for (count = 0; count != limit; count += sizeof (long long))
- *dst++ = 0;
- }
-
- /* Run initializers. */
- __libc_init_array ();
-
- osKernelInitialize();
- set_main_stack();
- osThreadCreate(&os_thread_def_main, NULL);
- osKernelStart();
- for (;;);
-}
-
-#else
-
-__attribute__((naked)) void software_init_hook (void) {
- __asm (
- ".syntax unified\n"
- ".thumb\n"
- "movs r0,#0\n"
- "movs r1,#0\n"
- "mov r4,r0\n"
- "mov r5,r1\n"
- "ldr r0,= __libc_fini_array\n"
- "bl atexit\n"
- "bl __libc_init_array\n"
- "mov r0,r4\n"
- "mov r1,r5\n"
- "bl osKernelInitialize\n"
- "bl set_main_stack\n"
- "ldr r0,=os_thread_def_main\n"
- "movs r1,#0\n"
- "bl osThreadCreate\n"
- "bl osKernelStart\n"
- "bl exit\n"
- );
-}
-
-#endif
-
-#elif defined (__ICCARM__)
-
-extern void* __vector_table;
-extern int __low_level_init(void);
-extern void __iar_data_init3(void);
-extern __weak void __iar_init_core( void );
-extern __weak void __iar_init_vfp( void );
-extern void __iar_dynamic_initialization(void);
-extern void mbed_sdk_init(void);
-extern void exit(int arg);
-
-#pragma required=__vector_table
-void __iar_program_start( void )
-{
- __iar_init_core();
- __iar_init_vfp();
-
- int a;
-
- if (__low_level_init() != 0) {
- __iar_data_init3();
- mbed_sdk_init();
- __iar_dynamic_initialization();
- }
- osKernelInitialize();
- set_main_stack();
- osThreadCreate(&os_thread_def_main, NULL);
- a = osKernelStart();
- exit(a);
-
-}
-
-#endif
-
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
-
-
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/RTX_Conf.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/RTX_Conf.h
deleted file mode 100644
index 0b0d461..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/RTX_Conf.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RTX_CONFIG.H
- * Purpose: Exported functions of RTX_Config.c
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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.
- *---------------------------------------------------------------------------*/
-
-
-/* Error Codes */
-#define OS_ERR_STK_OVF 1
-#define OS_ERR_FIFO_OVF 2
-#define OS_ERR_MBX_OVF 3
-
-/* Definitions */
-#define BOX_ALIGN_8 0x80000000
-#define _declare_box(pool,size,cnt) U32 pool[(((size)+3)/4)*(cnt) + 3]
-#define _declare_box8(pool,size,cnt) U64 pool[(((size)+7)/8)*(cnt) + 2]
-#define _init_box8(pool,size,bsize) _init_box (pool,size,(bsize) | BOX_ALIGN_8)
-
-/* Variables */
-extern U32 idle_task_stack[];
-extern U32 os_fifo[];
-extern void *os_active_TCB[];
-
-/* Constants */
-extern U16 const os_maxtaskrun;
-extern U32 const os_trv;
-extern U8 const os_flags;
-extern U32 const os_rrobin;
-extern U32 const os_clockrate;
-extern U32 const os_timernum;
-extern U16 const idle_task_stack_size;
-
-extern U8 const os_fifo_size;
-
-/* Functions */
-extern void os_idle_demon (void);
-extern int os_tick_init (void);
-extern void os_tick_irqack (void);
-extern void os_tmr_call (U16 info);
-extern void os_error (U32 err_code);
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/RTX_Conf_CM.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/RTX_Conf_CM.c
deleted file mode 100755
index 788edfd..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/RTX_Conf_CM.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RTX_Conf_CM.C
- * Purpose: Configuration of CMSIS RTX Kernel for Cortex-M
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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 "cmsis_os.h"
-
-
-/*----------------------------------------------------------------------------
- * RTX User configuration part BEGIN
- *---------------------------------------------------------------------------*/
-
-//-------- <<< Use Configuration Wizard in Context Menu >>> -----------------
-//
-// <h>Thread Configuration
-// =======================
-//
-// <o>Number of concurrent running threads <0-250>
-// <i> Defines max. number of threads that will run at the same time.
-// counting "main", but not counting "osTimerThread"
-// <i> Default: 6
-#ifndef OS_TASKCNT
-# if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM) || defined(TARGET_LPC4330) || defined(TARGET_LPC4337) || defined(TARGET_LPC1347) || defined(TARGET_K64F) || defined(TARGET_STM32F401RE)\
- || defined(TARGET_STM32F410RB) || defined(TARGET_KL46Z) || defined(TARGET_KL43Z) || defined(TARGET_STM32F407) || defined(TARGET_F407VG) || defined(TARGET_STM32F303VC) || defined(TARGET_LPC1549) || defined(TARGET_LPC11U68) \
- || defined(TARGET_STM32F411RE) || defined(TARGET_STM32F405RG) || defined(TARGET_K22F) || defined(TARGET_STM32F429ZI) || defined(TARGET_STM32F401VC) || defined(TARGET_MAX32610) || defined(TARGET_MAX32600) || defined(TARGET_TEENSY3_1) \
- || defined(TARGET_STM32L152RE) || defined(TARGET_STM32F446RE) || defined(TARGET_STM32F446VE) || defined(TARGET_STM32L476VG) || defined(TARGET_STM32L476RG) || defined(TARGET_STM32F469NI) || defined(TARGET_STM32F746NG) || defined(TARGET_STM32F746ZG) || defined(TARGET_STM32L152RC)
-# define OS_TASKCNT 14
-# elif defined(TARGET_LPC11U24) || defined(TARGET_STM32F303RE) || defined(TARGET_STM32F303K8) || defined(TARGET_LPC11U35_401) || defined(TARGET_LPC11U35_501) || defined(TARGET_LPCCAPPUCCINO) || defined(TARGET_LPC1114) \
- || defined(TARGET_LPC812) || defined(TARGET_KL25Z) || defined(TARGET_KL26Z) || defined(TARGET_KL05Z) || defined(TARGET_STM32F100RB) || defined(TARGET_STM32F051R8) \
- || defined(TARGET_STM32F103RB) || defined(TARGET_LPC824) || defined(TARGET_STM32F302R8) || defined(TARGET_STM32F334R8) || defined(TARGET_STM32F334C8) \
- || defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8) || defined(TARGET_STM32L073RZ) || defined(TARGET_STM32F072RB) || defined(TARGET_STM32F091RC) || defined(TARGET_NZ32_SC151) \
- || defined(TARGET_SSCI824) || defined(TARGET_STM32F030R8) || defined(TARGET_STM32F070RB)
-# define OS_TASKCNT 6
-# else
-# error "no target defined"
-# endif
-#endif
-
-// <o>Scheduler (+ interrupts) stack size [bytes] <64-4096:8><#/4>
-#ifndef OS_SCHEDULERSTKSIZE
-# if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM) || defined(TARGET_LPC4330) || defined(TARGET_LPC4337) || defined(TARGET_LPC1347) || defined(TARGET_K64F) || defined(TARGET_STM32F401RE)\
- || defined(TARGET_STM32F410RB) || defined(TARGET_KL46Z) || defined(TARGET_KL43Z) || defined(TARGET_STM32F407) || defined(TARGET_F407VG) || defined(TARGET_STM32F303VC) || defined(TARGET_LPC1549) || defined(TARGET_LPC11U68) \
- || defined(TARGET_STM32F411RE) || defined(TARGET_STM32F405RG) || defined(TARGET_K22F) || defined(TARGET_STM32F429ZI) || defined(TARGET_STM32F401VC) || defined(TARGET_MAX32610) || defined(TARGET_MAX32600) || defined(TARGET_TEENSY3_1) \
- || defined(TARGET_STM32L152RE) || defined(TARGET_STM32F446RE) || defined(TARGET_STM32F446VE) || defined(TARGET_STM32L476VG) || defined(TARGET_STM32L476RG) || defined(TARGET_STM32F469NI) || defined(TARGET_STM32F746NG) || defined(TARGET_STM32F746ZG) || defined(TARGET_STM32L152RC)
-# define OS_SCHEDULERSTKSIZE 256
-# elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11U35_401) || defined(TARGET_LPC11U35_501) || defined(TARGET_LPCCAPPUCCINO) || defined(TARGET_LPC1114) \
- || defined(TARGET_LPC812) || defined(TARGET_KL25Z) || defined(TARGET_KL26Z) || defined(TARGET_KL05Z) || defined(TARGET_STM32F100RB) || defined(TARGET_STM32F051R8) \
- || defined(TARGET_STM32F103RB) || defined(TARGET_LPC824) || defined(TARGET_STM32F302R8) || defined(TARGET_STM32F072RB) || defined(TARGET_STM32F091RC) || defined(TARGET_NZ32_SC151) \
- || defined(TARGET_SSCI824) || defined(TARGET_STM32F030R8) || defined(TARGET_STM32F070RB)
-# define OS_SCHEDULERSTKSIZE 128
-# elif defined(TARGET_STM32F334R8) || defined(TARGET_STM32F303RE) || defined(TARGET_STM32F303K8) || defined(TARGET_STM32F334C8) || defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8) || defined(TARGET_STM32L073RZ)
-# define OS_SCHEDULERSTKSIZE 112
-# else
-# error "no target defined"
-# endif
-#endif
-
-// <o>Idle stack size [bytes] <64-4096:8><#/4>
-// <i> Defines default stack size for the Idle thread.
-#ifndef OS_IDLESTKSIZE
- #define OS_IDLESTKSIZE 128
-#endif
-
-// <o>Timer Thread stack size [bytes] <64-4096:8><#/4>
-// <i> Defines stack size for Timer thread.
-// <i> Default: 200
-#ifndef OS_TIMERSTKSZ
- #define OS_TIMERSTKSZ WORDS_STACK_SIZE
-#endif
-
-// <q>Check for stack overflow
-// <i> Includes the stack checking code for stack overflow.
-// <i> Note that additional code reduces the Kernel performance.
-#ifndef OS_STKCHECK
- #define OS_STKCHECK 1
-#endif
-
-// <o>Processor mode for thread execution
-// <0=> Unprivileged mode
-// <1=> Privileged mode
-// <i> Default: Privileged mode
-#ifndef OS_RUNPRIV
- #define OS_RUNPRIV 1
-#endif
-
-// </h>
-// <h>SysTick Timer Configuration
-// ==============================
-//
-// <o>Timer clock value [Hz] <1-1000000000>
-// <i> Defines the timer clock value.
-// <i> Default: 6000000 (6MHz)
-#ifndef OS_CLOCK
-# if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_TEENSY3_1)
-# define OS_CLOCK 96000000
-
-# elif defined(TARGET_LPC1347) || defined(TARGET_STM32F303VC) || defined(TARGET_LPC1549) || defined(TARGET_STM32F334R8) || defined(TARGET_STM32F334C8) || defined(TARGET_STM32F303RE)
-# define OS_CLOCK 72000000
-
-# elif defined(TARGET_STM32F303K8)
-# define OS_CLOCK 64000000
-
-# elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11U35_401) || defined(TARGET_LPC11U35_501) || defined(TARGET_LPCCAPPUCCINO) || defined(TARGET_LPC1114) || defined(TARGET_KL25Z) \
- || defined(TARGET_KL26Z) || defined(TARGET_KL05Z) || defined(TARGET_KL46Z) || defined(TARGET_KL43Z) || defined(TARGET_STM32F051R8) || defined(TARGET_LPC11U68) || defined(TARGET_STM32F072RB) || defined(TARGET_STM32F091RC)
-# define OS_CLOCK 48000000
-
-# elif defined(TARGET_LPC812)
-# define OS_CLOCK 36000000
-
-# elif defined(TARGET_LPC824) || defined(TARGET_SSCI824)
-# define OS_CLOCK 30000000
-
-# elif defined(TARGET_STM32F100RB)
-# define OS_CLOCK 24000000
-
-# elif defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM) || defined(TARGET_K64F) || defined(TARGET_K22F)
-# define OS_CLOCK 120000000
-
-# elif defined(TARGET_LPC4330)
-# define OS_CLOCK 204000000
-
-# elif defined(TARGET_LPC4337)
-# define OS_CLOCK 204000000
-
-# elif defined(TARGET_STM32F407) || defined(TARGET_F407VG)
-# define OS_CLOCK 168000000
-
-# elif defined(TARGET_STM32F401RE)
-# define OS_CLOCK 84000000
-
-# elif defined(TARGET_STM32F411RE)
-# define OS_CLOCK 100000000
-
-# elif defined(TARGET_STM32F410RB)
-# define OS_CLOCK 100000000
-
-#elif defined(TARGET_STM32F103RB)
-# define OS_CLOCK 72000000
-
-#elif defined(TARGET_STM32F429ZI)
-# define OS_CLOCK 168000000
-
-#elif defined(TARGET_STM32F302R8)
-# define OS_CLOCK 72000000
-
-#elif defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8) || defined(TARGET_STM32L073RZ)
-# define OS_CLOCK 32000000
-
-#elif defined(TARGET_STM32F401VC)
-# define OS_CLOCK 84000000
-
-# elif defined(TARGET_STM32F746NG) || defined(TARGET_STM32F746ZG)
-# define OS_CLOCK 216000000
-
-#elif defined(TARGET_MAX32610) || defined(TARGET_MAX32600)
-# define OS_CLOCK 24000000
-
-#elif defined(TARGET_NZ32_SC151)
-# define OS_CLOCK 32000000
-
-#elif defined(TARGET_STM32L152RE)
-# define OS_CLOCK 24000000
-
-#elif (defined(TARGET_STM32F446RE) || defined(TARGET_STM32F446VE))
-# define OS_CLOCK 180000000
-
-#elif defined(TARGET_STM32F030R8)
-# define OS_CLOCK 48000000
-
-#elif defined(TARGET_STM32F070RB)
-# define OS_CLOCK 48000000
-
-#elif defined(TARGET_STM32L476VG) || defined(TARGET_STM32L476RG)
-# define OS_CLOCK 80000000
-
-#elif defined(TARGET_STM32F469NI)
-# define OS_CLOCK 168000000
-
-#elif defined(TARGET_STM32L152RC)
-# define OS_CLOCK 24000000
-
-# else
-# error "no target defined"
-# endif
-#endif
-
-// <o>Timer tick value [us] <1-1000000>
-// <i> Defines the timer tick value.
-// <i> Default: 1000 (1ms)
-#ifndef OS_TICK
- #define OS_TICK 1000
-#endif
-
-// </h>
-
-// <h>System Configuration
-// =======================
-//
-// <e>Round-Robin Thread switching
-// ===============================
-//
-// <i> Enables Round-Robin Thread switching.
-#ifndef OS_ROBIN
- #define OS_ROBIN 1
-#endif
-
-// <o>Round-Robin Timeout [ticks] <1-1000>
-// <i> Defines how long a thread will execute before a thread switch.
-// <i> Default: 5
-#ifndef OS_ROBINTOUT
- #define OS_ROBINTOUT 5
-#endif
-
-// </e>
-
-// <e>User Timers
-// ==============
-// <i> Enables user Timers
-#ifndef OS_TIMERS
- #define OS_TIMERS 1
-#endif
-
-// <o>Timer Thread Priority
-// <1=> Low
-// <2=> Below Normal
-// <3=> Normal
-// <4=> Above Normal
-// <5=> High
-// <6=> Realtime (highest)
-// <i> Defines priority for Timer Thread
-// <i> Default: High
-#ifndef OS_TIMERPRIO
- #define OS_TIMERPRIO 5
-#endif
-
-// <o>Timer Callback Queue size <1-32>
-// <i> Number of concurrent active timer callback functions.
-// <i> Default: 4
-#ifndef OS_TIMERCBQSZ
- #define OS_TIMERCBQS 4
-#endif
-
-// </e>
-
-// <o>ISR FIFO Queue size<4=> 4 entries <8=> 8 entries
-// <12=> 12 entries <16=> 16 entries
-// <24=> 24 entries <32=> 32 entries
-// <48=> 48 entries <64=> 64 entries
-// <96=> 96 entries
-// <i> ISR functions store requests to this buffer,
-// <i> when they are called from the interrupt handler.
-// <i> Default: 16 entries
-#ifndef OS_FIFOSZ
- #define OS_FIFOSZ 16
-#endif
-
-// </h>
-
-//------------- <<< end of configuration section >>> -----------------------
-
-// Standard library system mutexes
-// ===============================
-// Define max. number system mutexes that are used to protect
-// the arm standard runtime library. For microlib they are not used.
-#ifndef OS_MUTEXCNT
- #define OS_MUTEXCNT 12
-#endif
-
-/*----------------------------------------------------------------------------
- * RTX User configuration part END
- *---------------------------------------------------------------------------*/
-
-#define OS_TRV ((uint32_t)(((double)OS_CLOCK*(double)OS_TICK)/1E6)-1)
-
-
-/*----------------------------------------------------------------------------
- * OS Idle daemon
- *---------------------------------------------------------------------------*/
-extern void rtos_idle_loop(void);
-
-void os_idle_demon (void) {
- /* The idle demon is a system thread, running when no other thread is */
- /* ready to run. */
- rtos_idle_loop();
-}
-
-/*----------------------------------------------------------------------------
- * RTX Errors
- *---------------------------------------------------------------------------*/
-extern void mbed_die(void);
-
-void os_error (uint32_t err_code) {
- /* This function is called when a runtime error is detected. Parameter */
- /* 'err_code' holds the runtime error code (defined in RTX_Conf.h). */
- mbed_die();
-}
-
-void sysThreadError(osStatus status) {
- if (status != osOK) {
- mbed_die();
- }
-}
-
-/*----------------------------------------------------------------------------
- * RTX Configuration Functions
- *---------------------------------------------------------------------------*/
-
-#include "RTX_CM_lib.h"
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
-
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_GCC/HAL_CM4.S b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_GCC/HAL_CM4.S
deleted file mode 100644
index ce3242b..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_GCC/HAL_CM4.S
+++ /dev/null
@@ -1,405 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: HAL_CM4.S
- * Purpose: Hardware Abstraction Layer for Cortex-M4
- * Rev.: V4.70
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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.
- *---------------------------------------------------------------------------*/
-
- .file "HAL_CM4.S"
- .syntax unified
-
- .equ TCB_STACKF, 32
- .equ TCB_TSTACK, 40
-
-
-/*----------------------------------------------------------------------------
- * Functions
- *---------------------------------------------------------------------------*/
-
- .thumb
-
- .section ".text"
- .align 2
-
-
-/*--------------------------- rt_set_PSP ------------------------------------*/
-
-# void rt_set_PSP (U32 stack);
-
- .thumb_func
- .type rt_set_PSP, %function
- .global rt_set_PSP
-rt_set_PSP:
- .fnstart
- .cantunwind
-
- MSR PSP,R0
- BX LR
-
- .fnend
- .size rt_set_PSP, .-rt_set_PSP
-
-
-/*--------------------------- rt_get_PSP ------------------------------------*/
-
-# U32 rt_get_PSP (void);
-
- .thumb_func
- .type rt_get_PSP, %function
- .global rt_get_PSP
-rt_get_PSP:
- .fnstart
- .cantunwind
-
- MRS R0,PSP
- BX LR
-
- .fnend
- .size rt_get_PSP, .-rt_get_PSP
-
-
-/*--------------------------- os_set_env ------------------------------------*/
-
-# void os_set_env (void);
- /* Switch to Unprivileged/Privileged Thread mode, use PSP. */
-
- .thumb_func
- .type os_set_env, %function
- .global os_set_env
-os_set_env:
- .fnstart
- .cantunwind
-
- MOV R0,SP /* PSP = MSP */
- MSR PSP,R0
- LDR R0,=os_flags
- LDRB R0,[R0]
- LSLS R0,#31
- ITE NE
- MOVNE R0,#0x02 /* Privileged Thread mode, use PSP */
- MOVEQ R0,#0x03 /* Unprivileged Thread mode, use PSP */
- MSR CONTROL,R0
- BX LR
-
- .fnend
- .size os_set_env, .-os_set_env
-
-
-/*--------------------------- _alloc_box ------------------------------------*/
-
-# void *_alloc_box (void *box_mem);
- /* Function wrapper for Unprivileged/Privileged mode. */
-
- .thumb_func
- .type _alloc_box, %function
- .global _alloc_box
-_alloc_box:
- .fnstart
- .cantunwind
-
- LDR R12,=rt_alloc_box
- MRS R3,IPSR
- LSLS R3,#24
- IT NE
- BXNE R12
- MRS R3,CONTROL
- LSLS R3,#31
- IT EQ
- BXEQ R12
- SVC 0
- BX LR
-
- .fnend
- .size _alloc_box, .-_alloc_box
-
-
-/*--------------------------- _free_box -------------------------------------*/
-
-# int _free_box (void *box_mem, void *box);
- /* Function wrapper for Unprivileged/Privileged mode. */
-
- .thumb_func
- .type _free_box, %function
- .global _free_box
-_free_box:
- .fnstart
- .cantunwind
-
- LDR R12,=rt_free_box
- MRS R3,IPSR
- LSLS R3,#24
- IT NE
- BXNE R12
- MRS R3,CONTROL
- LSLS R3,#31
- IT EQ
- BXEQ R12
- SVC 0
- BX LR
-
- .fnend
- .size _free_box, .-_free_box
-
-
-/*-------------------------- SVC_Handler ------------------------------------*/
-
-# void SVC_Handler (void);
-
- .thumb_func
- .type SVC_Handler, %function
- .global SVC_Handler
-SVC_Handler:
- .ifdef IFX_XMC4XXX
- .global SVC_Handler_Veneer
-SVC_Handler_Veneer:
- .endif
- .fnstart
- .cantunwind
-
- MRS R0,PSP /* Read PSP */
- LDR R1,[R0,#24] /* Read Saved PC from Stack */
- LDRB R1,[R1,#-2] /* Load SVC Number */
- CBNZ R1,SVC_User
-
- LDM R0,{R0-R3,R12} /* Read R0-R3,R12 from stack */
- PUSH {R4,LR} /* Save EXC_RETURN */
- BLX R12 /* Call SVC Function */
- POP {R4,LR} /* Restore EXC_RETURN */
-
- MRS R12,PSP /* Read PSP */
- STM R12,{R0-R2} /* Store return values */
-
- LDR R3,=os_tsk
- LDM R3,{R1,R2} /* os_tsk.run, os_tsk.new */
- CMP R1,R2
- .ifdef IFX_XMC4XXX
- ITT EQ
- PUSHEQ {LR}
- POPEQ {PC}
- .else
- IT EQ
- BXEQ LR /* RETI, no task switch */
- .endif
-
- CBZ R1,SVC_Next /* Runtask deleted? */
- TST LR,#0x10 /* is it extended frame? */
- #ifdef __FPU_PRESENT
- ITTE EQ
- VSTMDBEQ R12!,{S16-S31} /* yes, stack also VFP hi-regs */
- #else
- ITE EQ
- #endif
- MOVEQ R0,#0x01 /* os_tsk->stack_frame val */
- MOVNE R0,#0x00
- STRB R0,[R1,#TCB_STACKF] /* os_tsk.run->stack_frame = val */
- STMDB R12!,{R4-R11} /* Save Old context */
- STR R12,[R1,#TCB_TSTACK] /* Update os_tsk.run->tsk_stack */
-
- PUSH {R2,R3}
- BL rt_stk_check /* Check for Stack overflow */
- POP {R2,R3}
-
-SVC_Next:
- STR R2,[R3] /* os_tsk.run = os_tsk.new */
-
- LDR R12,[R2,#TCB_TSTACK] /* os_tsk.new->tsk_stack */
- LDMIA R12!,{R4-R11} /* Restore New Context */
- LDRB R0,[R2,#TCB_STACKF] /* Stack Frame */
- CMP R0,#0 /* Basic/Extended Stack Frame */
- #ifdef __FPU_PRESENT
- ITTE NE
- VLDMIANE R12!,{S16-S31} /* restore VFP hi-registers */
- #else
- ITE NE
- #endif
- MVNNE LR,#~0xFFFFFFED /* set EXC_RETURN value */
- MVNEQ LR,#~0xFFFFFFFD
- MSR PSP,R12 /* Write PSP */
-
-SVC_Exit:
- .ifdef IFX_XMC4XXX
- PUSH {LR}
- POP {PC}
- .else
- BX LR
- .endif
-
- /*------------------- User SVC ------------------------------*/
-
-SVC_User:
- PUSH {R4,LR} /* Save Registers */
- LDR R2,=SVC_Count
- LDR R2,[R2]
- CMP R1,R2
- BHI SVC_Done /* Overflow */
-
- LDR R4,=SVC_Table-4
- LDR R4,[R4,R1,LSL #2] /* Load SVC Function Address */
-
- LDM R0,{R0-R3,R12} /* Read R0-R3,R12 from stack */
- BLX R4 /* Call SVC Function */
-
- MRS R12,PSP
- STM R12,{R0-R3} /* Function return values */
-SVC_Done:
- POP {R4,PC} /* RETI */
-
- .fnend
- .size SVC_Handler, .-SVC_Handler
-
-
-/*-------------------------- PendSV_Handler ---------------------------------*/
-
-# void PendSV_Handler (void);
-
- .thumb_func
- .type PendSV_Handler, %function
- .global PendSV_Handler
- .global Sys_Switch
-PendSV_Handler:
- .ifdef IFX_XMC4XXX
- .global PendSV_Handler_Veneer
-PendSV_Handler_Veneer:
- .endif
- .fnstart
- .cantunwind
-
- PUSH {R4,LR} /* Save EXC_RETURN */
- BL rt_pop_req
-
-Sys_Switch:
- POP {R4,LR} /* Restore EXC_RETURN */
-
- LDR R3,=os_tsk
- LDM R3,{R1,R2} /* os_tsk.run, os_tsk.new */
- CMP R1,R2
- .ifdef IFX_XMC4XXX
- ITT EQ
- PUSHEQ {LR}
- POPEQ {PC}
- .else
- IT EQ
- BXEQ LR /* RETI, no task switch */
- .endif
-
- MRS R12,PSP /* Read PSP */
- TST LR,#0x10 /* is it extended frame? */
- #ifdef __FPU_PRESENT
- ITTE EQ
- VSTMDBEQ R12!,{S16-S31} /* yes, stack also VFP hi-regs */
- #else
- ITE EQ
- #endif
- MOVEQ R0,#0x01 /* os_tsk->stack_frame val */
- MOVNE R0,#0x00
- STRB R0,[R1,#TCB_STACKF] /* os_tsk.run->stack_frame = val */
- STMDB R12!,{R4-R11} /* Save Old context */
- STR R12,[R1,#TCB_TSTACK] /* Update os_tsk.run->tsk_stack */
-
- PUSH {R2,R3}
- BL rt_stk_check /* Check for Stack overflow */
- POP {R2,R3}
-
- STR R2,[R3] /* os_tsk.run = os_tsk.new */
-
- LDR R12,[R2,#TCB_TSTACK] /* os_tsk.new->tsk_stack */
- LDMIA R12!,{R4-R11} /* Restore New Context */
- LDRB R0,[R2,#TCB_STACKF] /* Stack Frame */
- CMP R0,#0 /* Basic/Extended Stack Frame */
- #ifdef __FPU_PRESENT
- ITTE NE
- VLDMIANE R12!,{S16-S31} /* restore VFP hi-registers */
- #else
- ITE NE
- #endif
- MVNNE LR,#~0xFFFFFFED /* set EXC_RETURN value */
- MVNEQ LR,#~0xFFFFFFFD
- MSR PSP,R12 /* Write PSP */
-
-Sys_Exit:
- .ifdef IFX_XMC4XXX
- PUSH {LR}
- POP {PC}
- .else
- BX LR /* Return to Thread Mode */
- .endif
-
- .fnend
- .size PendSV_Handler, .-PendSV_Handler
-
-
-/*-------------------------- SysTick_Handler --------------------------------*/
-
-# void SysTick_Handler (void);
-
- .thumb_func
- .type SysTick_Handler, %function
- .global SysTick_Handler
-SysTick_Handler:
- .ifdef IFX_XMC4XXX
- .global SysTick_Handler_Veneer
-SysTick_Handler_Veneer:
- .endif
- .fnstart
- .cantunwind
-
- PUSH {R4,LR} /* Save EXC_RETURN */
- BL rt_systick
- B Sys_Switch
-
- .fnend
- .size SysTick_Handler, .-SysTick_Handler
-
-
-/*-------------------------- OS_Tick_Handler --------------------------------*/
-
-# void OS_Tick_Handler (void);
-
- .thumb_func
- .type OS_Tick_Handler, %function
- .global OS_Tick_Handler
-OS_Tick_Handler:
- .fnstart
- .cantunwind
-
- PUSH {R4,LR} /* Save EXC_RETURN */
- BL os_tick_irqack
- BL rt_systick
- B Sys_Switch
-
- .fnend
- .size OS_Tick_Handler, .-OS_Tick_Handler
-
-
- .end
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_GCC/SVC_Table.S b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_GCC/SVC_Table.S
deleted file mode 100644
index 2b99321..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_GCC/SVC_Table.S
+++ /dev/null
@@ -1,56 +0,0 @@
-;/*----------------------------------------------------------------------------
-; * RL-ARM - RTX
-; *----------------------------------------------------------------------------
-; * Name: SVC_TABLE.S
-; * Purpose: Pre-defined SVC Table for Cortex-M
-; * Rev.: V4.70
-; *----------------------------------------------------------------------------
-; *
-; * Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
-; * All rights reserved.
-; * Redistribution and use in source and binary forms, with or without
-; * modification, are permitted provided that the following conditions are met:
-; * - Redistributions of source code must retain the above copyright
-; * notice, this list of conditions and the following disclaimer.
-; * - 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.
-; * - Neither the name of ARM nor the names of its contributors may be used
-; * to endorse or promote products derived from this software without
-; * specific prior written permission.
-; *
-; * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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.
-; *---------------------------------------------------------------------------*/
-
-
- .file "SVC_Table.S"
-
-
- .section ".svc_table"
-
- .global SVC_Table
-SVC_Table:
-/* Insert user SVC functions here. SVC 0 used by RTL Kernel. */
-# .long __SVC_1 /* user SVC function */
-SVC_End:
-
- .global SVC_Count
-SVC_Count:
- .long (SVC_End-SVC_Table)/4
-
-
- .end
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/cmsis_os.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/cmsis_os.h
deleted file mode 100644
index d1e7198..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/cmsis_os.h
+++ /dev/null
@@ -1,774 +0,0 @@
-/* ----------------------------------------------------------------------
- * Copyright (C) 2012 ARM Limited. All rights reserved.
- *
- * $Date: 5. June 2012
- * $Revision: V1.01
- *
- * Project: CMSIS-RTOS API
- * Title: cmsis_os.h RTX header file
- *
- * Version 0.02
- * Initial Proposal Phase
- * Version 0.03
- * osKernelStart added, optional feature: main started as thread
- * osSemaphores have standard behavior
- * osTimerCreate does not start the timer, added osTimerStart
- * osThreadPass is renamed to osThreadYield
- * Version 1.01
- * Support for C++ interface
- * - const attribute removed from the osXxxxDef_t typedef's
- * - const attribute added to the osXxxxDef macros
- * Added: osTimerDelete, osMutexDelete, osSemaphoreDelete
- * Added: osKernelInitialize
- * -------------------------------------------------------------------- */
-
-/**
-\page cmsis_os_h Header File Template: cmsis_os.h
-
-The file \b cmsis_os.h is a template header file for a CMSIS-RTOS compliant Real-Time Operating System (RTOS).
-Each RTOS that is compliant with CMSIS-RTOS shall provide a specific \b cmsis_os.h header file that represents
-its implementation.
-
-The file cmsis_os.h contains:
- - CMSIS-RTOS API function definitions
- - struct definitions for parameters and return types
- - status and priority values used by CMSIS-RTOS API functions
- - macros for defining threads and other kernel objects
-
-
-<b>Name conventions and header file modifications</b>
-
-All definitions are prefixed with \b os to give an unique name space for CMSIS-RTOS functions.
-Definitions that are prefixed \b os_ are not used in the application code but local to this header file.
-All definitions and functions that belong to a module are grouped and have a common prefix, i.e. \b osThread.
-
-Definitions that are marked with <b>CAN BE CHANGED</b> can be adapted towards the needs of the actual CMSIS-RTOS implementation.
-These definitions can be specific to the underlying RTOS kernel.
-
-Definitions that are marked with <b>MUST REMAIN UNCHANGED</b> cannot be altered. Otherwise the CMSIS-RTOS implementation is no longer
-compliant to the standard. Note that some functions are optional and need not to be provided by every CMSIS-RTOS implementation.
-
-
-<b>Function calls from interrupt service routines</b>
-
-The following CMSIS-RTOS functions can be called from threads and interrupt service routines (ISR):
- - \ref osSignalSet
- - \ref osSemaphoreRelease
- - \ref osPoolAlloc, \ref osPoolCAlloc, \ref osPoolFree
- - \ref osMessagePut, \ref osMessageGet
- - \ref osMailAlloc, \ref osMailCAlloc, \ref osMailGet, \ref osMailPut, \ref osMailFree
-
-Functions that cannot be called from an ISR are verifying the interrupt status and return in case that they are called
-from an ISR context the status code \b osErrorISR. In some implementations this condition might be caught using the HARD FAULT vector.
-
-Some CMSIS-RTOS implementations support CMSIS-RTOS function calls from multiple ISR at the same time.
-If this is impossible, the CMSIS-RTOS rejects calls by nested ISR functions with the status code \b osErrorISRRecursive.
-
-
-<b>Define and reference object definitions</b>
-
-With <b>\#define osObjectsExternal</b> objects are defined as external symbols. This allows to create a consistent header file
-that is used throughout a project as shown below:
-
-<i>Header File</i>
-\code
-#include <cmsis_os.h> // CMSIS RTOS header file
-
-// Thread definition
-extern void thread_sample (void const *argument); // function prototype
-osThreadDef (thread_sample, osPriorityBelowNormal, 1, 100);
-
-// Pool definition
-osPoolDef(MyPool, 10, long);
-\endcode
-
-
-This header file defines all objects when included in a C/C++ source file. When <b>\#define osObjectsExternal</b> is
-present before the header file, the objects are defined as external symbols. A single consistent header file can therefore be
-used throughout the whole project.
-
-<i>Example</i>
-\code
-#include "osObjects.h" // Definition of the CMSIS-RTOS objects
-\endcode
-
-\code
-#define osObjectExternal // Objects will be defined as external symbols
-#include "osObjects.h" // Reference to the CMSIS-RTOS objects
-\endcode
-
-*/
-
-#ifndef _CMSIS_OS_H
-#define _CMSIS_OS_H
-
-/// \note MUST REMAIN UNCHANGED: \b osCMSIS identifies the CMSIS-RTOS API version.
-#define osCMSIS 0x10001 ///< API version (main [31:16] .sub [15:0])
-
-/// \note CAN BE CHANGED: \b osCMSIS_KERNEL identifies the underlying RTOS kernel and version number.
-#define osCMSIS_RTX ((4<<16)|61) ///< RTOS identification and version (main [31:16] .sub [15:0])
-
-/// \note MUST REMAIN UNCHANGED: \b osKernelSystemId shall be consistent in every CMSIS-RTOS.
-#define osKernelSystemId "RTX V4.61" ///< RTOS identification string
-
-
-#define CMSIS_OS_RTX
-
-// The stack space occupied is mainly dependent on the underling C standard library
-#if defined(TOOLCHAIN_GCC) || defined(TOOLCHAIN_ARM_STD) || defined(TOOLCHAIN_IAR)
-# define WORDS_STACK_SIZE 512
-#elif defined(TOOLCHAIN_ARM_MICRO)
-# define WORDS_STACK_SIZE 128
-#endif
-
-#define DEFAULT_STACK_SIZE (WORDS_STACK_SIZE*4)
-
-
-/// \note MUST REMAIN UNCHANGED: \b osFeature_xxx shall be consistent in every CMSIS-RTOS.
-#define osFeature_MainThread 1 ///< main thread 1=main can be thread, 0=not available
-#define osFeature_Pool 1 ///< Memory Pools: 1=available, 0=not available
-#define osFeature_MailQ 1 ///< Mail Queues: 1=available, 0=not available
-#define osFeature_MessageQ 1 ///< Message Queues: 1=available, 0=not available
-#define osFeature_Signals 16 ///< maximum number of Signal Flags available per thread
-#define osFeature_Semaphore 65535 ///< maximum count for \ref osSemaphoreCreate function
-#define osFeature_Wait 0 ///< osWait function: 1=available, 0=not available
-
-#if defined (__CC_ARM)
-#define os_InRegs __value_in_regs // Compiler specific: force struct in registers
-#elif defined (__ICCARM__)
-#define os_InRegs __value_in_regs // Compiler specific: force struct in registers
-#else
-#define os_InRegs
-#endif
-
-#include <stdint.h>
-#include <stddef.h>
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-#include "os_tcb.h"
-
-// ==== Enumeration, structures, defines ====
-
-/// Priority used for thread control.
-/// \note MUST REMAIN UNCHANGED: \b osPriority shall be consistent in every CMSIS-RTOS.
-typedef enum {
- osPriorityIdle = -3, ///< priority: idle (lowest)
- osPriorityLow = -2, ///< priority: low
- osPriorityBelowNormal = -1, ///< priority: below normal
- osPriorityNormal = 0, ///< priority: normal (default)
- osPriorityAboveNormal = +1, ///< priority: above normal
- osPriorityHigh = +2, ///< priority: high
- osPriorityRealtime = +3, ///< priority: realtime (highest)
- osPriorityError = 0x84 ///< system cannot determine priority or thread has illegal priority
-} osPriority;
-
-/// Timeout value.
-/// \note MUST REMAIN UNCHANGED: \b osWaitForever shall be consistent in every CMSIS-RTOS.
-#define osWaitForever 0xFFFFFFFF ///< wait forever timeout value
-
-/// Status code values returned by CMSIS-RTOS functions.
-/// \note MUST REMAIN UNCHANGED: \b osStatus shall be consistent in every CMSIS-RTOS.
-typedef enum {
- osOK = 0, ///< function completed; no error or event occurred.
- osEventSignal = 0x08, ///< function completed; signal event occurred.
- osEventMessage = 0x10, ///< function completed; message event occurred.
- osEventMail = 0x20, ///< function completed; mail event occurred.
- osEventTimeout = 0x40, ///< function completed; timeout occurred.
- osErrorParameter = 0x80, ///< parameter error: a mandatory parameter was missing or specified an incorrect object.
- osErrorResource = 0x81, ///< resource not available: a specified resource was not available.
- osErrorTimeoutResource = 0xC1, ///< resource not available within given time: a specified resource was not available within the timeout period.
- osErrorISR = 0x82, ///< not allowed in ISR context: the function cannot be called from interrupt service routines.
- osErrorISRRecursive = 0x83, ///< function called multiple times from ISR with same object.
- osErrorPriority = 0x84, ///< system cannot determine priority or thread has illegal priority.
- osErrorNoMemory = 0x85, ///< system is out of memory: it was impossible to allocate or reserve memory for the operation.
- osErrorValue = 0x86, ///< value of a parameter is out of range.
- osErrorOS = 0xFF, ///< unspecified RTOS error: run-time error but no other error message fits.
- os_status_reserved = 0x7FFFFFFF ///< prevent from enum down-size compiler optimization.
-} osStatus;
-
-
-/// Timer type value for the timer definition.
-/// \note MUST REMAIN UNCHANGED: \b os_timer_type shall be consistent in every CMSIS-RTOS.
-typedef enum {
- osTimerOnce = 0, ///< one-shot timer
- osTimerPeriodic = 1 ///< repeating timer
-} os_timer_type;
-
-/// Entry point of a thread.
-/// \note MUST REMAIN UNCHANGED: \b os_pthread shall be consistent in every CMSIS-RTOS.
-typedef void (*os_pthread) (void const *argument);
-
-/// Entry point of a timer call back function.
-/// \note MUST REMAIN UNCHANGED: \b os_ptimer shall be consistent in every CMSIS-RTOS.
-typedef void (*os_ptimer) (void const *argument);
-
-// >>> the following data type definitions may shall adapted towards a specific RTOS
-
-/// Thread ID identifies the thread (pointer to a thread control block).
-/// \note CAN BE CHANGED: \b os_thread_cb is implementation specific in every CMSIS-RTOS.
-typedef struct os_thread_cb *osThreadId;
-
-/// Timer ID identifies the timer (pointer to a timer control block).
-/// \note CAN BE CHANGED: \b os_timer_cb is implementation specific in every CMSIS-RTOS.
-typedef struct os_timer_cb *osTimerId;
-
-/// Mutex ID identifies the mutex (pointer to a mutex control block).
-/// \note CAN BE CHANGED: \b os_mutex_cb is implementation specific in every CMSIS-RTOS.
-typedef struct os_mutex_cb *osMutexId;
-
-/// Semaphore ID identifies the semaphore (pointer to a semaphore control block).
-/// \note CAN BE CHANGED: \b os_semaphore_cb is implementation specific in every CMSIS-RTOS.
-typedef struct os_semaphore_cb *osSemaphoreId;
-
-/// Pool ID identifies the memory pool (pointer to a memory pool control block).
-/// \note CAN BE CHANGED: \b os_pool_cb is implementation specific in every CMSIS-RTOS.
-typedef struct os_pool_cb *osPoolId;
-
-/// Message ID identifies the message queue (pointer to a message queue control block).
-/// \note CAN BE CHANGED: \b os_messageQ_cb is implementation specific in every CMSIS-RTOS.
-typedef struct os_messageQ_cb *osMessageQId;
-
-/// Mail ID identifies the mail queue (pointer to a mail queue control block).
-/// \note CAN BE CHANGED: \b os_mailQ_cb is implementation specific in every CMSIS-RTOS.
-typedef struct os_mailQ_cb *osMailQId;
-
-
-/// Thread Definition structure contains startup information of a thread.
-/// \note CAN BE CHANGED: \b os_thread_def is implementation specific in every CMSIS-RTOS.
-typedef struct os_thread_def {
- os_pthread pthread; ///< start address of thread function
- osPriority tpriority; ///< initial thread priority
- uint32_t stacksize; ///< stack size requirements in bytes
- uint32_t *stack_pointer; ///< pointer to the stack memory block
- struct OS_TCB tcb;
-} osThreadDef_t;
-
-/// Timer Definition structure contains timer parameters.
-/// \note CAN BE CHANGED: \b os_timer_def is implementation specific in every CMSIS-RTOS.
-typedef struct os_timer_def {
- os_ptimer ptimer; ///< start address of a timer function
- void *timer; ///< pointer to internal data
-} osTimerDef_t;
-
-/// Mutex Definition structure contains setup information for a mutex.
-/// \note CAN BE CHANGED: \b os_mutex_def is implementation specific in every CMSIS-RTOS.
-typedef struct os_mutex_def {
- void *mutex; ///< pointer to internal data
-} osMutexDef_t;
-
-/// Semaphore Definition structure contains setup information for a semaphore.
-/// \note CAN BE CHANGED: \b os_semaphore_def is implementation specific in every CMSIS-RTOS.
-typedef struct os_semaphore_def {
- void *semaphore; ///< pointer to internal data
-} osSemaphoreDef_t;
-
-/// Definition structure for memory block allocation.
-/// \note CAN BE CHANGED: \b os_pool_def is implementation specific in every CMSIS-RTOS.
-typedef struct os_pool_def {
- uint32_t pool_sz; ///< number of items (elements) in the pool
- uint32_t item_sz; ///< size of an item
- void *pool; ///< pointer to memory for pool
-} osPoolDef_t;
-
-/// Definition structure for message queue.
-/// \note CAN BE CHANGED: \b os_messageQ_def is implementation specific in every CMSIS-RTOS.
-typedef struct os_messageQ_def {
- uint32_t queue_sz; ///< number of elements in the queue
- void *pool; ///< memory array for messages
-} osMessageQDef_t;
-
-/// Definition structure for mail queue.
-/// \note CAN BE CHANGED: \b os_mailQ_def is implementation specific in every CMSIS-RTOS.
-typedef struct os_mailQ_def {
- uint32_t queue_sz; ///< number of elements in the queue
- uint32_t item_sz; ///< size of an item
- void *pool; ///< memory array for mail
-} osMailQDef_t;
-
-/// Event structure contains detailed information about an event.
-/// \note MUST REMAIN UNCHANGED: \b os_event shall be consistent in every CMSIS-RTOS.
-/// However the struct may be extended at the end.
-typedef struct {
- osStatus status; ///< status code: event or error information
- union {
- uint32_t v; ///< message as 32-bit value
- void *p; ///< message or mail as void pointer
- int32_t signals; ///< signal flags
- } value; ///< event value
- union {
- osMailQId mail_id; ///< mail id obtained by \ref osMailCreate
- osMessageQId message_id; ///< message id obtained by \ref osMessageCreate
- } def; ///< event definition
-} osEvent;
-
-
-// ==== Kernel Control Functions ====
-
-/// Initialize the RTOS Kernel for creating objects.
-/// \return status code that indicates the execution status of the function.
-/// \note MUST REMAIN UNCHANGED: \b osKernelInitialize shall be consistent in every CMSIS-RTOS.
-osStatus osKernelInitialize (void);
-
-/// Start the RTOS Kernel.
-/// \return status code that indicates the execution status of the function.
-/// \note MUST REMAIN UNCHANGED: \b osKernelStart shall be consistent in every CMSIS-RTOS.
-osStatus osKernelStart (void);
-
-/// Check if the RTOS kernel is already started.
-/// \note MUST REMAIN UNCHANGED: \b osKernelRunning shall be consistent in every CMSIS-RTOS.
-/// \return 0 RTOS is not started, 1 RTOS is started.
-int32_t osKernelRunning(void);
-
-
-// ==== Thread Management ====
-
-/// Create a Thread Definition with function, priority, and stack requirements.
-/// \param name name of the thread function.
-/// \param priority initial priority of the thread function.
-/// \param stacksz stack size (in bytes) requirements for the thread function.
-/// \note CAN BE CHANGED: The parameters to \b osThreadDef shall be consistent but the
-/// macro body is implementation specific in every CMSIS-RTOS.
-#if defined (osObjectsExternal) // object is external
-#define osThreadDef(name, priority, stacksz) \
-extern osThreadDef_t os_thread_def_##name
-#else // define the object
-#define osThreadDef(name, priority, stacksz) \
-uint32_t os_thread_def_stack_##name [stacksz / sizeof(uint32_t)]; \
-osThreadDef_t os_thread_def_##name = \
-{ (name), (priority), (stacksz), (os_thread_def_stack_##name)}
-#endif
-
-/// Access a Thread definition.
-/// \param name name of the thread definition object.
-/// \note CAN BE CHANGED: The parameter to \b osThread shall be consistent but the
-/// macro body is implementation specific in every CMSIS-RTOS.
-#define osThread(name) \
-&os_thread_def_##name
-
-/// Create a thread and add it to Active Threads and set it to state READY.
-/// \param[in] thread_def thread definition referenced with \ref osThread.
-/// \param[in] argument pointer that is passed to the thread function as start argument.
-/// \return thread ID for reference by other functions or NULL in case of error.
-/// \note MUST REMAIN UNCHANGED: \b osThreadCreate shall be consistent in every CMSIS-RTOS.
-osThreadId osThreadCreate (osThreadDef_t *thread_def, void *argument);
-
-/// Return the thread ID of the current running thread.
-/// \return thread ID for reference by other functions or NULL in case of error.
-/// \note MUST REMAIN UNCHANGED: \b osThreadGetId shall be consistent in every CMSIS-RTOS.
-osThreadId osThreadGetId (void);
-
-/// Terminate execution of a thread and remove it from Active Threads.
-/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
-/// \return status code that indicates the execution status of the function.
-/// \note MUST REMAIN UNCHANGED: \b osThreadTerminate shall be consistent in every CMSIS-RTOS.
-osStatus osThreadTerminate (osThreadId thread_id);
-
-/// Pass control to next thread that is in state \b READY.
-/// \return status code that indicates the execution status of the function.
-/// \note MUST REMAIN UNCHANGED: \b osThreadYield shall be consistent in every CMSIS-RTOS.
-osStatus osThreadYield (void);
-
-/// Change priority of an active thread.
-/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
-/// \param[in] priority new priority value for the thread function.
-/// \return status code that indicates the execution status of the function.
-/// \note MUST REMAIN UNCHANGED: \b osThreadSetPriority shall be consistent in every CMSIS-RTOS.
-osStatus osThreadSetPriority (osThreadId thread_id, osPriority priority);
-
-/// Get current priority of an active thread.
-/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
-/// \return current priority value of the thread function.
-/// \note MUST REMAIN UNCHANGED: \b osThreadGetPriority shall be consistent in every CMSIS-RTOS.
-osPriority osThreadGetPriority (osThreadId thread_id);
-
-
-// ==== Generic Wait Functions ====
-
-/// Wait for Timeout (Time Delay).
-/// \param[in] millisec time delay value
-/// \return status code that indicates the execution status of the function.
-osStatus osDelay (uint32_t millisec);
-
-#if (defined (osFeature_Wait) && (osFeature_Wait != 0)) // Generic Wait available
-
-/// Wait for Signal, Message, Mail, or Timeout.
-/// \param[in] millisec timeout value or 0 in case of no time-out
-/// \return event that contains signal, message, or mail information or error code.
-/// \note MUST REMAIN UNCHANGED: \b osWait shall be consistent in every CMSIS-RTOS.
-os_InRegs osEvent osWait (uint32_t millisec);
-
-#endif // Generic Wait available
-
-
-// ==== Timer Management Functions ====
-/// Define a Timer object.
-/// \param name name of the timer object.
-/// \param function name of the timer call back function.
-/// \note CAN BE CHANGED: The parameter to \b osTimerDef shall be consistent but the
-/// macro body is implementation specific in every CMSIS-RTOS.
-#if defined (osObjectsExternal) // object is external
-#define osTimerDef(name, function) \
-extern osTimerDef_t os_timer_def_##name
-#else // define the object
-#define osTimerDef(name, function) \
-uint32_t os_timer_cb_##name[5]; \
-osTimerDef_t os_timer_def_##name = \
-{ (function), (os_timer_cb_##name) }
-#endif
-
-/// Access a Timer definition.
-/// \param name name of the timer object.
-/// \note CAN BE CHANGED: The parameter to \b osTimer shall be consistent but the
-/// macro body is implementation specific in every CMSIS-RTOS.
-#define osTimer(name) \
-&os_timer_def_##name
-
-/// Create a timer.
-/// \param[in] timer_def timer object referenced with \ref osTimer.
-/// \param[in] type osTimerOnce for one-shot or osTimerPeriodic for periodic behavior.
-/// \param[in] argument argument to the timer call back function.
-/// \return timer ID for reference by other functions or NULL in case of error.
-/// \note MUST REMAIN UNCHANGED: \b osTimerCreate shall be consistent in every CMSIS-RTOS.
-osTimerId osTimerCreate (osTimerDef_t *timer_def, os_timer_type type, void *argument);
-
-/// Start or restart a timer.
-/// \param[in] timer_id timer ID obtained by \ref osTimerCreate.
-/// \param[in] millisec time delay value of the timer.
-/// \return status code that indicates the execution status of the function.
-/// \note MUST REMAIN UNCHANGED: \b osTimerStart shall be consistent in every CMSIS-RTOS.
-osStatus osTimerStart (osTimerId timer_id, uint32_t millisec);
-
-/// Stop the timer.
-/// \param[in] timer_id timer ID obtained by \ref osTimerCreate.
-/// \return status code that indicates the execution status of the function.
-/// \note MUST REMAIN UNCHANGED: \b osTimerStop shall be consistent in every CMSIS-RTOS.
-osStatus osTimerStop (osTimerId timer_id);
-
-/// Delete a timer that was created by \ref osTimerCreate.
-/// \param[in] timer_id timer ID obtained by \ref osTimerCreate.
-/// \return status code that indicates the execution status of the function.
-/// \note MUST REMAIN UNCHANGED: \b osTimerDelete shall be consistent in every CMSIS-RTOS.
-osStatus osTimerDelete (osTimerId timer_id);
-
-
-// ==== Signal Management ====
-
-/// Set the specified Signal Flags of an active thread.
-/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
-/// \param[in] signals specifies the signal flags of the thread that should be set.
-/// \return previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters.
-/// \note MUST REMAIN UNCHANGED: \b osSignalSet shall be consistent in every CMSIS-RTOS.
-int32_t osSignalSet (osThreadId thread_id, int32_t signals);
-
-/// Clear the specified Signal Flags of an active thread.
-/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
-/// \param[in] signals specifies the signal flags of the thread that shall be cleared.
-/// \return previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters.
-/// \note MUST REMAIN UNCHANGED: \b osSignalClear shall be consistent in every CMSIS-RTOS.
-int32_t osSignalClear (osThreadId thread_id, int32_t signals);
-
-/// Get Signal Flags status of an active thread.
-/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
-/// \return previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters.
-/// \note MUST REMAIN UNCHANGED: \b osSignalGet shall be consistent in every CMSIS-RTOS.
-int32_t osSignalGet (osThreadId thread_id);
-
-/// Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread.
-/// \param[in] signals wait until all specified signal flags set or 0 for any single signal flag.
-/// \param[in] millisec timeout value or 0 in case of no time-out.
-/// \return event flag information or error code.
-/// \note MUST REMAIN UNCHANGED: \b osSignalWait shall be consistent in every CMSIS-RTOS.
-os_InRegs osEvent osSignalWait (int32_t signals, uint32_t millisec);
-
-
-// ==== Mutex Management ====
-
-/// Define a Mutex.
-/// \param name name of the mutex object.
-/// \note CAN BE CHANGED: The parameter to \b osMutexDef shall be consistent but the
-/// macro body is implementation specific in every CMSIS-RTOS.
-#if defined (osObjectsExternal) // object is external
-#define osMutexDef(name) \
-extern osMutexDef_t os_mutex_def_##name
-#else // define the object
-#define osMutexDef(name) \
-uint32_t os_mutex_cb_##name[3]; \
-osMutexDef_t os_mutex_def_##name = { (os_mutex_cb_##name) }
-#endif
-
-/// Access a Mutex definition.
-/// \param name name of the mutex object.
-/// \note CAN BE CHANGED: The parameter to \b osMutex shall be consistent but the
-/// macro body is implementation specific in every CMSIS-RTOS.
-#define osMutex(name) \
-&os_mutex_def_##name
-
-/// Create and Initialize a Mutex object.
-/// \param[in] mutex_def mutex definition referenced with \ref osMutex.
-/// \return mutex ID for reference by other functions or NULL in case of error.
-/// \note MUST REMAIN UNCHANGED: \b osMutexCreate shall be consistent in every CMSIS-RTOS.
-osMutexId osMutexCreate (osMutexDef_t *mutex_def);
-
-/// Wait until a Mutex becomes available.
-/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate.
-/// \param[in] millisec timeout value or 0 in case of no time-out.
-/// \return status code that indicates the execution status of the function.
-/// \note MUST REMAIN UNCHANGED: \b osMutexWait shall be consistent in every CMSIS-RTOS.
-osStatus osMutexWait (osMutexId mutex_id, uint32_t millisec);
-
-/// Release a Mutex that was obtained by \ref osMutexWait.
-/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate.
-/// \return status code that indicates the execution status of the function.
-/// \note MUST REMAIN UNCHANGED: \b osMutexRelease shall be consistent in every CMSIS-RTOS.
-osStatus osMutexRelease (osMutexId mutex_id);
-
-/// Delete a Mutex that was created by \ref osMutexCreate.
-/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate.
-/// \return status code that indicates the execution status of the function.
-/// \note MUST REMAIN UNCHANGED: \b osMutexDelete shall be consistent in every CMSIS-RTOS.
-osStatus osMutexDelete (osMutexId mutex_id);
-
-
-// ==== Semaphore Management Functions ====
-
-#if (defined (osFeature_Semaphore) && (osFeature_Semaphore != 0)) // Semaphore available
-
-/// Define a Semaphore object.
-/// \param name name of the semaphore object.
-/// \note CAN BE CHANGED: The parameter to \b osSemaphoreDef shall be consistent but the
-/// macro body is implementation specific in every CMSIS-RTOS.
-#if defined (osObjectsExternal) // object is external
-#define osSemaphoreDef(name) \
-extern osSemaphoreDef_t os_semaphore_def_##name
-#else // define the object
-#define osSemaphoreDef(name) \
-uint32_t os_semaphore_cb_##name[2]; \
-osSemaphoreDef_t os_semaphore_def_##name = { (os_semaphore_cb_##name) }
-#endif
-
-/// Access a Semaphore definition.
-/// \param name name of the semaphore object.
-/// \note CAN BE CHANGED: The parameter to \b osSemaphore shall be consistent but the
-/// macro body is implementation specific in every CMSIS-RTOS.
-#define osSemaphore(name) \
-&os_semaphore_def_##name
-
-/// Create and Initialize a Semaphore object used for managing resources.
-/// \param[in] semaphore_def semaphore definition referenced with \ref osSemaphore.
-/// \param[in] count number of available resources.
-/// \return semaphore ID for reference by other functions or NULL in case of error.
-/// \note MUST REMAIN UNCHANGED: \b osSemaphoreCreate shall be consistent in every CMSIS-RTOS.
-osSemaphoreId osSemaphoreCreate (osSemaphoreDef_t *semaphore_def, int32_t count);
-
-/// Wait until a Semaphore token becomes available.
-/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate.
-/// \param[in] millisec timeout value or 0 in case of no time-out.
-/// \return number of available tokens, or -1 in case of incorrect parameters.
-/// \note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS.
-int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec);
-
-/// Release a Semaphore token.
-/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate.
-/// \return status code that indicates the execution status of the function.
-/// \note MUST REMAIN UNCHANGED: \b osSemaphoreRelease shall be consistent in every CMSIS-RTOS.
-osStatus osSemaphoreRelease (osSemaphoreId semaphore_id);
-
-/// Delete a Semaphore that was created by \ref osSemaphoreCreate.
-/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate.
-/// \return status code that indicates the execution status of the function.
-/// \note MUST REMAIN UNCHANGED: \b osSemaphoreDelete shall be consistent in every CMSIS-RTOS.
-osStatus osSemaphoreDelete (osSemaphoreId semaphore_id);
-
-#endif // Semaphore available
-
-
-// ==== Memory Pool Management Functions ====
-
-#if (defined (osFeature_Pool) && (osFeature_Pool != 0)) // Memory Pool Management available
-
-/// \brief Define a Memory Pool.
-/// \param name name of the memory pool.
-/// \param no maximum number of blocks (objects) in the memory pool.
-/// \param type data type of a single block (object).
-/// \note CAN BE CHANGED: The parameter to \b osPoolDef shall be consistent but the
-/// macro body is implementation specific in every CMSIS-RTOS.
-#if defined (osObjectsExternal) // object is external
-#define osPoolDef(name, no, type) \
-extern osPoolDef_t os_pool_def_##name
-#else // define the object
-#define osPoolDef(name, no, type) \
-uint32_t os_pool_m_##name[3+((sizeof(type)+3)/4)*(no)]; \
-osPoolDef_t os_pool_def_##name = \
-{ (no), sizeof(type), (os_pool_m_##name) }
-#endif
-
-/// \brief Access a Memory Pool definition.
-/// \param name name of the memory pool
-/// \note CAN BE CHANGED: The parameter to \b osPool shall be consistent but the
-/// macro body is implementation specific in every CMSIS-RTOS.
-#define osPool(name) \
-&os_pool_def_##name
-
-/// Create and Initialize a memory pool.
-/// \param[in] pool_def memory pool definition referenced with \ref osPool.
-/// \return memory pool ID for reference by other functions or NULL in case of error.
-/// \note MUST REMAIN UNCHANGED: \b osPoolCreate shall be consistent in every CMSIS-RTOS.
-osPoolId osPoolCreate (osPoolDef_t *pool_def);
-
-/// Allocate a memory block from a memory pool.
-/// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate.
-/// \return address of the allocated memory block or NULL in case of no memory available.
-/// \note MUST REMAIN UNCHANGED: \b osPoolAlloc shall be consistent in every CMSIS-RTOS.
-void *osPoolAlloc (osPoolId pool_id);
-
-/// Allocate a memory block from a memory pool and set memory block to zero.
-/// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate.
-/// \return address of the allocated memory block or NULL in case of no memory available.
-/// \note MUST REMAIN UNCHANGED: \b osPoolCAlloc shall be consistent in every CMSIS-RTOS.
-void *osPoolCAlloc (osPoolId pool_id);
-
-/// Return an allocated memory block back to a specific memory pool.
-/// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate.
-/// \param[in] block address of the allocated memory block that is returned to the memory pool.
-/// \return status code that indicates the execution status of the function.
-/// \note MUST REMAIN UNCHANGED: \b osPoolFree shall be consistent in every CMSIS-RTOS.
-osStatus osPoolFree (osPoolId pool_id, void *block);
-
-#endif // Memory Pool Management available
-
-
-// ==== Message Queue Management Functions ====
-
-#if (defined (osFeature_MessageQ) && (osFeature_MessageQ != 0)) // Message Queues available
-
-/// \brief Create a Message Queue Definition.
-/// \param name name of the queue.
-/// \param queue_sz maximum number of messages in the queue.
-/// \param type data type of a single message element (for debugger).
-/// \note CAN BE CHANGED: The parameter to \b osMessageQDef shall be consistent but the
-/// macro body is implementation specific in every CMSIS-RTOS.
-#if defined (osObjectsExternal) // object is external
-#define osMessageQDef(name, queue_sz, type) \
-extern osMessageQDef_t os_messageQ_def_##name
-#else // define the object
-#define osMessageQDef(name, queue_sz, type) \
-uint32_t os_messageQ_q_##name[4+(queue_sz)]; \
-osMessageQDef_t os_messageQ_def_##name = \
-{ (queue_sz), (os_messageQ_q_##name) }
-#endif
-
-/// \brief Access a Message Queue Definition.
-/// \param name name of the queue
-/// \note CAN BE CHANGED: The parameter to \b osMessageQ shall be consistent but the
-/// macro body is implementation specific in every CMSIS-RTOS.
-#define osMessageQ(name) \
-&os_messageQ_def_##name
-
-/// Create and Initialize a Message Queue.
-/// \param[in] queue_def queue definition referenced with \ref osMessageQ.
-/// \param[in] thread_id thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL.
-/// \return message queue ID for reference by other functions or NULL in case of error.
-/// \note MUST REMAIN UNCHANGED: \b osMessageCreate shall be consistent in every CMSIS-RTOS.
-osMessageQId osMessageCreate (osMessageQDef_t *queue_def, osThreadId thread_id);
-
-/// Put a Message to a Queue.
-/// \param[in] queue_id message queue ID obtained with \ref osMessageCreate.
-/// \param[in] info message information.
-/// \param[in] millisec timeout value or 0 in case of no time-out.
-/// \return status code that indicates the execution status of the function.
-/// \note MUST REMAIN UNCHANGED: \b osMessagePut shall be consistent in every CMSIS-RTOS.
-osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec);
-
-/// Get a Message or Wait for a Message from a Queue.
-/// \param[in] queue_id message queue ID obtained with \ref osMessageCreate.
-/// \param[in] millisec timeout value or 0 in case of no time-out.
-/// \return event information that includes status code.
-/// \note MUST REMAIN UNCHANGED: \b osMessageGet shall be consistent in every CMSIS-RTOS.
-os_InRegs osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec);
-
-#endif // Message Queues available
-
-
-// ==== Mail Queue Management Functions ====
-
-#if (defined (osFeature_MailQ) && (osFeature_MailQ != 0)) // Mail Queues available
-
-/// \brief Create a Mail Queue Definition.
-/// \param name name of the queue
-/// \param queue_sz maximum number of messages in queue
-/// \param type data type of a single message element
-/// \note CAN BE CHANGED: The parameter to \b osMailQDef shall be consistent but the
-/// macro body is implementation specific in every CMSIS-RTOS.
-#if defined (osObjectsExternal) // object is external
-#define osMailQDef(name, queue_sz, type) \
-extern osMailQDef_t os_mailQ_def_##name
-#else // define the object
-#define osMailQDef(name, queue_sz, type) \
-uint32_t os_mailQ_q_##name[4+(queue_sz)]; \
-uint32_t os_mailQ_m_##name[3+((sizeof(type)+3)/4)*(queue_sz)]; \
-void * os_mailQ_p_##name[2] = { (os_mailQ_q_##name), os_mailQ_m_##name }; \
-osMailQDef_t os_mailQ_def_##name = \
-{ (queue_sz), sizeof(type), (os_mailQ_p_##name) }
-#endif
-
-/// \brief Access a Mail Queue Definition.
-/// \param name name of the queue
-/// \note CAN BE CHANGED: The parameter to \b osMailQ shall be consistent but the
-/// macro body is implementation specific in every CMSIS-RTOS.
-#define osMailQ(name) \
-&os_mailQ_def_##name
-
-/// Create and Initialize mail queue.
-/// \param[in] queue_def reference to the mail queue definition obtain with \ref osMailQ
-/// \param[in] thread_id thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL.
-/// \return mail queue ID for reference by other functions or NULL in case of error.
-/// \note MUST REMAIN UNCHANGED: \b osMailCreate shall be consistent in every CMSIS-RTOS.
-osMailQId osMailCreate (osMailQDef_t *queue_def, osThreadId thread_id);
-
-/// Allocate a memory block from a mail.
-/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate.
-/// \param[in] millisec timeout value or 0 in case of no time-out
-/// \return pointer to memory block that can be filled with mail or NULL in case of error.
-/// \note MUST REMAIN UNCHANGED: \b osMailAlloc shall be consistent in every CMSIS-RTOS.
-void *osMailAlloc (osMailQId queue_id, uint32_t millisec);
-
-/// Allocate a memory block from a mail and set memory block to zero.
-/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate.
-/// \param[in] millisec timeout value or 0 in case of no time-out
-/// \return pointer to memory block that can be filled with mail or NULL in case of error.
-/// \note MUST REMAIN UNCHANGED: \b osMailCAlloc shall be consistent in every CMSIS-RTOS.
-void *osMailCAlloc (osMailQId queue_id, uint32_t millisec);
-
-/// Put a mail to a queue.
-/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate.
-/// \param[in] mail memory block previously allocated with \ref osMailAlloc or \ref osMailCAlloc.
-/// \return status code that indicates the execution status of the function.
-/// \note MUST REMAIN UNCHANGED: \b osMailPut shall be consistent in every CMSIS-RTOS.
-osStatus osMailPut (osMailQId queue_id, void *mail);
-
-/// Get a mail from a queue.
-/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate.
-/// \param[in] millisec timeout value or 0 in case of no time-out
-/// \return event that contains mail information or error code.
-/// \note MUST REMAIN UNCHANGED: \b osMailGet shall be consistent in every CMSIS-RTOS.
-os_InRegs osEvent osMailGet (osMailQId queue_id, uint32_t millisec);
-
-/// Free a memory block from a mail.
-/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate.
-/// \param[in] mail pointer to the memory block that was obtained with \ref osMailGet.
-/// \return status code that indicates the execution status of the function.
-/// \note MUST REMAIN UNCHANGED: \b osMailFree shall be consistent in every CMSIS-RTOS.
-osStatus osMailFree (osMailQId queue_id, void *mail);
-
-#endif // Mail Queues available
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // _CMSIS_OS_H
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/os_tcb.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/os_tcb.h
deleted file mode 100644
index 800f7f5..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/os_tcb.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef OS_TCB_H
-#define OS_TCB_H
-
-/* Types */
-typedef char S8;
-typedef unsigned char U8;
-typedef short S16;
-typedef unsigned short U16;
-typedef int S32;
-typedef unsigned int U32;
-typedef long long S64;
-typedef unsigned long long U64;
-typedef unsigned char BIT;
-typedef unsigned int BOOL;
-typedef void (*FUNCP)(void);
-
-typedef struct OS_TCB {
- /* General part: identical for all implementations. */
- U8 cb_type; /* Control Block Type */
- U8 state; /* Task state */
- U8 prio; /* Execution priority */
- U8 task_id; /* Task ID value for optimized TCB access */
- struct OS_TCB *p_lnk; /* Link pointer for ready/sem. wait list */
- struct OS_TCB *p_rlnk; /* Link pointer for sem./mbx lst backwards */
- struct OS_TCB *p_dlnk; /* Link pointer for delay list */
- struct OS_TCB *p_blnk; /* Link pointer for delay list backwards */
- U16 delta_time; /* Time until time out */
- U16 interval_time; /* Time interval for periodic waits */
- U16 events; /* Event flags */
- U16 waits; /* Wait flags */
- void **msg; /* Direct message passing when task waits */
-
- /* Hardware dependant part: specific for CM processor */
- U8 stack_frame; /* Stack frame: 0=Basic, 1=Extended */
- U8 reserved1;
- U16 reserved2;
- U32 priv_stack; /* Private stack size in bytes */
- U32 tsk_stack; /* Current task Stack pointer (R13) */
- U32 *stack; /* Pointer to Task Stack memory block */
-
- /* Library dependant part */
-#if defined (__CC_ARM) && !defined (__MICROLIB)
- /* A memory space for arm standard library. */
- U32 std_libspace[96/4];
-#endif
-
- /* Task entry point used for uVision debugger */
- FUNCP ptask; /* Task entry address */
-} *P_TCB;
-
-#endif
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_CMSIS.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_CMSIS.c
deleted file mode 100644
index a747caf..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_CMSIS.c
+++ /dev/null
@@ -1,1887 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: rt_CMSIS.c
- * Purpose: CMSIS RTOS API
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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.
- *---------------------------------------------------------------------------*/
-
-#define __CMSIS_GENERIC
-
-#if defined (__CORTEX_M4) || defined (__CORTEX_M4F)
- #include "core_cm4.h"
-#elif defined (__CORTEX_M7) || defined (__CORTEX_M7F)
- #include "core_cm7.h"
-#elif defined (__CORTEX_M3)
- #include "core_cm3.h"
-#elif defined (__CORTEX_M0)
- #include "core_cm0.h"
-#elif defined (__CORTEX_M0PLUS)
- #include "core_cm0plus.h"
-#else
- #error "Missing __CORTEX_Mx definition"
-#endif
-
-#include "rt_TypeDef.h"
-#include "RTX_Conf.h"
-#include "rt_System.h"
-#include "rt_Task.h"
-#include "rt_Event.h"
-#include "rt_List.h"
-#include "rt_Time.h"
-#include "rt_Mutex.h"
-#include "rt_Semaphore.h"
-#include "rt_Mailbox.h"
-#include "rt_MemBox.h"
-#include "rt_HAL_CM.h"
-
-#define os_thread_cb OS_TCB
-
-#include "cmsis_os.h"
-
-#if (osFeature_Signals != 16)
-#error Invalid "osFeature_Signals" value!
-#endif
-#if (osFeature_Semaphore > 65535)
-#error Invalid "osFeature_Semaphore" value!
-#endif
-#if (osFeature_Wait != 0)
-#error osWait not supported!
-#endif
-
-
-// ==== Enumeration, structures, defines ====
-
-// Service Calls defines
-
-#if defined (__CC_ARM) /* ARM Compiler */
-
-#define __NO_RETURN __declspec(noreturn)
-
-#define osEvent_type osEvent
-#define osEvent_ret_status ret
-#define osEvent_ret_value ret
-#define osEvent_ret_msg ret
-#define osEvent_ret_mail ret
-
-#define osCallback_type osCallback
-#define osCallback_ret ret
-
-#define SVC_0_1(f,t,...) \
-__svc_indirect(0) t _##f (t(*)()); \
- t f (void); \
-__attribute__((always_inline)) \
-static __inline t __##f (void) { \
- return _##f(f); \
-}
-
-#define SVC_1_1(f,t,t1,...) \
-__svc_indirect(0) t _##f (t(*)(t1),t1); \
- t f (t1 a1); \
-__attribute__((always_inline)) \
-static __inline t __##f (t1 a1) { \
- return _##f(f,a1); \
-}
-
-#define SVC_2_1(f,t,t1,t2,...) \
-__svc_indirect(0) t _##f (t(*)(t1,t2),t1,t2); \
- t f (t1 a1, t2 a2); \
-__attribute__((always_inline)) \
-static __inline t __##f (t1 a1, t2 a2) { \
- return _##f(f,a1,a2); \
-}
-
-#define SVC_3_1(f,t,t1,t2,t3,...) \
-__svc_indirect(0) t _##f (t(*)(t1,t2,t3),t1,t2,t3); \
- t f (t1 a1, t2 a2, t3 a3); \
-__attribute__((always_inline)) \
-static __inline t __##f (t1 a1, t2 a2, t3 a3) { \
- return _##f(f,a1,a2,a3); \
-}
-
-#define SVC_4_1(f,t,t1,t2,t3,t4,...) \
-__svc_indirect(0) t _##f (t(*)(t1,t2,t3,t4),t1,t2,t3,t4); \
- t f (t1 a1, t2 a2, t3 a3, t4 a4); \
-__attribute__((always_inline)) \
-static __inline t __##f (t1 a1, t2 a2, t3 a3, t4 a4) { \
- return _##f(f,a1,a2,a3,a4); \
-}
-
-#define SVC_1_2 SVC_1_1
-#define SVC_1_3 SVC_1_1
-#define SVC_2_3 SVC_2_1
-
-#elif defined (__GNUC__) /* GNU Compiler */
-
-#define __NO_RETURN __attribute__((noreturn))
-
-typedef uint32_t __attribute__((vector_size(8))) ret64;
-typedef uint32_t __attribute__((vector_size(16))) ret128;
-
-#define RET_pointer __r0
-#define RET_int32_t __r0
-#define RET_osStatus __r0
-#define RET_osPriority __r0
-#define RET_osEvent {(osStatus)__r0, {(uint32_t)__r1}, {(void *)__r2}}
-#define RET_osCallback {(void *)__r0, (void *)__r1}
-
-#define osEvent_type ret128
-#define osEvent_ret_status (ret128){ret.status}
-#define osEvent_ret_value (ret128){ret.status, ret.value.v}
-#define osEvent_ret_msg (ret128){ret.status, ret.value.v, (uint32_t)ret.def.message_id}
-#define osEvent_ret_mail (ret128){ret.status, ret.value.v, (uint32_t)ret.def.mail_id}
-
-#define osCallback_type ret64
-#define osCallback_ret (ret64) {(uint32_t)ret.fp, (uint32_t)ret.arg}
-
-#define SVC_ArgN(n) \
- register int __r##n __asm("r"#n);
-
-#define SVC_ArgR(n,t,a) \
- register t __r##n __asm("r"#n) = a;
-
-#define SVC_Arg0() \
- SVC_ArgN(0) \
- SVC_ArgN(1) \
- SVC_ArgN(2) \
- SVC_ArgN(3)
-
-#define SVC_Arg1(t1) \
- SVC_ArgR(0,t1,a1) \
- SVC_ArgN(1) \
- SVC_ArgN(2) \
- SVC_ArgN(3)
-
-#define SVC_Arg2(t1,t2) \
- SVC_ArgR(0,t1,a1) \
- SVC_ArgR(1,t2,a2) \
- SVC_ArgN(2) \
- SVC_ArgN(3)
-
-#define SVC_Arg3(t1,t2,t3) \
- SVC_ArgR(0,t1,a1) \
- SVC_ArgR(1,t2,a2) \
- SVC_ArgR(2,t3,a3) \
- SVC_ArgN(3)
-
-#define SVC_Arg4(t1,t2,t3,t4) \
- SVC_ArgR(0,t1,a1) \
- SVC_ArgR(1,t2,a2) \
- SVC_ArgR(2,t3,a3) \
- SVC_ArgR(3,t4,a4)
-
-#if (defined (__CORTEX_M0)) || defined (__CORTEX_M0PLUS)
-#define SVC_Call(f) \
- __asm volatile \
- ( \
- "ldr r7,="#f"\n\t" \
- "mov r12,r7\n\t" \
- "svc 0" \
- : "=r" (__r0), "=r" (__r1), "=r" (__r2), "=r" (__r3) \
- : "r" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) \
- : "r7", "r12", "lr", "cc" \
- );
-#else
-#define SVC_Call(f) \
- __asm volatile \
- ( \
- "ldr r12,="#f"\n\t" \
- "svc 0" \
- : "=r" (__r0), "=r" (__r1), "=r" (__r2), "=r" (__r3) \
- : "r" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) \
- : "r12", "lr", "cc" \
- );
-#endif
-
-#define SVC_0_1(f,t,rv) \
-__attribute__((always_inline)) \
-static inline t __##f (void) { \
- SVC_Arg0(); \
- SVC_Call(f); \
- return (t) rv; \
-}
-
-#define SVC_1_1(f,t,t1,rv) \
-__attribute__((always_inline)) \
-static inline t __##f (t1 a1) { \
- SVC_Arg1(t1); \
- SVC_Call(f); \
- return (t) rv; \
-}
-
-#define SVC_2_1(f,t,t1,t2,rv) \
-__attribute__((always_inline)) \
-static inline t __##f (t1 a1, t2 a2) { \
- SVC_Arg2(t1,t2); \
- SVC_Call(f); \
- return (t) rv; \
-}
-
-#define SVC_3_1(f,t,t1,t2,t3,rv) \
-__attribute__((always_inline)) \
-static inline t __##f (t1 a1, t2 a2, t3 a3) { \
- SVC_Arg3(t1,t2,t3); \
- SVC_Call(f); \
- return (t) rv; \
-}
-
-#define SVC_4_1(f,t,t1,t2,t3,t4,rv) \
-__attribute__((always_inline)) \
-static inline t __##f (t1 a1, t2 a2, t3 a3, t4 a4) { \
- SVC_Arg4(t1,t2,t3,t4); \
- SVC_Call(f); \
- return (t) rv; \
-}
-
-#define SVC_1_2 SVC_1_1
-#define SVC_1_3 SVC_1_1
-#define SVC_2_3 SVC_2_1
-
-#elif defined (__ICCARM__) /* IAR Compiler */
-
-#define __NO_RETURN __noreturn
-
-#define osEvent_type osEvent
-#define osEvent_ret_status ret
-#define osEvent_ret_value ret
-#define osEvent_ret_msg ret
-#define osEvent_ret_mail ret
-
-#define osCallback_type osCallback
-#define osCallback_ret ret
-
-#define RET_osEvent osEvent
-#define RET_osCallback osCallback
-
-#define SVC_Setup(f) \
- __asm( \
- "mov r12,%0\n" \
- :: "r"(&f): "r12" \
- );
-
-
-#define SVC_0_1(f,t,...) \
-t f (void); \
-_Pragma("swi_number=0") __swi t _##f (void); \
-static inline t __##f (void) { \
- SVC_Setup(f); \
- return _##f(); \
-}
-
-#define SVC_1_1(f,t,t1,...) \
-t f (t1 a1); \
-_Pragma("swi_number=0") __swi t _##f (t1 a1); \
-static inline t __##f (t1 a1) { \
- SVC_Setup(f); \
- return _##f(a1); \
-}
-
-#define SVC_2_1(f,t,t1,t2,...) \
-t f (t1 a1, t2 a2); \
-_Pragma("swi_number=0") __swi t _##f (t1 a1, t2 a2); \
-static inline t __##f (t1 a1, t2 a2) { \
- SVC_Setup(f); \
- return _##f(a1,a2); \
-}
-
-#define SVC_3_1(f,t,t1,t2,t3,...) \
-t f (t1 a1, t2 a2, t3 a3); \
-_Pragma("swi_number=0") __swi t _##f (t1 a1, t2 a2, t3 a3); \
-static inline t __##f (t1 a1, t2 a2, t3 a3) { \
- SVC_Setup(f); \
- return _##f(a1,a2,a3); \
-}
-
-#define SVC_4_1(f,t,t1,t2,t3,t4,...) \
-t f (t1 a1, t2 a2, t3 a3, t4 a4); \
-_Pragma("swi_number=0") __swi t _##f (t1 a1, t2 a2, t3 a3, t4 a4); \
-static inline t __##f (t1 a1, t2 a2, t3 a3, t4 a4) { \
- SVC_Setup(f); \
- return _##f(a1,a2,a3,a4); \
-}
-
-#define SVC_1_2 SVC_1_1
-#define SVC_1_3 SVC_1_1
-#define SVC_2_3 SVC_2_1
-
-#endif
-
-
-// Callback structure
-typedef struct {
- void *fp; // Function pointer
- void *arg; // Function argument
-} osCallback;
-
-
-// OS Section definitions
-#ifdef OS_SECTIONS_LINK_INFO
-extern const uint32_t os_section_id$$Base;
-extern const uint32_t os_section_id$$Limit;
-#endif
-
-// OS Timers external resources
-extern osThreadDef_t os_thread_def_osTimerThread;
-extern osThreadId osThreadId_osTimerThread;
-extern osMessageQDef_t os_messageQ_def_osTimerMessageQ;
-extern osMessageQId osMessageQId_osTimerMessageQ;
-
-
-// ==== Helper Functions ====
-
-/// Convert timeout in millisec to system ticks
-static uint32_t rt_ms2tick (uint32_t millisec) {
- uint32_t tick;
-
- if (millisec == osWaitForever) return 0xFFFF; // Indefinite timeout
- if (millisec > 4000000) return 0xFFFE; // Max ticks supported
-
- tick = ((1000 * millisec) + os_clockrate - 1) / os_clockrate;
- if (tick > 0xFFFE) return 0xFFFE;
-
- return tick;
-}
-
-/// Convert Thread ID to TCB pointer
-static P_TCB rt_tid2ptcb (osThreadId thread_id) {
- P_TCB ptcb;
-
- if (thread_id == NULL) return NULL;
-
- if ((uint32_t)thread_id & 3) return NULL;
-
-#ifdef OS_SECTIONS_LINK_INFO
- if ((os_section_id$$Base != 0) && (os_section_id$$Limit != 0)) {
- if (thread_id < (osThreadId)os_section_id$$Base) return NULL;
- if (thread_id >= (osThreadId)os_section_id$$Limit) return NULL;
- }
-#endif
-
- ptcb = thread_id;
-
- if (ptcb->cb_type != TCB) return NULL;
-
- return ptcb;
-}
-
-/// Convert ID pointer to Object pointer
-static void *rt_id2obj (void *id) {
-
- if ((uint32_t)id & 3) return NULL;
-
-#ifdef OS_SECTIONS_LINK_INFO
- if ((os_section_id$$Base != 0) && (os_section_id$$Limit != 0)) {
- if (id < (void *)os_section_id$$Base) return NULL;
- if (id >= (void *)os_section_id$$Limit) return NULL;
- }
-#endif
-
- return id;
-}
-
-
-// ==== Kernel Control ====
-
-uint8_t os_initialized; // Kernel Initialized flag
-uint8_t os_running; // Kernel Running flag
-
-// Kernel Control Service Calls declarations
-SVC_0_1(svcKernelInitialize, osStatus, RET_osStatus)
-SVC_0_1(svcKernelStart, osStatus, RET_osStatus)
-SVC_0_1(svcKernelRunning, int32_t, RET_int32_t)
-
-extern void sysThreadError (osStatus status);
-osThreadId svcThreadCreate (osThreadDef_t *thread_def, void *argument);
-osMessageQId svcMessageCreate (osMessageQDef_t *queue_def, osThreadId thread_id);
-
-// Kernel Control Service Calls
-
-/// Initialize the RTOS Kernel for creating objects
-osStatus svcKernelInitialize (void) {
- if (os_initialized) return osOK;
-
- rt_sys_init(); // RTX System Initialization
- os_tsk.run->prio = 255; // Highest priority
-
- sysThreadError(osOK);
-
- os_initialized = 1;
-
- return osOK;
-}
-
-/// Start the RTOS Kernel
-osStatus svcKernelStart (void) {
-
- if (os_running) return osOK;
-
- // Create OS Timers resources (Message Queue & Thread)
- osMessageQId_osTimerMessageQ = svcMessageCreate (&os_messageQ_def_osTimerMessageQ, NULL);
- osThreadId_osTimerThread = svcThreadCreate(&os_thread_def_osTimerThread, NULL);
-
- rt_tsk_prio(0, 0); // Lowest priority
- __set_PSP(os_tsk.run->tsk_stack + 8*4); // New context
- os_tsk.run = NULL; // Force context switch
-
- rt_sys_start();
-
- os_running = 1;
-
- return osOK;
-}
-
-/// Check if the RTOS kernel is already started
-int32_t svcKernelRunning(void) {
- return os_running;
-}
-
-// Kernel Control Public API
-
-/// Initialize the RTOS Kernel for creating objects
-osStatus osKernelInitialize (void) {
- if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR
- if ((__get_CONTROL() & 1) == 0) { // Privileged mode
- return svcKernelInitialize();
- } else {
- return __svcKernelInitialize();
- }
-}
-
-/// Start the RTOS Kernel
-osStatus osKernelStart (void) {
- uint32_t stack[8];
-
- if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR
- switch (__get_CONTROL() & 0x03) {
- case 0x00: // Privileged Thread mode & MSP
- __set_PSP((uint32_t)(stack + 8)); // Initial PSP
- if (os_flags & 1) {
- __set_CONTROL(0x02); // Set Privileged Thread mode & PSP
- } else {
- __set_CONTROL(0x03); // Set Unprivileged Thread mode & PSP
- }
- __DSB();
- __ISB();
- break;
- case 0x01: // Unprivileged Thread mode & MSP
- return osErrorOS;
- case 0x02: // Privileged Thread mode & PSP
- if ((os_flags & 1) == 0) { // Unprivileged Thread mode requested
- __set_CONTROL(0x03); // Set Unprivileged Thread mode & PSP
- __DSB();
- __ISB();
- }
- break;
- case 0x03: // Unprivileged Thread mode & PSP
- if (os_flags & 1) return osErrorOS; // Privileged Thread mode requested
- break;
- }
- return __svcKernelStart();
-}
-
-/// Check if the RTOS kernel is already started
-int32_t osKernelRunning(void) {
- if ((__get_IPSR() != 0) || ((__get_CONTROL() & 1) == 0)) {
- // in ISR or Privileged
- return os_running;
- } else {
- return __svcKernelRunning();
- }
-}
-
-
-// ==== Thread Management ====
-
-__NO_RETURN void osThreadExit (void);
-
-// Thread Service Calls declarations
-SVC_2_1(svcThreadCreate, osThreadId, osThreadDef_t *, void *, RET_pointer)
-SVC_0_1(svcThreadGetId, osThreadId, RET_pointer)
-SVC_1_1(svcThreadTerminate, osStatus, osThreadId, RET_osStatus)
-SVC_0_1(svcThreadYield, osStatus, RET_osStatus)
-SVC_2_1(svcThreadSetPriority, osStatus, osThreadId, osPriority, RET_osStatus)
-SVC_1_1(svcThreadGetPriority, osPriority, osThreadId, RET_osPriority)
-
-// Thread Service Calls
-extern OS_TID rt_get_TID (void);
-extern void rt_init_context (P_TCB p_TCB, U8 priority, FUNCP task_body);
-
-/// Create a thread and add it to Active Threads and set it to state READY
-osThreadId svcThreadCreate (osThreadDef_t *thread_def, void *argument) {
- P_TCB ptcb;
-
- if ((thread_def == NULL) ||
- (thread_def->pthread == NULL) ||
- (thread_def->tpriority < osPriorityIdle) ||
- (thread_def->tpriority > osPriorityRealtime) ||
- (thread_def->stacksize == 0) ||
- (thread_def->stack_pointer == NULL) ) {
- sysThreadError(osErrorParameter);
- return NULL;
- }
-
- U8 priority = thread_def->tpriority - osPriorityIdle + 1;
- P_TCB task_context = &thread_def->tcb;
-
- /* Utilize the user provided stack. */
- task_context->stack = (U32*)thread_def->stack_pointer;
- task_context->priv_stack = thread_def->stacksize;
- /* Find a free entry in 'os_active_TCB' table. */
- OS_TID tsk = rt_get_TID ();
- os_active_TCB[tsk-1] = task_context;
- task_context->task_id = tsk;
- /* Pass parameter 'argv' to 'rt_init_context' */
- task_context->msg = argument;
- /* Initialize thread context structure, including the thread's stack. */
- rt_init_context (task_context, priority, (FUNCP)thread_def->pthread);
-
- /* Dispatch this task to the scheduler for execution. */
- DBG_TASK_NOTIFY(task_context, __TRUE);
- rt_dispatch (task_context);
-
- ptcb = (P_TCB)os_active_TCB[tsk - 1]; // TCB pointer
-
- *((uint32_t *)ptcb->tsk_stack + 13) = (uint32_t)osThreadExit;
-
- return ptcb;
-}
-
-/// Return the thread ID of the current running thread
-osThreadId svcThreadGetId (void) {
- OS_TID tsk;
-
- tsk = rt_tsk_self();
- if (tsk == 0) return NULL;
- return (P_TCB)os_active_TCB[tsk - 1];
-}
-
-/// Terminate execution of a thread and remove it from ActiveThreads
-osStatus svcThreadTerminate (osThreadId thread_id) {
- OS_RESULT res;
- P_TCB ptcb;
-
- ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
- if (ptcb == NULL) return osErrorParameter;
-
- res = rt_tsk_delete(ptcb->task_id); // Delete task
-
- if (res == OS_R_NOK) return osErrorResource; // Delete task failed
-
- return osOK;
-}
-
-/// Pass control to next thread that is in state READY
-osStatus svcThreadYield (void) {
- rt_tsk_pass(); // Pass control to next task
- return osOK;
-}
-
-/// Change priority of an active thread
-osStatus svcThreadSetPriority (osThreadId thread_id, osPriority priority) {
- OS_RESULT res;
- P_TCB ptcb;
-
- ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
- if (ptcb == NULL) return osErrorParameter;
-
- if ((priority < osPriorityIdle) || (priority > osPriorityRealtime)) {
- return osErrorValue;
- }
-
- res = rt_tsk_prio( // Change task priority
- ptcb->task_id, // Task ID
- priority - osPriorityIdle + 1 // New task priority
- );
-
- if (res == OS_R_NOK) return osErrorResource; // Change task priority failed
-
- return osOK;
-}
-
-/// Get current priority of an active thread
-osPriority svcThreadGetPriority (osThreadId thread_id) {
- P_TCB ptcb;
-
- ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
- if (ptcb == NULL) return osPriorityError;
-
- return (osPriority)(ptcb->prio - 1 + osPriorityIdle);
-}
-
-
-// Thread Public API
-
-/// Create a thread and add it to Active Threads and set it to state READY
-osThreadId osThreadCreate (osThreadDef_t *thread_def, void *argument) {
- if (__get_IPSR() != 0) return NULL; // Not allowed in ISR
- if (((__get_CONTROL() & 1) == 0) && (os_running == 0)) {
- // Privileged and not running
- return svcThreadCreate(thread_def, argument);
- } else {
- return __svcThreadCreate(thread_def, argument);
- }
-}
-
-/// Return the thread ID of the current running thread
-osThreadId osThreadGetId (void) {
- if (__get_IPSR() != 0) return NULL; // Not allowed in ISR
- return __svcThreadGetId();
-}
-
-/// Terminate execution of a thread and remove it from ActiveThreads
-osStatus osThreadTerminate (osThreadId thread_id) {
- if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR
- return __svcThreadTerminate(thread_id);
-}
-
-/// Pass control to next thread that is in state READY
-osStatus osThreadYield (void) {
- if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR
- return __svcThreadYield();
-}
-
-/// Change priority of an active thread
-osStatus osThreadSetPriority (osThreadId thread_id, osPriority priority) {
- if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR
- return __svcThreadSetPriority(thread_id, priority);
-}
-
-/// Get current priority of an active thread
-osPriority osThreadGetPriority (osThreadId thread_id) {
- if (__get_IPSR() != 0) return osPriorityError;// Not allowed in ISR
- return __svcThreadGetPriority(thread_id);
-}
-
-/// INTERNAL - Not Public
-/// Auto Terminate Thread on exit (used implicitly when thread exists)
-__NO_RETURN void osThreadExit (void) {
- __svcThreadTerminate(__svcThreadGetId());
- for (;;); // Should never come here
-}
-
-
-// ==== Generic Wait Functions ====
-
-// Generic Wait Service Calls declarations
-SVC_1_1(svcDelay, osStatus, uint32_t, RET_osStatus)
-#if osFeature_Wait != 0
-SVC_1_3(svcWait, os_InRegs osEvent, uint32_t, RET_osEvent)
-#endif
-
-// Generic Wait Service Calls
-
-/// Wait for Timeout (Time Delay)
-osStatus svcDelay (uint32_t millisec) {
- if (millisec == 0) return osOK;
- rt_dly_wait(rt_ms2tick(millisec));
- return osEventTimeout;
-}
-
-/// Wait for Signal, Message, Mail, or Timeout
-#if osFeature_Wait != 0
-os_InRegs osEvent_type svcWait (uint32_t millisec) {
- osEvent ret;
-
- if (millisec == 0) {
- ret.status = osOK;
- return osEvent_ret_status;
- }
-
- /* To Do: osEventSignal, osEventMessage, osEventMail */
- rt_dly_wait(rt_ms2tick(millisec));
- ret.status = osEventTimeout;
-
- return osEvent_ret_status;
-}
-#endif
-
-
-// Generic Wait API
-
-/// Wait for Timeout (Time Delay)
-osStatus osDelay (uint32_t millisec) {
- if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR
- return __svcDelay(millisec);
-}
-
-/// Wait for Signal, Message, Mail, or Timeout
-os_InRegs osEvent osWait (uint32_t millisec) {
- osEvent ret;
-
-#if osFeature_Wait == 0
- ret.status = osErrorOS;
- return ret;
-#else
- if (__get_IPSR() != 0) { // Not allowed in ISR
- ret.status = osErrorISR;
- return ret;
- }
- return __svcWait(millisec);
-#endif
-}
-
-
-// ==== Timer Management ====
-
-// Timer definitions
-#define osTimerInvalid 0
-#define osTimerStopped 1
-#define osTimerRunning 2
-
-// Timer structures
-
-typedef struct os_timer_cb_ { // Timer Control Block
- struct os_timer_cb_ *next; // Pointer to next active Timer
- uint8_t state; // Timer State
- uint8_t type; // Timer Type (Periodic/One-shot)
- uint16_t reserved; // Reserved
- uint16_t tcnt; // Timer Delay Count
- uint16_t icnt; // Timer Initial Count
- void *arg; // Timer Function Argument
- osTimerDef_t *timer; // Pointer to Timer definition
-} os_timer_cb;
-
-// Timer variables
-os_timer_cb *os_timer_head; // Pointer to first active Timer
-
-
-// Timer Helper Functions
-
-// Insert Timer into the list sorted by time
-static void rt_timer_insert (os_timer_cb *pt, uint32_t tcnt) {
- os_timer_cb *p, *prev;
-
- prev = NULL;
- p = os_timer_head;
- while (p != NULL) {
- if (tcnt < p->tcnt) break;
- tcnt -= p->tcnt;
- prev = p;
- p = p->next;
- }
- pt->next = p;
- pt->tcnt = (uint16_t)tcnt;
- if (p != NULL) {
- p->tcnt -= pt->tcnt;
- }
- if (prev != NULL) {
- prev->next = pt;
- } else {
- os_timer_head = pt;
- }
-}
-
-// Remove Timer from the list
-static int rt_timer_remove (os_timer_cb *pt) {
- os_timer_cb *p, *prev;
-
- prev = NULL;
- p = os_timer_head;
- while (p != NULL) {
- if (p == pt) break;
- prev = p;
- p = p->next;
- }
- if (p == NULL) return -1;
- if (prev != NULL) {
- prev->next = pt->next;
- } else {
- os_timer_head = pt->next;
- }
- if (pt->next != NULL) {
- pt->next->tcnt += pt->tcnt;
- }
-
- return 0;
-}
-
-
-// Timer Service Calls declarations
-SVC_3_1(svcTimerCreate, osTimerId, osTimerDef_t *, os_timer_type, void *, RET_pointer)
-SVC_2_1(svcTimerStart, osStatus, osTimerId, uint32_t, RET_osStatus)
-SVC_1_1(svcTimerStop, osStatus, osTimerId, RET_osStatus)
-SVC_1_1(svcTimerDelete, osStatus, osTimerId, RET_osStatus)
-SVC_1_2(svcTimerCall, os_InRegs osCallback, osTimerId, RET_osCallback)
-
-// Timer Management Service Calls
-
-/// Create timer
-osTimerId svcTimerCreate (osTimerDef_t *timer_def, os_timer_type type, void *argument) {
- os_timer_cb *pt;
-
- if ((timer_def == NULL) || (timer_def->ptimer == NULL)) {
- sysThreadError(osErrorParameter);
- return NULL;
- }
-
- pt = timer_def->timer;
- if (pt == NULL) {
- sysThreadError(osErrorParameter);
- return NULL;
- }
-
- if ((type != osTimerOnce) && (type != osTimerPeriodic)) {
- sysThreadError(osErrorValue);
- return NULL;
- }
-
- if (osThreadId_osTimerThread == NULL) {
- sysThreadError(osErrorResource);
- return NULL;
- }
-
- if (pt->state != osTimerInvalid){
- sysThreadError(osErrorResource);
- return NULL;
- }
-
- pt->state = osTimerStopped;
- pt->type = (uint8_t)type;
- pt->arg = argument;
- pt->timer = timer_def;
-
- return (osTimerId)pt;
-}
-
-/// Start or restart timer
-osStatus svcTimerStart (osTimerId timer_id, uint32_t millisec) {
- os_timer_cb *pt;
- uint32_t tcnt;
-
- pt = rt_id2obj(timer_id);
- if (pt == NULL) return osErrorParameter;
-
- tcnt = rt_ms2tick(millisec);
- if (tcnt == 0) return osErrorValue;
-
- switch (pt->state) {
- case osTimerRunning:
- if (rt_timer_remove(pt) != 0) {
- return osErrorResource;
- }
- break;
- case osTimerStopped:
- pt->state = osTimerRunning;
- pt->icnt = (uint16_t)tcnt;
- break;
- default:
- return osErrorResource;
- }
-
- rt_timer_insert(pt, tcnt);
-
- return osOK;
-}
-
-/// Stop timer
-osStatus svcTimerStop (osTimerId timer_id) {
- os_timer_cb *pt;
-
- pt = rt_id2obj(timer_id);
- if (pt == NULL) return osErrorParameter;
-
- if (pt->state != osTimerRunning) return osErrorResource;
-
- pt->state = osTimerStopped;
-
- if (rt_timer_remove(pt) != 0) {
- return osErrorResource;
- }
-
- return osOK;
-}
-
-/// Delete timer
-osStatus svcTimerDelete (osTimerId timer_id) {
- os_timer_cb *pt;
-
- pt = rt_id2obj(timer_id);
- if (pt == NULL) return osErrorParameter;
-
- switch (pt->state) {
- case osTimerRunning:
- rt_timer_remove(pt);
- break;
- case osTimerStopped:
- break;
- default:
- return osErrorResource;
- }
-
- pt->state = osTimerInvalid;
-
- return osOK;
-}
-
-/// Get timer callback parameters
-os_InRegs osCallback_type svcTimerCall (osTimerId timer_id) {
- os_timer_cb *pt;
- osCallback ret;
-
- pt = rt_id2obj(timer_id);
- if (pt == NULL) {
- ret.fp = NULL;
- ret.arg = NULL;
- return osCallback_ret;
- }
-
- ret.fp = (void *)pt->timer->ptimer;
- ret.arg = pt->arg;
-
- return osCallback_ret;
-}
-
-static __INLINE osStatus isrMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec);
-
-/// Timer Tick (called each SysTick)
-void sysTimerTick (void) {
- os_timer_cb *pt, *p;
-
- p = os_timer_head;
- if (p == NULL) return;
-
- p->tcnt--;
- while ((p != NULL) && (p->tcnt == 0)) {
- pt = p;
- p = p->next;
- os_timer_head = p;
- isrMessagePut(osMessageQId_osTimerMessageQ, (uint32_t)pt, 0);
- if (pt->type == osTimerPeriodic) {
- rt_timer_insert(pt, pt->icnt);
- } else {
- pt->state = osTimerStopped;
- }
- }
-}
-
-
-// Timer Management Public API
-
-/// Create timer
-osTimerId osTimerCreate (osTimerDef_t *timer_def, os_timer_type type, void *argument) {
- if (__get_IPSR() != 0) return NULL; // Not allowed in ISR
- if (((__get_CONTROL() & 1) == 0) && (os_running == 0)) {
- // Privileged and not running
- return svcTimerCreate(timer_def, type, argument);
- } else {
- return __svcTimerCreate(timer_def, type, argument);
- }
-}
-
-/// Start or restart timer
-osStatus osTimerStart (osTimerId timer_id, uint32_t millisec) {
- if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR
- return __svcTimerStart(timer_id, millisec);
-}
-
-/// Stop timer
-osStatus osTimerStop (osTimerId timer_id) {
- if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR
- return __svcTimerStop(timer_id);
-}
-
-/// Delete timer
-osStatus osTimerDelete (osTimerId timer_id) {
- if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR
- return __svcTimerDelete(timer_id);
-}
-
-/// INTERNAL - Not Public
-/// Get timer callback parameters (used by OS Timer Thread)
-os_InRegs osCallback osTimerCall (osTimerId timer_id) {
- return __svcTimerCall(timer_id);
-}
-
-
-// Timer Thread
-__NO_RETURN void osTimerThread (void const *argument) {
- osCallback cb;
- osEvent evt;
-
- for (;;) {
- evt = osMessageGet(osMessageQId_osTimerMessageQ, osWaitForever);
- if (evt.status == osEventMessage) {
- cb = osTimerCall(evt.value.p);
- if (cb.fp != NULL) {
- (*(os_ptimer)cb.fp)(cb.arg);
- }
- }
- }
-}
-
-
-// ==== Signal Management ====
-
-// Signal Service Calls declarations
-SVC_2_1(svcSignalSet, int32_t, osThreadId, int32_t, RET_int32_t)
-SVC_2_1(svcSignalClear, int32_t, osThreadId, int32_t, RET_int32_t)
-SVC_1_1(svcSignalGet, int32_t, osThreadId, RET_int32_t)
-SVC_2_3(svcSignalWait, os_InRegs osEvent, int32_t, uint32_t, RET_osEvent)
-
-// Signal Service Calls
-
-/// Set the specified Signal Flags of an active thread
-int32_t svcSignalSet (osThreadId thread_id, int32_t signals) {
- P_TCB ptcb;
- int32_t sig;
-
- ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
- if (ptcb == NULL) return 0x80000000;
-
- if (signals & (0xFFFFFFFF << osFeature_Signals)) return 0x80000000;
-
- sig = ptcb->events; // Previous signal flags
-
- rt_evt_set(signals, ptcb->task_id); // Set event flags
-
- return sig;
-}
-
-/// Clear the specified Signal Flags of an active thread
-int32_t svcSignalClear (osThreadId thread_id, int32_t signals) {
- P_TCB ptcb;
- int32_t sig;
-
- ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
- if (ptcb == NULL) return 0x80000000;
-
- if (signals & (0xFFFFFFFF << osFeature_Signals)) return 0x80000000;
-
- sig = ptcb->events; // Previous signal flags
-
- rt_evt_clr(signals, ptcb->task_id); // Clear event flags
-
- return sig;
-}
-
-/// Get Signal Flags status of an active thread
-int32_t svcSignalGet (osThreadId thread_id) {
- P_TCB ptcb;
-
- ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
- if (ptcb == NULL) return 0x80000000;
-
- return ptcb->events; // Return event flags
-}
-
-/// Wait for one or more Signal Flags to become signaled for the current RUNNING thread
-os_InRegs osEvent_type svcSignalWait (int32_t signals, uint32_t millisec) {
- OS_RESULT res;
- osEvent ret;
-
- if (signals & (0xFFFFFFFF << osFeature_Signals)) {
- ret.status = osErrorValue;
- return osEvent_ret_status;
- }
-
- if (signals != 0) { // Wait for all specified signals
- res = rt_evt_wait(signals, rt_ms2tick(millisec), __TRUE);
- } else { // Wait for any signal
- res = rt_evt_wait(0xFFFF, rt_ms2tick(millisec), __FALSE);
- }
-
- if (res == OS_R_EVT) {
- ret.status = osEventSignal;
- ret.value.signals = signals ? signals : os_tsk.run->waits;
- } else {
- ret.status = millisec ? osEventTimeout : osOK;
- ret.value.signals = 0;
- }
-
- return osEvent_ret_value;
-}
-
-
-// Signal ISR Calls
-
-/// Set the specified Signal Flags of an active thread
-static __INLINE int32_t isrSignalSet (osThreadId thread_id, int32_t signals) {
- P_TCB ptcb;
- int32_t sig;
-
- ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
- if (ptcb == NULL) return 0x80000000;
-
- if (signals & (0xFFFFFFFF << osFeature_Signals)) return 0x80000000;
-
- sig = ptcb->events; // Previous signal flags
-
- isr_evt_set(signals, ptcb->task_id); // Set event flags
-
- return sig;
-}
-
-
-// Signal Public API
-
-/// Set the specified Signal Flags of an active thread
-int32_t osSignalSet (osThreadId thread_id, int32_t signals) {
- if (__get_IPSR() != 0) { // in ISR
- return isrSignalSet(thread_id, signals);
- } else { // in Thread
- return __svcSignalSet(thread_id, signals);
- }
-}
-
-/// Clear the specified Signal Flags of an active thread
-int32_t osSignalClear (osThreadId thread_id, int32_t signals) {
- if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR
- return __svcSignalClear(thread_id, signals);
-}
-
-/// Get Signal Flags status of an active thread
-int32_t osSignalGet (osThreadId thread_id) {
- if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR
- return __svcSignalGet(thread_id);
-}
-
-/// Wait for one or more Signal Flags to become signaled for the current RUNNING thread
-os_InRegs osEvent osSignalWait (int32_t signals, uint32_t millisec) {
- osEvent ret;
-
- if (__get_IPSR() != 0) { // Not allowed in ISR
- ret.status = osErrorISR;
- return ret;
- }
- return __svcSignalWait(signals, millisec);
-}
-
-
-// ==== Mutex Management ====
-
-// Mutex Service Calls declarations
-SVC_1_1(svcMutexCreate, osMutexId, osMutexDef_t *, RET_pointer)
-SVC_2_1(svcMutexWait, osStatus, osMutexId, uint32_t, RET_osStatus)
-SVC_1_1(svcMutexRelease, osStatus, osMutexId, RET_osStatus)
-SVC_1_1(svcMutexDelete, osStatus, osMutexId, RET_osStatus)
-
-// Mutex Service Calls
-
-/// Create and Initialize a Mutex object
-osMutexId svcMutexCreate (osMutexDef_t *mutex_def) {
- OS_ID mut;
-
- if (mutex_def == NULL) {
- sysThreadError(osErrorParameter);
- return NULL;
- }
-
- mut = mutex_def->mutex;
- if (mut == NULL) {
- sysThreadError(osErrorParameter);
- return NULL;
- }
-
- if (((P_MUCB)mut)->cb_type != 0) {
- sysThreadError(osErrorParameter);
- return NULL;
- }
-
- rt_mut_init(mut); // Initialize Mutex
-
- return mut;
-}
-
-/// Wait until a Mutex becomes available
-osStatus svcMutexWait (osMutexId mutex_id, uint32_t millisec) {
- OS_ID mut;
- OS_RESULT res;
-
- mut = rt_id2obj(mutex_id);
- if (mut == NULL) return osErrorParameter;
-
- if (((P_MUCB)mut)->cb_type != MUCB) return osErrorParameter;
-
- res = rt_mut_wait(mut, rt_ms2tick(millisec)); // Wait for Mutex
-
- if (res == OS_R_TMO) {
- return (millisec ? osErrorTimeoutResource : osErrorResource);
- }
-
- return osOK;
-}
-
-/// Release a Mutex that was obtained with osMutexWait
-osStatus svcMutexRelease (osMutexId mutex_id) {
- OS_ID mut;
- OS_RESULT res;
-
- mut = rt_id2obj(mutex_id);
- if (mut == NULL) return osErrorParameter;
-
- if (((P_MUCB)mut)->cb_type != MUCB) return osErrorParameter;
-
- res = rt_mut_release(mut); // Release Mutex
-
- if (res == OS_R_NOK) return osErrorResource; // Thread not owner or Zero Counter
-
- return osOK;
-}
-
-/// Delete a Mutex that was created by osMutexCreate
-osStatus svcMutexDelete (osMutexId mutex_id) {
- OS_ID mut;
-
- mut = rt_id2obj(mutex_id);
- if (mut == NULL) return osErrorParameter;
-
- if (((P_MUCB)mut)->cb_type != MUCB) return osErrorParameter;
-
- rt_mut_delete(mut); // Release Mutex
-
- return osOK;
-}
-
-
-// Mutex Public API
-
-/// Create and Initialize a Mutex object
-osMutexId osMutexCreate (osMutexDef_t *mutex_def) {
- if (__get_IPSR() != 0) return NULL; // Not allowed in ISR
- if (((__get_CONTROL() & 1) == 0) && (os_running == 0)) {
- // Privileged and not running
- return svcMutexCreate(mutex_def);
- } else {
- return __svcMutexCreate(mutex_def);
- }
-}
-
-/// Wait until a Mutex becomes available
-osStatus osMutexWait (osMutexId mutex_id, uint32_t millisec) {
- if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR
- return __svcMutexWait(mutex_id, millisec);
-}
-
-/// Release a Mutex that was obtained with osMutexWait
-osStatus osMutexRelease (osMutexId mutex_id) {
- if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR
- return __svcMutexRelease(mutex_id);
-}
-
-/// Delete a Mutex that was created by osMutexCreate
-osStatus osMutexDelete (osMutexId mutex_id) {
- if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR
- return __svcMutexDelete(mutex_id);
-}
-
-
-// ==== Semaphore Management ====
-
-// Semaphore Service Calls declarations
-SVC_2_1(svcSemaphoreCreate, osSemaphoreId, const osSemaphoreDef_t *, int32_t, RET_pointer)
-SVC_2_1(svcSemaphoreWait, int32_t, osSemaphoreId, uint32_t, RET_int32_t)
-SVC_1_1(svcSemaphoreRelease, osStatus, osSemaphoreId, RET_osStatus)
-SVC_1_1(svcSemaphoreDelete, osStatus, osSemaphoreId, RET_osStatus)
-
-// Semaphore Service Calls
-
-/// Create and Initialize a Semaphore object
-osSemaphoreId svcSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count) {
- OS_ID sem;
-
- if (semaphore_def == NULL) {
- sysThreadError(osErrorParameter);
- return NULL;
- }
-
- sem = semaphore_def->semaphore;
- if (sem == NULL) {
- sysThreadError(osErrorParameter);
- return NULL;
- }
-
- if (((P_SCB)sem)->cb_type != 0) {
- sysThreadError(osErrorParameter);
- return NULL;
- }
-
- if (count > osFeature_Semaphore) {
- sysThreadError(osErrorValue);
- return NULL;
- }
-
- rt_sem_init(sem, count); // Initialize Semaphore
-
- return sem;
-}
-
-/// Wait until a Semaphore becomes available
-int32_t svcSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec) {
- OS_ID sem;
- OS_RESULT res;
-
- sem = rt_id2obj(semaphore_id);
- if (sem == NULL) return -1;
-
- if (((P_SCB)sem)->cb_type != SCB) return -1;
-
- res = rt_sem_wait(sem, rt_ms2tick(millisec)); // Wait for Semaphore
-
- if (res == OS_R_TMO) return 0; // Timeout
-
- return (((P_SCB)sem)->tokens + 1);
-}
-
-/// Release a Semaphore
-osStatus svcSemaphoreRelease (osSemaphoreId semaphore_id) {
- OS_ID sem;
-
- sem = rt_id2obj(semaphore_id);
- if (sem == NULL) return osErrorParameter;
-
- if (((P_SCB)sem)->cb_type != SCB) return osErrorParameter;
-
- if (((P_SCB)sem)->tokens == osFeature_Semaphore) return osErrorResource;
-
- rt_sem_send(sem); // Release Semaphore
-
- return osOK;
-}
-
-/// Delete a Semaphore that was created by osSemaphoreCreate
-osStatus svcSemaphoreDelete (osSemaphoreId semaphore_id) {
- OS_ID sem;
-
- sem = rt_id2obj(semaphore_id);
- if (sem == NULL) return osErrorParameter;
-
- if (((P_SCB)sem)->cb_type != SCB) return osErrorParameter;
-
- rt_sem_delete(sem); // Delete Semaphore
-
- return osOK;
-}
-
-
-// Semaphore ISR Calls
-
-/// Release a Semaphore
-static __INLINE osStatus isrSemaphoreRelease (osSemaphoreId semaphore_id) {
- OS_ID sem;
-
- sem = rt_id2obj(semaphore_id);
- if (sem == NULL) return osErrorParameter;
-
- if (((P_SCB)sem)->cb_type != SCB) return osErrorParameter;
-
- if (((P_SCB)sem)->tokens == osFeature_Semaphore) return osErrorResource;
-
- isr_sem_send(sem); // Release Semaphore
-
- return osOK;
-}
-
-
-// Semaphore Public API
-
-/// Create and Initialize a Semaphore object
-osSemaphoreId osSemaphoreCreate (osSemaphoreDef_t *semaphore_def, int32_t count) {
- if (__get_IPSR() != 0) return NULL; // Not allowed in ISR
- if (((__get_CONTROL() & 1) == 0) && (os_running == 0)) {
- // Privileged and not running
- return svcSemaphoreCreate(semaphore_def, count);
- } else {
- return __svcSemaphoreCreate(semaphore_def, count);
- }
-}
-
-/// Wait until a Semaphore becomes available
-int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec) {
- if (__get_IPSR() != 0) return -1; // Not allowed in ISR
- return __svcSemaphoreWait(semaphore_id, millisec);
-}
-
-/// Release a Semaphore
-osStatus osSemaphoreRelease (osSemaphoreId semaphore_id) {
- if (__get_IPSR() != 0) { // in ISR
- return isrSemaphoreRelease(semaphore_id);
- } else { // in Thread
- return __svcSemaphoreRelease(semaphore_id);
- }
-}
-
-/// Delete a Semaphore that was created by osSemaphoreCreate
-osStatus osSemaphoreDelete (osSemaphoreId semaphore_id) {
- if (__get_IPSR() != 0) return osErrorISR; // Not allowed in ISR
- return __svcSemaphoreDelete(semaphore_id);
-}
-
-
-// ==== Memory Management Functions ====
-
-// Memory Management Helper Functions
-
-// Clear Memory Box (Zero init)
-static void rt_clr_box (void *box_mem, void *box) {
- uint32_t *p, n;
-
- if (box) {
- p = box;
- for (n = ((P_BM)box_mem)->blk_size; n; n -= 4) {
- *p++ = 0;
- }
- }
-}
-
-// Memory Management Service Calls declarations
-SVC_1_1(svcPoolCreate, osPoolId, const osPoolDef_t *, RET_pointer)
-SVC_2_1(sysPoolAlloc, void *, osPoolId, uint32_t, RET_pointer)
-SVC_2_1(sysPoolFree, osStatus, osPoolId, void *, RET_osStatus)
-
-// Memory Management Service & ISR Calls
-
-/// Create and Initialize memory pool
-osPoolId svcPoolCreate (const osPoolDef_t *pool_def) {
- uint32_t blk_sz;
-
- if ((pool_def == NULL) ||
- (pool_def->pool_sz == 0) ||
- (pool_def->item_sz == 0) ||
- (pool_def->pool == NULL)) {
- sysThreadError(osErrorParameter);
- return NULL;
- }
-
- blk_sz = (pool_def->item_sz + 3) & ~3;
-
- _init_box(pool_def->pool, sizeof(struct OS_BM) + pool_def->pool_sz * blk_sz, blk_sz);
-
- return pool_def->pool;
-}
-
-/// Allocate a memory block from a memory pool
-void *sysPoolAlloc (osPoolId pool_id, uint32_t clr) {
- void *ptr;
-
- if (pool_id == NULL) return NULL;
-
- ptr = rt_alloc_box(pool_id);
- if (clr) {
- rt_clr_box(pool_id, ptr);
- }
-
- return ptr;
-}
-
-/// Return an allocated memory block back to a specific memory pool
-osStatus sysPoolFree (osPoolId pool_id, void *block) {
- int32_t res;
-
- if (pool_id == NULL) return osErrorParameter;
-
- res = rt_free_box(pool_id, block);
- if (res != 0) return osErrorValue;
-
- return osOK;
-}
-
-
-// Memory Management Public API
-
-/// Create and Initialize memory pool
-osPoolId osPoolCreate (osPoolDef_t *pool_def) {
- if (__get_IPSR() != 0) return NULL; // Not allowed in ISR
- if (((__get_CONTROL() & 1) == 0) && (os_running == 0)) {
- // Privileged and not running
- return svcPoolCreate(pool_def);
- } else {
- return __svcPoolCreate(pool_def);
- }
-}
-
-/// Allocate a memory block from a memory pool
-void *osPoolAlloc (osPoolId pool_id) {
- if ((__get_IPSR() != 0) || ((__get_CONTROL() & 1) == 0)) { // in ISR or Privileged
- return sysPoolAlloc(pool_id, 0);
- } else { // in Thread
- return __sysPoolAlloc(pool_id, 0);
- }
-}
-
-/// Allocate a memory block from a memory pool and set memory block to zero
-void *osPoolCAlloc (osPoolId pool_id) {
- if ((__get_IPSR() != 0) || ((__get_CONTROL() & 1) == 0)) { // in ISR or Privileged
- return sysPoolAlloc(pool_id, 1);
- } else { // in Thread
- return __sysPoolAlloc(pool_id, 1);
- }
-}
-
-/// Return an allocated memory block back to a specific memory pool
-osStatus osPoolFree (osPoolId pool_id, void *block) {
- if ((__get_IPSR() != 0) || ((__get_CONTROL() & 1) == 0)) { // in ISR or Privileged
- return sysPoolFree(pool_id, block);
- } else { // in Thread
- return __sysPoolFree(pool_id, block);
- }
-}
-
-
-// ==== Message Queue Management Functions ====
-
-// Message Queue Management Service Calls declarations
-SVC_2_1(svcMessageCreate, osMessageQId, osMessageQDef_t *, osThreadId, RET_pointer)
-SVC_3_1(svcMessagePut, osStatus, osMessageQId, uint32_t, uint32_t, RET_osStatus)
-SVC_2_3(svcMessageGet, os_InRegs osEvent, osMessageQId, uint32_t, RET_osEvent)
-
-// Message Queue Service Calls
-
-/// Create and Initialize Message Queue
-osMessageQId svcMessageCreate (osMessageQDef_t *queue_def, osThreadId thread_id) {
-
- if ((queue_def == NULL) ||
- (queue_def->queue_sz == 0) ||
- (queue_def->pool == NULL)) {
- sysThreadError(osErrorParameter);
- return NULL;
- }
-
- if (((P_MCB)queue_def->pool)->cb_type != 0) {
- sysThreadError(osErrorParameter);
- return NULL;
- }
-
- rt_mbx_init(queue_def->pool, 4*(queue_def->queue_sz + 4));
-
- return queue_def->pool;
-}
-
-/// Put a Message to a Queue
-osStatus svcMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec) {
- OS_RESULT res;
-
- if (queue_id == NULL) return osErrorParameter;
-
- if (((P_MCB)queue_id)->cb_type != MCB) return osErrorParameter;
-
- res = rt_mbx_send(queue_id, (void *)info, rt_ms2tick(millisec));
-
- if (res == OS_R_TMO) {
- return (millisec ? osErrorTimeoutResource : osErrorResource);
- }
-
- return osOK;
-}
-
-/// Get a Message or Wait for a Message from a Queue
-os_InRegs osEvent_type svcMessageGet (osMessageQId queue_id, uint32_t millisec) {
- OS_RESULT res;
- osEvent ret;
-
- if (queue_id == NULL) {
- ret.status = osErrorParameter;
- return osEvent_ret_status;
- }
-
- if (((P_MCB)queue_id)->cb_type != MCB) {
- ret.status = osErrorParameter;
- return osEvent_ret_status;
- }
-
- res = rt_mbx_wait(queue_id, &ret.value.p, rt_ms2tick(millisec));
-
- if (res == OS_R_TMO) {
- ret.status = millisec ? osEventTimeout : osOK;
- return osEvent_ret_value;
- }
-
- ret.status = osEventMessage;
-
- return osEvent_ret_value;
-}
-
-
-// Message Queue ISR Calls
-
-/// Put a Message to a Queue
-static __INLINE osStatus isrMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec) {
-
- if ((queue_id == NULL) || (millisec != 0)) {
- return osErrorParameter;
- }
-
- if (((P_MCB)queue_id)->cb_type != MCB) return osErrorParameter;
-
- if (rt_mbx_check(queue_id) == 0) { // Check if Queue is full
- return osErrorResource;
- }
-
- isr_mbx_send(queue_id, (void *)info);
-
- return osOK;
-}
-
-/// Get a Message or Wait for a Message from a Queue
-static __INLINE os_InRegs osEvent isrMessageGet (osMessageQId queue_id, uint32_t millisec) {
- OS_RESULT res;
- osEvent ret;
-
- if ((queue_id == NULL) || (millisec != 0)) {
- ret.status = osErrorParameter;
- return ret;
- }
-
- if (((P_MCB)queue_id)->cb_type != MCB) {
- ret.status = osErrorParameter;
- return ret;
- }
-
- res = isr_mbx_receive(queue_id, &ret.value.p);
-
- if (res != OS_R_MBX) {
- ret.status = osOK;
- return ret;
- }
-
- ret.status = osEventMessage;
-
- return ret;
-}
-
-
-// Message Queue Management Public API
-
-/// Create and Initialize Message Queue
-osMessageQId osMessageCreate (osMessageQDef_t *queue_def, osThreadId thread_id) {
- if (__get_IPSR() != 0) return NULL; // Not allowed in ISR
- if (((__get_CONTROL() & 1) == 0) && (os_running == 0)) {
- // Privileged and not running
- return svcMessageCreate(queue_def, thread_id);
- } else {
- return __svcMessageCreate(queue_def, thread_id);
- }
-}
-
-/// Put a Message to a Queue
-osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec) {
- if (__get_IPSR() != 0) { // in ISR
- return isrMessagePut(queue_id, info, millisec);
- } else { // in Thread
- return __svcMessagePut(queue_id, info, millisec);
- }
-}
-
-/// Get a Message or Wait for a Message from a Queue
-os_InRegs osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec) {
- if (__get_IPSR() != 0) { // in ISR
- return isrMessageGet(queue_id, millisec);
- } else { // in Thread
- return __svcMessageGet(queue_id, millisec);
- }
-}
-
-
-// ==== Mail Queue Management Functions ====
-
-// Mail Queue Management Service Calls declarations
-SVC_2_1(svcMailCreate, osMailQId, osMailQDef_t *, osThreadId, RET_pointer)
-SVC_4_1(sysMailAlloc, void *, osMailQId, uint32_t, uint32_t, uint32_t, RET_pointer)
-SVC_3_1(sysMailFree, osStatus, osMailQId, void *, uint32_t, RET_osStatus)
-
-// Mail Queue Management Service & ISR Calls
-
-/// Create and Initialize mail queue
-osMailQId svcMailCreate (osMailQDef_t *queue_def, osThreadId thread_id) {
- uint32_t blk_sz;
- P_MCB pmcb;
- void *pool;
-
- if ((queue_def == NULL) ||
- (queue_def->queue_sz == 0) ||
- (queue_def->item_sz == 0) ||
- (queue_def->pool == NULL)) {
- sysThreadError(osErrorParameter);
- return NULL;
- }
-
- pmcb = *(((void **)queue_def->pool) + 0);
- pool = *(((void **)queue_def->pool) + 1);
-
- if ((pool == NULL) || (pmcb == NULL) || (pmcb->cb_type != 0)) {
- sysThreadError(osErrorParameter);
- return NULL;
- }
-
- blk_sz = (queue_def->item_sz + 3) & ~3;
-
- _init_box(pool, sizeof(struct OS_BM) + queue_def->queue_sz * blk_sz, blk_sz);
-
- rt_mbx_init(pmcb, 4*(queue_def->queue_sz + 4));
-
-
- return queue_def->pool;
-}
-
-/// Allocate a memory block from a mail
-void *sysMailAlloc (osMailQId queue_id, uint32_t millisec, uint32_t isr, uint32_t clr) {
- P_MCB pmcb;
- void *pool;
- void *mem;
-
- if (queue_id == NULL) return NULL;
-
- pmcb = *(((void **)queue_id) + 0);
- pool = *(((void **)queue_id) + 1);
-
- if ((pool == NULL) || (pmcb == NULL)) return NULL;
-
- if (isr && (millisec != 0)) return NULL;
-
- mem = rt_alloc_box(pool);
- if (clr) {
- rt_clr_box(pool, mem);
- }
-
- if ((mem == NULL) && (millisec != 0)) {
- // Put Task to sleep when Memory not available
- if (pmcb->p_lnk != NULL) {
- rt_put_prio((P_XCB)pmcb, os_tsk.run);
- } else {
- pmcb->p_lnk = os_tsk.run;
- os_tsk.run->p_lnk = NULL;
- os_tsk.run->p_rlnk = (P_TCB)pmcb;
- // Task is waiting to allocate a message
- pmcb->state = 3;
- }
- rt_block(rt_ms2tick(millisec), WAIT_MBX);
- }
-
- return mem;
-}
-
-/// Free a memory block from a mail
-osStatus sysMailFree (osMailQId queue_id, void *mail, uint32_t isr) {
- P_MCB pmcb;
- P_TCB ptcb;
- void *pool;
- void *mem;
- int32_t res;
-
- if (queue_id == NULL) return osErrorParameter;
-
- pmcb = *(((void **)queue_id) + 0);
- pool = *(((void **)queue_id) + 1);
-
- if ((pmcb == NULL) || (pool == NULL)) return osErrorParameter;
-
- res = rt_free_box(pool, mail);
-
- if (res != 0) return osErrorValue;
-
- if (pmcb->state == 3) {
- // Task is waiting to allocate a message
- if (isr) {
- rt_psq_enq (pmcb, (U32)pool);
- rt_psh_req ();
- } else {
- mem = rt_alloc_box(pool);
- if (mem != NULL) {
- ptcb = rt_get_first((P_XCB)pmcb);
- if (pmcb->p_lnk == NULL) {
- pmcb->state = 0;
- }
- rt_ret_val(ptcb, (U32)mem);
- rt_rmv_dly(ptcb);
- rt_dispatch(ptcb);
- }
- }
- }
-
- return osOK;
-}
-
-
-// Mail Queue Management Public API
-
-/// Create and Initialize mail queue
-osMailQId osMailCreate (osMailQDef_t *queue_def, osThreadId thread_id) {
- if (__get_IPSR() != 0) return NULL; // Not allowed in ISR
- if (((__get_CONTROL() & 1) == 0) && (os_running == 0)) {
- // Privileged and not running
- return svcMailCreate(queue_def, thread_id);
- } else {
- return __svcMailCreate(queue_def, thread_id);
- }
-}
-
-/// Allocate a memory block from a mail
-void *osMailAlloc (osMailQId queue_id, uint32_t millisec) {
- if (__get_IPSR() != 0) { // in ISR
- return sysMailAlloc(queue_id, millisec, 1, 0);
- } else { // in Thread
- return __sysMailAlloc(queue_id, millisec, 0, 0);
- }
-}
-
-/// Allocate a memory block from a mail and set memory block to zero
-void *osMailCAlloc (osMailQId queue_id, uint32_t millisec) {
- if (__get_IPSR() != 0) { // in ISR
- return sysMailAlloc(queue_id, millisec, 1, 1);
- } else { // in Thread
- return __sysMailAlloc(queue_id, millisec, 0, 1);
- }
-}
-
-/// Free a memory block from a mail
-osStatus osMailFree (osMailQId queue_id, void *mail) {
- if (__get_IPSR() != 0) { // in ISR
- return sysMailFree(queue_id, mail, 1);
- } else { // in Thread
- return __sysMailFree(queue_id, mail, 0);
- }
-}
-
-/// Put a mail to a queue
-osStatus osMailPut (osMailQId queue_id, void *mail) {
- if (queue_id == NULL) return osErrorParameter;
- if (mail == NULL) return osErrorValue;
- return osMessagePut(*((void **)queue_id), (uint32_t)mail, 0);
-}
-
-#ifdef __CC_ARM
-#pragma push
-#pragma Ospace
-#endif // __arm__
-/// Get a mail from a queue
-os_InRegs osEvent osMailGet (osMailQId queue_id, uint32_t millisec) {
- osEvent ret;
-
- if (queue_id == NULL) {
- ret.status = osErrorParameter;
- return ret;
- }
-
- ret = osMessageGet(*((void **)queue_id), millisec);
- if (ret.status == osEventMessage) ret.status = osEventMail;
-
- return ret;
-}
-#ifdef __CC_ARM
-#pragma pop
-#endif // __arm__
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Event.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Event.c
deleted file mode 100644
index acd8ccc..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Event.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RT_EVENT.C
- * Purpose: Implements waits and wake-ups for event flags
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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 "rt_TypeDef.h"
-#include "RTX_Conf.h"
-#include "rt_System.h"
-#include "rt_Event.h"
-#include "rt_List.h"
-#include "rt_Task.h"
-#include "rt_HAL_CM.h"
-
-
-/*----------------------------------------------------------------------------
- * Functions
- *---------------------------------------------------------------------------*/
-
-
-/*--------------------------- rt_evt_wait -----------------------------------*/
-
-OS_RESULT rt_evt_wait (U16 wait_flags, U16 timeout, BOOL and_wait) {
- /* Wait for one or more event flags with optional time-out. */
- /* "wait_flags" identifies the flags to wait for. */
- /* "timeout" is the time-out limit in system ticks (0xffff if no time-out) */
- /* "and_wait" specifies the AND-ing of "wait_flags" as condition to be met */
- /* to complete the wait. (OR-ing if set to 0). */
- U32 block_state;
-
- if (and_wait) {
- /* Check for AND-connected events */
- if ((os_tsk.run->events & wait_flags) == wait_flags) {
- os_tsk.run->events &= ~wait_flags;
- return (OS_R_EVT);
- }
- block_state = WAIT_AND;
- }
- else {
- /* Check for OR-connected events */
- if (os_tsk.run->events & wait_flags) {
- os_tsk.run->waits = os_tsk.run->events & wait_flags;
- os_tsk.run->events &= ~wait_flags;
- return (OS_R_EVT);
- }
- block_state = WAIT_OR;
- }
- /* Task has to wait */
- os_tsk.run->waits = wait_flags;
- rt_block (timeout, (U8)block_state);
- return (OS_R_TMO);
-}
-
-
-/*--------------------------- rt_evt_set ------------------------------------*/
-
-void rt_evt_set (U16 event_flags, OS_TID task_id) {
- /* Set one or more event flags of a selectable task. */
- P_TCB p_tcb;
-
- p_tcb = os_active_TCB[task_id-1];
- if (p_tcb == NULL) {
- return;
- }
- p_tcb->events |= event_flags;
- event_flags = p_tcb->waits;
- /* If the task is not waiting for an event, it should not be put */
- /* to ready state. */
- if (p_tcb->state == WAIT_AND) {
- /* Check for AND-connected events */
- if ((p_tcb->events & event_flags) == event_flags) {
- goto wkup;
- }
- }
- if (p_tcb->state == WAIT_OR) {
- /* Check for OR-connected events */
- if (p_tcb->events & event_flags) {
- p_tcb->waits &= p_tcb->events;
-wkup: p_tcb->events &= ~event_flags;
- rt_rmv_dly (p_tcb);
- p_tcb->state = READY;
-#ifdef __CMSIS_RTOS
- rt_ret_val2(p_tcb, 0x08/*osEventSignal*/, p_tcb->waits);
-#else
- rt_ret_val (p_tcb, OS_R_EVT);
-#endif
- rt_dispatch (p_tcb);
- }
- }
-}
-
-
-/*--------------------------- rt_evt_clr ------------------------------------*/
-
-void rt_evt_clr (U16 clear_flags, OS_TID task_id) {
- /* Clear one or more event flags (identified by "clear_flags") of a */
- /* selectable task (identified by "task"). */
- P_TCB task = os_active_TCB[task_id-1];
-
- if (task == NULL) {
- return;
- }
- task->events &= ~clear_flags;
-}
-
-
-/*--------------------------- isr_evt_set -----------------------------------*/
-
-void isr_evt_set (U16 event_flags, OS_TID task_id) {
- /* Same function as "os_evt_set", but to be called by ISRs. */
- P_TCB p_tcb = os_active_TCB[task_id-1];
-
- if (p_tcb == NULL) {
- return;
- }
- rt_psq_enq (p_tcb, event_flags);
- rt_psh_req ();
-}
-
-
-/*--------------------------- rt_evt_get ------------------------------------*/
-
-U16 rt_evt_get (void) {
- /* Get events of a running task after waiting for OR connected events. */
- return (os_tsk.run->waits);
-}
-
-
-/*--------------------------- rt_evt_psh ------------------------------------*/
-
-void rt_evt_psh (P_TCB p_CB, U16 set_flags) {
- /* Check if task has to be waken up */
- U16 event_flags;
-
- p_CB->events |= set_flags;
- event_flags = p_CB->waits;
- if (p_CB->state == WAIT_AND) {
- /* Check for AND-connected events */
- if ((p_CB->events & event_flags) == event_flags) {
- goto rdy;
- }
- }
- if (p_CB->state == WAIT_OR) {
- /* Check for OR-connected events */
- if (p_CB->events & event_flags) {
- p_CB->waits &= p_CB->events;
-rdy: p_CB->events &= ~event_flags;
- rt_rmv_dly (p_CB);
- p_CB->state = READY;
-#ifdef __CMSIS_RTOS
- rt_ret_val2(p_CB, 0x08/*osEventSignal*/, p_CB->waits);
-#else
- rt_ret_val (p_CB, OS_R_EVT);
-#endif
- rt_put_prio (&os_rdy, p_CB);
- }
- }
-}
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Event.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Event.h
deleted file mode 100644
index 8b92f3c..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Event.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RT_EVENT.H
- * Purpose: Implements waits and wake-ups for event flags
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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.
- *---------------------------------------------------------------------------*/
-
-/* Functions */
-extern OS_RESULT rt_evt_wait (U16 wait_flags, U16 timeout, BOOL and_wait);
-extern void rt_evt_set (U16 event_flags, OS_TID task_id);
-extern void rt_evt_clr (U16 clear_flags, OS_TID task_id);
-extern void isr_evt_set (U16 event_flags, OS_TID task_id);
-extern U16 rt_evt_get (void);
-extern void rt_evt_psh (P_TCB p_CB, U16 set_flags);
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
-
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_HAL_CM.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_HAL_CM.h
deleted file mode 100644
index 2ab4b36..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_HAL_CM.h
+++ /dev/null
@@ -1,276 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RT_HAL_CM.H
- * Purpose: Hardware Abstraction Layer for Cortex-M definitions
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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.
- *---------------------------------------------------------------------------*/
-
-/* Definitions */
-#define INITIAL_xPSR 0x01000000
-#define DEMCR_TRCENA 0x01000000
-#define ITM_ITMENA 0x00000001
-#define MAGIC_WORD 0xE25A2EA5
-
-#if defined (__CC_ARM) /* ARM Compiler */
-
-#if ((__TARGET_ARCH_7_M || __TARGET_ARCH_7E_M) && !NO_EXCLUSIVE_ACCESS)
- #define __USE_EXCLUSIVE_ACCESS
-#else
- #undef __USE_EXCLUSIVE_ACCESS
-#endif
-
-#elif defined (__GNUC__) /* GNU Compiler */
-
-#undef __USE_EXCLUSIVE_ACCESS
-
-#if defined (__CORTEX_M0) || defined (__CORTEX_M0PLUS)
-#define __TARGET_ARCH_6S_M 1
-#else
-#define __TARGET_ARCH_6S_M 0
-#endif
-
-#if defined (__VFP_FP__) && !defined(__SOFTFP__)
-#define __TARGET_FPU_VFP 1
-#else
-#define __TARGET_FPU_VFP 0
-#endif
-
-#define __inline inline
-#define __weak __attribute__((weak))
-
-#ifndef __CMSIS_GENERIC
-
-__attribute__((always_inline)) static inline void __enable_irq(void)
-{
- __asm volatile ("cpsie i");
-}
-
-__attribute__((always_inline)) static inline U32 __disable_irq(void)
-{
- U32 result;
-
- __asm volatile ("mrs %0, primask" : "=r" (result));
- __asm volatile ("cpsid i");
- return(result & 1);
-}
-
-#endif
-
-__attribute__(( always_inline)) static inline U8 __clz(U32 value)
-{
- U8 result;
-
- __asm volatile ("clz %0, %1" : "=r" (result) : "r" (value));
- return(result);
-}
-
-#elif defined (__ICCARM__) /* IAR Compiler */
-
-#undef __USE_EXCLUSIVE_ACCESS
-
-#if (__CORE__ == __ARM6M__)
-#define __TARGET_ARCH_6S_M 1
-#else
-#define __TARGET_ARCH_6S_M 0
-#endif
-
-#if defined __ARMVFP__
-#define __TARGET_FPU_VFP 1
-#else
-#define __TARGET_FPU_VFP 0
-#endif
-
-#define __inline inline
-
-#ifndef __CMSIS_GENERIC
-
-static inline void __enable_irq(void)
-{
- __asm volatile ("cpsie i");
-}
-
-static inline U32 __disable_irq(void)
-{
- U32 result;
-
- __asm volatile ("mrs %0, primask" : "=r" (result));
- __asm volatile ("cpsid i");
- return(result & 1);
-}
-
-#endif
-
-static inline U8 __clz(U32 value)
-{
- U8 result;
-
- __asm volatile ("clz %0, %1" : "=r" (result) : "r" (value));
- return(result);
-}
-
-#endif
-
-/* NVIC registers */
-#define NVIC_ST_CTRL (*((volatile U32 *)0xE000E010))
-#define NVIC_ST_RELOAD (*((volatile U32 *)0xE000E014))
-#define NVIC_ST_CURRENT (*((volatile U32 *)0xE000E018))
-#define NVIC_ISER ((volatile U32 *)0xE000E100)
-#define NVIC_ICER ((volatile U32 *)0xE000E180)
-#if (__TARGET_ARCH_6S_M)
-#define NVIC_IP ((volatile U32 *)0xE000E400)
-#else
-#define NVIC_IP ((volatile U8 *)0xE000E400)
-#endif
-#define NVIC_INT_CTRL (*((volatile U32 *)0xE000ED04))
-#define NVIC_AIR_CTRL (*((volatile U32 *)0xE000ED0C))
-#define NVIC_SYS_PRI2 (*((volatile U32 *)0xE000ED1C))
-#define NVIC_SYS_PRI3 (*((volatile U32 *)0xE000ED20))
-
-#define OS_PEND_IRQ() NVIC_INT_CTRL = (1<<28)
-#define OS_PENDING ((NVIC_INT_CTRL >> 26) & (1<<2 | 1))
-#define OS_UNPEND(fl) NVIC_INT_CTRL = (*fl = OS_PENDING) << 25
-#define OS_PEND(fl,p) NVIC_INT_CTRL = (fl | p<<2) << 26
-#define OS_LOCK() NVIC_ST_CTRL = 0x0005
-#define OS_UNLOCK() NVIC_ST_CTRL = 0x0007
-
-#define OS_X_PENDING ((NVIC_INT_CTRL >> 28) & 1)
-#define OS_X_UNPEND(fl) NVIC_INT_CTRL = (*fl = OS_X_PENDING) << 27
-#define OS_X_PEND(fl,p) NVIC_INT_CTRL = (fl | p) << 28
-#if (__TARGET_ARCH_6S_M)
-#define OS_X_INIT(n) NVIC_IP[n>>2] |= 0xFF << (8*(n & 0x03)); \
- NVIC_ISER[n>>5] = 1 << (n & 0x1F)
-#else
-#define OS_X_INIT(n) NVIC_IP[n] = 0xFF; \
- NVIC_ISER[n>>5] = 1 << (n & 0x1F)
-#endif
-#define OS_X_LOCK(n) NVIC_ICER[n>>5] = 1 << (n & 0x1F)
-#define OS_X_UNLOCK(n) NVIC_ISER[n>>5] = 1 << (n & 0x1F)
-
-/* Core Debug registers */
-#define DEMCR (*((volatile U32 *)0xE000EDFC))
-
-/* ITM registers */
-#define ITM_CONTROL (*((volatile U32 *)0xE0000E80))
-#define ITM_ENABLE (*((volatile U32 *)0xE0000E00))
-#define ITM_PORT30_U32 (*((volatile U32 *)0xE0000078))
-#define ITM_PORT31_U32 (*((volatile U32 *)0xE000007C))
-#define ITM_PORT31_U16 (*((volatile U16 *)0xE000007C))
-#define ITM_PORT31_U8 (*((volatile U8 *)0xE000007C))
-
-/* Variables */
-extern BIT dbg_msg;
-
-/* Functions */
-#ifdef __USE_EXCLUSIVE_ACCESS
- #define rt_inc(p) while(__strex((__ldrex(p)+1),p))
- #define rt_dec(p) while(__strex((__ldrex(p)-1),p))
-#else
- #define rt_inc(p) __disable_irq();(*p)++;__enable_irq();
- #define rt_dec(p) __disable_irq();(*p)--;__enable_irq();
-#endif
-
-__inline static U32 rt_inc_qi (U32 size, U8 *count, U8 *first) {
- U32 cnt,c2;
-#ifdef __USE_EXCLUSIVE_ACCESS
- do {
- if ((cnt = __ldrex(count)) == size) {
- __clrex();
- return (cnt); }
- } while (__strex(cnt+1, count));
- do {
- c2 = (cnt = __ldrex(first)) + 1;
- if (c2 == size) c2 = 0;
- } while (__strex(c2, first));
-#else
- __disable_irq();
- if ((cnt = *count) < size) {
- *count = cnt+1;
- c2 = (cnt = *first) + 1;
- if (c2 == size) c2 = 0;
- *first = c2;
- }
- __enable_irq ();
-#endif
- return (cnt);
-}
-
-__inline static void rt_systick_init (void) {
- NVIC_ST_RELOAD = os_trv;
- NVIC_ST_CURRENT = 0;
- NVIC_ST_CTRL = 0x0007;
- NVIC_SYS_PRI3 |= 0xFF000000;
-}
-
-__inline static void rt_svc_init (void) {
-#if !(__TARGET_ARCH_6S_M)
- int sh,prigroup;
-#endif
- NVIC_SYS_PRI3 |= 0x00FF0000;
-#if (__TARGET_ARCH_6S_M)
- NVIC_SYS_PRI2 |= (NVIC_SYS_PRI3<<(8+1)) & 0xFC000000;
-#else
- sh = 8 - __clz (~((NVIC_SYS_PRI3 << 8) & 0xFF000000));
- prigroup = ((NVIC_AIR_CTRL >> 8) & 0x07);
- if (prigroup >= sh) {
- sh = prigroup + 1;
- }
- NVIC_SYS_PRI2 = ((0xFEFFFFFF << sh) & 0xFF000000) | (NVIC_SYS_PRI2 & 0x00FFFFFF);
-#endif
-}
-
-extern void rt_set_PSP (U32 stack);
-extern U32 rt_get_PSP (void);
-extern void os_set_env (void);
-extern void *_alloc_box (void *box_mem);
-extern int _free_box (void *box_mem, void *box);
-
-extern void rt_init_stack (P_TCB p_TCB, FUNCP task_body);
-extern void rt_ret_val (P_TCB p_TCB, U32 v0);
-extern void rt_ret_val2 (P_TCB p_TCB, U32 v0, U32 v1);
-
-extern void dbg_init (void);
-extern void dbg_task_notify (P_TCB p_tcb, BOOL create);
-extern void dbg_task_switch (U32 task_id);
-
-#ifdef DBG_MSG
-#define DBG_INIT() dbg_init()
-#define DBG_TASK_NOTIFY(p_tcb,create) if (dbg_msg) dbg_task_notify(p_tcb,create)
-#define DBG_TASK_SWITCH(task_id) if (dbg_msg && (os_tsk.new_tsk != os_tsk.run)) \
- dbg_task_switch(task_id)
-#else
-#define DBG_INIT()
-#define DBG_TASK_NOTIFY(p_tcb,create)
-#define DBG_TASK_SWITCH(task_id)
-#endif
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
-
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_List.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_List.c
deleted file mode 100644
index 2134d14..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_List.c
+++ /dev/null
@@ -1,320 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RT_LIST.C
- * Purpose: Functions for the management of different lists
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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 "rt_TypeDef.h"
-#include "RTX_Conf.h"
-#include "rt_System.h"
-#include "rt_List.h"
-#include "rt_Task.h"
-#include "rt_Time.h"
-#include "rt_HAL_CM.h"
-
-/*----------------------------------------------------------------------------
- * Global Variables
- *---------------------------------------------------------------------------*/
-
-/* List head of chained ready tasks */
-struct OS_XCB os_rdy;
-/* List head of chained delay tasks */
-struct OS_XCB os_dly;
-
-
-/*----------------------------------------------------------------------------
- * Functions
- *---------------------------------------------------------------------------*/
-
-
-/*--------------------------- rt_put_prio -----------------------------------*/
-
-void rt_put_prio (P_XCB p_CB, P_TCB p_task) {
- /* Put task identified with "p_task" into list ordered by priority. */
- /* "p_CB" points to head of list; list has always an element at end with */
- /* a priority less than "p_task->prio". */
- P_TCB p_CB2;
- U32 prio;
- BOOL sem_mbx = __FALSE;
-
- if (p_CB->cb_type == SCB || p_CB->cb_type == MCB || p_CB->cb_type == MUCB) {
- sem_mbx = __TRUE;
- }
- prio = p_task->prio;
- p_CB2 = p_CB->p_lnk;
- /* Search for an entry in the list */
- while (p_CB2 != NULL && prio <= p_CB2->prio) {
- p_CB = (P_XCB)p_CB2;
- p_CB2 = p_CB2->p_lnk;
- }
- /* Entry found, insert the task into the list */
- p_task->p_lnk = p_CB2;
- p_CB->p_lnk = p_task;
- if (sem_mbx) {
- if (p_CB2 != NULL) {
- p_CB2->p_rlnk = p_task;
- }
- p_task->p_rlnk = (P_TCB)p_CB;
- }
- else {
- p_task->p_rlnk = NULL;
- }
-}
-
-
-/*--------------------------- rt_get_first ----------------------------------*/
-
-P_TCB rt_get_first (P_XCB p_CB) {
- /* Get task at head of list: it is the task with highest priority. */
- /* "p_CB" points to head of list. */
- P_TCB p_first;
-
- p_first = p_CB->p_lnk;
- p_CB->p_lnk = p_first->p_lnk;
- if (p_CB->cb_type == SCB || p_CB->cb_type == MCB || p_CB->cb_type == MUCB) {
- if (p_first->p_lnk != NULL) {
- p_first->p_lnk->p_rlnk = (P_TCB)p_CB;
- p_first->p_lnk = NULL;
- }
- p_first->p_rlnk = NULL;
- }
- else {
- p_first->p_lnk = NULL;
- }
- return (p_first);
-}
-
-
-/*--------------------------- rt_put_rdy_first ------------------------------*/
-
-void rt_put_rdy_first (P_TCB p_task) {
- /* Put task identified with "p_task" at the head of the ready list. The */
- /* task must have at least a priority equal to highest priority in list. */
- p_task->p_lnk = os_rdy.p_lnk;
- p_task->p_rlnk = NULL;
- os_rdy.p_lnk = p_task;
-}
-
-
-/*--------------------------- rt_get_same_rdy_prio --------------------------*/
-
-P_TCB rt_get_same_rdy_prio (void) {
- /* Remove a task of same priority from ready list if any exists. Other- */
- /* wise return NULL. */
- P_TCB p_first;
-
- p_first = os_rdy.p_lnk;
- if (p_first->prio == os_tsk.run->prio) {
- os_rdy.p_lnk = os_rdy.p_lnk->p_lnk;
- return (p_first);
- }
- return (NULL);
-}
-
-
-/*--------------------------- rt_resort_prio --------------------------------*/
-
-void rt_resort_prio (P_TCB p_task) {
- /* Re-sort ordered lists after the priority of 'p_task' has changed. */
- P_TCB p_CB;
-
- if (p_task->p_rlnk == NULL) {
- if (p_task->state == READY) {
- /* Task is chained into READY list. */
- p_CB = (P_TCB)&os_rdy;
- goto res;
- }
- }
- else {
- p_CB = p_task->p_rlnk;
- while (p_CB->cb_type == TCB) {
- /* Find a header of this task chain list. */
- p_CB = p_CB->p_rlnk;
- }
-res:rt_rmv_list (p_task);
- rt_put_prio ((P_XCB)p_CB, p_task);
- }
-}
-
-
-/*--------------------------- rt_put_dly ------------------------------------*/
-
-void rt_put_dly (P_TCB p_task, U16 delay) {
- /* Put a task identified with "p_task" into chained delay wait list using */
- /* a delay value of "delay". */
- P_TCB p;
- U32 delta,idelay = delay;
-
- p = (P_TCB)&os_dly;
- if (p->p_dlnk == NULL) {
- /* Delay list empty */
- delta = 0;
- goto last;
- }
- delta = os_dly.delta_time;
- while (delta < idelay) {
- if (p->p_dlnk == NULL) {
- /* End of list found */
-last: p_task->p_dlnk = NULL;
- p->p_dlnk = p_task;
- p_task->p_blnk = p;
- p->delta_time = (U16)(idelay - delta);
- p_task->delta_time = 0;
- return;
- }
- p = p->p_dlnk;
- delta += p->delta_time;
- }
- /* Right place found */
- p_task->p_dlnk = p->p_dlnk;
- p->p_dlnk = p_task;
- p_task->p_blnk = p;
- if (p_task->p_dlnk != NULL) {
- p_task->p_dlnk->p_blnk = p_task;
- }
- p_task->delta_time = (U16)(delta - idelay);
- p->delta_time -= p_task->delta_time;
-}
-
-
-/*--------------------------- rt_dec_dly ------------------------------------*/
-
-void rt_dec_dly (void) {
- /* Decrement delta time of list head: remove tasks having a value of zero.*/
- P_TCB p_rdy;
-
- if (os_dly.p_dlnk == NULL) {
- return;
- }
- os_dly.delta_time--;
- while ((os_dly.delta_time == 0) && (os_dly.p_dlnk != NULL)) {
- p_rdy = os_dly.p_dlnk;
- if (p_rdy->p_rlnk != NULL) {
- /* Task is really enqueued, remove task from semaphore/mailbox */
- /* timeout waiting list. */
- p_rdy->p_rlnk->p_lnk = p_rdy->p_lnk;
- if (p_rdy->p_lnk != NULL) {
- p_rdy->p_lnk->p_rlnk = p_rdy->p_rlnk;
- p_rdy->p_lnk = NULL;
- }
- p_rdy->p_rlnk = NULL;
- }
- rt_put_prio (&os_rdy, p_rdy);
- os_dly.delta_time = p_rdy->delta_time;
- if (p_rdy->state == WAIT_ITV) {
- /* Calculate the next time for interval wait. */
- p_rdy->delta_time = p_rdy->interval_time + (U16)os_time;
- }
- p_rdy->state = READY;
- os_dly.p_dlnk = p_rdy->p_dlnk;
- if (p_rdy->p_dlnk != NULL) {
- p_rdy->p_dlnk->p_blnk = (P_TCB)&os_dly;
- p_rdy->p_dlnk = NULL;
- }
- p_rdy->p_blnk = NULL;
- }
-}
-
-
-/*--------------------------- rt_rmv_list -----------------------------------*/
-
-void rt_rmv_list (P_TCB p_task) {
- /* Remove task identified with "p_task" from ready, semaphore or mailbox */
- /* waiting list if enqueued. */
- P_TCB p_b;
-
- if (p_task->p_rlnk != NULL) {
- /* A task is enqueued in semaphore / mailbox waiting list. */
- p_task->p_rlnk->p_lnk = p_task->p_lnk;
- if (p_task->p_lnk != NULL) {
- p_task->p_lnk->p_rlnk = p_task->p_rlnk;
- }
- return;
- }
-
- p_b = (P_TCB)&os_rdy;
- while (p_b != NULL) {
- /* Search the ready list for task "p_task" */
- if (p_b->p_lnk == p_task) {
- p_b->p_lnk = p_task->p_lnk;
- return;
- }
- p_b = p_b->p_lnk;
- }
-}
-
-
-/*--------------------------- rt_rmv_dly ------------------------------------*/
-
-void rt_rmv_dly (P_TCB p_task) {
- /* Remove task identified with "p_task" from delay list if enqueued. */
- P_TCB p_b;
-
- p_b = p_task->p_blnk;
- if (p_b != NULL) {
- /* Task is really enqueued */
- p_b->p_dlnk = p_task->p_dlnk;
- if (p_task->p_dlnk != NULL) {
- /* 'p_task' is in the middle of list */
- p_b->delta_time += p_task->delta_time;
- p_task->p_dlnk->p_blnk = p_b;
- p_task->p_dlnk = NULL;
- }
- else {
- /* 'p_task' is at the end of list */
- p_b->delta_time = 0;
- }
- p_task->p_blnk = NULL;
- }
-}
-
-
-/*--------------------------- rt_psq_enq ------------------------------------*/
-
-void rt_psq_enq (OS_ID entry, U32 arg) {
- /* Insert post service request "entry" into ps-queue. */
- U32 idx;
-
- idx = rt_inc_qi (os_psq->size, &os_psq->count, &os_psq->first);
- if (idx < os_psq->size) {
- os_psq->q[idx].id = entry;
- os_psq->q[idx].arg = arg;
- }
- else {
- os_error (OS_ERR_FIFO_OVF);
- }
-}
-
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
-
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_List.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_List.h
deleted file mode 100644
index cb3008e..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_List.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RT_LIST.H
- * Purpose: Functions for the management of different lists
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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.
- *---------------------------------------------------------------------------*/
-
-/* Definitions */
-
-/* Values for 'cb_type' */
-#define TCB 0
-#define MCB 1
-#define SCB 2
-#define MUCB 3
-#define HCB 4
-
-/* Variables */
-extern struct OS_XCB os_rdy;
-extern struct OS_XCB os_dly;
-
-/* Functions */
-extern void rt_put_prio (P_XCB p_CB, P_TCB p_task);
-extern P_TCB rt_get_first (P_XCB p_CB);
-extern void rt_put_rdy_first (P_TCB p_task);
-extern P_TCB rt_get_same_rdy_prio (void);
-extern void rt_resort_prio (P_TCB p_task);
-extern void rt_put_dly (P_TCB p_task, U16 delay);
-extern void rt_dec_dly (void);
-extern void rt_rmv_list (P_TCB p_task);
-extern void rt_rmv_dly (P_TCB p_task);
-extern void rt_psq_enq (OS_ID entry, U32 arg);
-
-/* This is a fast macro generating in-line code */
-#define rt_rdy_prio(void) (os_rdy.p_lnk->prio)
-
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
-
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mailbox.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mailbox.c
deleted file mode 100644
index ef28b76..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mailbox.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RT_MAILBOX.C
- * Purpose: Implements waits and wake-ups for mailbox messages
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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 "rt_TypeDef.h"
-#include "RTX_Conf.h"
-#include "rt_System.h"
-#include "rt_List.h"
-#include "rt_Mailbox.h"
-#include "rt_MemBox.h"
-#include "rt_Task.h"
-#include "rt_HAL_CM.h"
-
-
-/*----------------------------------------------------------------------------
- * Functions
- *---------------------------------------------------------------------------*/
-
-
-/*--------------------------- rt_mbx_init -----------------------------------*/
-
-void rt_mbx_init (OS_ID mailbox, U16 mbx_size) {
- /* Initialize a mailbox */
- P_MCB p_MCB = mailbox;
-
- p_MCB->cb_type = MCB;
- p_MCB->state = 0;
- p_MCB->isr_st = 0;
- p_MCB->p_lnk = NULL;
- p_MCB->first = 0;
- p_MCB->last = 0;
- p_MCB->count = 0;
- p_MCB->size = (mbx_size + sizeof(void *) - sizeof(struct OS_MCB)) /
- (U32)sizeof (void *);
-}
-
-
-/*--------------------------- rt_mbx_send -----------------------------------*/
-
-OS_RESULT rt_mbx_send (OS_ID mailbox, void *p_msg, U16 timeout) {
- /* Send message to a mailbox */
- P_MCB p_MCB = mailbox;
- P_TCB p_TCB;
-
- if ((p_MCB->p_lnk != NULL) && (p_MCB->state == 1)) {
- /* A task is waiting for message */
- p_TCB = rt_get_first ((P_XCB)p_MCB);
-#ifdef __CMSIS_RTOS
- rt_ret_val2(p_TCB, 0x10/*osEventMessage*/, (U32)p_msg);
-#else
- *p_TCB->msg = p_msg;
- rt_ret_val (p_TCB, OS_R_MBX);
-#endif
- rt_rmv_dly (p_TCB);
- rt_dispatch (p_TCB);
- }
- else {
- /* Store message in mailbox queue */
- if (p_MCB->count == p_MCB->size) {
- /* No free message entry, wait for one. If message queue is full, */
- /* then no task is waiting for message. The 'p_MCB->p_lnk' list */
- /* pointer can now be reused for send message waits task list. */
- if (timeout == 0) {
- return (OS_R_TMO);
- }
- if (p_MCB->p_lnk != NULL) {
- rt_put_prio ((P_XCB)p_MCB, os_tsk.run);
- }
- else {
- p_MCB->p_lnk = os_tsk.run;
- os_tsk.run->p_lnk = NULL;
- os_tsk.run->p_rlnk = (P_TCB)p_MCB;
- /* Task is waiting to send a message */
- p_MCB->state = 2;
- }
- os_tsk.run->msg = p_msg;
- rt_block (timeout, WAIT_MBX);
- return (OS_R_TMO);
- }
- /* Yes, there is a free entry in a mailbox. */
- p_MCB->msg[p_MCB->first] = p_msg;
- rt_inc (&p_MCB->count);
- if (++p_MCB->first == p_MCB->size) {
- p_MCB->first = 0;
- }
- }
- return (OS_R_OK);
-}
-
-
-/*--------------------------- rt_mbx_wait -----------------------------------*/
-
-OS_RESULT rt_mbx_wait (OS_ID mailbox, void **message, U16 timeout) {
- /* Receive a message; possibly wait for it */
- P_MCB p_MCB = mailbox;
- P_TCB p_TCB;
-
- /* If a message is available in the fifo buffer */
- /* remove it from the fifo buffer and return. */
- if (p_MCB->count) {
- *message = p_MCB->msg[p_MCB->last];
- if (++p_MCB->last == p_MCB->size) {
- p_MCB->last = 0;
- }
- if ((p_MCB->p_lnk != NULL) && (p_MCB->state == 2)) {
- /* A task is waiting to send message */
- p_TCB = rt_get_first ((P_XCB)p_MCB);
-#ifdef __CMSIS_RTOS
- rt_ret_val(p_TCB, 0/*osOK*/);
-#else
- rt_ret_val(p_TCB, OS_R_OK);
-#endif
- p_MCB->msg[p_MCB->first] = p_TCB->msg;
- if (++p_MCB->first == p_MCB->size) {
- p_MCB->first = 0;
- }
- rt_rmv_dly (p_TCB);
- rt_dispatch (p_TCB);
- }
- else {
- rt_dec (&p_MCB->count);
- }
- return (OS_R_OK);
- }
- /* No message available: wait for one */
- if (timeout == 0) {
- return (OS_R_TMO);
- }
- if (p_MCB->p_lnk != NULL) {
- rt_put_prio ((P_XCB)p_MCB, os_tsk.run);
- }
- else {
- p_MCB->p_lnk = os_tsk.run;
- os_tsk.run->p_lnk = NULL;
- os_tsk.run->p_rlnk = (P_TCB)p_MCB;
- /* Task is waiting to receive a message */
- p_MCB->state = 1;
- }
- rt_block(timeout, WAIT_MBX);
-#ifndef __CMSIS_RTOS
- os_tsk.run->msg = message;
-#endif
- return (OS_R_TMO);
-}
-
-
-/*--------------------------- rt_mbx_check ----------------------------------*/
-
-OS_RESULT rt_mbx_check (OS_ID mailbox) {
- /* Check for free space in a mailbox. Returns the number of messages */
- /* that can be stored to a mailbox. It returns 0 when mailbox is full. */
- P_MCB p_MCB = mailbox;
-
- return (p_MCB->size - p_MCB->count);
-}
-
-
-/*--------------------------- isr_mbx_send ----------------------------------*/
-
-void isr_mbx_send (OS_ID mailbox, void *p_msg) {
- /* Same function as "os_mbx_send", but to be called by ISRs. */
- P_MCB p_MCB = mailbox;
-
- rt_psq_enq (p_MCB, (U32)p_msg);
- rt_psh_req ();
-}
-
-
-/*--------------------------- isr_mbx_receive -------------------------------*/
-
-OS_RESULT isr_mbx_receive (OS_ID mailbox, void **message) {
- /* Receive a message in the interrupt function. The interrupt function */
- /* should not wait for a message since this would block the rtx os. */
- P_MCB p_MCB = mailbox;
-
- if (p_MCB->count) {
- /* A message is available in the fifo buffer. */
- *message = p_MCB->msg[p_MCB->last];
- if (p_MCB->state == 2) {
- /* A task is locked waiting to send message */
- rt_psq_enq (p_MCB, 0);
- rt_psh_req ();
- }
- rt_dec (&p_MCB->count);
- if (++p_MCB->last == p_MCB->size) {
- p_MCB->last = 0;
- }
- return (OS_R_MBX);
- }
- return (OS_R_OK);
-}
-
-
-/*--------------------------- rt_mbx_psh ------------------------------------*/
-
-void rt_mbx_psh (P_MCB p_CB, void *p_msg) {
- /* Store the message to the mailbox queue or pass it to task directly. */
- P_TCB p_TCB;
- void *mem;
-
- if (p_CB->p_lnk != NULL) switch (p_CB->state) {
-#ifdef __CMSIS_RTOS
- case 3:
- /* Task is waiting to allocate memory, remove it from the waiting list */
- mem = rt_alloc_box(p_msg);
- if (mem == NULL) break;
- p_TCB = rt_get_first ((P_XCB)p_CB);
- rt_ret_val(p_TCB, (U32)mem);
- p_TCB->state = READY;
- rt_rmv_dly (p_TCB);
- rt_put_prio (&os_rdy, p_TCB);
- break;
-#endif
- case 2:
- /* Task is waiting to send a message, remove it from the waiting list */
- p_TCB = rt_get_first ((P_XCB)p_CB);
-#ifdef __CMSIS_RTOS
- rt_ret_val(p_TCB, 0/*osOK*/);
-#else
- rt_ret_val(p_TCB, OS_R_OK);
-#endif
- p_CB->msg[p_CB->first] = p_TCB->msg;
- rt_inc (&p_CB->count);
- if (++p_CB->first == p_CB->size) {
- p_CB->first = 0;
- }
- p_TCB->state = READY;
- rt_rmv_dly (p_TCB);
- rt_put_prio (&os_rdy, p_TCB);
- break;
- case 1:
- /* Task is waiting for a message, pass the message to the task directly */
- p_TCB = rt_get_first ((P_XCB)p_CB);
-#ifdef __CMSIS_RTOS
- rt_ret_val2(p_TCB, 0x10/*osEventMessage*/, (U32)p_msg);
-#else
- *p_TCB->msg = p_msg;
- rt_ret_val (p_TCB, OS_R_MBX);
-#endif
- p_TCB->state = READY;
- rt_rmv_dly (p_TCB);
- rt_put_prio (&os_rdy, p_TCB);
- break;
- } else {
- /* No task is waiting for a message, store it to the mailbox queue */
- if (p_CB->count < p_CB->size) {
- p_CB->msg[p_CB->first] = p_msg;
- rt_inc (&p_CB->count);
- if (++p_CB->first == p_CB->size) {
- p_CB->first = 0;
- }
- }
- else {
- os_error (OS_ERR_MBX_OVF);
- }
- }
-}
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
-
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mailbox.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mailbox.h
deleted file mode 100644
index 0c8e2f3..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mailbox.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RT_MAILBOX.H
- * Purpose: Implements waits and wake-ups for mailbox messages
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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.
- *---------------------------------------------------------------------------*/
-
-/* Functions */
-extern void rt_mbx_init (OS_ID mailbox, U16 mbx_size);
-extern OS_RESULT rt_mbx_send (OS_ID mailbox, void *p_msg, U16 timeout);
-extern OS_RESULT rt_mbx_wait (OS_ID mailbox, void **message, U16 timeout);
-extern OS_RESULT rt_mbx_check (OS_ID mailbox);
-extern void isr_mbx_send (OS_ID mailbox, void *p_msg);
-extern OS_RESULT isr_mbx_receive (OS_ID mailbox, void **message);
-extern void rt_mbx_psh (P_MCB p_CB, void *p_msg);
-
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
-
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_MemBox.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_MemBox.c
deleted file mode 100644
index 5b96ae0..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_MemBox.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RT_MEMBOX.C
- * Purpose: Interface functions for fixed memory block management system
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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 "rt_TypeDef.h"
-#include "RTX_Conf.h"
-#include "rt_System.h"
-#include "rt_MemBox.h"
-#include "rt_HAL_CM.h"
-
-/*----------------------------------------------------------------------------
- * Global Functions
- *---------------------------------------------------------------------------*/
-
-
-/*--------------------------- _init_box -------------------------------------*/
-
-int _init_box (void *box_mem, U32 box_size, U32 blk_size) {
- /* Initialize memory block system, returns 0 if OK, 1 if fails. */
- void *end;
- void *blk;
- void *next;
- U32 sizeof_bm;
-
- /* Create memory structure. */
- if (blk_size & BOX_ALIGN_8) {
- /* Memory blocks 8-byte aligned. */
- blk_size = ((blk_size & ~BOX_ALIGN_8) + 7) & ~7;
- sizeof_bm = (sizeof (struct OS_BM) + 7) & ~7;
- }
- else {
- /* Memory blocks 4-byte aligned. */
- blk_size = (blk_size + 3) & ~3;
- sizeof_bm = sizeof (struct OS_BM);
- }
- if (blk_size == 0) {
- return (1);
- }
- if ((blk_size + sizeof_bm) > box_size) {
- return (1);
- }
- /* Create a Memory structure. */
- blk = ((U8 *) box_mem) + sizeof_bm;
- ((P_BM) box_mem)->free = blk;
- end = ((U8 *) box_mem) + box_size;
- ((P_BM) box_mem)->end = end;
- ((P_BM) box_mem)->blk_size = blk_size;
-
- /* Link all free blocks using offsets. */
- end = ((U8 *) end) - blk_size;
- while (1) {
- next = ((U8 *) blk) + blk_size;
- if (next > end) break;
- *((void **)blk) = next;
- blk = next;
- }
- /* end marker */
- *((void **)blk) = 0;
- return (0);
-}
-
-/*--------------------------- rt_alloc_box ----------------------------------*/
-
-void *rt_alloc_box (void *box_mem) {
- /* Allocate a memory block and return start address. */
- void **free;
-#ifndef __USE_EXCLUSIVE_ACCESS
- int irq_dis;
-
- irq_dis = __disable_irq ();
- free = ((P_BM) box_mem)->free;
- if (free) {
- ((P_BM) box_mem)->free = *free;
- }
- if (!irq_dis) __enable_irq ();
-#else
- do {
- if ((free = (void **)__ldrex(&((P_BM) box_mem)->free)) == 0) {
- __clrex();
- break;
- }
- } while (__strex((U32)*free, &((P_BM) box_mem)->free));
-#endif
- return (free);
-}
-
-
-/*--------------------------- _calloc_box -----------------------------------*/
-
-void *_calloc_box (void *box_mem) {
- /* Allocate a 0-initialized memory block and return start address. */
- void *free;
- U32 *p;
- U32 i;
-
- free = _alloc_box (box_mem);
- if (free) {
- p = free;
- for (i = ((P_BM) box_mem)->blk_size; i; i -= 4) {
- *p = 0;
- p++;
- }
- }
- return (free);
-}
-
-
-/*--------------------------- rt_free_box -----------------------------------*/
-
-int rt_free_box (void *box_mem, void *box) {
- /* Free a memory block, returns 0 if OK, 1 if box does not belong to box_mem */
-#ifndef __USE_EXCLUSIVE_ACCESS
- int irq_dis;
-#endif
-
- if (box < box_mem || box >= ((P_BM) box_mem)->end) {
- return (1);
- }
-
-#ifndef __USE_EXCLUSIVE_ACCESS
- irq_dis = __disable_irq ();
- *((void **)box) = ((P_BM) box_mem)->free;
- ((P_BM) box_mem)->free = box;
- if (!irq_dis) __enable_irq ();
-#else
- do {
- *((void **)box) = (void *)__ldrex(&((P_BM) box_mem)->free);
- } while (__strex ((U32)box, &((P_BM) box_mem)->free));
-#endif
- return (0);
-}
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
-
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_MemBox.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_MemBox.h
deleted file mode 100644
index c10a1cb..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_MemBox.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RT_MEMBOX.H
- * Purpose: Interface functions for fixed memory block management system
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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.
- *---------------------------------------------------------------------------*/
-
-/* Functions */
-#define rt_init_box _init_box
-#define rt_calloc_box _calloc_box
-extern int _init_box (void *box_mem, U32 box_size, U32 blk_size);
-extern void *rt_alloc_box (void *box_mem);
-extern void * _calloc_box (void *box_mem);
-extern int rt_free_box (void *box_mem, void *box);
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
-
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mutex.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mutex.c
deleted file mode 100644
index c7a996b..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mutex.c
+++ /dev/null
@@ -1,197 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RT_MUTEX.C
- * Purpose: Implements mutex synchronization objects
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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 "rt_TypeDef.h"
-#include "RTX_Conf.h"
-#include "rt_List.h"
-#include "rt_Task.h"
-#include "rt_Mutex.h"
-#include "rt_HAL_CM.h"
-
-
-/*----------------------------------------------------------------------------
- * Functions
- *---------------------------------------------------------------------------*/
-
-
-/*--------------------------- rt_mut_init -----------------------------------*/
-
-void rt_mut_init (OS_ID mutex) {
- /* Initialize a mutex object */
- P_MUCB p_MCB = mutex;
-
- p_MCB->cb_type = MUCB;
- p_MCB->prio = 0;
- p_MCB->level = 0;
- p_MCB->p_lnk = NULL;
- p_MCB->owner = NULL;
-}
-
-
-/*--------------------------- rt_mut_delete ---------------------------------*/
-
-#ifdef __CMSIS_RTOS
-OS_RESULT rt_mut_delete (OS_ID mutex) {
- /* Delete a mutex object */
- P_MUCB p_MCB = mutex;
- P_TCB p_TCB;
-
- /* Restore owner task's priority. */
- if (p_MCB->level != 0) {
- p_MCB->owner->prio = p_MCB->prio;
- if (p_MCB->owner != os_tsk.run) {
- rt_resort_prio (p_MCB->owner);
- }
- }
-
- while (p_MCB->p_lnk != NULL) {
- /* A task is waiting for mutex. */
- p_TCB = rt_get_first ((P_XCB)p_MCB);
- rt_ret_val(p_TCB, 0/*osOK*/);
- rt_rmv_dly(p_TCB);
- p_TCB->state = READY;
- rt_put_prio (&os_rdy, p_TCB);
- }
-
- if (os_rdy.p_lnk && (os_rdy.p_lnk->prio > os_tsk.run->prio)) {
- /* preempt running task */
- rt_put_prio (&os_rdy, os_tsk.run);
- os_tsk.run->state = READY;
- rt_dispatch (NULL);
- }
-
- p_MCB->cb_type = 0;
-
- return (OS_R_OK);
-}
-#endif
-
-
-/*--------------------------- rt_mut_release --------------------------------*/
-
-OS_RESULT rt_mut_release (OS_ID mutex) {
- /* Release a mutex object */
- P_MUCB p_MCB = mutex;
- P_TCB p_TCB;
-
- if (p_MCB->level == 0 || p_MCB->owner != os_tsk.run) {
- /* Unbalanced mutex release or task is not the owner */
- return (OS_R_NOK);
- }
- if (--p_MCB->level != 0) {
- return (OS_R_OK);
- }
- /* Restore owner task's priority. */
- os_tsk.run->prio = p_MCB->prio;
- if (p_MCB->p_lnk != NULL) {
- /* A task is waiting for mutex. */
- p_TCB = rt_get_first ((P_XCB)p_MCB);
-#ifdef __CMSIS_RTOS
- rt_ret_val(p_TCB, 0/*osOK*/);
-#else
- rt_ret_val(p_TCB, OS_R_MUT);
-#endif
- rt_rmv_dly (p_TCB);
- /* A waiting task becomes the owner of this mutex. */
- p_MCB->level = 1;
- p_MCB->owner = p_TCB;
- p_MCB->prio = p_TCB->prio;
- /* Priority inversion, check which task continues. */
- if (os_tsk.run->prio >= rt_rdy_prio()) {
- rt_dispatch (p_TCB);
- }
- else {
- /* Ready task has higher priority than running task. */
- rt_put_prio (&os_rdy, os_tsk.run);
- rt_put_prio (&os_rdy, p_TCB);
- os_tsk.run->state = READY;
- p_TCB->state = READY;
- rt_dispatch (NULL);
- }
- }
- else {
- /* Check if own priority raised by priority inversion. */
- if (rt_rdy_prio() > os_tsk.run->prio) {
- rt_put_prio (&os_rdy, os_tsk.run);
- os_tsk.run->state = READY;
- rt_dispatch (NULL);
- }
- }
- return (OS_R_OK);
-}
-
-
-/*--------------------------- rt_mut_wait -----------------------------------*/
-
-OS_RESULT rt_mut_wait (OS_ID mutex, U16 timeout) {
- /* Wait for a mutex, continue when mutex is free. */
- P_MUCB p_MCB = mutex;
-
- if (p_MCB->level == 0) {
- p_MCB->owner = os_tsk.run;
- p_MCB->prio = os_tsk.run->prio;
- goto inc;
- }
- if (p_MCB->owner == os_tsk.run) {
- /* OK, running task is the owner of this mutex. */
-inc:p_MCB->level++;
- return (OS_R_OK);
- }
- /* Mutex owned by another task, wait until released. */
- if (timeout == 0) {
- return (OS_R_TMO);
- }
- /* Raise the owner task priority if lower than current priority. */
- /* This priority inversion is called priority inheritance. */
- if (p_MCB->prio < os_tsk.run->prio) {
- p_MCB->owner->prio = os_tsk.run->prio;
- rt_resort_prio (p_MCB->owner);
- }
- if (p_MCB->p_lnk != NULL) {
- rt_put_prio ((P_XCB)p_MCB, os_tsk.run);
- }
- else {
- p_MCB->p_lnk = os_tsk.run;
- os_tsk.run->p_lnk = NULL;
- os_tsk.run->p_rlnk = (P_TCB)p_MCB;
- }
- rt_block(timeout, WAIT_MUT);
- return (OS_R_TMO);
-}
-
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
-
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mutex.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mutex.h
deleted file mode 100644
index bf15c4d..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Mutex.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RT_MUTEX.H
- * Purpose: Implements mutex synchronization objects
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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.
- *---------------------------------------------------------------------------*/
-
-/* Functions */
-extern void rt_mut_init (OS_ID mutex);
-extern OS_RESULT rt_mut_delete (OS_ID mutex);
-extern OS_RESULT rt_mut_release (OS_ID mutex);
-extern OS_RESULT rt_mut_wait (OS_ID mutex, U16 timeout);
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
-
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Robin.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Robin.c
deleted file mode 100644
index d693dc6..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Robin.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RT_ROBIN.C
- * Purpose: Round Robin Task switching
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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 "rt_TypeDef.h"
-#include "RTX_Conf.h"
-#include "rt_List.h"
-#include "rt_Task.h"
-#include "rt_Time.h"
-#include "rt_Robin.h"
-#include "rt_HAL_CM.h"
-
-/*----------------------------------------------------------------------------
- * Global Variables
- *---------------------------------------------------------------------------*/
-
-struct OS_ROBIN os_robin;
-
-
-/*----------------------------------------------------------------------------
- * Global Functions
- *---------------------------------------------------------------------------*/
-
-/*--------------------------- rt_init_robin ---------------------------------*/
-
-__weak void rt_init_robin (void) {
- /* Initialize Round Robin variables. */
- os_robin.task = NULL;
- os_robin.tout = (U16)os_rrobin;
-}
-
-/*--------------------------- rt_chk_robin ----------------------------------*/
-
-__weak void rt_chk_robin (void) {
- /* Check if Round Robin timeout expired and switch to the next ready task.*/
- P_TCB p_new;
-
- if (os_robin.task != os_rdy.p_lnk) {
- /* New task was suspended, reset Round Robin timeout. */
- os_robin.task = os_rdy.p_lnk;
- os_robin.time = (U16)os_time + os_robin.tout - 1;
- }
- if (os_robin.time == (U16)os_time) {
- /* Round Robin timeout has expired, swap Robin tasks. */
- os_robin.task = NULL;
- p_new = rt_get_first (&os_rdy);
- rt_put_prio ((P_XCB)&os_rdy, p_new);
- }
-}
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
-
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Robin.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Robin.h
deleted file mode 100644
index 3ccbffc..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Robin.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RT_ROBIN.H
- * Purpose: Round Robin Task switching definitions
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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.
- *---------------------------------------------------------------------------*/
-
-/* Variables */
-extern struct OS_ROBIN os_robin;
-
-/* Functions */
-extern void rt_init_robin (void);
-extern void rt_chk_robin (void);
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
-
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Semaphore.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Semaphore.c
deleted file mode 100644
index 93ff2bf..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Semaphore.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RT_SEMAPHORE.C
- * Purpose: Implements binary and counting semaphores
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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 "rt_TypeDef.h"
-#include "RTX_Conf.h"
-#include "rt_System.h"
-#include "rt_List.h"
-#include "rt_Task.h"
-#include "rt_Semaphore.h"
-#include "rt_HAL_CM.h"
-
-
-/*----------------------------------------------------------------------------
- * Functions
- *---------------------------------------------------------------------------*/
-
-
-/*--------------------------- rt_sem_init -----------------------------------*/
-
-void rt_sem_init (OS_ID semaphore, U16 token_count) {
- /* Initialize a semaphore */
- P_SCB p_SCB = semaphore;
-
- p_SCB->cb_type = SCB;
- p_SCB->p_lnk = NULL;
- p_SCB->tokens = token_count;
-}
-
-
-/*--------------------------- rt_sem_delete ---------------------------------*/
-
-#ifdef __CMSIS_RTOS
-OS_RESULT rt_sem_delete (OS_ID semaphore) {
- /* Delete semaphore */
- P_SCB p_SCB = semaphore;
- P_TCB p_TCB;
-
- while (p_SCB->p_lnk != NULL) {
- /* A task is waiting for token */
- p_TCB = rt_get_first ((P_XCB)p_SCB);
- rt_ret_val(p_TCB, 0);
- rt_rmv_dly(p_TCB);
- p_TCB->state = READY;
- rt_put_prio (&os_rdy, p_TCB);
- }
-
- if (os_rdy.p_lnk && (os_rdy.p_lnk->prio > os_tsk.run->prio)) {
- /* preempt running task */
- rt_put_prio (&os_rdy, os_tsk.run);
- os_tsk.run->state = READY;
- rt_dispatch (NULL);
- }
-
- p_SCB->cb_type = 0;
-
- return (OS_R_OK);
-}
-#endif
-
-
-/*--------------------------- rt_sem_send -----------------------------------*/
-
-OS_RESULT rt_sem_send (OS_ID semaphore) {
- /* Return a token to semaphore */
- P_SCB p_SCB = semaphore;
- P_TCB p_TCB;
-
- if (p_SCB->p_lnk != NULL) {
- /* A task is waiting for token */
- p_TCB = rt_get_first ((P_XCB)p_SCB);
-#ifdef __CMSIS_RTOS
- rt_ret_val(p_TCB, 1);
-#else
- rt_ret_val(p_TCB, OS_R_SEM);
-#endif
- rt_rmv_dly (p_TCB);
- rt_dispatch (p_TCB);
- }
- else {
- /* Store token. */
- p_SCB->tokens++;
- }
- return (OS_R_OK);
-}
-
-
-/*--------------------------- rt_sem_wait -----------------------------------*/
-
-OS_RESULT rt_sem_wait (OS_ID semaphore, U16 timeout) {
- /* Obtain a token; possibly wait for it */
- P_SCB p_SCB = semaphore;
-
- if (p_SCB->tokens) {
- p_SCB->tokens--;
- return (OS_R_OK);
- }
- /* No token available: wait for one */
- if (timeout == 0) {
- return (OS_R_TMO);
- }
- if (p_SCB->p_lnk != NULL) {
- rt_put_prio ((P_XCB)p_SCB, os_tsk.run);
- }
- else {
- p_SCB->p_lnk = os_tsk.run;
- os_tsk.run->p_lnk = NULL;
- os_tsk.run->p_rlnk = (P_TCB)p_SCB;
- }
- rt_block(timeout, WAIT_SEM);
- return (OS_R_TMO);
-}
-
-
-/*--------------------------- isr_sem_send ----------------------------------*/
-
-void isr_sem_send (OS_ID semaphore) {
- /* Same function as "os_sem"send", but to be called by ISRs */
- P_SCB p_SCB = semaphore;
-
- rt_psq_enq (p_SCB, 0);
- rt_psh_req ();
-}
-
-
-/*--------------------------- rt_sem_psh ------------------------------------*/
-
-void rt_sem_psh (P_SCB p_CB) {
- /* Check if task has to be waken up */
- P_TCB p_TCB;
-
- if (p_CB->p_lnk != NULL) {
- /* A task is waiting for token */
- p_TCB = rt_get_first ((P_XCB)p_CB);
- rt_rmv_dly (p_TCB);
- p_TCB->state = READY;
-#ifdef __CMSIS_RTOS
- rt_ret_val(p_TCB, 1);
-#else
- rt_ret_val(p_TCB, OS_R_SEM);
-#endif
- rt_put_prio (&os_rdy, p_TCB);
- }
- else {
- /* Store token */
- p_CB->tokens++;
- }
-}
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
-
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Semaphore.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Semaphore.h
deleted file mode 100644
index ec45480..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Semaphore.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RT_SEMAPHORE.H
- * Purpose: Implements binary and counting semaphores
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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.
- *---------------------------------------------------------------------------*/
-
-/* Functions */
-extern void rt_sem_init (OS_ID semaphore, U16 token_count);
-extern OS_RESULT rt_sem_delete(OS_ID semaphore);
-extern OS_RESULT rt_sem_send (OS_ID semaphore);
-extern OS_RESULT rt_sem_wait (OS_ID semaphore, U16 timeout);
-extern void isr_sem_send (OS_ID semaphore);
-extern void rt_sem_psh (P_SCB p_CB);
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
-
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_System.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_System.c
deleted file mode 100644
index f48b67b..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_System.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RT_SYSTEM.C
- * Purpose: System Task Manager
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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 "rt_TypeDef.h"
-#include "RTX_Conf.h"
-#include "rt_Task.h"
-#include "rt_System.h"
-#include "rt_Event.h"
-#include "rt_List.h"
-#include "rt_Mailbox.h"
-#include "rt_Semaphore.h"
-#include "rt_Time.h"
-#include "rt_Robin.h"
-#include "rt_HAL_CM.h"
-
-/*----------------------------------------------------------------------------
- * Global Variables
- *---------------------------------------------------------------------------*/
-
-int os_tick_irqn;
-
-/*----------------------------------------------------------------------------
- * Local Variables
- *---------------------------------------------------------------------------*/
-
-static volatile BIT os_lock;
-static volatile BIT os_psh_flag;
-static U8 pend_flags;
-
-/*----------------------------------------------------------------------------
- * Global Functions
- *---------------------------------------------------------------------------*/
-
-#if defined (__CC_ARM)
-__asm void $$RTX$$version (void) {
- /* Export a version number symbol for a version control. */
-
- EXPORT __RL_RTX_VER
-
-__RL_RTX_VER EQU 0x450
-}
-#endif
-
-
-/*--------------------------- rt_suspend ------------------------------------*/
-U32 rt_suspend (void) {
- /* Suspend OS scheduler */
- U32 delta = 0xFFFF;
-
- rt_tsk_lock();
-
- if (os_dly.p_dlnk) {
- delta = os_dly.delta_time;
- }
-#ifndef __CMSIS_RTOS
- if (os_tmr.next) {
- if (os_tmr.tcnt < delta) delta = os_tmr.tcnt;
- }
-#endif
-
- return (delta);
-}
-
-
-/*--------------------------- rt_resume -------------------------------------*/
-void rt_resume (U32 sleep_time) {
- /* Resume OS scheduler after suspend */
- P_TCB next;
- U32 delta;
-
- os_tsk.run->state = READY;
- rt_put_rdy_first (os_tsk.run);
-
- os_robin.task = NULL;
-
- /* Update delays. */
- if (os_dly.p_dlnk) {
- delta = sleep_time;
- if (delta >= os_dly.delta_time) {
- delta -= os_dly.delta_time;
- os_time += os_dly.delta_time;
- os_dly.delta_time = 1;
- while (os_dly.p_dlnk) {
- rt_dec_dly();
- if (delta == 0) break;
- delta--;
- os_time++;
- }
- } else {
- os_time += delta;
- os_dly.delta_time -= delta;
- }
- } else {
- os_time += sleep_time;
- }
-
-#ifndef __CMSIS_RTOS
- /* Check the user timers. */
- if (os_tmr.next) {
- delta = sleep_time;
- if (delta >= os_tmr.tcnt) {
- delta -= os_tmr.tcnt;
- os_tmr.tcnt = 1;
- while (os_tmr.next) {
- rt_tmr_tick();
- if (delta == 0) break;
- delta--;
- }
- } else {
- os_tmr.tcnt -= delta;
- }
- }
-#endif
-
- /* Switch back to highest ready task */
- next = rt_get_first (&os_rdy);
- rt_switch_req (next);
-
- rt_tsk_unlock();
-}
-
-
-/*--------------------------- rt_tsk_lock -----------------------------------*/
-
-void rt_tsk_lock (void) {
- /* Prevent task switching by locking out scheduler */
- if (os_tick_irqn < 0) {
- OS_LOCK();
- os_lock = __TRUE;
- OS_UNPEND (&pend_flags);
- } else {
- OS_X_LOCK(os_tick_irqn);
- os_lock = __TRUE;
- OS_X_UNPEND (&pend_flags);
- }
-}
-
-
-/*--------------------------- rt_tsk_unlock ---------------------------------*/
-
-void rt_tsk_unlock (void) {
- /* Unlock scheduler and re-enable task switching */
- if (os_tick_irqn < 0) {
- OS_UNLOCK();
- os_lock = __FALSE;
- OS_PEND (pend_flags, os_psh_flag);
- os_psh_flag = __FALSE;
- } else {
- OS_X_UNLOCK(os_tick_irqn);
- os_lock = __FALSE;
- OS_X_PEND (pend_flags, os_psh_flag);
- os_psh_flag = __FALSE;
- }
-}
-
-
-/*--------------------------- rt_psh_req ------------------------------------*/
-
-void rt_psh_req (void) {
- /* Initiate a post service handling request if required. */
- if (os_lock == __FALSE) {
- OS_PEND_IRQ ();
- }
- else {
- os_psh_flag = __TRUE;
- }
-}
-
-
-/*--------------------------- rt_pop_req ------------------------------------*/
-
-void rt_pop_req (void) {
- /* Process an ISR post service requests. */
- struct OS_XCB *p_CB;
- P_TCB next;
- U32 idx;
-
- os_tsk.run->state = READY;
- rt_put_rdy_first (os_tsk.run);
-
- idx = os_psq->last;
- while (os_psq->count) {
- p_CB = os_psq->q[idx].id;
- if (p_CB->cb_type == TCB) {
- /* Is of TCB type */
- rt_evt_psh ((P_TCB)p_CB, (U16)os_psq->q[idx].arg);
- }
- else if (p_CB->cb_type == MCB) {
- /* Is of MCB type */
- rt_mbx_psh ((P_MCB)p_CB, (void *)os_psq->q[idx].arg);
- }
- else {
- /* Must be of SCB type */
- rt_sem_psh ((P_SCB)p_CB);
- }
- if (++idx == os_psq->size) idx = 0;
- rt_dec (&os_psq->count);
- }
- os_psq->last = idx;
-
- next = rt_get_first (&os_rdy);
- rt_switch_req (next);
-}
-
-
-/*--------------------------- os_tick_init ----------------------------------*/
-
-__weak int os_tick_init (void) {
- /* Initialize SysTick timer as system tick timer. */
- rt_systick_init ();
- return (-1); /* Return IRQ number of SysTick timer */
-}
-
-
-/*--------------------------- os_tick_irqack --------------------------------*/
-
-__weak void os_tick_irqack (void) {
- /* Acknowledge timer interrupt. */
-}
-
-
-/*--------------------------- rt_systick ------------------------------------*/
-
-extern void sysTimerTick(void);
-
-void rt_systick (void) {
- /* Check for system clock update, suspend running task. */
- P_TCB next;
-
- os_tsk.run->state = READY;
- rt_put_rdy_first (os_tsk.run);
-
- /* Check Round Robin timeout. */
- rt_chk_robin ();
-
- /* Update delays. */
- os_time++;
- rt_dec_dly ();
-
- /* Check the user timers. */
-#ifdef __CMSIS_RTOS
- sysTimerTick();
-#else
- rt_tmr_tick ();
-#endif
-
- /* Switch back to highest ready task */
- next = rt_get_first (&os_rdy);
- rt_switch_req (next);
-}
-
-/*--------------------------- rt_stk_check ----------------------------------*/
-__weak void rt_stk_check (void) {
- /* Check for stack overflow. */
- if (os_tsk.run->task_id == 0x01) {
- // TODO: For the main thread the check should be done against the main heap pointer
- } else {
- if ((os_tsk.run->tsk_stack < (U32)os_tsk.run->stack) ||
- (os_tsk.run->stack[0] != MAGIC_WORD)) {
- os_error (OS_ERR_STK_OVF);
- }
- }
-}
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
-
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_System.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_System.h
deleted file mode 100644
index 91db648..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_System.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RT_SYSTEM.H
- * Purpose: System Task Manager definitions
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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.
- *---------------------------------------------------------------------------*/
-
-/* Variables */
-#define os_psq ((P_PSQ)&os_fifo)
-extern int os_tick_irqn;
-
-/* Functions */
-extern U32 rt_suspend (void);
-extern void rt_resume (U32 sleep_time);
-extern void rt_tsk_lock (void);
-extern void rt_tsk_unlock (void);
-extern void rt_psh_req (void);
-extern void rt_pop_req (void);
-extern void rt_systick (void);
-extern void rt_stk_check (void);
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
-
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Task.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Task.c
deleted file mode 100644
index 518f78f..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Task.c
+++ /dev/null
@@ -1,339 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RT_TASK.C
- * Purpose: Task functions and system start up.
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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 "rt_TypeDef.h"
-#include "RTX_Conf.h"
-#include "rt_System.h"
-#include "rt_Task.h"
-#include "rt_List.h"
-#include "rt_MemBox.h"
-#include "rt_Robin.h"
-#include "rt_HAL_CM.h"
-
-/*----------------------------------------------------------------------------
- * Global Variables
- *---------------------------------------------------------------------------*/
-
-/* Running and next task info. */
-struct OS_TSK os_tsk;
-
-/* Task Control Blocks of idle demon */
-struct OS_TCB os_idle_TCB;
-
-
-/*----------------------------------------------------------------------------
- * Local Functions
- *---------------------------------------------------------------------------*/
-
-OS_TID rt_get_TID (void) {
- U32 tid;
-
- for (tid = 1; tid <= os_maxtaskrun; tid++) {
- if (os_active_TCB[tid-1] == NULL) {
- return ((OS_TID)tid);
- }
- }
- return (0);
-}
-
-#if defined (__CC_ARM) && !defined (__MICROLIB)
-/*--------------------------- __user_perthread_libspace ---------------------*/
-extern void *__libspace_start;
-
-void *__user_perthread_libspace (void) {
- /* Provide a separate libspace for each task. */
- if (os_tsk.run == NULL) {
- /* RTX not running yet. */
- return (&__libspace_start);
- }
- return (void *)(os_tsk.run->std_libspace);
-}
-#endif
-
-/*--------------------------- rt_init_context -------------------------------*/
-
-void rt_init_context (P_TCB p_TCB, U8 priority, FUNCP task_body) {
- /* Initialize general part of the Task Control Block. */
- p_TCB->cb_type = TCB;
- p_TCB->state = READY;
- p_TCB->prio = priority;
- p_TCB->p_lnk = NULL;
- p_TCB->p_rlnk = NULL;
- p_TCB->p_dlnk = NULL;
- p_TCB->p_blnk = NULL;
- p_TCB->delta_time = 0;
- p_TCB->interval_time = 0;
- p_TCB->events = 0;
- p_TCB->waits = 0;
- p_TCB->stack_frame = 0;
-
- rt_init_stack (p_TCB, task_body);
-}
-
-
-/*--------------------------- rt_switch_req ---------------------------------*/
-
-void rt_switch_req (P_TCB p_new) {
- /* Switch to next task (identified by "p_new"). */
- os_tsk.new_tsk = p_new;
- p_new->state = RUNNING;
- DBG_TASK_SWITCH(p_new->task_id);
-}
-
-
-/*--------------------------- rt_dispatch -----------------------------------*/
-
-void rt_dispatch (P_TCB next_TCB) {
- /* Dispatch next task if any identified or dispatch highest ready task */
- /* "next_TCB" identifies a task to run or has value NULL (=no next task) */
- if (next_TCB == NULL) {
- /* Running task was blocked: continue with highest ready task */
- next_TCB = rt_get_first (&os_rdy);
- rt_switch_req (next_TCB);
- }
- else {
- /* Check which task continues */
- if (next_TCB->prio > os_tsk.run->prio) {
- /* preempt running task */
- rt_put_rdy_first (os_tsk.run);
- os_tsk.run->state = READY;
- rt_switch_req (next_TCB);
- }
- else {
- /* put next task into ready list, no task switch takes place */
- next_TCB->state = READY;
- rt_put_prio (&os_rdy, next_TCB);
- }
- }
-}
-
-
-/*--------------------------- rt_block --------------------------------------*/
-
-void rt_block (U16 timeout, U8 block_state) {
- /* Block running task and choose next ready task. */
- /* "timeout" sets a time-out value or is 0xffff (=no time-out). */
- /* "block_state" defines the appropriate task state */
- P_TCB next_TCB;
-
- if (timeout) {
- if (timeout < 0xffff) {
- rt_put_dly (os_tsk.run, timeout);
- }
- os_tsk.run->state = block_state;
- next_TCB = rt_get_first (&os_rdy);
- rt_switch_req (next_TCB);
- }
-}
-
-
-/*--------------------------- rt_tsk_pass -----------------------------------*/
-
-void rt_tsk_pass (void) {
- /* Allow tasks of same priority level to run cooperatively.*/
- P_TCB p_new;
-
- p_new = rt_get_same_rdy_prio();
- if (p_new != NULL) {
- rt_put_prio ((P_XCB)&os_rdy, os_tsk.run);
- os_tsk.run->state = READY;
- rt_switch_req (p_new);
- }
-}
-
-
-/*--------------------------- rt_tsk_self -----------------------------------*/
-
-OS_TID rt_tsk_self (void) {
- /* Return own task identifier value. */
- if (os_tsk.run == NULL) {
- return (0);
- }
- return (os_tsk.run->task_id);
-}
-
-
-/*--------------------------- rt_tsk_prio -----------------------------------*/
-
-OS_RESULT rt_tsk_prio (OS_TID task_id, U8 new_prio) {
- /* Change execution priority of a task to "new_prio". */
- P_TCB p_task;
-
- if (task_id == 0) {
- /* Change execution priority of calling task. */
- os_tsk.run->prio = new_prio;
-run:if (rt_rdy_prio() > new_prio) {
- rt_put_prio (&os_rdy, os_tsk.run);
- os_tsk.run->state = READY;
- rt_dispatch (NULL);
- }
- return (OS_R_OK);
- }
-
- /* Find the task in the "os_active_TCB" array. */
- if (task_id > os_maxtaskrun || os_active_TCB[task_id-1] == NULL) {
- /* Task with "task_id" not found or not started. */
- return (OS_R_NOK);
- }
- p_task = os_active_TCB[task_id-1];
- p_task->prio = new_prio;
- if (p_task == os_tsk.run) {
- goto run;
- }
- rt_resort_prio (p_task);
- if (p_task->state == READY) {
- /* Task enqueued in a ready list. */
- p_task = rt_get_first (&os_rdy);
- rt_dispatch (p_task);
- }
- return (OS_R_OK);
-}
-
-/*--------------------------- rt_tsk_delete ---------------------------------*/
-
-OS_RESULT rt_tsk_delete (OS_TID task_id) {
- /* Terminate the task identified with "task_id". */
- P_TCB task_context;
-
- if (task_id == 0 || task_id == os_tsk.run->task_id) {
- /* Terminate itself. */
- os_tsk.run->state = INACTIVE;
- os_tsk.run->tsk_stack = rt_get_PSP ();
- rt_stk_check ();
- os_active_TCB[os_tsk.run->task_id-1] = NULL;
-
- os_tsk.run->stack = NULL;
- DBG_TASK_NOTIFY(os_tsk.run, __FALSE);
- os_tsk.run = NULL;
- rt_dispatch (NULL);
- /* The program should never come to this point. */
- }
- else {
- /* Find the task in the "os_active_TCB" array. */
- if (task_id > os_maxtaskrun || os_active_TCB[task_id-1] == NULL) {
- /* Task with "task_id" not found or not started. */
- return (OS_R_NOK);
- }
- task_context = os_active_TCB[task_id-1];
- rt_rmv_list (task_context);
- rt_rmv_dly (task_context);
- os_active_TCB[task_id-1] = NULL;
-
- task_context->stack = NULL;
- DBG_TASK_NOTIFY(task_context, __FALSE);
- }
- return (OS_R_OK);
-}
-
-
-/*--------------------------- rt_sys_init -----------------------------------*/
-
-#ifdef __CMSIS_RTOS
-void rt_sys_init (void) {
-#else
-void rt_sys_init (FUNCP first_task, U32 prio_stksz, void *stk) {
-#endif
- /* Initialize system and start up task declared with "first_task". */
- U32 i;
-
- DBG_INIT();
-
- /* Initialize dynamic memory and task TCB pointers to NULL. */
- for (i = 0; i < os_maxtaskrun; i++) {
- os_active_TCB[i] = NULL;
- }
-
- /* Set up TCB of idle demon */
- os_idle_TCB.task_id = 255;
- os_idle_TCB.priv_stack = idle_task_stack_size;
- os_idle_TCB.stack = idle_task_stack;
- rt_init_context (&os_idle_TCB, 0, os_idle_demon);
-
- /* Set up ready list: initially empty */
- os_rdy.cb_type = HCB;
- os_rdy.p_lnk = NULL;
- /* Set up delay list: initially empty */
- os_dly.cb_type = HCB;
- os_dly.p_dlnk = NULL;
- os_dly.p_blnk = NULL;
- os_dly.delta_time = 0;
-
- /* Fix SP and systemvariables to assume idle task is running */
- /* Transform main program into idle task by assuming idle TCB */
-#ifndef __CMSIS_RTOS
- rt_set_PSP (os_idle_TCB.tsk_stack+32);
-#endif
- os_tsk.run = &os_idle_TCB;
- os_tsk.run->state = RUNNING;
-
- /* Initialize ps queue */
- os_psq->first = 0;
- os_psq->last = 0;
- os_psq->size = os_fifo_size;
-
- rt_init_robin ();
-
- /* Intitialize SVC and PendSV */
- rt_svc_init ();
-
-#ifndef __CMSIS_RTOS
- /* Intitialize and start system clock timer */
- os_tick_irqn = os_tick_init ();
- if (os_tick_irqn >= 0) {
- OS_X_INIT(os_tick_irqn);
- }
-
- /* Start up first user task before entering the endless loop */
- rt_tsk_create (first_task, prio_stksz, stk, NULL);
-#endif
-}
-
-
-/*--------------------------- rt_sys_start ----------------------------------*/
-
-#ifdef __CMSIS_RTOS
-void rt_sys_start (void) {
- /* Start system */
-
- /* Intitialize and start system clock timer */
- os_tick_irqn = os_tick_init ();
- if (os_tick_irqn >= 0) {
- OS_X_INIT(os_tick_irqn);
- }
-}
-#endif
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Task.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Task.h
deleted file mode 100644
index 9d3727b..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Task.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RT_TASK.H
- * Purpose: Task functions and system start up.
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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.
- *---------------------------------------------------------------------------*/
-
-/* Definitions */
-#define __CMSIS_RTOS 1
-
-/* Values for 'state' */
-#define INACTIVE 0
-#define READY 1
-#define RUNNING 2
-#define WAIT_DLY 3
-#define WAIT_ITV 4
-#define WAIT_OR 5
-#define WAIT_AND 6
-#define WAIT_SEM 7
-#define WAIT_MBX 8
-#define WAIT_MUT 9
-
-/* Return codes */
-#define OS_R_TMO 0x01
-#define OS_R_EVT 0x02
-#define OS_R_SEM 0x03
-#define OS_R_MBX 0x04
-#define OS_R_MUT 0x05
-
-#define OS_R_OK 0x00
-#define OS_R_NOK 0xff
-
-/* Variables */
-extern struct OS_TSK os_tsk;
-extern struct OS_TCB os_idle_TCB;
-
-/* Functions */
-extern void rt_switch_req (P_TCB p_new);
-extern void rt_dispatch (P_TCB next_TCB);
-extern void rt_block (U16 timeout, U8 block_state);
-extern void rt_tsk_pass (void);
-extern OS_TID rt_tsk_self (void);
-extern OS_RESULT rt_tsk_prio (OS_TID task_id, U8 new_prio);
-extern OS_RESULT rt_tsk_delete (OS_TID task_id);
-extern void rt_sys_init (void);
-extern void rt_sys_start (void);
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Time.c b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Time.c
deleted file mode 100644
index b02cceb..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Time.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RT_TIME.C
- * Purpose: Delay and interval wait functions
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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 "rt_TypeDef.h"
-#include "RTX_Conf.h"
-#include "rt_Task.h"
-#include "rt_Time.h"
-
-/*----------------------------------------------------------------------------
- * Global Variables
- *---------------------------------------------------------------------------*/
-
-/* Free running system tick counter */
-U32 os_time;
-
-
-/*----------------------------------------------------------------------------
- * Functions
- *---------------------------------------------------------------------------*/
-
-
-/*--------------------------- rt_time_get -----------------------------------*/
-
-U32 rt_time_get (void) {
- /* Get system time tick */
- return (os_time);
-}
-
-
-/*--------------------------- rt_dly_wait -----------------------------------*/
-
-void rt_dly_wait (U16 delay_time) {
- /* Delay task by "delay_time" */
- rt_block (delay_time, WAIT_DLY);
-}
-
-
-/*--------------------------- rt_itv_set ------------------------------------*/
-
-void rt_itv_set (U16 interval_time) {
- /* Set interval length and define start of first interval */
- os_tsk.run->interval_time = interval_time;
- os_tsk.run->delta_time = interval_time + (U16)os_time;
-}
-
-
-/*--------------------------- rt_itv_wait -----------------------------------*/
-
-void rt_itv_wait (void) {
- /* Wait for interval end and define start of next one */
- U16 delta;
-
- delta = os_tsk.run->delta_time - (U16)os_time;
- os_tsk.run->delta_time += os_tsk.run->interval_time;
- if ((delta & 0x8000) == 0) {
- rt_block (delta, WAIT_ITV);
- }
-}
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
-
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Time.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Time.h
deleted file mode 100644
index 2770637..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_Time.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RT_TIME.H
- * Purpose: Delay and interval wait functions definitions
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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.
- *---------------------------------------------------------------------------*/
-
-/* Variables */
-extern U32 os_time;
-
-/* Functions */
-extern U32 rt_time_get (void);
-extern void rt_dly_wait (U16 delay_time);
-extern void rt_itv_set (U16 interval_time);
-extern void rt_itv_wait (void);
-
-/*----------------------------------------------------------------------------
- * end of file
- *---------------------------------------------------------------------------*/
-
diff --git a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_TypeDef.h b/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_TypeDef.h
deleted file mode 100644
index 27416c5..0000000
--- a/libraries/mbed/rtos/rtx/TARGET_CORTEX_M/rt_TypeDef.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*----------------------------------------------------------------------------
- * RL-ARM - RTX
- *----------------------------------------------------------------------------
- * Name: RT_TYPEDEF.H
- * Purpose: Type Definitions
- * Rev.: V4.60
- *----------------------------------------------------------------------------
- *
- * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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 RT_TYPE_DEF_H
-#define RT_TYPE_DEF_H
-
-#include "os_tcb.h"
-
-typedef U32 OS_TID;
-typedef void *OS_ID;
-typedef U32 OS_RESULT;
-
-#define TCB_STACKF 32 /* 'stack_frame' offset */
-#define TCB_TSTACK 40 /* 'tsk_stack' offset */
-
-typedef struct OS_PSFE { /* Post Service Fifo Entry */
- void *id; /* Object Identification */
- U32 arg; /* Object Argument */
-} *P_PSFE;
-
-typedef struct OS_PSQ { /* Post Service Queue */
- U8 first; /* FIFO Head Index */
- U8 last; /* FIFO Tail Index */
- U8 count; /* Number of stored items in FIFO */
- U8 size; /* FIFO Size */
- struct OS_PSFE q[1]; /* FIFO Content */
-} *P_PSQ;
-
-typedef struct OS_TSK {
- P_TCB run; /* Current running task */
- P_TCB new_tsk; /* Scheduled task to run */
-} *P_TSK;
-
-typedef struct OS_ROBIN { /* Round Robin Control */
- P_TCB task; /* Round Robin task */
- U16 time; /* Round Robin switch time */
- U16 tout; /* Round Robin timeout */
-} *P_ROBIN;
-
-typedef struct OS_XCB {
- U8 cb_type; /* Control Block Type */
- struct OS_TCB *p_lnk; /* Link pointer for ready/sem. wait list */
- struct OS_TCB *p_rlnk; /* Link pointer for sem./mbx lst backwards */
- struct OS_TCB *p_dlnk; /* Link pointer for delay list */
- struct OS_TCB *p_blnk; /* Link pointer for delay list backwards */
- U16 delta_time; /* Time until time out */
-} *P_XCB;
-
-typedef struct OS_MCB {
- U8 cb_type; /* Control Block Type */
- U8 state; /* State flag variable */
- U8 isr_st; /* State flag variable for isr functions */
- struct OS_TCB *p_lnk; /* Chain of tasks waiting for message */
- U16 first; /* Index of the message list begin */
- U16 last; /* Index of the message list end */
- U16 count; /* Actual number of stored messages */
- U16 size; /* Maximum number of stored messages */
- void *msg[1]; /* FIFO for Message pointers 1st element */
-} *P_MCB;
-
-typedef struct OS_SCB {
- U8 cb_type; /* Control Block Type */
- U8 mask; /* Semaphore token mask */
- U16 tokens; /* Semaphore tokens */
- struct OS_TCB *p_lnk; /* Chain of tasks waiting for tokens */
-} *P_SCB;
-
-typedef struct OS_MUCB {
- U8 cb_type; /* Control Block Type */
- U8 prio; /* Owner task default priority */
- U16 level; /* Call nesting level */
- struct OS_TCB *p_lnk; /* Chain of tasks waiting for mutex */
- struct OS_TCB *owner; /* Mutex owner task */
-} *P_MUCB;
-
-typedef struct OS_XTMR {
- struct OS_TMR *next;
- U16 tcnt;
-} *P_XTMR;
-
-typedef struct OS_TMR {
- struct OS_TMR *next; /* Link pointer to Next timer */
- U16 tcnt; /* Timer delay count */
- U16 info; /* User defined call info */
-} *P_TMR;
-
-typedef struct OS_BM {
- void *free; /* Pointer to first free memory block */
- void *end; /* Pointer to memory block end */
- U32 blk_size; /* Memory block size */
-} *P_BM;
-
-/* Definitions */
-#define __TRUE 1
-#define __FALSE 0
-#define NULL ((void *) 0)
-
-#endif
diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/STM32F429BI.ld b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/STM32F429BI.ld
index ad7ddaf..29ddfcf 100644
--- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/STM32F429BI.ld
+++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/STM32F429BI.ld
@@ -10,9 +10,11 @@ MEMORY
BOOTLOADER (rx) : ORIGIN = 0x08000000, LENGTH = 128K
FIRMWARE (rx) : ORIGIN = 0x08000000 + 128K, LENGTH = 2048K - 128K
FLASH (rx) : ORIGIN = 0x08000000 + 128K, LENGTH = 2048K - 128K
- RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 192K - 4
+ CCMRAM (rwx) : ORIGIN = 0x10000000, LENGTH = 64K
+ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 192K - 4
+ SDRAM1 (rwx) : ORIGIN = 0xC0000000, LENGTH = 64M
+ SDRAM2 (rwx) : ORIGIN = 0xD0000000, LENGTH = 64M
}
-/* original: FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K */
/* Linker script to place sections and symbol values. Should be used together
* with other linker script that defines memory regions FLASH and RAM.
@@ -86,7 +88,7 @@ SECTIONS
__etext = .;
_sidata = .;
- .data : AT (__etext)
+ .data :
{
__data_start__ = .;
_sdata = .;
@@ -120,7 +122,49 @@ SECTIONS
__data_end__ = .;
_edata = .;
- } > RAM
+ } > RAM AT> FLASH
+
+ /* If initialized variables are placed in this section,
+ * the startup code needs to be modified to copy the init-values.
+ */
+ .ccmram :
+ {
+ . = ALIGN(4);
+ _sccmram = .;
+ *(.ccmram)
+ *(.ccmram*)
+
+ . = ALIGN(4);
+ _eccmram = .;
+ } >CCMRAM AT> FLASH
+
+ __end_ccmram = ORIGIN(CCMRAM) + LENGTH(CCMRAM);
+
+ .sdram1 :
+ {
+ . = ALIGN(4);
+ _ssdram1 = .;
+ *(.sdram1)
+ *(.sdram1*)
+
+ . = ALIGN(4);
+ _esdram1 = .;
+ } >SDRAM1
+
+ __end_sdram1 = ORIGIN(SDRAM1) + LENGTH(SDRAM1);
+
+ .sdram2 :
+ {
+ . = ALIGN(4);
+ _ssdram2 = .;
+ *(.sdram2)
+ *(.sdram2*)
+
+ . = ALIGN(4);
+ _esdram2 = .;
+ } >SDRAM2
+
+ __end_sdram2 = ORIGIN(SDRAM2) + LENGTH(SDRAM2);
.bss :
{
diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/startup_stm32f429xx.S b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/startup_stm32f429xx.S
index c431df8..7b4f6ff 100644
--- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/startup_stm32f429xx.S
+++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/startup_stm32f429xx.S
@@ -110,14 +110,9 @@ LoopFillZerobss:
/* Call the clock system intitialization function.*/
bl SystemInit
/* Call static constructors */
- //bl __libc_init_array
+ bl __libc_init_array
/* Call the application's entry point.*/
- //bl main
- // Calling the crt0 'cold-start' entry point. There __libc_init_array is called
- // and when existing hardware_init_hook() and software_init_hook() before
- // starting main(). software_init_hook() is available and has to be called due
- // to initializsation when using rtos.
- bl _start
+ bl main
bx lr
.size Reset_Handler, .-Reset_Handler
diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h
index 8a11b8b..50e70d5 100644
--- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h
+++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h
@@ -145,7 +145,7 @@
* @brief This is the HAL system configuration section
*/
#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */
-#define TICK_INT_PRIORITY ((uint32_t)0) /*!< tick interrupt priority */
+#define TICK_INT_PRIORITY ((uint32_t)0x0F) /*!< tick interrupt priority */
#define USE_RTOS 0
#define PREFETCH_ENABLE 1
#define INSTRUCTION_CACHE_ENABLE 1
diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c
index fbd0adf..f64e6ce 100644
--- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c
+++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c
@@ -44,16 +44,6 @@ void HAL_MspInit(void)
/* USER CODE END MspInit 0 */
- /* XXX
- * Fredrik's HAL_MspInit sets this to NVIC_PRIORITYGROUP_4 (as just
- * happened in HAL_Init), but then he resets it to NVIC_PRIORITYGROUP_0
- * in stm_init. */
- HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0);
-
- /* System interrupt init*/
- /* SysTick_IRQn interrupt configuration */
- HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
-
/* USER CODE BEGIN MspInit 1 */
/* USER CODE END MspInit 1 */
@@ -97,19 +87,23 @@ void HAL_RNG_MspDeInit(RNG_HandleTypeDef* hrng)
void HAL_SRAM_MspInit(SRAM_HandleTypeDef* hsram)
{
+ hsram = hsram;
}
void HAL_SRAM_MspDeInit(SRAM_HandleTypeDef* hsram)
{
+ hsram = hsram;
}
void HAL_SDRAM_MspInit(SDRAM_HandleTypeDef* hsdram)
{
+ hsdram = hsdram;
}
void HAL_SDRAM_MspDeInit(SDRAM_HandleTypeDef* hsdram)
{
+ hsdram = hsdram;
}
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
@@ -182,7 +176,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart)
hdma->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma->Init.Mode = DMA_CIRCULAR;
- hdma->Init.Priority = DMA_PRIORITY_LOW;
+ hdma->Init.Priority = DMA_PRIORITY_HIGH;
hdma->Init.FIFOMode = DMA_FIFOMODE_DISABLE;
/*
hdma->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
@@ -190,6 +184,7 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart)
hdma->Init.PeriphBurst = DMA_PBURST_SINGLE;
*/
if (HAL_DMA_Init(hdma) != HAL_OK) {
+ extern void mbed_die(void);
mbed_die();
}
}
diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_it.c b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_it.c
index 7c30228..d3bafb2 100644
--- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_it.c
+++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_it.c
@@ -44,20 +44,6 @@
/* Cortex-M4 Processor Exceptions Handlers */
/******************************************************************************/
-/*
- * We define these to make debugging easier, because otherwise gdb reports
- * HardFault_Handler as WWDG_IRQHandler.
- */
-
-/**
- * @brief This function handles NMI exception.
- * @param None
- * @retval None
- */
-void NMI_Handler(void)
-{
-}
-
/**
* @brief This function handles Hard Fault exception.
* @param None
@@ -65,72 +51,19 @@ void NMI_Handler(void)
*/
void HardFault_Handler(void)
{
- /* Go to infinite loop when Hard Fault exception occurs */
- while (1) { ; }
-}
-
-/**
- * @brief This function handles Memory Manage exception.
- * @param None
- * @retval None
- */
-void MemManage_Handler(void)
-{
- /* Go to infinite loop when Memory Manage exception occurs */
- while (1) { ; }
-}
-
-/**
- * @brief This function handles Bus Fault exception.
- * @param None
- * @retval None
+/*
+ * We define this to make debugging easier, because otherwise gdb reports
+ * HardFault_Handler as WWDG_IRQHandler.
*/
-void BusFault_Handler(void)
-{
- /* Go to infinite loop when Bus Fault exception occurs */
- while (1) { ; }
-}
-/**
- * @brief This function handles Usage Fault exception.
- * @param None
- * @retval None
- */
-void UsageFault_Handler(void)
-{
- /* Go to infinite loop when Usage Fault exception occurs */
+#ifdef HAL_GPIO_MODULE_ENABLED
+ //HAL_GPIO_WritePin(LED_PORT, LED_RED, GPIO_PIN_SET);
+ HAL_GPIO_WritePin(GPIOK, GPIO_PIN_7, GPIO_PIN_SET);
+#endif
+ /* Go to infinite loop when Hard Fault exception occurs */
while (1) { ; }
}
-
-#if 0 /* already defined in libraries/mbed/rtos/ */
-/**
- * @brief This function handles SVCall exception.
- * @param None
- * @retval None
- */
-void SVC_Handler(void)
-{
-}
-
-/**
- * @brief This function handles Debug Monitor exception.
- * @param None
- * @retval None
- */
-void DebugMon_Handler(void)
-{
-}
-
-/**
- * @brief This function handles PendSVC exception.
- * @param None
- * @retval None
- */
-void PendSV_Handler(void)
-{
-}
-
/**
* @brief This function handles SysTick Handler.
* @param None
@@ -139,8 +72,8 @@ void PendSV_Handler(void)
void SysTick_Handler(void)
{
HAL_IncTick();
+ HAL_SYSTICK_IRQHandler();
}
-#endif
/******************************************************************************/
/* STM32F4xx Peripherals Interrupt Handlers */
@@ -187,6 +120,12 @@ void USART2_IRQHandler(void)
HAL_UART_IRQHandler(&huart_user);
}
+/**
+ * @brief Rx Transfer completed callbacks.
+ * @param huart: pointer to a UART_HandleTypeDef structure that contains
+ * the configuration information for the specified UART module.
+ * @retval None
+ */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
extern void HAL_UART1_RxCpltCallback(UART_HandleTypeDef *huart);
@@ -199,24 +138,62 @@ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
HAL_UART2_RxCpltCallback(huart);
}
+__weak void HAL_UART1_RxCpltCallback(UART_HandleTypeDef *huart)
+{
+ /* NOTE: This function Should not be modified, when the callback is needed,
+ the HAL_UART1_RxCpltCallback could be implemented in the user file
+ */
+ huart = huart;
+}
+
+__weak void HAL_UART2_RxCpltCallback(UART_HandleTypeDef *huart)
+{
+ /* NOTE: This function Should not be modified, when the callback is needed,
+ the HAL_UART2_RxCpltCallback could be implemented in the user file
+ */
+ huart = huart;
+}
+
/**
- * @brief Rx Transfer completed callbacks.
+ * @brief Rx Half Transfer completed callbacks.
* @param huart: pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval None
*/
-__weak void HAL_UART1_RxCpltCallback(UART_HandleTypeDef *huart)
+void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
+{
+ extern void HAL_UART1_RxHalfCpltCallback(UART_HandleTypeDef *huart);
+ extern void HAL_UART2_RxHalfCpltCallback(UART_HandleTypeDef *huart);
+
+ if (huart->Instance == USART1)
+ HAL_UART1_RxHalfCpltCallback(huart);
+
+ else if (huart->Instance == USART2)
+ HAL_UART2_RxHalfCpltCallback(huart);
+}
+
+__weak void HAL_UART1_RxHalfCpltCallback(UART_HandleTypeDef *huart)
{
/* NOTE: This function Should not be modified, when the callback is needed,
- the HAL_UART_RxCpltCallback could be implemented in the user file
+ the HAL_UART1_RxHalfCpltCallback could be implemented in the user file
*/
+ huart = huart;
}
-__weak void HAL_UART2_RxCpltCallback(UART_HandleTypeDef *huart)
+__weak void HAL_UART2_RxHalfCpltCallback(UART_HandleTypeDef *huart)
{
/* NOTE: This function Should not be modified, when the callback is needed,
- the HAL_UART_TxCpltCallback could be implemented in the user file
+ the HAL_UART2_RxHalfCpltCallback could be implemented in the user file
*/
+ huart = huart;
+}
+
+void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
+{
+ huart = huart;
+
+ /* I dunno, just trap it for now */
+ Error_Handler();
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_ll_fmc.c b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_ll_fmc.c
index bdf38fc..8010aef 100644
--- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_ll_fmc.c
+++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_ll_fmc.c
@@ -1413,25 +1413,35 @@ HAL_StatusTypeDef FMC_SDRAM_Init(FMC_SDRAM_TypeDef *Device, FMC_SDRAM_InitTypeDe
}
else /* FMC_Bank2_SDRAM */
{
-///////////////////////////////
-// BEGIN PIECE OF WEIRD CODE //
-///////////////////////////////
-//
-// tmpr1 = Device->SDCR[FMC_SDRAM_BANK1];
-//
-// /* Clear NC, NR, MWID, NB, CAS, WP, SDCLK, RBURST, and RPIPE bits */
-// tmpr1 &= ((uint32_t)~(FMC_SDCR1_NC | FMC_SDCR1_NR | FMC_SDCR1_MWID | \
-// FMC_SDCR1_NB | FMC_SDCR1_CAS | FMC_SDCR1_WP | \
-// FMC_SDCR1_SDCLK | FMC_SDCR1_RBURST | FMC_SDCR1_RPIPE));
-//
-// tmpr1 |= (uint32_t)(Init->SDClockPeriod |\
-// Init->ReadBurst |\
-// Init->ReadPipeDelay);
-//
-///////////////////////////////
-// END PIECE OF WEIRD CODE //
-///////////////////////////////
-
+#if 0 /* broken code */
+ tmpr1 = Device->SDCR[FMC_SDRAM_BANK1];
+
+ /* Clear NC, NR, MWID, NB, CAS, WP, SDCLK, RBURST, and RPIPE bits */
+ tmpr1 &= ((uint32_t)~(FMC_SDCR1_NC | FMC_SDCR1_NR | FMC_SDCR1_MWID | \
+ FMC_SDCR1_NB | FMC_SDCR1_CAS | FMC_SDCR1_WP | \
+ FMC_SDCR1_SDCLK | FMC_SDCR1_RBURST | FMC_SDCR1_RPIPE));
+
+ tmpr1 |= (uint32_t)(Init->SDClockPeriod |\
+ Init->ReadBurst |\
+ Init->ReadPipeDelay);
+
+ tmpr2 = Device->SDCR[FMC_SDRAM_BANK2];
+
+ /* Clear NC, NR, MWID, NB, CAS, WP, SDCLK, RBURST, and RPIPE bits */
+ tmpr2 &= ((uint32_t)~(FMC_SDCR1_NC | FMC_SDCR1_NR | FMC_SDCR1_MWID | \
+ FMC_SDCR1_NB | FMC_SDCR1_CAS | FMC_SDCR1_WP | \
+ FMC_SDCR1_SDCLK | FMC_SDCR1_RBURST | FMC_SDCR1_RPIPE));
+
+ tmpr2 |= (uint32_t)(Init->ColumnBitsNumber |\
+ Init->RowBitsNumber |\
+ Init->MemoryDataWidth |\
+ Init->InternalBankNumber |\
+ Init->CASLatency |\
+ Init->WriteProtection);
+
+ Device->SDCR[FMC_SDRAM_BANK1] = tmpr1;
+ Device->SDCR[FMC_SDRAM_BANK2] = tmpr2;
+#else
tmpr2 = Device->SDCR[FMC_SDRAM_BANK1];
/* Clear NC, NR, MWID, NB, CAS, WP, SDCLK, RBURST, and RPIPE bits */
@@ -1446,10 +1456,8 @@ HAL_StatusTypeDef FMC_SDRAM_Init(FMC_SDRAM_TypeDef *Device, FMC_SDRAM_InitTypeDe
Init->CASLatency |\
Init->WriteProtection);
-//
-// Device->SDCR[FMC_SDRAM_BANK1] = tmpr1;
-//
Device->SDCR[FMC_SDRAM_BANK2] = tmpr2;
+#endif
}
return HAL_OK;
@@ -1500,27 +1508,32 @@ HAL_StatusTypeDef FMC_SDRAM_Timing_Init(FMC_SDRAM_TypeDef *Device, FMC_SDRAM_Tim
}
else /* FMC_Bank2_SDRAM */
{
-///////////////////////////////
-// BEGIN PIECE OF WEIRD CODE //
-///////////////////////////////
-//
-// tmpr1 = Device->SDTR[FMC_SDRAM_BANK2];
-//
-// /* Clear TMRD, TXSR, TRAS, TRC, TWR, TRP and TRCD bits */
-// tmpr1 &= ((uint32_t)~(FMC_SDTR1_TMRD | FMC_SDTR1_TXSR | FMC_SDTR1_TRAS | \
-// FMC_SDTR1_TRC | FMC_SDTR1_TWR | FMC_SDTR1_TRP | \
-// FMC_SDTR1_TRCD));
-//
-// tmpr1 |= (uint32_t)(((Timing->LoadToActiveDelay)-1) |\
-// (((Timing->ExitSelfRefreshDelay)-1) << 4) |\
-// (((Timing->SelfRefreshTime)-1) << 8) |\
-// (((Timing->WriteRecoveryTime)-1) <<16) |\
-// (((Timing->RCDDelay)-1) << 24));
-//
-///////////////////////////////
-// END PIECE OF WEIRD CODE //
-///////////////////////////////
+#if 0 /* broken code */
+ tmpr1 = Device->SDTR[FMC_SDRAM_BANK2];
+
+ /* Clear TMRD, TXSR, TRAS, TRC, TWR, TRP and TRCD bits */
+ tmpr1 &= ((uint32_t)~(FMC_SDTR1_TMRD | FMC_SDTR1_TXSR | FMC_SDTR1_TRAS | \
+ FMC_SDTR1_TRC | FMC_SDTR1_TWR | FMC_SDTR1_TRP | \
+ FMC_SDTR1_TRCD));
+
+ tmpr1 |= (uint32_t)(((Timing->LoadToActiveDelay)-1) |\
+ (((Timing->ExitSelfRefreshDelay)-1) << 4) |\
+ (((Timing->SelfRefreshTime)-1) << 8) |\
+ (((Timing->WriteRecoveryTime)-1) <<16) |\
+ (((Timing->RCDDelay)-1) << 24));
+
+ tmpr2 = Device->SDTR[FMC_SDRAM_BANK1];
+
+ /* Clear TMRD, TXSR, TRAS, TRC, TWR, TRP and TRCD bits */
+ tmpr2 &= ((uint32_t)~(FMC_SDTR1_TMRD | FMC_SDTR1_TXSR | FMC_SDTR1_TRAS | \
+ FMC_SDTR1_TRC | FMC_SDTR1_TWR | FMC_SDTR1_TRP | \
+ FMC_SDTR1_TRCD));
+ tmpr2 |= (uint32_t)((((Timing->RowCycleDelay)-1) << 12) |\
+ (((Timing->RPDelay)-1) << 20));
+ Device->SDTR[FMC_SDRAM_BANK2] = tmpr1;
+ Device->SDTR[FMC_SDRAM_BANK1] = tmpr2;
+#else
tmpr2 = Device->SDTR[FMC_SDRAM_BANK1];
/* Clear TMRD, TXSR, TRAS, TRC, TWR, TRP and TRCD bits */
@@ -1534,10 +1547,8 @@ HAL_StatusTypeDef FMC_SDRAM_Timing_Init(FMC_SDRAM_TypeDef *Device, FMC_SDRAM_Tim
(((Timing->WriteRecoveryTime)-1U) <<16U) |\
(((Timing->RCDDelay)-1U) << 24U));
-//
-// Device->SDTR[FMC_SDRAM_BANK2] = tmpr1;
-//
Device->SDTR[FMC_SDRAM_BANK2] = tmpr2;
+#endif
}
return HAL_OK;
diff --git a/libraries/thirdparty/libtfm b/libraries/thirdparty/libtfm
deleted file mode 160000
-Subproject e2eab1093a134e5a655d1ccad23a31b2b8252c6
diff --git a/projects/board-test/Makefile b/projects/board-test/Makefile
index 9b1812f..45e75fc 100644
--- a/projects/board-test/Makefile
+++ b/projects/board-test/Makefile
@@ -1,4 +1,7 @@
-TEST = led-test short-test uart-test fmc-test fmc-perf fmc-probe rtc-test
+TEST = led-test short-test uart-test fmc-test fmc-perf fmc-probe
+ifeq (${BOARD},TARGET_CRYPTECH_ALPHA)
+TEST += rtc-test spiflash-perf keystore-perf
+endif
all: $(TEST:=.elf)
diff --git a/projects/board-test/fmc-perf.c b/projects/board-test/fmc-perf.c
index 0c753a7..5af0946 100644
--- a/projects/board-test/fmc-perf.c
+++ b/projects/board-test/fmc-perf.c
@@ -1,7 +1,6 @@
/*
* Test read/write performance of the fmc bus
*/
-#include "stm32f4xx_hal.h"
#include "stm-init.h"
#include "stm-led.h"
#include "stm-fmc.h"
@@ -32,14 +31,8 @@ static void sanity(void)
uint32_t rnd, data;
rnd = random();
- if (fmc_write_32(0, &rnd) != 0) {
- uart_send_string("fmc_write_32 failed\r\n");
- Error_Handler();
- }
- if (fmc_read_32(0, &data) != 0) {
- uart_send_string("fmc_read_32 failed\r\n");
- Error_Handler();
- }
+ fmc_write_32(0, rnd);
+ fmc_read_32(0, &data);
if (data != rnd) {
uart_send_string("Data bus fail: expected ");
uart_send_hex(rnd, 8);
@@ -57,11 +50,11 @@ static void _time_check(char *label, const uint32_t t0)
uint32_t t = HAL_GetTick() - t0;
uart_send_string(label);
- uart_send_integer(t / 1000, 0);
+ uart_send_integer(t / 1000, 1);
uart_send_char('.');
uart_send_integer(t % 1000, 3);
uart_send_string(" seconds, ");
- uart_send_integer(((1000 * TEST_NUM_ROUNDS) / t), 0);
+ uart_send_integer(((1000 * TEST_NUM_ROUNDS) / t), 1);
uart_send_string("/sec\r\n");
}
@@ -77,10 +70,7 @@ static void test_read(void)
uint32_t i, data;
for (i = 0; i < TEST_NUM_ROUNDS; ++i) {
- if (fmc_read_32(0, &data) != 0) {
- uart_send_string("fmc_read_32 failed\r\n");
- Error_Handler();
- }
+ fmc_read_32(0, &data);
}
}
@@ -89,33 +79,16 @@ static void test_write(void)
uint32_t i;
for (i = 0; i < TEST_NUM_ROUNDS; ++i) {
- if (fmc_write_32(0, &i) != 0) {
- uart_send_string("fmc_write_32 failed\r\n");
- Error_Handler();
- }
+ fmc_write_32(0, i);
}
}
int main(void)
{
stm_init();
-
- uart_send_string("Keep calm for Novena boot...\r\n");
-
- // Blink blue LED for six seconds to not upset the Novena at boot.
- led_on(LED_BLUE);
- for (int i = 0; i < 12; i++) {
- HAL_Delay(500);
- led_toggle(LED_BLUE);
- }
- led_off(LED_BLUE);
-
// initialize rng
MX_RNG_Init();
- // prepare fmc interface
- fmc_init();
-
sanity();
time_check("read ", test_read());
diff --git a/projects/board-test/fmc-probe.c b/projects/board-test/fmc-probe.c
index 55d3521..38897ab 100644
--- a/projects/board-test/fmc-probe.c
+++ b/projects/board-test/fmc-probe.c
@@ -2,7 +2,6 @@
* in other cases, it will be the core name and version strings.
*/
-#include "stm32f4xx_hal.h"
#include "stm-init.h"
#include "stm-led.h"
#include "stm-fmc.h"
@@ -22,37 +21,15 @@ static uint32_t read0(uint32_t addr)
{
uint32_t data;
- if (fmc_read_32(addr, &data) != 0) {
- uart_send_string("fmc_read_32 failed\r\n");
- Error_Handler();
- }
+ fmc_read_32(addr, &data);
return data;
}
int main(void)
{
- int i;
-
stm_init();
-
- uart_send_string("Keep calm for Novena boot...\r\n");
-
- // Blink blue LED for six seconds to not upset the Novena at boot.
- led_on(LED_BLUE);
- for (i = 0; i < 12; i++) {
- HAL_Delay(500);
- led_toggle(LED_BLUE);
- }
-
- // prepare fmc interface
- fmc_init();
-
- // turn on green led, turn off other leds
led_on(LED_GREEN);
- led_off(LED_YELLOW);
- led_off(LED_RED);
- led_off(LED_BLUE);
for (uint32_t addr = 0; addr < 0x00080000; addr += 4) {
uint32_t data = read0(addr);
diff --git a/projects/board-test/fmc-test.c b/projects/board-test/fmc-test.c
index bc5a768..bd30dd5 100644
--- a/projects/board-test/fmc-test.c
+++ b/projects/board-test/fmc-test.c
@@ -4,8 +4,7 @@
/*
This requires a special bitstream with a special test register.
- See core/platform/novena/fmc/rtl/novena_fmc_top.v, sections marked
- `ifdef test:
+ See core/platform/alpha/rtl/alpha_fmc_test.v:
//----------------------------------------------------------------
// Dummy Register
//
@@ -34,11 +33,11 @@
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
-#include "stm32f4xx_hal.h"
#include "stm-init.h"
#include "stm-led.h"
#include "stm-fmc.h"
#include "stm-uart.h"
+#include "stm-fpgacfg.h"
//------------------------------------------------------------------------------
// Defines
@@ -76,6 +75,7 @@ int test_fpga_address_bus(void);
// Defines
//------------------------------------------------------------------------------
#define TEST_NUM_ROUNDS 100000
+#define VERBOSE 0
//------------------------------------------------------------------------------
@@ -88,7 +88,7 @@ int main(void)
uart_send_string("Keep calm for FPGA bitstream loading...\r\n");
- // Blink blue LED until the FPGA reports it has loaded it's bitstream
+ // Blink blue LED until the FPGA reports it has loaded its bitstream
led_on(LED_BLUE);
while (! fpgacfg_check_done()) {
for (i = 0; i < 4; i++) {
@@ -100,9 +100,6 @@ int main(void)
// initialize rng
MX_RNG_Init();
- // prepare fmc interface
- fmc_init();
-
// turn on green led, turn off other leds
led_on(LED_GREEN);
led_off(LED_YELLOW);
@@ -120,11 +117,15 @@ int main(void)
// test address bus
addr_test_ok = test_fpga_address_bus();
- uart_send_string("Data: ");
- uart_send_integer(data_test_ok, 6);
- uart_send_string(", addr: ");
- uart_send_integer(addr_test_ok, 6);
- uart_send_string("\r\n");
+ if (VERBOSE ||
+ (data_test_ok != TEST_NUM_ROUNDS ||
+ addr_test_ok != TEST_NUM_ROUNDS)) {
+ uart_send_string("Data: ");
+ uart_send_integer(data_test_ok, 6);
+ uart_send_string(", addr: ");
+ uart_send_integer(addr_test_ok, 6);
+ uart_send_string("\r\n");
+ }
if (data_test_ok == TEST_NUM_ROUNDS &&
addr_test_ok == TEST_NUM_ROUNDS) {
@@ -140,11 +141,12 @@ int main(void)
}
uart_send_string("Success ");
- uart_send_integer(successful_runs, 0);
+ uart_send_integer(successful_runs, 1);
uart_send_string(", fail ");
- uart_send_integer(failed_runs, 0);
- uart_send_string("\r\n\r\n");
-
+ uart_send_integer(failed_runs, 1);
+ uart_send_string("\r\n");
+ if (VERBOSE)
+ uart_send_string("\r\n");
HAL_Delay(sleep);
}
@@ -156,7 +158,7 @@ int main(void)
int test_fpga_data_bus(void)
//------------------------------------------------------------------------------
{
- int c, ok;
+ int c;
uint32_t rnd, buf;
HAL_StatusTypeDef hal_result;
@@ -169,12 +171,10 @@ int test_fpga_data_bus(void)
if (hal_result != HAL_OK) break;
// write value to fpga at address 0
- ok = fmc_write_32(0, &rnd);
- if (ok != 0) break;
+ fmc_write_32(0, rnd);
// read value from fpga
- ok = fmc_read_32(0, &buf);
- if (ok != 0) break;
+ fmc_read_32(0, &buf);
// compare (abort testing in case of error)
if (buf != rnd)
@@ -197,13 +197,16 @@ int test_fpga_data_bus(void)
data_diff = buf;
data_diff ^= rnd;
- uart_send_string("Sample of data bus test data: expected ");
- uart_send_binary(rnd, 32);
- uart_send_string(", got ");
- uart_send_binary(buf, 32);
- uart_send_string(", diff ");
- uart_send_binary(data_diff, 32);
- uart_send_string("\r\n");
+ if (VERBOSE || data_diff) {
+ uart_send_string("Sample of data bus test data: expected ");
+ uart_send_binary(rnd, 32);
+ uart_send_string(", got ");
+ uart_send_binary(buf, 32);
+ uart_send_string(", diff ");
+ uart_send_binary(data_diff, 32);
+ uart_send_string("\r\n");
+ }
+
// return number of successful tests
return c;
}
@@ -213,7 +216,7 @@ int test_fpga_data_bus(void)
int test_fpga_address_bus(void)
//------------------------------------------------------------------------------
{
- int c, ok;
+ int c;
uint32_t rnd, buf;
HAL_StatusTypeDef hal_result;
@@ -234,12 +237,10 @@ int test_fpga_address_bus(void)
if (rnd == 0) continue;
// write dummy value to fpga at some non-zero address
- ok = fmc_write_32(rnd, &buf);
- if (ok != 0) break;
+ fmc_write_32(rnd, buf);
// read value from fpga
- ok = fmc_read_32(0, &buf);
- if (ok != 0) break;
+ fmc_read_32(0, &buf);
// fpga receives address of 32-bit word, while we need
// byte address here to compare
@@ -266,13 +267,15 @@ int test_fpga_address_bus(void)
addr_diff = buf;
addr_diff ^= rnd;
- uart_send_string("Sample of addr bus test data: expected ");
- uart_send_binary(rnd, 32);
- uart_send_string(", got ");
- uart_send_binary(buf, 32);
- uart_send_string(", diff ");
- uart_send_binary(addr_diff, 32);
- uart_send_string("\r\n");
+ if (VERBOSE || addr_diff) {
+ uart_send_string("Sample of addr bus test data: expected ");
+ uart_send_binary(rnd, 32);
+ uart_send_string(", got ");
+ uart_send_binary(buf, 32);
+ uart_send_string(", diff ");
+ uart_send_binary(addr_diff, 32);
+ uart_send_string("\r\n");
+ }
return c;
}
diff --git a/projects/board-test/keystore-perf.c b/projects/board-test/keystore-perf.c
new file mode 100644
index 0000000..c2aa4fb
--- /dev/null
+++ b/projects/board-test/keystore-perf.c
@@ -0,0 +1,197 @@
+/*
+ * Test read/write/erase performance of the flash keystore.
+ */
+
+#include "string.h"
+
+#include "stm-init.h"
+#include "stm-led.h"
+#include "stm-uart.h"
+#include "stm-keystore.h"
+
+/*
+ * 1. Read the entire flash by subsectors, ignoring data.
+ */
+static void test_read_data(void)
+{
+ uint8_t read_buf[KEYSTORE_SUBSECTOR_SIZE];
+ uint32_t i;
+ HAL_StatusTypeDef err;
+
+ for (i = 0; i < KEYSTORE_NUM_SUBSECTORS; ++i) {
+ err = keystore_read_data(i * KEYSTORE_SUBSECTOR_SIZE, read_buf, KEYSTORE_SUBSECTOR_SIZE);
+ if (err != HAL_OK) {
+ uart_send_string("ERROR: keystore_read_data returned ");
+ uart_send_integer(err, 1);
+ uart_send_string("\r\n");
+ break;
+ }
+ }
+}
+
+/*
+ * Read the flash data and verify it against a known pattern.
+ */
+static void _read_verify(uint8_t *vrfy_buf)
+{
+ uint8_t read_buf[KEYSTORE_SUBSECTOR_SIZE];
+ uint32_t i;
+ HAL_StatusTypeDef err;
+
+ for (i = 0; i < KEYSTORE_NUM_SUBSECTORS; ++i) {
+ err = keystore_read_data(i * KEYSTORE_SUBSECTOR_SIZE, read_buf, KEYSTORE_SUBSECTOR_SIZE);
+ if (err != HAL_OK) {
+ uart_send_string("ERROR: keystore_read_data returned ");
+ uart_send_integer(err, 1);
+ uart_send_string("\r\n");
+ break;
+ }
+ if (memcmp(read_buf, vrfy_buf, KEYSTORE_SUBSECTOR_SIZE) != 0) {
+ uart_send_string("ERROR: verify failed in subsector ");
+ uart_send_integer(i, 1);
+ uart_send_string("\r\n");
+ break;
+ }
+ }
+}
+
+/*
+ * 2a. Erase the entire flash by sectors.
+ */
+static void test_erase_sector(void)
+{
+ uint32_t i;
+ HAL_StatusTypeDef err;
+
+ for (i = 0; i < KEYSTORE_NUM_SECTORS; ++i) {
+ err = keystore_erase_sector(i);
+ if (err != HAL_OK) {
+ uart_send_string("ERROR: keystore_erase_sector returned ");
+ uart_send_integer(err, 1);
+ uart_send_string("\r\n");
+ break;
+ }
+ }
+}
+
+/*
+ * 2b. Erase the entire flash by subsectors.
+ */
+static void test_erase_subsector(void)
+{
+ uint32_t i;
+ HAL_StatusTypeDef err;
+
+ for (i = 0; i < KEYSTORE_NUM_SUBSECTORS; ++i) {
+ err = keystore_erase_subsector(i);
+ if (err != HAL_OK) {
+ uart_send_string("ERROR: keystore_erase_subsector returned ");
+ uart_send_integer(err, 1);
+ uart_send_string("\r\n");
+ break;
+ }
+ }
+}
+
+/*
+ * 2c. Read the entire flash, verify erasure.
+ */
+static void test_verify_erase(void)
+{
+ uint8_t vrfy_buf[KEYSTORE_SUBSECTOR_SIZE];
+ uint32_t i;
+
+ for (i = 0; i < sizeof(vrfy_buf); ++i)
+ vrfy_buf[i] = 0xFF;
+
+ _read_verify(vrfy_buf);
+}
+
+/*
+ * 3a. Write the entire flash with a pattern.
+ */
+static void test_write_data(void)
+{
+ uint8_t write_buf[KEYSTORE_SUBSECTOR_SIZE];
+ uint32_t i;
+ HAL_StatusTypeDef err;
+
+ for (i = 0; i < sizeof(write_buf); ++i)
+ write_buf[i] = i & 0xFF;
+
+ for (i = 0; i < KEYSTORE_NUM_SUBSECTORS; ++i) {
+ err = keystore_write_data(i * KEYSTORE_SUBSECTOR_SIZE, write_buf, KEYSTORE_SUBSECTOR_SIZE);
+ if (err != HAL_OK) {
+ uart_send_string("ERROR: keystore_write_data returned ");
+ uart_send_integer(err, 1);
+ uart_send_string(" for subsector ");
+ uart_send_integer(i, 1);
+ uart_send_string("\r\n");
+ break;
+ }
+ }
+}
+
+/*
+ * 3b. Read the entire flash, verify data.
+ */
+static void test_verify_write(void)
+{
+ uint8_t vrfy_buf[KEYSTORE_SUBSECTOR_SIZE];
+ uint32_t i;
+
+ for (i = 0; i < sizeof(vrfy_buf); ++i)
+ vrfy_buf[i] = i & 0xFF;
+
+ _read_verify(vrfy_buf);
+}
+
+static void _time_check(char *label, const uint32_t t0, uint32_t n_rounds)
+{
+ uint32_t t = HAL_GetTick() - t0;
+
+ uart_send_string(label);
+ uart_send_integer(t / 1000, 1);
+ uart_send_char('.');
+ uart_send_integer(t % 1000, 3);
+ uart_send_string(" sec");
+ if (n_rounds > 1) {
+ uart_send_string(" for ");
+ uart_send_integer(n_rounds, 1);
+ uart_send_string(" rounds, ");
+ uart_send_integer(t / n_rounds, 1);
+ uart_send_char('.');
+ uart_send_integer(((t % n_rounds) * 100) / n_rounds, 2);
+ uart_send_string(" ms each");
+ }
+ uart_send_string("\r\n");
+}
+
+#define time_check(_label_, _expr_, _n_) \
+ do { \
+ uint32_t _t = HAL_GetTick(); \
+ (_expr_); \
+ _time_check(_label_, _t, _n_); \
+ } while (0)
+
+int main(void)
+{
+ stm_init();
+
+ if (keystore_check_id() != HAL_OK) {
+ uart_send_string("ERROR: keystore_check_id failed\r\n");
+ return 0;
+ }
+
+ uart_send_string("Starting...\r\n");
+
+ time_check("read data ", test_read_data(), KEYSTORE_NUM_SUBSECTORS);
+ time_check("erase subsector ", test_erase_subsector(), KEYSTORE_NUM_SUBSECTORS);
+ time_check("erase sector ", test_erase_sector(), KEYSTORE_NUM_SECTORS);
+ time_check("verify erase ", test_verify_erase(), KEYSTORE_NUM_SUBSECTORS);
+ time_check("write data ", test_write_data(), KEYSTORE_NUM_SUBSECTORS);
+ time_check("verify write ", test_verify_write(), KEYSTORE_NUM_SUBSECTORS);
+
+ uart_send_string("Done.\r\n\r\n");
+ return 0;
+}
diff --git a/projects/board-test/led-test.c b/projects/board-test/led-test.c
index 7e72788..2ec7c9d 100644
--- a/projects/board-test/led-test.c
+++ b/projects/board-test/led-test.c
@@ -1,7 +1,6 @@
/*
* Blink the four LEDs on the rev01 board in a pattern.
*/
-#include "stm32f4xx_hal.h"
#include "stm-init.h"
#include "stm-led.h"
diff --git a/projects/board-test/rtc-test.c b/projects/board-test/rtc-test.c
index b8a7511..bbb297a 100644
--- a/projects/board-test/rtc-test.c
+++ b/projects/board-test/rtc-test.c
@@ -8,7 +8,6 @@
*/
#include <string.h>
-#include "stm32f4xx_hal.h"
#include "stm-init.h"
#include "stm-led.h"
#include "stm-uart.h"
@@ -23,18 +22,18 @@ uint32_t i;
uint32_t device_ready(uint16_t i2c_addr)
{
- uart_send_string2(STM_UART_MGMT, "Checking readiness of 0x");
- uart_send_number2(STM_UART_MGMT, i2c_addr, 4, 16);
- uart_send_string2(STM_UART_MGMT, "...");
+ uart_send_string("Checking readiness of 0x");
+ uart_send_hex(i2c_addr, 4);
+ uart_send_string("...");
if (rtc_device_ready(i2c_addr) == HAL_OK) {
- uart_send_string2(STM_UART_MGMT, "OK\r\n");
+ uart_send_string("OK\r\n");
return 1;
}
- uart_send_string2(STM_UART_MGMT, "Not ready (0x");
- uart_send_number2(STM_UART_MGMT, i, 4, 16);
- uart_send_string2(STM_UART_MGMT, ")\r\n");
+ uart_send_string("Not ready (0x");
+ uart_send_hex(i, 4);
+ uart_send_string(")\r\n");
return 0;
}
@@ -44,34 +43,34 @@ void send_byte(const uint16_t i2c_addr, const uint8_t value)
{
uint8_t ch = value;
- uart_send_string2(STM_UART_MGMT, "Sending ");
- uart_send_number2(STM_UART_MGMT, ch, 2, 16);
- uart_send_string2(STM_UART_MGMT, " to 0x");
- uart_send_number2(STM_UART_MGMT, i2c_addr, 4, 16);
- uart_send_string2(STM_UART_MGMT, "...");
+ uart_send_string("Sending ");
+ uart_send_hex(ch, 2);
+ uart_send_string(" to 0x");
+ uart_send_hex(i2c_addr, 4);
+ uart_send_string("...");
if (rtc_send_byte(i2c_addr, ch, 1000) != HAL_OK) {
- uart_send_string2(STM_UART_MGMT, "Timeout\r\n");
+ uart_send_string("Timeout\r\n");
Error_Handler();
}
- uart_send_string2(STM_UART_MGMT, "OK\r\n");
+ uart_send_string("OK\r\n");
}
void read_bytes (uint8_t *buf, const uint16_t i2c_addr, const uint8_t len)
{
- uart_send_string2(STM_UART_MGMT, "Reading ");
- uart_send_number2(STM_UART_MGMT, len, 3, 10);
- uart_send_string2(STM_UART_MGMT, " bytes from 0x");
- uart_send_number2(STM_UART_MGMT, i2c_addr, 4, 16);
- uart_send_string2(STM_UART_MGMT, "...");
+ uart_send_string("Reading ");
+ uart_send_integer(len, 1);
+ uart_send_string(" bytes from 0x");
+ uart_send_hex(i2c_addr, 4);
+ uart_send_string("...");
if (rtc_read_bytes(i2c_addr, buf, len, 1000) != HAL_OK) {
- uart_send_string2(STM_UART_MGMT, "Timeout\r\n");
+ uart_send_string("Timeout\r\n");
Error_Handler();
}
- uart_send_string2(STM_UART_MGMT, "OK\r\n");
+ uart_send_string("OK\r\n");
}
void request_data(uint8_t *buf, const uint16_t i2c_addr, const uint8_t offset, const uint8_t bytes)
@@ -85,8 +84,8 @@ void print_time()
request_data(buf, RTC_RTC_ADDR, RTC_TIME_OFFSET, RTC_TIME_BYTES);
for (i = 0; i < RTC_TIME_BYTES; i++) {
- uart_send_number2(STM_UART_MGMT, buf[i], 2, 16);
- uart_send_string2(STM_UART_MGMT, " ");
+ uart_send_hex(buf[i], 2);
+ uart_send_string(" ");
}
}
@@ -94,37 +93,37 @@ void dump_sram()
{
request_data(buf, RTC_RTC_ADDR, 0x0, RTC_SRAM_TOTAL_BYTES);
- uart_send_string2(STM_UART_MGMT, "SRAM contents:\r\n");
- uart_send_hexdump(STM_UART_MGMT, buf, 0, RTC_SRAM_TOTAL_BYTES);
+ uart_send_string("SRAM contents:\r\n");
+ uart_send_hexdump(buf, 0, RTC_SRAM_TOTAL_BYTES);
- uart_send_string2(STM_UART_MGMT, "\r\n");
+ uart_send_string("\r\n");
}
void dump_eeprom()
{
request_data(buf, RTC_EEPROM_ADDR, 0x0, RTC_EEPROM_TOTAL_BYTES);
- uart_send_string2(STM_UART_MGMT, "EEPROM contents:\r\n");
- uart_send_hexdump(STM_UART_MGMT, buf, 0, RTC_EEPROM_TOTAL_BYTES);
- uart_send_string2(STM_UART_MGMT, "\r\n");
+ uart_send_string("EEPROM contents:\r\n");
+ uart_send_hexdump(buf, 0, RTC_EEPROM_TOTAL_BYTES);
+ uart_send_string("\r\n");
request_data(buf, RTC_EEPROM_ADDR, RTC_EEPROM_EUI48_OFFSET, RTC_EEPROM_EUI48_BYTES);
- uart_send_string2(STM_UART_MGMT, "EEPROM EUI-48:\r\n");
- uart_send_hexdump(STM_UART_MGMT, buf, RTC_EEPROM_EUI48_OFFSET, RTC_EEPROM_EUI48_BYTES);
+ uart_send_string("EEPROM EUI-48:\r\n");
+ uart_send_hexdump(buf, RTC_EEPROM_EUI48_OFFSET, RTC_EEPROM_EUI48_BYTES);
- uart_send_string2(STM_UART_MGMT, "\r\n");
+ uart_send_string("\r\n");
}
void enable_oscillator()
{
- uart_send_string2(STM_UART_MGMT, "Enabling oscillator...\r\n");
+ uart_send_string("Enabling oscillator...\r\n");
if (rtc_enable_oscillator() != HAL_OK) {
- uart_send_string2(STM_UART_MGMT, "Timeout\r\n");
+ uart_send_string("Timeout\r\n");
Error_Handler();
}
- uart_send_string2(STM_UART_MGMT, "OK\r\n");
+ uart_send_string("OK\r\n");
}
@@ -132,7 +131,7 @@ int
main()
{
stm_init();
- uart_send_string2(STM_UART_MGMT, "\r\n\r\n*** Init done\r\n");
+ uart_send_string("\r\n\r\n*** Init done\r\n");
dump_sram();
dump_eeprom();
@@ -148,7 +147,7 @@ main()
print_time(buf);
- uart_send_string2(STM_UART_MGMT, "\r\n\r\n");
+ uart_send_string("\r\n\r\n");
HAL_GPIO_TogglePin(LED_PORT, LED_GREEN);
DELAY();
diff --git a/projects/board-test/short-test.c b/projects/board-test/short-test.c
index 27b8e7a..db0251b 100644
--- a/projects/board-test/short-test.c
+++ b/projects/board-test/short-test.c
@@ -5,7 +5,6 @@
* Toggles the BLUE LED slowly and the RED LED for every
* character sent.
*/
-#include "stm32f4xx_hal.h"
#include "stm-init.h"
#include "stm-led.h"
#include "stm-uart.h"
diff --git a/projects/board-test/spiflash-perf.c b/projects/board-test/spiflash-perf.c
new file mode 100644
index 0000000..36c6131
--- /dev/null
+++ b/projects/board-test/spiflash-perf.c
@@ -0,0 +1,249 @@
+/*
+ * Test read/write/erase performance of the N25Q128 SPI flash chip.
+ */
+
+#include "string.h"
+
+#include "stm-init.h"
+#include "stm-led.h"
+#include "stm-uart.h"
+#include "stm-keystore.h"
+#include "spiflash_n25q128.h"
+
+/*
+ * Use the keystore memory for testing, because it's less involved than
+ * using the FPGA configuration memory, and less work to restore it to a
+ * useful configuration.
+ *
+ * However, rather than using the stm-keystore abstractions, this version
+ * goes straight to the low-level API.
+ */
+
+extern struct spiflash_ctx keystore_ctx;
+static struct spiflash_ctx *ctx = &keystore_ctx;
+
+/*
+ * 1a. Read the entire flash by pages, ignoring data.
+ */
+static void test_read_page(void)
+{
+ uint8_t read_buf[N25Q128_PAGE_SIZE];
+ uint32_t i;
+ int err;
+
+ for (i = 0; i < N25Q128_NUM_PAGES; ++i) {
+ err = n25q128_read_page(ctx, i, read_buf);
+ if (err != HAL_OK) {
+ uart_send_string("ERROR: n25q128_read_page returned ");
+ uart_send_integer(err, 1);
+ uart_send_string("\r\n");
+ break;
+ }
+ }
+}
+
+/*
+ * 1b. Read the entire flash by subsectors, ignoring data.
+ */
+static void test_read_subsector(void)
+{
+ uint8_t read_buf[N25Q128_SUBSECTOR_SIZE];
+ uint32_t i;
+ int err;
+
+ for (i = 0; i < N25Q128_NUM_SUBSECTORS; ++i) {
+ err = n25q128_read_subsector(ctx, i, read_buf);
+ if (err != HAL_OK) {
+ uart_send_string("ERROR: n25q128_read_subsector returned ");
+ uart_send_integer(err, 1);
+ uart_send_string("\r\n");
+ break;
+ }
+ }
+}
+
+/*
+ * Read the flash data and verify it against a known pattern.
+ * It turns out that verification doesn't slow us down in any measurable
+ * way, because memcmp on 256 bytes is pretty inconsequential.
+ */
+static void _read_verify(uint8_t *vrfy_buf)
+{
+ uint8_t read_buf[N25Q128_PAGE_SIZE];
+ uint32_t i;
+ int err;
+
+ for (i = 0; i < N25Q128_NUM_PAGES; ++i) {
+ err = n25q128_read_page(ctx, i, read_buf);
+ if (err != HAL_OK) {
+ uart_send_string("ERROR: n25q128_read_page returned ");
+ uart_send_integer(err, 1);
+ uart_send_string("\r\n");
+ break;
+ }
+ if (memcmp(read_buf, vrfy_buf, N25Q128_PAGE_SIZE) != 0) {
+ uart_send_string("ERROR: verify failed in page ");
+ uart_send_integer(i, 1);
+ uart_send_string("\r\n");
+ break;
+ }
+ }
+}
+
+/*
+ * 2a. Erase the entire flash by sectors.
+ */
+static void test_erase_sector(void)
+{
+ uint32_t i;
+ int err;
+
+ for (i = 0; i < N25Q128_NUM_SECTORS; ++i) {
+ err = n25q128_erase_sector(ctx, i);
+ if (err != HAL_OK) {
+ uart_send_string("ERROR: n25q128_erase_sector returned ");
+ uart_send_integer(err, 1);
+ uart_send_string("\r\n");
+ break;
+ }
+ }
+}
+
+/*
+ * 2b. Erase the entire flash by subsectors.
+ */
+static void test_erase_subsector(void)
+{
+ uint32_t i;
+ int err;
+
+ for (i = 0; i < N25Q128_NUM_SUBSECTORS; ++i) {
+ err = n25q128_erase_subsector(ctx, i);
+ if (err != HAL_OK) {
+ uart_send_string("ERROR: n25q128_erase_subsector returned ");
+ uart_send_integer(err, 1);
+ uart_send_string("\r\n");
+ break;
+ }
+ }
+}
+
+/*
+ * 2c. Erase the entire flash in bulk.
+ */
+static void test_erase_bulk(void)
+{
+ int err;
+
+ err = n25q128_erase_bulk(ctx);
+ if (err != HAL_OK) {
+ uart_send_string("ERROR: n25q128_erase_bulk returned ");
+ uart_send_integer(err, 1);
+ uart_send_string("\r\n");
+ }
+}
+
+/*
+ * 2d. Read the entire flash, verify erasure.
+ */
+static void test_verify_erase(void)
+{
+ uint8_t vrfy_buf[N25Q128_PAGE_SIZE];
+ uint32_t i;
+
+ for (i = 0; i < sizeof(vrfy_buf); ++i)
+ vrfy_buf[i] = 0xFF;
+
+ _read_verify(vrfy_buf);
+}
+
+/*
+ * 3a. Write the entire flash with a pattern.
+ */
+static void test_write_page(void)
+{
+ uint8_t write_buf[N25Q128_PAGE_SIZE];
+ uint32_t i;
+ int err;
+
+ for (i = 0; i < sizeof(write_buf); ++i)
+ write_buf[i] = i & 0xFF;
+
+ for (i = 0; i < N25Q128_NUM_PAGES; ++i) {
+ err = n25q128_write_page(ctx, i, write_buf);
+ if (err != HAL_OK) {
+ uart_send_string("ERROR: n25q128_write_page returned ");
+ uart_send_integer(err, 1);
+ uart_send_string(" for page ");
+ uart_send_integer(i, 1);
+ uart_send_string("\r\n");
+ break;
+ }
+ }
+}
+
+/*
+ * 3b. Read the entire flash, verify data.
+ */
+static void test_verify_write(void)
+{
+ uint8_t vrfy_buf[N25Q128_PAGE_SIZE];
+ uint32_t i;
+
+ for (i = 0; i < sizeof(vrfy_buf); ++i)
+ vrfy_buf[i] = i & 0xFF;
+
+ _read_verify(vrfy_buf);
+}
+
+static void _time_check(char *label, const uint32_t t0, uint32_t n_rounds)
+{
+ uint32_t t = HAL_GetTick() - t0;
+
+ uart_send_string(label);
+ uart_send_integer(t / 1000, 1);
+ uart_send_char('.');
+ uart_send_integer(t % 1000, 3);
+ uart_send_string(" sec");
+ if (n_rounds > 1) {
+ uart_send_string(" for ");
+ uart_send_integer(n_rounds, 1);
+ uart_send_string(" rounds, ");
+ uart_send_integer(t / n_rounds, 1);
+ uart_send_char('.');
+ uart_send_integer(((t % n_rounds) * 100) / n_rounds, 2);
+ uart_send_string(" ms each");
+ }
+ uart_send_string("\r\n");
+}
+
+#define time_check(_label_, _expr_, _n_) \
+ do { \
+ uint32_t _t = HAL_GetTick(); \
+ (_expr_); \
+ _time_check(_label_, _t, _n_); \
+ } while (0)
+
+int main(void)
+{
+ stm_init();
+
+ if (n25q128_check_id(ctx) != HAL_OK) {
+ uart_send_string("ERROR: n25q128_check_id failed\r\n");
+ return 0;
+ }
+
+ uart_send_string("Starting...\r\n");
+
+ time_check("read page ", test_read_page(), N25Q128_NUM_PAGES);
+ time_check("read subsector ", test_read_subsector(), N25Q128_NUM_SUBSECTORS);
+ time_check("erase subsector ", test_erase_subsector(), N25Q128_NUM_SUBSECTORS);
+ time_check("erase sector ", test_erase_sector(), N25Q128_NUM_SECTORS);
+ time_check("erase bulk ", test_erase_bulk(), 1);
+ time_check("verify erase ", test_verify_erase(), N25Q128_NUM_PAGES);
+ time_check("write page ", test_write_page(), N25Q128_NUM_PAGES);
+ time_check("verify write ", test_verify_write(), N25Q128_NUM_PAGES);
+
+ uart_send_string("Done.\r\n\r\n");
+ return 0;
+}
diff --git a/projects/board-test/uart-test.c b/projects/board-test/uart-test.c
index be06863..9a56dee 100644
--- a/projects/board-test/uart-test.c
+++ b/projects/board-test/uart-test.c
@@ -6,7 +6,6 @@
* Toggles the BLUE LED slowly and the GREEN LED for every
* character sent.
*/
-#include "stm32f4xx_hal.h"
#include "stm-init.h"
#include "stm-led.h"
#include "stm-uart.h"
diff --git a/projects/bootloader/Makefile b/projects/bootloader/Makefile
index 4eef758..6c1012f 100644
--- a/projects/bootloader/Makefile
+++ b/projects/bootloader/Makefile
@@ -1,6 +1,22 @@
PROG = bootloader
-OBJS = crc32.o dfu.o
+OBJS = dfu.o log.o
+
+BOARD_OBJS = \
+ ./stm-init.o \
+ $(TOPLEVEL)/stm-fmc.o \
+ $(TOPLEVEL)/stm-uart.o \
+ $(TOPLEVEL)/spiflash_n25q128.o \
+ $(TOPLEVEL)/stm-keystore.o \
+ $(TOPLEVEL)/stm-flash.o \
+ $(TOPLEVEL)/syscalls.o \
+ $(BOARD_DIR)/system_stm32f4xx.o \
+ $(BOARD_DIR)/stm32f4xx_hal_msp.o \
+ ./startup_stm32f429xx.o \
+ $(BOARD_DIR)/stm32f4xx_it.o
+
+CFLAGS += -I$(LIBHAL_SRC)
+LIBS += $(LIBHAL_BLD)/libhal.a $(LIBTFM_BLD)/libtfm.a
all: $(PROG:=.elf)
diff --git a/projects/bootloader/bootloader.c b/projects/bootloader/bootloader.c
index ab3c1d9..6413597 100644
--- a/projects/bootloader/bootloader.c
+++ b/projects/bootloader/bootloader.c
@@ -5,6 +5,8 @@
* or jump to previously installed firmware.
*
* Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ * Copyright: 2020, The Commons Conservancy Cryptech Project
+ * SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -16,9 +18,9 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * - Neither the name of the NORDUnet nor the names of its contributors may
- * be used to endorse or promote products derived from this software
- * without specific prior written permission.
+ * - Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -32,11 +34,30 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
+/* Ignore "deprecated" warnings in ARM-supplied CMSIS code:
+ *
+ * libraries/mbed/targets/cmsis/core_cm4.h:85:28: warning: listing the stack pointer register 'sp' in a clobber list is deprecated
+ * libraries/mbed/targets/cmsis/core_cm4.h:85:28: note: the value of the stack pointer after an 'asm' statement must be the same as it was before the statement
+ *
+ * This comes from our use of __set_MSP to set the stack pointer when
+ * switching tasks. If GCC ever decides to actually forbid this, then
+ * we'll have to figure out something else, possibly a native assembly
+ * function.
+ */
+#pragma GCC diagnostic ignored "-Wdeprecated"
+
#include "stm-init.h"
#include "stm-led.h"
#include "stm-uart.h"
+#include "stm-fmc.h"
#include "dfu.h"
+/* stub these out to avoid linker error */
+void fpgacfg_init(void) { }
+void sdram_init(void) { }
+void *hal_allocate_static_memory(const size_t size) { return 0; }
+
/* Linker symbols are strange in C. Make regular pointers for sanity. */
__IO uint32_t *dfu_control = &CRYPTECH_DFU_CONTROL;
__IO uint32_t *dfu_firmware = &CRYPTECH_FIRMWARE_START;
@@ -49,16 +70,20 @@ __IO uint32_t *dfu_code_ptr = &CRYPTECH_FIRMWARE_START + 1;
typedef void (*pFunction)(void);
-/* This is it's own function to make it more convenient to set a breakpoint at it in gdb */
-void do_early_dfu_jump(void)
+/* called from Reset_Handler */
+void check_early_dfu_jump(void)
{
- pFunction loaded_app = (pFunction) *dfu_code_ptr;
- /* Set the stack pointer to the correct one for the firmware */
- __set_MSP(*dfu_msp_ptr);
- /* Set the Vector Table Offset Register */
- SCB->VTOR = (uint32_t) dfu_firmware;
- loaded_app();
- while (1);
+ /* Check if we've just rebooted in order to jump to the firmware. */
+ if (*dfu_control == HARDWARE_EARLY_DFU_JUMP) {
+ *dfu_control = 0;
+ pFunction loaded_app = (pFunction) *dfu_code_ptr;
+ /* Set the stack pointer to the correct one for the firmware */
+ __set_MSP(*dfu_msp_ptr);
+ /* Set the Vector Table Offset Register */
+ SCB->VTOR = (uint32_t) dfu_firmware;
+ loaded_app();
+ while (1);
+ }
}
int should_dfu()
@@ -66,35 +91,31 @@ int should_dfu()
int i;
uint8_t rx = 0;
- /* While blinking the blue LED for one second, see if we receive a CR on the MGMT UART.
+ /* While blinking the blue LED for 5 seconds, see if we receive a CR on the MGMT UART.
* We've discussed also requiring one or both of the FPGA config jumpers installed
* before allowing DFU of the STM32 - that check could be done here.
*/
led_on(LED_BLUE);
- for (i = 0; i < 10; i++) {
+ for (i = 0; i < 50; i++) {
HAL_Delay(100);
led_toggle(LED_BLUE);
- if (uart_recv_char2(STM_UART_MGMT, &rx, 0) == HAL_OK) {
+ if (uart_recv_char(&rx, 0) == HAL_OK) {
if (rx == 13) return 1;
}
}
return 0;
}
-int
-main()
+/* Sleep for specified number of seconds -- used after bad PIN. */
+void hal_sleep(const unsigned seconds) { HAL_Delay(seconds * 1000); }
+
+int main(void)
{
int status;
- /* Check if we've just rebooted in order to jump to the firmware. */
- if (*dfu_control == HARDWARE_EARLY_DFU_JUMP) {
- *dfu_control = 0;
- do_early_dfu_jump();
- }
-
stm_init();
- uart_send_string2(STM_UART_MGMT, (char *) "\r\n\r\nThis is the bootloader speaking...");
+ uart_send_string("\r\n\r\nThis is the bootloader speaking...");
if (should_dfu()) {
led_off(LED_BLUE);
@@ -104,9 +125,9 @@ main()
*/
led_off(LED_BLUE);
led_on(LED_RED);
- uart_send_string2(STM_UART_MGMT, (char *) "dfu_receive_firmware failed: ");
- uart_send_number2(STM_UART_MGMT, status, 3, 16);
- uart_send_string2(STM_UART_MGMT, (char *) "\r\n\r\nRebooting in three seconds\r\n");
+ uart_send_string("dfu_receive_firmware failed: ");
+ uart_send_hex(status, 2);
+ uart_send_string("\r\n\r\nRebooting in three seconds\r\n");
HAL_Delay(3000);
HAL_NVIC_SystemReset();
while (1) {};
@@ -118,7 +139,7 @@ main()
*/
*dfu_control = HARDWARE_EARLY_DFU_JUMP;
- uart_send_string2(STM_UART_MGMT, (char *) "loading firmware\r\n\r\n");
+ uart_send_string("loading firmware\r\n\r\n");
/* De-initialize hardware by rebooting */
HAL_NVIC_SystemReset();
diff --git a/projects/bootloader/crc32.c b/projects/bootloader/crc32.c
deleted file mode 100644
index 4d1a0bc..0000000
--- a/projects/bootloader/crc32.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* Reference code from RFC1952. Not meant to be used outside test code. */
-
-#include "stm32f4xx_hal.h"
-
-
-/* Table of CRCs of all 8-bit messages. */
-unsigned long crc_table[256];
-
-/* Flag: has the table been computed? Initially false. */
-int crc_table_computed = 0;
-
-/* Make the table for a fast CRC. */
-void make_crc_table(void)
-{
- unsigned long c;
-
- int n, k;
- for (n = 0; n < 256; n++) {
- c = (unsigned long) n;
- for (k = 0; k < 8; k++) {
- if (c & 1) {
- c = 0xedb88320L ^ (c >> 1);
- } else {
- c = c >> 1;
- }
- }
- crc_table[n] = c;
- }
- crc_table_computed = 1;
-}
-
-/*
- Update a running crc with the bytes buf[0..len-1] and return
- the updated crc. The crc should be initialized to zero. Pre- and
- post-conditioning (one's complement) is performed within this
- function so it shouldn't be done by the caller. Usage example:
-
- unsigned long crc = 0L;
-
- while (read_buffer(buffer, length) != EOF) {
- crc = update_crc(crc, buffer, length);
- }
- if (crc != original_crc) error();
-*/
-uint32_t update_crc(uint32_t crc, uint8_t *buf, int len)
-{
- unsigned long c = crc ^ 0xffffffffL;
- int n;
-
- if (!crc_table_computed)
- make_crc_table();
- for (n = 0; n < len; n++) {
- c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
- }
- return c ^ 0xffffffffL;
-}
-
-/* Return the CRC of the bytes buf[0..len-1]. */
-unsigned long crc(unsigned char *buf, int len)
-{
- return update_crc(0L, buf, len);
-}
diff --git a/projects/bootloader/dfu.c b/projects/bootloader/dfu.c
index 231e388..83aef20 100644
--- a/projects/bootloader/dfu.c
+++ b/projects/bootloader/dfu.c
@@ -31,43 +31,132 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
+/* Rename both CMSIS HAL_OK and libhal HAL_OK to disambiguate */
+#define HAL_OK CMSIS_HAL_OK
#include "dfu.h"
#include "stm-led.h"
#include "stm-uart.h"
#include "stm-flash.h"
+#undef HAL_OK
+
+#define HAL_OK LIBHAL_OK
+#include "hal.h"
+#include "hal_internal.h"
+#undef HAL_OK
#include <string.h>
-extern uint32_t update_crc(uint32_t crc, uint8_t *buf, int len);
+static int getline(char *buf, int len)
+{
+ int i;
+ uint8_t c;
+
+ for (i = 0; i < len; ++i) {
+ if (uart_recv_char(&c, HAL_MAX_DELAY) != CMSIS_HAL_OK)
+ return -1;
+ if (c == '\r') {
+ buf[i] = '\0';
+ break;
+ }
+ buf[i] = c;
+ }
+ return i;
+}
+static void uart_flush(void)
+{
+ uint8_t c;
+ while (uart_recv_char(&c, 0) == CMSIS_HAL_OK) { ; }
+}
+
+static int do_login(void)
+{
+ char username[8];
+ char pin[hal_rpc_max_pin_length];
+ hal_client_handle_t client = { -1 };
+ hal_user_t user;
+ int n;
+
+ uart_flush();
+ uart_send_string("\r\nUsername: ");
+ if (getline(username, sizeof(username)) <= 0)
+ return -1;
+ if (strcmp(username, "wheel") == 0)
+ user = HAL_USER_WHEEL;
+ else if (strcmp(username, "so") == 0)
+ user = HAL_USER_SO;
+ else if (strcmp(username, "user") == 0)
+ user = HAL_USER_NORMAL;
+ else
+ user = HAL_USER_NONE;
+
+ uart_flush();
+ uart_send_string("\r\nPassword: ");
+ if ((n = getline(pin, sizeof(pin))) <= 0)
+ return -1;
+
+ uart_flush();
+
+ hal_ks_init_read_only_pins_only();
+
+ if (hal_rpc_login(client, user, pin, n) != LIBHAL_OK) {
+ uart_send_string("\r\nAccess denied\r\n");
+ return -1;
+ }
+ return 0;
+}
int dfu_receive_firmware(void)
{
- uint32_t filesize = 0, crc = 0, my_crc = 0, counter = 0;
uint32_t offset = DFU_FIRMWARE_ADDR, n = DFU_UPLOAD_CHUNK_SIZE;
- uint32_t buf[DFU_UPLOAD_CHUNK_SIZE / 4];
+ hal_crc32_t crc = 0, my_crc = hal_crc32_init();
+ uint32_t filesize = 0, counter = 0;
+ uint8_t buf[DFU_UPLOAD_CHUNK_SIZE];
+
+ if (do_login() != 0)
+ return -1;
+
+ /* Fake the CLI */
+ uart_send_string("\r\ncryptech> ");
+ char cmd[64];
+ if (getline(cmd, sizeof(cmd)) <= 0)
+ return -1;
+ if (strcmp(cmd, "firmware upload") != 0) {
+ uart_send_string("\r\nInvalid command \"");
+ uart_send_string(cmd);
+ uart_send_string("\"\r\n");
+ return -1;
+ }
- uart_send_string2(STM_UART_MGMT, (char *) "\r\nOK, bootloader waiting for new firmware\r\n");
+ uart_send_string("OK, write size (4 bytes), data in 4096 byte chunks, CRC-32 (4 bytes)\r\n");
/* Read file size (4 bytes) */
- uart_receive_bytes(STM_UART_MGMT, (void *) &filesize, 4, 1000);
+ uart_receive_bytes((void *) &filesize, sizeof(filesize), 10000);
if (filesize < 512 || filesize > DFU_FIRMWARE_END_ADDR - DFU_FIRMWARE_ADDR) {
+ uart_send_string("Invalid filesize ");
+ uart_send_integer(filesize, 1);
+ uart_send_string("\r\n");
return -1;
}
HAL_FLASH_Unlock();
+ uart_send_string("Send ");
+ uart_send_integer(filesize, 1);
+ uart_send_string(" bytes of data\r\n");
+
while (filesize) {
/* By initializing buf to the same value that erased flash has (0xff), we don't
* have to try and be smart when writing the last page of data to the memory.
*/
- memset(buf, 0xffffffff, sizeof(buf));
+ memset(buf, 0xff, sizeof(buf));
if (filesize < n) {
n = filesize;
}
- if (uart_receive_bytes(STM_UART_MGMT, (void *) &buf, n, 1000) != HAL_OK) {
+ if (uart_receive_bytes((void *) buf, n, 10000) != CMSIS_HAL_OK) {
return -2;
}
filesize -= n;
@@ -75,23 +164,34 @@ int dfu_receive_firmware(void)
/* After reception of a chunk but before ACKing we have "all" the time in the world to
* calculate CRC and write it to flash.
*/
- my_crc = update_crc(my_crc, (uint8_t *) buf, n);
- stm_flash_write32(offset, buf, sizeof(buf) / 4);
+ my_crc = hal_crc32_update(my_crc, buf, n);
+ stm_flash_write32(offset, (uint32_t *)buf, sizeof(buf)/4);
offset += DFU_UPLOAD_CHUNK_SIZE;
/* ACK this chunk by sending the current chunk counter (4 bytes) */
counter++;
- uart_send_bytes(STM_UART_MGMT, (void *) &counter, 4);
+ uart_send_bytes((void *) &counter, 4);
led_toggle(LED_BLUE);
}
+ my_crc = hal_crc32_finalize(my_crc);
+
HAL_FLASH_Lock();
- /* The sending side will now send it's calculated CRC-32 */
- uart_receive_bytes(STM_UART_MGMT, (void *) &crc, 4, 1000);
+ uart_send_string("Send CRC-32\r\n");
+
+ /* The sending side will now send its calculated CRC-32 */
+ uart_receive_bytes((void *) &crc, sizeof(crc), 10000);
+
+ uart_send_string("CRC-32 0x");
+ uart_send_hex(crc, 1);
+ uart_send_string(", calculated CRC 0x");
+ uart_send_hex(my_crc, 1);
if (crc == my_crc) {
- uart_send_string2(STM_UART_MGMT, (char *) "\r\nSuccess\r\n");
- return 0;
+ uart_send_string("CRC checksum MATCHED\r\n");
+ return 0;
+ } else {
+ uart_send_string("CRC checksum did NOT match\r\n");
}
led_on(LED_RED);
diff --git a/projects/bootloader/log.c b/projects/bootloader/log.c
new file mode 100644
index 0000000..fbc0e73
--- /dev/null
+++ b/projects/bootloader/log.c
@@ -0,0 +1,68 @@
+/*
+ * log.c
+ * -----
+ * Implement libhal logging API on Alpha.
+ *
+ * Copyright (c) 2017, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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 <stdarg.h>
+
+#define HAL_OK CMSIS_HAL_OK
+#include "stm-uart.h"
+#undef HAL_OK
+
+#define HAL_OK LIBHAL_OK
+#include "hal.h"
+#include "hal_internal.h"
+#undef HAL_OK
+
+static hal_log_level_t current_log_level;
+
+void hal_log_set_level(const hal_log_level_t level)
+{
+ current_log_level = level;
+}
+
+void hal_log(const hal_log_level_t level, const char *format, ...)
+{
+ if (level < current_log_level)
+ return;
+
+ char buffer[2048];
+ va_list ap;
+
+ va_start(ap, format);
+ vsnprintf(buffer, sizeof(buffer), format, ap);
+ va_end(ap);
+
+ uart_send_string(buffer);
+ uart_send_string("\r\n");
+}
diff --git a/projects/bootloader/startup_stm32f429xx.S b/projects/bootloader/startup_stm32f429xx.S
new file mode 100644
index 0000000..fc8bf34
--- /dev/null
+++ b/projects/bootloader/startup_stm32f429xx.S
@@ -0,0 +1,564 @@
+/**
+ ******************************************************************************
+ * @file startup_stm32f429xx.s
+ * @author MCD Application Team
+ * @version V2.4.1
+ * @date 09-October-2015
+ * @brief STM32F429xx Devices vector table for GCC based toolchains.
+ * This module performs:
+ * - Set the initial SP
+ * - Set the initial PC == Reset_Handler,
+ * - Set the vector table entries with the exceptions ISR address
+ * - Branches to main in the C library (which eventually
+ * calls main()).
+ * After Reset the Cortex-M4 processor is in Thread mode,
+ * priority is Privileged, and the Stack is set to Main.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
+ *
+ * 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. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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
+ .cpu cortex-m4
+ .fpu softvfp
+ .thumb
+
+.global g_pfnVectors
+.global Default_Handler
+
+/* start address for the initialization values of the .data section.
+defined in linker script */
+.word _sidata
+/* start address for the .data section. defined in linker script */
+.word _sdata
+/* end address for the .data section. defined in linker script */
+.word _edata
+/* start address for the .bss section. defined in linker script */
+.word _sbss
+/* end address for the .bss section. defined in linker script */
+.word _ebss
+/* stack used for SystemInit_ExtMemCtl; always internal RAM used */
+
+/**
+ * @brief This is the code that gets called when the processor first
+ * starts execution following a reset event. Only the absolutely
+ * necessary set is performed, after which the application
+ * supplied main() routine is called.
+ * @param None
+ * @retval : None
+*/
+
+ .section .text.Reset_Handler
+ .weak Reset_Handler
+ .type Reset_Handler, %function
+Reset_Handler:
+ ldr sp, =_estack /* set stack pointer */
+
+/* Copy the data segment initializers from flash to SRAM */
+ movs r1, #0
+ b LoopCopyDataInit
+
+CopyDataInit:
+ ldr r3, =_sidata
+ ldr r3, [r3, r1]
+ str r3, [r0, r1]
+ adds r1, r1, #4
+
+LoopCopyDataInit:
+ ldr r0, =_sdata
+ ldr r3, =_edata
+ adds r2, r0, r1
+ cmp r2, r3
+ bcc CopyDataInit
+ ldr r2, =_sbss
+ b LoopFillZerobss
+/* Zero fill the bss segment. */
+FillZerobss:
+ movs r3, #0
+ str r3, [r2], #4
+
+LoopFillZerobss:
+ ldr r3, = _ebss
+ cmp r2, r3
+ bcc FillZerobss
+
+ /* Check if we've just rebooted in order to jump to the firmware. */
+ bl check_early_dfu_jump
+
+/* Call the clock system intitialization function.*/
+ bl SystemInit
+/* Call static constructors */
+ bl __libc_init_array
+/* Call the application's entry point.*/
+ bl main
+ bx lr
+.size Reset_Handler, .-Reset_Handler
+
+/**
+ * @brief This is the code that gets called when the processor receives an
+ * unexpected interrupt. This simply enters an infinite loop, preserving
+ * the system state for examination by a debugger.
+ * @param None
+ * @retval None
+*/
+ .section .text.Default_Handler,"ax",%progbits
+Default_Handler:
+Infinite_Loop:
+ b Infinite_Loop
+ .size Default_Handler, .-Default_Handler
+/******************************************************************************
+*
+* The minimal vector table for a Cortex M3. Note that the proper constructs
+* must be placed on this to ensure that it ends up at physical address
+* 0x0000.0000.
+*
+*******************************************************************************/
+ .section .isr_vector,"a",%progbits
+ .type g_pfnVectors, %object
+ .size g_pfnVectors, .-g_pfnVectors
+
+g_pfnVectors:
+ .word _estack
+ .word Reset_Handler
+
+ .word NMI_Handler
+ .word HardFault_Handler
+ .word MemManage_Handler
+ .word BusFault_Handler
+ .word UsageFault_Handler
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word SVC_Handler
+ .word DebugMon_Handler
+ .word 0
+ .word PendSV_Handler
+ .word SysTick_Handler
+
+ /* External Interrupts */
+ .word WWDG_IRQHandler /* Window WatchDog */
+ .word PVD_IRQHandler /* PVD through EXTI Line detection */
+ .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */
+ .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */
+ .word FLASH_IRQHandler /* FLASH */
+ .word RCC_IRQHandler /* RCC */
+ .word EXTI0_IRQHandler /* EXTI Line0 */
+ .word EXTI1_IRQHandler /* EXTI Line1 */
+ .word EXTI2_IRQHandler /* EXTI Line2 */
+ .word EXTI3_IRQHandler /* EXTI Line3 */
+ .word EXTI4_IRQHandler /* EXTI Line4 */
+ .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */
+ .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */
+ .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */
+ .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */
+ .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */
+ .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */
+ .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */
+ .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */
+ .word CAN1_TX_IRQHandler /* CAN1 TX */
+ .word CAN1_RX0_IRQHandler /* CAN1 RX0 */
+ .word CAN1_RX1_IRQHandler /* CAN1 RX1 */
+ .word CAN1_SCE_IRQHandler /* CAN1 SCE */
+ .word EXTI9_5_IRQHandler /* External Line[9:5]s */
+ .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */
+ .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */
+ .word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */
+ .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */
+ .word TIM2_IRQHandler /* TIM2 */
+ .word TIM3_IRQHandler /* TIM3 */
+ .word TIM4_IRQHandler /* TIM4 */
+ .word I2C1_EV_IRQHandler /* I2C1 Event */
+ .word I2C1_ER_IRQHandler /* I2C1 Error */
+ .word I2C2_EV_IRQHandler /* I2C2 Event */
+ .word I2C2_ER_IRQHandler /* I2C2 Error */
+ .word SPI1_IRQHandler /* SPI1 */
+ .word SPI2_IRQHandler /* SPI2 */
+ .word USART1_IRQHandler /* USART1 */
+ .word USART2_IRQHandler /* USART2 */
+ .word USART3_IRQHandler /* USART3 */
+ .word EXTI15_10_IRQHandler /* External Line[15:10]s */
+ .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */
+ .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */
+ .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */
+ .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */
+ .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */
+ .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */
+ .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */
+ .word FMC_IRQHandler /* FMC */
+ .word SDIO_IRQHandler /* SDIO */
+ .word TIM5_IRQHandler /* TIM5 */
+ .word SPI3_IRQHandler /* SPI3 */
+ .word UART4_IRQHandler /* UART4 */
+ .word UART5_IRQHandler /* UART5 */
+ .word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */
+ .word TIM7_IRQHandler /* TIM7 */
+ .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */
+ .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */
+ .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */
+ .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */
+ .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */
+ .word ETH_IRQHandler /* Ethernet */
+ .word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */
+ .word CAN2_TX_IRQHandler /* CAN2 TX */
+ .word CAN2_RX0_IRQHandler /* CAN2 RX0 */
+ .word CAN2_RX1_IRQHandler /* CAN2 RX1 */
+ .word CAN2_SCE_IRQHandler /* CAN2 SCE */
+ .word OTG_FS_IRQHandler /* USB OTG FS */
+ .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */
+ .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */
+ .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */
+ .word USART6_IRQHandler /* USART6 */
+ .word I2C3_EV_IRQHandler /* I2C3 event */
+ .word I2C3_ER_IRQHandler /* I2C3 error */
+ .word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */
+ .word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */
+ .word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */
+ .word OTG_HS_IRQHandler /* USB OTG HS */
+ .word DCMI_IRQHandler /* DCMI */
+ .word 0 /* Reserved */
+ .word HASH_RNG_IRQHandler /* Hash and Rng */
+ .word FPU_IRQHandler /* FPU */
+ .word UART7_IRQHandler /* UART7 */
+ .word UART8_IRQHandler /* UART8 */
+ .word SPI4_IRQHandler /* SPI4 */
+ .word SPI5_IRQHandler /* SPI5 */
+ .word SPI6_IRQHandler /* SPI6 */
+ .word SAI1_IRQHandler /* SAI1 */
+ .word LTDC_IRQHandler /* LTDC_IRQHandler */
+ .word LTDC_ER_IRQHandler /* LTDC_ER_IRQHandler */
+ .word DMA2D_IRQHandler /* DMA2D */
+
+/*******************************************************************************
+*
+* Provide weak aliases for each Exception handler to the Default_Handler.
+* As they are weak aliases, any function with the same name will override
+* this definition.
+*
+*******************************************************************************/
+ .weak NMI_Handler
+ .thumb_set NMI_Handler,Default_Handler
+
+ .weak HardFault_Handler
+ .thumb_set HardFault_Handler,Default_Handler
+
+ .weak MemManage_Handler
+ .thumb_set MemManage_Handler,Default_Handler
+
+ .weak BusFault_Handler
+ .thumb_set BusFault_Handler,Default_Handler
+
+ .weak UsageFault_Handler
+ .thumb_set UsageFault_Handler,Default_Handler
+
+ .weak SVC_Handler
+ .thumb_set SVC_Handler,Default_Handler
+
+ .weak DebugMon_Handler
+ .thumb_set DebugMon_Handler,Default_Handler
+
+ .weak PendSV_Handler
+ .thumb_set PendSV_Handler,Default_Handler
+
+ .weak SysTick_Handler
+ .thumb_set SysTick_Handler,Default_Handler
+
+ .weak WWDG_IRQHandler
+ .thumb_set WWDG_IRQHandler,Default_Handler
+
+ .weak PVD_IRQHandler
+ .thumb_set PVD_IRQHandler,Default_Handler
+
+ .weak TAMP_STAMP_IRQHandler
+ .thumb_set TAMP_STAMP_IRQHandler,Default_Handler
+
+ .weak RTC_WKUP_IRQHandler
+ .thumb_set RTC_WKUP_IRQHandler,Default_Handler
+
+ .weak FLASH_IRQHandler
+ .thumb_set FLASH_IRQHandler,Default_Handler
+
+ .weak RCC_IRQHandler
+ .thumb_set RCC_IRQHandler,Default_Handler
+
+ .weak EXTI0_IRQHandler
+ .thumb_set EXTI0_IRQHandler,Default_Handler
+
+ .weak EXTI1_IRQHandler
+ .thumb_set EXTI1_IRQHandler,Default_Handler
+
+ .weak EXTI2_IRQHandler
+ .thumb_set EXTI2_IRQHandler,Default_Handler
+
+ .weak EXTI3_IRQHandler
+ .thumb_set EXTI3_IRQHandler,Default_Handler
+
+ .weak EXTI4_IRQHandler
+ .thumb_set EXTI4_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream0_IRQHandler
+ .thumb_set DMA1_Stream0_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream1_IRQHandler
+ .thumb_set DMA1_Stream1_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream2_IRQHandler
+ .thumb_set DMA1_Stream2_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream3_IRQHandler
+ .thumb_set DMA1_Stream3_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream4_IRQHandler
+ .thumb_set DMA1_Stream4_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream5_IRQHandler
+ .thumb_set DMA1_Stream5_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream6_IRQHandler
+ .thumb_set DMA1_Stream6_IRQHandler,Default_Handler
+
+ .weak ADC_IRQHandler
+ .thumb_set ADC_IRQHandler,Default_Handler
+
+ .weak CAN1_TX_IRQHandler
+ .thumb_set CAN1_TX_IRQHandler,Default_Handler
+
+ .weak CAN1_RX0_IRQHandler
+ .thumb_set CAN1_RX0_IRQHandler,Default_Handler
+
+ .weak CAN1_RX1_IRQHandler
+ .thumb_set CAN1_RX1_IRQHandler,Default_Handler
+
+ .weak CAN1_SCE_IRQHandler
+ .thumb_set CAN1_SCE_IRQHandler,Default_Handler
+
+ .weak EXTI9_5_IRQHandler
+ .thumb_set EXTI9_5_IRQHandler,Default_Handler
+
+ .weak TIM1_BRK_TIM9_IRQHandler
+ .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler
+
+ .weak TIM1_UP_TIM10_IRQHandler
+ .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler
+
+ .weak TIM1_TRG_COM_TIM11_IRQHandler
+ .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler
+
+ .weak TIM1_CC_IRQHandler
+ .thumb_set TIM1_CC_IRQHandler,Default_Handler
+
+ .weak TIM2_IRQHandler
+ .thumb_set TIM2_IRQHandler,Default_Handler
+
+ .weak TIM3_IRQHandler
+ .thumb_set TIM3_IRQHandler,Default_Handler
+
+ .weak TIM4_IRQHandler
+ .thumb_set TIM4_IRQHandler,Default_Handler
+
+ .weak I2C1_EV_IRQHandler
+ .thumb_set I2C1_EV_IRQHandler,Default_Handler
+
+ .weak I2C1_ER_IRQHandler
+ .thumb_set I2C1_ER_IRQHandler,Default_Handler
+
+ .weak I2C2_EV_IRQHandler
+ .thumb_set I2C2_EV_IRQHandler,Default_Handler
+
+ .weak I2C2_ER_IRQHandler
+ .thumb_set I2C2_ER_IRQHandler,Default_Handler
+
+ .weak SPI1_IRQHandler
+ .thumb_set SPI1_IRQHandler,Default_Handler
+
+ .weak SPI2_IRQHandler
+ .thumb_set SPI2_IRQHandler,Default_Handler
+
+ .weak USART1_IRQHandler
+ .thumb_set USART1_IRQHandler,Default_Handler
+
+ .weak USART2_IRQHandler
+ .thumb_set USART2_IRQHandler,Default_Handler
+
+ .weak USART3_IRQHandler
+ .thumb_set USART3_IRQHandler,Default_Handler
+
+ .weak EXTI15_10_IRQHandler
+ .thumb_set EXTI15_10_IRQHandler,Default_Handler
+
+ .weak RTC_Alarm_IRQHandler
+ .thumb_set RTC_Alarm_IRQHandler,Default_Handler
+
+ .weak OTG_FS_WKUP_IRQHandler
+ .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler
+
+ .weak TIM8_BRK_TIM12_IRQHandler
+ .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler
+
+ .weak TIM8_UP_TIM13_IRQHandler
+ .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler
+
+ .weak TIM8_TRG_COM_TIM14_IRQHandler
+ .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler
+
+ .weak TIM8_CC_IRQHandler
+ .thumb_set TIM8_CC_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream7_IRQHandler
+ .thumb_set DMA1_Stream7_IRQHandler,Default_Handler
+
+ .weak FMC_IRQHandler
+ .thumb_set FMC_IRQHandler,Default_Handler
+
+ .weak SDIO_IRQHandler
+ .thumb_set SDIO_IRQHandler,Default_Handler
+
+ .weak TIM5_IRQHandler
+ .thumb_set TIM5_IRQHandler,Default_Handler
+
+ .weak SPI3_IRQHandler
+ .thumb_set SPI3_IRQHandler,Default_Handler
+
+ .weak UART4_IRQHandler
+ .thumb_set UART4_IRQHandler,Default_Handler
+
+ .weak UART5_IRQHandler
+ .thumb_set UART5_IRQHandler,Default_Handler
+
+ .weak TIM6_DAC_IRQHandler
+ .thumb_set TIM6_DAC_IRQHandler,Default_Handler
+
+ .weak TIM7_IRQHandler
+ .thumb_set TIM7_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream0_IRQHandler
+ .thumb_set DMA2_Stream0_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream1_IRQHandler
+ .thumb_set DMA2_Stream1_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream2_IRQHandler
+ .thumb_set DMA2_Stream2_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream3_IRQHandler
+ .thumb_set DMA2_Stream3_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream4_IRQHandler
+ .thumb_set DMA2_Stream4_IRQHandler,Default_Handler
+
+ .weak ETH_IRQHandler
+ .thumb_set ETH_IRQHandler,Default_Handler
+
+ .weak ETH_WKUP_IRQHandler
+ .thumb_set ETH_WKUP_IRQHandler,Default_Handler
+
+ .weak CAN2_TX_IRQHandler
+ .thumb_set CAN2_TX_IRQHandler,Default_Handler
+
+ .weak CAN2_RX0_IRQHandler
+ .thumb_set CAN2_RX0_IRQHandler,Default_Handler
+
+ .weak CAN2_RX1_IRQHandler
+ .thumb_set CAN2_RX1_IRQHandler,Default_Handler
+
+ .weak CAN2_SCE_IRQHandler
+ .thumb_set CAN2_SCE_IRQHandler,Default_Handler
+
+ .weak OTG_FS_IRQHandler
+ .thumb_set OTG_FS_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream5_IRQHandler
+ .thumb_set DMA2_Stream5_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream6_IRQHandler
+ .thumb_set DMA2_Stream6_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream7_IRQHandler
+ .thumb_set DMA2_Stream7_IRQHandler,Default_Handler
+
+ .weak USART6_IRQHandler
+ .thumb_set USART6_IRQHandler,Default_Handler
+
+ .weak I2C3_EV_IRQHandler
+ .thumb_set I2C3_EV_IRQHandler,Default_Handler
+
+ .weak I2C3_ER_IRQHandler
+ .thumb_set I2C3_ER_IRQHandler,Default_Handler
+
+ .weak OTG_HS_EP1_OUT_IRQHandler
+ .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler
+
+ .weak OTG_HS_EP1_IN_IRQHandler
+ .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler
+
+ .weak OTG_HS_WKUP_IRQHandler
+ .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler
+
+ .weak OTG_HS_IRQHandler
+ .thumb_set OTG_HS_IRQHandler,Default_Handler
+
+ .weak DCMI_IRQHandler
+ .thumb_set DCMI_IRQHandler,Default_Handler
+
+ .weak HASH_RNG_IRQHandler
+ .thumb_set HASH_RNG_IRQHandler,Default_Handler
+
+ .weak FPU_IRQHandler
+ .thumb_set FPU_IRQHandler,Default_Handler
+
+ .weak UART7_IRQHandler
+ .thumb_set UART7_IRQHandler,Default_Handler
+
+ .weak UART8_IRQHandler
+ .thumb_set UART8_IRQHandler,Default_Handler
+
+ .weak SPI4_IRQHandler
+ .thumb_set SPI4_IRQHandler,Default_Handler
+
+ .weak SPI5_IRQHandler
+ .thumb_set SPI5_IRQHandler,Default_Handler
+
+ .weak SPI6_IRQHandler
+ .thumb_set SPI6_IRQHandler,Default_Handler
+
+ .weak SAI1_IRQHandler
+ .thumb_set SAI1_IRQHandler,Default_Handler
+
+ .weak LTDC_IRQHandler
+ .thumb_set LTDC_IRQHandler,Default_Handler
+
+ .weak LTDC_ER_IRQHandler
+ .thumb_set LTDC_ER_IRQHandler,Default_Handler
+
+ .weak DMA2D_IRQHandler
+ .thumb_set DMA2D_IRQHandler,Default_Handler
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
+
+
diff --git a/projects/bootloader/stm-init.c b/projects/bootloader/stm-init.c
new file mode 100644
index 0000000..b331b8a
--- /dev/null
+++ b/projects/bootloader/stm-init.c
@@ -0,0 +1,7 @@
+/* Disable modules that the bootloader doesn't need. */
+
+#include "stm32f4xx_hal.h"
+
+#undef HAL_I2C_MODULE_ENABLED
+
+#include "../../stm-init.c"
diff --git a/projects/cli-test/Makefile b/projects/cli-test/Makefile
index acf2720..5bb3fb1 100644
--- a/projects/cli-test/Makefile
+++ b/projects/cli-test/Makefile
@@ -1,11 +1,28 @@
-TEST = cli-test
+PROJ = cli-test
-OBJS = crc32.o test_sdram.o mgmt-cli.o mgmt-dfu.c mgmt-fpga.c mgmt-misc.c mgmt-show.c mgmt-test.c
+# objs in addition to $(PROJ).o
+OBJS = \
+ mgmt-cli.o \
+ mgmt-dfu.o \
+ mgmt-fpga.o \
+ mgmt-keystore.o \
+ mgmt-masterkey.o \
+ mgmt-misc.o \
+ mgmt-show.o
-CFLAGS += -I$(LIBCLI_DIR)
-LIBS += $(LIBCLI_DIR)/libcli.a
+CFLAGS += -I$(LIBCLI_SRC) -I$(LIBHAL_SRC)
+CFLAGS += -I$(LIBTFM_BLD)
+CFLAGS += -Wno-missing-field-initializers
-all: $(TEST:=.elf)
+ifdef DO_TIMING
+CFLAGS += -DDO_TIMING
+OBJS += mgmt-timing.o $(TOPLEVEL)/stm-dwt.o
+LDFLAGS += -lm
+endif
+
+LIBS += $(LIBCLI_BLD)/libcli.a $(LIBHAL_BLD)/libhal.a $(LIBTFM_BLD)/libtfm.a
+
+all: $(PROJ:=.elf)
%.elf: %.o $(BOARD_OBJS) $(OBJS) $(LIBS)
$(CC) $(CFLAGS) $^ -o $@ -T$(LDSCRIPT) -g -Wl,-Map=$*.map
diff --git a/projects/cli-test/cli-test.c b/projects/cli-test/cli-test.c
index ed6aac3..c50338b 100644
--- a/projects/cli-test/cli-test.c
+++ b/projects/cli-test/cli-test.c
@@ -33,6 +33,7 @@
*/
#include "stm-init.h"
#include "stm-led.h"
+#include "stm-uart.h"
#include "mgmt-cli.h"
#include "mgmt-dfu.h"
@@ -40,72 +41,78 @@
#include "mgmt-misc.h"
#include "mgmt-show.h"
#include "mgmt-test.h"
+#include "mgmt-keystore.h"
#include <string.h>
+#include <strings.h>
/* MGMT UART interrupt receive buffer (data will be put in a larger ring buffer) */
volatile uint8_t uart_rx;
-
-int check_auth(const char *username, const char *password)
-{
- if (strcasecmp(username, "ct") != 0)
- return CLI_ERROR;
- if (strcasecmp(password, "ct") != 0)
- return CLI_ERROR;
- return CLI_OK;
-}
-
-typedef void (*pFunction)(void);
-
-/* This is it's own function to make it more convenient to set a breakpoint at it in gdb */
-void do_early_dfu_jump(void)
-{
- pFunction loaded_app = (pFunction) *dfu_code_ptr;
- /* Set the stack pointer to the correct one for the firmware */
- __set_MSP(*dfu_msp_ptr);
- /* Set the Vector Table Offset Register */
- SCB->VTOR = (uint32_t) dfu_firmware;
- loaded_app();
- while (1);
-}
+/* Sleep for specified number of seconds -- used after bad PIN. */
+void hal_sleep(const unsigned seconds) { HAL_Delay(seconds * 1000); }
int
main()
{
- static struct cli_def cli;
+ stm_init();
+ led_on(LED_GREEN);
- /* Check if we've just rebooted in order to jump to the firmware. */
- if (*dfu_control == HARDWARE_EARLY_DFU_JUMP) {
- *dfu_control = 0;
- do_early_dfu_jump();
+ /* For the hsm, the keystores are initialized in hal_rpc_server_init(),
+ * which is...less than optimal, but this is not the time or place to fix
+ * it, especially in light of all the terrible things I'm doing in this
+ * version of cli-test.
+ */
+ extern void *hal_ks_token, *hal_ks_volatile;
+ extern int hal_ks_init(void *, int);
+ if (hal_ks_init(hal_ks_volatile, 1) != 0 || hal_ks_init(hal_ks_token, 1) != 0)
+ Error_Handler();
+
+ while (1) {
+ cli_main();
+ /* embedded_cli_loop returns when the user enters 'quit' or 'exit' */
}
- stm_init();
+ /* NOT REACHED */
+ Error_Handler();
+}
- led_on(LED_RED);
- mgmt_cli_init(&cli);
- cli_set_auth_callback(&cli, check_auth);
+/* end of variables declared with __attribute__((section(".sdram1"))) */
+extern uint8_t _esdram1 __asm ("_esdram1");
+/* end of SDRAM1 section */
+extern uint8_t __end_sdram1 __asm ("__end_sdram1");
+static uint8_t *sdram_heap = &_esdram1;
- configure_cli_show(&cli);
- configure_cli_fpga(&cli);
- configure_cli_test(&cli);
- configure_cli_misc(&cli);
- configure_cli_dfu(&cli);
+/* Allocate memory from SDRAM1. */
+static uint8_t *sdram_malloc(size_t size)
+{
+ uint8_t *p = sdram_heap;
- led_off(LED_RED);
- led_on(LED_GREEN);
+#define pad(n) (((n) + 3) & ~3)
+ size = pad(size);
- embedded_cli_loop(&cli);
+ if (p + size + sizeof(uint32_t) > &__end_sdram1)
+ return NULL;
- /* embedded_cli_loop returns when the user enters 'quit' or 'exit' */
+ *(uint32_t *)p = (uint32_t)size;
+ p += sizeof(uint32_t);
- cli_print(&cli, "Rebooting in 3 seconds");
- HAL_Delay(3000);
- HAL_NVIC_SystemReset();
+ sdram_heap += size + sizeof(uint32_t);
+ return p;
+}
- /* NOT REACHED */
- Error_Handler();
+/* Implement static memory allocation for libhal over sdram_malloc().
+ * Used in hal_ks_init.
+ */
+void *hal_allocate_static_memory(const size_t size)
+{
+ return sdram_malloc(size);
+}
+
+int hal_free_static_memory(const void * const ptr)
+{
+ return 0;
}
+
diff --git a/projects/cli-test/crc32.c b/projects/cli-test/crc32.c
deleted file mode 100644
index 4d1a0bc..0000000
--- a/projects/cli-test/crc32.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* Reference code from RFC1952. Not meant to be used outside test code. */
-
-#include "stm32f4xx_hal.h"
-
-
-/* Table of CRCs of all 8-bit messages. */
-unsigned long crc_table[256];
-
-/* Flag: has the table been computed? Initially false. */
-int crc_table_computed = 0;
-
-/* Make the table for a fast CRC. */
-void make_crc_table(void)
-{
- unsigned long c;
-
- int n, k;
- for (n = 0; n < 256; n++) {
- c = (unsigned long) n;
- for (k = 0; k < 8; k++) {
- if (c & 1) {
- c = 0xedb88320L ^ (c >> 1);
- } else {
- c = c >> 1;
- }
- }
- crc_table[n] = c;
- }
- crc_table_computed = 1;
-}
-
-/*
- Update a running crc with the bytes buf[0..len-1] and return
- the updated crc. The crc should be initialized to zero. Pre- and
- post-conditioning (one's complement) is performed within this
- function so it shouldn't be done by the caller. Usage example:
-
- unsigned long crc = 0L;
-
- while (read_buffer(buffer, length) != EOF) {
- crc = update_crc(crc, buffer, length);
- }
- if (crc != original_crc) error();
-*/
-uint32_t update_crc(uint32_t crc, uint8_t *buf, int len)
-{
- unsigned long c = crc ^ 0xffffffffL;
- int n;
-
- if (!crc_table_computed)
- make_crc_table();
- for (n = 0; n < len; n++) {
- c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
- }
- return c ^ 0xffffffffL;
-}
-
-/* Return the CRC of the bytes buf[0..len-1]. */
-unsigned long crc(unsigned char *buf, int len)
-{
- return update_crc(0L, buf, len);
-}
diff --git a/projects/cli-test/filetransfer b/projects/cli-test/filetransfer
index f704e31..6e58781 100755
--- a/projects/cli-test/filetransfer
+++ b/projects/cli-test/filetransfer
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
#
# Copyright (c) 2016, NORDUnet A/S All rights reserved.
#
@@ -37,7 +37,7 @@ import struct
import serial
import argparse
-from binascii import crc32
+from binascii import crc32, hexlify
CHUNK_SIZE = 256
DFU_CHUNK_SIZE = 256
@@ -79,19 +79,19 @@ def parse_args():
def _write(dst, data):
dst.write(data)
if len(data) == 4:
- print("Wrote 0x{!s}".format(data.encode('hex')))
+ print(("Wrote 0x{!s}".format(hexlify(data).decode("ascii"))))
else:
- print("Wrote {!r}".format(data))
+ print(("Wrote {!r}".format(data)))
def _read(dst):
- res = ''
+ res = b''
while True:
x = dst.read(1)
if not x:
break
res += x
- print ("Read {!r}".format(res))
+ print(("Read {!r}".format(res)))
return res
@@ -142,19 +142,19 @@ def send_file(filename, args, dst):
if not data:
break
dst.write(data)
- print("Wrote {!s} bytes (chunk {!s}/{!s})".format(len(data), counter, int(size / chunk_size)))
+ print(("Wrote {!s} bytes (chunk {!s}/{!s})".format(len(data), counter, int(size / chunk_size))))
# read ACK (a counter of number of 4k chunks received)
while True:
ack_bytes = dst.read(4)
if len(ack_bytes) == 4:
break
- print('ERROR: Did not receive an ACK, got {!r}'.format(ack_bytes))
+ print(('ERROR: Did not receive an ACK, got {!r}'.format(ack_bytes)))
dst.write('\r') # eventually get back to the CLI prompt
ack = struct.unpack('<I', ack_bytes)[0]
if ack != counter + 1:
- print('ERROR: Did not receive the expected counter as ACK (got {!r}/{!r}, not {!r})'.format(ack, ack_bytes, counter))
+ print(('ERROR: Did not receive the expected counter as ACK (got {!r}/{!r}, not {!r})'.format(ack, ack_bytes, counter)))
flush = dst.read(100)
- print('FLUSH data: {!r}'.format(flush))
+ print(('FLUSH data: {!r}'.format(flush)))
return False
counter += 1
diff --git a/projects/cli-test/mgmt-cli.c b/projects/cli-test/mgmt-cli.c
index 3b4ffe9..960d691 100644
--- a/projects/cli-test/mgmt-cli.c
+++ b/projects/cli-test/mgmt-cli.c
@@ -3,7 +3,9 @@
* ---------
* Management CLI code.
*
- * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ * Copyright (c) 2016-2017, NORDUnet A/S All rights reserved.
+ * Copyright: 2020, The Commons Conservancy Cryptech Project
+ * SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -15,9 +17,9 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * - Neither the name of the NORDUnet nor the names of its contributors may
- * be used to endorse or promote products derived from this software
- * without specific prior written permission.
+ * - Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -31,140 +33,166 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
+#include <string.h>
+
+/* Rename both CMSIS HAL_OK and libhal HAL_OK to disambiguate */
+#define HAL_OK CMSIS_HAL_OK
#include "stm-init.h"
#include "stm-uart.h"
#include "stm-led.h"
+
#include "mgmt-cli.h"
+#include "mgmt-fpga.h"
+#include "mgmt-misc.h"
+#include "mgmt-show.h"
+#include "mgmt-test.h"
+#include "mgmt-keystore.h"
+#include "mgmt-masterkey.h"
+#ifdef DO_TIMING
+#include "mgmt-timing.h"
+#endif
+
+#undef HAL_OK
+#define HAL_OK LIBHAL_OK
+#include "hal.h"
+#undef HAL_OK
+
+#ifndef CLI_UART_RECVBUF_SIZE
+#define CLI_UART_RECVBUF_SIZE 256
+#endif
+
+typedef struct {
+ unsigned ridx;
+ unsigned widx;
+ mgmt_cli_dma_state_t rx_state;
+ uint8_t buf[CLI_UART_RECVBUF_SIZE];
+} ringbuf_t;
-#include <string.h>
+inline void ringbuf_init(ringbuf_t *rb)
+{
+ memset(rb, 0, sizeof(*rb));
+}
-extern uint8_t uart_rx;
+/* return number of characters read */
+inline int ringbuf_read_char(ringbuf_t *rb, uint8_t *c)
+{
+ if (rb->ridx != rb->widx) {
+ *c = rb->buf[rb->ridx];
+ if (++rb->ridx >= sizeof(rb->buf))
+ rb->ridx = 0;
+ return 1;
+ }
+ return 0;
+}
-struct uart_ringbuf_t {
- uint32_t enabled, ridx;
- enum mgmt_cli_dma_state rx_state;
- uint8_t buf[CLI_UART_RECVBUF_SIZE];
-};
+inline void ringbuf_write_char(ringbuf_t *rb, uint8_t c)
+{
+ rb->buf[rb->widx] = c;
+ if (++rb->widx >= sizeof(rb->buf))
+ rb->widx = 0;
+}
+
+static ringbuf_t uart_ringbuf;
-volatile struct uart_ringbuf_t uart_ringbuf = {1, 0, DMA_RX_STOP, {0}};
+/* current character received from UART */
+static uint8_t uart_rx;
-#define RINGBUF_RIDX(rb) (rb.ridx & CLI_UART_RECVBUF_MASK)
-#define RINGBUF_WIDX(rb) (sizeof(rb.buf) - __HAL_DMA_GET_COUNTER(huart_mgmt.hdmarx))
-#define RINGBUF_COUNT(rb) ((unsigned)(RINGBUF_WIDX(rb) - RINGBUF_RIDX(rb)))
-#define RINGBUF_READ(rb, dst) {dst = rb.buf[RINGBUF_RIDX(rb)]; rb.buf[RINGBUF_RIDX(rb)] = '.'; rb.ridx++;}
+/* Callback for HAL_UART_Receive_DMA().
+ */
+void HAL_UART1_RxCpltCallback(UART_HandleTypeDef *huart)
+{
+ huart = huart;
-void uart_cli_print(struct cli_def *cli __attribute__ ((unused)), const char *buf)
+ ringbuf_write_char(&uart_ringbuf, uart_rx);
+}
+
+static void uart_cli_print(struct cli_def *cli __attribute__ ((unused)), const char *buf)
{
- char crlf[] = "\r\n";
- uart_send_string2(STM_UART_MGMT, buf);
- uart_send_string2(STM_UART_MGMT, crlf);
+ uart_send_string(buf);
+ uart_send_string("\r\n");
}
-int uart_cli_read(struct cli_def *cli __attribute__ ((unused)), void *buf, size_t count)
+static ssize_t uart_cli_read(struct cli_def *cli __attribute__ ((unused)), void *buf, size_t count)
{
- uint32_t timeout = 0xffffff;
- while (count && timeout) {
- if (RINGBUF_COUNT(uart_ringbuf)) {
- RINGBUF_READ(uart_ringbuf, *(uint8_t *) buf);
- buf++;
- count--;
+ for (size_t i = 0; i < count; ++i) {
+ while (ringbuf_read_char(&uart_ringbuf, (uint8_t *)(buf + i)) == 0) {
}
- timeout--;
}
- if (! timeout) return 0;
-
- return 1;
+ return (ssize_t)count;
}
-int uart_cli_write(struct cli_def *cli __attribute__ ((unused)), const void *buf, size_t count)
+static ssize_t uart_cli_write(struct cli_def *cli __attribute__ ((unused)), const void *buf, size_t count)
{
- uart_send_bytes(STM_UART_MGMT, (uint8_t *) buf, count);
- return (int) count;
+ uart_send_bytes((uint8_t *) buf, count);
+ return (ssize_t)count;
}
-int control_mgmt_uart_dma_rx(enum mgmt_cli_dma_state state)
+int control_mgmt_uart_dma_rx(mgmt_cli_dma_state_t state)
{
if (state == DMA_RX_START) {
if (uart_ringbuf.rx_state != DMA_RX_START) {
- memset((void *) uart_ringbuf.buf, 0, sizeof(uart_ringbuf.buf));
-
- /* Start receiving data from the UART using DMA */
- HAL_UART_Receive_DMA(&huart_mgmt, (uint8_t *) uart_ringbuf.buf, sizeof(uart_ringbuf.buf));
- uart_ringbuf.ridx = 0;
+ ringbuf_init(&uart_ringbuf);
+ HAL_UART_Receive_DMA(&huart_mgmt, &uart_rx, 1);
uart_ringbuf.rx_state = DMA_RX_START;
}
return 1;
} else if (state == DMA_RX_STOP) {
- if (HAL_UART_DMAStop(&huart_mgmt) != HAL_OK) return 0;
+ if (HAL_UART_DMAStop(&huart_mgmt) != CMSIS_HAL_OK) return 0;
uart_ringbuf.rx_state = DMA_RX_STOP;
return 1;
}
return 0;
}
-int embedded_cli_loop(struct cli_def *cli)
+static struct cli_def *mgmt_cli_init(void)
{
- unsigned char c;
- int n = 0;
- static struct cli_loop_ctx ctx;
-
- memset(&ctx, 0, sizeof(ctx));
- ctx.insertmode = 1;
+ struct cli_def *cli;
+ cli = cli_init();
+ cli_read_callback(cli, uart_cli_read);
+ cli_write_callback(cli, uart_cli_write);
+ cli_print_callback(cli, uart_cli_print);
+ cli_set_banner(cli, "Cryptech Alpha test CLI");
+ cli_set_hostname(cli, "cryptech");
+ return cli;
+}
- cli->state = CLI_STATE_LOGIN;
+hal_user_t user;
- /* start off in unprivileged mode */
- cli_set_privilege(cli, PRIVILEGE_UNPRIVILEGED);
- cli_set_configmode(cli, MODE_EXEC, NULL);
+static int check_auth(const char *username, const char *password)
+{
+ if (strcmp(username, "ct") != 0)
+ return CLI_ERROR;
+ if (strcmp(password, "ct") != 0)
+ return CLI_ERROR;
+ return CLI_OK;
+}
- cli_error(cli, "%s", cli->banner);
+int cli_main(void)
+{
+ struct cli_def *cli;
+ cli = mgmt_cli_init();
+ cli_set_auth_callback(cli, check_auth);
+
+ configure_cli_show(cli);
+ configure_cli_fpga(cli);
+ configure_cli_misc(cli);
+ configure_cli_keystore(cli);
+ configure_cli_masterkey(cli);
+#ifdef DO_TIMING
+ configure_cli_timing(cli);
+#endif
while (1) {
- cli_loop_start_new_command(cli, &ctx);
-
- control_mgmt_uart_dma_rx(DMA_RX_START);
-
- while (1) {
- cli_loop_show_prompt(cli, &ctx);
-
- n = cli_loop_read_next_char(cli, &ctx, &c);
-
- /*
- cli_print(cli, "Next char: '%c'/%i, ringbuf ridx %i, widx %i",
- c, (int) c,
- uart_ringbuf.ridx,
- RINGBUF_WIDX(uart_ringbuf)
- */
- if (n == CLI_LOOP_CTRL_BREAK)
- break;
- if (n == CLI_LOOP_CTRL_CONTINUE)
- continue;
-
- n = cli_loop_process_char(cli, &ctx, c);
- if (n == CLI_LOOP_CTRL_BREAK)
- break;
- if (n == CLI_LOOP_CTRL_CONTINUE)
- continue;
- }
-
- if (ctx.l < 0) break;
+ control_mgmt_uart_dma_rx(DMA_RX_START);
- /* cli_print(cli, "Process command: '%s'", ctx.cmd); */
- n = cli_loop_process_cmd(cli, &ctx);
- if (n == CLI_LOOP_CTRL_BREAK)
- break;
+ cli_loop(cli, 0);
+ /* cli_loop returns when the user enters 'quit' or 'exit' */
+ cli_print(cli, "\nLogging out...\n");
+ user = HAL_USER_NONE;
}
- return CLI_OK;
+ /*NOTREACHED*/
+ return -1;
}
-void mgmt_cli_init(struct cli_def *cli)
-{
- cli_init(cli);
- cli_read_callback(cli, uart_cli_read);
- cli_write_callback(cli, uart_cli_write);
- cli_print_callback(cli, uart_cli_print);
- cli_set_banner(cli, "Cryptech Alpha");
- cli_set_hostname(cli, "cryptech");
- cli_telnet_protocol(cli, 0);
-}
diff --git a/projects/cli-test/mgmt-cli.h b/projects/cli-test/mgmt-cli.h
index 16c9fbd98..0b9c40c 100644
--- a/projects/cli-test/mgmt-cli.h
+++ b/projects/cli-test/mgmt-cli.h
@@ -35,52 +35,15 @@
#ifndef __STM32_MGMT_CLI_H
#define __STM32_MGMT_CLI_H
-#include "stm-init.h"
#include <libcli.h>
-
-/* A bunch of defines to make it easier to add/maintain the CLI commands.
- *
- */
-#define _cli_cmd_struct(name, fullname, func, help) \
- static struct cli_command cmd_##fullname##_s = \
- {(char *) #name, func, 0, help, \
- PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL, NULL, NULL}
-
-/* ROOT is a top-level label with no command */
-#define cli_command_root(name) \
- _cli_cmd_struct(name, name, NULL, NULL); \
- cli_register_command2(cli, &cmd_##name##_s, NULL)
-
-/* BRANCH is a label with a parent, but no command */
-#define cli_command_branch(parent, name) \
- _cli_cmd_struct(name, parent##_##name, NULL, NULL); \
- cli_register_command2(cli, &cmd_##parent##_##name##_s, &cmd_##parent##_s)
-
-/* NODE is a label with a parent and with a command associated with it */
-#define cli_command_node(parent, name, help) \
- _cli_cmd_struct(name, parent##_##name, cmd_##parent##_##name, (char *) help); \
- cli_register_command2(cli, &cmd_##parent##_##name##_s, &cmd_##parent##_s)
-
-/* ROOT NODE is a label without a parent, but with a command associated with it */
-#define cli_command_root_node(name, help) \
- _cli_cmd_struct(name, name, cmd_##name, (char *) help); \
- cli_register_command2(cli, &cmd_##name##_s, NULL)
-
-
-#define CLI_UART_RECVBUF_SIZE 256 /* This must be a power of 2 */
-#define CLI_UART_RECVBUF_MASK (CLI_UART_RECVBUF_SIZE - 1)
-
-enum mgmt_cli_dma_state {
+typedef enum {
DMA_RX_STOP,
DMA_RX_START,
-};
+} mgmt_cli_dma_state_t;
+
+extern int control_mgmt_uart_dma_rx(mgmt_cli_dma_state_t state);
-extern void uart_cli_print(struct cli_def *cli __attribute__ ((unused)), const char *buf);
-extern int uart_cli_read(struct cli_def *cli __attribute__ ((unused)), void *buf, size_t count);
-extern int uart_cli_write(struct cli_def *cli __attribute__ ((unused)), const void *buf, size_t count);
-extern int embedded_cli_loop(struct cli_def *cli);
-extern void mgmt_cli_init(struct cli_def *cli);
-extern int control_mgmt_uart_dma_rx(enum mgmt_cli_dma_state state);
+extern int cli_main(void);
#endif /* __STM32_MGMT_CLI_H */
diff --git a/projects/cli-test/mgmt-dfu.c b/projects/cli-test/mgmt-dfu.c
index 27fd722..c7273f4 100644
--- a/projects/cli-test/mgmt-dfu.c
+++ b/projects/cli-test/mgmt-dfu.c
@@ -40,7 +40,10 @@
#include <string.h>
-extern uint32_t update_crc(uint32_t crc, uint8_t *buf, int len);
+#define DFU_FIRMWARE_ADDR ((uint32_t) &CRYPTECH_FIRMWARE_START)
+#define DFU_FIRMWARE_END_ADDR ((uint32_t) &CRYPTECH_FIRMWARE_END)
+#define DFU_UPLOAD_CHUNK_SIZE 256
+#define HARDWARE_EARLY_DFU_JUMP 0xBADABADA
/* Linker symbols are strange in C. Make regular pointers for sanity. */
__IO uint32_t *dfu_control = &CRYPTECH_DFU_CONTROL;
@@ -53,25 +56,29 @@ __IO uint32_t *dfu_msp_ptr = &CRYPTECH_FIRMWARE_START;
*/
__IO uint32_t *dfu_code_ptr = &CRYPTECH_FIRMWARE_START + 1;
-
-
-int cmd_dfu_dump(struct cli_def *cli, const char *command, char *argv[], int argc)
+static int cmd_dfu_dump(struct cli_def *cli, const char *command, char *argv[], int argc)
{
+ command = command;
+ argv = argv;
+ argc = argc;
+
cli_print(cli, "First 256 bytes from DFU application address %p:\r\n", dfu_firmware);
- uart_send_hexdump(STM_UART_MGMT, (uint8_t *) dfu_firmware, 0, 0xff);
- uart_send_string2(STM_UART_MGMT, (char *) "\r\n\r\n");
+ uart_send_hexdump((uint8_t *) dfu_firmware, 0, 0xff);
+ cli_print(cli, "\n");
return CLI_OK;
}
-int cmd_dfu_erase(struct cli_def *cli, const char *command, char *argv[], int argc)
+static int cmd_dfu_erase(struct cli_def *cli, const char *command, char *argv[], int argc)
{
int status;
- cli_print(cli, "Erasing flash sectors %i to %i (address %p to %p) - expect the CLI to crash now",
- stm_flash_sector_num((uint32_t) dfu_firmware),
- stm_flash_sector_num((uint32_t) dfu_firmware_end),
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ cli_print(cli, "Erasing flash address %p to %p - expect the CLI to crash now",
dfu_firmware,
dfu_firmware_end);
@@ -82,9 +89,14 @@ int cmd_dfu_erase(struct cli_def *cli, const char *command, char *argv[], int ar
return CLI_OK;
}
-int cmd_dfu_jump(struct cli_def *cli, const char *command, char *argv[], int argc)
+static int cmd_dfu_jump(struct cli_def *cli, const char *command, char *argv[], int argc)
{
uint32_t i;
+
+ command = command;
+ argv = argv;
+ argc = argc;
+
/* Load first byte from the DFU_FIRMWARE_PTR to verify it contains an IVT before
* jumping there.
*/
@@ -112,9 +124,11 @@ int cmd_dfu_jump(struct cli_def *cli, const char *command, char *argv[], int arg
void configure_cli_dfu(struct cli_def *cli)
{
- cli_command_root(dfu);
+ struct cli_command *c;
+
+ c = cli_register_command(cli, NULL, "dfu", NULL, 0, 0, NULL);
- cli_command_node(dfu, dump, "Show the first 256 bytes of the loaded firmware");
- cli_command_node(dfu, jump, "Jump to the loaded firmware");
- cli_command_node(dfu, erase, "Erase the firmware memory (will crash the CLI)");
+ cli_register_command(cli, c, "dump", cmd_dfu_dump, 0, 0, "Show the first 256 bytes of the loaded firmware");
+ cli_register_command(cli, c, "jump", cmd_dfu_jump, 0, 0, "Jump to the loaded firmware");
+ cli_register_command(cli, c, "erase", cmd_dfu_erase, 0, 0, "Erase the firmware memory (will crash the CLI)");
}
diff --git a/projects/cli-test/mgmt-dfu.h b/projects/cli-test/mgmt-dfu.h
index ac6589c..6128b35 100644
--- a/projects/cli-test/mgmt-dfu.h
+++ b/projects/cli-test/mgmt-dfu.h
@@ -35,7 +35,6 @@
#ifndef __STM32_CLI_MGMT_DFU_H
#define __STM32_CLI_MGMT_DFU_H
-#include "stm-init.h"
#include <libcli.h>
/* symbols defined in the linker script (STM32F429BI.ld) */
@@ -43,17 +42,6 @@ extern uint32_t CRYPTECH_FIRMWARE_START;
extern uint32_t CRYPTECH_FIRMWARE_END;
extern uint32_t CRYPTECH_DFU_CONTROL;
-#define DFU_FIRMWARE_ADDR ((uint32_t) &CRYPTECH_FIRMWARE_START)
-#define DFU_FIRMWARE_END_ADDR ((uint32_t) &CRYPTECH_FIRMWARE_END)
-#define DFU_UPLOAD_CHUNK_SIZE 256
-#define HARDWARE_EARLY_DFU_JUMP 0xBADABADA
-
-extern __IO uint32_t *dfu_control;
-extern __IO uint32_t *dfu_firmware;
-extern __IO uint32_t *dfu_msp_ptr;
-extern __IO uint32_t *dfu_code_ptr;
-
-
extern void configure_cli_dfu(struct cli_def *cli);
#endif /* __STM32_CLI_MGMT_DFU_H */
diff --git a/projects/cli-test/mgmt-fpga.c b/projects/cli-test/mgmt-fpga.c
index 8c1b2a8..b913316 100644
--- a/projects/cli-test/mgmt-fpga.c
+++ b/projects/cli-test/mgmt-fpga.c
@@ -3,7 +3,7 @@
* -----------
* CLI code to manage the FPGA configuration etc.
*
- * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ * Copyright (c) 2016-2017, NORDUnet A/S All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -43,25 +43,43 @@
#include <string.h>
-volatile uint32_t dfu_offset = 0;
+static volatile uint32_t dfu_offset = 0;
-int _flash_write_callback(uint8_t *buf, size_t len) {
- int res = fpgacfg_write_data(dfu_offset, buf, BITSTREAM_UPLOAD_CHUNK_SIZE) == 1;
+
+static HAL_StatusTypeDef _flash_write_callback(uint8_t *buf, size_t len)
+{
+ HAL_StatusTypeDef res;
+
+ if ((dfu_offset % FPGACFG_SECTOR_SIZE) == 0)
+ /* first page in sector, need to erase sector */
+ if ((res = fpgacfg_erase_sector(dfu_offset / FPGACFG_SECTOR_SIZE)) != HAL_OK)
+ return res;
+
+ /* fpgacfg_write_data (a thin wrapper around n25q128_write_data)
+ * requires the offset and length to be page-aligned. The last chunk
+ * will be short, so we pad it out to the full chunk size.
+ */
+ len = len;
+ res = fpgacfg_write_data(dfu_offset, buf, BITSTREAM_UPLOAD_CHUNK_SIZE);
dfu_offset += BITSTREAM_UPLOAD_CHUNK_SIZE;
return res;
}
-int cmd_fpga_bitstream_upload(struct cli_def *cli, const char *command, char *argv[], int argc)
+static int cmd_fpga_bitstream_upload(struct cli_def *cli, const char *command, char *argv[], int argc)
{
uint8_t buf[BITSTREAM_UPLOAD_CHUNK_SIZE];
+ command = command;
+ argv = argv;
+ argc = argc;
+
dfu_offset = 0;
fpgacfg_access_control(ALLOW_ARM);
cli_print(cli, "Checking if FPGA config memory is accessible");
- if (fpgacfg_check_id() != 1) {
+ if (fpgacfg_check_id() != HAL_OK) {
cli_print(cli, "ERROR: FPGA config memory not accessible. Check that jumpers JP7 and JP8 are installed.");
return CLI_ERROR;
}
@@ -74,12 +92,16 @@ int cmd_fpga_bitstream_upload(struct cli_def *cli, const char *command, char *ar
return CLI_OK;
}
-int cmd_fpga_bitstream_erase(struct cli_def *cli, const char *command, char *argv[], int argc)
+static int cmd_fpga_bitstream_erase(struct cli_def *cli, const char *command, char *argv[], int argc)
{
+ command = command;
+ argv = argv;
+ argc = argc;
+
fpgacfg_access_control(ALLOW_ARM);
cli_print(cli, "Checking if FPGA config memory is accessible");
- if (fpgacfg_check_id() != 1) {
+ if (fpgacfg_check_id() != HAL_OK) {
cli_print(cli, "ERROR: FPGA config memory not accessible. Check that jumpers JP7 and JP8 are installed.");
return CLI_ERROR;
}
@@ -90,7 +112,7 @@ int cmd_fpga_bitstream_erase(struct cli_def *cli, const char *command, char *arg
*
* This command could be made to accept an argument indicating the whole memory should be erased.
*/
- if (! fpgacfg_erase_sectors(1)) {
+ if (fpgacfg_erase_sector(0) != HAL_OK) {
cli_print(cli, "Erasing first sector in FPGA config memory failed");
return CLI_ERROR;
}
@@ -101,8 +123,12 @@ int cmd_fpga_bitstream_erase(struct cli_def *cli, const char *command, char *arg
return CLI_OK;
}
-int cmd_fpga_reset(struct cli_def *cli, const char *command, char *argv[], int argc)
+static int cmd_fpga_reset(struct cli_def *cli, const char *command, char *argv[], int argc)
{
+ command = command;
+ argv = argv;
+ argc = argc;
+
fpgacfg_access_control(ALLOW_FPGA);
fpgacfg_reset_fpga(RESET_FULL);
cli_print(cli, "FPGA has been reset");
@@ -110,8 +136,12 @@ int cmd_fpga_reset(struct cli_def *cli, const char *command, char *argv[], int a
return CLI_OK;
}
-int cmd_fpga_reset_registers(struct cli_def *cli, const char *command, char *argv[], int argc)
+static int cmd_fpga_reset_registers(struct cli_def *cli, const char *command, char *argv[], int argc)
{
+ command = command;
+ argv = argv;
+ argc = argc;
+
fpgacfg_access_control(ALLOW_FPGA);
fpgacfg_reset_fpga(RESET_REGISTERS);
cli_print(cli, "FPGA registers have been reset");
@@ -121,16 +151,19 @@ int cmd_fpga_reset_registers(struct cli_def *cli, const char *command, char *arg
void configure_cli_fpga(struct cli_def *cli)
{
- /* fpga */
- cli_command_root(fpga);
+ struct cli_command *c = cli_register_command(cli, NULL, "fpga", NULL, 0, 0, NULL);
+
/* fpga reset */
- cli_command_node(fpga, reset, "Reset FPGA (config reset)");
+ struct cli_command *c_reset = cli_register_command(cli, c, "reset", cmd_fpga_reset, 0, 0, "Reset FPGA (config reset)");
+
/* fpga reset registers */
- cli_command_node(fpga_reset, registers, "Reset FPGA registers (soft reset)");
+ cli_register_command(cli, c_reset, "registers", cmd_fpga_reset_registers, 0, 0, "Reset FPGA registers (soft reset)");
+
+ struct cli_command *c_bitstream = cli_register_command(cli, c, "bitstream", NULL, 0, 0, NULL);
- cli_command_branch(fpga, bitstream);
/* fpga bitstream upload */
- cli_command_node(fpga_bitstream, upload, "Upload new FPGA bitstream");
+ cli_register_command(cli, c_bitstream, "upload", cmd_fpga_bitstream_upload, 0, 0, "Upload new FPGA bitstream");
+
/* fpga bitstream erase */
- cli_command_node(fpga_bitstream, erase, "Erase FPGA config memory");
+ cli_register_command(cli, c_bitstream, "erase", cmd_fpga_bitstream_erase, 0, 0, "Erase FPGA config memory");
}
diff --git a/projects/cli-test/mgmt-fpga.h b/projects/cli-test/mgmt-fpga.h
index ce185de..9d0aedc 100644
--- a/projects/cli-test/mgmt-fpga.h
+++ b/projects/cli-test/mgmt-fpga.h
@@ -35,7 +35,6 @@
#ifndef __STM32_CLI_MGMT_FPGA_H
#define __STM32_CLI_MGMT_FPGA_H
-#include "stm-init.h"
#include <libcli.h>
diff --git a/projects/cli-test/mgmt-keystore.c b/projects/cli-test/mgmt-keystore.c
new file mode 100644
index 0000000..6d0d38d
--- /dev/null
+++ b/projects/cli-test/mgmt-keystore.c
@@ -0,0 +1,412 @@
+/*
+ * mgmt-keystore.c
+ * ---------------
+ * CLI 'keystore' commands.
+ *
+ * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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.
+ */
+
+/* Rename both CMSIS HAL_OK and libhal HAL_OK to disambiguate */
+
+#define HAL_OK CMSIS_HAL_OK
+#include "stm-init.h"
+#include "stm-keystore.h"
+#include "stm-fpgacfg.h"
+#include "stm-uart.h"
+#include "mgmt-cli.h"
+#include "mgmt-show.h"
+#undef HAL_OK
+
+#define HAL_OK LIBHAL_OK
+#include "hal.h"
+#warning Really should not be including hal_internal.h here, fix API instead of bypassing it
+#include "hal_internal.h"
+#undef HAL_OK
+
+#include <stdlib.h>
+#include <string.h>
+
+
+static int cmd_keystore_set_pin(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ hal_user_t user;
+ hal_error_t status;
+ hal_client_handle_t client = { -1 };
+
+ command = command;
+
+ if (argc != 2) {
+ cli_print(cli, "Wrong number of arguments (%i).", argc);
+ cli_print(cli, "Syntax: keystore set pin <user|so|wheel> <pin>");
+ return CLI_ERROR;
+ }
+
+ if (!strcmp(argv[0], "user"))
+ user = HAL_USER_NORMAL;
+ else if (!strcmp(argv[0], "so"))
+ user = HAL_USER_SO;
+ else if (!strcmp(argv[0], "wheel"))
+ user = HAL_USER_WHEEL;
+ else {
+ cli_print(cli, "First argument must be 'user', 'so' or 'wheel' - not '%s'", argv[0]);
+ return CLI_ERROR;
+ }
+
+ status = hal_rpc_set_pin(client, user, argv[1], strlen(argv[1]));
+ if (status != LIBHAL_OK) {
+ cli_print(cli, "Failed setting PIN: %s", hal_error_string(status));
+ return CLI_ERROR;
+ }
+
+ return CLI_OK;
+}
+
+static int cmd_keystore_clear_pin(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ hal_user_t user;
+ hal_error_t status;
+ hal_client_handle_t client = { -1 };
+
+ command = command;
+
+ if (argc != 1) {
+ cli_print(cli, "Wrong number of arguments (%i).", argc);
+ cli_print(cli, "Syntax: keystore clear pin <user|so|wheel>");
+ return CLI_ERROR;
+ }
+
+ if (!strcmp(argv[0], "user"))
+ user = HAL_USER_NORMAL;
+ else if (!strcmp(argv[0], "so"))
+ user = HAL_USER_SO;
+ else if (!strcmp(argv[0], "wheel"))
+ user = HAL_USER_WHEEL;
+ else {
+ cli_print(cli, "First argument must be 'user', 'so' or 'wheel' - not '%s'", argv[0]);
+ return CLI_ERROR;
+ }
+
+ status = hal_rpc_set_pin(client, user, "", 0);
+ if (status != LIBHAL_OK) {
+ cli_print(cli, "Failed setting PIN: %s", hal_error_string(status));
+ return CLI_ERROR;
+ }
+
+ return CLI_OK;
+}
+
+static int cmd_keystore_set_pin_iterations(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ hal_error_t status;
+ hal_client_handle_t client = { -1 };
+
+ command = command;
+
+ if (argc != 1) {
+ cli_print(cli, "Wrong number of arguments (%i).", argc);
+ cli_print(cli, "Syntax: keystore set pin iterations <number>");
+ return CLI_ERROR;
+ }
+
+ status = hal_set_pin_default_iterations(client, strtoul(argv[0], NULL, 0));
+ if (status != LIBHAL_OK) {
+ cli_print(cli, "Failed setting iterations: %s", hal_error_string(status));
+ return CLI_ERROR;
+ }
+
+ return CLI_OK;
+}
+
+/*
+ * This is badly broken under either old or new keystore API:
+ *
+ * + DER is a binary format, it's not safe to read it this way,
+ * and strlen() will not do what anybody wants;
+ *
+ * + As written, this stores an EC public key on no known curve,
+ * ie, useless nonsense.
+ *
+ * The usual text format for DER objects is Base64, often with
+ * so-called "PEM" header and footer lines. Key type, curve, etcetera
+ * would be extra command line parameters.
+ */
+#if 0
+static int cmd_keystore_set_key(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ hal_error_t status;
+ int hint = 0;
+
+ command = command;
+
+ if (argc != 2) {
+ cli_print(cli, "Wrong number of arguments (%i).", argc);
+ cli_print(cli, "Syntax: keystore set key <name> <der>");
+ return CLI_ERROR;
+ }
+
+ if ((status = hal_ks_store(HAL_KEY_TYPE_EC_PUBLIC,
+ HAL_CURVE_NONE,
+ 0,
+ (uint8_t *) argv[0], strlen(argv[0]),
+ (uint8_t *) argv[1], strlen(argv[1]),
+ &hint)) != LIBHAL_OK) {
+
+ cli_print(cli, "Failed storing key: %s", hal_error_string(status));
+ return CLI_ERROR;
+ }
+
+ cli_print(cli, "Stored key %i", hint);
+
+ return CLI_OK;
+}
+#endif /* 0 */
+
+static int cmd_keystore_delete_key(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ const hal_client_handle_t client = { HAL_HANDLE_NONE };
+ const hal_session_handle_t session = { HAL_HANDLE_NONE };
+ hal_pkey_handle_t pkey = { HAL_HANDLE_NONE };
+ hal_error_t status;
+ hal_uuid_t name;
+
+ command = command;
+
+ if (argc != 1) {
+ cli_print(cli, "Wrong number of arguments (%i).", argc);
+ cli_print(cli, "Syntax: keystore delete key <name>");
+ return CLI_ERROR;
+ }
+
+ if ((status = hal_uuid_parse(&name, argv[0])) != LIBHAL_OK) {
+ cli_print(cli, "Couldn't parse key name: %s", hal_error_string(status));
+ return CLI_ERROR;
+ }
+
+ if ((status = hal_rpc_pkey_open(client, session, &pkey, &name)) != LIBHAL_OK ||
+ (status = hal_rpc_pkey_delete(pkey)) != LIBHAL_OK) {
+ cli_print(cli, "Failed deleting key: %s", hal_error_string(status));
+ return CLI_ERROR;
+ }
+
+ cli_print(cli, "Deleted key %s", argv[0]);
+
+ return CLI_OK;
+}
+
+static int cmd_keystore_show_data(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ uint8_t buf[KEYSTORE_PAGE_SIZE];
+ uint32_t i;
+
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ if (keystore_check_id() != CMSIS_HAL_OK) {
+ cli_print(cli, "ERROR: The keystore memory is not accessible.");
+ }
+
+ memset(buf, 0, sizeof(buf));
+ if ((i = keystore_read_data(0, buf, sizeof(buf))) != CMSIS_HAL_OK) {
+ cli_print(cli, "Failed reading first page from keystore memory: %li", i);
+ return CLI_ERROR;
+ }
+
+ cli_print(cli, "First page from keystore memory:\r\n");
+ uart_send_hexdump(buf, 0, sizeof(buf) - 1);
+ cli_print(cli, "\n");
+
+ return CLI_OK;
+}
+
+static int show_keys(struct cli_def *cli, const char *title)
+{
+ const hal_client_handle_t client = { -1 };
+ const hal_session_handle_t session = { HAL_HANDLE_NONE };
+ char key_name[HAL_UUID_TEXT_SIZE];
+ hal_uuid_t previous_uuid = {{0}};
+ hal_pkey_handle_t pkey;
+ hal_curve_name_t curve;
+ hal_key_flags_t flags;
+ unsigned n, state = 0;
+ hal_key_type_t type;
+ hal_error_t status;
+ hal_uuid_t uuids[50];
+ int done = 0;
+
+ cli_print(cli, title);
+
+ while (!done) {
+
+ if ((status = hal_rpc_pkey_match(client, session, HAL_KEY_TYPE_NONE, HAL_CURVE_NONE,
+ 0, 0, NULL, 0, &state, uuids, &n,
+ sizeof(uuids)/sizeof(*uuids),
+ &previous_uuid)) != LIBHAL_OK) {
+ cli_print(cli, "Could not fetch UUID list: %s", hal_error_string(status));
+ return 0;
+ }
+
+ done = n < sizeof(uuids)/sizeof(*uuids);
+
+ if (!done)
+ previous_uuid = uuids[sizeof(uuids)/sizeof(*uuids) - 1];
+
+ for (unsigned i = 0; i < n; i++) {
+
+ if ((status = hal_uuid_format(&uuids[i], key_name, sizeof(key_name))) != LIBHAL_OK) {
+ cli_print(cli, "Could not convert key name: %s",
+ hal_error_string(status));
+ return 0;
+ }
+
+ if ((status = hal_rpc_pkey_open(client, session, &pkey, &uuids[i])) != LIBHAL_OK) {
+ cli_print(cli, "Could not open key %s: %s",
+ key_name, hal_error_string(status));
+ return 0;
+ }
+
+ if ((status = hal_rpc_pkey_get_key_type(pkey, &type)) != LIBHAL_OK ||
+ (status = hal_rpc_pkey_get_key_curve(pkey, &curve)) != LIBHAL_OK ||
+ (status = hal_rpc_pkey_get_key_flags(pkey, &flags)) != LIBHAL_OK)
+ cli_print(cli, "Could not fetch metadata for key %s: %s",
+ key_name, hal_error_string(status));
+
+ if (status == LIBHAL_OK)
+ status = hal_rpc_pkey_close(pkey);
+ else
+ (void) hal_rpc_pkey_close(pkey);
+
+ if (status != LIBHAL_OK)
+ return 0;
+
+ const char *type_name = "unknown";
+ switch (type) {
+ case HAL_KEY_TYPE_NONE: type_name = "none"; break;
+ case HAL_KEY_TYPE_RSA_PRIVATE: type_name = "RSA private"; break;
+ case HAL_KEY_TYPE_RSA_PUBLIC: type_name = "RSA public"; break;
+ case HAL_KEY_TYPE_EC_PRIVATE: type_name = "EC private"; break;
+ case HAL_KEY_TYPE_EC_PUBLIC: type_name = "EC public"; break;
+ }
+
+ const char *curve_name = "unknown";
+ switch (curve) {
+ case HAL_CURVE_NONE: curve_name = "none"; break;
+ case HAL_CURVE_P256: curve_name = "P-256"; break;
+ case HAL_CURVE_P384: curve_name = "P-384"; break;
+ case HAL_CURVE_P521: curve_name = "P-521"; break;
+ }
+
+ cli_print(cli, "Key %2i, name %s, type %s, curve %s, flags 0x%lx",
+ i, key_name, type_name, curve_name, (unsigned long) flags);
+ }
+ }
+
+ return 1;
+}
+
+static int cmd_keystore_show_keys(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ if (show_keys(cli, "Keystore:"))
+ return CLI_OK;
+ else
+ return CLI_ERROR;
+}
+
+static int cmd_keystore_erase(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ hal_error_t err;
+ int status;
+
+ command = command;
+
+ if (argc != 1 || strcmp(argv[0], "YesIAmSure") != 0) {
+ cli_print(cli, "Syntax: keystore erase YesIAmSure");
+ return CLI_ERROR;
+ }
+
+ cli_print(cli, "OK, erasing keystore, this might take a while...");
+ if ((status = keystore_erase_bulk()) != CMSIS_HAL_OK) {
+ cli_print(cli, "Failed erasing token keystore: %i", status);
+ return CLI_ERROR;
+ }
+
+ if ((err = hal_ks_init(hal_ks_token, 0)) != LIBHAL_OK) {
+ cli_print(cli, "Failed to reinitialize token keystore: %s", hal_error_string(err));
+ return CLI_ERROR;
+ }
+
+ if ((err = hal_ks_init(hal_ks_volatile, 0)) != LIBHAL_OK) {
+ cli_print(cli, "Failed to reinitialize memory keystore: %s", hal_error_string(err));
+ return CLI_ERROR;
+ }
+
+ cli_print(cli, "Keystore erased");
+ return CLI_OK;
+}
+
+void configure_cli_keystore(struct cli_def *cli)
+{
+ struct cli_command *c = cli_register_command(cli, NULL, "keystore", NULL, 0, 0, NULL);
+
+ struct cli_command *c_set = cli_register_command(cli, c, "set", NULL, 0, 0, NULL);
+ struct cli_command *c_clear = cli_register_command(cli, c, "clear", NULL, 0, 0, NULL);
+ struct cli_command *c_delete = cli_register_command(cli, c, "delete", NULL, 0, 0, NULL);
+ struct cli_command *c_show = cli_register_command(cli, c, "show", NULL, 0, 0, NULL);
+
+ /* keystore erase */
+ cli_register_command(cli, c, "erase", cmd_keystore_erase, 0, 0, "Erase the whole keystore");
+
+ /* keystore set pin */
+ struct cli_command *c_set_pin = cli_register_command(cli, c_set, "pin", cmd_keystore_set_pin, 0, 0, "Set either 'wheel', 'user' or 'so' PIN");
+
+ /* keystore set pin iterations */
+ cli_register_command(cli, c_set_pin, "iterations", cmd_keystore_set_pin_iterations, 0, 0, "Set PBKDF2 iterations for PINs");
+
+ /* keystore clear pin */
+ cli_register_command(cli, c_clear, "pin", cmd_keystore_clear_pin, 0, 0, "Clear either 'wheel', 'user' or 'so' PIN");
+
+#if 0
+ /* keystore set key */
+ cli_register_command(cli, c_set, "key", cmd_keystore_set_key, 0, 0, "Set a key");
+#endif
+
+ /* keystore delete key */
+ cli_register_command(cli, c_delete, "key", cmd_keystore_delete_key, 0, 0, "Delete a key");
+
+ /* keystore show data */
+ cli_register_command(cli, c_show, "data", cmd_keystore_show_data, 0, 0, "Dump the first page from the keystore memory");
+
+ /* keystore show keys */
+ cli_register_command(cli, c_show, "keys", cmd_keystore_show_keys, 0, 0, "Show what keys are in the keystore");
+
+}
diff --git a/projects/cli-test/mgmt-keystore.h b/projects/cli-test/mgmt-keystore.h
new file mode 100644
index 0000000..9e14ac6
--- /dev/null
+++ b/projects/cli-test/mgmt-keystore.h
@@ -0,0 +1,42 @@
+/*
+ * mgmt-keystore.h
+ * ----------
+ * Management CLI 'keystore' functions.
+ *
+ * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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 __STM32_CLI_MGMT_KEYSTORE_H
+#define __STM32_CLI_MGMT_KEYSTORE_H
+
+#include <libcli.h>
+
+extern void configure_cli_keystore(struct cli_def *cli);
+
+#endif /* __STM32_CLI_MGMT_KEYSTORE_H */
diff --git a/projects/cli-test/mgmt-keywrap.c b/projects/cli-test/mgmt-keywrap.c
new file mode 100644
index 0000000..7d3e219
--- /dev/null
+++ b/projects/cli-test/mgmt-keywrap.c
@@ -0,0 +1,316 @@
+/*
+ * mgmt-keywrap.h
+ * -----------
+ * Management CLI functions related to AES keywrap
+ *
+ * Copyright (c) 2018, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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.
+ */
+
+#define HAL_OK CMSIS_HAL_OK
+#include "stm-init.h"
+#include "stm-uart.h"
+#include "mgmt-cli.h"
+#include "mgmt-keywrap.h"
+#undef HAL_OK
+
+#define HAL_OK LIBHAL_OK
+#include "hal.h"
+#include "hal_internal.h"
+#undef HAL_OK
+
+#include <string.h>
+
+/* test vectors and test code are from test-aes-key-wrap.c */
+
+/*
+ * Test cases from RFC 5649 all use a 192-bit key, which our AES
+ * implementation doesn't support, so had to write our own.
+ */
+
+static const uint8_t Q[] = { /* Plaintext, 81 bytes */
+ 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21, 0x20, 0x20, 0x4d, 0x79, 0x20, 0x6e,
+ 0x61, 0x6d, 0x65, 0x20, 0x69, 0x73, 0x20, 0x49, 0x6e, 0x69, 0x67, 0x6f,
+ 0x20, 0x4d, 0x6f, 0x6e, 0x74, 0x6f, 0x79, 0x61, 0x2e, 0x20, 0x20, 0x59,
+ 0x6f, 0x75, 0x20, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x20, 0x6d, 0x79, 0x20,
+ 0x41, 0x45, 0x53, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x77, 0x72, 0x61, 0x70,
+ 0x70, 0x65, 0x72, 0x2e, 0x20, 0x20, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72,
+ 0x65, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x69, 0x65, 0x2e
+};
+
+static const uint8_t K_128[] = { /* 128-bit KEK, 16 bytes */
+ 0xbc, 0x2a, 0xd8, 0x90, 0xd8, 0x91, 0x10, 0x65, 0xf0, 0x42, 0x10, 0x1b,
+ 0x4a, 0x6b, 0xaf, 0x99
+};
+
+static const uint8_t K_256[] = { /* 256-bit KEK, 32 bytes */
+ 0xe3, 0x97, 0x52, 0x81, 0x2b, 0x7e, 0xc2, 0xa4, 0x6a, 0xac, 0x50, 0x18,
+ 0x0d, 0x10, 0xc6, 0x85, 0x2c, 0xcf, 0x86, 0x0a, 0xa9, 0x4f, 0x69, 0xab,
+ 0x16, 0xa6, 0x4f, 0x3e, 0x96, 0xa0, 0xbd, 0x9e
+};
+
+static const uint8_t C_128[] = { /* Plaintext wrapped by 128-bit KEK, 96 bytes */
+ 0xb0, 0x10, 0x91, 0x7b, 0xe7, 0x67, 0x9c, 0x10, 0x16, 0x64, 0xe7, 0x73,
+ 0xd2, 0x68, 0xba, 0xed, 0x8c, 0x50, 0x49, 0x80, 0x16, 0x2f, 0x4e, 0x97,
+ 0xe8, 0x45, 0x5c, 0x2f, 0x2b, 0x7a, 0x88, 0x0e, 0xd8, 0xef, 0xaa, 0x40,
+ 0xb0, 0x2e, 0xb4, 0x50, 0xe7, 0x60, 0xf7, 0xbb, 0xed, 0x56, 0x79, 0x16,
+ 0x65, 0xb7, 0x13, 0x9b, 0x4c, 0x66, 0x86, 0x5f, 0x4d, 0x53, 0x2d, 0xcd,
+ 0x83, 0x41, 0x01, 0x35, 0x0d, 0x06, 0x39, 0x4e, 0x9e, 0xfe, 0x68, 0xc5,
+ 0x2f, 0x37, 0x33, 0x99, 0xbb, 0x88, 0xf7, 0x76, 0x1e, 0x82, 0x48, 0xd6,
+ 0xa2, 0xf3, 0x9b, 0x92, 0x01, 0x65, 0xcb, 0x48, 0x36, 0xf5, 0x42, 0xd3
+};
+
+static const uint8_t C_256[] = { /* Plaintext wrapped by 256-bit KEK, 96 bytes */
+ 0x08, 0x00, 0xbc, 0x1b, 0x35, 0xe4, 0x2a, 0x69, 0x3f, 0x43, 0x07, 0x54,
+ 0x31, 0xba, 0xb6, 0x89, 0x7c, 0x64, 0x9f, 0x03, 0x84, 0xc4, 0x4a, 0x71,
+ 0xdb, 0xcb, 0xae, 0x55, 0x30, 0xdf, 0xb0, 0x2b, 0xc3, 0x91, 0x5d, 0x07,
+ 0xa9, 0x24, 0xdb, 0xe7, 0xbe, 0x4d, 0x0d, 0x62, 0xd4, 0xf8, 0xb1, 0x94,
+ 0xf1, 0xb9, 0x22, 0xb5, 0x94, 0xab, 0x7e, 0x0b, 0x15, 0x6a, 0xd9, 0x5f,
+ 0x6c, 0x20, 0xb7, 0x7e, 0x13, 0x19, 0xfa, 0xc4, 0x70, 0xec, 0x0d, 0xbd,
+ 0xf7, 0x01, 0xc6, 0xb3, 0x9a, 0x19, 0xaf, 0xf2, 0x47, 0x68, 0xea, 0x7e,
+ 0x97, 0x7e, 0x52, 0x2e, 0xd4, 0x03, 0x31, 0xcb, 0x22, 0xb6, 0xfe, 0xf5
+};
+
+static int run_test(struct cli_def *cli,
+ const uint8_t * const K, const size_t K_len,
+ const uint8_t * const C, const size_t C_len)
+{
+#define TC_BUFSIZE 96 /* sizeof(C) */
+ const size_t Q_len = sizeof(Q);
+ uint8_t q[TC_BUFSIZE], c[TC_BUFSIZE];
+ size_t q_len = sizeof(q), c_len = sizeof(c);
+ hal_error_t err;
+ int ok1 = 1, ok2 = 1;
+
+ /*
+ * Wrap and compare results.
+ */
+
+ cli_print(cli, "Wrapping with %lu-bit KEK...", (unsigned long) K_len * 8);
+ if ((err = hal_aes_keywrap(NULL, K, K_len, Q, Q_len, c, &c_len)) != LIBHAL_OK) {
+ cli_print(cli, "Couldn't wrap with %lu-bit KEK: %s",
+ (unsigned long) K_len * 8, hal_error_string(err));
+ ok1 = 0;
+ }
+ else if (C_len != c_len || memcmp(C, c, C_len) != 0) {
+ cli_print(cli, "Ciphertext mismatch:\n Want: ");
+ uart_send_hexdump(C, 0, C_len - 1);
+ cli_print(cli, "\n Got: ");
+ uart_send_hexdump(c, 0, c_len - 1);
+ cli_print(cli, "");
+ ok1 = 0;
+ }
+ else {
+ cli_print(cli, "OK");
+ }
+
+ /*
+ * Unwrap and compare results.
+ */
+
+ cli_print(cli, "Unwrapping with %lu-bit KEK...", (unsigned long) K_len * 8);
+ if ((err = hal_aes_keyunwrap(NULL, K, K_len, C, C_len, q, &q_len)) != LIBHAL_OK) {
+ cli_print(cli, "Couldn't unwrap with %lu-bit KEK: %s",
+ (unsigned long) K_len * 8, hal_error_string(err));
+ ok2 = 0;
+ }
+ else if (Q_len != q_len || memcmp(Q, q, Q_len) != 0) {
+ cli_print(cli, "Plaintext mismatch:\n Want: ");
+ uart_send_hexdump(Q, 0, Q_len - 1);
+ cli_print(cli, "\n Got: ");
+ uart_send_hexdump(q, 0, q_len - 1);
+ cli_print(cli, "");
+ ok2 = 0;
+ }
+ else {
+ cli_print(cli, "OK");
+ }
+
+ return ok1 && ok2;
+}
+
+static int cmd_keywrap_test(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ command = command;
+
+ if (argc == 0) {
+ cli_print(cli, "1. Test vectors with software keywrap");
+ hal_aes_use_keywrap_core(0);
+ run_test(cli, K_128, sizeof(K_128), C_128, sizeof(C_128));
+ run_test(cli, K_256, sizeof(K_256), C_256, sizeof(C_256));
+
+ cli_print(cli, "\n2. Test vectors with keywrap core");
+ if (hal_aes_use_keywrap_core(1) == 0) {
+ cli_print(cli, "keywrap core not found, skipping");
+ }
+ else {
+ hal_aes_use_keywrap_core(1);
+ run_test(cli, K_128, sizeof(K_128), C_128, sizeof(C_128));
+ run_test(cli, K_256, sizeof(K_256), C_256, sizeof(C_256));
+ }
+
+ cli_print(cli, "\nFor more tests: keywrap test <keysize> <iterations>");
+ return CLI_OK;
+ }
+
+ hal_error_t err;
+
+ if (argc != 2) {
+ usage:
+ cli_print(cli, "Syntax: keywrap test <keysize> <iterations>");
+ return CLI_ERROR;
+ }
+
+ const int keysize = atoi(argv[0]);
+ const int iterations = atoi(argv[1]);
+ if (keysize <= 0 || iterations <= 0)
+ goto usage;
+
+ uint8_t Q[keysize + 8]; size_t Q_len;
+ uint8_t C[keysize + 8]; size_t C_len;
+ memset(C, 0, sizeof(C));
+ if ((err = hal_get_random(NULL, Q, keysize)) != LIBHAL_OK) {
+ cli_print(cli, "hal_get_random: %s", hal_error_string(err));
+ return CLI_ERROR;
+ }
+
+ cli_print(cli, "1. sanity test");
+ C_len = sizeof(C);
+ if ((err = hal_aes_keywrap(NULL, K_256, sizeof(K_256), Q, keysize, C, &C_len)) != LIBHAL_OK) {
+ cli_print(cli, "hal_aes_keywrap: %s", hal_error_string(err));
+ return CLI_ERROR;
+ }
+
+ for (int i = 0; i <= 1; ++i) {
+ if (!hal_aes_use_keywrap_core(i) && i) {
+ cli_print(cli, "keywrap core not found, skipping");
+ continue;
+ }
+ uint8_t q[keysize + 8];
+ size_t q_len = sizeof(q);
+ if ((err = hal_aes_keyunwrap(NULL, K_256, sizeof(K_256), C, C_len, q, &q_len)) != LIBHAL_OK) {
+ cli_print(cli, "hal_aes_keyunwrap: %s", hal_error_string(err));
+ return CLI_ERROR;
+ }
+ if (q_len != (size_t)keysize) {
+ cli_print(cli, "unwrap size mismatch: expected %d, got %d", (int)keysize, (int)q_len);
+ return CLI_ERROR;
+ }
+ if (memcmp(Q, q, q_len) != 0) {
+ cli_print(cli, "unwrap mismatch:\n Want: ");
+ uart_send_hexdump(Q, 0, Q_len - 1);
+ cli_print(cli, "\n Got: ");
+ uart_send_hexdump(q, 0, q_len - 1);
+ cli_print(cli, "");
+ return CLI_ERROR;
+ }
+ cli_print(cli, "with %s: OK", i ? "keywrap core" : "software keywrap");
+ }
+
+ cli_print(cli, "\n2. wrap timing with software keywrap");
+
+ hal_aes_use_keywrap_core(0);
+ uint32_t start = HAL_GetTick();
+ for (int i = 0; i < iterations; ++i) {
+ C_len = sizeof(C);
+ if ((err = hal_aes_keywrap(NULL, K_256, sizeof(K_256), Q, keysize, C, &C_len)) != LIBHAL_OK) {
+ cli_print(cli, "hal_aes_keywrap: %s", hal_error_string(err));
+ return CLI_ERROR;
+ }
+ }
+ uint32_t elapsed = HAL_GetTick() - start;
+ uint32_t per = 1000 * elapsed / iterations;
+ cli_print(cli, "%ld.%03lds total, %ld.%03ldms per wrap",
+ elapsed / 1000, elapsed % 1000, per / 1000, per % 1000);
+
+ cli_print(cli, "\n3. wrap timing with keywrap core");
+
+ if (hal_aes_use_keywrap_core(1) == 0) {
+ cli_print(cli, "keywrap core not found, skipping");
+ }
+ else {
+ start = HAL_GetTick();
+ for (int i = 0; i < iterations; ++i) {
+ C_len = sizeof(C);
+ if ((err = hal_aes_keywrap(NULL, K_256, sizeof(K_256), Q, keysize, C, &C_len)) != LIBHAL_OK) {
+ cli_print(cli, "hal_aes_keywrap: %s", hal_error_string(err));
+ return CLI_ERROR;
+ }
+ }
+ elapsed = HAL_GetTick() - start;
+ per = 1000 * elapsed / iterations;
+ cli_print(cli, "%ld.%03lds total, %ld.%03ldms per wrap",
+ elapsed / 1000, elapsed % 1000, per / 1000, per % 1000);
+ }
+
+ cli_print(cli, "\n4. unwrap timing with software keywrap");
+
+ hal_aes_use_keywrap_core(0);
+ start = HAL_GetTick();
+ for (int i = 0; i < iterations; ++i) {
+ Q_len = sizeof(Q);
+ if ((err = hal_aes_keyunwrap(NULL, K_256, sizeof(K_256), C, C_len, Q, &Q_len)) != LIBHAL_OK) {
+ cli_print(cli, "hal_aes_keyunwrap: %s", hal_error_string(err));
+ return CLI_ERROR;
+ }
+ }
+ elapsed = HAL_GetTick() - start;
+ per = 1000 * elapsed / iterations;
+ cli_print(cli, "%ld.%03lds total, %ld.%03ldms per wrap",
+ elapsed / 1000, elapsed % 1000, per / 1000, per % 1000);
+
+ cli_print(cli, "\n5. unwrap timing with keywrap core");
+
+ if (hal_aes_use_keywrap_core(1) == 0) {
+ cli_print(cli, "keywrap core not found, skipping");
+ }
+ else {
+ start = HAL_GetTick();
+ for (int i = 0; i < iterations; ++i) {
+ Q_len = sizeof(Q);
+ if ((err = hal_aes_keyunwrap(NULL, K_256, sizeof(K_256), C, C_len, Q, &Q_len)) != LIBHAL_OK) {
+ cli_print(cli, "hal_aes_keywrap: %s", hal_error_string(err));
+ return CLI_ERROR;
+ }
+ }
+ elapsed = HAL_GetTick() - start;
+ per = 1000 * elapsed / iterations;
+ cli_print(cli, "%ld.%03lds total, %ld.%03ldms per wrap",
+ elapsed / 1000, elapsed % 1000, per / 1000, per % 1000);
+ }
+
+ return CLI_OK;
+}
+
+void configure_cli_keywrap(struct cli_def *cli)
+{
+ struct cli_command *c_keywrap = cli_register_command(cli, NULL, "keywrap", NULL, 0, 0, NULL);
+
+ /* keywrap test */
+ cli_register_command(cli, c_keywrap, "test", cmd_keywrap_test, 0, 0, "Test the keywrap core");
+}
diff --git a/projects/cli-test/mgmt-keywrap.h b/projects/cli-test/mgmt-keywrap.h
new file mode 100644
index 0000000..a18aded
--- /dev/null
+++ b/projects/cli-test/mgmt-keywrap.h
@@ -0,0 +1,42 @@
+/*
+ * mgmt-keywrap.h
+ * -----------
+ * Management CLI functions related to AES keywrap
+ *
+ * Copyright (c) 2018, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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 __STM32_CLI_MGMT_KEYWRAP_H
+#define __STM32_CLI_MGMT_KEYWRAP_H
+
+#include <libcli.h>
+
+extern void configure_cli_keywrap(struct cli_def *cli);
+
+#endif /* __STM32_CLI_MGMT_KEYWRAP_H */
diff --git a/projects/cli-test/mgmt-masterkey.c b/projects/cli-test/mgmt-masterkey.c
new file mode 100644
index 0000000..811e15b
--- /dev/null
+++ b/projects/cli-test/mgmt-masterkey.c
@@ -0,0 +1,225 @@
+/*
+ * mgmt-masterkey.c
+ * ----------------
+ * Masterkey CLI functions.
+ *
+ * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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.
+ */
+
+/* Rename both CMSIS HAL_OK and libhal HAL_OK to disambiguate */
+#define HAL_OK CMSIS_HAL_OK
+#include "stm-init.h"
+#include "stm-uart.h"
+#include "mgmt-cli.h"
+#include "mgmt-masterkey.h"
+
+#undef HAL_OK
+#define LIBHAL_OK HAL_OK
+#include <hal.h>
+#warning Refactor so we do not need to include hal_internal here
+#include <hal_internal.h>
+#undef HAL_OK
+
+#include <stdlib.h>
+
+static char * _status2str(const hal_error_t status)
+{
+ switch (status) {
+ case LIBHAL_OK:
+ return (char *) "Set";
+ case HAL_ERROR_MASTERKEY_NOT_SET:
+ return (char *) "Not set";
+ default:
+ return (char *) "Unknown";
+ }
+}
+
+static int _parse_hex_groups(uint8_t *buf, size_t len, char *argv[], int argc)
+{
+ int i;
+ uint32_t *dst = (uint32_t *) buf;
+ uint32_t *end = (uint32_t *) buf + len - 1;
+ char *err_ptr = NULL;
+
+ if (! argc) return 0;
+
+ for (i = 0; i < argc; i++) {
+ if (dst >= end) return -1;
+ *dst++ = strtoul(argv[i], &err_ptr, 16);
+ if (*err_ptr) return -2;
+ }
+
+ return 1;
+}
+
+static int cmd_masterkey_status(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ hal_error_t status;
+ uint8_t buf[KEK_LENGTH] = {0};
+
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ cli_print(cli, "Status of master key:\n");
+
+ status = hal_mkm_volatile_read(NULL, 0);
+ cli_print(cli, " volatile: %s / %s", _status2str(status), hal_error_string(status));
+
+ status = hal_mkm_flash_read(NULL, 0);
+ cli_print(cli, " flash: %s / %s", _status2str(status), hal_error_string(status));
+
+ /* XXX Temporary gaping security hole while developing the master key functionality.
+ * REMOVE READ-OUT OF MASTER KEY.
+ */
+
+ status = hal_mkm_volatile_read(&buf[0], sizeof(buf));
+ if (status == LIBHAL_OK || status == HAL_ERROR_MASTERKEY_NOT_SET) {
+ cli_print(cli, "\nVolatile read-out:\n");
+ uart_send_hexdump(buf, 0, sizeof(buf) - 1);
+ cli_print(cli, "\n");
+ } else {
+ cli_print(cli, "Failed reading from volatile memory: %s", hal_error_string(status));
+ }
+
+ status = hal_mkm_flash_read(&buf[0], sizeof(buf));
+ if (status == LIBHAL_OK || status == HAL_ERROR_MASTERKEY_NOT_SET) {
+ cli_print(cli, "\nFlash read-out:\n");
+ uart_send_hexdump(buf, 0, sizeof(buf) - 1);
+ cli_print(cli, "\n");
+ } else {
+ cli_print(cli, "Failed reading from flash: %s", hal_error_string(status));
+ }
+
+ return CLI_OK;
+}
+
+static int cmd_masterkey_set(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ uint8_t buf[KEK_LENGTH] = {0};
+ hal_error_t err;
+ int i;
+
+ command = command;
+
+ if ((i = _parse_hex_groups(&buf[0], sizeof(buf), argv, argc)) != 1) {
+ cli_print(cli, "Failed parsing master key (%i)", i);
+ return CLI_OK;
+ }
+
+ cli_print(cli, "Parsed key:\n");
+ uart_send_hexdump(buf, 0, sizeof(buf) - 1);
+ cli_print(cli, "\n");
+
+ if ((err = hal_mkm_volatile_write(buf, sizeof(buf))) == LIBHAL_OK) {
+ cli_print(cli, "Master key set in volatile memory");
+ } else {
+ cli_print(cli, "Failed writing key to volatile memory: %s", hal_error_string(err));
+ }
+ return CLI_OK;
+}
+
+static int cmd_masterkey_erase(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ hal_error_t err;
+
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ if ((err = hal_mkm_volatile_erase(KEK_LENGTH)) == LIBHAL_OK) {
+ cli_print(cli, "Erased master key from volatile memory");
+ } else {
+ cli_print(cli, "Failed erasing master key from volatile memory: %s", hal_error_string(err));
+ }
+ return CLI_OK;
+}
+
+static int cmd_masterkey_unsecure_set(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ uint8_t buf[KEK_LENGTH] = {0};
+ hal_error_t err;
+ int i;
+
+ command = command;
+
+ if ((i = _parse_hex_groups(&buf[0], sizeof(buf), argv, argc)) != 1) {
+ cli_print(cli, "Failed parsing master key (%i)", i);
+ return CLI_OK;
+ }
+
+ cli_print(cli, "Parsed key:\n");
+ uart_send_hexdump(buf, 0, sizeof(buf) - 1);
+ cli_print(cli, "\n");
+
+ if ((err = hal_mkm_flash_write(buf, sizeof(buf))) == LIBHAL_OK) {
+ cli_print(cli, "Master key set in unsecure flash memory");
+ } else {
+ cli_print(cli, "Failed writing key to unsecure flash memory: %s", hal_error_string(err));
+ }
+ return CLI_OK;
+}
+
+static int cmd_masterkey_unsecure_erase(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ hal_error_t err;
+
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ if ((err = hal_mkm_flash_erase(KEK_LENGTH)) == LIBHAL_OK) {
+ cli_print(cli, "Erased unsecure master key from flash");
+ } else {
+ cli_print(cli, "Failed erasing unsecure master key from flash: %s", hal_error_string(err));
+ }
+ return CLI_OK;
+}
+
+void configure_cli_masterkey(struct cli_def *cli)
+{
+ struct cli_command *c = cli_register_command(cli, NULL, "masterkey", NULL, 0, 0, NULL);
+
+ /* masterkey status */
+ cli_register_command(cli, c, "status", cmd_masterkey_status, 0, 0, "Show status of master key in RAM/flash");
+
+ /* masterkey set */
+ cli_register_command(cli, c, "set", cmd_masterkey_set, 0, 0, "Set the master key in the volatile Master Key Memory");
+
+ /* masterkey erase */
+ cli_register_command(cli, c, "erase", cmd_masterkey_erase, 0, 0, "Erase the master key from the volatile Master Key Memory");
+
+ struct cli_command *c_unsecure = cli_register_command(cli, c, "unsecure", NULL, 0, 0, NULL);
+
+ /* masterkey unsecure set */
+ cli_register_command(cli, c_unsecure, "set", cmd_masterkey_unsecure_set, 0, 0, "Set master key in unprotected flash memory (if unsure, DON'T)");
+
+ /* masterkey unsecure erase */
+ cli_register_command(cli, c_unsecure, "erase", cmd_masterkey_unsecure_erase, 0, 0, "Erase master key from unprotected flash memory");
+}
diff --git a/projects/cli-test/mgmt-masterkey.h b/projects/cli-test/mgmt-masterkey.h
new file mode 100644
index 0000000..67835e9
--- /dev/null
+++ b/projects/cli-test/mgmt-masterkey.h
@@ -0,0 +1,42 @@
+/*
+ * mgmt-masterkey.h
+ * -----------
+ * Management CLI masterkeyellaneous functions.
+ *
+ * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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 __STM32_CLI_MGMT_MASTERKEY_H
+#define __STM32_CLI_MGMT_MASTERKEY_H
+
+#include <libcli.h>
+
+extern void configure_cli_masterkey(struct cli_def *cli);
+
+#endif /* __STM32_CLI_MGMT_MASTERKEY_H */
diff --git a/projects/cli-test/mgmt-misc.c b/projects/cli-test/mgmt-misc.c
index aea790a..ca95c63 100644
--- a/projects/cli-test/mgmt-misc.c
+++ b/projects/cli-test/mgmt-misc.c
@@ -3,7 +3,9 @@
* -----------
* Miscellaneous CLI functions.
*
- * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ * Copyright (c) 2016-2017, NORDUnet A/S All rights reserved.
+ * Copyright: 2020, The Commons Conservancy Cryptech Project
+ * SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -15,9 +17,9 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * - Neither the name of the NORDUnet nor the names of its contributors may
- * be used to endorse or promote products derived from this software
- * without specific prior written permission.
+ * - Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -32,41 +34,44 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#define HAL_OK CMSIS_HAL_OK
#include "stm-init.h"
#include "stm-uart.h"
-
#include "mgmt-cli.h"
#include "mgmt-misc.h"
+#undef HAL_OK
-#include <string.h>
-
-
-extern uint32_t update_crc(uint32_t crc, uint8_t *buf, int len);
+#define HAL_OK LIBHAL_OK
+#include "hal.h"
+#include "hal_internal.h"
+#undef HAL_OK
+#include <string.h>
-volatile uint32_t demo_crc = 0;
+static volatile hal_crc32_t demo_crc;
-int _count_bytes_callback(uint8_t *buf, size_t len) {
- demo_crc = update_crc(demo_crc, buf, len);
- return 1;
+static HAL_StatusTypeDef _count_bytes_callback(uint8_t *buf, size_t len) {
+ demo_crc = hal_crc32_update(demo_crc, buf, len);
+ return CMSIS_HAL_OK;
}
int cli_receive_data(struct cli_def *cli, uint8_t *buf, size_t len, cli_data_callback data_callback)
{
- uint32_t filesize = 0, crc = 0, my_crc = 0, counter = 0;
+ hal_crc32_t crc = 0, my_crc = hal_crc32_init();
+ uint32_t filesize = 0, counter = 0;
size_t n = len;
if (! control_mgmt_uart_dma_rx(DMA_RX_STOP)) {
cli_print(cli, "Failed stopping DMA");
- return CLI_OK;
+ goto fail;
}
cli_print(cli, "OK, write size (4 bytes), data in %li byte chunks, CRC-32 (4 bytes)", (uint32_t) n);
- if (uart_receive_bytes(STM_UART_MGMT, (void *) &filesize, 4, 1000) != HAL_OK) {
+ if (uart_receive_bytes((void *) &filesize, sizeof(filesize), 1000) != CMSIS_HAL_OK) {
cli_print(cli, "Receive timed out");
- return CLI_ERROR;
+ goto fail;
}
cli_print(cli, "Send %li bytes of data", filesize);
@@ -79,27 +84,28 @@ int cli_receive_data(struct cli_def *cli, uint8_t *buf, size_t len, cli_data_cal
if (filesize < n) n = filesize;
- if (uart_receive_bytes(STM_UART_MGMT, (void *) buf, n, 1000) != HAL_OK) {
+ if (uart_receive_bytes((void *) buf, n, 1000) != CMSIS_HAL_OK) {
cli_print(cli, "Receive timed out");
- return CLI_ERROR;
+ goto fail;
}
filesize -= n;
- my_crc = update_crc(my_crc, buf, n);
+ my_crc = hal_crc32_update(my_crc, buf, n);
/* After reception of a chunk but before ACKing we have "all" the time in the world to
* calculate CRC and invoke the data_callback.
*/
- if (data_callback != NULL && ! data_callback(buf, (size_t) n)) {
+ if (data_callback != NULL && data_callback(buf, n) != CMSIS_HAL_OK) {
cli_print(cli, "Data processing failed");
- return CLI_OK;
+ goto fail;
}
counter++;
- uart_send_bytes(STM_UART_MGMT, (void *) &counter, 4);
+ uart_send_bytes((void *) &counter, 4);
}
+ my_crc = hal_crc32_finalize(my_crc);
cli_print(cli, "Send CRC-32");
- uart_receive_bytes(STM_UART_MGMT, (void *) &crc, 4, 1000);
+ uart_receive_bytes((void *) &crc, sizeof(crc), 1000);
cli_print(cli, "CRC-32 0x%x, calculated CRC 0x%x", (unsigned int) crc, (unsigned int) my_crc);
if (crc == my_crc) {
cli_print(cli, "CRC checksum MATCHED");
@@ -107,31 +113,129 @@ int cli_receive_data(struct cli_def *cli, uint8_t *buf, size_t len, cli_data_cal
cli_print(cli, "CRC checksum did NOT match");
}
+ fail:
+ control_mgmt_uart_dma_rx(DMA_RX_START);
return CLI_OK;
}
-int cmd_filetransfer(struct cli_def *cli, const char *command, char *argv[], int argc)
+static int cmd_filetransfer(struct cli_def *cli, const char *command, char *argv[], int argc)
{
uint8_t buf[FILETRANSFER_UPLOAD_CHUNK_SIZE];
- demo_crc = 0;
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ demo_crc = hal_crc32_init();
cli_receive_data(cli, &buf[0], sizeof(buf), _count_bytes_callback);
+ demo_crc = hal_crc32_finalize(demo_crc);
cli_print(cli, "Demo CRC is: %li/0x%x", demo_crc, (unsigned int) demo_crc);
return CLI_OK;
}
-int cmd_reboot(struct cli_def *cli, const char *command, char *argv[], int argc)
+static int cmd_reboot(struct cli_def *cli, const char *command, char *argv[], int argc)
{
+ command = command;
+ argv = argv;
+ argc = argc;
+
cli_print(cli, "\n\n\nRebooting\n\n\n");
HAL_NVIC_SystemReset();
- while (1) {};
+
+ /*NOTREACHED*/
+ return CLI_OK;
+}
+
+static int cmd_rsa_blinding(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ if (argc != 1) {
+ cli_print(cli, "Wrong number of arguments (%i).", argc);
+ cli_print(cli, "Syntax: %s <on|off|clear>", command);
+ return CLI_ERROR;
+ }
+
+ if (strcmp(argv[0], "on") == 0)
+ hal_rsa_set_blinding(1);
+ else if (strcmp(argv[0], "off") == 0)
+ hal_rsa_set_blinding(0);
+ else if (strcmp(argv[0], "clear") == 0)
+ hal_rsa_clear_blinding_cache();
+ else {
+ cli_print(cli, "Argument must be 'on', 'off', or 'clear' - not '%s'", argv[0]);
+ return CLI_ERROR;
+ }
+
+ return CLI_OK;
+}
+
+static int cmd_rsa_crt(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ int onoff;
+
+ if (argc != 1) {
+ cli_print(cli, "Wrong number of arguments (%i).", argc);
+ cli_print(cli, "Syntax: %s <on|off>", command);
+ return CLI_ERROR;
+ }
+
+ if (strcmp(argv[0], "on") == 0)
+ onoff = 1;
+ else if (strcmp(argv[0], "off") == 0)
+ onoff = 0;
+ else {
+ cli_print(cli, "Argument must be 'on' or 'off' - not '%s'", argv[0]);
+ return CLI_ERROR;
+ }
+
+ hal_rsa_set_crt(onoff);
+
+ return CLI_OK;
+}
+
+static int cmd_rsa_modexpng(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ int onoff;
+
+ if (argc != 1) {
+ cli_print(cli, "Wrong number of arguments (%i).", argc);
+ cli_print(cli, "Syntax: %s <on|off>", command);
+ return CLI_ERROR;
+ }
+
+ if (strcmp(argv[0], "on") == 0)
+ onoff = 1;
+ else if (strcmp(argv[0], "off") == 0)
+ onoff = 0;
+ else {
+ cli_print(cli, "Argument must be 'on' or 'off' - not '%s'", argv[0]);
+ return CLI_ERROR;
+ }
+
+ hal_error_t err;
+ if ((err = hal_modexp_use_modexpng(onoff)) == LIBHAL_OK)
+ return CLI_OK;
+
+ cli_print(cli, hal_error_string(err));
+ return CLI_ERROR;
}
void configure_cli_misc(struct cli_def *cli)
{
/* filetransfer */
- cli_command_root_node(filetransfer, "Test file transfering");
+ cli_register_command(cli, NULL, "filetransfer", cmd_filetransfer, 0, 0, "Test file transfering");
+
+ struct cli_command *c_rsa = cli_register_command(cli, NULL, "rsa", NULL, 0, 0, NULL);
+
+ /* rsa blinding */
+ cli_register_command(cli, c_rsa, "blinding", cmd_rsa_blinding, 0, 0, "Set use of RSA blinding");
+
+ /* rsa crt */
+ cli_register_command(cli, c_rsa, "crt", cmd_rsa_crt, 0, 0, "Set use of RSA CRT");
+
+ /* rsa modexpng */
+ cli_register_command(cli, c_rsa, "modexpng", cmd_rsa_modexpng, 0, 0, "Set use of ModExpNG");
+
/* reboot */
- cli_command_root_node(reboot, "Reboot the STM32");
+ cli_register_command(cli, NULL, "reboot", cmd_reboot, 0, 0, "Reboot the STM32");
}
diff --git a/projects/cli-test/mgmt-misc.h b/projects/cli-test/mgmt-misc.h
index b7eb4f4..c0581c9 100644
--- a/projects/cli-test/mgmt-misc.h
+++ b/projects/cli-test/mgmt-misc.h
@@ -35,15 +35,14 @@
#ifndef __STM32_CLI_MGMT_MISC_H
#define __STM32_CLI_MGMT_MISC_H
-#include "stm-init.h"
#include <libcli.h>
-
#define FILETRANSFER_UPLOAD_CHUNK_SIZE 256
-typedef int (*cli_data_callback)(uint8_t *, size_t);
+typedef HAL_StatusTypeDef (*cli_data_callback)(uint8_t *, size_t);
-extern void configure_cli_misc(struct cli_def *cli);
extern int cli_receive_data(struct cli_def *cli, uint8_t *buf, size_t len, cli_data_callback data_callback);
+extern void configure_cli_misc(struct cli_def *cli);
+
#endif /* __STM32_CLI_MGMT_MISC_H */
diff --git a/projects/cli-test/mgmt-show.c b/projects/cli-test/mgmt-show.c
index 3ae196e..4338dcd 100644
--- a/projects/cli-test/mgmt-show.c
+++ b/projects/cli-test/mgmt-show.c
@@ -32,6 +32,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/* Rename both CMSIS HAL_OK and libhal HAL_OK to disambiguate */
+#define HAL_OK CMSIS_HAL_OK
#include "stm-init.h"
#include "stm-keystore.h"
#include "stm-fpgacfg.h"
@@ -40,13 +42,24 @@
#include "mgmt-cli.h"
#include "mgmt-show.h"
-#include <string.h>
+#undef HAL_OK
+#define LIBHAL_OK HAL_OK
+#include "hal.h"
+
+#define HAL_STATIC_PKEY_STATE_BLOCKS 6
+#include "hal_internal.h"
+#undef HAL_OK
+#include <string.h>
-int cmd_show_cpuspeed(struct cli_def *cli, const char *command, char *argv[], int argc)
+static int cmd_show_cpuspeed(struct cli_def *cli, const char *command, char *argv[], int argc)
{
volatile uint32_t hclk;
+ command = command;
+ argv = argv;
+ argc = argc;
+
hclk = HAL_RCC_GetHCLKFreq();
cli_print(cli, "HSE_VALUE: %li", HSE_VALUE);
cli_print(cli, "HCLK: %li (%i MHz)", hclk, (int) hclk / 1000 / 1000);
@@ -54,36 +67,71 @@ int cmd_show_cpuspeed(struct cli_def *cli, const char *command, char *argv[], in
return CLI_OK;
}
-int cmd_show_fpga_status(struct cli_def *cli, const char *command, char *argv[], int argc)
+static int cmd_show_fpga_status(struct cli_def *cli, const char *command, char *argv[], int argc)
{
- cli_print(cli, "FPGA has %sloaded a bitstream", fpgacfg_check_done() ? "":"NOT ");
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ cli_print(cli, "FPGA has %sloaded a bitstream", (fpgacfg_check_done() == CMSIS_HAL_OK) ? "":"NOT ");
return CLI_OK;
}
-int cmd_show_keystore_status(struct cli_def *cli, const char *command, char *argv[], int argc)
+static int cmd_show_fpga_cores(struct cli_def *cli, const char *command, char *argv[], int argc)
{
- cli_print(cli, "Keystore memory is %sonline", (keystore_check_id() != 1) ? "NOT ":"");
+ hal_core_t *core;
+ const hal_core_info_t *info;
+
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ if (fpgacfg_check_done() != CMSIS_HAL_OK) {
+ cli_print(cli, "FPGA has not loaded a bitstream");
+ return CLI_OK;
+ }
+
+ for (core = hal_core_iterate(NULL); core != NULL; core = hal_core_iterate(core)) {
+ info = hal_core_info(core);
+ cli_print(cli, "%04x: %8.8s %4.4s",
+ (unsigned int)info->base, info->name, info->version);
+ }
+
return CLI_OK;
}
-int cmd_show_keystore_data(struct cli_def *cli, const char *command, char *argv[], int argc)
+static int cmd_show_keystore_status(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ cli_print(cli, "Keystore memory is %sonline", (keystore_check_id() == CMSIS_HAL_OK) ? "":"NOT ");
+ return CLI_OK;
+}
+
+static int cmd_show_keystore_data(struct cli_def *cli, const char *command, char *argv[], int argc)
{
uint8_t buf[KEYSTORE_PAGE_SIZE];
uint32_t i;
- if (keystore_check_id() != 1) {
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ if (keystore_check_id() != CMSIS_HAL_OK) {
cli_print(cli, "ERROR: The keystore memory is not accessible.");
}
memset(buf, 0, sizeof(buf));
- if ((i = keystore_read_data(0, buf, sizeof(buf))) != 1) {
+ if ((i = keystore_read_data(0, buf, sizeof(buf))) != CMSIS_HAL_OK) {
cli_print(cli, "Failed reading first page from keystore memory: %li", i);
return CLI_ERROR;
}
cli_print(cli, "First page from keystore memory:\r\n");
- uart_send_hexdump(STM_UART_MGMT, buf, 0, sizeof(buf) - 1);
- uart_send_string2(STM_UART_MGMT, (char *) "\r\n\r\n");
+ uart_send_hexdump(buf, 0, sizeof(buf) - 1);
+ cli_print(cli, "\n");
for (i = 0; i < 8; i++) {
if (buf[i] == 0xff) break; /* never written */
@@ -97,14 +145,14 @@ int cmd_show_keystore_data(struct cli_def *cli, const char *command, char *argv[
if (buf[i] == 0xff) {
cli_print(cli, "Tombstoning byte %li", i);
buf[i] = 0x55;
- if ((i = keystore_write_data(0, buf, sizeof(buf))) != 1) {
+ if ((i = keystore_write_data(0, buf, sizeof(buf))) != CMSIS_HAL_OK) {
cli_print(cli, "Failed writing data at offset 0: %li", i);
return CLI_ERROR;
}
}
} else {
cli_print(cli, "Erasing first sector since all the first 8 bytes are tombstones");
- if ((i = keystore_erase_sectors(1)) != 1) {
+ if ((i = keystore_erase_sector(0)) != CMSIS_HAL_OK) {
cli_print(cli, "Failed erasing the first sector: %li", i);
return CLI_ERROR;
}
@@ -116,18 +164,24 @@ int cmd_show_keystore_data(struct cli_def *cli, const char *command, char *argv[
void configure_cli_show(struct cli_def *cli)
{
- /* show */
- cli_command_root(show);
+ struct cli_command *c = cli_register_command(cli, NULL, "show", NULL, 0, 0, NULL);
/* show cpuspeed */
- cli_command_node(show, cpuspeed, "Show the speed at which the CPU currently operates");
+ cli_register_command(cli, c, "cpuspeed", cmd_show_cpuspeed, 0, 0, "Show the speed at which the CPU currently operates");
+
+ struct cli_command *c_fpga = cli_register_command(cli, c, "fpga", NULL, 0, 0, NULL);
- cli_command_branch(show, fpga);
/* show fpga status*/
- cli_command_node(show_fpga, status, "Show status about the FPGA");
+ cli_register_command(cli, c_fpga, "status", cmd_show_fpga_status, 0, 0, "Show status about the FPGA");
+
+ /* show fpga cores*/
+ cli_register_command(cli, c_fpga, "cores", cmd_show_fpga_cores, 0, 0, "Show the currently available FPGA cores");
+
+ struct cli_command *c_keystore = cli_register_command(cli, c, "keystore", NULL, 0, 0, NULL);
- cli_command_branch(show, keystore);
/* show keystore status*/
- cli_command_node(show_keystore, status, "Show status of the keystore memory");
- cli_command_node(show_keystore, data, "Show the first page of the keystore memory");
+ cli_register_command(cli, c_keystore, "status", cmd_show_keystore_status, 0, 0, "Show status of the keystore memory");
+
+ /* show keystore data */
+ cli_register_command(cli, c_keystore, "data", cmd_show_keystore_data, 0, 0, "Show the first page of the keystore memory");
}
diff --git a/projects/cli-test/mgmt-show.h b/projects/cli-test/mgmt-show.h
index 0d7ba3a..7b80a30 100644
--- a/projects/cli-test/mgmt-show.h
+++ b/projects/cli-test/mgmt-show.h
@@ -1,5 +1,5 @@
/*
- * mgmt-misc.h
+ * mgmt-show.h
* -----------
* Management CLI 'show' functions.
*
@@ -35,7 +35,6 @@
#ifndef __STM32_CLI_MGMT_SHOW_H
#define __STM32_CLI_MGMT_SHOW_H
-#include "stm-init.h"
#include <libcli.h>
extern void configure_cli_show(struct cli_def *cli);
diff --git a/projects/cli-test/mgmt-test.c b/projects/cli-test/mgmt-test.c
index c1f255e..9b9972d 100644
--- a/projects/cli-test/mgmt-test.c
+++ b/projects/cli-test/mgmt-test.c
@@ -35,34 +35,31 @@
#include "stm-init.h"
#include "stm-led.h"
#include "stm-sdram.h"
+#include "stm-fmc.h"
+#include "stm-fpgacfg.h"
#include "mgmt-cli.h"
#include "mgmt-test.h"
#include "test_sdram.h"
+#include "test_mkmif.h"
+#include "test-fmc.h"
#include <stdlib.h>
-
-int cmd_test_sdram(struct cli_def *cli, const char *command, char *argv[], int argc)
+static int cmd_test_sdram(struct cli_def *cli, const char *command, char *argv[], int argc)
{
// run external memory initialization sequence
- HAL_StatusTypeDef status;
int ok, num_cycles = 1, i, test_completed;
+ command = command;
+
if (argc == 1) {
num_cycles = strtol(argv[0], NULL, 0);
if (num_cycles > 100) num_cycles = 100;
if (num_cycles < 1) num_cycles = 1;
}
- cli_print(cli, "Initializing SDRAM");
- status = sdram_init();
- if (status != HAL_OK) {
- cli_print(cli, "Failed initializing SDRAM: %i", (int) status);
- return CLI_OK;
- }
-
for (i = 1; i <= num_cycles; i++) {
cli_print(cli, "Starting SDRAM test (%i/%i)", i, num_cycles);
test_completed = 0;
@@ -107,11 +104,83 @@ int cmd_test_sdram(struct cli_def *cli, const char *command, char *argv[], int a
return CLI_OK;
}
+static int cmd_test_fmc(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ int i, num_cycles = 1, num_rounds = 100000;
+
+ command = command;
+
+ if (argc >= 1) {
+ num_cycles = strtol(argv[0], NULL, 0);
+ if (num_cycles > 100000) num_cycles = 100000;
+ if (num_cycles < 1) num_cycles = 1;
+ }
+
+ if (argc == 2) {
+ num_rounds = strtol(argv[1], NULL, 0);
+ if (num_rounds > 1000000) num_rounds = 1000000;
+ if (num_rounds < 1) num_rounds = 1;
+ }
+
+ cli_print(cli, "Checking if FPGA has loaded it's bitstream");
+ // Blink blue LED until the FPGA reports it has loaded it's bitstream
+ led_on(LED_BLUE);
+ while (! fpgacfg_check_done()) {
+ for (i = 0; i < 4; i++) {
+ HAL_Delay(500);
+ led_toggle(LED_BLUE);
+ }
+ }
+
+ // turn on green led, turn off other leds
+ led_on(LED_GREEN);
+ led_off(LED_YELLOW);
+ led_off(LED_RED);
+ led_off(LED_BLUE);
+
+ // vars
+ volatile int data_test_ok = 0, addr_test_ok = 0, successful_runs = 0, failed_runs = 0, sleep = 0;
+
+ for (i = 1; i <= num_cycles; i++) {
+ cli_print(cli, "Starting FMC test (%i/%i)", i, num_cycles);
+
+ // test data bus
+ data_test_ok = test_fpga_data_bus(cli, num_rounds);
+ // test address bus
+ addr_test_ok = test_fpga_address_bus(cli, num_rounds);
+
+ cli_print(cli, "Data: %i, addr %i", data_test_ok, addr_test_ok);
+
+ if (data_test_ok == num_rounds &&
+ addr_test_ok == num_rounds) {
+ // toggle yellow led to indicate, that we are alive
+ led_toggle(LED_YELLOW);
+
+ successful_runs++;
+ sleep = 0;
+ } else {
+ led_on(LED_RED);
+ failed_runs++;
+ sleep = 2000;
+ }
+
+ cli_print(cli, "Success %i, failed %i runs\r\n", successful_runs, failed_runs);
+ HAL_Delay(sleep);
+ }
+
+ return CLI_OK;
+}
+
void configure_cli_test(struct cli_def *cli)
{
- /* test */
- cli_command_root(test);
+ struct cli_command *c = cli_register_command(cli, NULL, "test", NULL, 0, 0, NULL);
/* test sdram */
- cli_command_node(test, sdram, "Run SDRAM tests");
+ cli_register_command(cli, c, "sdram", cmd_test_sdram, 0, 0, "Run SDRAM tests");
+
+ /* test mkmif */
+ cli_register_command(cli, c, "mkmif", cmd_test_mkmif, 0, 0, "Run Master Key Memory Interface tests");
+
+ /* test fmc */
+ cli_register_command(cli, c, "fmc", cmd_test_fmc, 0, 0, "Run FMC bus tests");
}
diff --git a/projects/cli-test/test-fmc.c b/projects/cli-test/test-fmc.c
new file mode 100644
index 0000000..d9b0c9b
--- /dev/null
+++ b/projects/cli-test/test-fmc.c
@@ -0,0 +1,217 @@
+/*
+ * test-fmc.c
+ * -----------
+ * FPGA communication bus (FMC) tests.
+ *
+ * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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.
+ */
+
+/*
+ This requires a special bitstream with a special test register.
+ See core/platform/novena/fmc/rtl/novena_fmc_top.v, sections marked
+ `ifdef test:
+ //----------------------------------------------------------------
+ // Dummy Register
+ //
+ // General-purpose register to test FMC interface using STM32
+ // demo program instead of core selector logic.
+ //
+ // This register is a bit tricky, but it allows testing of both
+ // data and address buses. Reading from FPGA will always return
+ // value, which is currently stored in the test register,
+ // regardless of read transaction address. Writing to FPGA has
+ // two variants: a) writing to address 0 will store output data
+ // data value in the test register, b) writing to any non-zero
+ // address will store _address_ of write transaction in the test
+ // register.
+ //
+ // To test data bus, write some different patterns to address 0,
+ // then readback from any address and compare.
+ //
+ // To test address bus, write anything to some different non-zero
+ // addresses, then readback from any address and compare returned
+ // value with previously written address.
+ //
+ //----------------------------------------------------------------
+ */
+
+#include "stm-init.h"
+#include "stm-fmc.h"
+#include "stm-uart.h"
+
+#include "test-fmc.h"
+
+static RNG_HandleTypeDef rng_inst;
+
+/* These are some interesting-to-look-at-in-the-debugger values that are declared
+ * volatile so that the compiler wouldn't optimize/obscure them.
+ */
+volatile uint32_t data_diff = 0;
+volatile uint32_t addr_diff = 0;
+
+
+static int _write_then_read(struct cli_def *cli, uint32_t addr, uint32_t write_buf, uint32_t *read_buf)
+{
+ int ok;
+
+ fmc_write_32(addr, write_buf);
+ fmc_read_32(0, read_buf);
+
+ return 1;
+}
+
+int test_fpga_data_bus(struct cli_def *cli, uint32_t test_rounds)
+{
+ int i, c;
+ uint32_t rnd, buf;
+ HAL_StatusTypeDef hal_result;
+
+ /* initialize stm32 rng */
+ rng_inst.Instance = RNG;
+ HAL_RNG_Init(&rng_inst);
+
+ /* run some rounds of data bus test */
+ for (c = 0; c < (int)test_rounds; c++) {
+ data_diff = 0;
+ /* try to generate "random" number */
+ hal_result = HAL_RNG_GenerateRandomNumber(&rng_inst, &rnd);
+ if (hal_result != HAL_OK) {
+ cli_print(cli, "STM32 RNG failed");
+ break;
+ }
+
+ /* write value to fpga at address 0 and then read it back from the test register */
+ if (! _write_then_read(cli, 0, rnd, &buf)) break;
+
+ /* compare (abort testing in case of error) */
+ data_diff = buf ^ rnd;
+ if (data_diff) {
+ cli_print(cli, "Data bus FAIL: expected %lx got %lx", rnd, buf);
+ uart_send_string((char *) "Binary diff: ");
+ uart_send_binary(data_diff, 32);
+ uart_send_string("\r\n");
+
+ break;
+ }
+ }
+
+ if (! data_diff) {
+ cli_print(cli, "Sample of data bus test data: expected 0x%lx got 0x%lx", rnd, buf);
+ } else {
+ uint32_t data;
+ cli_print(cli, "\nFMC data bus per-bit analysis:");
+ for (i = 0; i < 31; i++) {
+ data = 1 << i;
+
+ if (! _write_then_read(cli, 0, data, &buf)) break;
+
+ if (data == buf) {
+ cli_print(cli, "Data 0x%08lx (FMC_D%02i) - OK", data, i + 1);
+ } else {
+ cli_print(cli, "Data 0x%08lx (FMC_D%02i) - FAIL (read 0x%08lx)", data, i + 1, buf);
+ }
+ }
+ }
+
+
+ /* return number of successful tests */
+ return c;
+}
+
+int test_fpga_address_bus(struct cli_def *cli, uint32_t test_rounds)
+{
+ int i, c;
+ uint32_t addr, buf, dummy = 1;
+ HAL_StatusTypeDef hal_result;
+
+ /* initialize stm32 rng */
+ rng_inst.Instance = RNG;
+ HAL_RNG_Init(&rng_inst);
+
+ /* run some rounds of address bus test */
+ for (c = 0; c < (int)test_rounds; c++) {
+ addr_diff = 0;
+ /* try to generate "random" number */
+ hal_result = HAL_RNG_GenerateRandomNumber(&rng_inst, &addr);
+ if (hal_result != HAL_OK) break;
+
+ /* there are 26 physicaly connected address lines on the alpha,
+ but "only" 24 usable for now (the top two ones are used by FMC
+ to choose bank, and we only have one bank set up currently)
+ */
+ addr &= 0x3fffffc;
+
+ /* don't test zero addresses (fpga will store data, not address) */
+ if (addr == 0) continue;
+
+ /* write dummy value to fpga at some non-zero address and then read from the
+ test register to see what address the FPGA thought we wrote to
+ */
+ if (! _write_then_read(cli, addr, dummy, &buf)) break;
+
+ /* fpga receives address of 32-bit word, while we need
+ byte address here to compare
+ */
+ buf <<= 2;
+
+ /* compare (abort testing in case of error) */
+ addr_diff = buf ^ addr;
+ if (addr_diff) {
+ cli_print(cli, "Address bus FAIL: expected 0x%lx got 0x%lx", addr, buf);
+ uart_send_string((char *) "Binary diff: ");
+ uart_send_binary(addr_diff, 32);
+ uart_send_string("\r\n");
+
+ break;
+ }
+ }
+
+ if (! addr_diff) {
+ cli_print(cli, "Sample of address bus test data: expected 0x%lx got 0x%lx", addr, buf);
+ } else {
+ cli_print(cli, "\nFMC address bus per-bit analysis:");
+ for (i = 0; i < 23; i++) {
+ uint32_t shifted_addr;
+ addr = 1 << i;
+
+ shifted_addr = addr << 2;
+
+ if (! _write_then_read(cli, shifted_addr, dummy, &buf)) break;
+
+ if (addr == buf) {
+ cli_print(cli, "Address 0x%08lx (FMC_A%02i) - OK", addr, i + 1);
+ } else {
+ cli_print(cli, "Address 0x%08lx (FMC_A%02i) - FAIL (read 0x%08lx)", addr, i + 1, buf);
+ }
+ }
+ }
+
+ /* return number of successful tests */
+ return c;
+}
diff --git a/projects/cli-test/test-fmc.h b/projects/cli-test/test-fmc.h
new file mode 100644
index 0000000..c49da48
--- /dev/null
+++ b/projects/cli-test/test-fmc.h
@@ -0,0 +1,43 @@
+/*
+ * test-fmc.h
+ * ------------
+ * Prototypes and defines for testing the FMC bus comms with the FPGA.
+ *
+ * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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 __STM32_CLI_TEST_FMC_H
+#define __STM32_CLI_TEST_FMC_H
+
+#include "mgmt-cli.h"
+
+extern int test_fpga_data_bus(struct cli_def *cli, uint32_t test_rounds);
+extern int test_fpga_address_bus(struct cli_def *cli, uint32_t test_rounds);
+
+
+#endif /* __STM32_CLI_TEST_FMC_H */
diff --git a/projects/cli-test/test-mkmif.c b/projects/cli-test/test-mkmif.c
new file mode 100644
index 0000000..cd71040
--- /dev/null
+++ b/projects/cli-test/test-mkmif.c
@@ -0,0 +1,166 @@
+/*
+ * Test Joachim's MKMIF core.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+
+#include <sys/time.h>
+
+/* Rename both CMSIS HAL_OK and libhal HAL_OK to disambiguate */
+#define HAL_OK CMSIS_HAL_OK
+#include "mgmt-cli.h"
+
+#undef HAL_OK
+#define HAL_OK LIBHAL_OK
+#include "hal.h"
+#undef HAL_OK
+
+
+#define SCLK_DIV 0x20
+
+typedef union {
+ uint8_t byte[4];
+ uint32_t word;
+} byteword_t;
+
+static hal_error_t sclk_test(struct cli_def *cli, hal_core_t *core, const uint32_t divisor)
+{
+ uint32_t readback;
+ hal_error_t err;
+
+ cli_print(cli, "Trying to adjust the clockspeed (divisor %x).", (unsigned int) divisor);
+
+ if ((err = hal_mkmif_set_clockspeed(core, divisor)) != LIBHAL_OK) {
+ cli_print(cli, "hal_mkmif_set_clockspeed: %s", hal_error_string(err));
+ return err;
+ }
+ if ((err = hal_mkmif_get_clockspeed(core, &readback)) != LIBHAL_OK) {
+ cli_print(cli, "hal_mkmif_get_clockspeed: %s", hal_error_string(err));
+ return err;
+ }
+ if (readback != divisor) {
+ cli_print(cli, "expected %x, got %x", (unsigned int)divisor, (unsigned int)readback);
+ return HAL_ERROR_IO_UNEXPECTED;
+ }
+ return LIBHAL_OK;
+}
+
+static hal_error_t init_test(struct cli_def *cli, hal_core_t *core)
+{
+ hal_error_t err;
+
+ cli_print(cli, "Trying to init to the memory in continuous mode.");
+
+ if ((err = hal_mkmif_init(core)) != LIBHAL_OK) {
+ cli_print(cli, "hal_mkmif_init: %s", hal_error_string(err));
+ return err;
+ }
+
+ return LIBHAL_OK;
+}
+
+static hal_error_t write_test(struct cli_def *cli, hal_core_t *core)
+{
+ uint32_t write_data;
+ uint32_t write_address;
+ int i;
+ hal_error_t err;
+
+ for (write_data = 0x01020304, write_address = 0, i = 0;
+ i < 0x10;
+ write_data += 0x01010101, write_address += 4, ++i) {
+
+ cli_print(cli, "Trying to write 0x%08x to memory address 0x%08x.",
+ (unsigned int)write_data, (unsigned int)write_address);
+
+ if ((err = hal_mkmif_write_word(core, write_address, write_data)) != LIBHAL_OK) {
+ cli_print(cli, "hal_mkmif_write: %s", hal_error_string(err));
+ return err;
+ }
+ }
+
+ return LIBHAL_OK;
+}
+
+static hal_error_t read_test(struct cli_def *cli, hal_core_t *core)
+{
+ uint32_t read_data;
+ uint32_t read_address;
+ int i;
+ hal_error_t err;
+
+ for (read_address = 0, i = 0;
+ i < 0x10;
+ read_address += 4, ++i) {
+
+ cli_print(cli, "Trying to read from memory address 0x%08x.", (unsigned int)read_address);
+
+ if ((err = hal_mkmif_read_word(core, read_address, &read_data)) != LIBHAL_OK) {
+ cli_print(cli, "hal_mkmif_read: %s", hal_error_string(err));
+ return err;
+ }
+ cli_print(cli, "Data read: 0x%08x", (unsigned int)read_data);
+ }
+
+ return LIBHAL_OK;
+}
+
+static hal_error_t write_read_test(struct cli_def *cli, hal_core_t *core)
+{
+ uint32_t data;
+ uint32_t readback;
+ hal_error_t err;
+
+ cli_print(cli, "Trying to write 0xdeadbeef to the memory and then read back.");
+
+ data = 0xdeadbeef;
+
+ if ((err = hal_mkmif_write_word(core, 0x00000000, data)) != LIBHAL_OK) {
+ cli_print(cli, "write error: %s", hal_error_string(err));
+ return err;
+ }
+
+ if ((err = hal_mkmif_read_word(core, 0x00000000, &readback)) != LIBHAL_OK) {
+ cli_print(cli, "read error: %s", hal_error_string(err));
+ return err;
+ }
+
+ if (readback != data) {
+ cli_print(cli, "read %08x, expected %08x", (unsigned int)readback, (unsigned int)data);
+ return HAL_ERROR_IO_UNEXPECTED;
+ }
+
+ return LIBHAL_OK;
+}
+
+int cmd_test_mkmif(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ hal_core_t *core = hal_core_find(MKMIF_NAME, NULL);
+ hal_error_t res;
+
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ if (core == NULL) {
+ cli_print(cli, "MKMIF core not present, not testing.");
+ return HAL_ERROR_CORE_NOT_FOUND;
+ }
+
+ res =
+ sclk_test(cli, core, SCLK_DIV) ||
+ init_test(cli, core) ||
+ write_read_test(cli, core) ||
+ write_test(cli, core) ||
+ read_test(cli, core);
+
+ if (res != LIBHAL_OK) {
+ cli_print(cli, "\nTest FAILED");
+ }
+
+ return CLI_OK;
+}
diff --git a/projects/cli-test/test_mkmif.h b/projects/cli-test/test_mkmif.h
new file mode 100644
index 0000000..d5f2f75
--- /dev/null
+++ b/projects/cli-test/test_mkmif.h
@@ -0,0 +1,40 @@
+/*
+ * test_mkmif.h
+ * ------------
+ * Prototypes and defines for testing the master key memory interface.
+ *
+ * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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 __STM32_CLI_TEST_MKMIF_H
+#define __STM32_CLI_TEST_MKMIF_H
+
+extern int cmd_test_mkmif(struct cli_def *cli, const char *command, char *argv[], int argc);
+
+
+#endif /* __STM32_CLI_TEST_MKMIF_H */
diff --git a/projects/cli-test/test_sdram.c b/projects/cli-test/test_sdram.c
index e720667..4961b94 100644
--- a/projects/cli-test/test_sdram.c
+++ b/projects/cli-test/test_sdram.c
@@ -31,7 +31,6 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "stm32f4xx_hal.h"
#include "stm-led.h"
#include "stm-sdram.h"
#include "test_sdram.h"
diff --git a/projects/hsm/Makefile b/projects/hsm/Makefile
index f5546d8..7fd3ad6 100644
--- a/projects/hsm/Makefile
+++ b/projects/hsm/Makefile
@@ -1,19 +1,53 @@
PROJ = hsm
-SRCS = main.c
+# objs in addition to $(PROJ).o
+OBJS = mgmt-cli.o \
+ mgmt-firmware.o \
+ mgmt-bootloader.o \
+ mgmt-fpga.o \
+ mgmt-keystore.o \
+ mgmt-masterkey.o \
+ mgmt-misc.o \
+ mgmt-task.o \
+ log.o \
+ $(TOPLEVEL)/task.o
-OBJS = $(SRCS:.c=.o)
+CFLAGS += -DNUM_RPC_TASK=8
-CFLAGS += -I $(LIBHAL_DIR)
+CFLAGS += -I$(LIBHAL_SRC)
+CFLAGS += -I$(LIBCLI_SRC)
+CFLAGS += -I$(LIBTFM_BLD)
+CFLAGS += -Wno-missing-field-initializers
-LIBS += $(LIBHAL_DIR)/libhal.a $(LIBTFM_DIR)/libtfm.a
+LIBS += $(LIBHAL_BLD)/libhal.a $(LIBTFM_BLD)/libtfm.a
+LIBS += $(LIBCLI_BLD)/libcli.a
+
+LDFLAGS += -mcpu=cortex-m4 -mthumb -mlittle-endian -mthumb-interwork
+LDFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
+LDFLAGS += -Wl,--gc-sections
+
+ifdef DO_PROFILING
+LDFLAGS += --specs=rdimon.specs -lc -lrdimon
+endif
+
+ifdef DO_TASK_METRICS
+CFLAGS += -DDO_TASK_METRICS
+endif
+
+ifdef DO_TIMING
+CFLAGS += -DDO_TIMING
+CFLAGS += -I../cli-test
+CFLAGS += -DCLI_STACK_SIZE=65536
+OBJS += ../cli-test/mgmt-timing.o $(TOPLEVEL)/stm-dwt.o
+LDFLAGS += -lm
+endif
all: $(PROJ:=.elf)
-$(PROJ).elf: $(OBJS) $(BOARD_OBJS) $(LIBS)
- $(CC) $(CFLAGS) $^ -o $@ -T$(LDSCRIPT) -g -Wl,-Map=$(PROJ).map
- $(OBJCOPY) -O binary $(PROJ).elf $(PROJ).bin
- $(SIZE) $(PROJ).elf
+%.elf: %.o $(BOARD_OBJS) $(OBJS) $(LIBS)
+ $(CC) $^ -o $@ -T$(LDSCRIPT) -g -Wl,-Map=$*.map $(LDFLAGS)
+ $(OBJCOPY) -O binary $*.elf $*.bin
+ $(SIZE) $*.elf
clean:
rm -f *.o
diff --git a/projects/hsm/cryptech_miniterm b/projects/hsm/cryptech_miniterm
new file mode 100755
index 0000000..b646811
--- /dev/null
+++ b/projects/hsm/cryptech_miniterm
@@ -0,0 +1,45 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2016, NORDUnet A/S All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+# - Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# - 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.
+#
+# - Neither the name of the NORDUnet nor the names of its contributors may
+# be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+# HOLDER 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.
+
+"""
+Utility to run PySerial's "miniterm" with default settings suitable
+for talking to the Cryptech Alpha's console port.
+"""
+
+import serial.tools.miniterm
+import sys
+import os
+
+default_port = os.getenv("CRYPTECH_CTY_CLIENT_SERIAL_DEVICE")
+default_baud = os.getenv("CRYPTECH_CTY_CLIENT_SERIAL_SPEED", 921600)
+
+sys.exit(serial.tools.miniterm.main(default_port = default_port,
+ default_baudrate = int(default_baud)))
+
diff --git a/projects/hsm/cryptech_probe b/projects/hsm/cryptech_probe
new file mode 100755
index 0000000..356931a
--- /dev/null
+++ b/projects/hsm/cryptech_probe
@@ -0,0 +1,158 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2016, NORDUnet A/S All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+# - Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# - 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.
+#
+# - Neither the name of the NORDUnet nor the names of its contributors may
+# be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+# HOLDER 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.
+
+"""
+Utility to probe USB serial port(s) trying to figure out which one(s)
+we have plugged in today. stdout is environment variable settings,
+suitable for use in bash with "eval `cryptech_probe`"; all other output
+goes to stderr.
+"""
+
+import sys
+import time
+import argparse
+import serial.tools.list_ports_posix
+
+if sys.version_info.major == 2:
+ def colon_hex(raw):
+ return ":".join("{:02x}".format(ord(b)) for b in raw)
+else:
+ def colon_hex(raw):
+ return ":".join("{:02x}".format(b) for b in raw)
+
+class positive_integer(int):
+ def __init__(self, value):
+ if self <= 0:
+ raise ValueError
+
+parser = argparse.ArgumentParser(formatter_class = argparse.ArgumentDefaultsHelpFormatter)
+parser.add_argument("-v", "--verbose", action = "store_true", help = "produce human-readable output")
+parser.add_argument("-d", "--debug", action = "store_true", help = "blather about what we're doing")
+parser.add_argument("--no-cleanup", action = "store_true", help = "don't send cleanup sequences after probing")
+parser.add_argument("--read-buffer-size", type = positive_integer, help = "size of read buffer", default = 1024)
+args = parser.parse_args()
+
+SLIP_END = b"\300" # Indicates end of SLIP packet
+SLIP_ESC = b"\333" # Indicates byte stuffing
+SLIP_ESC_END = b"\334" # ESC ESC_END means END data byte
+SLIP_ESC_ESC = b"\335" # ESC ESC_ESC means ESC data byte
+
+Control_U = b"\025" # Console: clear line
+Control_M = b"\015" # Console: end of line
+
+RPC_query = b"\0" * 8 # client_handle = 0, function code = RPC_FUNC_GET_VERSION
+RPC_reply = b"\0" * 12 # opcode = RPC_FUNC_GET_VERSION, client_handle = 0, valret = HAL_OK
+
+# This is the query string we send to each USB port we find. It's
+# intended to be relatively harmless, at least for either of the HSM
+# ports: the final Control-U should prevent the console from trying to
+# interpret the RPC command, and the SLIP_END markers should cause
+# the RPC server to treat the ASCII control characters as noise.
+#
+# Yes, this is a total kludge. Useful identifiers for the USB ports
+# are are on the wish list for a future revision of the hardware, but
+# for the moment, we do what we can with what we have.
+
+probe_string = SLIP_END + Control_U + SLIP_END + RPC_query + SLIP_END + Control_U + Control_M
+
+ports = [port for port, desc, hwid in serial.tools.list_ports_posix.comports()
+ if "VID:PID=0403:6014" in hwid]
+
+if not ports:
+ sys.exit("Couldn't find any likely USB ports")
+
+if args.debug:
+ sys.stderr.write("Candidate USB ports: {}\n".format(", ".join(ports)))
+
+env = {}
+
+for port in ports:
+
+ while True:
+ try:
+ tty = serial.Serial(port, 921600, timeout=0.1)
+ break
+ except serial.SerialException:
+ time.sleep(0.2)
+
+ # Not sure we really need to dribble the probe string out this slowly anymore,
+ # but once upon a time we did this for a reason and it's not like this program
+ # is a performance bottleneck, so stick with the safe version.
+
+ for i in range(len(probe_string)):
+ tty.write(probe_string[i:i+1])
+ time.sleep(0.1)
+
+ response = tty.read(args.read_buffer_size)
+ if args.debug:
+ sys.stderr.write("Received from {}: {!r} ({})\n".format(port, response, colon_hex(response)))
+
+ # Check whether we got a known console prompt.
+
+ is_cty = any(prompt in response for prompt in (b"Username:", b"Password:", b"cryptech>"))
+
+ # Check whether we got something that looks like the response to an RPC version query.
+ # We skip over the version value itself, as it might change, but we check that it's
+ # terminated properly. This is fragile, and will need to handle SLIP decoding if
+ # we ever bump one of the version fields up into the range where the SLIP control
+ # characters live, but it will do for the moment.
+
+ try:
+ is_hsm = response[response.index(SLIP_END + RPC_reply) + len(SLIP_END + RPC_reply) + 4] == SLIP_END[0]
+ except ValueError:
+ is_hsm = False
+ except IndexError:
+ is_hsm = False
+
+ if is_cty and args.verbose:
+ sys.stderr.write("{} looks like the Cryptech HSM console port\n".format(port))
+
+ if is_hsm and args.verbose:
+ sys.stderr.write("{} looks like the Cryptech HSM RPC port\n".format(port))
+
+ if is_cty:
+ env.update(CRYPTECH_CTY_CLIENT_SERIAL_DEVICE = port)
+
+ if is_hsm:
+ env.update(CRYPTECH_RPC_CLIENT_SERIAL_DEVICE = port)
+
+ if (is_cty or is_hsm) and not args.no_cleanup:
+ if is_cty:
+ tty.write(Control_U)
+ if is_hsm:
+ tty.write(SLIP_END)
+ while tty.read(args.read_buffer_size):
+ pass
+
+ tty.close()
+
+if env:
+ sys.stdout.write("export {}\n".format(
+ " ".join("{}='{}'".format(var, env[var]) for var in sorted(env))))
diff --git a/projects/hsm/cryptech_upload b/projects/hsm/cryptech_upload
new file mode 100755
index 0000000..b40427d
--- /dev/null
+++ b/projects/hsm/cryptech_upload
@@ -0,0 +1,385 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2016-2017, NORDUnet A/S All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+# - Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# - 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.
+#
+# - Neither the name of the NORDUnet nor the names of its contributors may
+# be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+# HOLDER 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.
+
+"""
+Utility to upload a new firmware image or FPGA bitstream.
+"""
+
+import os
+import sys
+import time
+import struct
+import serial
+import socket
+import getpass
+import os.path
+import tarfile
+import argparse
+import platform
+
+from binascii import crc32, hexlify
+
+FIRMWARE_CHUNK_SIZE = 4096
+FPGA_CHUNK_SIZE = 4096
+
+
+def parse_args():
+ """
+ Parse the command line arguments
+ """
+
+ share_directory = "/usr/share" if platform.system() == "Linux" else "/usr/local/share"
+
+ default_tarball = os.path.join(share_directory, "cryptech-alpha-firmware.tar.gz")
+
+ if not os.path.exists(default_tarball):
+ default_tarball = None
+
+ parser = argparse.ArgumentParser(description = __doc__,
+ formatter_class = argparse.ArgumentDefaultsHelpFormatter,
+ )
+
+ parser.add_argument("-d", "--device",
+ default = os.getenv("CRYPTECH_CTY_CLIENT_SERIAL_DEVICE", "/dev/ttyUSB0"),
+ help = "Name of management port USB serial device",
+ )
+
+ parser.add_argument("--socket",
+ default = os.getenv("CRYPTECH_CTY_CLIENT_SOCKET_NAME",
+ "/tmp/.cryptech_muxd.cty"),
+ help = "Name of cryptech_muxd management port socket",
+ )
+
+ parser.add_argument("--firmware-tarball",
+ type = argparse.FileType("rb"),
+ default = default_tarball,
+ help = "Location of firmware tarball",
+ )
+
+ parser.add_argument("--username",
+ choices = ("so", "wheel"),
+ default = "so",
+ help = "Username to use when logging into the HSM",
+ )
+
+ parser.add_argument("--pin",
+ help = "PIN to use when logging into the HSM",
+ )
+
+ parser.add_argument("--separate-pins",
+ action = "store_true",
+ help = "Prompt separately for each PIN required during firmware upload")
+
+ actions = parser.add_mutually_exclusive_group(required = True)
+ actions.add_argument("--fpga",
+ action = "store_true",
+ help = "Upload FPGA bitstream",
+ )
+ actions.add_argument("--firmware", "--hsm",
+ action = "store_true",
+ help = "Upload HSM firmware image",
+ )
+ actions.add_argument("--bootloader",
+ action = "store_true",
+ help = "Upload bootloader image (dangerous!)",
+ )
+
+ parser.add_argument("--simon-says-whack-my-bootloader",
+ action = "store_true",
+ help = "Confirm that you really want to risk bricking the HSM",
+ )
+
+ parser.add_argument("-i", "--explicit-image",
+ type = argparse.FileType("rb"),
+ help = "Explicit source image file for upload, overrides firmware tarball")
+
+ parser.add_argument("--debug",
+ action = "store_true",
+ help = "Enable debugging of upload protocol",
+ )
+
+ parser.add_argument("-q", "--quiet",
+ action = "store_true",
+ help = "Only report errors",
+ )
+
+ return parser.parse_args()
+
+
+class ManagementPortAbstract(object):
+ """
+ Abstract class encapsulating actions on the HSM management port.
+ """
+
+ def __init__(self, args):
+ self.args = args
+
+ def write(self, data):
+ numeric = isinstance(data, int)
+ if numeric:
+ data = struct.pack("<I", data)
+ self.send(data)
+ if self.args.debug:
+ if numeric:
+ print("Wrote 0x{}".format(hexlify(data).decode("ascii")))
+ else:
+ print("Wrote {!r}".format(data))
+
+ def read(self):
+ res = b""
+ x = self.recv()
+ while not x:
+ x = self.recv()
+ while x:
+ res += x
+ x = self.recv()
+ if self.args.debug:
+ print("Read {!r}".format(res))
+ return res
+
+ def execute(self, cmd):
+ self.write(b"\r")
+ prompt = self.read()
+ #if prompt.endswith("This is the bootloader speaking..."):
+ # prompt = self.read()
+ if prompt.endswith(b"Username: "):
+ self.write(self.args.username.encode("ascii") + b"\r")
+ prompt = self.read()
+ if prompt.endswith(b"Password: "):
+ if not self.args.pin or self.args.separate_pins:
+ self.args.pin = getpass.getpass("{} PIN: ".format(self.args.username))
+ self.write(self.args.pin.encode("ascii") + b"\r")
+ prompt = self.read()
+ if not prompt.endswith((b"> ", b"# ")):
+ print("Device does not seem to be ready for a file transfer (got {!r})".format(prompt))
+ return prompt
+ self.write(cmd + b"\r")
+ response = self.read()
+ return response
+
+
+class ManagementPortSerial(ManagementPortAbstract):
+ """
+ Implmentation of HSM management port abstraction over a direct
+ serial connection.
+ """
+
+ def __init__(self, args, timeout = 1):
+ super(ManagementPortSerial, self).__init__(args)
+ self.serial = serial.Serial(args.device, 921600, timeout = timeout)
+
+ def send(self, data):
+ self.serial.write(data)
+ self.serial.flush()
+
+ def recv(self):
+ return self.serial.read(1)
+
+ def set_timeout(self, timeout):
+ self.serial.timeout = timeout
+
+ def close(self):
+ self.serial.close()
+
+class ManagementPortSocket(ManagementPortAbstract):
+ """
+ Implmentation of HSM management port abstraction over a PF_UNIX
+ socket connection to the cryptech_muxd management socket.
+ """
+
+ def __init__(self, args, timeout = 1):
+ super(ManagementPortSocket, self).__init__(args)
+ self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ self.socket.connect(args.socket)
+ self.socket.settimeout(timeout)
+
+ def send(self, data):
+ self.socket.sendall(data)
+
+ def recv(self):
+ try:
+ return self.socket.recv(1)
+ except socket.timeout:
+ return b""
+
+ def set_timeout(self, timeout):
+ self.socket.settimeout(timeout)
+
+ def close(self):
+ self.socket.close()
+
+
+def send_file(src, size, args, dst):
+ """
+ Upload an image from some file-like source to the management port.
+ Details depend on what kind of image it is.
+ """
+
+ if args.fpga:
+ chunk_size = FPGA_CHUNK_SIZE
+ response = dst.execute(b"fpga bitstream upload")
+ elif args.firmware:
+ chunk_size = FIRMWARE_CHUNK_SIZE
+ response = dst.execute(b"firmware upload")
+ if b"Rebooting" in response:
+ response = dst.execute(b"firmware upload")
+ elif args.bootloader:
+ chunk_size = FIRMWARE_CHUNK_SIZE
+ response = dst.execute(b"bootloader upload")
+ if b"Access denied" in response:
+ print("Access denied")
+ return False
+ if not b"OK" in response:
+ print("Device did not accept the upload command (got {!r})".format(response))
+ return False
+
+ dst.set_timeout(0.001)
+ crc = 0
+ counter = 0
+ # 1. Write size of file (4 bytes)
+ dst.write(struct.pack("<I", size))
+ response = dst.read()
+ if not response.startswith(b"Send "):
+ print(response)
+ return False
+
+ # 2. Write file contents while calculating CRC-32
+ chunks = int((size + chunk_size - 1) / chunk_size)
+ for counter in range(chunks):
+ data = src.read(chunk_size)
+ dst.write(data)
+ if not args.quiet:
+ print("Wrote {!s} bytes (chunk {!s}/{!s})".format(len(data), counter + 1, chunks))
+ # read ACK (a counter of number of 4k chunks received)
+ ack_bytes = b""
+ while len(ack_bytes) < 4:
+ ack_bytes += dst.read()
+ ack = struct.unpack("<I", ack_bytes[:4])[0]
+ if ack != counter + 1:
+ print("ERROR: Did not receive the expected counter as ACK (got {!r}/{!r}, not {!r})".format(ack, ack_bytes, counter))
+ return False
+ counter += 1
+
+ crc = crc32(data, crc) & 0xffffffff
+
+ # 3. Write CRC-32 (4 bytes)
+ dst.write(struct.pack("<I", crc))
+ response = dst.read()
+ if not args.quiet:
+ print(response)
+
+ src.close()
+
+ if args.fpga:
+ # tell the fpga to read its new configuration
+ dst.execute(b"fpga reset")
+ # log out of the CLI
+ # (firmware/bootloader upgrades reboot, don't need an exit)
+ dst.execute(b"exit")
+
+ return True
+
+
+dire_bootloader_warning = '''
+ WARNING
+
+Updating the bootloader risks bricking your HSM! If something goes
+badly wrong here, or you upload a bad bootloader image, you will not
+be able to recover without an ST-LINK programmer.
+
+In most cases a normal "--firmware" upgrade should be all that is
+necessary to bring your HSM up to date, there is seldom any real need
+to update the bootloader.
+
+Do not proceed with this unless you REALLY know what you are doing.
+
+If you got here by accident, ^C now, without answering the PIN prompt.
+'''
+
+
+def main():
+ global args
+ args = parse_args()
+
+
+ if args.bootloader:
+ if not args.simon_says_whack_my_bootloader:
+ sys.exit("You didn't say \"Simon says\"")
+ print(dire_bootloader_warning)
+ args.pin = None
+
+ if args.explicit_image is None and args.firmware_tarball is None:
+ sys.exit("No source file specified for upload and firmware tarball not found")
+
+ if args.explicit_image:
+ src = args.explicit_image # file-like object, thanks to argparse
+ size = os.fstat(src.fileno()).st_size
+ if size == 0: # Flashing from stdin won't work, sorry
+ sys.exit("Can't flash from a pipe or zero-length file")
+ if not args.quiet:
+ print("Uploading from explicitly-specified file {}".format(args.explicit_image.name))
+
+ else:
+ tar = tarfile.open(fileobj = args.firmware_tarball)
+ if not args.quiet:
+ print("Firmware tarball {} content:".format(args.firmware_tarball.name))
+ tar.list(True)
+ if args.fpga:
+ name = "alpha_fmc.bit"
+ elif args.firmware:
+ name = "hsm.bin"
+ elif args.bootloader:
+ name = "bootloader.bin"
+ else:
+ # Somebody updated other part of this script without updating this part :(
+ sys.exit("Don't know which component to select from firmware tarball, sorry")
+ try:
+ size = tar.getmember(name).size
+ except KeyError:
+ sys.exit("Expected component {} missing from firmware tarball {}".format(name, args.firmware_tarball.name))
+ src = tar.extractfile(name)
+ if not args.quiet:
+ print("Uploading {} from {}".format(name, args.firmware_tarball.name))
+
+ if not args.quiet:
+ print("Initializing management port and synchronizing with HSM, this may take a few seconds")
+ try:
+ dst = ManagementPortSocket(args, timeout = 1)
+ except socket.error as e:
+ dst = ManagementPortSerial(args, timeout = 1)
+ send_file(src, size, args, dst)
+ dst.close()
+
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
diff --git a/projects/hsm/hsm.c b/projects/hsm/hsm.c
new file mode 100644
index 0000000..52157c9
--- /dev/null
+++ b/projects/hsm/hsm.c
@@ -0,0 +1,522 @@
+/*
+ * hsm.c
+ * ----------------
+ * Main module for the HSM project.
+ *
+ * Copyright (c) 2016-2017, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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.
+ */
+
+/*
+ * This is the main RPC server module. At the moment, it has a single
+ * worker thread to handle RPC requests, while the main thread handles CLI
+ * activity. The design allows for multiple worker threads to handle
+ * concurrent RPC requests from multiple clients (muxed through a daemon
+ * on the host).
+ */
+
+#include <string.h>
+
+/* Rename both CMSIS HAL_OK and libhal HAL_OK to disambiguate */
+#define HAL_OK CMSIS_HAL_OK
+#include "stm-init.h"
+#include "stm-led.h"
+#include "stm-fmc.h"
+#include "stm-uart.h"
+#include "stm-sdram.h"
+#include "task.h"
+
+#include "mgmt-cli.h"
+
+#undef HAL_OK
+#define HAL_OK LIBHAL_OK
+#include "hal.h"
+#include "hal_internal.h"
+#include "slip_internal.h"
+#include "xdr_internal.h"
+#undef HAL_OK
+
+#ifndef NUM_RPC_TASK
+#define NUM_RPC_TASK 1
+#elif NUM_RPC_TASK < 1 || NUM_RPC_TASK > 10
+#error invalid NUM_RPC_TASK
+#endif
+
+#ifndef TASK_STACK_SIZE
+/* Define an absurdly large task stack, because some pkey operation use a
+ * lot of stack variables. This has to go in SDRAM, because it exceeds the
+ * total RAM on the ARM.
+ */
+#define TASK_STACK_SIZE 200*1024
+#endif
+
+/* Stack for the busy task. This doesn't need to be very big.
+ */
+#ifndef BUSY_STACK_SIZE
+#define BUSY_STACK_SIZE 1*1024
+#endif
+static uint8_t busy_stack[BUSY_STACK_SIZE];
+
+/* Stack for the CLI task. This needs to be big enough to accept a
+ * 4096-byte block of an FPGA or bootloader image upload.
+ */
+#ifndef CLI_STACK_SIZE
+#define CLI_STACK_SIZE 16*1024
+#endif
+
+/* RPC buffers. For each active request, there will be two - input and output.
+ */
+typedef struct rpc_buffer_s {
+ size_t len;
+ uint8_t buf[HAL_RPC_MAX_PKT_SIZE];
+ struct rpc_buffer_s *next; /* for ibuf queue linking */
+} rpc_buffer_t;
+
+/* RPC input (requst) buffers */
+static rpc_buffer_t *ibufs;
+
+/* ibuf queue structure */
+typedef struct {
+ rpc_buffer_t *head, *tail;
+ size_t len, max; /* for reporting */
+} ibufq_t;
+
+/* ibuf queues. These correspond roughly to task states - 'waiting' is for
+ * unallocated ibufs, while 'ready' is for requests that are ready to be
+ * processed.
+ */
+static ibufq_t ibuf_waiting, ibuf_ready;
+
+/* Get an ibuf from a queue. */
+static rpc_buffer_t *ibuf_get(ibufq_t *q)
+{
+ hal_critical_section_start();
+ rpc_buffer_t *ibuf = q->head;
+ if (ibuf) {
+ q->head = ibuf->next;
+ if (q->head == NULL)
+ q->tail = NULL;
+ ibuf->next = NULL;
+ --q->len;
+ }
+ hal_critical_section_end();
+ return ibuf;
+}
+
+/* Put an ibuf on a queue. */
+static void ibuf_put(ibufq_t *q, rpc_buffer_t *ibuf)
+{
+ hal_critical_section_start();
+ if (q->tail)
+ q->tail->next = ibuf;
+ else
+ q->head = ibuf;
+ q->tail = ibuf;
+ ibuf->next = NULL;
+ if (++q->len > q->max)
+ q->max = q->len;
+ hal_critical_section_end();
+}
+
+/* Get the current length of the 'ready' queue, for reporting in the CLI. */
+size_t request_queue_len(void)
+{
+ size_t n;
+
+ hal_critical_section_start();
+ n = ibuf_ready.len;
+ hal_critical_section_end();
+
+ return n;
+}
+
+/* Get the maximum length of the 'ready' queue, for reporting in the CLI. */
+size_t request_queue_max(void)
+{
+ size_t n;
+
+ hal_critical_section_start();
+ n = ibuf_ready.max;
+ hal_critical_section_end();
+
+ return n;
+}
+
+static void dispatch_task(void);
+static void busy_task(void);
+static tcb_t *busy_tcb;
+
+/* Select an available dispatch task. For simplicity, this doesn't try to
+ * allocate tasks in a round-robin fashion, so the lowest-numbered task
+ * will see the most action. OTOH, this lets us gauge the level of system
+ * activity in the CLI's 'task show' command.
+ */
+static tcb_t *task_next_waiting(void)
+{
+ for (tcb_t *t = task_iterate(NULL); t; t = task_iterate(t)) {
+ if (task_get_func(t) == dispatch_task &&
+ task_get_state(t) == TASK_WAITING)
+ return t;
+ }
+ return NULL;
+}
+
+static uint8_t *sdram_malloc(size_t size);
+
+/* Callback for HAL_UART_Receive_DMA().
+ */
+static void RxCallback(uint8_t c)
+{
+ int complete;
+ static rpc_buffer_t *ibuf = NULL;
+
+ /* If we couldn't previously get an ibuf, a task may have freed one up
+ * in the meantime. Otherwise, allocate one from SDRAM. In normal
+ * operation, the number of ibufs will expand to the number of remote
+ * clients (which we don't know and can't predict). It would take an
+ * active attempt to DOS the system to exhaust SDRAM, and there are
+ * easier ways to attack the device (don't release hash or pkey handles).
+ */
+ if (ibuf == NULL) {
+ ibuf = ibuf_get(&ibuf_waiting);
+ if (ibuf == NULL) {
+ ibuf = (rpc_buffer_t *)sdram_malloc(sizeof(rpc_buffer_t));
+ if (ibuf == NULL)
+ Error_Handler();
+ }
+ ibuf->len = 0;
+ }
+
+ /* Process this character into the ibuf. */
+ if (hal_slip_process_char(c, ibuf->buf, &ibuf->len, sizeof(ibuf->buf), &complete) != LIBHAL_OK)
+ Error_Handler();
+
+ if (complete) {
+ /* Add the ibuf to the request queue, and try to get another ibuf.
+ */
+ ibuf_put(&ibuf_ready, ibuf);
+ ibuf = ibuf_get(&ibuf_waiting);
+ if (ibuf != NULL)
+ ibuf->len = 0;
+ /* else all ibufs are busy, try again next time */
+
+ /* Wake a dispatch task to deal with this request, or wake the
+ * busy task to re-try scheduling a dispatch task.
+ */
+ tcb_t *t = task_next_waiting();
+ if (t)
+ task_wake(t);
+ else
+ task_wake(busy_tcb);
+ }
+}
+
+/* A ring buffer for the UART DMA receiver. In theory, it should get at most
+ * 92 characters per 1ms tick, but we're going to up-size it for safety.
+ */
+#ifndef RPC_UART_RECVBUF_SIZE
+#define RPC_UART_RECVBUF_SIZE 1024 /* must be a power of 2 */
+#endif
+#define RPC_UART_RECVBUF_MASK (RPC_UART_RECVBUF_SIZE - 1)
+
+typedef struct {
+ uint32_t ridx;
+ uint8_t buf[RPC_UART_RECVBUF_SIZE];
+} uart_ringbuf_t;
+
+volatile uart_ringbuf_t uart_ringbuf = {0, {0}};
+
+#define RINGBUF_RIDX(rb) (rb.ridx & RPC_UART_RECVBUF_MASK)
+#define RINGBUF_WIDX(rb) (sizeof(rb.buf) - __HAL_DMA_GET_COUNTER(huart_user.hdmarx))
+#define RINGBUF_COUNT(rb) ((RINGBUF_WIDX(rb) - RINGBUF_RIDX(rb)) & RPC_UART_RECVBUF_MASK)
+#define RINGBUF_READ(rb, dst) {dst = rb.buf[RINGBUF_RIDX(rb)]; rb.ridx++;}
+
+size_t uart_rx_max = 0;
+
+void HAL_SYSTICK_Callback(void)
+{
+#ifdef DO_PROFILING
+ extern void profil_callback(void);
+ profil_callback();
+#endif
+
+ size_t count = RINGBUF_COUNT(uart_ringbuf);
+ if (uart_rx_max < count) uart_rx_max = count;
+
+ while (RINGBUF_COUNT(uart_ringbuf)) {
+ uint8_t c;
+ RINGBUF_READ(uart_ringbuf, c);
+ RxCallback(c);
+ }
+}
+
+/* Send one character over the UART. This is called from
+ * hal_slip_send_char().
+ */
+hal_error_t hal_serial_send_char(uint8_t c)
+{
+ return (uart_send_char2(STM_UART_USER, c) == 0) ? LIBHAL_OK : HAL_ERROR_RPC_TRANSPORT;
+}
+
+/* Task entry point for the RPC request handler.
+ */
+static void dispatch_task(void)
+{
+ rpc_buffer_t obuf_s, *obuf = &obuf_s;
+
+ while (1) {
+ /* Wait for a complete RPC request */
+ task_sleep();
+
+ rpc_buffer_t *ibuf = ibuf_get(&ibuf_ready);
+ if (ibuf == NULL)
+ /* probably an error, but go back to sleep */
+ continue;
+
+ memset(obuf, 0, sizeof(*obuf));
+ obuf->len = sizeof(obuf->buf);
+
+ /* Process the request */
+ hal_error_t ret = hal_rpc_server_dispatch(ibuf->buf, ibuf->len, obuf->buf, &obuf->len);
+ ibuf_put(&ibuf_waiting, ibuf);
+ if (ret == LIBHAL_OK) {
+ /* Send the response */
+ if (hal_rpc_sendto(obuf->buf, obuf->len, NULL) != LIBHAL_OK)
+ Error_Handler();
+ }
+ /* Else hal_rpc_server_dispatch failed with an XDR error, which
+ * probably means the request packet was garbage. In any case, we
+ * have nothing to transmit.
+ */
+ }
+}
+
+/* Task entry point for the task-rescheduling task.
+ */
+static void busy_task(void)
+{
+ while (1) {
+ /* Wake as many tasks as we have requests.
+ */
+ size_t n;
+ for (n = request_queue_len(); n > 0; --n) {
+ tcb_t *t;
+ if ((t = task_next_waiting()) != NULL)
+ task_wake(t);
+ else
+ break;
+ }
+ if (n == 0)
+ /* flushed the queue, our work here is done */
+ task_sleep();
+ else
+ /* more work to do, try again after some tasks have run */
+ task_yield();
+ }
+}
+
+#include "stm-fpgacfg.h"
+
+static void hashsig_restart_task(void)
+{
+ /* wait for the fpga to configure itself on cold-boot */
+ while (fpgacfg_check_done() != CMSIS_HAL_OK)
+ task_yield();
+
+ /* reinitialize the hashsig key structures after a device restart */
+ hal_hashsig_ks_init();
+
+ /* done, convert this task to an RPC handler */
+ task_mod((char *)task_get_cookie(NULL), dispatch_task, NULL);
+}
+
+/* end of variables declared with __attribute__((section(".sdram1"))) */
+extern uint8_t _esdram1 __asm ("_esdram1");
+/* end of SDRAM1 section */
+extern uint8_t __end_sdram1 __asm ("__end_sdram1");
+static uint8_t *sdram_heap = &_esdram1;
+
+/* Allocate memory from SDRAM1. */
+static uint8_t *sdram_malloc(size_t size)
+{
+ uint8_t *p = sdram_heap;
+
+#define pad(n) (((n) + 3) & ~3)
+ size = pad(size);
+
+ if (p + size + sizeof(uint32_t) > &__end_sdram1)
+ return NULL;
+
+ *(uint32_t *)p = (uint32_t)size;
+ p += sizeof(uint32_t);
+
+ sdram_heap += size + sizeof(uint32_t);
+ return p;
+}
+
+/* A very limited form of free(), which only frees memory if it's at the
+ * top of the heap.
+ */
+static hal_error_t sdram_free(uint8_t *ptr)
+{
+ uint8_t *p = ptr - sizeof(uint32_t);
+ uint32_t size = *(uint32_t *)p;
+ if (ptr + size == sdram_heap) {
+ sdram_heap = p;
+ return LIBHAL_OK;
+ }
+ else
+ return HAL_ERROR_FORBIDDEN;
+}
+
+hal_error_t sdram_stats(size_t *used, size_t *available)
+{
+ if (used == NULL || available == NULL)
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+ *used = sdram_heap - &_esdram1;
+ *available = &__end_sdram1 - sdram_heap;
+
+ return LIBHAL_OK;
+}
+
+/* Implement static memory allocation for libhal over sdram_malloc().
+ */
+void *hal_allocate_static_memory(const size_t size)
+{
+ return sdram_malloc(size);
+}
+
+hal_error_t hal_free_static_memory(const void * const ptr)
+{
+ return sdram_free((uint8_t *)ptr);
+}
+
+/* Critical section start/end - temporarily disable interrupts.
+ */
+void hal_critical_section_start(void)
+{
+ __disable_irq();
+}
+
+void hal_critical_section_end(void)
+{
+ __enable_irq();
+}
+
+/* A genericized public interface to task_yield(), for calling from
+ * libhal.
+ */
+void hal_task_yield(void)
+{
+ task_yield();
+}
+
+void hal_task_yield_maybe(void)
+{
+ task_yield_maybe();
+}
+
+/* A mutex to arbitrate concurrent access to the keystore.
+ */
+task_mutex_t ks_mutex = { 0 };
+void hal_ks_lock(void) { task_mutex_lock(&ks_mutex); }
+void hal_ks_unlock(void) { task_mutex_unlock(&ks_mutex); }
+
+/* A mutex to arbitrary concurrent access to the RSA blinding factors cache.
+ */
+task_mutex_t rsa_bf_mutex = { 0 };
+void hal_rsa_bf_lock(void) { task_mutex_lock(&rsa_bf_mutex); }
+void hal_rsa_bf_unlock(void) { task_mutex_unlock(&rsa_bf_mutex); }
+
+/* Sleep for specified number of seconds.
+ */
+void hal_sleep(const unsigned seconds) { task_delay(seconds * 1000); }
+
+/* The main task. This does all the setup, and the worker tasks handle
+ * the rest.
+ */
+int main(void)
+{
+ stm_init();
+ led_on(LED_GREEN);
+
+ if (hal_rpc_server_init() != LIBHAL_OK)
+ Error_Handler();
+
+ /* Initialize the ibuf queues. */
+ ibufs = (rpc_buffer_t *)sdram_malloc(NUM_RPC_TASK * sizeof(rpc_buffer_t));
+ if (ibufs == NULL)
+ Error_Handler();
+ memset(ibufs, 0, NUM_RPC_TASK * sizeof(rpc_buffer_t));
+ memset(&ibuf_waiting, 0, sizeof(ibuf_waiting));
+ memset(&ibuf_ready, 0, sizeof(ibuf_ready));
+ for (size_t i = 0; i < NUM_RPC_TASK; ++i)
+ ibuf_put(&ibuf_waiting, &ibufs[i]);
+
+ /* Create the rpc dispatch worker tasks. */
+ static char label[NUM_RPC_TASK][sizeof("dispatch0")];
+ for (int i = 0; i < NUM_RPC_TASK; ++i) {
+ sprintf(label[i], "dispatch%d", i);
+ void *stack = (void *)sdram_malloc(TASK_STACK_SIZE);
+ if (stack == NULL)
+ Error_Handler();
+ if (i == NUM_RPC_TASK - 1) {
+ if (task_add("hashsig_restart", hashsig_restart_task, label[i], stack, TASK_STACK_SIZE) == NULL)
+ Error_Handler();
+ }
+ else {
+ if (task_add(label[i], dispatch_task, NULL, stack, TASK_STACK_SIZE) == NULL)
+ Error_Handler();
+ }
+ }
+
+ /* Create the busy task. */
+ busy_tcb = task_add("busy", busy_task, NULL, busy_stack, sizeof(busy_stack));
+ if (busy_tcb == NULL)
+ Error_Handler();
+
+ /* Start the UART receiver. */
+ if (HAL_UART_Receive_DMA(&huart_user, (uint8_t *) uart_ringbuf.buf, sizeof(uart_ringbuf.buf)) != CMSIS_HAL_OK)
+ Error_Handler();
+
+ /* Launch other tasks (csprng warm-up task?)
+ * Wait for FPGA_DONE interrupt.
+ */
+
+ /* Create the CLI task. */
+ void *cli_stack = (void *)sdram_malloc(CLI_STACK_SIZE);
+ if (task_add("cli", (funcp_t)cli_main, NULL, cli_stack, CLI_STACK_SIZE) == NULL)
+ Error_Handler();
+
+ /* Start the tasker */
+ task_yield();
+
+ /*NOTREACHED*/
+ return 0;
+}
diff --git a/projects/hsm/log.c b/projects/hsm/log.c
new file mode 100644
index 0000000..fbc0e73
--- /dev/null
+++ b/projects/hsm/log.c
@@ -0,0 +1,68 @@
+/*
+ * log.c
+ * -----
+ * Implement libhal logging API on Alpha.
+ *
+ * Copyright (c) 2017, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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 <stdarg.h>
+
+#define HAL_OK CMSIS_HAL_OK
+#include "stm-uart.h"
+#undef HAL_OK
+
+#define HAL_OK LIBHAL_OK
+#include "hal.h"
+#include "hal_internal.h"
+#undef HAL_OK
+
+static hal_log_level_t current_log_level;
+
+void hal_log_set_level(const hal_log_level_t level)
+{
+ current_log_level = level;
+}
+
+void hal_log(const hal_log_level_t level, const char *format, ...)
+{
+ if (level < current_log_level)
+ return;
+
+ char buffer[2048];
+ va_list ap;
+
+ va_start(ap, format);
+ vsnprintf(buffer, sizeof(buffer), format, ap);
+ va_end(ap);
+
+ uart_send_string(buffer);
+ uart_send_string("\r\n");
+}
diff --git a/projects/hsm/main.c b/projects/hsm/main.c
deleted file mode 100644
index 79c567b..0000000
--- a/projects/hsm/main.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * rpc_server.c
- * ------------
- * Remote procedure call server-side private API implementation.
- *
- * Copyright (c) 2016, NORDUnet A/S All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - 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.
- *
- * - Neither the name of the NORDUnet nor the names of its contributors may
- * be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
- * HOLDER 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.
- */
-
-/*
- * This is the main RPC server moddule. It creates a new thread to deal
- * with each request, to prevent a long-running request (e.g. RSA keygen)
- * from blocking independent requests from other clients. This has a
- * number of consequences. We can't do a blocking receive in the main
- * thread, because that prevents the dispatch thread from transmitting the
- * response (because they both want to lock the UART - see
- * stm32f4xx_hal_uart.c). So we have to do a non-blocking receive with a
- * callback routine. But we can't create a thread from the callback
- * routine, because it's in the context of an ISR, so we raise a semaphore
- * for the main thread to create the dispatch thread.
- */
-
-#include <string.h>
-
-#include "cmsis_os.h"
-
-#include "stm-init.h"
-#include "stm-led.h"
-#include "stm-fmc.h"
-#include "stm-uart.h"
-
-/* stm32f4xx_hal_def.h and hal.h both define HAL_OK as an enum value */
-#define HAL_OK HAL_OKAY
-
-#include "hal.h"
-#include "hal_internal.h"
-#include "slip_internal.h"
-#include "xdr_internal.h"
-
-/* RPC buffers. For each active RPC, there will be two - input and output.
- */
-
-#ifndef NUM_RPC_BUFFER
-/* An arbitrary number, but we don't expect to have more than 8 concurrent
- * RPC requests.
- */
-#define NUM_RPC_BUFFER 16
-#endif
-
-#ifndef MAX_PKT_SIZE
-/* Another arbitrary number, more or less driven by the 4096-bit RSA
- * keygen test.
- */
-#define MAX_PKT_SIZE 4096
-#endif
-
-/* The thread entry point takes a single void* argument, so we bundle the
- * packet buffer and length arguments together.
- */
-typedef struct {
- size_t len;
- uint8_t buf[MAX_PKT_SIZE];
-} rpc_buffer_t;
-
-osPoolDef(rpc_buffer_pool, NUM_RPC_BUFFER, rpc_buffer_t);
-osPoolId rpc_buffer_pool;
-
-static rpc_buffer_t *rpc_buffer_alloc(void)
-{
- return (rpc_buffer_t *)osPoolCAlloc(rpc_buffer_pool);
-}
-
-/* A mutex to arbitrate concurrent UART transmits, from RPC responses.
- */
-osMutexId uart_mutex;
-osMutexDef(uart_mutex);
-
-/* Thread entry point for the RPC request handler.
- */
-static void dispatch_thread(void const *args)
-{
- rpc_buffer_t *ibuf = (rpc_buffer_t *)args;
- rpc_buffer_t *obuf = rpc_buffer_alloc();
- if (obuf == NULL) {
- uint8_t buf[8];
- uint8_t * bufptr = &buf[4];
- const uint8_t * const limit = buf + sizeof(buf);
- memcpy(buf, ibuf->buf, 4);
- hal_xdr_encode_int(&bufptr, limit, HAL_ERROR_ALLOCATION_FAILURE);
- osMutexWait(uart_mutex, osWaitForever);
- hal_rpc_sendto(ibuf->buf, sizeof(buf), NULL);
- osMutexRelease(uart_mutex);
- osPoolFree(rpc_buffer_pool, ibuf);
- Error_Handler();
- }
- /* copy client ID from request to response */
- memcpy(obuf->buf, ibuf->buf, 4);
- obuf->len = sizeof(obuf->buf) - 4;
- hal_rpc_server_dispatch(ibuf->buf + 4, ibuf->len - 4, obuf->buf + 4, &obuf->len);
- osPoolFree(rpc_buffer_pool, ibuf);
- osMutexWait(uart_mutex, osWaitForever);
- hal_error_t ret = hal_rpc_sendto(obuf->buf, obuf->len + 4, NULL);
- osMutexRelease(uart_mutex);
- osPoolFree(rpc_buffer_pool, obuf);
- if (ret != HAL_OK)
- Error_Handler();
-}
-osThreadDef(dispatch_thread, osPriorityNormal, DEFAULT_STACK_SIZE);
-
-/* Semaphore to inform the main thread that there's a new RPC request.
- */
-osSemaphoreId rpc_sem;
-osSemaphoreDef(rpc_sem);
-
-static uint8_t c; /* current character received from UART */
-static rpc_buffer_t *ibuf; /* current RPC input buffer */
-
-/* Callback for HAL_UART_Receive_IT().
- */
-void HAL_UART2_RxCpltCallback(UART_HandleTypeDef *huart)
-{
- int complete;
- hal_slip_recv_char(ibuf->buf, &ibuf->len, sizeof(ibuf->buf), &complete);
- if (complete)
- osSemaphoreRelease(rpc_sem);
-
- HAL_UART_Receive_IT(huart, &c, 1);
-}
-
-hal_error_t hal_serial_send_char(uint8_t c)
-{
- return (uart_send_char(c) == 0) ? HAL_OK : HAL_ERROR_RPC_TRANSPORT;
-}
-
-hal_error_t hal_serial_recv_char(uint8_t *cp)
-{
- /* return the character from HAL_UART_Receive_IT */
- *cp = c;
- return HAL_OK;
-}
-
-/* The main thread. After the system setup, it waits for the RPC-request
- * semaphore from HAL_UART_RxCpltCallback, and spawns a dispatch thread.
- */
-int main()
-{
- stm_init();
-
-#ifdef TARGET_CRYPTECH_DEV_BRIDGE
- /* Wait six seconds to not upset the Novena at boot. */
- led_on(LED_BLUE);
- for (int i = 0; i < 12; i++) {
- osDelay(500);
- led_toggle(LED_BLUE);
- }
- led_off(LED_BLUE);
-#endif
- led_on(LED_GREEN);
- /* Prepare FMC interface. */
- fmc_init();
-
- /* Haaaack. probe_cores() calls malloc(), which works from the main
- * thread, but not from a spawned thread. It would be better to
- * rewrite it to use static memory, but for now, just force it to
- * probe early.
- */
- hal_core_iterate(NULL);
-
- rpc_buffer_pool = osPoolCreate(osPool(rpc_buffer_pool));
- uart_mutex = osMutexCreate(osMutex(uart_mutex));
- rpc_sem = osSemaphoreCreate(osSemaphore(rpc_sem), 0);
-
-#ifdef TARGET_CRYPTECH_ALPHA
- /* Launch other threads:
- * - admin thread on USART1
- * - csprng warm-up thread?
- */
-#endif
-
- if (hal_rpc_server_init() != HAL_OK)
- Error_Handler();
-
- ibuf = rpc_buffer_alloc();
- if (ibuf == NULL)
- /* Something is badly wrong. */
- Error_Handler();
-
- /* Start the non-blocking receive */
- HAL_UART_Receive_IT(&huart_user, &c, 1);
-
- while (1) {
- osSemaphoreWait(rpc_sem, osWaitForever);
- if (osThreadCreate(osThread(dispatch_thread), (void *)ibuf) == NULL)
- Error_Handler();
- while ((ibuf = rpc_buffer_alloc()) == NULL);
- /* XXX There's a potential race condition, where another request
- * could write into the old ibuf, or into the null pointer if
- * we're out of ibufs.
- */
- }
-}
diff --git a/projects/hsm/mgmt-bootloader.c b/projects/hsm/mgmt-bootloader.c
new file mode 100644
index 0000000..1d8b8ad
--- /dev/null
+++ b/projects/hsm/mgmt-bootloader.c
@@ -0,0 +1,89 @@
+/*
+ * mgmt-bootloader.c
+ * -----------------
+ * CLI code for updating the bootloader.
+ *
+ * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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.
+ */
+
+/* Rename both CMSIS HAL_OK and libhal HAL_OK to disambiguate */
+#define HAL_OK CMSIS_HAL_OK
+#include "stm-init.h"
+#include "stm-uart.h"
+#include "stm-flash.h"
+#include "mgmt-cli.h"
+#include "mgmt-misc.h"
+#include "mgmt-bootloader.h"
+
+#undef HAL_OK
+#define HAL_OK LIBHAL_OK
+#include "hal.h"
+#undef HAL_OK
+
+extern hal_user_t user;
+
+static uint32_t dfu_offset;
+
+static HAL_StatusTypeDef _flash_write_callback(uint8_t *buf, size_t len)
+{
+ HAL_StatusTypeDef status = stm_flash_write32(dfu_offset, (uint32_t *)buf, len/4);
+ dfu_offset += DFU_UPLOAD_CHUNK_SIZE;
+ return status;
+}
+
+static int cmd_bootloader_upload(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ if (user < HAL_USER_SO) {
+ cli_print(cli, "Permission denied.");
+ return CLI_ERROR;
+ }
+
+ uint8_t buf[DFU_UPLOAD_CHUNK_SIZE];
+ dfu_offset = DFU_BOOTLOADER_ADDR;
+
+ int ret = cli_receive_data(cli, buf, sizeof(buf), _flash_write_callback);
+ if (ret == CLI_OK) {
+ cli_print(cli, "\nRebooting\n");
+ HAL_NVIC_SystemReset();
+ }
+ return ret;
+}
+
+void configure_cli_bootloader(struct cli_def *cli)
+{
+ struct cli_command *c;
+
+ c = cli_register_command(cli, NULL, "bootloader", NULL, 0, 0, NULL);
+
+ cli_register_command(cli, c, "upload", cmd_bootloader_upload, 0, 0, "Upload new bootloader image");
+}
diff --git a/projects/hsm/mgmt-bootloader.h b/projects/hsm/mgmt-bootloader.h
new file mode 100644
index 0000000..31dbefc
--- /dev/null
+++ b/projects/hsm/mgmt-bootloader.h
@@ -0,0 +1,51 @@
+/*
+ * mgmt-bootloader.h
+ * ---------------
+ * Management CLI bootloader upgrade code.
+ *
+ * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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 __STM32_CLI_MGMT_BOOTLOADER_H
+#define __STM32_CLI_MGMT_BOOTLOADER_H
+
+#include <libcli.h>
+
+/* symbols defined in the linker script (STM32F429BI_bootloader.ld) */
+extern uint32_t CRYPTECH_BOOTLOADER_START;
+extern uint32_t CRYPTECH_BOOTLOADER_END;
+extern uint32_t CRYPTECH_DFU_CONTROL;
+
+#define DFU_BOOTLOADER_ADDR ((uint32_t) &CRYPTECH_BOOTLOADER_START)
+#define DFU_BOOTLOADER_END_ADDR ((uint32_t) &CRYPTECH_BOOTLOADER_END)
+#define DFU_UPLOAD_CHUNK_SIZE 4096
+
+extern void configure_cli_bootloader(struct cli_def *cli);
+
+#endif /* __STM32_CLI_MGMT_BOOTLOADER_H */
diff --git a/projects/hsm/mgmt-cli.c b/projects/hsm/mgmt-cli.c
new file mode 100644
index 0000000..fd5c90a
--- /dev/null
+++ b/projects/hsm/mgmt-cli.c
@@ -0,0 +1,220 @@
+/*
+ * mgmt-cli.c
+ * ---------
+ * Management CLI code.
+ *
+ * Copyright (c) 2016-2017, NORDUnet A/S All rights reserved.
+ * Copyright: 2020, The Commons Conservancy Cryptech Project
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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 <string.h>
+
+/* Rename both CMSIS HAL_OK and libhal HAL_OK to disambiguate */
+#define HAL_OK CMSIS_HAL_OK
+#include "stm-init.h"
+#include "stm-uart.h"
+#include "stm-led.h"
+#include "task.h"
+
+#include "mgmt-cli.h"
+#include "mgmt-firmware.h"
+#include "mgmt-bootloader.h"
+#include "mgmt-fpga.h"
+#include "mgmt-misc.h"
+#include "mgmt-keystore.h"
+#include "mgmt-masterkey.h"
+#include "mgmt-task.h"
+#ifdef DO_TIMING
+#include "mgmt-timing.h"
+#endif
+
+#undef HAL_OK
+#define HAL_OK LIBHAL_OK
+#include "hal.h"
+#warning Refactor so we do not need to include hal_internal.h here
+#include "hal_internal.h"
+#undef HAL_OK
+
+static tcb_t *cli_task;
+
+#ifndef CLI_UART_RECVBUF_SIZE
+#define CLI_UART_RECVBUF_SIZE 256
+#endif
+
+typedef struct {
+ unsigned ridx;
+ unsigned widx;
+ mgmt_cli_dma_state_t rx_state;
+ uint8_t buf[CLI_UART_RECVBUF_SIZE];
+} ringbuf_t;
+
+inline void ringbuf_init(ringbuf_t *rb)
+{
+ memset(rb, 0, sizeof(*rb));
+}
+
+/* return number of characters read */
+inline int ringbuf_read_char(ringbuf_t *rb, uint8_t *c)
+{
+ if (rb->ridx != rb->widx) {
+ *c = rb->buf[rb->ridx];
+ if (++rb->ridx >= sizeof(rb->buf))
+ rb->ridx = 0;
+ return 1;
+ }
+ return 0;
+}
+
+inline void ringbuf_write_char(ringbuf_t *rb, uint8_t c)
+{
+ rb->buf[rb->widx] = c;
+ if (++rb->widx >= sizeof(rb->buf))
+ rb->widx = 0;
+}
+
+static ringbuf_t uart_ringbuf;
+
+/* current character received from UART */
+static uint8_t uart_rx;
+
+/* Callback for HAL_UART_Receive_DMA().
+ */
+void HAL_UART1_RxCpltCallback(UART_HandleTypeDef *huart)
+{
+ huart = huart;
+
+ ringbuf_write_char(&uart_ringbuf, uart_rx);
+ task_wake(cli_task);
+}
+
+static void uart_cli_print(struct cli_def *cli __attribute__ ((unused)), const char *buf)
+{
+ char crlf[] = "\r\n";
+ uart_send_string(buf);
+ uart_send_string(crlf);
+}
+
+static ssize_t uart_cli_read(struct cli_def *cli __attribute__ ((unused)), void *buf, size_t count)
+{
+ for (size_t i = 0; i < count; ++i) {
+ while (ringbuf_read_char(&uart_ringbuf, (uint8_t *)(buf + i)) == 0)
+ task_sleep();
+ }
+ return (ssize_t)count;
+}
+
+static ssize_t uart_cli_write(struct cli_def *cli __attribute__ ((unused)), const void *buf, size_t count)
+{
+ uart_send_bytes((uint8_t *) buf, count);
+ return (ssize_t)count;
+}
+
+int control_mgmt_uart_dma_rx(mgmt_cli_dma_state_t state)
+{
+ if (state == DMA_RX_START) {
+ if (uart_ringbuf.rx_state != DMA_RX_START) {
+ ringbuf_init(&uart_ringbuf);
+ HAL_UART_Receive_DMA(&huart_mgmt, &uart_rx, 1);
+ uart_ringbuf.rx_state = DMA_RX_START;
+ }
+ return 1;
+ } else if (state == DMA_RX_STOP) {
+ if (HAL_UART_DMAStop(&huart_mgmt) != CMSIS_HAL_OK) return 0;
+ uart_ringbuf.rx_state = DMA_RX_STOP;
+ return 1;
+ }
+ return 0;
+}
+
+hal_user_t user;
+
+static int check_auth(const char *username, const char *password)
+{
+ hal_client_handle_t client = { -1 };
+
+ /* PIN-based login */
+ if (strcmp(username, "wheel") == 0)
+ user = HAL_USER_WHEEL;
+ else if (strcmp(username, "so") == 0)
+ user = HAL_USER_SO;
+ else if (strcmp(username, "user") == 0)
+ user = HAL_USER_NORMAL;
+ else
+ user = HAL_USER_NONE;
+
+ if (hal_rpc_login(client, user, password, strlen(password)) == LIBHAL_OK)
+ return CLI_OK;
+
+ user = HAL_USER_NONE;
+ return CLI_ERROR;
+}
+
+int cli_main(void)
+{
+ cli_task = task_get_tcb();
+
+ struct cli_def *cli;
+ cli = cli_init();
+ if (cli == NULL)
+ Error_Handler();
+
+ cli_read_callback(cli, uart_cli_read);
+ cli_write_callback(cli, uart_cli_write);
+ cli_print_callback(cli, uart_cli_print);
+ cli_set_banner(cli, "Cryptech Alpha");
+ cli_set_hostname(cli, "cryptech");
+ cli_set_auth_callback(cli, check_auth);
+
+ /* we don't have any privileged commands at the moment */
+ cli_unregister_command(cli, "enable");
+
+ configure_cli_fpga(cli);
+ configure_cli_keystore(cli);
+ configure_cli_masterkey(cli);
+ configure_cli_firmware(cli);
+ configure_cli_bootloader(cli);
+ configure_cli_misc(cli);
+ configure_cli_task(cli);
+#ifdef DO_TIMING
+ configure_cli_timing(cli);
+#endif
+
+ while (1) {
+ control_mgmt_uart_dma_rx(DMA_RX_START);
+
+ cli_loop(cli, 0);
+ /* cli_loop returns when the user enters 'quit' or 'exit' */
+ cli_print(cli, "\nLogging out...\n");
+ user = HAL_USER_NONE;
+ }
+
+ /*NOTREACHED*/
+ return -1;
+}
diff --git a/projects/hsm/mgmt-cli.h b/projects/hsm/mgmt-cli.h
new file mode 100644
index 0000000..0b9c40c
--- /dev/null
+++ b/projects/hsm/mgmt-cli.h
@@ -0,0 +1,49 @@
+/*
+ * mgmt-cli.h
+ * ---------
+ * Management CLI code.
+ *
+ * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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 __STM32_MGMT_CLI_H
+#define __STM32_MGMT_CLI_H
+
+#include <libcli.h>
+
+typedef enum {
+ DMA_RX_STOP,
+ DMA_RX_START,
+} mgmt_cli_dma_state_t;
+
+extern int control_mgmt_uart_dma_rx(mgmt_cli_dma_state_t state);
+
+extern int cli_main(void);
+
+#endif /* __STM32_MGMT_CLI_H */
diff --git a/projects/hsm/mgmt-firmware.c b/projects/hsm/mgmt-firmware.c
new file mode 100644
index 0000000..b6b3321
--- /dev/null
+++ b/projects/hsm/mgmt-firmware.c
@@ -0,0 +1,75 @@
+/*
+ * mgmt-firmware.c
+ * ---------------
+ * CLI code for managing the loaded firmware.
+ *
+ * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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.
+ */
+
+/* Rename both CMSIS HAL_OK and libhal HAL_OK to disambiguate */
+#define HAL_OK CMSIS_HAL_OK
+#include "stm-init.h"
+#include "stm-uart.h"
+
+#include "mgmt-cli.h"
+
+#undef HAL_OK
+#define HAL_OK LIBHAL_OK
+#include "hal.h"
+#undef HAL_OK
+
+extern hal_user_t user;
+
+static int cmd_firmware_upload(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ if (user < HAL_USER_SO) {
+ cli_print(cli, "Permission denied.");
+ return CLI_ERROR;
+ }
+
+ /* reboot and let the bootloader handle the upload */
+ cli_print(cli, "\n\n\nRebooting\n\n\n");
+ HAL_NVIC_SystemReset();
+
+ /*NOTREACHED*/
+ return CLI_OK;
+}
+
+void configure_cli_firmware(struct cli_def *cli)
+{
+ struct cli_command *c;
+
+ c = cli_register_command(cli, NULL, "firmware", NULL, 0, 0, NULL);
+
+ cli_register_command(cli, c, "upload", cmd_firmware_upload, 0, 0, "Upload new firmware image");
+}
diff --git a/projects/hsm/mgmt-firmware.h b/projects/hsm/mgmt-firmware.h
new file mode 100644
index 0000000..af7c67c
--- /dev/null
+++ b/projects/hsm/mgmt-firmware.h
@@ -0,0 +1,42 @@
+/*
+ * mgmt-firmware.h
+ * ---------------
+ * Management CLI Device Firmware Upgrade code.
+ *
+ * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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 __STM32_CLI_MGMT_FIRMWARE_H
+#define __STM32_CLI_MGMT_FIRMWARE_H
+
+#include <libcli.h>
+
+extern void configure_cli_firmware(struct cli_def *cli);
+
+#endif /* __STM32_CLI_MGMT_FIRMWARE_H */
diff --git a/projects/hsm/mgmt-fpga.c b/projects/hsm/mgmt-fpga.c
new file mode 100644
index 0000000..af7ba11
--- /dev/null
+++ b/projects/hsm/mgmt-fpga.c
@@ -0,0 +1,194 @@
+/*
+ * mgmt-fpga.c
+ * -----------
+ * CLI code to manage the FPGA configuration etc.
+ *
+ * Copyright (c) 2016-2017, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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.
+ */
+
+/* Rename both CMSIS HAL_OK and libhal HAL_OK to disambiguate */
+#define HAL_OK CMSIS_HAL_OK
+#include "stm-init.h"
+#include "stm-uart.h"
+#include "stm-fpgacfg.h"
+
+#include "mgmt-cli.h"
+#include "mgmt-fpga.h"
+#include "mgmt-misc.h"
+
+#undef HAL_OK
+#define HAL_OK LIBHAL_OK
+#include "hal.h"
+#undef HAL_OK
+
+#include <string.h>
+
+
+extern hal_user_t user;
+
+static volatile uint32_t dfu_offset = 0;
+
+
+static HAL_StatusTypeDef _flash_write_callback(uint8_t *buf, size_t len)
+{
+ HAL_StatusTypeDef res;
+
+ if ((dfu_offset % FPGACFG_SECTOR_SIZE) == 0)
+ /* first page in sector, need to erase sector */
+ if ((res = fpgacfg_erase_sector(dfu_offset / FPGACFG_SECTOR_SIZE)) != CMSIS_HAL_OK)
+ return res;
+
+ /* fpgacfg_write_data (a thin wrapper around n25q128_write_data)
+ * requires the offset and length to be page-aligned. The last chunk
+ * will be short, so we pad it out to the full chunk size.
+ */
+ len = len;
+ res = fpgacfg_write_data(dfu_offset, buf, BITSTREAM_UPLOAD_CHUNK_SIZE);
+ dfu_offset += BITSTREAM_UPLOAD_CHUNK_SIZE;
+ return res;
+}
+
+static int cmd_fpga_bitstream_upload(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ if (user < HAL_USER_SO) {
+ cli_print(cli, "Permission denied.");
+ return CLI_ERROR;
+ }
+
+ uint8_t buf[BITSTREAM_UPLOAD_CHUNK_SIZE];
+
+ dfu_offset = 0;
+
+ fpgacfg_access_control(ALLOW_ARM);
+
+ cli_print(cli, "Checking if FPGA config memory is accessible");
+ if (fpgacfg_check_id() != CMSIS_HAL_OK) {
+ cli_print(cli, "ERROR: FPGA config memory not accessible. Check that jumpers JP7 and JP8 are installed.");
+ return CLI_ERROR;
+ }
+
+ cli_receive_data(cli, &buf[0], sizeof(buf), _flash_write_callback);
+
+ fpgacfg_access_control(ALLOW_FPGA);
+
+ cli_print(cli, "DFU offset now: %li (%li chunks)", dfu_offset, dfu_offset / BITSTREAM_UPLOAD_CHUNK_SIZE);
+ return CLI_OK;
+}
+
+static int cmd_fpga_bitstream_erase(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ fpgacfg_access_control(ALLOW_ARM);
+
+ cli_print(cli, "Checking if FPGA config memory is accessible");
+ if (fpgacfg_check_id() != CMSIS_HAL_OK) {
+ cli_print(cli, "ERROR: FPGA config memory not accessible. Check that jumpers JP7 and JP8 are installed.");
+ return CLI_ERROR;
+ }
+
+ /* Erasing the whole config memory takes a while, we just need to erase the first sector.
+ * The bitstream has an EOF marker, so even if the next bitstream uploaded is shorter than
+ * the current one there should be no problem.
+ *
+ * This command could be made to accept an argument indicating the whole memory should be erased.
+ */
+ if (fpgacfg_erase_sector(0) != CMSIS_HAL_OK) {
+ cli_print(cli, "Erasing first sector in FPGA config memory failed");
+ return CLI_ERROR;
+ }
+
+ cli_print(cli, "Erased FPGA config memory");
+ fpgacfg_access_control(ALLOW_FPGA);
+
+ return CLI_OK;
+}
+
+static int cmd_fpga_reset(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ fpgacfg_access_control(ALLOW_FPGA);
+ fpgacfg_reset_fpga(RESET_FULL);
+ hal_core_reset_table();
+ cli_print(cli, "FPGA has been reset");
+
+ return CLI_OK;
+}
+
+static int cmd_fpga_show_cores(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ hal_core_t *core;
+ const hal_core_info_t *info;
+
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ if (fpgacfg_check_done() != CMSIS_HAL_OK) {
+ cli_print(cli, "FPGA has not loaded a bitstream");
+ return CLI_OK;
+ }
+
+ for (core = hal_core_iterate(NULL); core != NULL; core = hal_core_iterate(core)) {
+ info = hal_core_info(core);
+ cli_print(cli, "%04x: %8.8s %4.4s",
+ (unsigned int)info->base, info->name, info->version);
+ }
+
+ return CLI_OK;
+}
+
+void configure_cli_fpga(struct cli_def *cli)
+{
+ struct cli_command *c = cli_register_command(cli, NULL, "fpga", NULL, 0, 0, NULL);
+
+ struct cli_command *c_show = cli_register_command(cli, c, "show", NULL, 0, 0, NULL);
+ struct cli_command *c_bitstream = cli_register_command(cli, c, "bitstream", NULL, 0, 0, NULL);
+
+ /* fpga show cores */
+ cli_register_command(cli, c_show, "cores", cmd_fpga_show_cores, 0, 0, "Show FPGA core names and versions");
+
+ /* fpga reset */
+ cli_register_command(cli, c, "reset", cmd_fpga_reset, 0, 0, "Reset FPGA (config reset)");
+
+ /* fpga bitstream upload */
+ cli_register_command(cli, c_bitstream, "upload", cmd_fpga_bitstream_upload, 0, 0, "Upload new FPGA bitstream");
+
+ /* fpga bitstream erase */
+ cli_register_command(cli, c_bitstream, "erase", cmd_fpga_bitstream_erase, 0, 0, "Erase FPGA config memory");
+}
diff --git a/projects/hsm/mgmt-fpga.h b/projects/hsm/mgmt-fpga.h
new file mode 100644
index 0000000..9d0aedc
--- /dev/null
+++ b/projects/hsm/mgmt-fpga.h
@@ -0,0 +1,49 @@
+/*
+ * mgmt-fpga.h
+ * -----------
+ * Management FPGA related code.
+ *
+ * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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 __STM32_CLI_MGMT_FPGA_H
+#define __STM32_CLI_MGMT_FPGA_H
+
+#include <libcli.h>
+
+
+/* The chunk size have to be a multiple of the SPI flash page size (256 bytes),
+ and it has to match the chunk size in the program sending the bitstream over the UART.
+*/
+#define BITSTREAM_UPLOAD_CHUNK_SIZE 4096
+
+
+extern void configure_cli_fpga(struct cli_def *cli);
+
+#endif /* __STM32_CLI_MGMT_FPGA_H */
diff --git a/projects/hsm/mgmt-keystore.c b/projects/hsm/mgmt-keystore.c
new file mode 100644
index 0000000..9eb42da
--- /dev/null
+++ b/projects/hsm/mgmt-keystore.c
@@ -0,0 +1,408 @@
+/*
+ * mgmt-keystore.c
+ * ---------------
+ * CLI 'keystore' commands.
+ *
+ * Copyright (c) 2016-2017, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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.
+ */
+
+/* Rename both CMSIS HAL_OK and libhal HAL_OK to disambiguate */
+#define HAL_OK CMSIS_HAL_OK
+#include "stm-init.h"
+#include "stm-keystore.h"
+#include "stm-fpgacfg.h"
+#include "stm-uart.h"
+
+#include "mgmt-cli.h"
+
+#undef HAL_OK
+#define LIBHAL_OK HAL_OK
+#include "hal.h"
+#warning Really should not be including hal_internal.h here, fix API instead of bypassing it
+#include "hal_internal.h"
+#undef HAL_OK
+
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <ctype.h>
+
+
+static int cmd_keystore_set_pin(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ hal_user_t user;
+ hal_error_t status;
+ hal_client_handle_t client = { -1 };
+
+ command = command;
+
+ if (argc != 2) {
+ cli_print(cli, "Wrong number of arguments (%i).", argc);
+ cli_print(cli, "Syntax: keystore set pin <user|so|wheel> <pin>");
+ return CLI_ERROR;
+ }
+
+ if (strcmp(argv[0], "user") == 0)
+ user = HAL_USER_NORMAL;
+ else if (strcmp(argv[0], "so") == 0)
+ user = HAL_USER_SO;
+ else if (strcmp(argv[0], "wheel") == 0)
+ user = HAL_USER_WHEEL;
+ else {
+ cli_print(cli, "First argument must be 'user', 'so' or 'wheel' - not '%s'", argv[0]);
+ return CLI_ERROR;
+ }
+
+ status = hal_rpc_set_pin(client, user, argv[1], strlen(argv[1]));
+ if (status != LIBHAL_OK) {
+ cli_print(cli, "Failed setting PIN: %s", hal_error_string(status));
+ return CLI_ERROR;
+ }
+
+ return CLI_OK;
+}
+
+static int cmd_keystore_clear_pin(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ hal_user_t user;
+ hal_error_t status;
+ hal_client_handle_t client = { -1 };
+
+ command = command;
+
+ if (argc != 1) {
+ cli_print(cli, "Wrong number of arguments (%i).", argc);
+ cli_print(cli, "Syntax: keystore clear pin <user|so|wheel>");
+ return CLI_ERROR;
+ }
+
+ user = HAL_USER_NONE;
+ if (strcmp(argv[0], "user") == 0)
+ user = HAL_USER_NORMAL;
+ else if (strcmp(argv[0], "so") == 0)
+ user = HAL_USER_SO;
+ else if (strcmp(argv[0], "wheel") == 0)
+ user = HAL_USER_WHEEL;
+ else {
+ cli_print(cli, "First argument must be 'user', 'so' or 'wheel' - not '%s'", argv[0]);
+ return CLI_ERROR;
+ }
+
+ if ((status = hal_rpc_set_pin(client, user, "", 0)) != LIBHAL_OK) {
+ cli_print(cli, "Failed clearing PIN: %s", hal_error_string(status));
+ return CLI_ERROR;
+ }
+
+ return CLI_OK;
+}
+
+static int cmd_keystore_set_pin_iterations(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ hal_error_t status;
+ hal_client_handle_t client = { -1 };
+
+ command = command;
+
+ if (argc != 1) {
+ cli_print(cli, "Wrong number of arguments (%i).", argc);
+ cli_print(cli, "Syntax: keystore set pin iterations <number>");
+ return CLI_ERROR;
+ }
+
+ status = hal_set_pin_default_iterations(client, strtoul(argv[0], NULL, 0));
+ if (status != LIBHAL_OK) {
+ cli_print(cli, "Failed setting iterations: %s", hal_error_string(status));
+ return CLI_ERROR;
+ }
+
+ return CLI_OK;
+}
+
+static int cmd_keystore_delete_key(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ const hal_client_handle_t client = { -1 };
+ const hal_session_handle_t session = { HAL_HANDLE_NONE };
+ hal_pkey_handle_t pkey = { HAL_HANDLE_NONE };
+ hal_error_t status;
+ hal_uuid_t name;
+
+ command = command;
+
+ if (argc != 1) {
+ cli_print(cli, "Wrong number of arguments (%i).", argc);
+ cli_print(cli, "Syntax: keystore delete key <name>");
+ return CLI_ERROR;
+ }
+
+ if ((status = hal_uuid_parse(&name, argv[0])) != LIBHAL_OK) {
+ cli_print(cli, "Couldn't parse key name: %s", hal_error_string(status));
+ return CLI_ERROR;
+ }
+
+ if ((status = hal_rpc_pkey_open(client, session, &pkey, &name)) != LIBHAL_OK) {
+ cli_print(cli, "Couldn't find key: %s", hal_error_string(status));
+ return CLI_ERROR;
+ }
+
+ if ((status = hal_rpc_pkey_delete(pkey)) != LIBHAL_OK) {
+ cli_print(cli, "Failed deleting key: %s", hal_error_string(status));
+ (void) hal_rpc_pkey_close(pkey);
+ return CLI_ERROR;
+ }
+
+ cli_print(cli, "Deleted key %s", argv[0]);
+
+ return CLI_OK;
+}
+
+#include "ks.h"
+
+static int show_keys(struct cli_def *cli, const char *title)
+{
+ const hal_client_handle_t client = { -1 };
+ const hal_session_handle_t session = { HAL_HANDLE_NONE };
+ char key_name[HAL_UUID_TEXT_SIZE];
+ hal_uuid_t previous_uuid = {{0}};
+ hal_pkey_handle_t pkey;
+ hal_curve_name_t curve;
+ hal_key_flags_t flags;
+ unsigned n, state = 0;
+ hal_uuid_t uuids[50];
+ hal_key_type_t type;
+ hal_error_t status;
+ int count = 0;
+ int done = 0;
+
+ cli_print(cli, title);
+
+ size_t avail;
+ if ((status = hal_ks_available(hal_ks_token, &avail)) == HAL_OK)
+ cli_print(cli, "Token keystore: %d available", avail);
+ else
+ cli_print(cli, "Error reading token keystore: %s", hal_error_string(status));
+ if ((status = hal_ks_available(hal_ks_volatile, &avail)) == HAL_OK)
+ cli_print(cli, "Volatile keystore: %d available", avail);
+ else
+ cli_print(cli, "Error reading volatile keystore: %s", hal_error_string(status));
+
+ while (!done) {
+
+ if ((status = hal_rpc_pkey_match(client, session, HAL_KEY_TYPE_NONE, HAL_CURVE_NONE,
+ 0, 0, NULL, 0, &state, uuids, &n,
+ sizeof(uuids)/sizeof(*uuids),
+ &previous_uuid)) != LIBHAL_OK) {
+ cli_print(cli, "Could not fetch UUID list: %s", hal_error_string(status));
+ return CLI_ERROR;
+ }
+
+ done = n < sizeof(uuids)/sizeof(*uuids);
+
+ if (!done)
+ previous_uuid = uuids[sizeof(uuids)/sizeof(*uuids) - 1];
+
+ for (unsigned i = 0; i < n; i++) {
+
+ if ((status = hal_uuid_format(&uuids[i], key_name, sizeof(key_name))) != LIBHAL_OK) {
+ cli_print(cli, "Could not convert key name, skipping: %s",
+ hal_error_string(status));
+ continue;
+ }
+
+ if ((status = hal_rpc_pkey_open(client, session, &pkey, &uuids[i])) != LIBHAL_OK) {
+ cli_print(cli, "Could not open key %s, skipping: %s",
+ key_name, hal_error_string(status));
+ continue;
+ }
+
+ if ((status = hal_rpc_pkey_get_key_type(pkey, &type)) != LIBHAL_OK ||
+ (status = hal_rpc_pkey_get_key_curve(pkey, &curve)) != LIBHAL_OK ||
+ (status = hal_rpc_pkey_get_key_flags(pkey, &flags)) != LIBHAL_OK)
+ cli_print(cli, "Could not fetch metadata for key %s, skipping: %s",
+ key_name, hal_error_string(status));
+
+ if (status == LIBHAL_OK)
+ status = hal_rpc_pkey_close(pkey);
+ else
+ (void) hal_rpc_pkey_close(pkey);
+
+ if (status != LIBHAL_OK)
+ continue;
+
+ const char *type_name = "unknown";
+ switch (type) {
+ case HAL_KEY_TYPE_NONE: type_name = "none"; break;
+ case HAL_KEY_TYPE_RSA_PRIVATE: type_name = "RSA private"; break;
+ case HAL_KEY_TYPE_RSA_PUBLIC: type_name = "RSA public"; break;
+ case HAL_KEY_TYPE_EC_PRIVATE: type_name = "EC private"; break;
+ case HAL_KEY_TYPE_EC_PUBLIC: type_name = "EC public"; break;
+ case HAL_KEY_TYPE_HASHSIG_PRIVATE: type_name = "hashsig private"; break;
+ case HAL_KEY_TYPE_HASHSIG_PUBLIC: type_name = "hashsig public"; break;
+ case HAL_KEY_TYPE_HASHSIG_LMS: type_name = "hashsig lms"; break;
+ case HAL_KEY_TYPE_HASHSIG_LMOTS: type_name = "hashsig lmots"; break;
+ }
+
+ const char *curve_name = "unknown";
+ switch (curve) {
+ case HAL_CURVE_NONE: curve_name = "none"; break;
+ case HAL_CURVE_P256: curve_name = "P-256"; break;
+ case HAL_CURVE_P384: curve_name = "P-384"; break;
+ case HAL_CURVE_P521: curve_name = "P-521"; break;
+ }
+
+ cli_print(cli, "Key %2i, name %s, type %s, curve %s, flags 0x%lx",
+ count++, key_name, type_name, curve_name, (unsigned long) flags);
+ }
+ }
+
+ return CLI_OK;
+}
+
+static int show_pin(struct cli_def *cli, char *label, hal_user_t user)
+{
+ const hal_ks_pin_t *p;
+
+ if (hal_get_pin(user, &p) != HAL_OK)
+ return CLI_ERROR;
+
+ /*
+ * I'm not sure iterations is the most interesting thing to show, but
+ * it's what we had before.
+ */
+
+ cli_print(cli, "%s iterations: 0x%lx", label, p->iterations);
+ return CLI_OK;
+}
+
+static int cmd_keystore_show_keys(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ int err = 0;
+
+ err |= show_keys(cli, "Keystore:");
+
+ cli_print(cli, "\nPins:");
+ err |= show_pin(cli, "Wheel", HAL_USER_WHEEL);
+ err |= show_pin(cli, "SO ", HAL_USER_SO);
+ err |= show_pin(cli, "User ", HAL_USER_NORMAL);
+
+ return err ? CLI_ERROR : CLI_OK;
+}
+
+static int cmd_keystore_erase(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ hal_error_t err;
+ HAL_StatusTypeDef status;
+ int preserve_PINs = 0;
+
+ command = command;
+
+ if (argc < 1 || argc > 2 || strcmp(argv[0], "YesIAmSure") != 0) {
+ usage:
+ cli_print(cli, "Syntax: keystore erase YesIAmSure [preservePINs]");
+ return CLI_ERROR;
+ }
+ if (argc == 2) {
+ if (strcasecmp(argv[1], "preservePINs") != 0)
+ goto usage;
+ else
+ preserve_PINs = 1;
+ }
+
+ hal_user_t users[3] = { HAL_USER_NORMAL, HAL_USER_SO, HAL_USER_WHEEL };
+ hal_ks_pin_t pins[3];
+ if (preserve_PINs) {
+ for (size_t i = 0; i < 3; ++i) {
+ const hal_ks_pin_t *pin;
+ if (hal_get_pin(users[i], &pin) != HAL_OK) {
+ cli_print(cli, "Failed to get the PINs");
+ return CLI_ERROR;
+ }
+ memcpy(&pins[i], pin, sizeof(*pin));
+ }
+ }
+
+ cli_print(cli, "OK, erasing keystore, this will take about 45 seconds...");
+ if ((status = keystore_erase_bulk()) != CMSIS_HAL_OK) {
+ cli_print(cli, "Failed erasing token keystore: %i", status);
+ return CLI_ERROR;
+ }
+
+ if ((err = hal_ks_init(hal_ks_token, 0)) != LIBHAL_OK) {
+ cli_print(cli, "Failed to reinitialize token keystore: %s", hal_error_string(err));
+ return CLI_ERROR;
+ }
+
+ if ((err = hal_ks_init(hal_ks_volatile, 0)) != LIBHAL_OK) {
+ cli_print(cli, "Failed to reinitialize memory keystore: %s", hal_error_string(err));
+ return CLI_ERROR;
+ }
+
+ if (preserve_PINs) {
+ for (size_t i = 0; i < 3; ++i) {
+ if (hal_set_pin(users[i], &pins[i]) != HAL_OK) {
+ cli_print(cli, "Failed to restore the PINs");
+ return CLI_ERROR;
+ }
+ }
+ }
+
+ cli_print(cli, "Keystore erased");
+ return CLI_OK;
+}
+
+void configure_cli_keystore(struct cli_def *cli)
+{
+ struct cli_command *c = cli_register_command(cli, NULL, "keystore", NULL, 0, 0, NULL);
+
+ struct cli_command *c_show = cli_register_command(cli, c, "show", NULL, 0, 0, NULL);
+ struct cli_command *c_set = cli_register_command(cli, c, "set", NULL, 0, 0, NULL);
+ struct cli_command *c_clear = cli_register_command(cli, c, "clear", NULL, 0, 0, NULL);
+ struct cli_command *c_delete = cli_register_command(cli, c, "delete", NULL, 0, 0, NULL);
+
+ /* keystore show keys */
+ cli_register_command(cli, c_show, "keys", cmd_keystore_show_keys, 0, 0, "Show what PINs and keys are in the keystore");
+
+ /* keystore set pin */
+ struct cli_command *c_set_pin = cli_register_command(cli, c_set, "pin", cmd_keystore_set_pin, 0, 0, "Set either 'wheel', 'user' or 'so' PIN");
+
+ /* keystore set pin iterations */
+ cli_register_command(cli, c_set_pin, "iterations", cmd_keystore_set_pin_iterations, 0, 0, "Set PBKDF2 iterations for PINs");
+
+ /* keystore clear pin */
+ cli_register_command(cli, c_clear, "pin", cmd_keystore_clear_pin, 0, 0, "Clear either 'wheel', 'user' or 'so' PIN");
+
+ /* keystore delete key */
+ cli_register_command(cli, c_delete, "key", cmd_keystore_delete_key, 0, 0, "Delete a key");
+
+ /* keystore erase */
+ cli_register_command(cli, c, "erase", cmd_keystore_erase, 0, 0, "Erase the whole keystore");
+}
diff --git a/projects/hsm/mgmt-keystore.h b/projects/hsm/mgmt-keystore.h
new file mode 100644
index 0000000..9e14ac6
--- /dev/null
+++ b/projects/hsm/mgmt-keystore.h
@@ -0,0 +1,42 @@
+/*
+ * mgmt-keystore.h
+ * ----------
+ * Management CLI 'keystore' functions.
+ *
+ * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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 __STM32_CLI_MGMT_KEYSTORE_H
+#define __STM32_CLI_MGMT_KEYSTORE_H
+
+#include <libcli.h>
+
+extern void configure_cli_keystore(struct cli_def *cli);
+
+#endif /* __STM32_CLI_MGMT_KEYSTORE_H */
diff --git a/projects/hsm/mgmt-masterkey.c b/projects/hsm/mgmt-masterkey.c
new file mode 100644
index 0000000..97e62a0
--- /dev/null
+++ b/projects/hsm/mgmt-masterkey.c
@@ -0,0 +1,244 @@
+/*
+ * mgmt-masterkey.c
+ * ----------------
+ * Masterkey CLI functions.
+ *
+ * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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.
+ */
+
+/* Rename both CMSIS HAL_OK and libhal HAL_OK to disambiguate */
+#define HAL_OK CMSIS_HAL_OK
+#include "stm-init.h"
+#include "stm-uart.h"
+#include "mgmt-cli.h"
+#include "mgmt-masterkey.h"
+
+#undef HAL_OK
+#define LIBHAL_OK HAL_OK
+#include <hal.h>
+#warning Refactor so we do not need to include hal_internal.h here
+#include <hal_internal.h>
+#undef HAL_OK
+
+#include <stdlib.h>
+
+static char * _status2str(const hal_error_t status)
+{
+ switch (status) {
+ case LIBHAL_OK:
+ return (char *) "Set";
+ case HAL_ERROR_MASTERKEY_NOT_SET:
+ return (char *) "Not set";
+ default:
+ return (char *) "Unknown";
+ }
+}
+
+static int cmd_masterkey_status(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ hal_error_t status;
+
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ cli_print(cli, "Status of master key:\n");
+
+ status = hal_keywrap_mkm_status(NULL);
+ cli_print(cli, " volatile: %s / %s", _status2str(status), hal_error_string(status));
+
+ status = hal_mkm_flash_read(NULL, 0);
+ cli_print(cli, " flash: %s / %s", _status2str(status), hal_error_string(status));
+
+ return CLI_OK;
+}
+
+static int str_to_hex_digit(char c)
+{
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'a' && c <= 'f')
+ c = c - 'a' + 10;
+ else if (c >= 'A' && c <= 'F')
+ c = c - 'A' + 10;
+ else
+ return -1;
+
+ return c;
+}
+
+static inline char hex_to_str_digit(const uint8_t c)
+{
+ return (c < 10) ? ((char)c + '0') : ((char)c + 'A' - 10);
+}
+
+static char *hexdump_kek(const uint8_t * const kek)
+{
+ /* This is only for dumping masterkey values, so has no length checks.
+ * Do not use it for anything else.
+ *
+ * For convenience of possibly hand-copying and hand-retyping, the key
+ * is divided into 8 4-byte (8-character) groups.
+ */
+
+ static char buf[2 * KEK_LENGTH + 8];
+ char *dst = buf;
+
+ for (size_t i = 0; i < KEK_LENGTH; ++i) {
+ uint8_t b = kek[i];
+ *dst++ = hex_to_str_digit(b >> 4);
+ *dst++ = hex_to_str_digit(b & 0xf);
+ if ((i & 3) == 3)
+ *dst++ = ' ';
+ }
+ buf[sizeof(buf) - 1] = '\0';
+
+ return buf;
+}
+
+static int _masterkey_set(struct cli_def *cli, char *argv[], int argc,
+ char *label, hal_error_t (*writer)(const uint8_t * const, const size_t))
+{
+ uint8_t buf[KEK_LENGTH] = {0};
+ hal_error_t err;
+
+ if (argc == 0) {
+ /* fill master key with yummy randomness */
+ if ((err = hal_get_random(NULL, buf, sizeof(buf))) != LIBHAL_OK) {
+ cli_print(cli, "Error getting random key: %s", hal_error_string(err));
+ return CLI_ERROR;
+ }
+ cli_print(cli, "Random key:\n%s", hexdump_kek(buf));
+ }
+
+ else {
+ /* input is 32 hex bytes, arranged however the user wants */
+ size_t len = 0;
+ for (int i = 0; i < argc; ++i) {
+ for (char *cp = argv[i]; *cp != '\0'; ) {
+ int c;
+ if ((c = str_to_hex_digit(*cp++)) < 0)
+ goto errout;
+ buf[len] = c << 4;
+ if ((c = str_to_hex_digit(*cp++)) < 0)
+ goto errout;
+ buf[len] |= c & 0xf;
+ if (++len > KEK_LENGTH)
+ goto errout;
+ }
+ }
+ if (len < KEK_LENGTH) {
+ errout:
+ cli_print(cli, "Failed parsing master key, expected exactly %d hex bytes", KEK_LENGTH);
+ return CLI_ERROR;
+ }
+
+ cli_print(cli, "Parsed key:\n%s", hexdump_kek(buf));
+ }
+
+ if ((err = writer(buf, sizeof(buf))) == LIBHAL_OK) {
+ cli_print(cli, "Master key set in %s memory", label);
+ } else {
+ cli_print(cli, "Failed writing key to %s memory: %s", label, hal_error_string(err));
+ }
+ return CLI_OK;
+}
+
+static hal_error_t _mkm_volatile_write(const uint8_t *kek, const size_t kek_len)
+{
+ return hal_keywrap_mkm_write(NULL, kek, kek_len);
+}
+
+static int cmd_masterkey_set(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ command = command;
+
+ return _masterkey_set(cli, argv, argc, "volatile", _mkm_volatile_write);
+}
+
+static int cmd_masterkey_erase(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ hal_error_t err;
+
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ if ((err = hal_keywrap_mkm_erase(NULL, KEK_LENGTH)) == LIBHAL_OK) {
+ cli_print(cli, "Erased master key from volatile memory");
+ } else {
+ cli_print(cli, "Failed erasing master key from volatile memory: %s", hal_error_string(err));
+ }
+ return CLI_OK;
+}
+
+static int cmd_masterkey_unsecure_set(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ command = command;
+
+ return _masterkey_set(cli, argv, argc, "flash", hal_mkm_flash_write);
+}
+
+static int cmd_masterkey_unsecure_erase(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ hal_error_t err;
+
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ if ((err = hal_mkm_flash_erase(KEK_LENGTH)) == LIBHAL_OK) {
+ cli_print(cli, "Erased unsecure master key from flash");
+ } else {
+ cli_print(cli, "Failed erasing unsecure master key from flash: %s", hal_error_string(err));
+ }
+ return CLI_OK;
+}
+
+void configure_cli_masterkey(struct cli_def *cli)
+{
+ struct cli_command *c = cli_register_command(cli, NULL, "masterkey", NULL, 0, 0, NULL);
+
+ /* masterkey status */
+ cli_register_command(cli, c, "status", cmd_masterkey_status, 0, 0, "Show status of master key in RAM/flash");
+
+ /* masterkey set */
+ cli_register_command(cli, c, "set", cmd_masterkey_set, 0, 0, "Set the master key in the volatile Master Key Memory");
+
+ /* masterkey erase */
+ cli_register_command(cli, c, "erase", cmd_masterkey_erase, 0, 0, "Erase the master key from the volatile Master Key Memory");
+
+ struct cli_command *c_unsecure = cli_register_command(cli, c, "unsecure", NULL, 0, 0, NULL);
+
+ /* masterkey unsecure set */
+ cli_register_command(cli, c_unsecure, "set", cmd_masterkey_unsecure_set, 0, 0, "Set master key in unprotected flash memory (if unsure, DON'T)");
+
+ /* masterkey unsecure erase */
+ cli_register_command(cli, c_unsecure, "erase", cmd_masterkey_unsecure_erase, 0, 0, "Erase master key from unprotected flash memory");
+}
diff --git a/projects/hsm/mgmt-masterkey.h b/projects/hsm/mgmt-masterkey.h
new file mode 100644
index 0000000..67835e9
--- /dev/null
+++ b/projects/hsm/mgmt-masterkey.h
@@ -0,0 +1,42 @@
+/*
+ * mgmt-masterkey.h
+ * -----------
+ * Management CLI masterkeyellaneous functions.
+ *
+ * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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 __STM32_CLI_MGMT_MASTERKEY_H
+#define __STM32_CLI_MGMT_MASTERKEY_H
+
+#include <libcli.h>
+
+extern void configure_cli_masterkey(struct cli_def *cli);
+
+#endif /* __STM32_CLI_MGMT_MASTERKEY_H */
diff --git a/projects/hsm/mgmt-misc.c b/projects/hsm/mgmt-misc.c
new file mode 100644
index 0000000..377af73
--- /dev/null
+++ b/projects/hsm/mgmt-misc.c
@@ -0,0 +1,259 @@
+/*
+ * mgmt-misc.c
+ * -----------
+ * Miscellaneous CLI functions.
+ *
+ * Copyright (c) 2016-2018, NORDUnet A/S All rights reserved.
+ * Copyright: 2020, The Commons Conservancy Cryptech Project
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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.
+ */
+
+#define HAL_OK CMSIS_HAL_OK
+#include "stm-init.h"
+#include "stm-uart.h"
+#include "mgmt-cli.h"
+#include "mgmt-misc.h"
+#undef HAL_OK
+
+#define HAL_OK LIBHAL_OK
+#include "hal.h"
+#include "hal_internal.h"
+#undef HAL_OK
+
+#include <string.h>
+
+
+int cli_receive_data(struct cli_def *cli, uint8_t *buf, size_t len, cli_data_callback data_callback)
+{
+ hal_crc32_t crc = 0, my_crc = hal_crc32_init();
+ uint32_t filesize = 0, counter = 0;
+ size_t n = len;
+
+ if (! control_mgmt_uart_dma_rx(DMA_RX_STOP)) {
+ cli_print(cli, "Failed stopping DMA");
+ goto okay;
+ }
+
+ cli_print(cli, "OK, write size (4 bytes), data in %li byte chunks, CRC-32 (4 bytes)", (uint32_t) n);
+
+ if (uart_receive_bytes((void *) &filesize, sizeof(filesize), 2000) != CMSIS_HAL_OK) {
+ cli_print(cli, "Receive timed out");
+ goto fail;
+ }
+
+ cli_print(cli, "Send %li bytes of data", filesize);
+
+ while (filesize) {
+ /* By initializing buf to the same value that erased flash has (0xff), we don't
+ * have to try and be smart when writing the last page of data to a flash memory.
+ */
+ memset(buf, 0xff, len);
+
+ if (filesize < n) n = filesize;
+
+ if (uart_receive_bytes((void *) buf, n, 2000) != CMSIS_HAL_OK) {
+ cli_print(cli, "Receive timed out");
+ goto fail;
+ }
+ filesize -= n;
+ my_crc = hal_crc32_update(my_crc, buf, n);
+
+ /* After reception of a chunk but before ACKing we have "all" the time in the world to
+ * calculate CRC and invoke the data_callback.
+ */
+ if (data_callback != NULL && data_callback(buf, n) != CMSIS_HAL_OK) {
+ cli_print(cli, "Data processing failed");
+ goto okay;
+ }
+
+ counter++;
+ uart_send_bytes((void *) &counter, 4);
+ }
+
+ my_crc = hal_crc32_finalize(my_crc);
+ cli_print(cli, "Send CRC-32");
+ uart_receive_bytes((void *) &crc, sizeof(crc), 2000);
+ cli_print(cli, "CRC-32 0x%x, calculated CRC 0x%x", (unsigned int) crc, (unsigned int) my_crc);
+ if (crc == my_crc) {
+ cli_print(cli, "CRC checksum MATCHED");
+ } else {
+ cli_print(cli, "CRC checksum did NOT match");
+ }
+
+ okay:
+ control_mgmt_uart_dma_rx(DMA_RX_START);
+ return CLI_OK;
+
+ fail:
+ control_mgmt_uart_dma_rx(DMA_RX_START);
+ return CLI_ERROR;
+}
+
+#ifdef DO_PROFILING
+static int cmd_profile_start(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ cli = cli;
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ extern uint32_t CRYPTECH_FIRMWARE_START;
+ extern char __etext; /* end of text/code symbol, defined by linker */
+ extern void monstartup (size_t lowpc, size_t highpc);
+ monstartup((size_t)&CRYPTECH_FIRMWARE_START, (size_t)&__etext);
+ return CLI_OK;
+}
+
+static int cmd_profile_stop(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ cli = cli;
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ extern void _mcleanup(void);
+ _mcleanup();
+ return CLI_OK;
+}
+
+#endif
+
+static int cmd_reboot(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ cli_print(cli, "\n\n\nRebooting\n\n\n");
+ HAL_NVIC_SystemReset();
+
+ /*NOTREACHED*/
+ return CLI_OK;
+}
+
+static int cmd_rsa_blinding(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ if (argc != 1) {
+ cli_print(cli, "Wrong number of arguments (%i).", argc);
+ cli_print(cli, "Syntax: %s <on|off|clear>", command);
+ return CLI_ERROR;
+ }
+
+ if (strcmp(argv[0], "on") == 0)
+ hal_rsa_set_blinding(1);
+ else if (strcmp(argv[0], "off") == 0)
+ hal_rsa_set_blinding(0);
+ else if (strcmp(argv[0], "clear") == 0)
+ hal_rsa_clear_blinding_cache();
+ else {
+ cli_print(cli, "Argument must be 'on', 'off', or 'clear' - not '%s'", argv[0]);
+ return CLI_ERROR;
+ }
+
+ return CLI_OK;
+}
+
+static int cmd_rsa_crt(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ int onoff;
+
+ if (argc != 1) {
+ cli_print(cli, "Wrong number of arguments (%i).", argc);
+ cli_print(cli, "Syntax: %s <on|off>", command);
+ return CLI_ERROR;
+ }
+
+ if (strcmp(argv[0], "on") == 0)
+ onoff = 1;
+ else if (strcmp(argv[0], "off") == 0)
+ onoff = 0;
+ else {
+ cli_print(cli, "Argument must be 'on' or 'off' - not '%s'", argv[0]);
+ return CLI_ERROR;
+ }
+
+ hal_rsa_set_crt(onoff);
+
+ return CLI_OK;
+}
+
+static int cmd_rsa_modexpng(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ int onoff;
+
+ if (argc != 1) {
+ cli_print(cli, "Wrong number of arguments (%i).", argc);
+ cli_print(cli, "Syntax: %s <on|off>", command);
+ return CLI_ERROR;
+ }
+
+ if (strcmp(argv[0], "on") == 0)
+ onoff = 1;
+ else if (strcmp(argv[0], "off") == 0)
+ onoff = 0;
+ else {
+ cli_print(cli, "Argument must be 'on' or 'off' - not '%s'", argv[0]);
+ return CLI_ERROR;
+ }
+
+ hal_error_t err;
+ if ((err = hal_modexp_use_modexpng(onoff)) == LIBHAL_OK)
+ return CLI_OK;
+
+ cli_print(cli, hal_error_string(err));
+ return CLI_ERROR;
+}
+
+void configure_cli_misc(struct cli_def *cli)
+{
+#ifdef DO_PROFILING
+ struct cli_command *c_profile = cli_register_command(cli, NULL, "profile", NULL, 0, 0, NULL);
+
+ /* profile start */
+ cli_register_command(cli, c_profile, "start", cmd_profile_start, 0, 0, "Start collecting profiling data");
+
+ /* profile stop */
+ cli_register_command(cli, c_profile, "stop", cmd_profile_stop, 0, 0, "Stop collecting profiling data");
+#endif
+
+ struct cli_command *c_rsa = cli_register_command(cli, NULL, "rsa", NULL, 0, 0, NULL);
+
+ /* rsa blinding */
+ cli_register_command(cli, c_rsa, "blinding", cmd_rsa_blinding, 0, 0, "Set use of RSA blinding");
+
+ /* rsa crt */
+ cli_register_command(cli, c_rsa, "crt", cmd_rsa_crt, 0, 0, "Set use of RSA CRT");
+
+ /* rsa modexpng */
+ cli_register_command(cli, c_rsa, "modexpng", cmd_rsa_modexpng, 0, 0, "Set use of ModExpNG");
+
+ /* reboot */
+ cli_register_command(cli, NULL, "reboot", cmd_reboot, 0, 0, "Reboot the STM32");
+}
+
diff --git a/projects/hsm/mgmt-misc.h b/projects/hsm/mgmt-misc.h
new file mode 100644
index 0000000..ef63a9e
--- /dev/null
+++ b/projects/hsm/mgmt-misc.h
@@ -0,0 +1,47 @@
+/*
+ * mgmt-misc.h
+ * -----------
+ * Management CLI miscellaneous functions.
+ *
+ * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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 __STM32_CLI_MGMT_MISC_H
+#define __STM32_CLI_MGMT_MISC_H
+
+#include <libcli.h>
+
+/* Write a chunk of received data to flash. */
+typedef HAL_StatusTypeDef (*cli_data_callback)(uint8_t *, size_t);
+
+extern int cli_receive_data(struct cli_def *cli, uint8_t *buf, size_t len, cli_data_callback data_callback);
+
+extern void configure_cli_misc(struct cli_def *cli);
+
+#endif /* __STM32_CLI_MGMT_MISC_H */
diff --git a/projects/hsm/mgmt-task.c b/projects/hsm/mgmt-task.c
new file mode 100644
index 0000000..180c6d9
--- /dev/null
+++ b/projects/hsm/mgmt-task.c
@@ -0,0 +1,136 @@
+/*
+ * mgmt-task.c
+ * -----------
+ * CLI 'task' functions.
+ *
+ * Copyright (c) 2016-2017, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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.
+ */
+
+/*
+ * Show the active tasks. This is mostly for debugging, and looks deeply
+ * into OS-level structures, but sometimes you just need to know...
+ */
+
+#include "mgmt-cli.h"
+#include "mgmt-task.h"
+#include "task.h"
+
+static char *task_state[] = {
+ "INIT",
+ "WAITING",
+ "READY"
+};
+
+extern size_t request_queue_len(void);
+extern size_t request_queue_max(void);
+
+static int cmd_task_show(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ cli_print(cli, "name state stack high water");
+ cli_print(cli, "-------- -------- ----------------");
+
+ for (tcb_t *t = task_iterate(NULL); t != NULL; t = task_iterate(t)) {
+ cli_print(cli, "%-15s %-15s %d",
+ task_get_name(t),
+ task_state[task_get_state(t)],
+ task_get_stack_highwater(t));
+ }
+
+ cli_print(cli, " ");
+ cli_print(cli, "RPC request queue current length: %u", request_queue_len());
+ cli_print(cli, "RPC request queue maximum length: %u", request_queue_max());
+
+ extern size_t uart_rx_max;
+ cli_print(cli, " ");
+ cli_print(cli, "UART receive queue maximum length: %u", uart_rx_max);
+
+ size_t used, available;
+ extern void sdram_stats(size_t *used, size_t *available);
+ sdram_stats(&used, &available);
+ cli_print(cli, " ");
+ cli_print(cli, "SDRAM used: %u, available: %u", used, available);
+
+ return CLI_OK;
+}
+
+#ifdef DO_TASK_METRICS
+static int cmd_task_show_metrics(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ struct task_metrics tm;
+
+ task_get_metrics(&tm);
+
+ cli_print(cli, "avg time between yields: %ld.%06ld sec", tm.avg.tv_sec, tm.avg.tv_usec);
+ cli_print(cli, "max time between yields: %ld.%06ld sec", tm.max.tv_sec, tm.max.tv_usec);
+
+ return CLI_OK;
+}
+
+static int cmd_task_reset_metrics(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ cli = cli;
+ command = command;
+ argv = argv;
+ argc = argc;
+
+ task_reset_metrics();
+
+ return CLI_OK;
+}
+#endif
+
+void configure_cli_task(struct cli_def *cli)
+{
+ struct cli_command *c = cli_register_command(cli, NULL, "task", NULL, 0, 0, NULL);
+
+ /* task show */
+#ifdef DO_TASK_METRICS
+ struct cli_command *c_show =
+#endif
+ cli_register_command(cli, c, "show", cmd_task_show, 0, 0, "Show the active tasks");
+
+#ifdef DO_TASK_METRICS
+ /* task show metrics */
+ cli_register_command(cli, c_show, "metrics", cmd_task_show_metrics, 0, 0, "Show task metrics");
+
+ /* task reset */
+ struct cli_command *c_reset = cli_register_command(cli, c, "reset", NULL, 0, 0, NULL);
+
+ /* task reset metrics */
+ cli_register_command(cli, c_reset, "metrics", cmd_task_reset_metrics, 0, 0, "Reset task metrics");
+#endif
+}
diff --git a/projects/hsm/mgmt-task.h b/projects/hsm/mgmt-task.h
new file mode 100644
index 0000000..f903962
--- /dev/null
+++ b/projects/hsm/mgmt-task.h
@@ -0,0 +1,42 @@
+/*
+ * mgmt-task.h
+ * -----------
+ * Management CLI 'task' functions.
+ *
+ * Copyright (c) 2016-2017, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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 __STM32_CLI_MGMT_TASK_H
+#define __STM32_CLI_MGMT_TASK_H
+
+#include <libcli.h>
+
+extern void configure_cli_task(struct cli_def *cli);
+
+#endif /* __STM32_CLI_MGMT_TASK_H */
diff --git a/projects/libhal-test/Makefile b/projects/libhal-test/Makefile
index f58f480..c5dbc84 100644
--- a/projects/libhal-test/Makefile
+++ b/projects/libhal-test/Makefile
@@ -1,12 +1,12 @@
-TEST = cores test-bus test-trng test-hash test-aes-key-wrap test-pbkdf2 test-ecdsa test-rsa test-mkmif
+TEST = cores test-bus test-trng test-hash test-aes-key-wrap test-pbkdf2 test-ecdsa test-rsa
-CFLAGS += -I $(LIBHAL_DIR)
+CFLAGS += -I $(LIBHAL_SRC)
LIBC_OBJS = printf.o gettimeofday.o
-LIBS += $(LIBHAL_DIR)/libhal.a $(LIBTFM_DIR)/libtfm.a
+LIBS += $(LIBHAL_BLD)/libhal.a $(LIBTFM_BLD)/libtfm.a
all: $(TEST:=.elf)
-vpath %.c $(LIBHAL_DIR)/tests $(LIBHAL_DIR)/utils
+vpath %.c $(LIBHAL_SRC)/tests $(LIBHAL_SRC)/utils
# .mo extension for files with main() that need to be wrapped as __main()
%.mo: %.c
@@ -17,9 +17,6 @@ vpath %.c $(LIBHAL_DIR)/tests $(LIBHAL_DIR)/utils
$(OBJCOPY) -O binary $*.elf $*.bin
$(SIZE) $*.elf
-# don't automatically delete objects, to avoid a lot of unnecessary rebuilding
-.SECONDARY: $(BOARD_OBJS) $(LIBC_OBJS)
-
clean:
rm -f *.o *.mo
rm -f *.elf
diff --git a/projects/libhal-test/gettimeofday.c b/projects/libhal-test/gettimeofday.c
index b13485d..f7a87f1 100644
--- a/projects/libhal-test/gettimeofday.c
+++ b/projects/libhal-test/gettimeofday.c
@@ -56,6 +56,8 @@ int gettimeofday(struct timeval *tv, struct timezone *tz)
{
uint32_t tick = HAL_GetTick(); /* uptime in ms */
+ tz = tz;
+
tv->tv_sec = tick / 1000;
tv->tv_usec = (tick % 1000) * 1000;
diff --git a/projects/libhal-test/main.c b/projects/libhal-test/main.c
index a40871b..c0d9330 100644
--- a/projects/libhal-test/main.c
+++ b/projects/libhal-test/main.c
@@ -43,18 +43,8 @@ extern void __main(void);
int main(void)
{
stm_init();
-
-#ifdef TARGET_CRYPTECH_DEV_BRIDGE
- // Blink blue LED for six seconds to not upset the Novena at boot.
- led_on(LED_BLUE);
- for (int i = 0; i < 12; i++) {
- HAL_Delay(500);
- led_toggle(LED_BLUE);
- }
- led_off(LED_BLUE);
-#endif
+ HAL_Delay(500);
led_on(LED_GREEN);
- fmc_init();
__main();
diff --git a/projects/libhal-test/printf.c b/projects/libhal-test/printf.c
index 5a15d12..85af09b 100644
--- a/projects/libhal-test/printf.c
+++ b/projects/libhal-test/printf.c
@@ -244,7 +244,7 @@ OK, I found my mistake. The math here is _always_ unsigned */
if (precision != 0)
{
width = max(width, precision);
- if (precision > strlen(where))
+ if (precision > strlen((const char *)where))
flags |= PR_LZ;
precision = 0;
}
@@ -295,7 +295,7 @@ EMIT2: if((flags & PR_LJ) == 0)
count++;
}
/* emit string/char/converted number */
- for(int i = (flags & PR_WS) ? 1 : 0;
+ for(unsigned i = (flags & PR_WS) ? 1 : 0;
i < length; ++i)
{
fn(*where++, &ptr);
@@ -362,6 +362,8 @@ You must write your own putchar()
*****************************************************************************/
int vprintf_help(unsigned c, void **ptr)
{
+ ptr = ptr;
+
putchar(c);
return 0 ;
}
diff --git a/projects/rtos-test/Makefile b/projects/rtos-test/Makefile
deleted file mode 100644
index dd2cab5..0000000
--- a/projects/rtos-test/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-TEST = thread-test semaphore-test mutex-test
-
-all: $(TEST:=.elf)
-
-%.elf: %.o $(BOARD_OBJS) $(LIBS)
- $(CC) $(CFLAGS) $^ -o $@ -T$(LDSCRIPT) -g -Wl,-Map=$*.map
- $(OBJCOPY) -O ihex $*.elf $*.hex
- $(OBJCOPY) -O binary $*.elf $*.bin
- $(OBJDUMP) -St $*.elf >$*.lst
- $(SIZE) $*.elf
-
-clean:
- rm -f *.o
- rm -f *.elf
- rm -f *.hex
- rm -f *.bin
- rm -f *.map
- rm -f *.lst
diff --git a/projects/rtos-test/mutex-test.c b/projects/rtos-test/mutex-test.c
deleted file mode 100644
index 402f9ba..0000000
--- a/projects/rtos-test/mutex-test.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "cmsis_os.h"
-
-#include "stm-init.h"
-#include "stm-uart.h"
-
-osMutexId stdio_mutex;
-osMutexDef(stdio_mutex);
-
-void notify(const char* name, int state) {
- osMutexWait(stdio_mutex, osWaitForever);
- //printf("%s: %d\n\r", name, state);
- uart_send_string(name);
- uart_send_string(": ");
- uart_send_integer(state, 1);
- uart_send_string("\r\n");
- osMutexRelease(stdio_mutex);
-}
-
-void test_thread(void const *args) {
- while (1) {
- notify((const char*)args, 0); osDelay(1000);
- notify((const char*)args, 1); osDelay(1000);
- }
-}
-
-void t2(void const *argument) {test_thread("Th 2");}
-osThreadDef(t2, osPriorityNormal, DEFAULT_STACK_SIZE);
-
-void t3(void const *argument) {test_thread("Th 3");}
-osThreadDef(t3, osPriorityNormal, DEFAULT_STACK_SIZE);
-
-int main() {
- stm_init();
- stdio_mutex = osMutexCreate(osMutex(stdio_mutex));
-
- osThreadCreate(osThread(t2), NULL);
- osThreadCreate(osThread(t3), NULL);
-
- test_thread((void *)"Th 1");
-}
diff --git a/projects/rtos-test/semaphore-test.c b/projects/rtos-test/semaphore-test.c
deleted file mode 100644
index 3a3b5de..0000000
--- a/projects/rtos-test/semaphore-test.c
+++ /dev/null
@@ -1,34 +0,0 @@
-#include "cmsis_os.h"
-
-#include "stm-init.h"
-#include "stm-uart.h"
-
-osSemaphoreId two_slots;
-osSemaphoreDef(two_slots);
-
-void test_thread(void const *name) {
- while (1) {
- osSemaphoreWait(two_slots, osWaitForever);
- //printf("%s\n\r", (const char*)name);
- uart_send_string((const char*)name);
- uart_send_string("\r\n");
- osDelay(1000);
- osSemaphoreRelease(two_slots);
- }
-}
-
-void t2(void const *argument) {test_thread("Th 2");}
-osThreadDef(t2, osPriorityNormal, DEFAULT_STACK_SIZE);
-
-void t3(void const *argument) {test_thread("Th 3");}
-osThreadDef(t3, osPriorityNormal, DEFAULT_STACK_SIZE);
-
-int main (void) {
- stm_init();
- two_slots = osSemaphoreCreate(osSemaphore(two_slots), 2);
-
- osThreadCreate(osThread(t2), NULL);
- osThreadCreate(osThread(t3), NULL);
-
- test_thread((void *)"Th 1");
-}
diff --git a/projects/rtos-test/thread-test.c b/projects/rtos-test/thread-test.c
deleted file mode 100644
index 8b31a26..0000000
--- a/projects/rtos-test/thread-test.c
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "cmsis_os.h"
-
-#include "stm-init.h"
-#include "stm-led.h"
-
-void led2_thread(void const *args)
-{
- while (1) {
- led_toggle(LED_BLUE);
- osDelay(1000);
- }
-}
-osThreadDef(led2_thread, osPriorityNormal, DEFAULT_STACK_SIZE);
-
-int main()
-{
- stm_init();
- osThreadCreate(osThread(led2_thread), NULL);
-
- while (1) {
- led_toggle(LED_GREEN);
- osDelay(500);
- }
-}
diff --git a/spiflash_n25q128.c b/spiflash_n25q128.c
index 6e35a41..df53f19 100644
--- a/spiflash_n25q128.c
+++ b/spiflash_n25q128.c
@@ -6,7 +6,7 @@
* The Alpha board has two of these SPI flash memorys, the FPGA config memory
* and the keystore memory.
*
- * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ * Copyright (c) 2016-2017, NORDUnet A/S All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -35,320 +35,310 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "stm32f4xx_hal.h"
-#include "stm-fpgacfg.h"
-#include "stm-init.h"
+#include "spiflash_n25q128.h"
-#define _n25q128_select(ctx) HAL_GPIO_WritePin(ctx->cs_n_port, ctx->cs_n_pin, GPIO_PIN_RESET);
-#define _n25q128_deselect(ctx) HAL_GPIO_WritePin(ctx->cs_n_port, ctx->cs_n_pin, GPIO_PIN_SET);
+#define N25Q128_NUM_BYTES (N25Q128_PAGE_SIZE * N25Q128_NUM_PAGES)
+#if N25Q128_SECTOR_SIZE * N25Q128_NUM_SECTORS != N25Q128_NUM_BYTES || \
+ N25Q128_SUBSECTOR_SIZE * N25Q128_NUM_SUBSECTORS != N25Q128_NUM_BYTES
+#error Inconsistent definitions for pages / sectors / subsectors
+#endif
-int _n25q128_get_wel_flag(struct spiflash_ctx *ctx);
+static inline void _n25q128_select(struct spiflash_ctx *ctx)
+{
+ HAL_GPIO_WritePin(ctx->cs_n_port, ctx->cs_n_pin, GPIO_PIN_RESET);
+}
+
+static inline void _n25q128_deselect(struct spiflash_ctx *ctx)
+{
+ HAL_GPIO_WritePin(ctx->cs_n_port, ctx->cs_n_pin, GPIO_PIN_SET);
+}
-int n25q128_check_id(struct spiflash_ctx *ctx)
+/* Read a bit from the status register. */
+static inline int _n25q128_get_status_bit(struct spiflash_ctx *ctx, unsigned bitnum)
{
// tx, rx buffers
- uint8_t spi_tx[4];
- uint8_t spi_rx[4];
+ uint8_t spi_tx[2];
+ uint8_t spi_rx[2];
- // result
- HAL_StatusTypeDef ok;
+ //assert(bitnum < sizeof(uint8_t));
- // send READ ID command
- spi_tx[0] = N25Q128_COMMAND_READ_ID;
+ // send READ STATUS command
+ spi_tx[0] = N25Q128_COMMAND_READ_STATUS;
- // select, send command & read response, deselect
+ // send command, read response, deselect
_n25q128_select(ctx);
- ok = HAL_SPI_TransmitReceive(ctx->hspi, spi_tx, spi_rx, 4, N25Q128_SPI_TIMEOUT);
- HAL_Delay(1);
+ int ok =
+ HAL_SPI_TransmitReceive(ctx->hspi, spi_tx, spi_rx, 2, N25Q128_SPI_TIMEOUT) == HAL_OK;
_n25q128_deselect(ctx);
// check
- if (ok != HAL_OK) return 0;
-
- // parse response (note, that the very first byte was received during the
- // transfer of the command byte, so it contains garbage and should
- // be ignored here)
- if (spi_rx[1] != N25Q128_ID_MANUFACTURER) return 0;
- if (spi_rx[2] != N25Q128_ID_DEVICE_TYPE) return 0;
- if (spi_rx[3] != N25Q128_ID_DEVICE_CAPACITY) return 0;
+ if (!ok) return -1;
// done
- return 1;
+ return ((spi_rx[1] >> bitnum) & 1);
}
-
-int n25q128_read_page(struct spiflash_ctx *ctx, uint32_t page_offset, uint8_t *page_buffer)
+/* Read the Write Enable Latch bit in the status register. */
+static inline int _n25q128_get_wel_flag(struct spiflash_ctx *ctx)
{
- // tx buffer
- uint8_t spi_tx[4];
-
- // result
- HAL_StatusTypeDef ok;
-
- // check offset
- if (page_offset >= N25Q128_NUM_PAGES) return 0;
-
- // calculate byte address
- page_offset *= N25Q128_PAGE_SIZE;
-
- // prepare READ command
- spi_tx[0] = N25Q128_COMMAND_READ_PAGE;
- spi_tx[1] = (uint8_t)(page_offset >> 16);
- spi_tx[2] = (uint8_t)(page_offset >> 8);
- spi_tx[3] = (uint8_t)(page_offset >> 0);
-
- // activate, send command
- _n25q128_select(ctx);
- ok = HAL_SPI_Transmit(ctx->hspi, spi_tx, 4, N25Q128_SPI_TIMEOUT);
- HAL_Delay(1);
-
- // check
- if (ok != HAL_OK) {
- _n25q128_deselect(ctx);
- return 0;
- }
-
- // read response, deselect
- ok = HAL_SPI_Receive(ctx->hspi, page_buffer, N25Q128_PAGE_SIZE, N25Q128_SPI_TIMEOUT);
- HAL_Delay(1);
- _n25q128_deselect(ctx);
-
- // check
- if (ok != HAL_OK) return 0;
+ return _n25q128_get_status_bit(ctx, 1);
+}
- // done
- return 1;
+/* Read the Write In Progress bit in the status register. */
+static inline int _n25q128_get_wip_flag(struct spiflash_ctx *ctx)
+{
+ return _n25q128_get_status_bit(ctx, 0);
}
+/* Wait until the flash memory is done writing */
+static HAL_StatusTypeDef _n25q128_wait_while_wip(struct spiflash_ctx *ctx, uint32_t timeout)
+{
+ uint32_t tick_end = HAL_GetTick() + timeout;
+
+ do {
+ switch (_n25q128_get_wip_flag(ctx)) {
+ case 0:
+ return HAL_OK;
+ case -1:
+ return HAL_ERROR;
+ default:
+ /* try again */
+ continue;
+ }
+ } while (HAL_GetTick() < tick_end);
+
+ return HAL_TIMEOUT;
+}
-int n25q128_write_page(struct spiflash_ctx *ctx, uint32_t page_offset, const uint8_t *page_buffer)
+/* Send the Write Enable command */
+static HAL_StatusTypeDef _n25q128_write_enable(struct spiflash_ctx *ctx)
{
// tx buffer
- uint8_t spi_tx[4];
-
- // result
- HAL_StatusTypeDef ok;
-
- // check offset
- if (page_offset >= N25Q128_NUM_PAGES) return 0;
+ uint8_t spi_tx[1];
// enable writing
spi_tx[0] = N25Q128_COMMAND_WRITE_ENABLE;
// activate, send command, deselect
_n25q128_select(ctx);
- ok = HAL_SPI_Transmit(ctx->hspi, spi_tx, 1, N25Q128_SPI_TIMEOUT);
- HAL_Delay(1);
+ int ok =
+ HAL_SPI_Transmit(ctx->hspi, spi_tx, 1, N25Q128_SPI_TIMEOUT) == HAL_OK;
_n25q128_deselect(ctx);
// check
- if (ok != HAL_OK) return 0;
+ if (!ok) return HAL_ERROR;
// make sure, that write enable did the job
- int wel = _n25q128_get_wel_flag(ctx);
- if (wel != 1) return 0;
+ return _n25q128_get_wel_flag(ctx) ? HAL_OK : HAL_ERROR;
+}
- // calculate byte address
- page_offset *= N25Q128_PAGE_SIZE;
+HAL_StatusTypeDef n25q128_check_id(struct spiflash_ctx *ctx)
+{
+ // tx, rx buffers
+ uint8_t spi_tx[4];
+ uint8_t spi_rx[4];
- // prepare PROGRAM PAGE command
- spi_tx[0] = N25Q128_COMMAND_PAGE_PROGRAM;
- spi_tx[1] = (uint8_t)(page_offset >> 16);
- spi_tx[2] = (uint8_t)(page_offset >> 8);
- spi_tx[3] = (uint8_t)(page_offset >> 0);
+ // send READ ID command
+ spi_tx[0] = N25Q128_COMMAND_READ_ID;
- // activate, send command
+ // select, send command & read response, deselect
_n25q128_select(ctx);
- ok = HAL_SPI_Transmit(ctx->hspi, spi_tx, 4, N25Q128_SPI_TIMEOUT);
- HAL_Delay(1);
-
- // check
- if (ok != HAL_OK) {
- _n25q128_deselect(ctx);
- return 0;
- }
-
- // send data, deselect
- ok = HAL_SPI_Transmit(ctx->hspi, (uint8_t *) page_buffer, N25Q128_PAGE_SIZE, N25Q128_SPI_TIMEOUT);
- HAL_Delay(1);
+ int ok =
+ HAL_SPI_TransmitReceive(ctx->hspi, spi_tx, spi_rx, 4, N25Q128_SPI_TIMEOUT) == HAL_OK;
_n25q128_deselect(ctx);
// check
- if (ok != HAL_OK) return 0;
+ if (!ok) return HAL_ERROR;
- // done
- return 1;
+ // parse response (note, that the very first byte was received during the
+ // transfer of the command byte, so it contains garbage and should
+ // be ignored here)
+ return
+ (spi_rx[1] == N25Q128_ID_MANUFACTURER &&
+ spi_rx[2] == N25Q128_ID_DEVICE_TYPE &&
+ spi_rx[3] == N25Q128_ID_DEVICE_CAPACITY) ? HAL_OK : HAL_ERROR;
}
-int n25q128_get_wip_flag(struct spiflash_ctx *ctx)
+HAL_StatusTypeDef n25q128_write_page(struct spiflash_ctx *ctx, uint32_t page_offset, const uint8_t *page_buffer)
{
- // tx, rx buffers
- uint8_t spi_tx[2];
- uint8_t spi_rx[2];
+ // tx buffer
+ uint8_t spi_tx[4];
- // result
- HAL_StatusTypeDef ok;
+ // check offset
+ if (page_offset >= N25Q128_NUM_PAGES) return HAL_ERROR;
- // send READ STATUS command
- spi_tx[0] = N25Q128_COMMAND_READ_STATUS;
+ // enable writing
+ if (_n25q128_write_enable(ctx) != 0) return HAL_ERROR;
- // send command, read response, deselect
+ // calculate byte address
+ uint32_t byte_offset = page_offset * N25Q128_PAGE_SIZE;
+
+ // prepare PROGRAM PAGE command
+ spi_tx[0] = N25Q128_COMMAND_PAGE_PROGRAM;
+ spi_tx[1] = (uint8_t)(byte_offset >> 16);
+ spi_tx[2] = (uint8_t)(byte_offset >> 8);
+ spi_tx[3] = (uint8_t)(byte_offset >> 0);
+
+ // activate, send command, send data, deselect
_n25q128_select(ctx);
- ok = HAL_SPI_TransmitReceive(ctx->hspi, spi_tx, spi_rx, 2, N25Q128_SPI_TIMEOUT);
- HAL_Delay(1);
+ int ok =
+ HAL_SPI_Transmit(ctx->hspi, spi_tx, 4, N25Q128_SPI_TIMEOUT) == HAL_OK &&
+ HAL_SPI_Transmit(ctx->hspi, (uint8_t *) page_buffer, N25Q128_PAGE_SIZE, N25Q128_SPI_TIMEOUT) == HAL_OK;
_n25q128_deselect(ctx);
// check
- if (ok != HAL_OK) return -1;
+ if (!ok) return HAL_ERROR;
- // done
- return (spi_rx[1] & 1);
+ // wait until write finishes
+ return _n25q128_wait_while_wip(ctx, 1000);
}
-int n25q128_erase_sector(struct spiflash_ctx *ctx, uint32_t sector_offset)
+static HAL_StatusTypeDef n25q128_erase_something(struct spiflash_ctx *ctx, uint8_t command, uint32_t byte_offset)
{
+ // check offset
+ if (byte_offset >= N25Q128_NUM_BYTES) return HAL_ERROR;
+
// tx buffer
uint8_t spi_tx[4];
- // result
- HAL_StatusTypeDef ok;
-
- // check offset
- if (sector_offset >= N25Q128_NUM_SECTORS) return 0;
-
// enable writing
- spi_tx[0] = N25Q128_COMMAND_WRITE_ENABLE;
+ if (_n25q128_write_enable(ctx) != 0) return HAL_ERROR;
- // select, send command, deselect
+ // send command (ERASE SECTOR or ERASE SUBSECTOR)
+ spi_tx[0] = command;
+ spi_tx[1] = (uint8_t)(byte_offset >> 16);
+ spi_tx[2] = (uint8_t)(byte_offset >> 8);
+ spi_tx[3] = (uint8_t)(byte_offset >> 0);
+
+ // activate, send command, deselect
_n25q128_select(ctx);
- ok = HAL_SPI_Transmit(ctx->hspi, spi_tx, 1, N25Q128_SPI_TIMEOUT);
- HAL_Delay(1);
+ int ok =
+ HAL_SPI_Transmit(ctx->hspi, spi_tx, 4, N25Q128_SPI_TIMEOUT) == HAL_OK;
_n25q128_deselect(ctx);
// check
- if (ok != HAL_OK) return 0;
+ if (!ok) return HAL_ERROR;
- // make sure, that write enable did the job
- int wel = _n25q128_get_wel_flag(ctx);
- if (wel != 1) return 0;
-
- // calculate byte address
- sector_offset *= N25Q128_SECTOR_SIZE;
+ // wait for erase to finish
+ return _n25q128_wait_while_wip(ctx, 1000);
+}
- // send ERASE SUBSECTOR command
- spi_tx[0] = N25Q128_COMMAND_ERASE_SECTOR;
- spi_tx[1] = (uint8_t)(sector_offset >> 16);
- spi_tx[2] = (uint8_t)(sector_offset >> 8);
- spi_tx[3] = (uint8_t)(sector_offset >> 0);
- // activate, send command, deselect
- _n25q128_select(ctx);
- ok = HAL_SPI_Transmit(ctx->hspi, spi_tx, 4, N25Q128_SPI_TIMEOUT);
- HAL_Delay(1);
- _n25q128_deselect(ctx);
+HAL_StatusTypeDef n25q128_erase_sector(struct spiflash_ctx *ctx, uint32_t sector_offset)
+{
+ return n25q128_erase_something(ctx, N25Q128_COMMAND_ERASE_SECTOR,
+ sector_offset * N25Q128_SECTOR_SIZE);
+}
- // check
- if (ok != HAL_OK) return 0;
- // done
- return 1;
+HAL_StatusTypeDef n25q128_erase_subsector(struct spiflash_ctx *ctx, uint32_t subsector_offset)
+{
+ return n25q128_erase_something(ctx, N25Q128_COMMAND_ERASE_SUBSECTOR,
+ subsector_offset * N25Q128_SUBSECTOR_SIZE);
}
-int _n25q128_get_wel_flag(struct spiflash_ctx *ctx)
+HAL_StatusTypeDef n25q128_erase_bulk(struct spiflash_ctx *ctx)
{
- // tx, rx buffers
- uint8_t spi_tx[2];
- uint8_t spi_rx[2];
+ // tx buffer
+ uint8_t spi_tx[1];
- // result
- HAL_StatusTypeDef ok;
+ // enable writing
+ if (_n25q128_write_enable(ctx) != 0) return HAL_ERROR;
- // send READ STATUS command
- spi_tx[0] = N25Q128_COMMAND_READ_STATUS;
+ // send command
+ spi_tx[0] = N25Q128_COMMAND_ERASE_BULK;
- // send command, read response, deselect
+ // activate, send command, deselect
_n25q128_select(ctx);
- ok = HAL_SPI_TransmitReceive(ctx->hspi, spi_tx, spi_rx, 2, N25Q128_SPI_TIMEOUT);
- HAL_Delay(1);
+ int ok =
+ HAL_SPI_Transmit(ctx->hspi, spi_tx, 1, N25Q128_SPI_TIMEOUT) == HAL_OK;
_n25q128_deselect(ctx);
// check
- if (ok != HAL_OK) return -1;
+ if (!ok) return HAL_ERROR;
- // done
- return ((spi_rx[1] >> 1) & 1);
+ // wait for erase to finish
+ return _n25q128_wait_while_wip(ctx, 60000);
}
-/* Wait until the flash memory is done writing (wip = Write In Progress) */
-inline int _wait_while_wip(struct spiflash_ctx *ctx, uint32_t timeout)
-{
- int i;
- while (timeout--) {
- i = n25q128_get_wip_flag(ctx);
- if (i < 0) return 0;
- if (! i) break;
- HAL_Delay(10);
- }
- return 1;
-}
-/* This function performs erasure if needed, and then writing of a number of pages to the flash memory */
-int n25q128_write_data(struct spiflash_ctx *ctx, uint32_t offset, const uint8_t *buf, const uint32_t len)
+/* This function writes of a number of pages to the flash memory.
+ * The caller is responsible for ensuring that the pages have been erased.
+ */
+HAL_StatusTypeDef n25q128_write_data(struct spiflash_ctx *ctx, uint32_t offset, const uint8_t *buf, const uint32_t len)
{
uint32_t page;
- /* Ensure alignment */
- if ((offset % N25Q128_PAGE_SIZE) != 0) return -1;
- if ((len % N25Q128_PAGE_SIZE) != 0) return -2;
-
- if ((offset % N25Q128_SECTOR_SIZE) == 0) {
- /* first page in sector, need to erase sector */
-
- if (! _wait_while_wip(ctx, 1000)) return -3;
-
- if (! n25q128_erase_sector(ctx, offset / N25Q128_SECTOR_SIZE)) {
- return -4;
- }
- }
+ /*
+ * The data sheet says:
+ * If the bits of the least significant address, which is the starting
+ * address, are not all zero, all data transmitted beyond the end of the
+ * current page is programmed from the starting address of the same page.
+ * If the number of bytes sent to the device exceed the maximum page size,
+ * previously latched data is discarded and only the last maximum
+ * page-size number of data bytes are guaranteed to be programmed
+ * correctly within the same page. If the number of bytes sent to the
+ * device is less than the maximum page size, they are correctly
+ * programmed at the specified addresses without any effect on the other
+ * bytes of the same page.
+ *
+ * This is sufficiently confusing that it makes sense to constrain the API
+ * to page alignment in address and length, because that's how we're using
+ * it anyway.
+ */
+
+ if (offset % N25Q128_PAGE_SIZE != 0 || len % N25Q128_PAGE_SIZE != 0) return HAL_ERROR;
for (page = 0; page < len / N25Q128_PAGE_SIZE; page++) {
- if (! _wait_while_wip(ctx, 1000)) return -5;
-
- if (! n25q128_write_page(ctx, offset / N25Q128_PAGE_SIZE, buf)) {
- return -6;
+ if (n25q128_write_page(ctx, offset / N25Q128_PAGE_SIZE, buf) != 0) {
+ return HAL_ERROR;
}
buf += N25Q128_PAGE_SIZE;
offset += N25Q128_PAGE_SIZE;
-
- /* XXX read back data and verify it, or maybe just verify ability to write
- * to memory by verifying the contents of one page after erase?
- */
}
- return 1;
+ return HAL_OK;
}
/* This function reads zero or more pages from the SPI flash. */
-int n25q128_read_data(struct spiflash_ctx *ctx, uint32_t offset, uint8_t *buf, const uint32_t len)
+HAL_StatusTypeDef n25q128_read_data(struct spiflash_ctx *ctx, uint32_t offset, uint8_t *buf, const uint32_t len)
{
- uint32_t page;
+ // tx buffer
+ uint8_t spi_tx[4];
- /* Ensure alignment */
- if ((offset % N25Q128_PAGE_SIZE) != 0) return -1;
- if ((len % N25Q128_PAGE_SIZE) != 0) return -2;
+ /*
+ * The data sheet says:
+ * The addressed byte can be at any location, and the address
+ * automatically increments to the next address after each byte of data is
+ * shifted out; therefore, the entire memory can be read with a single
+ * command. The operation is terminated by driving S# [chip select] HIGH
+ * at any time during data output.
+ *
+ * We're only going to call this with page-aligned address and length, but
+ * we're not going to enforce it here.
+ */
+
+ // avoid overflow
+ if (offset + len > N25Q128_NUM_BYTES) return HAL_ERROR;
- for (page = 0; page < len / N25Q128_PAGE_SIZE; page++) {
- if (! n25q128_read_page(ctx, offset / N25Q128_PAGE_SIZE, buf)) {
- return -3;
- }
- buf += N25Q128_PAGE_SIZE;
- offset += N25Q128_PAGE_SIZE;
- }
+ // prepare READ command
+ spi_tx[0] = N25Q128_COMMAND_READ;
+ spi_tx[1] = (uint8_t)(offset >> 16);
+ spi_tx[2] = (uint8_t)(offset >> 8);
+ spi_tx[3] = (uint8_t)(offset >> 0);
- return 1;
+ // activate, send command, read response, deselect
+ _n25q128_select(ctx);
+ int ok =
+ HAL_SPI_Transmit(ctx->hspi, spi_tx, 4, N25Q128_SPI_TIMEOUT) == HAL_OK &&
+ HAL_SPI_Receive(ctx->hspi, buf, len, N25Q128_SPI_TIMEOUT) == HAL_OK;
+ _n25q128_deselect(ctx);
+
+ // check
+ return ok ? HAL_OK : HAL_ERROR;
}
diff --git a/spiflash_n25q128.h b/spiflash_n25q128.h
index fefcb0d..926be56 100644
--- a/spiflash_n25q128.h
+++ b/spiflash_n25q128.h
@@ -6,7 +6,7 @@
* The Alpha board has two of these SPI flash memorys, the FPGA config memory
* and the keystore memory.
*
- * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ * Copyright (c) 2016-2017, NORDUnet A/S All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -40,11 +40,13 @@
#include "stm32f4xx_hal.h"
-#define N25Q128_COMMAND_READ_ID 0x9E
-#define N25Q128_COMMAND_READ_PAGE 0x03
+#define N25Q128_COMMAND_READ 0x03
#define N25Q128_COMMAND_READ_STATUS 0x05
+#define N25Q128_COMMAND_READ_ID 0x9E
#define N25Q128_COMMAND_WRITE_ENABLE 0x06
#define N25Q128_COMMAND_ERASE_SECTOR 0xD8
+#define N25Q128_COMMAND_ERASE_SUBSECTOR 0x20
+#define N25Q128_COMMAND_ERASE_BULK 0xC7
#define N25Q128_COMMAND_PAGE_PROGRAM 0x02
#define N25Q128_PAGE_SIZE 0x100 // 256
@@ -53,6 +55,9 @@
#define N25Q128_SECTOR_SIZE 0x10000 // 65536
#define N25Q128_NUM_SECTORS 0x100 // 256
+#define N25Q128_SUBSECTOR_SIZE 0x1000 // 4096
+#define N25Q128_NUM_SUBSECTORS 0x1000 // 4096
+
#define N25Q128_SPI_TIMEOUT 1000
#define N25Q128_ID_MANUFACTURER 0x20
@@ -65,12 +70,17 @@ struct spiflash_ctx {
uint16_t cs_n_pin;
};
-extern int n25q128_check_id(struct spiflash_ctx *ctx);
-extern int n25q128_get_wip_flag(struct spiflash_ctx *ctx);
-extern int n25q128_read_page(struct spiflash_ctx *ctx, uint32_t page_offset, uint8_t *page_buffer);
-extern int n25q128_write_page(struct spiflash_ctx *ctx, uint32_t page_offset, const uint8_t *page_buffer);
-extern int n25q128_erase_sector(struct spiflash_ctx *ctx, uint32_t sector_offset);
+extern HAL_StatusTypeDef n25q128_check_id(struct spiflash_ctx *ctx);
+extern HAL_StatusTypeDef n25q128_read_data(struct spiflash_ctx *ctx, uint32_t offset, uint8_t *buf, const uint32_t len);
+extern HAL_StatusTypeDef n25q128_write_page(struct spiflash_ctx *ctx, uint32_t page_offset, const uint8_t *page_buffer);
+extern HAL_StatusTypeDef n25q128_write_data(struct spiflash_ctx *ctx, uint32_t offset, const uint8_t *buf, const uint32_t len);
+extern HAL_StatusTypeDef n25q128_erase_subsector(struct spiflash_ctx *ctx, uint32_t subsector_offset);
+extern HAL_StatusTypeDef n25q128_erase_sector(struct spiflash_ctx *ctx, uint32_t sector_offset);
+extern HAL_StatusTypeDef n25q128_erase_bulk(struct spiflash_ctx *ctx);
+
+#define n25q128_read_page(ctx, page_offset, page_buffer) \
+ n25q128_read_data(ctx, page_offset * N25Q128_PAGE_SIZE, page_buffer, N25Q128_PAGE_SIZE)
+#define n25q128_read_subsector(ctx, subsector_offset, subsector_buffer) \
+ n25q128_read_data(ctx, subsector_offset * N25Q128_SUBSECTOR_SIZE, subsector_buffer, N25Q128_SUBSECTOR_SIZE)
-extern int n25q128_write_data(struct spiflash_ctx *ctx, uint32_t offset, const uint8_t *buf, const uint32_t len);
-extern int n25q128_read_data(struct spiflash_ctx *ctx, uint32_t offset, uint8_t *buf, const uint32_t len);
#endif /* __STM32_SPIFLASH_N25Q128_H */
diff --git a/stm-flash.c b/stm-flash.c
index 991379b..952543f 100644
--- a/stm-flash.c
+++ b/stm-flash.c
@@ -33,9 +33,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "stm32f4xx_hal.h"
-#include "stm-flash.h"
#include "stm-init.h"
+#include "stm-flash.h"
/* Flash sector offsets from RM0090, Table 6. Flash module - 2 Mbyte dual bank organization */
@@ -70,28 +69,30 @@ uint32_t flash_sector_offsets[FLASH_NUM_SECTORS + 1] = {
0x08200000 /* first address *after* flash */
};
-int stm_flash_sector_num(const uint32_t offset)
+static uint32_t stm_flash_sector_num(const uint32_t offset)
{
- int i = FLASH_NUM_SECTORS;
+ uint32_t i;
+
+ if (offset < flash_sector_offsets[0])
+ return 0xFFFFFFFF;
- while (i-- >= 0) {
- if (offset >= flash_sector_offsets[i] &&
- offset < flash_sector_offsets[i + 1]) {
+ for (i = 0; i < FLASH_NUM_SECTORS; ++i)
+ if (offset < flash_sector_offsets[i + 1])
return i;
- }
- }
- return -1;
+
+ return 0xFFFFFFFF;
}
-int stm_flash_erase_sectors(const uint32_t start_offset, const uint32_t end_offset)
+HAL_StatusTypeDef stm_flash_erase_sectors(const uint32_t start_offset, const uint32_t end_offset)
{
uint32_t start_sector = stm_flash_sector_num(start_offset);
uint32_t end_sector = stm_flash_sector_num(end_offset);
FLASH_EraseInitTypeDef FLASH_EraseInitStruct;
uint32_t SectorError = 0;
+ HAL_StatusTypeDef err;
- if (start_sector > end_sector) return -1;
- if (start_sector < 0 || end_sector > FLASH_NUM_SECTORS) return -2;
+ if (start_sector > end_sector || end_sector > FLASH_NUM_SECTORS)
+ return HAL_ERROR;
FLASH_EraseInitStruct.Sector = start_sector;
FLASH_EraseInitStruct.NbSectors = (end_sector - start_sector) + 1;
@@ -99,40 +100,38 @@ int stm_flash_erase_sectors(const uint32_t start_offset, const uint32_t end_offs
FLASH_EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3;
HAL_FLASH_Unlock();
-
- if (HAL_FLASHEx_Erase(&FLASH_EraseInitStruct, &SectorError) != HAL_OK) {
- return -3;
- }
-
+ err = HAL_FLASHEx_Erase(&FLASH_EraseInitStruct, &SectorError);
HAL_FLASH_Lock();
- if (SectorError == 0xFFFFFFFF) return 0;
+ if (err != HAL_OK || SectorError != 0xFFFFFFFF)
+ return HAL_ERROR;
- return -3;
+ return HAL_OK;
}
-int stm_flash_write32(uint32_t offset, const uint32_t *buf, const uint32_t elements)
+HAL_StatusTypeDef stm_flash_write32(uint32_t offset, const uint32_t *buf, const size_t elements)
{
uint32_t sector = stm_flash_sector_num(offset);
- uint32_t i, j;
+ size_t i;
+ HAL_StatusTypeDef err = HAL_OK;
if (offset == flash_sector_offsets[sector]) {
/* Request to write to beginning of a flash sector, erase it first. */
if (stm_flash_erase_sectors(offset, offset) != 0) {
- return -1;
+ return HAL_ERROR;
}
}
HAL_FLASH_Unlock();
for (i = 0; i < elements; i++) {
- if ((j = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, offset, buf[i])) != HAL_OK) {
- return -2;
+ if ((err = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, offset, buf[i])) != HAL_OK) {
+ break;
}
offset += 4;
}
HAL_FLASH_Lock();
- return 1;
+ return err;
}
diff --git a/stm-flash.h b/stm-flash.h
index a9cf7db..db7d327 100644
--- a/stm-flash.h
+++ b/stm-flash.h
@@ -1,7 +1,8 @@
/*
* stm-flash.h
* -----------
- * Functions and defines for accessing the flash memory.
+ * Functions for writing/erasing the STM32 internal flash memory.
+ * The flash is memory mapped, so no code is needed here to read it.
*
* Copyright (c) 2016, NORDUnet A/S All rights reserved.
*
@@ -35,8 +36,7 @@
#ifndef __STM32_FLASH_H
#define __STM32_FLASH_H
-extern int stm_flash_sector_num(const uint32_t offset);
-extern int stm_flash_erase_sectors(const uint32_t start_offset, const uint32_t end_offset);
-extern int stm_flash_write32(const uint32_t offset, const uint32_t *buf, const uint32_t elements);
+extern HAL_StatusTypeDef stm_flash_erase_sectors(const uint32_t start_offset, const uint32_t end_offset);
+extern HAL_StatusTypeDef stm_flash_write32(const uint32_t offset, const uint32_t *buf, const size_t elements);
#endif /* __STM32_FLASH_H */
diff --git a/stm-fmc.c b/stm-fmc.c
index 698f7af..18b6c8f 100644
--- a/stm-fmc.c
+++ b/stm-fmc.c
@@ -3,7 +3,9 @@
* ---------
* Functions to set up and use the FMC bus.
*
- * Copyright (c) 2015, NORDUnet A/S All rights reserved.
+ * Copyright 2015-2019 NORDUnet A/S
+ * Copyright 2021 The Commons Conservancy Cryptech Project
+ * SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -15,9 +17,9 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * - Neither the name of the NORDUnet nor the names of its contributors may
- * be used to endorse or promote products derived from this software
- * without specific prior written permission.
+ * - Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -31,113 +33,20 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "stm32f4xx_hal.h"
#include "stm-init.h"
#include "stm-fmc.h"
static SRAM_HandleTypeDef _fmc_fpga_inst;
-static HAL_StatusTypeDef _fmc_init_params(void);
-static int _fmc_nwait_idle(void);
-
-
-HAL_StatusTypeDef fmc_init(void)
+void fmc_init(void)
{
static int initialized = 0;
-
- if (initialized) {
- return HAL_OK;
- }
+ if (initialized) return;
initialized = 1;
// configure fmc pins
- fmc_init_gpio();
-
- // configure fmc registers
- return _fmc_init_params();
-}
-
-
-int fmc_write_32(uint32_t addr, uint32_t *data)
-{
- // calculate target fpga address
- uint32_t ptr = FMC_FPGA_BASE_ADDR + (addr & FMC_FPGA_ADDR_MASK);
-
- // write data to fpga
- HAL_StatusTypeDef ok = HAL_SRAM_Write_32b(&_fmc_fpga_inst, (uint32_t *)ptr, data, 1);
-
- // check for error
- if (ok != HAL_OK) return -1;
-
- // wait for transaction to complete
- int wait = _fmc_nwait_idle();
-
- // check for timeout
- if (wait != 0) return -1;
-
- // everything went ok
- return 0;
-}
-
-
-int fmc_read_32(uint32_t addr, uint32_t *data)
-{
- // calculate target fpga address
- uint32_t ptr = FMC_FPGA_BASE_ADDR + (addr & FMC_FPGA_ADDR_MASK);
-
- // perform dummy read transaction
- HAL_StatusTypeDef ok = HAL_SRAM_Read_32b(&_fmc_fpga_inst, (uint32_t *)ptr, data, 1);
-
- // check for error
- if (ok != HAL_OK) return -1;
-
- // wait for dummy transaction to complete
- int wait = _fmc_nwait_idle();
-
- // check for timeout
- if (wait != 0) return -1;
-
- // read data from fpga
- ok = HAL_SRAM_Read_32b(&_fmc_fpga_inst, (uint32_t *)ptr, data, 1);
- // check for error
- if (ok != HAL_OK) return -1;
-
- // wait for read transaction to complete
- wait = _fmc_nwait_idle();
-
- // check for timeout
- if (wait != 0) return -1;
-
- // everything went ok
- return 0;
-}
-
-
-static int _fmc_nwait_idle()
-{
- int cnt; // counter
-
- // poll NWAIT (number of iterations is limited)
- for (cnt=0; cnt<FMC_FPGA_NWAIT_MAX_POLL_TICKS; cnt++)
- {
- // read pin state
- GPIO_PinState nwait = HAL_GPIO_ReadPin(FMC_GPIO_PORT_NWAIT, FMC_GPIO_PIN_NWAIT);
-
- // stop waiting if fpga is ready
- if (nwait == FMC_NWAIT_IDLE) break;
- }
-
- // check for timeout
- if (cnt >= FMC_FPGA_NWAIT_MAX_POLL_TICKS) return -1;
-
- // ok
- return 0;
-}
-
-void fmc_init_gpio(void)
-{
GPIO_InitTypeDef GPIO_InitStruct;
// enable fmc clock
@@ -155,7 +64,7 @@ void fmc_init_gpio(void)
*/
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
- GPIO_InitStruct.Pull = GPIO_PULLUP;
+ GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
fmc_af_gpio(GPIOE, GPIO_PIN_2
@@ -171,11 +80,9 @@ void fmc_init_gpio(void)
| GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
fmc_af_gpio(GPIOI, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3
| GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_9 | GPIO_PIN_10);
-}
+ // configure fmc registers
-static HAL_StatusTypeDef _fmc_init_params(void)
-{
/*
* fill internal fields
*/
@@ -210,7 +117,7 @@ static HAL_StatusTypeDef _fmc_init_params(void)
_fmc_fpga_inst.Init.WrapMode = FMC_WRAP_MODE_DISABLE;
// don't care in fixed latency mode
- _fmc_fpga_inst.Init.WaitSignalActive = FMC_WAIT_TIMING_DURING_WS;
+ _fmc_fpga_inst.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;
// allow write access to fpga
_fmc_fpga_inst.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE;
@@ -244,18 +151,40 @@ static HAL_StatusTypeDef _fmc_init_params(void)
// don't care in sync mode
fmc_timing.DataSetupTime = 255;
- // not needed, since nwait will be polled manually
+ // not needed
fmc_timing.BusTurnAroundDuration = 0;
- // use smallest allowed divisor for best performance
- fmc_timing.CLKDivision = 2;
+ // use 45 MHz to match what FMC arbiter in the FPGA expects
+ fmc_timing.CLKDivision = 4; // 180/4
- // stm is too slow to work with min allowed 2-cycle latency
- fmc_timing.DataLatency = 3;
+ // use 6 to match what FMC arbiter in the FPGA expects
+ fmc_timing.DataLatency = 6;
// don't care in sync mode
fmc_timing.AccessMode = FMC_ACCESS_MODE_A;
// initialize fmc
- return HAL_SRAM_Init(&_fmc_fpga_inst, &fmc_timing, NULL);
+ HAL_SRAM_Init(&_fmc_fpga_inst, &fmc_timing, NULL);
+
+ // STM32 only enables FMC clock right before the very first read/write
+ // access. FPGA takes certain time (<= 100 us) to lock its PLL to this frequency,
+ // so a certain number of initial FMC transactions may be missed. One read transaction
+ // takes ~0.22 us (10 ticks @ 45 MHz), so doing ~500 dummy reads will make sure, that FPGA
+ // has already locked its PLL and is ready. Another way around is to repeatedly read
+ // some register that is guaranteed to have known value until reading starts returning
+ // correct data.
+
+ // to prevent compiler from optimizing this away, we pretent we're calculating sum
+ int cyc;
+ uint32_t sum = 0;
+ volatile uint32_t part;
+
+ for (cyc=0; cyc<500; cyc++)
+ {
+ part = *(__IO uint32_t *)FMC_FPGA_BASE_ADDR;
+ sum += part;
+ }
+
+ // dummy write to read-only address to not let the compiler remove the above loop
+ *(__IO uint32_t *)FMC_FPGA_BASE_ADDR = sum;
}
diff --git a/stm-fmc.h b/stm-fmc.h
index 8c37bd7..e9b5749 100644
--- a/stm-fmc.h
+++ b/stm-fmc.h
@@ -4,6 +4,8 @@
* Functions to set up and use the FMC bus.
*
* Copyright (c) 2015, NORDUnet A/S All rights reserved.
+ * Copyright: 2020, The Commons Conservancy Cryptech Project
+ * SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -15,9 +17,9 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * - Neither the name of the NORDUnet nor the names of its contributors may
- * be used to endorse or promote products derived from this software
- * without specific prior written permission.
+ * - Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -39,12 +41,6 @@
#define FMC_FPGA_BASE_ADDR 0x60000000
#define FMC_FPGA_ADDR_MASK 0x03FFFFFC // there are 26 physical lines, but "only" 24 usable for now
-#define FMC_FPGA_NWAIT_MAX_POLL_TICKS 10
-
-#define FMC_GPIO_PORT_NWAIT GPIOD
-#define FMC_GPIO_PIN_NWAIT GPIO_PIN_6
-
-#define FMC_NWAIT_IDLE GPIO_PIN_SET
#define fmc_af_gpio(port, pins) \
GPIO_InitStruct.Pin = pins; \
@@ -56,10 +52,21 @@
HAL_GPIO_Init(port, &GPIO_InitStruct)
-extern HAL_StatusTypeDef fmc_init(void);
-extern void fmc_init_gpio(void);
+extern void fmc_init(void);
+
+static inline void *fmc_fpga_addr(off_t addr)
+{
+ return (void *)(FMC_FPGA_BASE_ADDR + (addr & FMC_FPGA_ADDR_MASK));
+}
+
+static inline void fmc_write_32(uint32_t addr, uint32_t data)
+{
+ *(uint32_t *)fmc_fpga_addr(addr) = data;
+}
-extern int fmc_write_32(uint32_t addr, uint32_t *data);
-extern int fmc_read_32(uint32_t addr, uint32_t *data);
+static inline void fmc_read_32(uint32_t addr, uint32_t *data)
+{
+ *data = *(uint32_t *)fmc_fpga_addr(addr);
+}
#endif /* __STM_FMC_H */
diff --git a/stm-fpgacfg.c b/stm-fpgacfg.c
index 6f6114d..54342bf 100644
--- a/stm-fpgacfg.c
+++ b/stm-fpgacfg.c
@@ -4,7 +4,7 @@
* Functions for accessing the FPGA config memory and controlling
* the low-level status of the FPGA (reset registers/reboot etc.).
*
- * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ * Copyright (c) 2016-2017, NORDUnet A/S All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -33,20 +33,47 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "stm32f4xx_hal.h"
#include "stm-fpgacfg.h"
#include "stm-init.h"
-SPI_HandleTypeDef hspi_fpgacfg;
+static SPI_HandleTypeDef hspi_fpgacfg;
-struct spiflash_ctx fpgacfg_ctx = {&hspi_fpgacfg, PROM_CS_N_GPIO_Port, PROM_CS_N_Pin};
+static struct spiflash_ctx fpgacfg_ctx = {&hspi_fpgacfg, PROM_CS_N_GPIO_Port, PROM_CS_N_Pin};
-int fpgacfg_check_id()
+void fpgacfg_init(void)
+{
+ /* Give the FPGA access to it's bitstream ASAP (maybe this should actually
+ * be done in the application, before calling stm_init()).
+ */
+ fpgacfg_access_control(ALLOW_FPGA);
+
+ /* Set up GPIOs to manage access to the FPGA config memory.
+ * FPGACFG_GPIO_INIT is defined in stm-fpgacfg.h.
+ */
+ FPGACFG_GPIO_INIT();
+
+ /* SPI2 (FPGA config memory) init function */
+ hspi_fpgacfg.Instance = SPI2;
+ hspi_fpgacfg.Init.Mode = SPI_MODE_MASTER;
+ hspi_fpgacfg.Init.Direction = SPI_DIRECTION_2LINES;
+ hspi_fpgacfg.Init.DataSize = SPI_DATASIZE_8BIT;
+ hspi_fpgacfg.Init.CLKPolarity = SPI_POLARITY_LOW;
+ hspi_fpgacfg.Init.CLKPhase = SPI_PHASE_1EDGE;
+ hspi_fpgacfg.Init.NSS = SPI_NSS_SOFT;
+ hspi_fpgacfg.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
+ hspi_fpgacfg.Init.FirstBit = SPI_FIRSTBIT_MSB;
+ hspi_fpgacfg.Init.TIMode = SPI_TIMODE_DISABLE;
+ hspi_fpgacfg.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
+ hspi_fpgacfg.Init.CRCPolynomial = 10;
+ HAL_SPI_Init(&hspi_fpgacfg);
+}
+
+HAL_StatusTypeDef fpgacfg_check_id(void)
{
return n25q128_check_id(&fpgacfg_ctx);
}
-int fpgacfg_write_data(uint32_t offset, const uint8_t *buf, const uint32_t len)
+HAL_StatusTypeDef fpgacfg_write_data(uint32_t offset, const uint8_t *buf, const uint32_t len)
{
return n25q128_write_data(&fpgacfg_ctx, offset, buf, len);
}
@@ -86,29 +113,12 @@ void fpgacfg_reset_fpga(enum fpgacfg_reset reset)
}
}
-int fpgacfg_check_done(void)
+HAL_StatusTypeDef fpgacfg_check_done(void)
{
- GPIO_PinState status = HAL_GPIO_ReadPin(FPGA_DONE_Port, FPGA_DONE_Pin);
- return (status == GPIO_PIN_SET);
+ return (HAL_GPIO_ReadPin(FPGA_DONE_Port, FPGA_DONE_Pin) == GPIO_PIN_SET) ? HAL_OK : HAL_ERROR;
}
-int fpgacfg_erase_sectors(int num)
+HAL_StatusTypeDef fpgacfg_erase_sector(uint32_t sector_offset)
{
- if (num > N25Q128_NUM_SECTORS || num < 0) num = N25Q128_NUM_SECTORS;
- while (num) {
- int timeout = 200; /* times 10ms = 2 seconds timeout */
- while (timeout--) {
- int i = n25q128_get_wip_flag(&fpgacfg_ctx);
- if (i < 0) return 0;
- if (! i) break;
- HAL_Delay(10);
- }
- if (! timeout) return 0;
-
- if (! n25q128_erase_sector(&fpgacfg_ctx, num - 1)) {
- return -1;
- }
- num--;
- }
- return 1;
+ return n25q128_erase_sector(&fpgacfg_ctx, sector_offset);
}
diff --git a/stm-fpgacfg.h b/stm-fpgacfg.h
index 0d5eeb9..74cc683 100644
--- a/stm-fpgacfg.h
+++ b/stm-fpgacfg.h
@@ -4,7 +4,7 @@
* Functions and defines for accessing the FPGA config memory and controlling
* the low-level status of the FPGA (reset registers/reboot etc.).
*
- * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ * Copyright (c) 2016-2017, NORDUnet A/S All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -39,6 +39,8 @@
#include "stm32f4xx_hal.h"
#include "spiflash_n25q128.h"
+#define FPGACFG_SECTOR_SIZE N25Q128_SECTOR_SIZE
+
/* Pins connected to the FPGA config memory (SPI flash) */
#define PROM_FPGA_DIS_Pin GPIO_PIN_14
#define PROM_FPGA_DIS_GPIO_Port GPIOI
@@ -83,15 +85,14 @@ enum fpgacfg_reset {
RESET_REGISTERS,
};
-extern SPI_HandleTypeDef hspi_fpgacfg;
-
-extern int fpgacfg_check_id(void);
-extern int fpgacfg_write_data(uint32_t offset, const uint8_t *buf, const uint32_t len);
-extern int fpgacfg_erase_sectors(int num);
+extern void fpgacfg_init(void);
+extern HAL_StatusTypeDef fpgacfg_check_id(void);
+extern HAL_StatusTypeDef fpgacfg_write_data(uint32_t offset, const uint8_t *buf, const uint32_t len);
+extern HAL_StatusTypeDef fpgacfg_erase_sector(uint32_t sector_offset);
extern void fpgacfg_access_control(enum fpgacfg_access_ctrl access);
/* Reset the FPGA */
extern void fpgacfg_reset_fpga(enum fpgacfg_reset reset);
/* Check status of FPGA bitstream loading */
-extern int fpgacfg_check_done(void);
+extern HAL_StatusTypeDef fpgacfg_check_done(void);
#endif /* __STM32_FPGACFG_H */
diff --git a/stm-init.c b/stm-init.c
index d2d8d65..c06554b 100644
--- a/stm-init.c
+++ b/stm-init.c
@@ -33,7 +33,6 @@
*/
/* Includes ------------------------------------------------------------------*/
-#include "stm32f4xx_hal.h"
#include "stm-init.h"
#ifdef HAL_GPIO_MODULE_ENABLED
#include "stm-led.h"
@@ -48,6 +47,12 @@
#include "stm-fpgacfg.h"
#include "stm-keystore.h"
#endif
+#ifdef HAL_SRAM_MODULE_ENABLED
+#include "stm-fmc.h"
+#endif
+#ifdef HAL_SDRAM_MODULE_ENABLED
+#include "stm-sdram.h"
+#endif
/* Private variables ---------------------------------------------------------*/
@@ -55,20 +60,6 @@
#ifdef HAL_GPIO_MODULE_ENABLED
static void MX_GPIO_Init(void);
#endif
-#ifdef HAL_UART_MODULE_ENABLED
-static void MX_USART1_UART_Init(void);
-static void MX_USART2_UART_Init(void);
-#endif
-#ifdef HAL_DMA_MODULE_ENABLED
-static void MX_DMA_Init(void);
-#endif
-#ifdef HAL_I2C_MODULE_ENABLED
-static void MX_I2C2_Init(void);
-#endif
-#ifdef HAL_SPI_MODULE_ENABLED
-static void MX_SPI1_Init(void);
-static void MX_SPI2_Init(void);
-#endif
void stm_init(void)
{
@@ -78,187 +69,52 @@ void stm_init(void)
/* System interrupt init*/
/* Sets the priority grouping field */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0);
- HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
/* Initialize all configured peripherals */
#ifdef HAL_GPIO_MODULE_ENABLED
MX_GPIO_Init();
- #ifdef HAL_SPI_MODULE_ENABLED
- /* Give the FPGA access to it's bitstream ASAP (maybe this should actually
- * be done in the application, before calling stm_init()).
- */
- fpgacfg_access_control(ALLOW_FPGA);
- #endif
-#endif
-#ifdef HAL_DMA_MODULE_ENABLED
- MX_DMA_Init();
#endif
#ifdef HAL_UART_MODULE_ENABLED
- MX_USART1_UART_Init();
- MX_USART2_UART_Init();
+ uart_init();
#endif
#ifdef HAL_I2C_MODULE_ENABLED
- MX_I2C2_Init();
+ rtc_init();
#endif
#ifdef HAL_SPI_MODULE_ENABLED
- MX_SPI1_Init();
- MX_SPI2_Init();
+ fpgacfg_init();
+ keystore_init();
+#endif
+#ifdef TARGET_CRYPTECH_DEV_BRIDGE
+ // Blink blue LED for six seconds to not upset the Novena at boot.
+ led_on(LED_BLUE);
+ for (int i = 0; i < 12; i++) {
+ HAL_Delay(500);
+ led_toggle(LED_BLUE);
+ }
+ led_off(LED_BLUE);
#endif
-}
-
-
-#ifdef HAL_UART_MODULE_ENABLED
-/* USART1 init function */
-static void MX_USART1_UART_Init(void)
-{
- huart_mgmt.Instance = USART1;
- huart_mgmt.Init.BaudRate = USART_MGMT_BAUD_RATE;
- huart_mgmt.Init.WordLength = UART_WORDLENGTH_8B;
- huart_mgmt.Init.StopBits = UART_STOPBITS_1;
- huart_mgmt.Init.Parity = UART_PARITY_NONE;
- huart_mgmt.Init.Mode = UART_MODE_TX_RX;
- huart_mgmt.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS;
- huart_mgmt.Init.OverSampling = UART_OVERSAMPLING_16;
-
-#ifdef HAL_DMA_MODULE_ENABLED
- __HAL_LINKDMA(&huart_mgmt, hdmarx, hdma_usart_mgmt_rx);
+#ifdef HAL_SRAM_MODULE_ENABLED
+ fmc_init();
#endif
-
- if (HAL_UART_Init(&huart_mgmt) != HAL_OK) {
- /* Initialization Error */
- Error_Handler();
- }
-}
-/* USART2 init function */
-static void MX_USART2_UART_Init(void)
-{
- huart_user.Instance = USART2;
- huart_user.Init.BaudRate = USART_USER_BAUD_RATE;
- huart_user.Init.WordLength = UART_WORDLENGTH_8B;
- huart_user.Init.StopBits = UART_STOPBITS_1;
- huart_user.Init.Parity = UART_PARITY_NONE;
- huart_user.Init.Mode = UART_MODE_TX_RX;
- huart_user.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS;
- huart_user.Init.OverSampling = UART_OVERSAMPLING_16;
-
-#ifdef HAL_DMA_MODULE_ENABLED
- __HAL_LINKDMA(&huart_user, hdmarx, hdma_usart_user_rx);
+#ifdef HAL_SDRAM_MODULE_ENABLED
+ sdram_init();
#endif
-
- if (HAL_UART_Init(&huart_user) != HAL_OK) {
- /* Initialization Error */
- Error_Handler();
- }
}
-#endif
+
#ifdef HAL_GPIO_MODULE_ENABLED
/* Configure General Purpose Input/Output pins */
static void MX_GPIO_Init(void)
{
- GPIO_InitTypeDef GPIO_InitStruct;
-
/* GPIO Ports Clock Enable */
LED_CLK_ENABLE();
/* Configure LED GPIO pins */
gpio_output(LED_PORT, LED_RED | LED_YELLOW | LED_GREEN | LED_BLUE, GPIO_PIN_RESET);
-
-#ifdef HAL_SPI_MODULE_ENABLED
- /* Set up GPIOs to manage access to the FPGA config memory.
- * FPGACFG_GPIO_INIT is defined in stm-fpgacfg.h.
- */
- FPGACFG_GPIO_INIT();
- /* Set up GPIOs for the keystore memory.
- * KEYSTORE_GPIO_INIT is defined in stm-keystore.h.
- */
- KEYSTORE_GPIO_INIT();
-#endif /* HAL_SPI_MODULE_ENABLED */
}
-#undef gpio_output
#endif
-
-#ifdef HAL_DMA_MODULE_ENABLED
-/**
- * Enable DMA controller clock
- */
-static void MX_DMA_Init(void)
-{
- /* DMA controller clock enable */
- __HAL_RCC_DMA2_CLK_ENABLE();
- __HAL_RCC_DMA1_CLK_ENABLE();
-
- /* DMA interrupt init */
-
- /* USER UART RX */
- HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 0, 0);
- HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn);
- /* MGMT UART RX */
- HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0);
- HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
-}
-#endif /* HAL_DMA_MODULE_ENABLED */
-
-
-#ifdef HAL_I2C_MODULE_ENABLED
-/* I2C2 init function (external RTC chip) */
-void MX_I2C2_Init(void)
-{
- hi2c_rtc.Instance = I2C2;
- hi2c_rtc.Init.ClockSpeed = 10000;
- hi2c_rtc.Init.DutyCycle = I2C_DUTYCYCLE_2;
- hi2c_rtc.Init.OwnAddress1 = 0; /* Will operate as Master */
- hi2c_rtc.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
- hi2c_rtc.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
- hi2c_rtc.Init.OwnAddress2 = 0;
- hi2c_rtc.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
- hi2c_rtc.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;
-
- if (HAL_I2C_Init(&hi2c_rtc) != HAL_OK) {
- Error_Handler();
- }
-}
-#endif
-
-#ifdef HAL_SPI_MODULE_ENABLED
-/* SPI1 (keystore memory) init function */
-void MX_SPI1_Init(void)
-{
- hspi_keystore.Instance = SPI1;
- hspi_keystore.Init.Mode = SPI_MODE_MASTER;
- hspi_keystore.Init.Direction = SPI_DIRECTION_2LINES;
- hspi_keystore.Init.DataSize = SPI_DATASIZE_8BIT;
- hspi_keystore.Init.CLKPolarity = SPI_POLARITY_LOW;
- hspi_keystore.Init.CLKPhase = SPI_PHASE_1EDGE;
- hspi_keystore.Init.NSS = SPI_NSS_SOFT;
- hspi_keystore.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
- hspi_keystore.Init.FirstBit = SPI_FIRSTBIT_MSB;
- hspi_keystore.Init.TIMode = SPI_TIMODE_DISABLE;
- hspi_keystore.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
- hspi_keystore.Init.CRCPolynomial = 10;
- HAL_SPI_Init(&hspi_keystore);
-}
-/* SPI2 (FPGA config memory) init function */
-void MX_SPI2_Init(void)
-{
- hspi_fpgacfg.Instance = SPI2;
- hspi_fpgacfg.Init.Mode = SPI_MODE_MASTER;
- hspi_fpgacfg.Init.Direction = SPI_DIRECTION_2LINES;
- hspi_fpgacfg.Init.DataSize = SPI_DATASIZE_8BIT;
- hspi_fpgacfg.Init.CLKPolarity = SPI_POLARITY_LOW;
- hspi_fpgacfg.Init.CLKPhase = SPI_PHASE_1EDGE;
- hspi_fpgacfg.Init.NSS = SPI_NSS_SOFT;
- hspi_fpgacfg.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
- hspi_fpgacfg.Init.FirstBit = SPI_FIRSTBIT_MSB;
- hspi_fpgacfg.Init.TIMode = SPI_TIMODE_DISABLE;
- hspi_fpgacfg.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
- hspi_fpgacfg.Init.CRCPolynomial = 10;
- HAL_SPI_Init(&hspi_fpgacfg);
-}
-#endif /* HAL_SPI_MODULE_ENABLED */
-
/**
* @brief This function is executed in case of error occurrence.
* @param None
@@ -269,29 +125,10 @@ void Error_Handler(void)
#ifdef HAL_GPIO_MODULE_ENABLED
HAL_GPIO_WritePin(LED_PORT, LED_RED, GPIO_PIN_SET);
#endif
- while (1) { ; }
-}
-
-#ifdef USE_FULL_ASSERT
-
-/**
- * @brief Reports the name of the source file and the source line number
- * where the assert_param error has occurred.
- * @param file: pointer to the source file name
- * @param line: assert_param error line source number
- * @retval None
- */
-void assert_failed(uint8_t* file, uint32_t line)
-{
- /* USER CODE BEGIN 6 */
- /* User can add his own implementation to report the file name and line number,
- ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
- /* USER CODE END 6 */
+ while (1) { ; }
}
-#endif
-
/**
* @}
*/
diff --git a/stm-init.h b/stm-init.h
index dd19311..ff1c4c2 100644
--- a/stm-init.h
+++ b/stm-init.h
@@ -35,31 +35,37 @@
#ifndef __STM_INIT_H
#define __STM_INIT_H
-#include "cmsis_os.h"
#include "stm32f4xx_hal.h"
-/* Macros used to make GPIO pin setup (in stm-init.c) easier */
-#define gpio_output(output_port, output_pins, output_level) \
- /* Configure GPIO pin Output Level */ \
- HAL_GPIO_WritePin(output_port, output_pins, output_level); \
- /* Configure pin as output */ \
- GPIO_InitStruct.Pin = output_pins; \
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; \
- GPIO_InitStruct.Pull = GPIO_NOPULL; \
- GPIO_InitStruct.Speed = GPIO_SPEED_LOW; \
- HAL_GPIO_Init(output_port, &GPIO_InitStruct)
+/* Functions used to make GPIO pin setup (in stm-init.c) easier */
-#define gpio_input(input_port, input_pin, input_pull) \
- GPIO_InitStruct.Pin = input_pin; \
- GPIO_InitStruct.Mode = GPIO_MODE_INPUT; \
- GPIO_InitStruct.Pull = input_pull; \
- GPIO_InitStruct.Speed = GPIO_SPEED_LOW; \
- HAL_GPIO_Init(input_port, &GPIO_InitStruct)
+static inline void gpio_output(GPIO_TypeDef* output_port, uint16_t output_pins, GPIO_PinState output_level)
+{
+ GPIO_InitTypeDef GPIO_InitStruct;
+ /* Configure GPIO pin Output Level */
+ HAL_GPIO_WritePin(output_port, output_pins, output_level);
+
+ /* Configure pin as output */
+ GPIO_InitStruct.Pin = output_pins;
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
+ HAL_GPIO_Init(output_port, &GPIO_InitStruct);
+}
+
+static inline void gpio_input(GPIO_TypeDef* input_port, uint16_t input_pin, GPIO_PinState input_pull)
+{
+ GPIO_InitTypeDef GPIO_InitStruct;
+
+ GPIO_InitStruct.Pin = input_pin;
+ GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+ GPIO_InitStruct.Pull = input_pull;
+ GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
+ HAL_GPIO_Init(input_port, &GPIO_InitStruct);
+}
extern void stm_init(void);
extern void Error_Handler(void);
-#define HAL_Delay osDelay
-
#endif /* __STM_INIT_H */
diff --git a/stm-keystore.c b/stm-keystore.c
index 74826d0..7683f40 100644
--- a/stm-keystore.c
+++ b/stm-keystore.c
@@ -3,7 +3,7 @@
* ----------
* Functions for accessing the keystore memory.
*
- * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ * Copyright (c) 2016-2017, NORDUnet A/S All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -32,46 +32,62 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "stm32f4xx_hal.h"
-#include "stm-keystore.h"
#include "stm-init.h"
+#include "stm-keystore.h"
-SPI_HandleTypeDef hspi_keystore;
+static SPI_HandleTypeDef hspi_keystore;
struct spiflash_ctx keystore_ctx = {&hspi_keystore, KSM_PROM_CS_N_GPIO_Port, KSM_PROM_CS_N_Pin};
-int keystore_check_id()
+/* SPI1 (keystore memory) init function */
+void keystore_init(void)
+{
+ /* Set up GPIOs for the keystore memory.
+ * KEYSTORE_GPIO_INIT is defined in stm-keystore.h.
+ */
+ KEYSTORE_GPIO_INIT();
+
+ hspi_keystore.Instance = SPI1;
+ hspi_keystore.Init.Mode = SPI_MODE_MASTER;
+ hspi_keystore.Init.Direction = SPI_DIRECTION_2LINES;
+ hspi_keystore.Init.DataSize = SPI_DATASIZE_8BIT;
+ hspi_keystore.Init.CLKPolarity = SPI_POLARITY_LOW;
+ hspi_keystore.Init.CLKPhase = SPI_PHASE_1EDGE;
+ hspi_keystore.Init.NSS = SPI_NSS_SOFT;
+ hspi_keystore.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
+ hspi_keystore.Init.FirstBit = SPI_FIRSTBIT_MSB;
+ hspi_keystore.Init.TIMode = SPI_TIMODE_DISABLE;
+ hspi_keystore.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
+ hspi_keystore.Init.CRCPolynomial = 10;
+ HAL_SPI_Init(&hspi_keystore);
+}
+
+HAL_StatusTypeDef keystore_check_id(void)
{
return n25q128_check_id(&keystore_ctx);
}
-int keystore_read_data(uint32_t offset, uint8_t *buf, const uint32_t len)
+HAL_StatusTypeDef keystore_read_data(uint32_t offset, uint8_t *buf, const uint32_t len)
{
return n25q128_read_data(&keystore_ctx, offset, buf, len);
}
-int keystore_write_data(uint32_t offset, const uint8_t *buf, const uint32_t len)
+HAL_StatusTypeDef keystore_write_data(uint32_t offset, const uint8_t *buf, const uint32_t len)
{
return n25q128_write_data(&keystore_ctx, offset, buf, len);
}
-int keystore_erase_sectors(int num)
+HAL_StatusTypeDef keystore_erase_subsector(uint32_t subsector_offset)
{
- if (num > N25Q128_NUM_SECTORS || num < 0) num = N25Q128_NUM_SECTORS;
- while (num) {
- int timeout = 200; /* times 10ms = 2 seconds timeout */
- while (timeout--) {
- int i = n25q128_get_wip_flag(&keystore_ctx);
- if (i < 0) return 0;
- if (! i) break;
- HAL_Delay(10);
- }
- if (! timeout) return 0;
+ return n25q128_erase_subsector(&keystore_ctx, subsector_offset);
+}
- if (! n25q128_erase_sector(&keystore_ctx, num - 1)) {
- return -1;
- }
- num--;
- }
- return 1;
+HAL_StatusTypeDef keystore_erase_sector(uint32_t sector_offset)
+{
+ return n25q128_erase_sector(&keystore_ctx, sector_offset);
+}
+
+HAL_StatusTypeDef keystore_erase_bulk(void)
+{
+ return n25q128_erase_bulk(&keystore_ctx);
}
diff --git a/stm-keystore.h b/stm-keystore.h
index 2c493d2..9aa740c 100644
--- a/stm-keystore.h
+++ b/stm-keystore.h
@@ -3,7 +3,7 @@
* ---------
* Functions and defines for accessing the keystore memory.
*
- * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ * Copyright (c) 2016-2017, NORDUnet A/S All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -39,7 +39,11 @@
#include "spiflash_n25q128.h"
#define KEYSTORE_PAGE_SIZE N25Q128_PAGE_SIZE
+#define KEYSTORE_NUM_PAGES N25Q128_NUM_PAGES
#define KEYSTORE_SECTOR_SIZE N25Q128_SECTOR_SIZE
+#define KEYSTORE_NUM_SECTORS N25Q128_NUM_SECTORS
+#define KEYSTORE_SUBSECTOR_SIZE N25Q128_SUBSECTOR_SIZE
+#define KEYSTORE_NUM_SUBSECTORS N25Q128_NUM_SUBSECTORS
/* Pins connected to the FPGA config memory (SPI flash) */
#define KSM_PROM_CS_N_Pin GPIO_PIN_0
@@ -51,11 +55,12 @@
gpio_output(KSM_PROM_CS_N_GPIO_Port, KSM_PROM_CS_N_Pin, GPIO_PIN_SET)
-extern SPI_HandleTypeDef hspi_keystore;
-
-extern int keystore_check_id(void);
-extern int keystore_read_data(uint32_t offset, uint8_t *buf, const uint32_t len);
-extern int keystore_write_data(uint32_t offset, const uint8_t *buf, const uint32_t len);
-extern int keystore_erase_sectors(int num);
+extern void keystore_init(void);
+extern HAL_StatusTypeDef keystore_check_id(void);
+extern HAL_StatusTypeDef keystore_read_data(uint32_t offset, uint8_t *buf, const uint32_t len);
+extern HAL_StatusTypeDef keystore_write_data(uint32_t offset, const uint8_t *buf, const uint32_t len);
+extern HAL_StatusTypeDef keystore_erase_subsector(uint32_t subsector_offset);
+extern HAL_StatusTypeDef keystore_erase_sector(uint32_t sector_offset);
+extern HAL_StatusTypeDef keystore_erase_bulk(void);
#endif /* __STM32_KEYSTORE_H */
diff --git a/stm-rtc.c b/stm-rtc.c
index 66e41e8..1204728 100644
--- a/stm-rtc.c
+++ b/stm-rtc.c
@@ -32,17 +32,35 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "stm32f4xx_hal.h"
+#include "stm-init.h"
#include "stm-rtc.h"
I2C_HandleTypeDef hi2c_rtc;
+/* I2C2 init function (external RTC chip) */
+void rtc_init(void)
+{
+ hi2c_rtc.Instance = I2C2;
+ hi2c_rtc.Init.ClockSpeed = 10000;
+ hi2c_rtc.Init.DutyCycle = I2C_DUTYCYCLE_2;
+ hi2c_rtc.Init.OwnAddress1 = 0; /* Will operate as Master */
+ hi2c_rtc.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
+ hi2c_rtc.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
+ hi2c_rtc.Init.OwnAddress2 = 0;
+ hi2c_rtc.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
+ hi2c_rtc.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;
+
+ if (HAL_I2C_Init(&hi2c_rtc) != HAL_OK) {
+ Error_Handler();
+ }
+}
+
HAL_StatusTypeDef rtc_device_ready(uint16_t i2c_addr)
{
return HAL_I2C_IsDeviceReady (&hi2c_rtc, i2c_addr, 10, 1000);
}
-HAL_StatusTypeDef rtc_enable_oscillator()
+HAL_StatusTypeDef rtc_enable_oscillator(void)
{
uint8_t buf[2];
HAL_StatusTypeDef res;
@@ -78,7 +96,7 @@ HAL_StatusTypeDef rtc_read_bytes (const uint16_t i2c_addr, uint8_t *buf, const u
{
HAL_StatusTypeDef res;
- while (HAL_I2C_Master_Receive (&hi2c_rtc, i2c_addr, buf, len, 1000) != HAL_OK) {
+ while (HAL_I2C_Master_Receive (&hi2c_rtc, i2c_addr, buf, len, timeout) != HAL_OK) {
res = HAL_I2C_GetError (&hi2c_rtc);
if (res != HAL_I2C_ERROR_AF) {
return res;
diff --git a/stm-rtc.h b/stm-rtc.h
index edbed9d..794ef2d 100644
--- a/stm-rtc.h
+++ b/stm-rtc.h
@@ -37,8 +37,7 @@
#include "stm32f4xx_hal.h"
-extern I2C_HandleTypeDef hi2c_rtc;
-
+extern void rtc_init(void);
extern HAL_StatusTypeDef rtc_device_ready(uint16_t i2c_addr);
extern HAL_StatusTypeDef rtc_enable_oscillator();
extern HAL_StatusTypeDef rtc_send_byte(const uint16_t i2c_addr, const uint8_t value, const uint16_t timeout);
diff --git a/stm-sdram.c b/stm-sdram.c
index 0ec8065..3ad17f0 100644
--- a/stm-sdram.c
+++ b/stm-sdram.c
@@ -1,267 +1,216 @@
-/*
- * stm-sdram.c
- * -----------
- * Functions concerning the 2x512 Mbit SDRAM working memory.
- *
- * Copyright (c) 2016, NORDUnet A/S All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - 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.
- *
- * - Neither the name of the NORDUnet nor the names of its contributors may
- * be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
- * HOLDER 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 "stm32f4xx_hal.h"
-#include "stm-init.h"
-#include "stm-sdram.h"
-#include "stm-fmc.h"
-#include "stm-led.h"
-
-SDRAM_HandleTypeDef hsdram1;
-SDRAM_HandleTypeDef hsdram2;
-
-void _sdram_init_gpio(void);
-HAL_StatusTypeDef _sdram_init_fmc(void);
-HAL_StatusTypeDef _sdram_init_params(SDRAM_HandleTypeDef *sdram1, SDRAM_HandleTypeDef *sdram2);
-
-
-HAL_StatusTypeDef sdram_init(void)
-{
- HAL_StatusTypeDef status;
- static int initialized = 0;
-
- if (initialized) {
- return;
- }
- initialized = 1;
-
- /* We rely on several things being set up by fmc_init() instead of duplicating all
- * that code here for independent FPGA/SDRAM FMC setup. This means the FPGA<->STM32
- * FMC bus can be used without the SDRAMs initialized, but the SDRAMs can't be
- * initialized withouth the FPGA<->STM32 FMC bus being set up too.
- */
- fmc_init();
-
- // configure FMC
- _sdram_init_gpio();
- status = _sdram_init_fmc();
- if (status != HAL_OK) return status;
-
- // configure SDRAM registers
- status = _sdram_init_params(&hsdram1, &hsdram2);
- if (status != HAL_OK) return status;
-
- return HAL_OK;
-}
-
-void _sdram_init_gpio(void)
-{
- GPIO_InitTypeDef GPIO_InitStruct;
-
- /* The bulk of the FMC GPIO pins are set up in fmc_init_gpio().
- * This function just needs to enable the additional ones used
- * with the SDRAMs.
- */
- fmc_af_gpio(GPIOB, GPIO_PIN_5 | GPIO_PIN_6);
- fmc_af_gpio(GPIOC, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3);
- fmc_af_gpio(GPIOE, GPIO_PIN_0 | GPIO_PIN_1);
- fmc_af_gpio(GPIOF, GPIO_PIN_11);
- fmc_af_gpio(GPIOG, GPIO_PIN_8 | GPIO_PIN_15);
- fmc_af_gpio(GPIOI, GPIO_PIN_4 | GPIO_PIN_5);
-}
-
-HAL_StatusTypeDef _sdram_init_fmc()
-{
- HAL_StatusTypeDef status;
- FMC_SDRAM_TimingTypeDef SdramTiming;
-
- /*
- * following settings are for -75E speed grade memory chip
- * clocked at only 90 MHz instead of the rated 133 MHz
- *
- * ExitSelfRefreshDelay: 67 ns @ 90 MHz is 6.03 cycles, so in theory
- * 6 can be used here, but let's be on the safe side
- *
- * WriteRecoveryTime: must be >= tRAS - tRCD (5 - 2 = 3 cycles),
- * and >= tRC - tRCD - tRP (8 - 2 - 2 = 4 cycles)
- */
- SdramTiming.LoadToActiveDelay = 2; // tMRD
- SdramTiming.ExitSelfRefreshDelay = 7; // (see above)
- SdramTiming.SelfRefreshTime = 5; // should be >= tRAS (5 cycles)
- SdramTiming.RowCycleDelay = 8; // tRC
- SdramTiming.WriteRecoveryTime = 4; // (see above)
- SdramTiming.RPDelay = 2; // tRP
- SdramTiming.RCDDelay = 2; // tRCD
-
- /*
- * configure the first bank
- */
-
- // memory type
- hsdram1.Instance = FMC_SDRAM_DEVICE;
-
- // bank
- hsdram1.Init.SDBank = FMC_SDRAM_BANK1;
-
- // settings for IS42S32160F
- hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9;
- hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13;
- hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_32;
- hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
- hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_2;
-
- // write protection not needed
- hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
-
- // memory clock is 90 MHz (HCLK / 2)
- hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
-
- // read burst not needed
- hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_DISABLE;
-
- // additional pipeline stages not neeed
- hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;
-
- // call HAL layer
- status = HAL_SDRAM_Init(&hsdram1, &SdramTiming);
- if (status != HAL_OK) return status;
-
- /*
- * configure the second bank
- */
-
- // memory type
- hsdram2.Instance = FMC_SDRAM_DEVICE;
-
- // bank number
- hsdram2.Init.SDBank = FMC_SDRAM_BANK2;
-
- // settings for IS42S32160F
- hsdram2.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9;
- hsdram2.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13;
- hsdram2.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_32;
- hsdram2.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
- hsdram2.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_2;
-
- // write protection not needed
- hsdram2.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
-
- // memory clock is 90 MHz (HCLK / 2)
- hsdram2.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
-
- // read burst not needed
- hsdram2.Init.ReadBurst = FMC_SDRAM_RBURST_DISABLE;
-
- // additional pipeline stages not neeed
- hsdram2.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;
-
- // call HAL layer
- return HAL_SDRAM_Init(&hsdram2, &SdramTiming);
-}
-
-HAL_StatusTypeDef _sdram_init_params(SDRAM_HandleTypeDef *sdram1, SDRAM_HandleTypeDef *sdram2)
-{
- HAL_StatusTypeDef ok; // status
- FMC_SDRAM_CommandTypeDef cmd; // command
-
- /*
- * enable clocking
- */
- cmd.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
- cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2;
- cmd.AutoRefreshNumber = 1;
- cmd.ModeRegisterDefinition = 0;
-
- HAL_Delay(1);
- ok = HAL_SDRAM_SendCommand(sdram1, &cmd, 1);
- if (ok != HAL_OK) return ok;
-
- /*
- * precharge all banks
- */
- cmd.CommandMode = FMC_SDRAM_CMD_PALL;
- cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2;
- cmd.AutoRefreshNumber = 1;
- cmd.ModeRegisterDefinition = 0;
-
- HAL_Delay(1);
- ok = HAL_SDRAM_SendCommand(sdram1, &cmd, 1);
- if (ok != HAL_OK) return ok;
-
-
- /*
- * send two auto-refresh commands in a row
- */
- cmd.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
- cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2;
- cmd.AutoRefreshNumber = 1;
- cmd.ModeRegisterDefinition = 0;
-
- ok = HAL_SDRAM_SendCommand(sdram1, &cmd, 1);
- if (ok != HAL_OK) return ok;
-
- ok = HAL_SDRAM_SendCommand(sdram1, &cmd, 1);
- if (ok != HAL_OK) return ok;
-
-
- /*
- * load mode register
- */
- cmd.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
- cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2;
- cmd.AutoRefreshNumber = 1;
- cmd.ModeRegisterDefinition =
- SDRAM_MODEREG_BURST_LENGTH_1 |
- SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
- SDRAM_MODEREG_CAS_LATENCY_2 |
- SDRAM_MODEREG_OPERATING_MODE_STANDARD |
- SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ;
-
- ok = HAL_SDRAM_SendCommand(sdram1, &cmd, 1);
- if (ok != HAL_OK) return ok;
-
-
- /*
- * set number of consequtive auto-refresh commands
- * and program refresh rate
- *
- * RefreshRate = 64 ms / 8192 cyc = 7.8125 us/cyc
- *
- * RefreshCycles = 7.8125 us * 90 MHz = 703
- *
- * According to the formula on p.1665 of the reference manual,
- * we also need to subtract 20 from the value, so the target
- * refresh rate is 703 - 20 = 683.
- */
-
- ok = HAL_SDRAM_SetAutoRefreshNumber(sdram1, 8);
- if (ok != HAL_OK) return ok;
-
- HAL_SDRAM_ProgramRefreshRate(sdram1, 683);
- if (ok != HAL_OK) return ok;
-
- /*
- * done
- */
- return HAL_OK;
-}
+/*
+ * stm-sdram.c
+ * -----------
+ * Functions concerning the 2x512 Mbit SDRAM working memory.
+ *
+ * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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 "stm-init.h"
+#include "stm-sdram.h"
+#include "stm-fmc.h"
+#include "stm-led.h"
+
+/* Mode Register Bits */
+#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000)
+#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001)
+#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002)
+#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004)
+
+#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
+#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
+
+#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020)
+#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030)
+
+#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
+
+#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
+#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
+
+static SDRAM_HandleTypeDef hsdram1;
+static SDRAM_HandleTypeDef hsdram2;
+
+static void _sdram_init_gpio(void);
+static void _sdram_init_fmc(void);
+static void _sdram_init_params(void);
+
+void sdram_init(void)
+{
+ static int initialized = 0;
+ if (initialized) return;
+ initialized = 1;
+
+ /* We rely on several things being set up by fmc_init() instead of duplicating all
+ * that code here for independent FPGA/SDRAM FMC setup. This means the FPGA<->STM32
+ * FMC bus can be used without the SDRAMs initialized, but the SDRAMs can't be
+ * initialized withouth the FPGA<->STM32 FMC bus being set up too.
+ */
+ fmc_init();
+
+ /* configure FMC */
+ _sdram_init_gpio();
+ _sdram_init_fmc();
+
+ /* configure SDRAM registers */
+ _sdram_init_params();
+}
+
+static void _sdram_init_gpio(void)
+{
+ GPIO_InitTypeDef GPIO_InitStruct;
+
+ /* The bulk of the FMC GPIO pins are set up in fmc_init_gpio().
+ * This function just needs to enable the additional ones used
+ * with the SDRAMs.
+ */
+ fmc_af_gpio(GPIOB, GPIO_PIN_5 | GPIO_PIN_6);
+ fmc_af_gpio(GPIOC, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3);
+ fmc_af_gpio(GPIOE, GPIO_PIN_0 | GPIO_PIN_1);
+ fmc_af_gpio(GPIOF, GPIO_PIN_11);
+ fmc_af_gpio(GPIOG, GPIO_PIN_8 | GPIO_PIN_15);
+ fmc_af_gpio(GPIOI, GPIO_PIN_4 | GPIO_PIN_5);
+}
+
+static void _sdram_config_bank(SDRAM_HandleTypeDef *hsdram, uint32_t SDBank, FMC_SDRAM_TimingTypeDef *SdramTiming)
+{
+ /* memory type */
+ hsdram->Instance = FMC_SDRAM_DEVICE;
+
+ /* bank */
+ hsdram->Init.SDBank = SDBank;
+
+ /* settings for IS42S32160F */
+ hsdram->Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9;
+ hsdram->Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13;
+ hsdram->Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_32;
+ hsdram->Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
+ hsdram->Init.CASLatency = FMC_SDRAM_CAS_LATENCY_2;
+
+ /* write protection not needed */
+ hsdram->Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
+
+ /* memory clock is 90 MHz (HCLK / 2) */
+ hsdram->Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
+
+ /* read burst not needed */
+ hsdram->Init.ReadBurst = FMC_SDRAM_RBURST_DISABLE;
+
+ /* additional pipeline stages not neeed */
+ hsdram->Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;
+
+ /* call HAL layer */
+ HAL_SDRAM_Init(hsdram, SdramTiming);
+}
+
+static void _sdram_init_fmc(void)
+{
+ FMC_SDRAM_TimingTypeDef SdramTiming;
+
+ /*
+ * following settings are for -75E speed grade memory chip
+ * clocked at only 90 MHz instead of the rated 133 MHz
+ *
+ * ExitSelfRefreshDelay: 67 ns @ 90 MHz is 6.03 cycles, so in theory
+ * 6 can be used here, but let's be on the safe side
+ *
+ * WriteRecoveryTime: must be >= tRAS - tRCD (5 - 2 = 3 cycles),
+ * and >= tRC - tRCD - tRP (8 - 2 - 2 = 4 cycles)
+ */
+ SdramTiming.LoadToActiveDelay = 2; // tMRD
+ SdramTiming.ExitSelfRefreshDelay = 7; // (see above)
+ SdramTiming.SelfRefreshTime = 5; // should be >= tRAS (5 cycles)
+ SdramTiming.RowCycleDelay = 8; // tRC
+ SdramTiming.WriteRecoveryTime = 4; // (see above)
+ SdramTiming.RPDelay = 2; // tRP
+ SdramTiming.RCDDelay = 2; // tRCD
+
+ /* configure the first bank */
+ _sdram_config_bank(&hsdram1, FMC_SDRAM_BANK1, &SdramTiming);
+
+ /* configure the second bank */
+ _sdram_config_bank(&hsdram2, FMC_SDRAM_BANK2, &SdramTiming);
+}
+
+static void _sdram_init_params(void)
+{
+ FMC_SDRAM_CommandTypeDef cmd;
+
+ /* enable clocking */
+ cmd.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
+ cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2;
+ cmd.AutoRefreshNumber = 1;
+ cmd.ModeRegisterDefinition = 0;
+ HAL_Delay(1);
+ HAL_SDRAM_SendCommand(&hsdram1, &cmd, 1);
+
+ /* precharge all banks */
+ cmd.CommandMode = FMC_SDRAM_CMD_PALL;
+ cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2;
+ cmd.AutoRefreshNumber = 1;
+ cmd.ModeRegisterDefinition = 0;
+ HAL_Delay(1);
+ HAL_SDRAM_SendCommand(&hsdram1, &cmd, 1);
+
+ /* send two auto-refresh commands in a row */
+ cmd.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
+ cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2;
+ cmd.AutoRefreshNumber = 1;
+ cmd.ModeRegisterDefinition = 0;
+ HAL_SDRAM_SendCommand(&hsdram1, &cmd, 1);
+ HAL_SDRAM_SendCommand(&hsdram1, &cmd, 1);
+
+ /* load mode register */
+ cmd.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
+ cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2;
+ cmd.AutoRefreshNumber = 1;
+ cmd.ModeRegisterDefinition =
+ SDRAM_MODEREG_BURST_LENGTH_1 |
+ SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
+ SDRAM_MODEREG_CAS_LATENCY_2 |
+ SDRAM_MODEREG_OPERATING_MODE_STANDARD |
+ SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ;
+ HAL_SDRAM_SendCommand(&hsdram1, &cmd, 1);
+
+ /*
+ * set number of consequtive auto-refresh commands
+ * and program refresh rate
+ *
+ * RefreshRate = 64 ms / 8192 cyc = 7.8125 us/cyc
+ *
+ * RefreshCycles = 7.8125 us * 90 MHz = 703
+ *
+ * According to the formula on p.1665 of the reference manual,
+ * we also need to subtract 20 from the value, so the target
+ * refresh rate is 703 - 20 = 683.
+ */
+
+ HAL_SDRAM_SetAutoRefreshNumber(&hsdram1, 8);
+
+ HAL_SDRAM_ProgramRefreshRate(&hsdram1, 683);
+}
diff --git a/stm-sdram.h b/stm-sdram.h
index 8f58b34..88a7086 100644
--- a/stm-sdram.h
+++ b/stm-sdram.h
@@ -1,66 +1,46 @@
-/*
- * stm-sdram.h
- * -----------
- * Functions and defines concerning the 2x512 Mbit SDRAM working memory.
- *
- * Copyright (c) 2016, NORDUnet A/S All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - 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.
- *
- * - Neither the name of the NORDUnet nor the names of its contributors may
- * be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
- * HOLDER 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 __STM32_SDRAM_H
-#define __STM32_SDRAM_H
-
-/* Base Addresses */
-#define SDRAM_BASEADDR_CHIP1 ((uint32_t *)0xC0000000)
-#define SDRAM_BASEADDR_CHIP2 ((uint32_t *)0xD0000000)
-
-/* Memory Size, 64 MBytes (512 Mbits) */
-#define SDRAM_SIZE 0x4000000
-
-/* Mode Register Bits */
-#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000)
-#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001)
-#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002)
-#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004)
-
-#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
-#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
-
-#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020)
-#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030)
-
-#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
-
-#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
-#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
-
-extern SDRAM_HandleTypeDef hsdram1;
-extern SDRAM_HandleTypeDef hsdram2;
-
-extern HAL_StatusTypeDef sdram_init(void);
-
-#endif
+/*
+ * stm-sdram.h
+ * -----------
+ * Functions and defines concerning the 2x512 Mbit SDRAM working memory.
+ *
+ * Copyright (c) 2016, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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 __STM32_SDRAM_H
+#define __STM32_SDRAM_H
+
+/* Base Addresses */
+#define SDRAM_BASEADDR_CHIP1 ((uint32_t *)0xC0000000)
+#define SDRAM_BASEADDR_CHIP2 ((uint32_t *)0xD0000000)
+
+/* Memory Size, 64 MBytes (512 Mbits) */
+#define SDRAM_SIZE 0x4000000
+
+extern void sdram_init(void);
+
+#endif
diff --git a/stm-uart.c b/stm-uart.c
index 7911d44..1f006b7 100644
--- a/stm-uart.c
+++ b/stm-uart.c
@@ -4,6 +4,8 @@
* Functions for sending strings and numbers over the uart.
*
* Copyright (c) 2015, NORDUnet A/S All rights reserved.
+ * Copyright: 2020, The Commons Conservancy Cryptech Project
+ * SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -15,9 +17,9 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * - Neither the name of the NORDUnet nor the names of its contributors may
- * be used to endorse or promote products derived from this software
- * without specific prior written permission.
+ * - Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -32,7 +34,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "stm32f4xx_hal.h"
+#include "stm-init.h"
#include "stm-uart.h"
#include <string.h>
@@ -43,96 +45,127 @@ UART_HandleTypeDef huart_user; /* USART2 */
DMA_HandleTypeDef hdma_usart_mgmt_rx;
DMA_HandleTypeDef hdma_usart_user_rx;
-#define DEFAULT_UART STM_UART_USER
+UART_HandleTypeDef* default_uart = STM_UART_MGMT;
-
-inline UART_HandleTypeDef *_which_uart(stm_uart_port_t port)
+#ifdef HAL_DMA_MODULE_ENABLED
+/**
+ * Enable DMA controller clock
+ */
+static void MX_DMA_Init(void)
{
- if (port == STM_UART_USER) {
- return &huart_user;
- } else if (port == STM_UART_MGMT) {
- return &huart_mgmt;
- }
-
- return NULL;
+ /* DMA controller clock enable */
+ __HAL_RCC_DMA2_CLK_ENABLE();
+ __HAL_RCC_DMA1_CLK_ENABLE();
+
+ /* DMA interrupt init */
+
+ /* USER UART RX */
+ HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 0, 0);
+ HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn);
+ /* MGMT UART RX */
+ HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0);
+ HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
}
+#endif /* HAL_DMA_MODULE_ENABLED */
-/* send a single character */
-HAL_StatusTypeDef uart_send_char(uint8_t ch)
+/* USART1 init function */
+static void MX_USART1_UART_Init(void)
{
- return uart_send_char2(DEFAULT_UART, ch);
+ huart_mgmt.Instance = USART1;
+ huart_mgmt.Init.BaudRate = USART_MGMT_BAUD_RATE;
+ huart_mgmt.Init.WordLength = UART_WORDLENGTH_8B;
+ huart_mgmt.Init.StopBits = UART_STOPBITS_1;
+ huart_mgmt.Init.Parity = UART_PARITY_NONE;
+ huart_mgmt.Init.Mode = UART_MODE_TX_RX;
+ huart_mgmt.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS;
+ huart_mgmt.Init.OverSampling = UART_OVERSAMPLING_16;
+
+#ifdef HAL_DMA_MODULE_ENABLED
+ __HAL_LINKDMA(&huart_mgmt, hdmarx, hdma_usart_mgmt_rx);
+#endif
+
+ if (HAL_UART_Init(&huart_mgmt) != HAL_OK) {
+ /* Initialization Error */
+ Error_Handler();
+ }
}
-
-HAL_StatusTypeDef uart_send_char2(stm_uart_port_t port, uint8_t ch)
+/* USART2 init function */
+static void MX_USART2_UART_Init(void)
{
- return uart_send_bytes(port, &ch, 1);
+ huart_user.Instance = USART2;
+ huart_user.Init.BaudRate = USART_USER_BAUD_RATE;
+ huart_user.Init.WordLength = UART_WORDLENGTH_8B;
+ huart_user.Init.StopBits = UART_STOPBITS_1;
+ huart_user.Init.Parity = UART_PARITY_NONE;
+ huart_user.Init.Mode = UART_MODE_TX_RX;
+ huart_user.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS;
+ huart_user.Init.OverSampling = UART_OVERSAMPLING_16;
+
+#ifdef HAL_DMA_MODULE_ENABLED
+ __HAL_LINKDMA(&huart_user, hdmarx, hdma_usart_user_rx);
+#endif
+
+ if (HAL_UART_Init(&huart_user) != HAL_OK) {
+ /* Initialization Error */
+ Error_Handler();
+ }
}
-/* receive a single character */
-HAL_StatusTypeDef uart_recv_char(uint8_t *cp)
+void uart_init(void)
{
- return uart_recv_char2(DEFAULT_UART, cp, HAL_MAX_DELAY);
+#ifdef HAL_DMA_MODULE_ENABLED
+ MX_DMA_Init();
+#endif
+ MX_USART1_UART_Init();
+ MX_USART2_UART_Init();
}
-/* receive a single character */
-HAL_StatusTypeDef uart_recv_char2(stm_uart_port_t port, uint8_t *cp, uint32_t timeout)
+void uart_set_default(UART_HandleTypeDef *uart)
{
- UART_HandleTypeDef *uart = _which_uart(port);
-
- if (uart)
- return HAL_UART_Receive(uart, cp, 1, timeout);
+ default_uart = uart;
+}
- return HAL_ERROR;
+/* send a single character */
+HAL_StatusTypeDef uart_send_char2(UART_HandleTypeDef *uart, uint8_t ch)
+{
+ return uart_send_bytes2(uart, &ch, 1);
}
-/* send a string */
-HAL_StatusTypeDef uart_send_string(char *s)
+/* receive a single character */
+HAL_StatusTypeDef uart_recv_char2(UART_HandleTypeDef *uart, uint8_t *cp, uint32_t timeout)
{
- return uart_send_string2(DEFAULT_UART, s);
+ return HAL_UART_Receive(uart, cp, 1, timeout);
}
/* send a string */
-HAL_StatusTypeDef uart_send_string2(stm_uart_port_t port, const char *s)
+HAL_StatusTypeDef uart_send_string2(UART_HandleTypeDef *uart, const char *s)
{
- return uart_send_bytes(port, (uint8_t *) s, strlen(s));
+ return uart_send_bytes2(uart, (uint8_t *) s, strlen(s));
}
/* send raw bytes */
-HAL_StatusTypeDef uart_send_bytes(stm_uart_port_t port, uint8_t *buf, size_t len)
+HAL_StatusTypeDef uart_send_bytes2(UART_HandleTypeDef *uart, uint8_t *buf, size_t len)
{
- uint32_t timeout = 100;
- UART_HandleTypeDef *uart = _which_uart(port);
-
- if (uart) {
- while (HAL_UART_GetState(uart) != HAL_UART_STATE_READY && timeout--) { ; }
- if (! timeout) return HAL_ERROR;
-
- return HAL_UART_Transmit(uart, (uint8_t *) buf, (uint32_t) len, 0x1);
+ for (int timeout = 0; timeout < 100; ++timeout) {
+ HAL_UART_StateTypeDef status = HAL_UART_GetState(uart);
+ if (status == HAL_UART_STATE_READY ||
+ status == HAL_UART_STATE_BUSY_RX)
+ return HAL_UART_Transmit(uart, (uint8_t *) buf, (uint32_t) len, 0x1);
}
- return HAL_ERROR;
+ return HAL_TIMEOUT;
}
/* receive raw bytes */
-HAL_StatusTypeDef uart_receive_bytes(stm_uart_port_t port, uint8_t *buf, size_t len, uint32_t timeout)
+HAL_StatusTypeDef uart_receive_bytes2(UART_HandleTypeDef *uart, uint8_t *buf, size_t len, uint32_t timeout)
{
- UART_HandleTypeDef *uart = _which_uart(port);
-
- if (uart)
- return HAL_UART_Receive(uart, (uint8_t *) buf, (uint32_t) len, timeout);
-
- return HAL_ERROR;
+ return HAL_UART_Receive(uart, (uint8_t *) buf, (uint32_t) len, timeout);
}
/* Generalized routine to send binary, decimal, and hex integers.
* This code is adapted from Chris Giese's printf.c
*/
-HAL_StatusTypeDef uart_send_number(uint32_t num, uint8_t digits, uint8_t radix)
-{
- return uart_send_number2(DEFAULT_UART, num, digits, radix);
-}
-
-HAL_StatusTypeDef uart_send_number2(stm_uart_port_t port, uint32_t num, uint8_t digits, uint8_t radix)
+HAL_StatusTypeDef uart_send_number2(UART_HandleTypeDef *uart, uint32_t num, uint8_t digits, uint8_t radix)
{
#define BUFSIZE 32
char buf[BUFSIZE];
@@ -160,29 +193,30 @@ HAL_StatusTypeDef uart_send_number2(stm_uart_port_t port, uint32_t num, uint8_t
/* number is larger than the specified number of digits */
digits = buf + BUFSIZE - where;
- return uart_send_bytes(port, (uint8_t *) where, digits);
+ return uart_send_bytes2(uart, (uint8_t *) where, digits);
}
-HAL_StatusTypeDef uart_send_hexdump(stm_uart_port_t port, const uint8_t *buf,
- const uint8_t start_offset, const uint8_t end_offset)
+HAL_StatusTypeDef uart_send_hexdump2(UART_HandleTypeDef *uart, const uint8_t *buf,
+ const uint8_t start_offset, const uint8_t end_offset)
{
uint32_t i;
- uart_send_string2(port, "00 -- ");
+ uart_send_number2(uart, start_offset, 2, 16);
+ uart_send_string2(uart, " -- ");
- for (i = 0; i <= end_offset; i++) {
+ for (i = start_offset; i <= end_offset; i++) {
if (i && (! (i % 16))) {
- uart_send_string2(port, "\r\n");
+ uart_send_string2(uart, "\r\n");
if (i != end_offset) {
/* Output new offset unless the last byte is reached */
- uart_send_number2(port, i, 2, 16);
- uart_send_string2(port, " -- ");
+ uart_send_number2(uart, i, 2, 16);
+ uart_send_string2(uart, " -- ");
}
}
- uart_send_number2(port, *(buf + i), 2, 16);
- uart_send_string2(port, " ");
+ uart_send_number2(uart, *(buf + i), 2, 16);
+ uart_send_string2(uart, " ");
}
return HAL_OK;
diff --git a/stm-uart.h b/stm-uart.h
index 6133093..8ea13d8 100644
--- a/stm-uart.h
+++ b/stm-uart.h
@@ -37,37 +37,48 @@
#include "stm32f4xx_hal.h"
-#define USART_MGMT_BAUD_RATE 921600
-#define USART_USER_BAUD_RATE 921600
-
-typedef enum {
- STM_UART_USER,
- STM_UART_MGMT
-} stm_uart_port_t;
+#define USART_MGMT_BAUD_RATE 921600
+#define USART_USER_BAUD_RATE 921600
extern UART_HandleTypeDef huart_mgmt;
extern UART_HandleTypeDef huart_user;
+#define STM_UART_USER &huart_user
+#define STM_UART_MGMT &huart_mgmt
+
+/* These are only exposed because they're used in the DMA IRQ handler code.
+ * Pretend you never saw them.
+ */
extern DMA_HandleTypeDef hdma_usart_mgmt_rx;
extern DMA_HandleTypeDef hdma_usart_user_rx;
-extern HAL_StatusTypeDef uart_send_char(uint8_t ch);
-extern HAL_StatusTypeDef uart_recv_char(uint8_t *cp);
-
-extern HAL_StatusTypeDef uart_send_string(char *s);
-extern HAL_StatusTypeDef uart_send_number(uint32_t num, uint8_t digits, uint8_t radix);
+extern void uart_init(void);
-extern HAL_StatusTypeDef uart_send_char2(stm_uart_port_t port, uint8_t ch);
-extern HAL_StatusTypeDef uart_recv_char2(stm_uart_port_t port, uint8_t *cp, uint32_t timeout);
-
-extern HAL_StatusTypeDef uart_send_string2(stm_uart_port_t port, const char *s);
-extern HAL_StatusTypeDef uart_send_number2(stm_uart_port_t port, uint32_t num, uint8_t digits, uint8_t radix);
+/* Default UART is MGMT; don't change it unless you need to.
+ */
+extern UART_HandleTypeDef* default_uart;
+extern void uart_set_default(UART_HandleTypeDef *uart);
-extern HAL_StatusTypeDef uart_send_bytes(stm_uart_port_t port, uint8_t *buf, size_t len);
-extern HAL_StatusTypeDef uart_receive_bytes(stm_uart_port_t port, uint8_t *buf, size_t len, uint32_t timeout);
+/* Send and receive to/from an explicit UART. For the most part, you
+ * shouldn't need to call these directly, but can use the default_uart
+ * macros below.
+ */
+extern HAL_StatusTypeDef uart_send_char2(UART_HandleTypeDef *uart, uint8_t ch);
+extern HAL_StatusTypeDef uart_recv_char2(UART_HandleTypeDef *uart, uint8_t *cp, uint32_t timeout);
+extern HAL_StatusTypeDef uart_send_string2(UART_HandleTypeDef *uart, const char *s);
+extern HAL_StatusTypeDef uart_send_number2(UART_HandleTypeDef *uart, uint32_t num, uint8_t digits, uint8_t radix);
+extern HAL_StatusTypeDef uart_send_bytes2(UART_HandleTypeDef *uart, uint8_t *buf, size_t len);
+extern HAL_StatusTypeDef uart_receive_bytes2(UART_HandleTypeDef *uart, uint8_t *buf, size_t len, uint32_t timeout);
+extern HAL_StatusTypeDef uart_send_hexdump2(UART_HandleTypeDef *uart, const uint8_t *buf,
+ const uint8_t start_offset, const uint8_t end_offset);
-extern HAL_StatusTypeDef uart_send_hexdump(stm_uart_port_t port, const uint8_t *buf,
- const uint8_t start_offset, const uint8_t end_offset);
+#define uart_send_char(c) uart_send_char2(default_uart, c)
+#define uart_recv_char(cp, t) uart_recv_char2(default_uart, cp, t)
+#define uart_send_string(s) uart_send_string2(default_uart, s)
+#define uart_send_bytes(b, l) uart_send_bytes2(default_uart, b, l)
+#define uart_receive_bytes(b, l, t) uart_receive_bytes2(default_uart, b, l, t)
+#define uart_send_number(n, d, r) uart_send_number2(default_uart, n, d, r)
+#define uart_send_hexdump(b, s, e) uart_send_hexdump2(default_uart, b, s, e)
#define uart_send_binary(num, bits) uart_send_number(num, bits, 2)
#define uart_send_integer(num, digits) uart_send_number(num, digits, 10)
diff --git a/syscalls.c b/syscalls.c
index d7b7211..fc842c0 100644
--- a/syscalls.c
+++ b/syscalls.c
@@ -48,6 +48,7 @@
/***************************************************************************/
+#ifndef DO_PROFILING
int _read_r (struct _reent *r, int file, char * ptr, int len)
{
r = r;
@@ -101,8 +102,12 @@ int _write_r (struct _reent *r, int file, char * ptr, int len)
int _close_r (struct _reent *r, int file)
{
+ r = r;
+ file = file;
+
return 0;
}
+#endif
/***************************************************************************/
@@ -115,6 +120,8 @@ caddr_t _sbrk_r (struct _reent *r, int incr)
static char * heap_end;
char * prev_heap_end;
+ r = r;
+
if (heap_end == NULL)
heap_end = & end;
@@ -143,6 +150,7 @@ caddr_t _sbrk_r (struct _reent *r, int incr)
/***************************************************************************/
+#ifndef DO_PROFILING
int _fstat_r (struct _reent *r, int file, struct stat * st)
{
r = r;
@@ -181,6 +189,7 @@ int _kill (int a, int b)
return 0;
}
+#endif
/***************************************************************************/
@@ -193,6 +202,7 @@ int _getpid(int a)
/***************************************************************************/
+#ifndef DO_PROFILING
int _open(int a, int b)
{
a = a;
@@ -200,5 +210,6 @@ int _open(int a, int b)
return 0;
}
+#endif
/*** EOF ***/
diff --git a/task.c b/task.c
new file mode 100644
index 0000000..adb845b
--- /dev/null
+++ b/task.c
@@ -0,0 +1,450 @@
+/*
+ * task.c
+ * ----------------
+ * Simple cooperative tasking system.
+ *
+ * Copyright (c) 2017, NORDUnet A/S All rights reserved.
+ * Copyright: 2020, The Commons Conservancy Cryptech Project
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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.
+ */
+
+/* Dead-simple fully-cooperative tasker. There are no priorities; tasks
+ * are run in a strictly round-robin fashion. There is no preemption;
+ * tasks explicitly yield control. Tasks are created at system init time,
+ * and are expected to run an infinite loop; tasks do not return, nor are
+ * tasks deleted.
+ */
+
+/* Ignore "deprecated" warnings in ARM-supplied CMSIS code:
+ *
+ * libraries/mbed/targets/cmsis/core_cm4.h:85:28: warning: listing the stack pointer register 'sp' in a clobber list is deprecated
+ * libraries/mbed/targets/cmsis/core_cm4.h:85:28: note: the value of the stack pointer after an 'asm' statement must be the same as it was before the statement
+ *
+ * This comes from our use of __set_MSP to set the stack pointer when
+ * switching tasks. If GCC ever decides to actually forbid this, then
+ * we'll have to figure out something else, possibly a native assembly
+ * function.
+ */
+#pragma GCC diagnostic ignored "-Wdeprecated"
+
+#include "stm-init.h"
+#include "task.h"
+
+/* Task Control Block. The structure is private, in case we want to change
+ * it later without having to change the API. In any case, external code
+ * shouldn't poke its fingers in the internal details.
+ */
+struct task_cb {
+ struct task_cb *next;
+ task_state_t state;
+
+ char *name;
+ funcp_t func;
+ void *cookie;
+
+ void *stack_base;
+ size_t stack_len;
+ void *stack_ptr;
+};
+
+/* Number of tasks. Default is number of RPC dispatch tasks, plus CLI task. */
+#ifndef MAX_TASK
+#ifdef NUM_RPC_TASK
+#define MAX_TASK (NUM_RPC_TASK + 2)
+#else
+#define MAX_TASK 6
+#endif
+#endif
+
+static tcb_t tcbs[MAX_TASK];
+static size_t num_task = 0;
+
+/* We have a circular list of tasks. New tasks are added at the tail, and
+ * tail->next is the head.
+ */
+static tcb_t *tail = NULL;
+
+/* Currently running task */
+static tcb_t *cur_task = NULL;
+
+#define STACK_GUARD_WORD 0x55AA5A5A
+
+#ifdef DO_TASK_METRICS
+static uint32_t tick_start = 0;
+static uint32_t tick_idle = 0;
+static uint32_t tick_max = 0;
+static uint32_t nyield = 0;
+#endif
+
+static uint32_t tick_prev = 0;
+#ifndef TASK_YIELD_THRESHOLD
+#define TASK_YIELD_THRESHOLD 100
+#endif
+
+/* Add a task.
+ */
+tcb_t *task_add(char *name, funcp_t func, void *cookie, void *stack, size_t stack_len)
+{
+ if (num_task >= MAX_TASK)
+ return NULL;
+
+ if (name == NULL || func == NULL || stack == NULL)
+ return NULL;
+
+ tcb_t *t = &tcbs[num_task++];
+ t->state = TASK_INIT;
+
+ t->name = name;
+ t->func = func;
+ t->cookie = cookie;
+
+ t->stack_base = stack;
+ t->stack_len = stack_len;
+ t->stack_ptr = stack + stack_len;
+
+ for (uint32_t *p = (uint32_t *)t->stack_base; p < (uint32_t *)t->stack_ptr; ++p)
+ *p = STACK_GUARD_WORD;
+
+ if (tail == NULL) {
+ /* Empty list; initialize it to this task. */
+ t->next = t;
+ }
+ else {
+ /* Otherwise insert at the end of the list. */
+ t->next = tail->next;
+ tail->next = t;
+ }
+ tail = t;
+
+ return t;
+}
+
+/* Reinitalize the current task.
+ * NOTE: This will destroy any state in the running task.
+ * DO NOT CALL THIS UNLESS YOU ARE REALLY SURE THAT'S WHAT YOU WANT TO DO.
+ */
+void task_mod(char *name, funcp_t func, void *cookie)
+{
+ tcb_t *t = cur_task;
+ t->name = name;
+ t->func = func;
+ t->cookie = cookie;
+ t->state = TASK_INIT;
+ t->stack_ptr = t->stack_base + t->stack_len;
+ for (uint32_t *p = (uint32_t *)t->stack_base; p < (uint32_t *)t->stack_ptr; ++p)
+ *p = STACK_GUARD_WORD;
+ __set_MSP((uint32_t)cur_task->stack_ptr);
+ task_yield();
+}
+
+/* Set the idle hook function pointer.
+ *
+ * This function is called repeatedly when the system is idle (there are
+ * no runnable tasks).
+ *
+ * The idle function should NOT call task_delay or HAL_Delay, because that
+ * will cause fatal recursion. We could add a recursion guard to
+ * task_yield, but we're not currently using the idle hook, and I'm
+ * thinking about removing it entirely.
+ */
+static void default_idle_hook(void) { }
+static funcp_t idle_hook = default_idle_hook;
+void task_set_idle_hook(funcp_t func)
+{
+ idle_hook = (func == NULL) ? default_idle_hook : func;
+}
+
+/* Find the next runnable task.
+ */
+static tcb_t *next_task(void)
+{
+ tcb_t *t;
+
+ /* If the tasker isn't running yet, return the first task. */
+ if (cur_task == NULL)
+ return (tail == NULL) ? NULL : tail->next;
+
+ // XXX critical section?
+
+ /* find the next runnable task */
+ for (t = cur_task->next; t != cur_task; t = t->next) {
+ if (t->state != TASK_WAITING)
+ return t;
+ }
+
+ /* searched all the way back to cur_task - is it runnable? */
+ return (cur_task->state == TASK_WAITING) ? NULL : cur_task;
+}
+
+/* Check for stack overruns.
+ */
+static void check_stack(tcb_t *t)
+{
+ if (t->stack_ptr < t->stack_base ||
+ t->stack_ptr >= t->stack_base + t->stack_len ||
+ *(uint32_t *)t->stack_base != STACK_GUARD_WORD)
+ Error_Handler();
+}
+
+/* Yield control to the next runnable task.
+ */
+void task_yield(void)
+{
+ tcb_t *next;
+
+ /* If there are no defined tasks, exit immediately so we don't get
+ * caught in the idle loop.
+ */
+ if (tail == NULL)
+ return;
+
+#ifdef DO_TASK_METRICS
+ uint32_t tick0 = HAL_GetTick();
+#endif
+
+ /* Find the next runnable task. Loop if every task is waiting. */
+ while (1) {
+ next = next_task();
+ if (next == NULL)
+ idle_hook();
+ else
+ break;
+ }
+
+ /* If we decide we don't need the idle hook, the preceding loop could
+ * devolve to something like this:
+ *
+ * do {
+ * next = next_task();
+ * } while (next == NULL);
+ */
+
+#ifdef DO_TASK_METRICS
+ uint32_t tick = HAL_GetTick();
+ tick_idle += (tick - tick0);
+ if (tick_start == 0)
+ tick_start = tick;
+ if (tick_prev != 0) {
+ uint32_t duration = tick0 - tick_prev;
+ if (duration > tick_max)
+ tick_max = duration;
+ }
+ tick_prev = tick;
+ ++nyield;
+#else
+ tick_prev = HAL_GetTick();
+#endif
+
+ /* If there are no other runnable tasks (and cur_task is runnable),
+ * we don't need to context-switch.
+ */
+ if (next == cur_task && cur_task->state != TASK_INIT)
+ return;
+
+ /* Save current context, if there is one. */
+ if (cur_task != NULL && cur_task->state != TASK_INIT) {
+ __asm("push {r0-r12, lr}");
+ cur_task->stack_ptr = (void *)__get_MSP();
+
+ /* Check for stack overruns. */
+ check_stack(cur_task);
+ }
+
+ cur_task = next;
+
+ /* If task is in init state, call its entry point. */
+ if (cur_task->state == TASK_INIT) {
+ __set_MSP((uint32_t)cur_task->stack_ptr);
+ cur_task->state = TASK_READY;
+ cur_task->func();
+ /*NOTREACHED*/
+ }
+
+ /* Otherwise, restore the task's context. */
+ else {
+ __set_MSP((uint32_t)cur_task->stack_ptr);
+ __asm("pop {r0-r12, lr}");
+ return;
+ }
+}
+
+/* Yield if it's been "too long" since the last yield.
+ */
+void task_yield_maybe(void)
+{
+ if (HAL_GetTick() - tick_prev >= TASK_YIELD_THRESHOLD)
+ task_yield();
+}
+
+/* Put the current task to sleep (make it non-runnable).
+ */
+void task_sleep(void)
+{
+ if (cur_task != NULL)
+ cur_task->state = TASK_WAITING;
+
+ task_yield();
+}
+
+/* Wake a task (make it runnable).
+ */
+void task_wake(tcb_t *t)
+{
+ if (t != NULL)
+ t->state = TASK_READY;
+}
+
+/* Accessor functions */
+
+tcb_t *task_get_tcb(void)
+{
+ return cur_task;
+}
+
+char *task_get_name(tcb_t *t)
+{
+ if (t == NULL)
+ t = cur_task;
+
+ return t->name;
+}
+
+funcp_t task_get_func(tcb_t *t)
+{
+ if (t == NULL)
+ t = cur_task;
+
+ return t->func;
+}
+
+void *task_get_cookie(tcb_t *t)
+{
+ if (t == NULL)
+ t = cur_task;
+
+ return t->cookie;
+}
+
+task_state_t task_get_state(tcb_t *t)
+{
+ if (t == NULL)
+ t = cur_task;
+
+ return t->state;
+}
+
+void *task_get_stack(tcb_t *t)
+{
+ if (t == NULL)
+ t = cur_task;
+
+ return t->stack_ptr;
+}
+
+/* stupid linear search for first non guard word */
+size_t task_get_stack_highwater(tcb_t *t)
+{
+ if (t == NULL)
+ t = cur_task;
+
+ const uint32_t * const b = (uint32_t *)t->stack_base;
+
+ for (size_t i = 0; i < t->stack_len/4; ++i) {
+ if (b[i] != STACK_GUARD_WORD) {
+ return (t->stack_len - (i * 4));
+ }
+ }
+
+ return 0;
+}
+
+/* Iterate through tasks.
+ *
+ * Returns the next task control block, or NULL at the end of the list.
+ */
+tcb_t *task_iterate(tcb_t *t)
+{
+ if (t == NULL)
+ return (tail == NULL) ? NULL : tail->next;
+
+ if (t == tail)
+ return NULL;
+
+ return t->next;
+}
+
+/* Delay a number of 1ms ticks.
+ */
+void task_delay(uint32_t delay)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ while ((HAL_GetTick() - tickstart) < delay)
+ task_yield();
+}
+void HAL_Delay(uint32_t delay) __attribute__((alias("task_delay")));
+
+/* Simple mutex-like locks. A real mutex would require the unlocker to be
+ * the current owner, but then we have to define and return errors, when
+ * all we want at the moment is simple mutual exclusion.
+ */
+void task_mutex_lock(task_mutex_t *mutex)
+{
+ while (mutex->locked)
+ task_yield();
+ mutex->locked = 1;
+}
+
+void task_mutex_unlock(task_mutex_t *mutex)
+{
+ if (mutex != NULL)
+ mutex->locked = 0;
+}
+
+#ifdef DO_TASK_METRICS
+void task_get_metrics(struct task_metrics *tm)
+{
+ if (tm != NULL) {
+ tm->avg.tv_sec = 0;
+ tm->avg.tv_usec = (HAL_GetTick() - tick_start - tick_idle) * 1000 / nyield;
+ if (tm->avg.tv_usec > 1000000) {
+ tm->avg.tv_sec = tm->avg.tv_usec / 1000000;
+ tm->avg.tv_usec = tm->avg.tv_usec % 1000000;
+ }
+ tm->max.tv_sec = tick_max / 1000;
+ tm->max.tv_usec = (tick_max % 1000) * 1000;
+ }
+}
+
+void task_reset_metrics(void)
+{
+ tick_start = HAL_GetTick();
+ tick_prev = tick_idle = tick_max = nyield = 0;
+}
+#endif
diff --git a/task.h b/task.h
new file mode 100644
index 0000000..a71f2e4
--- /dev/null
+++ b/task.h
@@ -0,0 +1,89 @@
+/*
+ * task.c
+ * ----------------
+ * Simple cooperative tasking system.
+ *
+ * Copyright (c) 2017, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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 _TASK_H_
+#define _TASK_H_
+
+#include <sys/types.h>
+#include <stdint.h>
+
+typedef enum task_state {
+ TASK_INIT,
+ TASK_WAITING,
+ TASK_READY
+} task_state_t;
+
+typedef struct task_cb tcb_t;
+
+typedef struct { unsigned locked; } task_mutex_t;
+
+typedef void (*funcp_t)(void);
+
+extern tcb_t *task_add(char *name, funcp_t func, void *cookie, void *stack, size_t stack_len);
+extern void task_mod(char *name, funcp_t func, void *cookie);
+
+extern void task_set_idle_hook(funcp_t func);
+
+extern void task_yield(void);
+extern void task_yield_maybe(void);
+extern void task_sleep(void);
+extern void task_wake(tcb_t *t);
+
+extern tcb_t *task_get_tcb(void);
+extern char *task_get_name(tcb_t *t);
+extern funcp_t task_get_func(tcb_t *t);
+extern void *task_get_cookie(tcb_t *t);
+extern task_state_t task_get_state(tcb_t *t);
+extern void *task_get_stack(tcb_t *t);
+extern size_t task_get_stack_highwater(tcb_t *t);
+
+extern tcb_t *task_iterate(tcb_t *t);
+
+extern void task_delay(uint32_t delay);
+
+extern void task_mutex_lock(task_mutex_t *mutex);
+extern void task_mutex_unlock(task_mutex_t *mutex);
+
+#ifdef DO_TASK_METRICS
+#include <sys/time.h>
+
+struct task_metrics {
+ struct timeval avg, max;
+};
+
+void task_get_metrics(struct task_metrics *tm);
+void task_reset_metrics(void);
+#endif
+
+#endif /* _TASK_H_ */