nikinan/stm32-rpi-transport

SPI client: v0.1

Commit 7b4cae100136 · Nikin Ikin · 2026-09-28 13:54 +0200

Changeset
7b4cae100136772586ebed399067b52e6cfb30d6

View source at this commit

Comments

No comments yet.

Log in to comment

Diff

diff --git a/e407/p1_basic_template/Makefile b/e407/p1_basic_template/Makefile
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/Makefile
@@ -0,0 +1,212 @@
+# Minimal Makefile for STM32F407 SPI test with SEGGER RTT
+#
+# Toolchain: arm-none-eabi-gcc
+#
+# Uses:
+#  - standalone stm32f4xx-hal-driver repository
+#  - CMSIS device pack for STM32F4
+#  - CMSIS Core
+#  - SEGGER RTT
+
+HAL_REPO            ?= stm32f4xx-hal-driver
+CMSIS_CORE_REPO     ?= cmsis_core
+CMSIS_DEVICE_F4_REPO ?= cmsis_device_f4
+
+HAL_DIR    := $(HAL_REPO)
+CMSIS_CORE := $(CMSIS_CORE_REPO)/CMSIS/Core
+CMSIS_DEV  := $(CMSIS_DEVICE_F4_REPO)
+
+CC      := arm-none-eabi-gcc
+AS      := arm-none-eabi-gcc
+OBJCOPY := arm-none-eabi-objcopy
+SIZE    := arm-none-eabi-size
+
+TARGET  := bootloader
+BUILD   := build
+
+APP_OBJDIR   := $(BUILD)/app
+RTT_OBJDIR   := $(BUILD)/rtt
+HAL_OBJDIR   := $(BUILD)/hal
+CMSIS_OBJDIR := $(BUILD)/cmsis
+
+CFLAGS := -mcpu=cortex-m4 \
+          -mthumb \
+          -O0 \
+          -g3 \
+          -ffunction-sections \
+          -fdata-sections \
+          -Wall \
+          -Wextra \
+          -Wno-unused-parameter \
+          -std=gnu11 \
+          -DSTM32F407xx \
+          -DUSE_HAL_DRIVER \
+	  -DUSER_VECT_TAB_ADDRESS \
+	  -DVECT_TAB_SRAM
+
+INCLUDES := -Iinclude \
+            -Iinc \
+            -Ihal_conf \
+            -IRTT \
+            -I$(HAL_DIR)/Inc \
+            -I$(CMSIS_CORE)/Include \
+            -I$(CMSIS_DEV)/Include
+
+LDSCRIPT := STM32F417IG_SRAM.ld
+
+LDFLAGS := -T$(LDSCRIPT) \
+           -Wl,--gc-sections \
+           --specs=nosys.specs
+
+
+# --------------------------------------------------------------------------
+# Sources
+# --------------------------------------------------------------------------
+
+APP_SRCS_C := \
+	src/main.c \
+	src/common.c \
+	src/spi_transport_backend.c
+
+RTT_SRCS_C := \
+	RTT/SEGGER_RTT.c \
+	RTT/SEGGER_RTT_printf.c
+
+HAL_SRCS_C := \
+	$(HAL_DIR)/Src/stm32f4xx_hal.c \
+	$(HAL_DIR)/Src/stm32f4xx_hal_gpio.c \
+	$(HAL_DIR)/Src/stm32f4xx_hal_dma.c \
+        $(HAL_DIR)/Src/stm32f4xx_hal_spi.c \
+	$(HAL_DIR)/Src/stm32f4xx_hal_flash.c \
+	$(HAL_DIR)/Src/stm32f4xx_hal_flash_ex.c \
+	$(HAL_DIR)/Src/stm32f4xx_hal_cortex.c \
+	$(HAL_DIR)/Src/stm32f4xx_hal_rcc.c
+
+CMSIS_SRCS_C := \
+	$(CMSIS_DEV)/Source/Templates/system_stm32f4xx.c
+
+SRCS_S := \
+	src/startup_stm32f40_41xxx.s
+
+
+# --------------------------------------------------------------------------
+# Object files
+# --------------------------------------------------------------------------
+
+APP_OBJS := \
+	$(patsubst src/%.c,$(APP_OBJDIR)/%.o,$(APP_SRCS_C))
+
+RTT_OBJS := \
+	$(patsubst RTT/%.c,$(RTT_OBJDIR)/%.o,$(RTT_SRCS_C))
+
+HAL_OBJS := $(addprefix $(HAL_OBJDIR)/,$(notdir $(HAL_SRCS_C:.c=.o)))
+
+CMSIS_OBJS := \
+	$(addprefix $(CMSIS_OBJDIR)/,$(notdir $(CMSIS_SRCS_C:.c=.o)))
+
+STARTUP_OBJS := \
+	$(patsubst %.s,$(BUILD)/%.o,$(SRCS_S))
+
+OBJS := \
+	$(APP_OBJS) \
+	$(RTT_OBJS) \
+	$(HAL_OBJS) \
+	$(CMSIS_OBJS) \
+	$(STARTUP_OBJS)
+
+DEPS := $(OBJS:.o=.d)
+
+
+# --------------------------------------------------------------------------
+# Targets
+# --------------------------------------------------------------------------
+
+.PHONY: all clean size
+
+all: $(BUILD)/$(TARGET).elf \
+     $(BUILD)/$(TARGET).bin \
+     size
+
+
+# --------------------------------------------------------------------------
+# Application
+# --------------------------------------------------------------------------
+
+$(APP_OBJDIR)/%.o: src/%.c
+	@mkdir -p $(dir $@)
+	$(CC) $(CFLAGS) $(INCLUDES) -MMD -MP -c $< -o $@
+
+
+# --------------------------------------------------------------------------
+# SEGGER RTT
+# --------------------------------------------------------------------------
+
+$(RTT_OBJDIR)/%.o: RTT/%.c
+	@mkdir -p $(dir $@)
+	$(CC) $(CFLAGS) $(INCLUDES) -MMD -MP -c $< -o $@
+
+
+# --------------------------------------------------------------------------
+# HAL
+# --------------------------------------------------------------------------
+
+$(HAL_OBJDIR)/%.o: $(HAL_DIR)/Src/%.c
+	@mkdir -p $(dir $@)
+	$(CC) $(CFLAGS) $(INCLUDES) -MMD -MP -c $< -o $@
+
+
+# --------------------------------------------------------------------------
+# CMSIS
+# --------------------------------------------------------------------------
+
+$(CMSIS_OBJDIR)/%.o: $(CMSIS_DEV)/Source/Templates/%.c
+	@mkdir -p $(dir $@)
+	$(CC) $(CFLAGS) $(INCLUDES) -MMD -MP -c $< -o $@
+
+
+# --------------------------------------------------------------------------
+# Startup
+# --------------------------------------------------------------------------
+
+$(BUILD)/%.o: %.s
+	@mkdir -p $(dir $@)
+	$(AS) $(CFLAGS) -c $< -o $@
+
+
+# --------------------------------------------------------------------------
+# Link
+# --------------------------------------------------------------------------
+
+$(BUILD)/$(TARGET).elf: $(OBJS)
+	$(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) -o $@
+
+
+# --------------------------------------------------------------------------
+# Binary
+# --------------------------------------------------------------------------
+
+$(BUILD)/$(TARGET).bin: $(BUILD)/$(TARGET).elf
+	$(OBJCOPY) -O binary $< $@
+
+
+# --------------------------------------------------------------------------
+# Size
+# --------------------------------------------------------------------------
+
+size: $(BUILD)/$(TARGET).elf
+	$(SIZE) $<
+
+
+# --------------------------------------------------------------------------
+# Clean
+# --------------------------------------------------------------------------
+
+clean:
+	rm -rf $(BUILD)
+
+
+# --------------------------------------------------------------------------
+# Dependencies
+# --------------------------------------------------------------------------
+
+-include $(DEPS)
diff --git a/e407/p1_basic_template/RTT b/e407/p1_basic_template/RTT
new file mode 120000
--- /dev/null
+++ b/e407/p1_basic_template/RTT
@@ -0,0 +1,1 @@
+SEGGER_RTT_V614b/RTT
\ No newline at end of file
diff --git a/e407/p1_basic_template/SEGGER_RTT_V614b/Examples/Main_RTT_InputEchoApp.c b/e407/p1_basic_template/SEGGER_RTT_V614b/Examples/Main_RTT_InputEchoApp.c
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/SEGGER_RTT_V614b/Examples/Main_RTT_InputEchoApp.c
@@ -0,0 +1,43 @@
+/*********************************************************************
+*               SEGGER MICROCONTROLLER GmbH & Co. KG                 *
+*       Solutions for real time microcontroller applications         *
+**********************************************************************
+*                                                                    *
+*       (c) 2014 - 2015  SEGGER Microcontroller GmbH & Co. KG        *
+*                                                                    *
+*       www.segger.com     Support: [email protected]               *
+*                                                                    *
+**********************************************************************
+
+--------- END-OF-HEADER --------------------------------------------
+File    : Main_RTT_MenuApp.c
+Purpose : Sample application to demonstrate RTT bi-directional functionality
+*/
+
+#define MAIN_C
+
+#include <stdio.h>
+
+#include "SEGGER_RTT.h"
+
+volatile int _Cnt;
+volatile int _Delay;
+
+static char r;
+
+/*********************************************************************
+*
+*       main
+*/
+void main(void) {
+
+  SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n");
+  SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
+  do {
+    r = SEGGER_RTT_WaitKey();
+    SEGGER_RTT_Write(0, &r, 1);
+    r++;
+  } while (1);
+}
+
+/*************************** End of file ****************************/
diff --git a/e407/p1_basic_template/SEGGER_RTT_V614b/Examples/Main_RTT_MenuApp.c b/e407/p1_basic_template/SEGGER_RTT_V614b/Examples/Main_RTT_MenuApp.c
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/SEGGER_RTT_V614b/Examples/Main_RTT_MenuApp.c
@@ -0,0 +1,70 @@
+/*********************************************************************
+*               SEGGER MICROCONTROLLER GmbH & Co. KG                 *
+*       Solutions for real time microcontroller applications         *
+**********************************************************************
+*                                                                    *
+*       (c) 2014 - 2015  SEGGER Microcontroller GmbH & Co. KG        *
+*                                                                    *
+*       www.segger.com     Support: [email protected]               *
+*                                                                    *
+**********************************************************************
+--------- END-OF-HEADER --------------------------------------------
+File    : Main_RTT_MenuApp.c
+Purpose : Sample application to demonstrate RTT bi-directional functionality
+*/
+
+#define MAIN_C
+
+#include <stdio.h>
+
+#include "SEGGER_RTT.h"
+
+volatile int _Cnt;
+volatile int _Delay;
+
+/*********************************************************************
+*
+*       main
+*/
+void main(void) {
+  int r;
+  int CancelOp;
+
+  do {
+    _Cnt = 0;
+
+    SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n");
+    SEGGER_RTT_WriteString(0, "Press <1> to continue in blocking mode (Application waits if necessary, no data lost)\r\n");
+    SEGGER_RTT_WriteString(0, "Press <2> to continue in non-blocking mode (Application does not wait, data lost if fifo full)\r\n");
+    do {
+      r = SEGGER_RTT_WaitKey();
+    } while ((r != '1') && (r != '2'));
+    if (r == '1') {
+      SEGGER_RTT_WriteString(0, "\r\nSelected <1>. Configuring RTT and starting...\r\n");
+      SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL);
+    } else {
+      SEGGER_RTT_WriteString(0, "\r\nSelected <2>. Configuring RTT and starting...\r\n");
+      SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
+    }
+    CancelOp = 0;
+    do {
+      //for (_Delay = 0; _Delay < 10000; _Delay++);
+      SEGGER_RTT_printf(0, "Count: %d. Press <Space> to get back to menu.\r\n", _Cnt++);
+      r = SEGGER_RTT_HasKey();
+      if (r) {
+        CancelOp = (SEGGER_RTT_GetKey() == ' ') ? 1 : 0;
+      }
+      //
+      // Check if user selected to cancel the current operation
+      //
+      if (CancelOp) {
+        SEGGER_RTT_WriteString(0, "Operation cancelled, going back to menu...\r\n");
+        break;
+      }
+    } while (1);
+    SEGGER_RTT_GetKey();
+    SEGGER_RTT_WriteString(0, "\r\n");
+  } while (1);
+}
+
+/*************************** End of file ****************************/
diff --git a/e407/p1_basic_template/SEGGER_RTT_V614b/Examples/Main_RTT_PrintfTest.c b/e407/p1_basic_template/SEGGER_RTT_V614b/Examples/Main_RTT_PrintfTest.c
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/SEGGER_RTT_V614b/Examples/Main_RTT_PrintfTest.c
@@ -0,0 +1,118 @@
+/*********************************************************************
+*               SEGGER MICROCONTROLLER GmbH & Co. KG                 *
+*       Solutions for real time microcontroller applications         *
+**********************************************************************
+*                                                                    *
+*       (c) 2014 - 2015  SEGGER Microcontroller GmbH & Co. KG        *
+*                                                                    *
+*       www.segger.com     Support: [email protected]               *
+*                                                                    *
+**********************************************************************
+
+--------- END-OF-HEADER --------------------------------------------
+File    : Main_RTT_MenuApp.c
+Purpose : Sample application to demonstrate RTT bi-directional functionality
+*/
+
+#define MAIN_C
+
+#include <stdio.h>
+
+#include "SEGGER_RTT.h"
+
+volatile int _Cnt;
+
+/*********************************************************************
+*
+*       main
+*/
+void main(void) {
+
+  SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL);
+
+  SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n\r\n");
+  SEGGER_RTT_WriteString(0, "###### Testing SEGGER_printf() ######\r\n");
+
+  SEGGER_RTT_printf(0, "printf Test: %%c,         'S' : %c.\r\n", 'S');
+  SEGGER_RTT_printf(0, "printf Test: %%5c,        'E' : %5c.\r\n", 'E');
+  SEGGER_RTT_printf(0, "printf Test: %%-5c,       'G' : %-5c.\r\n", 'G');
+  SEGGER_RTT_printf(0, "printf Test: %%5.3c,      'G' : %-5c.\r\n", 'G');
+  SEGGER_RTT_printf(0, "printf Test: %%.3c,       'E' : %-5c.\r\n", 'E');
+  SEGGER_RTT_printf(0, "printf Test: %%c,         'R' : %c.\r\n", 'R');
+
+  SEGGER_RTT_printf(0, "printf Test: %%s,      \"RTT\" : %s.\r\n", "RTT");
+  SEGGER_RTT_printf(0, "printf Test: %%s, \"RTT\\r\\nRocks.\" : %s.\r\n", "RTT\r\nRocks.");
+
+  SEGGER_RTT_printf(0, "printf Test: %%u,       12345 : %u.\r\n", 12345);
+  SEGGER_RTT_printf(0, "printf Test: %%+u,      12345 : %+u.\r\n", 12345);
+  SEGGER_RTT_printf(0, "printf Test: %%.3u,     12345 : %.3u.\r\n", 12345);
+  SEGGER_RTT_printf(0, "printf Test: %%.6u,     12345 : %.6u.\r\n", 12345);
+  SEGGER_RTT_printf(0, "printf Test: %%6.3u,    12345 : %6.3u.\r\n", 12345);
+  SEGGER_RTT_printf(0, "printf Test: %%8.6u,    12345 : %8.6u.\r\n", 12345);
+  SEGGER_RTT_printf(0, "printf Test: %%08u,     12345 : %08u.\r\n", 12345);
+  SEGGER_RTT_printf(0, "printf Test: %%08.6u,   12345 : %08.6u.\r\n", 12345);
+  SEGGER_RTT_printf(0, "printf Test: %%0u,      12345 : %0u.\r\n", 12345);
+  SEGGER_RTT_printf(0, "printf Test: %%-.6u,    12345 : %-.6u.\r\n", 12345);
+  SEGGER_RTT_printf(0, "printf Test: %%-6.3u,   12345 : %-6.3u.\r\n", 12345);
+  SEGGER_RTT_printf(0, "printf Test: %%-8.6u,   12345 : %-8.6u.\r\n", 12345);
+  SEGGER_RTT_printf(0, "printf Test: %%-08u,    12345 : %-08u.\r\n", 12345);
+  SEGGER_RTT_printf(0, "printf Test: %%-08.6u,  12345 : %-08.6u.\r\n", 12345);
+  SEGGER_RTT_printf(0, "printf Test: %%-0u,     12345 : %-0u.\r\n", 12345);
+
+  SEGGER_RTT_printf(0, "printf Test: %%u,      -12345 : %u.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%+u,     -12345 : %+u.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%.3u,    -12345 : %.3u.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%.6u,    -12345 : %.6u.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%6.3u,   -12345 : %6.3u.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%8.6u,   -12345 : %8.6u.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%08u,    -12345 : %08u.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%08.6u,  -12345 : %08.6u.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%0u,     -12345 : %0u.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%-.6u,   -12345 : %-.6u.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%-6.3u,  -12345 : %-6.3u.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%-8.6u,  -12345 : %-8.6u.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%-08u,   -12345 : %-08u.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%-08.6u, -12345 : %-08.6u.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%-0u,    -12345 : %-0u.\r\n", -12345);
+
+  SEGGER_RTT_printf(0, "printf Test: %%d,      -12345 : %d.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%+d,     -12345 : %+d.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%.3d,    -12345 : %.3d.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%.6d,    -12345 : %.6d.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%6.3d,   -12345 : %6.3d.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%8.6d,   -12345 : %8.6d.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%08d,    -12345 : %08d.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%08.6d,  -12345 : %08.6d.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%0d,     -12345 : %0d.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%-.6d,   -12345 : %-.6d.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%-6.3d,  -12345 : %-6.3d.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%-8.6d,  -12345 : %-8.6d.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%-08d,   -12345 : %-08d.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%-08.6d, -12345 : %-08.6d.\r\n", -12345);
+  SEGGER_RTT_printf(0, "printf Test: %%-0d,    -12345 : %-0d.\r\n", -12345);
+
+  SEGGER_RTT_printf(0, "printf Test: %%x,      0x1234ABC : %x.\r\n", 0x1234ABC);
+  SEGGER_RTT_printf(0, "printf Test: %%+x,     0x1234ABC : %+x.\r\n", 0x1234ABC);
+  SEGGER_RTT_printf(0, "printf Test: %%.3x,    0x1234ABC : %.3x.\r\n", 0x1234ABC);
+  SEGGER_RTT_printf(0, "printf Test: %%.6x,    0x1234ABC : %.6x.\r\n", 0x1234ABC);
+  SEGGER_RTT_printf(0, "printf Test: %%6.3x,   0x1234ABC : %6.3x.\r\n", 0x1234ABC);
+  SEGGER_RTT_printf(0, "printf Test: %%8.6x,   0x1234ABC : %8.6x.\r\n", 0x1234ABC);
+  SEGGER_RTT_printf(0, "printf Test: %%08x,    0x1234ABC : %08x.\r\n", 0x1234ABC);
+  SEGGER_RTT_printf(0, "printf Test: %%08.6x,  0x1234ABC : %08.6x.\r\n", 0x1234ABC);
+  SEGGER_RTT_printf(0, "printf Test: %%0x,     0x1234ABC : %0x.\r\n", 0x1234ABC);
+  SEGGER_RTT_printf(0, "printf Test: %%-.6x,   0x1234ABC : %-.6x.\r\n", 0x1234ABC);
+  SEGGER_RTT_printf(0, "printf Test: %%-6.3x,  0x1234ABC : %-6.3x.\r\n", 0x1234ABC);
+  SEGGER_RTT_printf(0, "printf Test: %%-8.6x,  0x1234ABC : %-8.6x.\r\n", 0x1234ABC);
+  SEGGER_RTT_printf(0, "printf Test: %%-08x,   0x1234ABC : %-08x.\r\n", 0x1234ABC);
+  SEGGER_RTT_printf(0, "printf Test: %%-08.6x, 0x1234ABC : %-08.6x.\r\n", 0x1234ABC);
+  SEGGER_RTT_printf(0, "printf Test: %%-0x,    0x1234ABC : %-0x.\r\n", 0x1234ABC);
+
+  SEGGER_RTT_printf(0, "printf Test: %%p,      &_Cnt      : %p.\r\n", &_Cnt);
+
+  SEGGER_RTT_WriteString(0, "###### SEGGER_printf() Tests done. ######\r\n");
+  do {
+    _Cnt++;
+  } while (1);
+}
+
+/*************************** End of file ****************************/
diff --git a/e407/p1_basic_template/SEGGER_RTT_V614b/Examples/Main_RTT_SpeedTestApp.c b/e407/p1_basic_template/SEGGER_RTT_V614b/Examples/Main_RTT_SpeedTestApp.c
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/SEGGER_RTT_V614b/Examples/Main_RTT_SpeedTestApp.c
@@ -0,0 +1,69 @@
+/*********************************************************************
+*               SEGGER MICROCONTROLLER GmbH & Co. KG                 *
+*       Solutions for real time microcontroller applications         *
+**********************************************************************
+*                                                                    *
+*       (c) 2014 - 2015  SEGGER Microcontroller GmbH & Co. KG        *
+*                                                                    *
+*       www.segger.com     Support: [email protected]               *
+*                                                                    *
+**********************************************************************
+
+--------- END-OF-HEADER --------------------------------------------
+File    : Main_RTT_SpeedTestApp.c
+Purpose : Sample program for measuring RTT performance.
+*/
+
+#include "RTOS.h"
+#include "BSP.h"
+
+#include "SEGGER_RTT.h"
+#include <stdio.h>
+
+OS_STACKPTR int StackHP[128], StackLP[128];          /* Task stacks */
+OS_TASK TCBHP, TCBLP;                        /* Task-control-blocks */
+
+static void HPTask(void) {
+  while (1) {
+    //
+    // Measure time needed for RTT output
+    // Perform dummy write with 0 characters, so we know the overhead of toggling LEDs and RTT in general
+    //
+// Set BP here. Then start sampling on scope
+    BSP_ClrLED(0);
+    SEGGER_RTT_Write(0, 0, 0);
+    BSP_SetLED(0);
+    BSP_ClrLED(0);
+    SEGGER_RTT_Write(0, "01234567890123456789012345678901234567890123456789012345678901234567890123456789\r\n", 82);
+    BSP_SetLED(0);
+// Set BP here. Then stop sampling on scope
+    OS_Delay(200);
+  }
+}
+
+static void LPTask(void) {
+  while (1) {
+    BSP_ToggleLED(1);
+    OS_Delay (500);
+  }
+}
+
+/*********************************************************************
+*
+*       main
+*
+*********************************************************************/
+
+int main(void) {
+  OS_IncDI();                      /* Initially disable interrupts  */
+  OS_InitKern();                   /* Initialize OS                 */
+  OS_InitHW();                     /* Initialize Hardware for OS    */
+  BSP_Init();                      /* Initialize LED ports          */
+  BSP_SetLED(0);
+  /* You need to create at least one task before calling OS_Start() */
+  OS_CREATETASK(&TCBHP, "HP Task", HPTask, 100, StackHP);
+  OS_CREATETASK(&TCBLP, "LP Task", LPTask,  50, StackLP);
+  OS_Start();                      /* Start multitasking            */
+  return 0;
+}
+
diff --git a/e407/p1_basic_template/SEGGER_RTT_V614b/README.txt b/e407/p1_basic_template/SEGGER_RTT_V614b/README.txt
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/SEGGER_RTT_V614b/README.txt
@@ -0,0 +1,20 @@
+README.txt for the SEGGER RTT Implementation Pack.
+
+Included files:
+===============
+Root Directory
+  - Examples
+    - Main_RTT_InputEchoApp.c    - Sample application which echoes input on Channel 0.
+    - Main_RTT_MenuApp.c         - Sample application to demonstrate RTT bi-directional functionality.
+    - Main_RTT_PrintfTest.c      - Sample application to test RTT small printf implementation.
+    - Main_RTT_SpeedTestApp.c    - Sample application for measuring RTT performance. embOS needed.
+  - RTT
+    - SEGGER_RTT.c                - The RTT implementation.
+    - SEGGER_RTT.h                - Header for RTT implementation.
+    - SEGGER_RTT_Conf.h           - Pre-processor configuration for the RTT implementation.
+    - SEGGER_RTT_Printf.c         - Simple implementation of printf to write formatted strings via RTT.
+  - Syscalls
+    - RTT_Syscalls_GCC.c          - Low-level syscalls to retarget printf() to RTT with GCC / Newlib.
+    - RTT_Syscalls_IAR.c          - Low-level syscalls to retarget printf() to RTT with IAR compiler.
+    - RTT_Syscalls_KEIL.c         - Low-level syscalls to retarget printf() to RTT with KEIL/uVision compiler.
+    - RTT_Syscalls_SES.c          - Low-level syscalls to retarget printf() to RTT with SEGGER Embedded Studio.
diff --git a/e407/p1_basic_template/SEGGER_RTT_V614b/RTT/SEGGER_RTT.c b/e407/p1_basic_template/SEGGER_RTT_V614b/RTT/SEGGER_RTT.c
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/SEGGER_RTT_V614b/RTT/SEGGER_RTT.c
@@ -0,0 +1,1453 @@
+/*********************************************************************
+*               SEGGER MICROCONTROLLER GmbH & Co. KG                 *
+*       Solutions for real time microcontroller applications         *
+**********************************************************************
+*                                                                    *
+*       (c) 2014 - 2016  SEGGER Microcontroller GmbH & Co. KG        *
+*                                                                    *
+*       www.segger.com     Support: [email protected]               *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+*       SEGGER RTT * Real Time Transfer for embedded targets         *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+* All rights reserved.                                               *
+*                                                                    *
+* SEGGER strongly recommends to not make any changes                 *
+* to or modify the source code of this software in order to stay     *
+* compatible with the RTT protocol and J-Link.                       *
+*                                                                    *
+* Redistribution and use in source and binary forms, with or         *
+* without modification, are permitted provided that the following    *
+* conditions are met:                                                *
+*                                                                    *
+* o Redistributions of source code must retain the above copyright   *
+*   notice, this list of conditions and the following disclaimer.    *
+*                                                                    *
+* o 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.                                           *
+*                                                                    *
+* o Neither the name of SEGGER Microcontroller GmbH & Co. KG         *
+*   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 SEGGER Microcontroller 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.                                                            *
+*                                                                    *
+**********************************************************************
+---------------------------END-OF-HEADER------------------------------
+File    : SEGGER_RTT.c
+Purpose : Implementation of SEGGER real-time transfer (RTT) which
+          allows real-time communication on targets which support
+          debugger memory accesses while the CPU is running.
+Revision: $Rev: 4351 $
+
+Additional information:
+          Type "int" is assumed to be 32-bits in size
+          H->T    Host to target communication
+          T->H    Target to host communication
+
+          RTT channel 0 is always present and reserved for Terminal usage.
+          Name is fixed to "Terminal"
+
+          Effective buffer size: SizeOfBuffer - 1
+
+          WrOff == RdOff:       Buffer is empty
+          WrOff == (RdOff - 1): Buffer is full
+          WrOff >  RdOff:       Free space includes wrap-around
+          WrOff <  RdOff:       Used space includes wrap-around
+          (WrOff == (SizeOfBuffer - 1)) && (RdOff == 0):  
+                                Buffer full and wrap-around after next byte
+
+
+----------------------------------------------------------------------
+*/
+
+#include "SEGGER_RTT.h"
+
+#include <string.h>                 // for memcpy
+
+/*********************************************************************
+*
+*       Configuration, default values
+*
+**********************************************************************
+*/
+
+#ifndef   BUFFER_SIZE_UP
+  #define BUFFER_SIZE_UP                                  1024  // Size of the buffer for terminal output of target, up to host
+#endif
+
+#ifndef   BUFFER_SIZE_DOWN
+  #define BUFFER_SIZE_DOWN                                16    // Size of the buffer for terminal input to target from host (Usually keyboard input)
+#endif
+
+#ifndef   SEGGER_RTT_MAX_NUM_UP_BUFFERS
+  #define SEGGER_RTT_MAX_NUM_UP_BUFFERS                    2    // Number of up-buffers (T->H) available on this target
+#endif
+
+#ifndef   SEGGER_RTT_MAX_NUM_DOWN_BUFFERS
+  #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS                  2    // Number of down-buffers (H->T) available on this target
+#endif
+
+#ifndef SEGGER_RTT_BUFFER_SECTION
+  #if defined(SEGGER_RTT_SECTION)
+    #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION
+  #endif
+#endif
+
+#ifndef   SEGGER_RTT_ALIGNMENT
+  #define SEGGER_RTT_ALIGNMENT                            0
+#endif
+
+#ifndef   SEGGER_RTT_BUFFER_ALIGNMENT
+  #define SEGGER_RTT_BUFFER_ALIGNMENT                     0
+#endif
+
+#ifndef   SEGGER_RTT_MODE_DEFAULT
+  #define SEGGER_RTT_MODE_DEFAULT                         SEGGER_RTT_MODE_NO_BLOCK_SKIP
+#endif
+
+#ifndef   SEGGER_RTT_LOCK
+  #define SEGGER_RTT_LOCK()
+#endif
+
+#ifndef   SEGGER_RTT_UNLOCK
+  #define SEGGER_RTT_UNLOCK()
+#endif
+
+#ifndef   STRLEN
+  #define STRLEN(a)                                       strlen((a))
+#endif
+
+#ifndef   MEMCPY
+  #define MEMCPY(pDest, pSrc, NumBytes)                   memcpy((pDest), (pSrc), (NumBytes))
+#endif
+
+#ifndef   MIN
+  #define MIN(a, b)         (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef   MAX
+  #define MAX(a, b)         (((a) > (b)) ? (a) : (b))
+#endif
+//
+// For some environments, NULL may not be defined until certain headers are included
+//
+#ifndef NULL
+  #define NULL 0
+#endif
+
+/*********************************************************************
+*
+*       Defines, fixed
+*
+**********************************************************************
+*/
+#if (defined __ICCARM__) || (defined __ICCRX__)
+  #define RTT_PRAGMA(P) _Pragma(#P)
+#endif
+
+#if SEGGER_RTT_ALIGNMENT || SEGGER_RTT_BUFFER_ALIGNMENT
+  #if (defined __GNUC__)
+    #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment)))
+  #elif (defined __ICCARM__) || (defined __ICCRX__)
+    #define PRAGMA(A) _Pragma(#A)
+#define SEGGER_RTT_ALIGN(Var, Alignment) RTT_PRAGMA(data_alignment=Alignment) \
+                                  Var
+  #elif (defined __CC_ARM__)
+    #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment)))
+  #else
+    #error "Alignment not supported for this compiler."
+  #endif
+#else
+  #define SEGGER_RTT_ALIGN(Var, Alignment) Var
+#endif
+
+#if defined(SEGGER_RTT_SECTION) || defined (SEGGER_RTT_BUFFER_SECTION)
+  #if (defined __GNUC__)
+    #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section))) Var
+  #elif (defined __ICCARM__) || (defined __ICCRX__)
+#define SEGGER_RTT_PUT_SECTION(Var, Section) RTT_PRAGMA(location=Section) \
+                                        Var
+  #elif (defined __CC_ARM__)
+    #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section), zero_init))  Var
+  #else
+    #error "Section placement not supported for this compiler."
+  #endif
+#else
+  #define SEGGER_RTT_PUT_SECTION(Var, Section) Var
+#endif
+
+
+#if SEGGER_RTT_ALIGNMENT
+  #define SEGGER_RTT_CB_ALIGN(Var)  SEGGER_RTT_ALIGN(Var, SEGGER_RTT_ALIGNMENT)
+#else
+  #define SEGGER_RTT_CB_ALIGN(Var)  Var
+#endif
+
+#if SEGGER_RTT_BUFFER_ALIGNMENT
+  #define SEGGER_RTT_BUFFER_ALIGN(Var)  SEGGER_RTT_ALIGN(Var, SEGGER_RTT_BUFFER_ALIGNMENT)
+#else
+  #define SEGGER_RTT_BUFFER_ALIGN(Var)  Var
+#endif
+
+
+#if defined(SEGGER_RTT_SECTION)
+  #define SEGGER_RTT_PUT_CB_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_SECTION)
+#else
+  #define SEGGER_RTT_PUT_CB_SECTION(Var) Var
+#endif
+
+#if defined(SEGGER_RTT_BUFFER_SECTION)
+  #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_BUFFER_SECTION)
+#else
+  #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) Var
+#endif
+
+/*********************************************************************
+*
+*       Static const data
+*
+**********************************************************************
+*/
+
+static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+/*********************************************************************
+*
+*       Static data
+*
+**********************************************************************
+*/
+//
+// RTT Control Block and allocate buffers for channel 0
+//
+SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT));
+
+SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer  [BUFFER_SIZE_UP]));
+SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[BUFFER_SIZE_DOWN]));
+
+static char _ActiveTerminal;
+
+/*********************************************************************
+*
+*       Static functions
+*
+**********************************************************************
+*/
+
+/*********************************************************************
+*
+*       _DoInit()
+*
+*  Function description
+*    Initializes the control block an buffers.
+*    May only be called via INIT() to avoid overriding settings.
+*
+*/
+#define INIT()  do {                                            \
+                  if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); }  \
+                } while (0)
+static void _DoInit(void) {
+  SEGGER_RTT_CB* p;
+  //
+  // Initialize control block
+  //
+  p = &_SEGGER_RTT;
+  p->MaxNumUpBuffers    = SEGGER_RTT_MAX_NUM_UP_BUFFERS;
+  p->MaxNumDownBuffers  = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS;
+  //
+  // Initialize up buffer 0
+  //
+  p->aUp[0].sName         = "Terminal";
+  p->aUp[0].pBuffer       = _acUpBuffer;
+  p->aUp[0].SizeOfBuffer  = sizeof(_acUpBuffer);
+  p->aUp[0].RdOff         = 0u;
+  p->aUp[0].WrOff         = 0u;
+  p->aUp[0].Flags         = SEGGER_RTT_MODE_DEFAULT;
+  //
+  // Initialize down buffer 0
+  //
+  p->aDown[0].sName         = "Terminal";
+  p->aDown[0].pBuffer       = _acDownBuffer;
+  p->aDown[0].SizeOfBuffer  = sizeof(_acDownBuffer);
+  p->aDown[0].RdOff         = 0u;
+  p->aDown[0].WrOff         = 0u;
+  p->aDown[0].Flags         = SEGGER_RTT_MODE_DEFAULT;
+  //
+  // Finish initialization of the control block.
+  // Copy Id string in three steps to make sure "SEGGER RTT" is not found
+  // in initializer memory (usually flash) by J-Link
+  //
+  strcpy(&p->acID[7], "RTT");
+  strcpy(&p->acID[0], "SEGGER");
+  p->acID[6] = ' ';
+}
+
+/*********************************************************************
+*
+*       _WriteBlocking()
+*
+*  Function description
+*    Stores a specified number of characters in SEGGER RTT ring buffer
+*    and updates the associated write pointer which is periodically
+*    read by the host.
+*    The caller is responsible for managing the write chunk sizes as
+*    _WriteBlocking() will block until all data has been posted successfully.
+*
+*  Parameters
+*    pRing        Ring buffer to post to.
+*    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
+*    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
+*
+*  Return value
+*    >= 0 - Number of bytes written into buffer.
+*/
+static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) {
+  unsigned NumBytesToWrite;
+  unsigned NumBytesWritten;
+  unsigned RdOff;
+  unsigned WrOff;
+  //
+  // Write data to buffer and handle wrap-around if necessary
+  //
+  NumBytesWritten = 0u;
+  WrOff = pRing->WrOff;
+  do {
+    RdOff = pRing->RdOff;                         // May be changed by host (debug probe) in the meantime
+    if (RdOff > WrOff) {
+      NumBytesToWrite = RdOff - WrOff - 1u;
+    } else {
+      NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u);
+    }
+    NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff));      // Number of bytes that can be written until buffer wrap-around
+    NumBytesToWrite = MIN(NumBytesToWrite, NumBytes);
+    memcpy(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite);
+    NumBytesWritten += NumBytesToWrite;
+    pBuffer         += NumBytesToWrite;
+    NumBytes        -= NumBytesToWrite;
+    WrOff           += NumBytesToWrite;
+    if (WrOff == pRing->SizeOfBuffer) {
+      WrOff = 0u;
+    }
+    pRing->WrOff = WrOff;
+  } while (NumBytes);
+  //
+  return NumBytesWritten;
+}
+
+/*********************************************************************
+*
+*       _WriteNoCheck()
+*
+*  Function description
+*    Stores a specified number of characters in SEGGER RTT ring buffer
+*    and updates the associated write pointer which is periodically
+*    read by the host.
+*    It is callers responsibility to make sure data actually fits in buffer.
+*
+*  Parameters
+*    pRing        Ring buffer to post to.
+*    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
+*    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
+*
+*  Notes
+*    (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking
+*/
+static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) {
+  unsigned NumBytesAtOnce;
+  unsigned WrOff;
+  unsigned Rem;
+
+  WrOff = pRing->WrOff;
+  Rem = pRing->SizeOfBuffer - WrOff;
+  if (Rem > NumBytes) {
+    //
+    // All data fits before wrap around
+    //
+    memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
+    pRing->WrOff = WrOff + NumBytes;
+  } else {
+    //
+    // We reach the end of the buffer, so need to wrap around
+    //
+    NumBytesAtOnce = Rem;
+    memcpy(pRing->pBuffer + WrOff, pData, NumBytesAtOnce);
+    NumBytesAtOnce = NumBytes - Rem;
+    memcpy(pRing->pBuffer, pData + Rem, NumBytesAtOnce);
+    pRing->WrOff = NumBytesAtOnce;
+  }
+}
+
+/*********************************************************************
+*
+*       _PostTerminalSwitch()
+*
+*  Function description
+*    Switch terminal to the given terminal ID.  It is the caller's
+*    responsibility to ensure the terminal ID is correct and there is
+*    enough space in the buffer for this to complete successfully.
+*
+*  Parameters
+*    pRing        Ring buffer to post to.
+*    TerminalId   Terminal ID to switch to.
+*/
+static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) {
+  char ac[2];
+
+  ac[0] = 0xFFu;
+  ac[1] = _aTerminalId[TerminalId];  // Caller made already sure that TerminalId does not exceed our terminal limit
+  _WriteBlocking(pRing, ac, 2u);
+}
+
+/*********************************************************************
+*
+*       _GetAvailWriteSpace()
+*
+*  Function description
+*    Returns the number of bytes that can be written to the ring
+*    buffer without blocking.
+*
+*  Parameters
+*    pRing        Ring buffer to check.
+*
+*  Return value
+*    Number of bytes that are free in the buffer.
+*/
+static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) {
+  unsigned RdOff;
+  unsigned WrOff;
+  unsigned r;
+  //
+  // Avoid warnings regarding volatile access order.  It's not a problem
+  // in this case, but dampen compiler enthusiasm.
+  //
+  RdOff = pRing->RdOff;
+  WrOff = pRing->WrOff;
+  if (RdOff <= WrOff) {
+    r = pRing->SizeOfBuffer - 1u - WrOff + RdOff;
+  } else {
+    r = RdOff - WrOff - 1u;
+  }
+  return r;
+}
+
+/*********************************************************************
+*
+*       Public code
+*
+**********************************************************************
+*/
+/*********************************************************************
+*
+*       SEGGER_RTT_ReadNoLock()
+*
+*  Function description
+*    Reads characters from SEGGER real-time-terminal control block
+*    which have been previously stored by the host.
+*    Do not lock against interrupts and multiple access.
+*
+*  Parameters
+*    BufferIndex  Index of Down-buffer to be used (e.g. 0 for "Terminal").
+*    pBuffer      Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
+*    BufferSize   Size of the target application buffer.
+*
+*  Return value
+*    Number of bytes that have been read.
+*/
+unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) {
+  unsigned                NumBytesRem;
+  unsigned                NumBytesRead;
+  unsigned                RdOff;
+  unsigned                WrOff;
+  unsigned char*          pBuffer;
+  SEGGER_RTT_BUFFER_DOWN* pRing;
+  //
+  INIT();
+  pRing = &_SEGGER_RTT.aDown[BufferIndex];
+  pBuffer = (unsigned char*)pData;
+  RdOff = pRing->RdOff;
+  WrOff = pRing->WrOff;
+  NumBytesRead = 0u;
+  //
+  // Read from current read position to wrap-around of buffer, first
+  //
+  if (RdOff > WrOff) {
+    NumBytesRem = pRing->SizeOfBuffer - RdOff;
+    NumBytesRem = MIN(NumBytesRem, BufferSize);
+    memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
+    NumBytesRead += NumBytesRem;
+    pBuffer      += NumBytesRem;
+    BufferSize   -= NumBytesRem;
+    RdOff        += NumBytesRem;
+    //
+    // Handle wrap-around of buffer
+    //
+    if (RdOff == pRing->SizeOfBuffer) {
+      RdOff = 0u;
+    }
+  }
+  //
+  // Read remaining items of buffer
+  //
+  NumBytesRem = WrOff - RdOff;
+  NumBytesRem = MIN(NumBytesRem, BufferSize);
+  if (NumBytesRem > 0u) {
+    memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
+    NumBytesRead += NumBytesRem;
+    pBuffer      += NumBytesRem;
+    BufferSize   -= NumBytesRem;
+    RdOff        += NumBytesRem;
+  }
+  if (NumBytesRead) {
+    pRing->RdOff = RdOff;
+  }
+  //
+  return NumBytesRead;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_Read
+*
+*  Function description
+*    Reads characters from SEGGER real-time-terminal control block
+*    which have been previously stored by the host.
+*
+*  Parameters
+*    BufferIndex  Index of Down-buffer to be used (e.g. 0 for "Terminal").
+*    pBuffer      Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
+*    BufferSize   Size of the target application buffer.
+*
+*  Return value
+*    Number of bytes that have been read.
+*/
+unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) {
+  unsigned NumBytesRead;
+  //
+  SEGGER_RTT_LOCK();
+  //
+  // Call the non-locking read function
+  //
+  NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize);
+  //
+  // Finish up.
+  //
+  SEGGER_RTT_UNLOCK();
+  //
+  return NumBytesRead;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_WriteWithOverwriteNoLock
+*
+*  Function description
+*    Stores a specified number of characters in SEGGER RTT
+*    control block.
+*    SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application 
+*    and overwrites data if the data does not fit into the buffer.
+*
+*  Parameters
+*    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
+*    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
+*    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
+*
+*  Notes
+*    (1) If there is not enough space in the "Up"-buffer, data is overwritten.
+*    (2) For performance reasons this function does not call Init()
+*        and may only be called after RTT has been initialized.
+*        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
+*    (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link 
+*        connection reads RTT data.
+*/
+void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
+  const char*           pData;
+  SEGGER_RTT_BUFFER_UP* pRing;
+  unsigned              Avail;
+
+  pData = (const char *)pBuffer;
+  //
+  // Get "to-host" ring buffer and copy some elements into local variables.
+  //
+  pRing = &_SEGGER_RTT.aUp[BufferIndex];
+  //
+  // Check if we will overwrite data and need to adjust the RdOff.
+  //
+  if (pRing->WrOff == pRing->RdOff) {
+    Avail = pRing->SizeOfBuffer - 1u;
+  } else if ( pRing->WrOff < pRing->RdOff) {
+    Avail = pRing->RdOff - pRing->WrOff - 1u;
+  } else {
+    Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer;
+  }
+  if (NumBytes > Avail) {
+    pRing->RdOff += (NumBytes - Avail);
+    while (pRing->RdOff >= pRing->SizeOfBuffer) {
+      pRing->RdOff -= pRing->SizeOfBuffer;
+    }
+  }
+  //
+  // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds
+  //
+  Avail = pRing->SizeOfBuffer - pRing->WrOff;
+  do {
+    if (Avail > NumBytes) {
+      //
+      // Last round
+      //
+#if 1 // memcpy() is good for large amounts of data, but the overhead is too big for small amounts. Use a simple byte loop instead.
+      char* pDst;
+      pDst = pRing->pBuffer + pRing->WrOff;
+      pRing->WrOff += NumBytes;
+      do {
+        *pDst++ = *pData++;
+      } while (--NumBytes);
+#else
+      memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
+      pRing->WrOff += NumBytes;
+#endif
+      break;  //Alternatively: NumBytes = 0;
+    } else {
+      //
+      //  Wrap-around necessary, write until wrap-around and reset WrOff
+      //
+      memcpy(pRing->pBuffer + pRing->WrOff, pData, Avail);
+      pData += Avail;
+      pRing->WrOff = 0;
+      NumBytes -= Avail;
+      Avail = (pRing->SizeOfBuffer - 1);
+    }
+  } while (NumBytes);
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_WriteSkipNoLock
+*
+*  Function description
+*    Stores a specified number of characters in SEGGER RTT
+*    control block which is then read by the host.
+*    SEGGER_RTT_WriteSkipNoLock does not lock the application and
+*    skips all data, if the data does not fit into the buffer.
+*
+*  Parameters
+*    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
+*    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
+*    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
+*
+*  Return value
+*    Number of bytes which have been stored in the "Up"-buffer.
+*
+*  Notes
+*    (1) If there is not enough space in the "Up"-buffer, all data is dropped.
+*    (2) For performance reasons this function does not call Init()
+*        and may only be called after RTT has been initialized.
+*        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
+*/
+unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
+  const char*           pData;
+  SEGGER_RTT_BUFFER_UP* pRing;
+  unsigned              Avail;
+  unsigned              RdOff;
+  unsigned              WrOff;
+  unsigned              Rem;
+
+  pData = (const char *)pBuffer;
+  //
+  // Get "to-host" ring buffer and copy some elements into local variables.
+  //
+  pRing = &_SEGGER_RTT.aUp[BufferIndex];
+  RdOff = pRing->RdOff;
+  WrOff = pRing->WrOff;
+  //
+  // Handle the most common cases fastest.
+  // Which is:
+  //    RdOff <= WrOff -> Space until wrap around is free.
+  //  AND
+  //    WrOff + NumBytes < SizeOfBuffer -> No Wrap around necessary.
+  //
+  //  OR
+  //
+  //    RdOff > WrOff -> Space until RdOff - 1 is free.
+  //  AND
+  //    WrOff + NumBytes < RdOff -> Data fits into buffer
+  //
+  if (RdOff <= WrOff) {
+    //
+    // Get space until WrOff will be at wrap around.
+    //
+    Avail = pRing->SizeOfBuffer - 1u - WrOff ;
+    if (Avail >= NumBytes) {
+#if 1 // memcpy() is good for large amounts of data, but the overhead is too big for small amounts. Use a simple byte loop instead.
+      char* pDst;
+      pDst = pRing->pBuffer + WrOff;
+      WrOff += NumBytes;
+      do {
+        *pDst++ = *pData++;
+      } while (--NumBytes);
+      pRing->WrOff = WrOff + NumBytes;
+#else
+      memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
+      pRing->WrOff = WrOff + NumBytes;
+#endif
+      return 1;
+    }
+    //
+    // If data did not fit into space until wrap around calculate complete space in buffer.
+    //
+    Avail += RdOff;
+    //
+    // If there is still no space for the whole of this output, don't bother.
+    //
+    if (Avail >= NumBytes) {
+      //
+      //  OK, we have enough space in buffer. Copy in one or 2 chunks
+      //
+      Rem = pRing->SizeOfBuffer - WrOff;      // Space until end of buffer
+      if (Rem > NumBytes) {
+        memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
+        pRing->WrOff = WrOff + NumBytes;
+      } else {
+        //
+        // We reach the end of the buffer, so need to wrap around
+        //
+        memcpy(pRing->pBuffer + WrOff, pData, Rem);
+        memcpy(pRing->pBuffer, pData + Rem, NumBytes - Rem);
+        pRing->WrOff = NumBytes - Rem;
+      }
+      return 1;
+    }
+  } else {
+    Avail = RdOff - WrOff - 1u;
+    if (Avail >= NumBytes) {
+      memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
+      pRing->WrOff = WrOff + NumBytes;
+      return 1;
+    }
+  }
+  //
+  // If we reach this point no data has been written
+  //
+  return 0;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_WriteNoLock
+*
+*  Function description
+*    Stores a specified number of characters in SEGGER RTT
+*    control block which is then read by the host.
+*    SEGGER_RTT_WriteNoLock does not lock the application.
+*
+*  Parameters
+*    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
+*    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
+*    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
+*
+*  Return value
+*    Number of bytes which have been stored in the "Up"-buffer.
+*
+*  Notes
+*    (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped.
+*    (2) For performance reasons this function does not call Init()
+*        and may only be called after RTT has been initialized.
+*        Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
+*/
+unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
+  unsigned              Status;
+  unsigned              Avail;
+  const char*           pData;
+  SEGGER_RTT_BUFFER_UP* pRing;
+
+  pData = (const char *)pBuffer;
+  //
+  // Get "to-host" ring buffer.
+  //
+  pRing = &_SEGGER_RTT.aUp[BufferIndex];
+  //
+  // How we output depends upon the mode...
+  //
+  switch (pRing->Flags) {
+  case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
+    //
+    // If we are in skip mode and there is no space for the whole
+    // of this output, don't bother.
+    //
+    Avail = _GetAvailWriteSpace(pRing);
+    if (Avail < NumBytes) {
+      Status = 0u;
+    } else {
+      Status = NumBytes;
+      _WriteNoCheck(pRing, pData, NumBytes);
+    }
+    break;
+  case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
+    //
+    // If we are in trim mode, trim to what we can output without blocking.
+    //
+    Avail = _GetAvailWriteSpace(pRing);
+    Status = Avail < NumBytes ? Avail : NumBytes;
+    _WriteNoCheck(pRing, pData, Status);
+    break;
+  case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
+    //
+    // If we are in blocking mode, output everything.
+    //
+    Status = _WriteBlocking(pRing, pData, NumBytes);
+    break;
+  default:
+    Status = 0u;
+    break;
+  }
+  //
+  // Finish up.
+  //
+  return Status;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_Write
+*
+*  Function description
+*    Stores a specified number of characters in SEGGER RTT
+*    control block which is then read by the host.
+*
+*  Parameters
+*    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
+*    pBuffer      Pointer to character array. Does not need to point to a \0 terminated string.
+*    NumBytes     Number of bytes to be stored in the SEGGER RTT control block.
+*
+*  Return value
+*    Number of bytes which have been stored in the "Up"-buffer.
+*
+*  Notes
+*    (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped.
+*/
+unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
+  unsigned Status;
+  //
+  INIT();
+  SEGGER_RTT_LOCK();
+  //
+  // Call the non-locking write function
+  //
+  Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes);
+  //
+  // Finish up.
+  //
+  SEGGER_RTT_UNLOCK();
+  //
+  return Status;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_WriteString
+*
+*  Function description
+*    Stores string in SEGGER RTT control block.
+*    This data is read by the host.
+*
+*  Parameters
+*    BufferIndex  Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
+*    s            Pointer to string.
+*
+*  Return value
+*    Number of bytes which have been stored in the "Up"-buffer.
+*
+*  Notes
+*    (1) If there is not enough space in the "Up"-buffer, depending on configuration,
+*        remaining characters may be dropped or RTT module waits until there is more space in the buffer.
+*    (2) String passed to this function has to be \0 terminated
+*    (3) \0 termination character is *not* stored in RTT buffer
+*/
+unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) {
+  unsigned Len;
+
+  Len = STRLEN(s);
+  return SEGGER_RTT_Write(BufferIndex, s, Len);
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_GetKey
+*
+*  Function description
+*    Reads one character from the SEGGER RTT buffer.
+*    Host has previously stored data there.
+*
+*  Return value
+*    <  0 -   No character available (buffer empty).
+*    >= 0 -   Character which has been read. (Possible values: 0 - 255)
+*
+*  Notes
+*    (1) This function is only specified for accesses to RTT buffer 0.
+*/
+int SEGGER_RTT_GetKey(void) {
+  char c;
+  int r;
+
+  r = (int)SEGGER_RTT_Read(0u, &c, 1u);
+  if (r == 1) {
+    r = (int)(unsigned char)c;
+  } else {
+    r = -1;
+  }
+  return r;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_WaitKey
+*
+*  Function description
+*    Waits until at least one character is avaible in the SEGGER RTT buffer.
+*    Once a character is available, it is read and this function returns.
+*
+*  Return value
+*    >=0 -   Character which has been read.
+*
+*  Notes
+*    (1) This function is only specified for accesses to RTT buffer 0
+*    (2) This function is blocking if no character is present in RTT buffer
+*/
+int SEGGER_RTT_WaitKey(void) {
+  int r;
+
+  do {
+    r = SEGGER_RTT_GetKey();
+  } while (r < 0);
+  return r;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_HasKey
+*
+*  Function description
+*    Checks if at least one character for reading is available in the SEGGER RTT buffer.
+*
+*  Return value
+*    == 0 -     No characters are available to read.
+*    == 1 -     At least one character is available.
+*
+*  Notes
+*    (1) This function is only specified for accesses to RTT buffer 0
+*/
+int SEGGER_RTT_HasKey(void) {
+  unsigned RdOff;
+  int r;
+
+  INIT();
+  RdOff = _SEGGER_RTT.aDown[0].RdOff;
+  if (RdOff != _SEGGER_RTT.aDown[0].WrOff) {
+    r = 1;
+  } else {
+    r = 0;
+  }
+  return r;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_HasData
+*
+*  Function description
+*    Check if there is data from the host in the given buffer.
+*
+*  Return value:
+*  ==0:  No data
+*  !=0:  Data in buffer
+*
+*/
+unsigned SEGGER_RTT_HasData(unsigned BufferIndex) {
+  SEGGER_RTT_BUFFER_DOWN* pRing;
+  unsigned                v;
+
+  pRing = &_SEGGER_RTT.aDown[BufferIndex];
+  v = pRing->WrOff;
+  return v - pRing->RdOff;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_AllocDownBuffer
+*
+*  Function description
+*    Run-time configuration of the next down-buffer (H->T).
+*    The next buffer, which is not used yet is configured.
+*    This includes: Buffer address, size, name, flags, ...
+*
+*  Parameters
+*    sName        Pointer to a constant name string.
+*    pBuffer      Pointer to a buffer to be used.
+*    BufferSize   Size of the buffer.
+*    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
+*
+*  Return value
+*    >= 0 - O.K. Buffer Index
+*     < 0 - Error
+*/
+int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
+  int BufferIndex;
+
+  INIT();
+  SEGGER_RTT_LOCK();
+  BufferIndex = 0;
+  do {
+    if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) {
+      break;
+    }
+    BufferIndex++;
+  } while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers);
+  if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) {
+    _SEGGER_RTT.aDown[BufferIndex].sName        = sName;
+    _SEGGER_RTT.aDown[BufferIndex].pBuffer      = (char*)pBuffer;
+    _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
+    _SEGGER_RTT.aDown[BufferIndex].RdOff        = 0u;
+    _SEGGER_RTT.aDown[BufferIndex].WrOff        = 0u;
+    _SEGGER_RTT.aDown[BufferIndex].Flags        = Flags;
+  } else {
+    BufferIndex = -1;
+  }
+  SEGGER_RTT_UNLOCK();
+  return BufferIndex;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_AllocUpBuffer
+*
+*  Function description
+*    Run-time configuration of the next up-buffer (T->H).
+*    The next buffer, which is not used yet is configured.
+*    This includes: Buffer address, size, name, flags, ...
+*
+*  Parameters
+*    sName        Pointer to a constant name string.
+*    pBuffer      Pointer to a buffer to be used.
+*    BufferSize   Size of the buffer.
+*    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
+*
+*  Return value
+*    >= 0 - O.K. Buffer Index
+*     < 0 - Error
+*/
+int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
+  int BufferIndex;
+
+  INIT();
+  SEGGER_RTT_LOCK();
+  BufferIndex = 0;
+  do {
+    if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) {
+      break;
+    }
+    BufferIndex++;
+  } while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers);
+  if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) {
+    _SEGGER_RTT.aUp[BufferIndex].sName        = sName;
+    _SEGGER_RTT.aUp[BufferIndex].pBuffer      = (char*)pBuffer;
+    _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
+    _SEGGER_RTT.aUp[BufferIndex].RdOff        = 0u;
+    _SEGGER_RTT.aUp[BufferIndex].WrOff        = 0u;
+    _SEGGER_RTT.aUp[BufferIndex].Flags        = Flags;
+  } else {
+    BufferIndex = -1;
+  }
+  SEGGER_RTT_UNLOCK();
+  return BufferIndex;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_ConfigUpBuffer
+*
+*  Function description
+*    Run-time configuration of a specific up-buffer (T->H).
+*    Buffer to be configured is specified by index.
+*    This includes: Buffer address, size, name, flags, ...
+*
+*  Parameters
+*    BufferIndex  Index of the buffer to configure.
+*    sName        Pointer to a constant name string.
+*    pBuffer      Pointer to a buffer to be used.
+*    BufferSize   Size of the buffer.
+*    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
+*
+*  Return value
+*    >= 0 - O.K.
+*     < 0 - Error
+*
+*  Additional information
+*    Buffer 0 is configured on compile-time.
+*    May only be called once per buffer.
+*    Buffer name and flags can be reconfigured using the appropriate functions.
+*/
+int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
+  int r;
+
+  INIT();
+  if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
+    SEGGER_RTT_LOCK();
+    if (BufferIndex > 0u) {
+      _SEGGER_RTT.aUp[BufferIndex].sName        = sName;
+      _SEGGER_RTT.aUp[BufferIndex].pBuffer      = (char*)pBuffer;
+      _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
+      _SEGGER_RTT.aUp[BufferIndex].RdOff        = 0u;
+      _SEGGER_RTT.aUp[BufferIndex].WrOff        = 0u;
+    }
+    _SEGGER_RTT.aUp[BufferIndex].Flags          = Flags;
+    SEGGER_RTT_UNLOCK();
+    r =  0;
+  } else {
+    r = -1;
+  }
+  return r;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_ConfigDownBuffer
+*
+*  Function description
+*    Run-time configuration of a specific down-buffer (H->T).
+*    Buffer to be configured is specified by index.
+*    This includes: Buffer address, size, name, flags, ...
+*
+*  Parameters
+*    BufferIndex  Index of the buffer to configure.
+*    sName        Pointer to a constant name string.
+*    pBuffer      Pointer to a buffer to be used.
+*    BufferSize   Size of the buffer.
+*    Flags        Operating modes. Define behavior if buffer is full (not enough space for entire message).
+*
+*  Return value
+*    >= 0  O.K.
+*     < 0  Error
+*
+*  Additional information
+*    Buffer 0 is configured on compile-time.
+*    May only be called once per buffer.
+*    Buffer name and flags can be reconfigured using the appropriate functions.
+*/
+int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
+  int r;
+
+  INIT();
+  if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
+    SEGGER_RTT_LOCK();
+    if (BufferIndex > 0u) {
+      _SEGGER_RTT.aDown[BufferIndex].sName        = sName;
+      _SEGGER_RTT.aDown[BufferIndex].pBuffer      = (char*)pBuffer;
+      _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
+      _SEGGER_RTT.aDown[BufferIndex].RdOff        = 0u;
+      _SEGGER_RTT.aDown[BufferIndex].WrOff        = 0u;
+    }
+    _SEGGER_RTT.aDown[BufferIndex].Flags          = Flags;
+    SEGGER_RTT_UNLOCK();
+    r =  0;
+  } else {
+    r = -1;
+  }
+  return r;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_SetNameUpBuffer
+*
+*  Function description
+*    Run-time configuration of a specific up-buffer name (T->H).
+*    Buffer to be configured is specified by index.
+*
+*  Parameters
+*    BufferIndex  Index of the buffer to renamed.
+*    sName        Pointer to a constant name string.
+*
+*  Return value
+*    >= 0  O.K.
+*     < 0  Error
+*/
+int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) {
+  int r;
+
+  INIT();
+  if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
+    SEGGER_RTT_LOCK();
+    _SEGGER_RTT.aUp[BufferIndex].sName = sName;
+    SEGGER_RTT_UNLOCK();
+    r =  0;
+  } else {
+    r = -1;
+  }
+  return r;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_SetNameDownBuffer
+*
+*  Function description
+*    Run-time configuration of a specific Down-buffer name (T->H).
+*    Buffer to be configured is specified by index.
+*
+*  Parameters
+*    BufferIndex  Index of the buffer to renamed.
+*    sName        Pointer to a constant name string.
+*
+*  Return value
+*    >= 0  O.K.
+*     < 0  Error
+*/
+int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) {
+  int r;
+
+  INIT();
+  if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
+    SEGGER_RTT_LOCK();
+    _SEGGER_RTT.aDown[BufferIndex].sName = sName;
+    SEGGER_RTT_UNLOCK();
+    r =  0;
+  } else {
+    r = -1;
+  }
+  return r;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_SetFlagsUpBuffer
+*
+*  Function description
+*    Run-time configuration of specific up-buffer flags (T->H).
+*    Buffer to be configured is specified by index.
+*
+*  Parameters
+*    BufferIndex  Index of the buffer.
+*    Flags        Flags to set for the buffer.
+*
+*  Return value
+*    >= 0  O.K.
+*     < 0  Error
+*/
+int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) {
+  int r;
+
+  INIT();
+  if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
+    SEGGER_RTT_LOCK();
+    _SEGGER_RTT.aUp[BufferIndex].Flags = Flags;
+    SEGGER_RTT_UNLOCK();
+    r =  0;
+  } else {
+    r = -1;
+  }
+  return r;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_SetFlagsDownBuffer
+*
+*  Function description
+*    Run-time configuration of specific Down-buffer flags (T->H).
+*    Buffer to be configured is specified by index.
+*
+*  Parameters
+*    BufferIndex  Index of the buffer to renamed.
+*    Flags        Flags to set for the buffer.
+*
+*  Return value
+*    >= 0  O.K.
+*     < 0  Error
+*/
+int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) {
+  int r;
+
+  INIT();
+  if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
+    SEGGER_RTT_LOCK();
+    _SEGGER_RTT.aDown[BufferIndex].Flags = Flags;
+    SEGGER_RTT_UNLOCK();
+    r =  0;
+  } else {
+    r = -1;
+  }
+  return r;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_Init
+*
+*  Function description
+*    Initializes the RTT Control Block.
+*    Should be used in RAM targets, at start of the application.
+*
+*/
+void SEGGER_RTT_Init (void) {
+  _DoInit();
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_SetTerminal
+*
+*  Function description
+*    Sets the terminal to be used for output on channel 0.
+*
+*  Parameters
+*    TerminalId  Index of the terminal.
+*
+*  Return value
+*    >= 0  O.K.
+*     < 0  Error (e.g. if RTT is configured for non-blocking mode and there was no space in the buffer to set the new terminal Id)
+*/
+int SEGGER_RTT_SetTerminal (char TerminalId) {
+  char                  ac[2];
+  SEGGER_RTT_BUFFER_UP* pRing;
+  unsigned Avail;
+  int r;
+  //
+  INIT();
+  //
+  r = 0;
+  ac[0] = 0xFFU;
+  if ((unsigned char)TerminalId < (unsigned char)sizeof(_aTerminalId)) { // We only support a certain number of channels
+    ac[1] = _aTerminalId[(unsigned char)TerminalId];
+    pRing = &_SEGGER_RTT.aUp[0];    // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed
+    SEGGER_RTT_LOCK();    // Lock to make sure that no other task is writing into buffer, while we are and number of free bytes in buffer does not change downwards after checking and before writing
+    if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) {
+      _ActiveTerminal = TerminalId;
+      _WriteBlocking(pRing, ac, 2u);
+    } else {                                                                            // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes
+      Avail = _GetAvailWriteSpace(pRing);
+      if (Avail >= 2) {
+        _ActiveTerminal = TerminalId;    // Only change active terminal in case of success
+        _WriteNoCheck(pRing, ac, 2u);
+      } else {
+        r = -1;
+      }
+    }
+    SEGGER_RTT_UNLOCK();
+  } else {
+    r = -1;
+  }
+  return r;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_TerminalOut
+*
+*  Function description
+*    Writes a string to the given terminal
+*     without changing the terminal for channel 0.
+*
+*  Parameters
+*    TerminalId   Index of the terminal.
+*    s            String to be printed on the terminal.
+*
+*  Return value
+*    >= 0 - Number of bytes written.
+*     < 0 - Error.
+*
+*/
+int SEGGER_RTT_TerminalOut (char TerminalId, const char* s) {
+  int                   Status;
+  unsigned              FragLen;
+  unsigned              Avail;
+  SEGGER_RTT_BUFFER_UP* pRing;
+  //
+  INIT();
+  //
+  // Validate terminal ID.
+  //
+  if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels
+    //
+    // Get "to-host" ring buffer.
+    //
+    pRing = &_SEGGER_RTT.aUp[0];
+    //
+    // Need to be able to change terminal, write data, change back.
+    // Compute the fixed and variable sizes.
+    //
+    FragLen = strlen(s);
+    //
+    // How we output depends upon the mode...
+    //
+    SEGGER_RTT_LOCK();
+    Avail = _GetAvailWriteSpace(pRing);
+    switch (pRing->Flags & SEGGER_RTT_MODE_MASK) {
+    case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
+      //
+      // If we are in skip mode and there is no space for the whole
+      // of this output, don't bother switching terminals at all.
+      //
+      if (Avail < (FragLen + 4u)) {
+        Status = 0;
+      } else {
+        _PostTerminalSwitch(pRing, TerminalId);
+        Status = (int)_WriteBlocking(pRing, s, FragLen);
+        _PostTerminalSwitch(pRing, _ActiveTerminal);
+      }
+      break;
+    case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
+      //
+      // If we are in trim mode and there is not enough space for everything,
+      // trim the output but always include the terminal switch.  If no room
+      // for terminal switch, skip that totally.
+      //
+      if (Avail < 4u) {
+        Status = -1;
+      } else {
+        _PostTerminalSwitch(pRing, TerminalId);
+        Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u));
+        _PostTerminalSwitch(pRing, _ActiveTerminal);
+      }
+      break;
+    case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
+      //
+      // If we are in blocking mode, output everything.
+      //
+      _PostTerminalSwitch(pRing, TerminalId);
+      Status = (int)_WriteBlocking(pRing, s, FragLen);
+      _PostTerminalSwitch(pRing, _ActiveTerminal);
+      break;
+    default:
+      Status = -1;
+      break;
+    }
+    //
+    // Finish up.
+    //
+    SEGGER_RTT_UNLOCK();
+  } else {
+    Status = -1;
+  }
+  return Status;
+}
+
+
+/*************************** End of file ****************************/
diff --git a/e407/p1_basic_template/SEGGER_RTT_V614b/RTT/SEGGER_RTT.h b/e407/p1_basic_template/SEGGER_RTT_V614b/RTT/SEGGER_RTT.h
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/SEGGER_RTT_V614b/RTT/SEGGER_RTT.h
@@ -0,0 +1,244 @@
+/*********************************************************************
+*               SEGGER MICROCONTROLLER GmbH & Co. KG                 *
+*       Solutions for real time microcontroller applications         *
+**********************************************************************
+*                                                                    *
+*       (c) 2014 - 2016  SEGGER Microcontroller GmbH & Co. KG        *
+*                                                                    *
+*       www.segger.com     Support: [email protected]               *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+*       SEGGER RTT * Real Time Transfer for embedded targets         *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+* All rights reserved.                                               *
+*                                                                    *
+* SEGGER strongly recommends to not make any changes                 *
+* to or modify the source code of this software in order to stay     *
+* compatible with the RTT protocol and J-Link.                       *
+*                                                                    *
+* Redistribution and use in source and binary forms, with or         *
+* without modification, are permitted provided that the following    *
+* conditions are met:                                                *
+*                                                                    *
+* o Redistributions of source code must retain the above copyright   *
+*   notice, this list of conditions and the following disclaimer.    *
+*                                                                    *
+* o 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.                                           *
+*                                                                    *
+* o Neither the name of SEGGER Microcontroller GmbH & Co. KG         *
+*   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 SEGGER Microcontroller 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.                                                            *
+*                                                                    *
+**********************************************************************
+---------------------------END-OF-HEADER------------------------------
+File    : SEGGER_RTT.h
+Purpose : Implementation of SEGGER real-time transfer which allows
+          real-time communication on targets which support debugger 
+          memory accesses while the CPU is running.
+Revision: $Rev: 4351 $
+----------------------------------------------------------------------
+*/
+
+#ifndef SEGGER_RTT_H
+#define SEGGER_RTT_H
+
+#include "SEGGER_RTT_Conf.h"
+
+/*********************************************************************
+*
+*       Defines, fixed
+*
+**********************************************************************
+*/
+
+/*********************************************************************
+*
+*       Types
+*
+**********************************************************************
+*/
+
+//
+// Description for a circular buffer (also called "ring buffer")
+// which is used as up-buffer (T->H)
+//
+typedef struct {
+  const     char*    sName;         // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4"
+            char*    pBuffer;       // Pointer to start of buffer
+            unsigned SizeOfBuffer;  // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty.
+            unsigned WrOff;         // Position of next item to be written by either target.
+  volatile  unsigned RdOff;         // Position of next item to be read by host. Must be volatile since it may be modified by host.
+            unsigned Flags;         // Contains configuration flags
+} SEGGER_RTT_BUFFER_UP;
+
+//
+// Description for a circular buffer (also called "ring buffer")
+// which is used as down-buffer (H->T)
+//
+typedef struct {
+  const     char*    sName;         // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4"
+            char*    pBuffer;       // Pointer to start of buffer
+            unsigned SizeOfBuffer;  // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty.
+  volatile  unsigned WrOff;         // Position of next item to be written by host. Must be volatile since it may be modified by host.
+            unsigned RdOff;         // Position of next item to be read by target (down-buffer).
+            unsigned Flags;         // Contains configuration flags
+} SEGGER_RTT_BUFFER_DOWN;
+
+//
+// RTT control block which describes the number of buffers available
+// as well as the configuration for each buffer
+//
+//
+typedef struct {
+  char                    acID[16];                                 // Initialized to "SEGGER RTT"
+  int                     MaxNumUpBuffers;                          // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2)
+  int                     MaxNumDownBuffers;                        // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2)
+  SEGGER_RTT_BUFFER_UP    aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS];       // Up buffers, transferring information up from target via debug probe to host
+  SEGGER_RTT_BUFFER_DOWN  aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS];   // Down buffers, transferring information down from host via debug probe to target
+} SEGGER_RTT_CB;
+
+/*********************************************************************
+*
+*       Global data
+*
+**********************************************************************
+*/
+extern SEGGER_RTT_CB _SEGGER_RTT;
+
+/*********************************************************************
+*
+*       RTT API functions
+*
+**********************************************************************
+*/
+#ifdef __cplusplus
+  extern "C" {
+#endif
+int          SEGGER_RTT_AllocDownBuffer         (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
+int          SEGGER_RTT_AllocUpBuffer           (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
+int          SEGGER_RTT_ConfigUpBuffer          (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
+int          SEGGER_RTT_ConfigDownBuffer        (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
+int          SEGGER_RTT_GetKey                  (void);
+unsigned     SEGGER_RTT_HasData                 (unsigned BufferIndex);
+int          SEGGER_RTT_HasKey                  (void);
+void         SEGGER_RTT_Init                    (void);
+unsigned     SEGGER_RTT_Read                    (unsigned BufferIndex,       void* pBuffer, unsigned BufferSize);
+unsigned     SEGGER_RTT_ReadNoLock              (unsigned BufferIndex,       void* pData,   unsigned BufferSize);
+int          SEGGER_RTT_SetNameDownBuffer       (unsigned BufferIndex, const char* sName);
+int          SEGGER_RTT_SetNameUpBuffer         (unsigned BufferIndex, const char* sName);
+int          SEGGER_RTT_SetFlagsDownBuffer      (unsigned BufferIndex, unsigned Flags);
+int          SEGGER_RTT_SetFlagsUpBuffer        (unsigned BufferIndex, unsigned Flags);
+int          SEGGER_RTT_WaitKey                 (void);
+unsigned     SEGGER_RTT_Write                   (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
+unsigned     SEGGER_RTT_WriteNoLock             (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
+unsigned     SEGGER_RTT_WriteSkipNoLock         (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
+unsigned     SEGGER_RTT_WriteString             (unsigned BufferIndex, const char* s);
+void         SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
+//
+// Function macro for performance optimization
+//
+#define      SEGGER_RTT_HASDATA(n)       (_SEGGER_RTT.aDown[n].WrOff - _SEGGER_RTT.aDown[n].RdOff)
+
+/*********************************************************************
+*
+*       RTT "Terminal" API functions
+*
+**********************************************************************
+*/
+int     SEGGER_RTT_SetTerminal        (char TerminalId);
+int     SEGGER_RTT_TerminalOut        (char TerminalId, const char* s);
+
+/*********************************************************************
+*
+*       RTT printf functions (require SEGGER_RTT_printf.c)
+*
+**********************************************************************
+*/
+int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...);
+#ifdef __cplusplus
+  }
+#endif
+
+/*********************************************************************
+*
+*       Defines
+*
+**********************************************************************
+*/
+
+//
+// Operating modes. Define behavior if buffer is full (not enough space for entire message)
+//
+#define SEGGER_RTT_MODE_NO_BLOCK_SKIP         (0U)     // Skip. Do not block, output nothing. (Default)
+#define SEGGER_RTT_MODE_NO_BLOCK_TRIM         (1U)     // Trim: Do not block, output as much as fits.
+#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL    (2U)     // Block: Wait until there is space in the buffer.
+#define SEGGER_RTT_MODE_MASK                  (3U)
+
+//
+// Control sequences, based on ANSI.
+// Can be used to control color, and clear the screen
+//
+#define RTT_CTRL_RESET                ""         // Reset to default colors
+#define RTT_CTRL_CLEAR                ""         // Clear screen, reposition cursor to top left
+
+#define RTT_CTRL_TEXT_BLACK           ""
+#define RTT_CTRL_TEXT_RED             ""
+#define RTT_CTRL_TEXT_GREEN           ""
+#define RTT_CTRL_TEXT_YELLOW          ""
+#define RTT_CTRL_TEXT_BLUE            ""
+#define RTT_CTRL_TEXT_MAGENTA         ""
+#define RTT_CTRL_TEXT_CYAN            ""
+#define RTT_CTRL_TEXT_WHITE           ""
+
+#define RTT_CTRL_TEXT_BRIGHT_BLACK    ""
+#define RTT_CTRL_TEXT_BRIGHT_RED      ""
+#define RTT_CTRL_TEXT_BRIGHT_GREEN    ""
+#define RTT_CTRL_TEXT_BRIGHT_YELLOW   ""
+#define RTT_CTRL_TEXT_BRIGHT_BLUE     ""
+#define RTT_CTRL_TEXT_BRIGHT_MAGENTA  ""
+#define RTT_CTRL_TEXT_BRIGHT_CYAN     ""
+#define RTT_CTRL_TEXT_BRIGHT_WHITE    ""
+
+#define RTT_CTRL_BG_BLACK             ""
+#define RTT_CTRL_BG_RED               ""
+#define RTT_CTRL_BG_GREEN             ""
+#define RTT_CTRL_BG_YELLOW            ""
+#define RTT_CTRL_BG_BLUE              ""
+#define RTT_CTRL_BG_MAGENTA           ""
+#define RTT_CTRL_BG_CYAN              ""
+#define RTT_CTRL_BG_WHITE             ""
+
+#define RTT_CTRL_BG_BRIGHT_BLACK      ""
+#define RTT_CTRL_BG_BRIGHT_RED        ""
+#define RTT_CTRL_BG_BRIGHT_GREEN      ""
+#define RTT_CTRL_BG_BRIGHT_YELLOW     ""
+#define RTT_CTRL_BG_BRIGHT_BLUE       ""
+#define RTT_CTRL_BG_BRIGHT_MAGENTA    ""
+#define RTT_CTRL_BG_BRIGHT_CYAN       ""
+#define RTT_CTRL_BG_BRIGHT_WHITE      ""
+
+
+#endif
+
+/*************************** End of file ****************************/
diff --git a/e407/p1_basic_template/SEGGER_RTT_V614b/RTT/SEGGER_RTT_Conf.h b/e407/p1_basic_template/SEGGER_RTT_V614b/RTT/SEGGER_RTT_Conf.h
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/SEGGER_RTT_V614b/RTT/SEGGER_RTT_Conf.h
@@ -0,0 +1,292 @@
+/*********************************************************************
+*               SEGGER MICROCONTROLLER GmbH & Co. KG                 *
+*       Solutions for real time microcontroller applications         *
+**********************************************************************
+*                                                                    *
+*       (c) 2014 - 2016  SEGGER Microcontroller GmbH & Co. KG        *
+*                                                                    *
+*       www.segger.com     Support: [email protected]               *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+*       SEGGER RTT * Real Time Transfer for embedded targets         *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+* All rights reserved.                                               *
+*                                                                    *
+* SEGGER strongly recommends to not make any changes                 *
+* to or modify the source code of this software in order to stay     *
+* compatible with the RTT protocol and J-Link.                       *
+*                                                                    *
+* Redistribution and use in source and binary forms, with or         *
+* without modification, are permitted provided that the following    *
+* conditions are met:                                                *
+*                                                                    *
+* o Redistributions of source code must retain the above copyright   *
+*   notice, this list of conditions and the following disclaimer.    *
+*                                                                    *
+* o 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.                                           *
+*                                                                    *
+* o Neither the name of SEGGER Microcontroller GmbH & Co. KG         *
+*   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 SEGGER Microcontroller 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.                                                            *
+*                                                                    *
+**********************************************************************
+---------------------------END-OF-HEADER------------------------------
+File    : SEGGER_RTT_Conf.h
+Purpose : Implementation of SEGGER real-time transfer (RTT) which
+          allows real-time communication on targets which support
+          debugger memory accesses while the CPU is running.
+Revision: $Rev: 5496 $
+----------------------------------------------------------------------
+*/
+
+#ifndef SEGGER_RTT_CONF_H
+#define SEGGER_RTT_CONF_H
+
+#ifdef __IAR_SYSTEMS_ICC__
+  #include <intrinsics.h>
+#endif
+
+/*********************************************************************
+*
+*       Defines, configurable
+*
+**********************************************************************
+*/
+
+#define SEGGER_RTT_MAX_NUM_UP_BUFFERS             (3)     // Max. number of up-buffers (T->H) available on this target    (Default: 3)
+#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS           (3)     // Max. number of down-buffers (H->T) available on this target  (Default: 3)
+
+#define BUFFER_SIZE_UP                            (1024)  // Size of the buffer for terminal output of target, up to host (Default: 1k)
+#define BUFFER_SIZE_DOWN                          (16)    // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16)
+
+#define SEGGER_RTT_PRINTF_BUFFER_SIZE             (64u)    // Size of buffer for RTT printf to bulk-send chars via RTT     (Default: 64)
+
+#define SEGGER_RTT_MODE_DEFAULT                   SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0)
+
+//
+// Target is not allowed to perform other RTT operations while string still has not been stored completely.
+// Otherwise we would probably end up with a mixed string in the buffer.
+// If using  RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here.
+//
+// SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4.
+// Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches.
+// When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly.
+// (Higher priority = lower priority number)
+// Default value for embOS: 128u
+// Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
+// In case of doubt mask all interrupts: 1 << (8 - BASEPRI_PRIO_BITS) i.e. 1 << 5 when 3 bits are implemented in NVIC
+// or define SEGGER_RTT_LOCK() to completely disable interrupts.
+//
+
+#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY         (0x20)   // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20)
+
+/*********************************************************************
+*
+*       RTT lock configuration for SEGGER Embedded Studio,
+*       Rowley CrossStudio and GCC
+*/
+#if (defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__)
+  #ifdef __ARM_ARCH_6M__
+    #define SEGGER_RTT_LOCK()   {                                                                   \
+                                    unsigned int LockState;                                         \
+                                  __asm volatile ("mrs   %0, primask  \n\t"                         \
+                                                  "mov   r1, $1     \n\t"                           \
+                                                  "msr   primask, r1  \n\t"                         \
+                                                  : "=r" (LockState)                                \
+                                                  :                                                 \
+                                                  : "r1"                                            \
+                                                  );
+
+    #define SEGGER_RTT_UNLOCK()   __asm volatile ("msr   primask, %0  \n\t"                         \
+                                                  :                                                 \
+                                                  : "r" (LockState)                                 \
+                                                  :                                                 \
+                                                  );                                                \
+                                }
+
+  #elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__))
+    #ifndef   SEGGER_RTT_MAX_INTERRUPT_PRIORITY
+      #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY   (0x20)
+    #endif
+    #define SEGGER_RTT_LOCK()   {                                                                   \
+                                    unsigned int LockState;                                         \
+                                  __asm volatile ("mrs   %0, basepri  \n\t"                         \
+                                                  "mov   r1, %1       \n\t"                         \
+                                                  "msr   basepri, r1  \n\t"                         \
+                                                  : "=r" (LockState)                                \
+                                                  : "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY)          \
+                                                  : "r1"                                            \
+                                                  );
+
+    #define SEGGER_RTT_UNLOCK()   __asm volatile ("msr   basepri, %0  \n\t"                         \
+                                                  :                                                 \
+                                                  : "r" (LockState)                                 \
+                                                  :                                                 \
+                                                  );                                                \
+                                }
+
+  #elif defined(__ARM_ARCH_7A__)
+    #define SEGGER_RTT_LOCK() {                                                \
+                                 unsigned int LockState;                       \
+                                 __asm volatile ("mrs r1, CPSR \n\t"           \
+                                                 "mov %0, r1 \n\t"             \
+                                                 "orr r1, r1, #0xC0 \n\t"      \
+                                                 "msr CPSR_c, r1 \n\t"         \
+                                                 : "=r" (LockState)            \
+                                                 :                             \
+                                                 : "r1"                        \
+                                                 );
+
+    #define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t"              \
+                                                "mrs r1, CPSR \n\t"            \
+                                                "bic r1, r1, #0xC0 \n\t"       \
+                                                "and r0, r0, #0xC0 \n\t"       \
+                                                "orr r1, r1, r0 \n\t"          \
+                                                "msr CPSR_c, r1 \n\t"          \
+                                                :                              \
+                                                : "r" (LockState)              \
+                                                : "r0", "r1"                   \
+                                                );                             \
+                            }
+#else
+    #define SEGGER_RTT_LOCK()
+    #define SEGGER_RTT_UNLOCK()
+  #endif
+#endif
+
+/*********************************************************************
+*
+*       RTT lock configuration for IAR EWARM
+*/
+#ifdef __ICCARM__
+  #if (defined (__ARM6M__) && (__CORE__ == __ARM6M__))
+    #define SEGGER_RTT_LOCK()   {                                                                   \
+                                  unsigned int LockState;                                           \
+                                  LockState = __get_PRIMASK();                                      \
+                                  __set_PRIMASK(1);
+
+    #define SEGGER_RTT_UNLOCK()   __set_PRIMASK(LockState);                                         \
+                                }
+  #elif ((defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || (defined (__ARM7M__) && (__CORE__ == __ARM7M__)))
+    #ifndef   SEGGER_RTT_MAX_INTERRUPT_PRIORITY
+      #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY   (0x20)
+    #endif
+    #define SEGGER_RTT_LOCK()   {                                                                   \
+                                  unsigned int LockState;                                           \
+                                  LockState = __get_BASEPRI();                                      \
+                                  __set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY);
+
+    #define SEGGER_RTT_UNLOCK()   __set_BASEPRI(LockState);                                         \
+                                }
+  #endif
+#endif
+
+/*********************************************************************
+*
+*       RTT lock configuration for IAR RX
+*/
+#ifdef __ICCRX__
+  #define SEGGER_RTT_LOCK()   {                                                                     \
+                                unsigned long LockState;                                            \
+                                LockState = __get_interrupt_state();                                \
+                                __disable_interrupt();
+
+  #define SEGGER_RTT_UNLOCK()   __set_interrupt_state(LockState);                                   \
+                              }
+#endif
+
+/*********************************************************************
+*
+*       RTT lock configuration for KEIL ARM
+*/
+#ifdef __CC_ARM
+  #if (defined __TARGET_ARCH_6S_M)
+    #define SEGGER_RTT_LOCK()   {                                                                   \
+                                  unsigned int LockState;                                           \
+                                  register unsigned char PRIMASK __asm( "primask");                 \
+                                  LockState = PRIMASK;                                              \
+                                  PRIMASK = 1u;                                                     \
+                                  __schedule_barrier();
+
+    #define SEGGER_RTT_UNLOCK()   PRIMASK = LockState;                                              \
+                                  __schedule_barrier();                                             \
+                                }
+  #elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M))
+    #ifndef   SEGGER_RTT_MAX_INTERRUPT_PRIORITY
+      #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY   (0x20)
+    #endif
+    #define SEGGER_RTT_LOCK()   {                                                                   \
+                                  unsigned int LockState;                                           \
+                                  register unsigned char BASEPRI __asm( "basepri");                 \
+                                  LockState = BASEPRI;                                              \
+                                  BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY;                      \
+                                  __schedule_barrier();
+
+    #define SEGGER_RTT_UNLOCK()   BASEPRI = LockState;                                              \
+                                  __schedule_barrier();                                             \
+                                }
+  #endif
+#endif
+
+/*********************************************************************
+*
+*       RTT lock configuration for TI ARM
+*/
+#ifdef __TI_ARM__
+  #if defined (__TI_ARM_V6M0__)
+    #define SEGGER_RTT_LOCK()   {                                                                   \
+                                  unsigned int LockState;                                           \
+                                  LockState = __get_PRIMASK();                                      \
+                                  __set_PRIMASK(1);
+
+    #define SEGGER_RTT_UNLOCK()   __set_PRIMASK(LockState);                                         \
+                                }
+  #elif (defined (__TI_ARM_V7M3__) || defined (__TI_ARM_V7M4__))
+    #ifndef   SEGGER_RTT_MAX_INTERRUPT_PRIORITY
+      #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY   (0x20)
+    #endif
+    #define SEGGER_RTT_LOCK()   {                                                                   \
+                                  unsigned int LockState;                                           \
+                                  LockState = OS_GetBASEPRI();                                      \
+                                  OS_SetBASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY);
+
+    #define SEGGER_RTT_UNLOCK()   OS_SetBASEPRI(LockState);                                         \
+                                }
+  #endif
+#endif
+
+/*********************************************************************
+*
+*       RTT lock configuration fallback
+*/
+#ifndef   SEGGER_RTT_LOCK
+  #define SEGGER_RTT_LOCK()                // Lock RTT (nestable)   (i.e. disable interrupts)
+#endif
+
+#ifndef   SEGGER_RTT_UNLOCK
+  #define SEGGER_RTT_UNLOCK()              // Unlock RTT (nestable) (i.e. enable previous interrupt lock state)
+#endif
+
+#endif
+/*************************** End of file ****************************/
diff --git a/e407/p1_basic_template/SEGGER_RTT_V614b/RTT/SEGGER_RTT_printf.c b/e407/p1_basic_template/SEGGER_RTT_V614b/RTT/SEGGER_RTT_printf.c
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/SEGGER_RTT_V614b/RTT/SEGGER_RTT_printf.c
@@ -0,0 +1,511 @@
+/*********************************************************************
+*               SEGGER MICROCONTROLLER GmbH & Co. KG                 *
+*       Solutions for real time microcontroller applications         *
+**********************************************************************
+*                                                                    *
+*       (c) 2014 - 2016  SEGGER Microcontroller GmbH & Co. KG        *
+*                                                                    *
+*       www.segger.com     Support: [email protected]               *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+*       SEGGER RTT * Real Time Transfer for embedded targets         *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+* All rights reserved.                                               *
+*                                                                    *
+* SEGGER strongly recommends to not make any changes                 *
+* to or modify the source code of this software in order to stay     *
+* compatible with the RTT protocol and J-Link.                       *
+*                                                                    *
+* Redistribution and use in source and binary forms, with or         *
+* without modification, are permitted provided that the following    *
+* conditions are met:                                                *
+*                                                                    *
+* o Redistributions of source code must retain the above copyright   *
+*   notice, this list of conditions and the following disclaimer.    *
+*                                                                    *
+* o 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.                                           *
+*                                                                    *
+* o Neither the name of SEGGER Microcontroller GmbH & Co. KG         *
+*   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 SEGGER Microcontroller 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.                                                            *
+*                                                                    *
+**********************************************************************
+---------------------------END-OF-HEADER------------------------------
+File    : SEGGER_RTT_printf.c
+Purpose : Replacement for printf to write formatted data via RTT
+Revision: $Rev: 4351 $
+----------------------------------------------------------------------
+*/
+#include "SEGGER_RTT.h"
+#include "SEGGER_RTT_Conf.h"
+
+/*********************************************************************
+*
+*       Defines, configurable
+*
+**********************************************************************
+*/
+
+#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE
+  #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64)
+#endif
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+
+#define FORMAT_FLAG_LEFT_JUSTIFY   (1u << 0)
+#define FORMAT_FLAG_PAD_ZERO       (1u << 1)
+#define FORMAT_FLAG_PRINT_SIGN     (1u << 2)
+#define FORMAT_FLAG_ALTERNATE      (1u << 3)
+
+/*********************************************************************
+*
+*       Types
+*
+**********************************************************************
+*/
+
+typedef struct {
+  char*     pBuffer;
+  unsigned  BufferSize;
+  unsigned  Cnt;
+
+  int   ReturnValue;
+
+  unsigned RTTBufferIndex;
+} SEGGER_RTT_PRINTF_DESC;
+
+/*********************************************************************
+*
+*       Function prototypes
+*
+**********************************************************************
+*/
+int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList);
+
+/*********************************************************************
+*
+*       Static code
+*
+**********************************************************************
+*/
+/*********************************************************************
+*
+*       _StoreChar
+*/
+static void _StoreChar(SEGGER_RTT_PRINTF_DESC * p, char c) {
+  unsigned Cnt;
+
+  Cnt = p->Cnt;
+  if ((Cnt + 1u) <= p->BufferSize) {
+    *(p->pBuffer + Cnt) = c;
+    p->Cnt = Cnt + 1u;
+    p->ReturnValue++;
+  }
+  //
+  // Write part of string, when the buffer is full
+  //
+  if (p->Cnt == p->BufferSize) {
+    if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) {
+      p->ReturnValue = -1;
+    } else {
+      p->Cnt = 0u;
+    }
+  }
+}
+
+/*********************************************************************
+*
+*       _PrintUnsigned
+*/
+static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) {
+  static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+  unsigned Div;
+  unsigned Digit;
+  unsigned Number;
+  unsigned Width;
+  char c;
+
+  Number = v;
+  Digit = 1u;
+  //
+  // Get actual field width
+  //
+  Width = 1u;
+  while (Number >= Base) {
+    Number = (Number / Base);
+    Width++;
+  }
+  if (NumDigits > Width) {
+    Width = NumDigits;
+  }
+  //
+  // Print leading chars if necessary
+  //
+  if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) {
+    if (FieldWidth != 0u) {
+      if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) {
+        c = '0';
+      } else {
+        c = ' ';
+      }
+      while ((FieldWidth != 0u) && (Width < FieldWidth)) {
+        FieldWidth--;
+        _StoreChar(pBufferDesc, c);
+        if (pBufferDesc->ReturnValue < 0) {
+          break;
+        }
+      }
+    }
+  }
+  if (pBufferDesc->ReturnValue >= 0) {
+    //
+    // Compute Digit.
+    // Loop until Digit has the value of the highest digit required.
+    // Example: If the output is 345 (Base 10), loop 2 times until Digit is 100.
+    //
+    while (1) {
+      if (NumDigits > 1u) {       // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned)
+        NumDigits--;
+      } else {
+        Div = v / Digit;
+        if (Div < Base) {        // Is our divider big enough to extract the highest digit from value? => Done
+          break;
+        }
+      }
+      Digit *= Base;
+    }
+    //
+    // Output digits
+    //
+    do {
+      Div = v / Digit;
+      v -= Div * Digit;
+      _StoreChar(pBufferDesc, _aV2C[Div]);
+      if (pBufferDesc->ReturnValue < 0) {
+        break;
+      }
+      Digit /= Base;
+    } while (Digit);
+    //
+    // Print trailing spaces if necessary
+    //
+    if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) {
+      if (FieldWidth != 0u) {
+        while ((FieldWidth != 0u) && (Width < FieldWidth)) {
+          FieldWidth--;
+          _StoreChar(pBufferDesc, ' ');
+          if (pBufferDesc->ReturnValue < 0) {
+            break;
+          }
+        }
+      }
+    }
+  }
+}
+
+/*********************************************************************
+*
+*       _PrintInt
+*/
+static void _PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) {
+  unsigned Width;
+  int Number;
+
+  Number = (v < 0) ? -v : v;
+
+  //
+  // Get actual field width
+  //
+  Width = 1u;
+  while (Number >= (int)Base) {
+    Number = (Number / (int)Base);
+    Width++;
+  }
+  if (NumDigits > Width) {
+    Width = NumDigits;
+  }
+  if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) {
+    FieldWidth--;
+  }
+
+  //
+  // Print leading spaces if necessary
+  //
+  if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) {
+    if (FieldWidth != 0u) {
+      while ((FieldWidth != 0u) && (Width < FieldWidth)) {
+        FieldWidth--;
+        _StoreChar(pBufferDesc, ' ');
+        if (pBufferDesc->ReturnValue < 0) {
+          break;
+        }
+      }
+    }
+  }
+  //
+  // Print sign if necessary
+  //
+  if (pBufferDesc->ReturnValue >= 0) {
+    if (v < 0) {
+      v = -v;
+      _StoreChar(pBufferDesc, '-');
+    } else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) {
+      _StoreChar(pBufferDesc, '+');
+    } else {
+
+    }
+    if (pBufferDesc->ReturnValue >= 0) {
+      //
+      // Print leading zeros if necessary
+      //
+      if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) {
+        if (FieldWidth != 0u) {
+          while ((FieldWidth != 0u) && (Width < FieldWidth)) {
+            FieldWidth--;
+            _StoreChar(pBufferDesc, '0');
+            if (pBufferDesc->ReturnValue < 0) {
+              break;
+            }
+          }
+        }
+      }
+      if (pBufferDesc->ReturnValue >= 0) {
+        //
+        // Print number without sign
+        //
+        _PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags);
+      }
+    }
+  }
+}
+
+/*********************************************************************
+*
+*       Public code
+*
+**********************************************************************
+*/
+/*********************************************************************
+*
+*       SEGGER_RTT_vprintf
+*
+*  Function description
+*    Stores a formatted string in SEGGER RTT control block.
+*    This data is read by the host.
+*
+*  Parameters
+*    BufferIndex  Index of "Up"-buffer to be used. (e.g. 0 for "Terminal")
+*    sFormat      Pointer to format string
+*    pParamList   Pointer to the list of arguments for the format string
+*
+*  Return values
+*    >= 0:  Number of bytes which have been stored in the "Up"-buffer.
+*     < 0:  Error
+*/
+int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) {
+  char c;
+  SEGGER_RTT_PRINTF_DESC BufferDesc;
+  int v;
+  unsigned NumDigits;
+  unsigned FormatFlags;
+  unsigned FieldWidth;
+  char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE];
+
+  BufferDesc.pBuffer        = acBuffer;
+  BufferDesc.BufferSize     = SEGGER_RTT_PRINTF_BUFFER_SIZE;
+  BufferDesc.Cnt            = 0u;
+  BufferDesc.RTTBufferIndex = BufferIndex;
+  BufferDesc.ReturnValue    = 0;
+
+  do {
+    c = *sFormat;
+    sFormat++;
+    if (c == 0u) {
+      break;
+    }
+    if (c == '%') {
+      //
+      // Filter out flags
+      //
+      FormatFlags = 0u;
+      v = 1;
+      do {
+        c = *sFormat;
+        switch (c) {
+        case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break;
+        case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO;     sFormat++; break;
+        case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN;   sFormat++; break;
+        case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE;    sFormat++; break;
+        default:  v = 0; break;
+        }
+      } while (v);
+      //
+      // filter out field with
+      //
+      FieldWidth = 0u;
+      do {
+        c = *sFormat;
+        if ((c < '0') || (c > '9')) {
+          break;
+        }
+        sFormat++;
+        FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0');
+      } while (1);
+
+      //
+      // Filter out precision (number of digits to display)
+      //
+      NumDigits = 0u;
+      c = *sFormat;
+      if (c == '.') {
+        sFormat++;
+        do {
+          c = *sFormat;
+          if ((c < '0') || (c > '9')) {
+            break;
+          }
+          sFormat++;
+          NumDigits = NumDigits * 10u + ((unsigned)c - '0');
+        } while (1);
+      }
+      //
+      // Filter out length modifier
+      //
+      c = *sFormat;
+      do {
+        if ((c == 'l') || (c == 'h')) {
+          sFormat++;
+          c = *sFormat;
+        } else {
+          break;
+        }
+      } while (1);
+      //
+      // Handle specifiers
+      //
+      switch (c) {
+      case 'c': {
+        char c0;
+        v = va_arg(*pParamList, int);
+        c0 = (char)v;
+        _StoreChar(&BufferDesc, c0);
+        break;
+      }
+      case 'd':
+        v = va_arg(*pParamList, int);
+        _PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags);
+        break;
+      case 'u':
+        v = va_arg(*pParamList, int);
+        _PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags);
+        break;
+      case 'x':
+      case 'X':
+        v = va_arg(*pParamList, int);
+        _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags);
+        break;
+      case 's':
+        {
+          const char * s = va_arg(*pParamList, const char *);
+          do {
+            c = *s;
+            s++;
+            if (c == '\0') {
+              break;
+            }
+           _StoreChar(&BufferDesc, c);
+          } while (BufferDesc.ReturnValue >= 0);
+        }
+        break;
+      case 'p':
+        v = va_arg(*pParamList, int);
+        _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u);
+        break;
+      case '%':
+        _StoreChar(&BufferDesc, '%');
+        break;
+      default:
+        break;
+      }
+      sFormat++;
+    } else {
+      _StoreChar(&BufferDesc, c);
+    }
+  } while (BufferDesc.ReturnValue >= 0);
+
+  if (BufferDesc.ReturnValue > 0) {
+    //
+    // Write remaining data, if any
+    //
+    if (BufferDesc.Cnt != 0u) {
+      SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt);
+    }
+    BufferDesc.ReturnValue += (int)BufferDesc.Cnt;
+  }
+  return BufferDesc.ReturnValue;
+}
+
+/*********************************************************************
+*
+*       SEGGER_RTT_printf
+*
+*  Function description
+*    Stores a formatted string in SEGGER RTT control block.
+*    This data is read by the host.
+*
+*  Parameters
+*    BufferIndex  Index of "Up"-buffer to be used. (e.g. 0 for "Terminal")
+*    sFormat      Pointer to format string, followed by the arguments for conversion
+*
+*  Return values
+*    >= 0:  Number of bytes which have been stored in the "Up"-buffer.
+*     < 0:  Error
+*
+*  Notes
+*    (1) Conversion specifications have following syntax:
+*          %[flags][FieldWidth][.Precision]ConversionSpecifier
+*    (2) Supported flags:
+*          -: Left justify within the field width
+*          +: Always print sign extension for signed conversions
+*          0: Pad with 0 instead of spaces. Ignored when using '-'-flag or precision
+*        Supported conversion specifiers:
+*          c: Print the argument as one char
+*          d: Print the argument as a signed integer
+*          u: Print the argument as an unsigned integer
+*          x: Print the argument as an hexadecimal integer
+*          s: Print the string pointed to by the argument
+*          p: Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.)
+*/
+int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...) {
+  int r;
+  va_list ParamList;
+
+  va_start(ParamList, sFormat);
+  r = SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList);
+  va_end(ParamList);
+  return r;
+}
+/*************************** End of file ****************************/
diff --git a/e407/p1_basic_template/SEGGER_RTT_V614b/Syscalls/SEGGER_RTT_Syscalls_GCC.c b/e407/p1_basic_template/SEGGER_RTT_V614b/Syscalls/SEGGER_RTT_Syscalls_GCC.c
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/SEGGER_RTT_V614b/Syscalls/SEGGER_RTT_Syscalls_GCC.c
@@ -0,0 +1,130 @@
+/*********************************************************************
+*               SEGGER MICROCONTROLLER GmbH & Co. KG                 *
+*       Solutions for real time microcontroller applications         *
+**********************************************************************
+*                                                                    *
+*       (c) 2014 - 2016  SEGGER Microcontroller GmbH & Co. KG        *
+*                                                                    *
+*       www.segger.com     Support: [email protected]               *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+*       SEGGER RTT * Real Time Transfer for embedded targets         *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+* All rights reserved.                                               *
+*                                                                    *
+* SEGGER strongly recommends to not make any changes                 *
+* to or modify the source code of this software in order to stay     *
+* compatible with the RTT protocol and J-Link.                       *
+*                                                                    *
+* Redistribution and use in source and binary forms, with or         *
+* without modification, are permitted provided that the following    *
+* conditions are met:                                                *
+*                                                                    *
+* o Redistributions of source code must retain the above copyright   *
+*   notice, this list of conditions and the following disclaimer.    *
+*                                                                    *
+* o 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.                                           *
+*                                                                    *
+* o Neither the name of SEGGER Microcontroller GmbH & Co. KG         *
+*   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 SEGGER Microcontroller 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.                                                            *
+*                                                                    *
+**********************************************************************
+---------------------------END-OF-HEADER------------------------------
+File    : SEGGER_RTT_Syscalls_GCC.c
+Purpose : Low-level functions for using printf() via RTT in GCC.
+          To use RTT for printf output, include this file in your 
+          application.
+Revision: $Rev: 4351 $
+----------------------------------------------------------------------
+*/
+#if (defined __GNUC__) && !(defined __SES_ARM) && !(defined __CROSSWORKS_ARM)
+
+#include <reent.h>  // required for _write_r
+#include "SEGGER_RTT.h"
+
+
+/*********************************************************************
+*
+*       Types
+*
+**********************************************************************
+*/
+//
+// If necessary define the _reent struct 
+// to match the one passed by the used standard library.
+//
+struct _reent;
+
+/*********************************************************************
+*
+*       Function prototypes
+*
+**********************************************************************
+*/
+int _write(int file, char *ptr, int len);
+int _write_r(struct _reent *r, int file, const void *ptr, int len);
+
+/*********************************************************************
+*
+*       Global functions
+*
+**********************************************************************
+*/
+
+/*********************************************************************
+*
+*       _write()
+*
+* Function description
+*   Low-level write function.
+*   libc subroutines will use this system routine for output to all files,
+*   including stdout.
+*   Write data via RTT.
+*/
+int _write(int file, char *ptr, int len) {
+  (void) file;  /* Not used, avoid warning */
+  SEGGER_RTT_Write(0, ptr, len);
+  return len;
+}
+
+/*********************************************************************
+*
+*       _write_r()
+*
+* Function description
+*   Low-level reentrant write function.
+*   libc subroutines will use this system routine for output to all files,
+*   including stdout.
+*   Write data via RTT.
+*/
+int _write_r(struct _reent *r, int file, const void *ptr, int len) {
+  (void) file;  /* Not used, avoid warning */
+  (void) r;     /* Not used, avoid warning */
+  SEGGER_RTT_Write(0, ptr, len);
+  return len;
+}
+
+#endif
+/****** End Of File *************************************************/
diff --git a/e407/p1_basic_template/SEGGER_RTT_V614b/Syscalls/SEGGER_RTT_Syscalls_IAR.c b/e407/p1_basic_template/SEGGER_RTT_V614b/Syscalls/SEGGER_RTT_Syscalls_IAR.c
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/SEGGER_RTT_V614b/Syscalls/SEGGER_RTT_Syscalls_IAR.c
@@ -0,0 +1,115 @@
+/*********************************************************************
+*               SEGGER MICROCONTROLLER GmbH & Co. KG                 *
+*       Solutions for real time microcontroller applications         *
+**********************************************************************
+*                                                                    *
+*       (c) 2014 - 2016  SEGGER Microcontroller GmbH & Co. KG        *
+*                                                                    *
+*       www.segger.com     Support: [email protected]               *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+*       SEGGER RTT * Real Time Transfer for embedded targets         *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+* All rights reserved.                                               *
+*                                                                    *
+* SEGGER strongly recommends to not make any changes                 *
+* to or modify the source code of this software in order to stay     *
+* compatible with the RTT protocol and J-Link.                       *
+*                                                                    *
+* Redistribution and use in source and binary forms, with or         *
+* without modification, are permitted provided that the following    *
+* conditions are met:                                                *
+*                                                                    *
+* o Redistributions of source code must retain the above copyright   *
+*   notice, this list of conditions and the following disclaimer.    *
+*                                                                    *
+* o 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.                                           *
+*                                                                    *
+* o Neither the name of SEGGER Microcontroller GmbH & Co. KG         *
+*   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 SEGGER Microcontroller 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.                                                            *
+*                                                                    *
+**********************************************************************
+---------------------------END-OF-HEADER------------------------------
+File    : SEGGER_RTT_Syscalls_IAR.c
+Purpose : Low-level functions for using printf() via RTT in IAR.
+          To use RTT for printf output, include this file in your 
+          application and set the Library Configuration to Normal.
+Revision: $Rev: 4351 $
+----------------------------------------------------------------------
+*/
+#ifdef __IAR_SYSTEMS_ICC__
+
+#include <yfuns.h>
+#include "SEGGER_RTT.h"
+#pragma module_name = "?__write"
+
+/*********************************************************************
+*
+*       Function prototypes
+*
+**********************************************************************
+*/
+size_t __write(int handle, const unsigned char * buffer, size_t size);
+
+/*********************************************************************
+*
+*       Global functions
+*
+**********************************************************************
+*/
+/*********************************************************************
+*
+*       __write()
+*
+* Function description
+*   Low-level write function.
+*   Standard library subroutines will use this system routine
+*   for output to all files, including stdout.
+*   Write data via RTT.
+*/
+size_t __write(int handle, const unsigned char * buffer, size_t size) {
+  (void) handle;  /* Not used, avoid warning */
+  SEGGER_RTT_Write(0, (const char*)buffer, size);
+  return size;
+}
+
+/*********************************************************************
+*
+*       __write_buffered()
+*
+* Function description
+*   Low-level write function.
+*   Standard library subroutines will use this system routine
+*   for output to all files, including stdout.
+*   Write data via RTT.
+*/
+size_t __write_buffered(int handle, const unsigned char * buffer, size_t size) {
+  (void) handle;  /* Not used, avoid warning */
+  SEGGER_RTT_Write(0, (const char*)buffer, size);
+  return size;
+}
+
+#endif
+/****** End Of File *************************************************/
diff --git a/e407/p1_basic_template/SEGGER_RTT_V614b/Syscalls/SEGGER_RTT_Syscalls_KEIL.c b/e407/p1_basic_template/SEGGER_RTT_V614b/Syscalls/SEGGER_RTT_Syscalls_KEIL.c
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/SEGGER_RTT_V614b/Syscalls/SEGGER_RTT_Syscalls_KEIL.c
@@ -0,0 +1,374 @@
+/*********************************************************************
+*               SEGGER MICROCONTROLLER GmbH & Co. KG                 *
+*       Solutions for real time microcontroller applications         *
+**********************************************************************
+*                                                                    *
+*       (c) 2014 - 2016  SEGGER Microcontroller GmbH & Co. KG        *
+*                                                                    *
+*       www.segger.com     Support: [email protected]               *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+*       SEGGER RTT * Real Time Transfer for embedded targets         *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+* All rights reserved.                                               *
+*                                                                    *
+* SEGGER strongly recommends to not make any changes                 *
+* to or modify the source code of this software in order to stay     *
+* compatible with the RTT protocol and J-Link.                       *
+*                                                                    *
+* Redistribution and use in source and binary forms, with or         *
+* without modification, are permitted provided that the following    *
+* conditions are met:                                                *
+*                                                                    *
+* o Redistributions of source code must retain the above copyright   *
+*   notice, this list of conditions and the following disclaimer.    *
+*                                                                    *
+* o 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.                                           *
+*                                                                    *
+* o Neither the name of SEGGER Microcontroller GmbH & Co. KG         *
+*   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 SEGGER Microcontroller 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.                                                            *
+*                                                                    *
+**********************************************************************
+---------------------------END-OF-HEADER------------------------------
+File    : RTT_Syscalls_KEIL.c
+Purpose : Retargeting module for KEIL MDK-CM3.
+          Low-level functions for using printf() via RTT
+Revision: $Rev: 4351 $
+----------------------------------------------------------------------
+*/
+#ifdef __CC_ARM
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rt_sys.h>
+#include <rt_misc.h>
+
+#include "SEGGER_RTT.h"
+/*********************************************************************
+*
+*       #pragmas
+*
+**********************************************************************
+*/
+#pragma import(__use_no_semihosting)
+
+#ifdef _MICROLIB
+  #pragma import(__use_full_stdio)
+#endif
+
+/*********************************************************************
+*
+*       Defines non-configurable
+*
+**********************************************************************
+*/
+
+/* Standard IO device handles - arbitrary, but any real file system handles must be
+   less than 0x8000. */
+#define STDIN             0x8001    // Standard Input Stream
+#define STDOUT            0x8002    // Standard Output Stream
+#define STDERR            0x8003    // Standard Error Stream
+
+/*********************************************************************
+*
+*       Public const
+*
+**********************************************************************
+*/
+//const char __stdin_name[]  = "STDIN";
+const char __stdout_name[] = "STDOUT";
+const char __stderr_name[] = "STDERR";
+
+/*********************************************************************
+*
+*       Public code
+*
+**********************************************************************
+*/
+
+/*********************************************************************
+*
+*       _ttywrch
+*
+*  Function description:
+*    Outputs a character to the console
+*
+*  Parameters:
+*    c    - character to output
+*  
+*/
+void _ttywrch(int c) {
+  fputc(c, stdout); // stdout
+  fflush(stdout);
+}
+
+/*********************************************************************
+*
+*       _sys_open
+*
+*  Function description:
+*    Opens the device/file in order to do read/write operations
+*
+*  Parameters:
+*    sName        - sName of the device/file to open
+*    OpenMode    - This parameter is currently ignored
+*  
+*  Return value:
+*    != 0     - Handle to the object to open, otherwise 
+*    == 0     -"device" is not handled by this module
+*
+*/
+FILEHANDLE _sys_open(const char * sName, int OpenMode) {
+  (void)OpenMode;
+  // Register standard Input Output devices.
+  if (strcmp(sName, __stdout_name) == 0) {
+    return (STDOUT);
+  } else if (strcmp(sName, __stderr_name) == 0) {
+    return (STDERR);
+  } else
+  return (0);  // Not implemented
+}
+
+/*********************************************************************
+*
+*       _sys_close
+*
+*  Function description:
+*    Closes the handle to the open device/file
+*
+*  Parameters:
+*    hFile    - Handle to a file opened via _sys_open
+*  
+*  Return value:
+*    0     - device/file closed
+*
+*/
+int _sys_close(FILEHANDLE hFile) {
+  (void)hFile;
+  return 0;  // Not implemented
+}
+
+/*********************************************************************
+*
+*       _sys_write
+*
+*  Function description:
+*    Writes the data to an open handle.
+*    Currently this function only outputs data to the console
+*
+*  Parameters:
+*    hFile    - Handle to a file opened via _sys_open
+*    pBuffer  - Pointer to the data that shall be written
+*    NumBytes      - Number of bytes to write
+*    Mode     - The Mode that shall be used
+*  
+*  Return value:
+*    Number of bytes *not* written to the file/device
+*
+*/
+int _sys_write(FILEHANDLE hFile, const unsigned char * pBuffer, unsigned NumBytes, int Mode) {
+  int r = 0;
+
+  (void)Mode;
+  if (hFile == STDOUT) {
+    return NumBytes - SEGGER_RTT_Write(0, (const char*)pBuffer, NumBytes);
+  }
+  return r;
+}
+
+/*********************************************************************
+*
+*       _sys_read
+*
+*  Function description:
+*    Reads data from an open handle.
+*    Currently this modules does nothing.
+*
+*  Parameters:
+*    hFile    - Handle to a file opened via _sys_open
+*    pBuffer  - Pointer to buffer to store the read data
+*    NumBytes      - Number of bytes to read
+*    Mode     - The Mode that shall be used
+*  
+*  Return value:
+*    Number of bytes read from the file/device
+*
+*/
+int _sys_read(FILEHANDLE hFile, unsigned char * pBuffer, unsigned NumBytes, int Mode) {
+  (void)hFile;
+  (void)pBuffer;
+  (void)NumBytes;
+  (void)Mode;
+  return (0);  // Not implemented
+}
+
+/*********************************************************************
+*
+*       _sys_istty
+*
+*  Function description:
+*    This function shall return whether the opened file 
+*    is a console device or not.
+*
+*  Parameters:
+*    hFile    - Handle to a file opened via _sys_open
+*  
+*  Return value:
+*    1       - Device is     a console
+*    0       - Device is not a console
+*
+*/
+int _sys_istty(FILEHANDLE hFile) {
+  if (hFile > 0x8000) {
+    return (1);
+  }
+  return (0);  // Not implemented
+}
+
+/*********************************************************************
+*
+*       _sys_seek
+*
+*  Function description:
+*    Seeks via the file to a specific position
+*
+*  Parameters:
+*    hFile  - Handle to a file opened via _sys_open
+*    Pos    - 
+*  
+*  Return value:
+*    int       - 
+*
+*/
+int _sys_seek(FILEHANDLE hFile, long Pos) {
+  (void)hFile;
+  (void)Pos;
+  return (0);  // Not implemented
+}
+
+/*********************************************************************
+*
+*       _sys_ensure
+*
+*  Function description:
+*    
+*
+*  Parameters:
+*    hFile    - Handle to a file opened via _sys_open
+*  
+*  Return value:
+*    int       - 
+*
+*/
+int _sys_ensure(FILEHANDLE hFile) {
+  (void)hFile;
+  return (-1);  // Not implemented
+}
+
+/*********************************************************************
+*
+*       _sys_flen
+*
+*  Function description:
+*    Returns the length of the opened file handle
+*
+*  Parameters:
+*    hFile    - Handle to a file opened via _sys_open
+*  
+*  Return value:
+*    Length of the file
+*
+*/
+long _sys_flen(FILEHANDLE hFile) {
+  (void)hFile;
+  return (0);  // Not implemented
+}
+
+/*********************************************************************
+*
+*       _sys_tmpnam
+*
+*  Function description:
+*    This function converts the file number fileno for a temporary 
+*    file to a unique filename, for example, tmp0001.
+*
+*  Parameters:
+*    pBuffer    - Pointer to a buffer to store the name
+*    FileNum    - file number to convert
+*    MaxLen     - Size of the buffer
+*  
+*  Return value:
+*     1 - Error
+*     0 - Success  
+*
+*/
+int _sys_tmpnam(char * pBuffer, int FileNum, unsigned MaxLen) {
+  (void)pBuffer;
+  (void)FileNum;
+  (void)MaxLen;
+  return (1);  // Not implemented
+}
+
+/*********************************************************************
+*
+*       _sys_command_string
+*
+*  Function description:
+*    This function shall execute a system command.
+*
+*  Parameters:
+*    cmd    - Pointer to the command string
+*    len    - Length of the string
+*  
+*  Return value:
+*    == NULL - Command was not successfully executed
+*    == sCmd - Command was passed successfully
+*
+*/
+char * _sys_command_string(char * cmd, int len) {
+  (void)len;
+  return cmd;  // Not implemented
+}
+
+/*********************************************************************
+*
+*       _sys_exit
+*
+*  Function description:
+*    This function is called when the application returns from main
+*
+*  Parameters:
+*    ReturnCode    - Return code from the main function
+*  
+*
+*/
+void _sys_exit(int ReturnCode) {
+  (void)ReturnCode;
+  while (1);  // Not implemented
+}
+
+#endif
+/*************************** End of file ****************************/
diff --git a/e407/p1_basic_template/SEGGER_RTT_V614b/Syscalls/SEGGER_RTT_Syscalls_SES.c b/e407/p1_basic_template/SEGGER_RTT_V614b/Syscalls/SEGGER_RTT_Syscalls_SES.c
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/SEGGER_RTT_V614b/Syscalls/SEGGER_RTT_Syscalls_SES.c
@@ -0,0 +1,257 @@
+/*********************************************************************
+*               SEGGER MICROCONTROLLER GmbH & Co. KG                 *
+*       Solutions for real time microcontroller applications         *
+**********************************************************************
+*                                                                    *
+*       (c) 2014 - 2016  SEGGER Microcontroller GmbH & Co. KG        *
+*                                                                    *
+*       www.segger.com     Support: [email protected]               *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+*       SEGGER RTT * Real Time Transfer for embedded targets         *
+*                                                                    *
+**********************************************************************
+*                                                                    *
+* All rights reserved.                                               *
+*                                                                    *
+* SEGGER strongly recommends to not make any changes                 *
+* to or modify the source code of this software in order to stay     *
+* compatible with the RTT protocol and J-Link.                       *
+*                                                                    *
+* Redistribution and use in source and binary forms, with or         *
+* without modification, are permitted provided that the following    *
+* conditions are met:                                                *
+*                                                                    *
+* o Redistributions of source code must retain the above copyright   *
+*   notice, this list of conditions and the following disclaimer.    *
+*                                                                    *
+* o 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.                                           *
+*                                                                    *
+* o Neither the name of SEGGER Microcontroller GmbH & Co. KG         *
+*   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 SEGGER Microcontroller 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.                                                            *
+*                                                                    *
+**********************************************************************
+---------------------------END-OF-HEADER------------------------------
+File    : SEGGER_RTT_Syscalls_SES.c
+Purpose : Reimplementation of printf, puts and __getchar using RTT 
+          in SEGGER Embedded Studio.
+          To use RTT for printf output, include this file in your 
+          application.
+Revision: $Rev: 4351 $
+----------------------------------------------------------------------
+*/
+#if (defined __SES_ARM) || (defined __CROSSWORKS_ARM)
+  
+#include "SEGGER_RTT.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include "limits.h"
+#include "__libc.h"
+#include "__vfprintf.h"
+
+/*********************************************************************
+*
+*       Defines, configurable
+*
+**********************************************************************
+*/
+//
+// Select string formatting implementation.
+//
+// RTT printf formatting
+//  - Configurable stack usage. (SEGGER_RTT_PRINTF_BUFFER_SIZE in SEGGER_RTT_Conf.h)
+//  - No maximum string length.
+//  - Limited conversion specifiers and flags. (See SEGGER_RTT_printf.c)
+// Standard library printf formatting
+//  - Configurable formatting capabilities.
+//  - Full conversion specifier and flag support.
+//  - Maximum string length has to be known or (slightly) slower character-wise output.
+// 
+// #define PRINTF_USE_SEGGER_RTT_FORMATTING    0 // Use standard library formatting
+// #define PRINTF_USE_SEGGER_RTT_FORMATTING    1 // Use RTT formatting
+//
+#ifndef   PRINTF_USE_SEGGER_RTT_FORMATTING
+  #define PRINTF_USE_SEGGER_RTT_FORMATTING    0
+#endif
+//
+// If using standard library formatting, 
+// select maximum output string buffer size or character-wise output.
+//
+// #define PRINTF_BUFFER_SIZE                  0 // Use character-wise output
+// #define PRINTF_BUFFER_SIZE                128 // Default maximum string length
+//
+#ifndef   PRINTF_BUFFER_SIZE
+  #define PRINTF_BUFFER_SIZE                128
+#endif
+
+#if PRINTF_USE_SEGGER_RTT_FORMATTING  // Use SEGGER RTT formatting implementation
+/*********************************************************************
+*
+*       Function prototypes
+*
+**********************************************************************
+*/
+int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList);
+
+/*********************************************************************
+*
+*       Global functions, printf
+*
+**********************************************************************
+*/
+/********************************************************************* 
+*
+*       printf()
+*
+*  Function description
+*    print a formatted string using RTT and SEGGER RTT formatting.
+*/
+int printf(const char *fmt,...) {
+  int     n;
+  va_list args;
+  
+  va_start (args, fmt);
+  n = SEGGER_RTT_vprintf(0, fmt, &args);
+  va_end(args);
+  return n;
+}
+
+#elif PRINTF_BUFFER_SIZE == 0 // Use standard library formatting with character-wise output
+
+/*********************************************************************
+*
+*       Static functions
+*
+**********************************************************************
+*/
+static int _putchar(int x, __printf_tag_ptr ctx) {
+  (void)ctx;
+  SEGGER_RTT_Write(0, (char *)&x, 1);
+  return x;
+}
+
+/*********************************************************************
+*
+*       Global functions, printf
+*
+**********************************************************************
+*/
+/********************************************************************* 
+*
+*       printf()
+*
+*  Function description
+*    print a formatted string character-wise, using RTT and standard 
+*    library formatting.
+*/
+int printf(const char *fmt, ...) {
+  int         n;
+  va_list     args;
+  __printf_t  iod;
+  
+  va_start(args, fmt);
+  iod.string    = 0;
+  iod.maxchars  = INT_MAX;
+  iod.output_fn = _putchar;
+  SEGGER_RTT_LOCK();
+  n = __vfprintf(&iod, fmt, args);
+  SEGGER_RTT_UNLOCK();
+  va_end(args);
+  return n;
+}
+
+#else // Use standard library formatting with static buffer
+
+/*********************************************************************
+*
+*       Global functions, printf
+*
+**********************************************************************
+*/
+/********************************************************************* 
+*
+*       printf()
+*
+*  Function description
+*    print a formatted string using RTT and standard library formatting.
+*/
+int printf(const char *fmt,...) {
+  int     n;
+  char    aBuffer[PRINTF_BUFFER_SIZE];
+  va_list args;
+  
+  va_start (args, fmt);
+  n = vsnprintf(aBuffer, sizeof(aBuffer), fmt, args);
+  if (n > (int)sizeof(aBuffer)) {
+    SEGGER_RTT_Write(0, aBuffer, sizeof(aBuffer));
+  } else if (n > 0) {
+    SEGGER_RTT_Write(0, aBuffer, n);
+  }
+  va_end(args);
+  return n;
+}
+#endif
+
+/*********************************************************************
+*
+*       Global functions
+*
+**********************************************************************
+*/
+/********************************************************************* 
+*
+*       puts()
+*
+*  Function description
+*    print a string using RTT.
+*/
+int puts(const char *s) {
+  return SEGGER_RTT_WriteString(0, s);
+}
+
+/********************************************************************* 
+*
+*       __putchar()
+*
+*  Function description
+*    Write one character via RTT.
+*/
+int __putchar(int x, __printf_tag_ptr ctx) {
+  (void)ctx;
+  SEGGER_RTT_Write(0, (char *)&x, 1);
+  return x;
+}
+
+/********************************************************************* 
+*
+*       __getchar()
+*
+*  Function description
+*    Wait for and get a character via RTT.
+*/
+int __getchar() {
+  return SEGGER_RTT_WaitKey();
+}
+
+#endif
+/****** End Of File *************************************************/
diff --git a/e407/p1_basic_template/STM32F417IG_FLASH.ld b/e407/p1_basic_template/STM32F417IG_FLASH.ld
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/STM32F417IG_FLASH.ld
@@ -0,0 +1,186 @@
+/*
+*****************************************************************************
+**
+**  File        : stm32_flash.ld
+**
+**  Abstract    : Linker script for STM32F417IG Device with
+**                1024KByte FLASH, 128KByte RAM
+**
+**                Set heap size, stack size and stack location according
+**                to application requirements.
+**
+**                Set memory bank area and size if external memory is used.
+**
+**  Target      : STMicroelectronics STM32
+**
+**  Environment : Atollic TrueSTUDIO(R)
+**
+**  Distribution: The file is distributed �as is,� without any warranty
+**                of any kind.
+**
+**  (c)Copyright Atollic AB.
+**  You may use this file as-is or modify it according to the needs of your
+**  project. This file may only be built (assembled or compiled and linked)
+**  using the Atollic TrueSTUDIO(R) product. The use of this file together
+**  with other tools than Atollic TrueSTUDIO(R) is not permitted.
+**
+*****************************************************************************
+*/
+
+/* Entry Point */
+ENTRY(Reset_Handler)
+
+/* Highest address of the user mode stack */
+_estack = 0x2001FFFF;    /* end of RAM */
+
+/* Generate a link error if heap and stack don't fit into RAM */
+_Min_Heap_Size = 0x200;      /* required amount of heap  */
+_Min_Stack_Size = 0x400; /* required amount of stack */
+
+/* Specify the memory areas */
+MEMORY
+{
+FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 1024K
+RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 128K
+CCMRAM (rw)      : ORIGIN = 0x10000000, LENGTH = 64K
+}
+
+/* Define output sections */
+SECTIONS
+{
+  /* The startup code goes first into FLASH */
+  .isr_vector :
+  {
+    . = ALIGN(4);
+    KEEP(*(.isr_vector)) /* Startup code */
+    . = ALIGN(4);
+  } >FLASH
+
+  /* The program code and other data goes into FLASH */
+  .text :
+  {
+    . = ALIGN(4);
+    *(.text)           /* .text sections (code) */
+    *(.text*)          /* .text* sections (code) */
+    *(.glue_7)         /* glue arm to thumb code */
+    *(.glue_7t)        /* glue thumb to arm code */
+    *(.eh_frame)
+
+    KEEP (*(.init))
+    KEEP (*(.fini))
+
+    . = ALIGN(4);
+    _etext = .;        /* define a global symbols at end of code */
+  } >FLASH
+
+  /* Constant data goes into FLASH */
+  .rodata :
+  {
+    . = ALIGN(4);
+    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
+    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
+    . = ALIGN(4);
+  } >FLASH
+
+  .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
+  .ARM : {
+    __exidx_start = .;
+    *(.ARM.exidx*)
+    __exidx_end = .;
+  } >FLASH
+
+  .preinit_array     :
+  {
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP (*(.preinit_array*))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+  } >FLASH
+  .init_array :
+  {
+    PROVIDE_HIDDEN (__init_array_start = .);
+    KEEP (*(SORT(.init_array.*)))
+    KEEP (*(.init_array*))
+    PROVIDE_HIDDEN (__init_array_end = .);
+  } >FLASH
+  .fini_array :
+  {
+    PROVIDE_HIDDEN (__fini_array_start = .);
+    KEEP (*(SORT(.fini_array.*)))
+    KEEP (*(.fini_array*))
+    PROVIDE_HIDDEN (__fini_array_end = .);
+  } >FLASH
+
+  /* used by the startup to initialize data */
+  _sidata = LOADADDR(.data);
+
+  /* Initialized data sections goes into RAM, load LMA copy after code */
+  .data : 
+  {
+    . = ALIGN(4);
+    _sdata = .;        /* create a global symbol at data start */
+    *(.data)           /* .data sections */
+    *(.data*)          /* .data* sections */
+
+    . = ALIGN(4);
+    _edata = .;        /* define a global symbol at data end */
+  } >RAM AT> FLASH
+
+  _siccmram = LOADADDR(.ccmram);
+
+  /* CCM-RAM section 
+  * 
+  * IMPORTANT NOTE! 
+  * If initialized variables will be placed in this section, 
+  * the startup code needs to be modified to copy the init-values.  
+  */
+  .ccmram :
+  {
+    . = ALIGN(4);
+    _sccmram = .;       /* create a global symbol at ccmram start */
+    *(.ccmram)
+    *(.ccmram*)
+    
+    . = ALIGN(4);
+    _eccmram = .;       /* create a global symbol at ccmram end */
+  } >CCMRAM AT> FLASH
+
+  
+  /* Uninitialized data section */
+  . = ALIGN(4);
+  .bss :
+  {
+    /* This is used by the startup in order to initialize the .bss secion */
+    _sbss = .;         /* define a global symbol at bss start */
+    __bss_start__ = _sbss;
+    *(.bss)
+    *(.bss*)
+    *(COMMON)
+
+    . = ALIGN(4);
+    _ebss = .;         /* define a global symbol at bss end */
+    __bss_end__ = _ebss;
+  } >RAM
+
+  /* User_heap_stack section, used to check that there is enough RAM left */
+  ._user_heap_stack :
+  {
+    . = ALIGN(4);
+    PROVIDE ( end = . );
+    PROVIDE ( _end = . );
+    . = . + _Min_Heap_Size;
+    . = . + _Min_Stack_Size;
+    . = ALIGN(4);
+  } >RAM
+
+  
+
+  /* Remove information from the standard libraries */
+  /DISCARD/ :
+  {
+    libc.a ( * )
+    libm.a ( * )
+    libgcc.a ( * )
+  }
+
+  .ARM.attributes 0 : { *(.ARM.attributes) }
+}
diff --git a/e407/p1_basic_template/STM32F417IG_SRAM.ld b/e407/p1_basic_template/STM32F417IG_SRAM.ld
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/STM32F417IG_SRAM.ld
@@ -0,0 +1,186 @@
+/*
+*****************************************************************************
+**
+**  File        : stm32_flash.ld
+**
+**  Abstract    : Linker script for STM32F417IG Device with
+**                1024KByte FLASH, 128KByte RAM
+**
+**                Set heap size, stack size and stack location according
+**                to application requirements.
+**
+**                Set memory bank area and size if external memory is used.
+**
+**  Target      : STMicroelectronics STM32
+**
+**  Environment : Atollic TrueSTUDIO(R)
+**
+**  Distribution: The file is distributed �as is,� without any warranty
+**                of any kind.
+**
+**  (c)Copyright Atollic AB.
+**  You may use this file as-is or modify it according to the needs of your
+**  project. This file may only be built (assembled or compiled and linked)
+**  using the Atollic TrueSTUDIO(R) product. The use of this file together
+**  with other tools than Atollic TrueSTUDIO(R) is not permitted.
+**
+*****************************************************************************
+*/
+
+/* Entry Point */
+ENTRY(Reset_Handler)
+
+/* Highest address of the user mode stack */
+_estack = 0x2001FFFF;    /* end of RAM */
+
+/* Generate a link error if heap and stack don't fit into RAM */
+_Min_Heap_Size = 0x200;      /* required amount of heap  */
+_Min_Stack_Size = 0x400; /* required amount of stack */
+
+/* Specify the memory areas */
+MEMORY
+{
+FLASH (rx)      : ORIGIN = 0x20000000, LENGTH = 64K
+RAM (xrw)      : ORIGIN = 0x2000ffff, LENGTH = 64K
+CCMRAM (rw)      : ORIGIN = 0x10000000, LENGTH = 64K
+}
+
+/* Define output sections */
+SECTIONS
+{
+  /* The startup code goes first into FLASH */
+  .isr_vector :
+  {
+    . = ALIGN(4);
+    KEEP(*(.isr_vector)) /* Startup code */
+    . = ALIGN(4);
+  } >FLASH
+
+  /* The program code and other data goes into FLASH */
+  .text :
+  {
+    . = ALIGN(4);
+    *(.text)           /* .text sections (code) */
+    *(.text*)          /* .text* sections (code) */
+    *(.glue_7)         /* glue arm to thumb code */
+    *(.glue_7t)        /* glue thumb to arm code */
+    *(.eh_frame)
+
+    KEEP (*(.init))
+    KEEP (*(.fini))
+
+    . = ALIGN(4);
+    _etext = .;        /* define a global symbols at end of code */
+  } >FLASH
+
+  /* Constant data goes into FLASH */
+  .rodata :
+  {
+    . = ALIGN(4);
+    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
+    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
+    . = ALIGN(4);
+  } >FLASH
+
+  .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
+  .ARM : {
+    __exidx_start = .;
+    *(.ARM.exidx*)
+    __exidx_end = .;
+  } >FLASH
+
+  .preinit_array     :
+  {
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP (*(.preinit_array*))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+  } >FLASH
+  .init_array :
+  {
+    PROVIDE_HIDDEN (__init_array_start = .);
+    KEEP (*(SORT(.init_array.*)))
+    KEEP (*(.init_array*))
+    PROVIDE_HIDDEN (__init_array_end = .);
+  } >FLASH
+  .fini_array :
+  {
+    PROVIDE_HIDDEN (__fini_array_start = .);
+    KEEP (*(SORT(.fini_array.*)))
+    KEEP (*(.fini_array*))
+    PROVIDE_HIDDEN (__fini_array_end = .);
+  } >FLASH
+
+  /* used by the startup to initialize data */
+  _sidata = LOADADDR(.data);
+
+  /* Initialized data sections goes into RAM, load LMA copy after code */
+  .data : 
+  {
+    . = ALIGN(4);
+    _sdata = .;        /* create a global symbol at data start */
+    *(.data)           /* .data sections */
+    *(.data*)          /* .data* sections */
+
+    . = ALIGN(4);
+    _edata = .;        /* define a global symbol at data end */
+  } >RAM AT> FLASH
+
+  _siccmram = LOADADDR(.ccmram);
+
+  /* CCM-RAM section 
+  * 
+  * IMPORTANT NOTE! 
+  * If initialized variables will be placed in this section, 
+  * the startup code needs to be modified to copy the init-values.  
+  */
+  .ccmram :
+  {
+    . = ALIGN(4);
+    _sccmram = .;       /* create a global symbol at ccmram start */
+    *(.ccmram)
+    *(.ccmram*)
+    
+    . = ALIGN(4);
+    _eccmram = .;       /* create a global symbol at ccmram end */
+  } >CCMRAM AT> FLASH
+
+  
+  /* Uninitialized data section */
+  . = ALIGN(4);
+  .bss :
+  {
+    /* This is used by the startup in order to initialize the .bss secion */
+    _sbss = .;         /* define a global symbol at bss start */
+    __bss_start__ = _sbss;
+    *(.bss)
+    *(.bss*)
+    *(COMMON)
+
+    . = ALIGN(4);
+    _ebss = .;         /* define a global symbol at bss end */
+    __bss_end__ = _ebss;
+  } >RAM
+
+  /* User_heap_stack section, used to check that there is enough RAM left */
+  ._user_heap_stack :
+  {
+    . = ALIGN(4);
+    PROVIDE ( end = . );
+    PROVIDE ( _end = . );
+    . = . + _Min_Heap_Size;
+    . = . + _Min_Stack_Size;
+    . = ALIGN(4);
+  } >RAM
+
+  
+
+  /* Remove information from the standard libraries */
+  /DISCARD/ :
+  {
+    libc.a ( * )
+    libm.a ( * )
+    libgcc.a ( * )
+  }
+
+  .ARM.attributes 0 : { *(.ARM.attributes) }
+}
diff --git a/e407/p1_basic_template/buildenv.sh b/e407/p1_basic_template/buildenv.sh
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/buildenv.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+export PATH=/opt/jlink:/opt/gcc-mcu/bin:$PATH
diff --git a/e407/p1_basic_template/cmsis_core b/e407/p1_basic_template/cmsis_core
new file mode 120000
--- /dev/null
+++ b/e407/p1_basic_template/cmsis_core
@@ -0,0 +1,1 @@
+../../../STM32CubeF4/Drivers
\ No newline at end of file
diff --git a/e407/p1_basic_template/cmsis_device_f4 b/e407/p1_basic_template/cmsis_device_f4
new file mode 120000
--- /dev/null
+++ b/e407/p1_basic_template/cmsis_device_f4
@@ -0,0 +1,1 @@
+../../../cmsis_device_f4
\ No newline at end of file
diff --git a/e407/p1_basic_template/debug.gdb b/e407/p1_basic_template/debug.gdb
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/debug.gdb
@@ -0,0 +1,5 @@
+target remote :2331
+monitor halt
+monitor reset
+load
+c
diff --git a/e407/p1_basic_template/hal_conf/stm32f4xx_hal_conf.h b/e407/p1_basic_template/hal_conf/stm32f4xx_hal_conf.h
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/hal_conf/stm32f4xx_hal_conf.h
@@ -0,0 +1,98 @@
+#ifndef STM32F4xx_HAL_CONF_H
+#define STM32F4xx_HAL_CONF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* --------------------------------------------------------------------------
+ * Core HAL / module selection
+ * -------------------------------------------------------------------------- */
+
+/* Enable HAL driver */
+#define HAL_MODULE_ENABLED
+
+/* Minimum set commonly needed for a bootloader:
+ * - RCC: clocks
+ * - GPIO: pins / LEDs
+ * - FLASH: in-app programming, option bytes etc.
+ * - CORTEX: NVIC/SysTick helpers
+ * - PWR: often required indirectly for clock/voltage scaling setups
+ */
+#define HAL_RCC_MODULE_ENABLED
+#define HAL_GPIO_MODULE_ENABLED
+#define HAL_FLASH_MODULE_ENABLED
+#define HAL_CORTEX_MODULE_ENABLED
+#define HAL_PWR_MODULE_ENABLED
+#define HAL_SPI_MODULE_ENABLED
+#define HAL_DMA_MODULE_ENABLED
+
+/* --------------------------------------------------------------------------
+ * Oscillator values
+ * -------------------------------------------------------------------------- */
+/* Olimex E407 typically has an 12 MHz HSE crystal (adjust if yours differs). */
+#ifndef HSE_VALUE
+#define HSE_VALUE    12000000U
+#endif
+
+#ifndef HSI_VALUE
+#define HSI_VALUE    16000000U
+#endif
+
+/* Optional (not strictly needed unless you use them later) */
+#ifndef LSE_VALUE
+#define LSE_VALUE    32768U
+#endif
+
+#ifndef LSI_VALUE
+#define LSI_VALUE    32000U
+#endif
+
+/* Oscillator startup timeouts */
+#ifndef HSE_STARTUP_TIMEOUT
+#define HSE_STARTUP_TIMEOUT 100U
+#endif
+
+#ifndef LSE_STARTUP_TIMEOUT
+#define LSE_STARTUP_TIMEOUT 5000U
+#endif
+
+
+/* --------------------------------------------------------------------------
+ * SysTick / time base
+ * -------------------------------------------------------------------------- */
+/* DO NOT set this to 0 unless you really know what you're doing.
+ * 0 == highest priority, which can break interrupt behavior later.
+ * For STM32F4 with 4 priority bits, 0x0F is lowest priority.
+ */
+#ifndef TICK_INT_PRIORITY
+#define TICK_INT_PRIORITY  0x0FU
+#endif
+
+/* --------------------------------------------------------------------------
+ * Optional: full assert
+ * -------------------------------------------------------------------------- */
+/* Uncomment to enable assert in HAL drivers (pulls in assert_failed()) */
+/* #define USE_FULL_ASSERT 1 */
+
+/* --------------------------------------------------------------------------
+ * Include enabled HAL module headers
+ * -------------------------------------------------------------------------- */
+#include "stm32f4xx_hal_rcc.h"
+#include "stm32f4xx_hal_dma.h"
+#include "stm32f4xx_hal_spi.h"
+#include "stm32f4xx_hal_gpio.h"
+#include "stm32f4xx_hal_flash.h"
+#include "stm32f4xx_hal_flash_ex.h"
+#include "stm32f4xx_hal_cortex.h"
+#include "stm32f4xx_hal_pwr.h"
+#include "stm32f4xx_hal_pwr_ex.h"
+#include "stm32f4xx_hal_pwr_ex.h"
+#include "stm32_assert.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STM32F4xx_HAL_CONF_H */
+
diff --git a/e407/p1_basic_template/inc/stm32_assert.h b/e407/p1_basic_template/inc/stm32_assert.h
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/inc/stm32_assert.h
@@ -0,0 +1,56 @@
+/**
+  ******************************************************************************
+  * @file    stm32_assert.h
+  * @author  MCD Application Team
+  * @brief   STM32 assert template file.
+  *          This file should be copied to the application folder and renamed
+  *          to stm32_assert.h.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2017 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32_ASSERT_H
+#define __STM32_ASSERT_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Includes ------------------------------------------------------------------*/
+/* Exported macro ------------------------------------------------------------*/
+#ifdef  USE_FULL_ASSERT
+/**
+  * @brief  The assert_param macro is used for function's parameters check.
+  * @param  expr If expr is false, it calls assert_failed function
+  *         which reports the name of the source file and the source
+  *         line number of the call that failed.
+  *         If expr is true, it returns no value.
+  * @retval None
+  */
+  #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
+/* Exported functions ------------------------------------------------------- */
+  void assert_failed(uint8_t* file, uint32_t line);
+#else
+  #define assert_param(expr) ((void)0U)
+#endif /* USE_FULL_ASSERT */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32_ASSERT_H */
+
+
+
diff --git a/e407/p1_basic_template/include/common.h b/e407/p1_basic_template/include/common.h
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/include/common.h
@@ -0,0 +1,3 @@
+#pragma once
+
+void Error_Handler(void);
\ No newline at end of file
diff --git a/e407/p1_basic_template/include/debug.h b/e407/p1_basic_template/include/debug.h
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/include/debug.h
@@ -0,0 +1,8 @@
+#ifndef DEBUG_H
+#define DEBUG_H
+
+#include "SEGGER_RTT.h"
+
+#define LOG(fmt, ...) SEGGER_RTT_printf(0, fmt, ##__VA_ARGS__)
+
+#endif /* DEBUG_H */
\ No newline at end of file
diff --git a/e407/p1_basic_template/include/main.h b/e407/p1_basic_template/include/main.h
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/include/main.h
@@ -0,0 +1,44 @@
+/**
+  ******************************************************************************
+  * @file    Project/STM32F4xx_StdPeriph_Templates/main.h 
+  * @author  MCD Application Team
+  * @version V1.8.0
+  * @date    04-November-2016
+  * @brief   Header for main.c module
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
+  *
+  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+  * You may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
+  *
+  *        http://www.st.com/software_license_agreement_liberty_v2
+  *
+  * Unless required by applicable law or agreed to in writing, software 
+  * distributed under the License is distributed on an "AS IS" BASIS, 
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  *
+  ******************************************************************************
+  */
+  
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __MAIN_H
+#define __MAIN_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx.h"
+
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+void TimingDelay_Decrement(void);
+
+#endif /* __MAIN_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/e407/p1_basic_template/include/spi_transport_backend.h b/e407/p1_basic_template/include/spi_transport_backend.h
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/include/spi_transport_backend.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#define SPI_RX_MAX 32
+
+int spi_transport_init();
+int spi_transport_receive(uint8_t *buf, uint32_t max_len);
+int spi_transport_send(uint8_t *buf, uint32_t max_len);
\ No newline at end of file
diff --git a/e407/p1_basic_template/include/stm32f4xx_conf.h b/e407/p1_basic_template/include/stm32f4xx_conf.h
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/include/stm32f4xx_conf.h
@@ -0,0 +1,172 @@
+/**
+  ******************************************************************************
+  * @file    Project/STM32F4xx_StdPeriph_Templates/stm32f4xx_conf.h  
+  * @author  MCD Application Team
+  * @version V1.8.0
+  * @date    04-November-2016
+  * @brief   Library configuration file.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
+  *
+  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+  * You may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
+  *
+  *        http://www.st.com/software_license_agreement_liberty_v2
+  *
+  * Unless required by applicable law or agreed to in writing, software 
+  * distributed under the License is distributed on an "AS IS" BASIS, 
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F4xx_CONF_H
+#define __STM32F4xx_CONF_H
+
+/* Includes ------------------------------------------------------------------*/
+/* Uncomment the line below to enable peripheral header file inclusion */
+#include "stm32f4xx_adc.h"
+#include "stm32f4xx_crc.h"
+#include "stm32f4xx_dbgmcu.h"
+#include "stm32f4xx_dma.h"
+#include "stm32f4xx_exti.h"
+#include "stm32f4xx_flash.h"
+#include "stm32f4xx_gpio.h"
+#include "stm32f4xx_i2c.h"
+#include "stm32f4xx_iwdg.h"
+#include "stm32f4xx_pwr.h"
+#include "stm32f4xx_rcc.h"
+#include "stm32f4xx_rtc.h"
+#include "stm32f4xx_sdio.h"
+#include "stm32f4xx_spi.h"
+#include "stm32f4xx_syscfg.h"
+#include "stm32f4xx_tim.h"
+#include "stm32f4xx_usart.h"
+#include "stm32f4xx_wwdg.h"
+#include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */
+
+#if defined(STM32F429_439xx) || defined(STM32F446xx) || defined(STM32F469_479xx)
+#include "stm32f4xx_cryp.h"
+#include "stm32f4xx_hash.h"
+#include "stm32f4xx_rng.h"
+#include "stm32f4xx_can.h"
+#include "stm32f4xx_dac.h"
+#include "stm32f4xx_dcmi.h"
+#include "stm32f4xx_dma2d.h"
+#include "stm32f4xx_fmc.h"
+#include "stm32f4xx_ltdc.h"
+#include "stm32f4xx_sai.h"
+#endif /* STM32F429_439xx || STM32F446xx || STM32F469_479xx */
+
+#if defined(STM32F427_437xx)
+#include "stm32f4xx_cryp.h"
+#include "stm32f4xx_hash.h"
+#include "stm32f4xx_rng.h"
+#include "stm32f4xx_can.h"
+#include "stm32f4xx_dac.h"
+#include "stm32f4xx_dcmi.h"
+#include "stm32f4xx_dma2d.h"
+#include "stm32f4xx_fmc.h"
+#include "stm32f4xx_sai.h"
+#endif /* STM32F427_437xx */
+
+#if defined(STM32F40_41xxx)
+#include "stm32f4xx_cryp.h"
+#include "stm32f4xx_hash.h"
+#include "stm32f4xx_rng.h"
+#include "stm32f4xx_can.h"
+#include "stm32f4xx_dac.h"
+#include "stm32f4xx_dcmi.h"
+#include "stm32f4xx_fsmc.h"
+#endif /* STM32F40_41xxx */
+
+#if defined(STM32F410xx)
+#include "stm32f4xx_rng.h"
+#include "stm32f4xx_dac.h"
+#endif /* STM32F410xx */
+
+#if defined(STM32F411xE)
+#include "stm32f4xx_flash_ramfunc.h"
+#endif /* STM32F411xE */
+
+#if defined(STM32F446xx) || defined(STM32F469_479xx)
+#include "stm32f4xx_qspi.h"
+#endif /* STM32F446xx || STM32F469_479xx */
+
+#if defined(STM32F410xx) || defined(STM32F446xx)
+#include "stm32f4xx_fmpi2c.h"
+#endif /* STM32F410xx || STM32F446xx */
+
+#if defined(STM32F446xx)
+#include "stm32f4xx_spdifrx.h"
+#include "stm32f4xx_cec.h"
+#endif /* STM32F446xx */
+
+#if defined(STM32F469_479xx)
+#include "stm32f4xx_dsi.h"
+#endif /* STM32F469_479xx */
+
+#if defined(STM32F410xx)
+#include "stm32f4xx_lptim.h"
+#endif /* STM32F410xx */
+
+#if defined(STM32F412xG)
+#include "stm32f4xx_rng.h"
+#include "stm32f4xx_can.h"
+#include "stm32f4xx_qspi.h"
+#include "stm32f4xx_rng.h"
+#include "stm32f4xx_fsmc.h"
+#include "stm32f4xx_dfsdm.h"
+#endif /* STM32F412xG */
+
+#if defined(STM32F413_423xx)
+#include "stm32f4xx_cryp.h"
+#include "stm32f4xx_fmpi2c.h"
+#include "stm32f4xx_rng.h"
+#include "stm32f4xx_can.h"
+#include "stm32f4xx_qspi.h"
+#include "stm32f4xx_rng.h"
+#include "stm32f4xx_fsmc.h"
+#include "stm32f4xx_dfsdm.h"
+#endif /* STM32F413_423xx */
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+
+/* If an external clock source is used, then the value of the following define 
+   should be set to the value of the external clock source, else, if no external 
+   clock is used, keep this define commented */
+/*#define I2S_EXTERNAL_CLOCK_VAL   12288000 */ /* Value of the external clock in Hz */
+
+
+/* Uncomment the line below to expanse the "assert_param" macro in the 
+   Standard Peripheral Library drivers code */
+/* #define USE_FULL_ASSERT    1 */
+
+/* Exported macro ------------------------------------------------------------*/
+#ifdef  USE_FULL_ASSERT
+
+/**
+  * @brief  The assert_param macro is used for function's parameters check.
+  * @param  expr: If expr is false, it calls assert_failed function
+  *   which reports the name of the source file and the source
+  *   line number of the call that failed. 
+  *   If expr is true, it returns no value.
+  * @retval None
+  */
+  #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
+/* Exported functions ------------------------------------------------------- */
+  void assert_failed(uint8_t* file, uint32_t line);
+#else
+  #define assert_param(expr) ((void)0)
+#endif /* USE_FULL_ASSERT */
+
+#endif /* __STM32F4xx_CONF_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/e407/p1_basic_template/include/stm32f4xx_it.h b/e407/p1_basic_template/include/stm32f4xx_it.h
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/include/stm32f4xx_it.h
@@ -0,0 +1,60 @@
+/**
+  ******************************************************************************
+  * @file    Project/STM32F4xx_StdPeriph_Templates/stm32f4xx_it.h 
+  * @author  MCD Application Team
+  * @version V1.8.0
+  * @date    04-November-2016
+  * @brief   This file contains the headers of the interrupt handlers.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
+  *
+  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+  * You may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
+  *
+  *        http://www.st.com/software_license_agreement_liberty_v2
+  *
+  * Unless required by applicable law or agreed to in writing, software 
+  * distributed under the License is distributed on an "AS IS" BASIS, 
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F4xx_IT_H
+#define __STM32F4xx_IT_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif 
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx.h"
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+
+void NMI_Handler(void);
+void HardFault_Handler(void);
+void MemManage_Handler(void);
+void BusFault_Handler(void);
+void UsageFault_Handler(void);
+void SVC_Handler(void);
+void DebugMon_Handler(void);
+void PendSV_Handler(void);
+void SysTick_Handler(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F4xx_IT_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/e407/p1_basic_template/include/transport.h b/e407/p1_basic_template/include/transport.h
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/include/transport.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <stdint.h>
+
+typedef struct {
+    int (*init)(void);
+    int (*receive)(uint8_t *buf, uint32_t max_len);
+    int (*send)(uint8_t *buf, uint32_t max_len);
+} transport_t;
+
+const transport_t *transport_select(void);
\ No newline at end of file
diff --git a/e407/p1_basic_template/src/Makefile b/e407/p1_basic_template/src/Makefile
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/src/Makefile
@@ -0,0 +1,84 @@
+# Minimal Makefile for STM32F407 bootloader (Phase 0–3, pre-SPI)
+# Toolchain: arm-none-eabi-gcc
+#
+# Uses:
+#  - standalone stm32f4xx-hal-driver repository
+#  - CMSIS device pack for STM32F4
+
+HAL_REPO   ?= ../stm32f4xx-hal-driver
+CMSIS_CORE_REPO ?= ../cmsis_core
+CMSIS_DEVICE_F4_REPO ?= ../cmsis_device_f4
+
+HAL_DIR    := $(HAL_REPO)
+CMSIS_CORE := $(CMSIS_CORE_REPO)/CMSIS/Core
+CMSIS_DEV  := $(CMSIS_DEVICE_F4_REPO)
+
+CC      := arm-none-eabi-gcc
+AS      := arm-none-eabi-gcc
+OBJCOPY := arm-none-eabi-objcopy
+SIZE    := arm-none-eabi-size
+
+TARGET  := bootloader
+BUILD   := build
+
+APP_OBJDIR := $(BUILD)/app
+HAL_OBJDIR := $(BUILD)/hal
+CMSIS_OBJDIR := $(BUILD)/cmsis
+
+CFLAGS := -mcpu=cortex-m4 -mthumb -O2 -g3           -ffunction-sections -fdata-sections           -Wall -Wextra -Wno-unused-parameter           -std=gnu11 -DSTM32F407xx -DUSE_HAL_DRIVER
+
+INCLUDES :=     -Iinc	-Ihal_conf	-I$(HAL_DIR)/Inc     -I$(CMSIS_CORE)/Include     -I$(CMSIS_DEV)/Include
+
+LDSCRIPT := linker/STM32F417IG_FLASH.ld
+
+LDFLAGS := -T$(LDSCRIPT)            -Wl,--gc-sections           --specs=nosys.specs
+
+APP_SRCS_C :=	src/main.c	src/bl_led.c	src/bl_image.c     src/bl_meta.c     src/bl_update.c     src/bl_flash.c      src/ram_test.c
+
+HAL_SRCS_C :=	$(HAL_DIR)/Src/stm32f4xx_hal.c     $(HAL_DIR)/Src/stm32f4xx_hal_gpio.c     $(HAL_DIR)/Src/stm32f4xx_hal_flash.c     $(HAL_DIR)/Src/stm32f4xx_hal_flash_ex.c     $(HAL_DIR)/Src/stm32f4xx_hal_cortex.c $(HAL_DIR)/Src/stm32f4xx_hal_rcc.c
+
+CMSIS_SRCS_C := $(CMSIS_DEV)/Source/Templates/system_stm32f4xx.c
+
+SRCS_S := startup/startup_stm32f40_41xxx.s
+
+APP_OBJS := $(patsubst src/%.c,$(APP_OBJDIR)/%.o,$(APP_SRCS_C))
+HAL_OBJS := $(addprefix $(HAL_OBJDIR)/,$(notdir $(HAL_SRCS_C:.c=.o)))
+CMSIS_OBJS := $(addprefix $(CMSIS_OBJDIR)/,$(notdir $(CMSIS_SRCS_C:.c=.o)))
+
+OBJS :=     $(APP_OBJS) $(HAL_OBJS) $(CMSIS_OBJS) $(patsubst %.s,$(BUILD)/%.o,$(SRCS_S))
+
+DEPS := $(OBJS:.o=.d)
+
+.PHONY: all clean size
+
+all: $(BUILD)/$(TARGET).elf $(BUILD)/$(TARGET).bin size
+
+$(APP_OBJDIR)/%.o: src/%.c
+	@mkdir -p $(dir $@)
+	$(CC) $(CFLAGS) $(INCLUDES) -MMD -MP -c $< -o $@
+
+$(HAL_OBJDIR)/%.o: $(HAL_DIR)/Src/%.c
+	@mkdir -p $(dir $@)
+	$(CC) $(CFLAGS) $(INCLUDES) -MMD -MP -c $< -o $@
+
+$(CMSIS_OBJDIR)/%.o: $(CMSIS_DEV)/Source/Templates/%.c
+	@mkdir -p $(dir $@)
+	$(CC) $(CFLAGS) $(INCLUDES) -MMD -MP -c $< -o $@
+
+$(BUILD)/%.o: %.s
+	@mkdir -p $(dir $@)
+	$(AS) $(CFLAGS) -c $< -o $@
+
+$(BUILD)/$(TARGET).elf: $(OBJS)
+	$(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) -o $@
+
+$(BUILD)/$(TARGET).bin: $(BUILD)/$(TARGET).elf
+	$(OBJCOPY) -O binary $< $@
+
+size: $(BUILD)/$(TARGET).elf
+	$(SIZE) $<
+
+clean:
+	rm -rf $(BUILD)
+
+-include $(DEPS)
diff --git a/e407/p1_basic_template/src/common.c b/e407/p1_basic_template/src/common.c
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/src/common.c
@@ -0,0 +1,10 @@
+#include "stm32f4xx.h"
+
+void Error_Handler(void)
+{
+    __disable_irq();
+
+    while (1)
+    {
+    }
+}
diff --git a/e407/p1_basic_template/src/main.c b/e407/p1_basic_template/src/main.c
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/src/main.c
@@ -0,0 +1,95 @@
+#include "stm32f4xx_hal.h"
+#include "debug.h"
+#include "common.h"
+#include "transport.h"
+
+#include "spi_transport_backend.h"
+
+static void SystemClock_Config(void);
+
+
+/* -------------------------------------------------------------------------- */
+
+void SysTick_Handler(void)
+{
+    HAL_IncTick();
+}
+
+int main(void)
+{
+    const transport_t *transport;
+    uint8_t rx[SPI_RX_MAX];
+    int res;
+
+    HAL_Init();
+    SEGGER_RTT_Init();
+    SystemClock_Config();
+
+
+    /* Init here the transport layer */
+    transport = transport_select();
+    transport->init();
+
+    LOG("\r\n");
+    LOG("E407 SPI slave test\r\n");
+
+    while (1)
+    {
+        /*
+         * STM32 = SPI slave
+         * RPi    = SPI master
+         */
+
+        /* Wait for transmission in the transport backend */
+        res = transport->receive(rx, sizeof(rx));
+
+        if(res > 0) {
+            LOG("RX: ");
+            for (int i = 0; i < res; i++)
+                LOG("%02X ", rx[i]);
+            LOG("\r\n");
+        } else if (res < 0) {
+            LOG("Invalid SPI transaction\r\n");
+        }
+    }
+}
+
+/* -------------------------------------------------------------------------- */
+/* Clock                                                                      */
+/* -------------------------------------------------------------------------- */
+
+static void SystemClock_Config(void)
+{
+    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
+    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
+
+    /*
+     * Simple 16 MHz HSI.
+     */
+    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
+    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
+    RCC_OscInitStruct.HSICalibrationValue =
+        RCC_HSICALIBRATION_DEFAULT;
+    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_OFF;
+
+    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
+        Error_Handler();
+
+    RCC_ClkInitStruct.ClockType =
+          RCC_CLOCKTYPE_HCLK
+        | RCC_CLOCKTYPE_SYSCLK
+        | RCC_CLOCKTYPE_PCLK1
+        | RCC_CLOCKTYPE_PCLK2;
+
+    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
+    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
+    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
+    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
+
+    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct,
+                            FLASH_LATENCY_0) != HAL_OK)
+        Error_Handler();
+}
+
+
+/* -------------------------------------------------------------------------- */
\ No newline at end of file
diff --git a/e407/p1_basic_template/src/spi_transport_backend.c b/e407/p1_basic_template/src/spi_transport_backend.c
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/src/spi_transport_backend.c
@@ -0,0 +1,239 @@
+#include "stm32f4xx_hal.h"
+#include "stm32f4xx_hal_dma.h"
+#include "stm32f4xx_hal_spi.h"
+
+#include "common.h"
+#include "debug.h"
+#include "spi_transport_backend.h"
+#include "transport.h"
+
+#include <string.h>
+
+static volatile uint8_t  spi_rx[SPI_RX_MAX];
+static volatile uint32_t spi_rx_count = 0;
+static volatile uint8_t  spi_nss_high = 0;
+
+#if defined(DEBUG)
+volatile uint32_t spi_irq_count = 0;
+volatile uint32_t exti_count = 0;
+#endif
+
+static SPI_HandleTypeDef hspi1;
+
+static const transport_t transport_spi =
+{
+        .init = spi_transport_init,
+        .send = spi_transport_send,
+        .receive = spi_transport_receive
+};
+
+const transport_t *transport_select(void) {
+    return &transport_spi;
+}
+
+void SPI1_IRQHandler(void)
+{
+#if defined(DEBUG)
+    spi_irq_count++;
+#endif
+
+    if (__HAL_SPI_GET_FLAG(&hspi1, SPI_FLAG_RXNE) &&
+        __HAL_SPI_GET_IT_SOURCE(&hspi1, SPI_IT_RXNE))
+    {
+        uint8_t data;
+
+        data = *(__IO uint8_t *)&SPI1->DR;
+
+        if (spi_rx_count < SPI_RX_MAX)
+        {
+            spi_rx[spi_rx_count++] = data;
+        } else {
+            spi_rx_count++;
+        }
+    }
+}
+
+void EXTI4_IRQHandler(void)
+{
+    if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_4))
+    {
+        __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_4);
+
+        /*
+         * NSS has gone HIGH.
+         * SPI transaction is finished.
+         */
+#if defined(DEBUG)
+        exti_count++;
+#endif
+        spi_nss_high = 1;
+    }
+}
+
+/* -------------------------------------------------------------------------- */
+/* SPI1                                                                      */
+/* -------------------------------------------------------------------------- */
+
+void MX_SPI1_Init(void)
+{
+    hspi1.Instance = SPI1;
+
+    hspi1.Init.Mode = SPI_MODE_SLAVE;
+    hspi1.Init.Direction = SPI_DIRECTION_2LINES;
+    hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
+
+    /*
+     * SPI mode 0:
+     * CPOL = 0
+     * CPHA = 0
+     */
+    hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
+    hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
+
+    hspi1.Init.NSS = SPI_NSS_HARD_INPUT;
+
+    /*
+     * Not relevant in slave mode.
+     */
+    hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
+
+    hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
+    hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
+    hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
+    hspi1.Init.CRCPolynomial = 7;
+
+    if (HAL_SPI_Init(&hspi1) != HAL_OK)
+        Error_Handler();
+
+    __HAL_SPI_ENABLE(&hspi1);
+    __HAL_SPI_ENABLE_IT(&hspi1, SPI_IT_RXNE);
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* SPI1 GPIO                                                                 */
+/* -------------------------------------------------------------------------- */
+
+void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
+{
+    GPIO_InitTypeDef GPIO_InitStruct = {0};
+
+    if (hspi->Instance == SPI1)
+    {
+        __HAL_RCC_SPI1_CLK_ENABLE();
+        __HAL_RCC_GPIOA_CLK_ENABLE();
+        __HAL_RCC_GPIOB_CLK_ENABLE();
+        __HAL_RCC_SYSCFG_CLK_ENABLE();
+
+        /*
+         * PA5 = SCK
+         * PA6 = MISO
+         * PB5 = MOSI
+         */
+        GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6;
+        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+        GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+        GPIO_InitStruct.Pin = GPIO_PIN_5;
+        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+        /* EXTI4 source = GPIOA */
+        SYSCFG->EXTICR[1] &= ~(0xF << 0);
+        /* Rising edge only */
+        EXTI->RTSR |= EXTI_RTSR_TR4;
+        EXTI->FTSR &= ~EXTI_FTSR_TR4;
+        /* Unmask EXTI4 */
+        EXTI->IMR |= EXTI_IMR_MR4;
+        /* Clear possible pending interrupt */
+        EXTI->PR = EXTI_PR_PR4;
+
+        HAL_NVIC_SetPriority(SPI1_IRQn, 1, 0);
+        HAL_NVIC_EnableIRQ(SPI1_IRQn);
+
+        /* EXTI4 lower priority than SPI1 */
+        HAL_NVIC_SetPriority(EXTI4_IRQn, 2, 0);
+        HAL_NVIC_EnableIRQ(EXTI4_IRQn);
+
+
+    }
+}
+
+/* -------------------------------------------------------------------------- */
+/* GPIO                                                                       */
+/* -------------------------------------------------------------------------- */
+
+void MX_GPIO_Init(void)
+{
+    /*
+     * Nothing else required.
+     * SPI GPIOs are initialized by HAL_SPI_MspInit().
+     */
+}
+
+int spi_transport_init() {
+
+    MX_GPIO_Init();
+    MX_SPI1_Init();
+
+    return 0;
+}
+
+int spi_transport_send(uint8_t *buf, uint32_t max_len) {
+    /* Placeholder ToDo */
+    LOG("ToDo ... Upstream SPI transaction");
+
+    return 0;
+}
+
+int spi_transport_receive(uint8_t *buf, uint32_t max_len) {
+
+        int len;
+
+
+        /*
+         * Wait until the transaction finished
+         */
+        if (!spi_nss_high)
+            return 0;
+
+        /*
+        * NSS is HIGH, so the master has finished.
+        *
+        * SPI1 has higher interrupt priority than EXTI4,
+        * so the final RXNE interrupt will be serviced first
+        * if both become pending at approximately the same time.
+        */
+
+        __disable_irq();
+
+        spi_nss_high = 0;
+        len = spi_rx_count;
+
+        /* Invalid transaction */
+        if(len > (int)max_len) {
+            spi_rx_count = 0;
+            __enable_irq();
+            return -1;
+        }
+
+        memcpy(buf, (const void *)spi_rx, len);
+
+        spi_rx_count = 0;
+
+        __enable_irq();
+
+#if defined(DEBUG)
+        LOG("SPI IRQ=%lu EXTI=%lu RX=%lu CR1=%08lX CR2=%08lX SR=%08lX\n",
+            spi_irq_count,
+            exti_count,
+            len,
+            SPI1->CR1,
+            SPI1->CR2,
+            SPI1->SR);
+#endif
+
+        return len;
+}
\ No newline at end of file
diff --git a/e407/p1_basic_template/src/startup_stm32f40_41xxx.s b/e407/p1_basic_template/src/startup_stm32f40_41xxx.s
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/src/startup_stm32f40_41xxx.s
@@ -0,0 +1,517 @@
+/**
+  ******************************************************************************
+  * @file      startup_stm32f40_41xxx.s
+  * @author    MCD Application Team
+  * @version   V1.8.0
+  * @date      09-November-2016
+  * @brief     STM32F40xxx/41xxx Devices vector table for Atollic TrueSTUDIO toolchain.   
+  *            This module performs:
+  *                - Set the initial SP
+  *                - Set the initial PC == Reset_Handler,
+  *                - Set the vector table entries with the exceptions ISR address
+  *                - Configure the clock system and the external SRAM mounted on 
+  *                  STM324xG-EVAL board to be used as data memory (optional, 
+  *                  to be enabled by user)
+  *                - 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 2016 STMicroelectronics</center></h2>
+  *
+  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+  * You may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
+  *
+  *        http://www.st.com/software_license_agreement_liberty_v2
+  *
+  * Unless required by applicable law or agreed to in writing, software 
+  * distributed under the License is distributed on an "AS IS" BASIS, 
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  *
+  ******************************************************************************
+  */
+    
+  .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:  
+
+/* 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
+
+/* 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     FSMC_IRQHandler                   /* FSMC                         */                   
+  .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     CRYP_IRQHandler                   /* CRYP crypto                  */                   
+  .word     HASH_RNG_IRQHandler               /* Hash and Rng                 */
+  .word     FPU_IRQHandler                    /* FPU                          */
+                        
+/*******************************************************************************
+*
+* 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      FSMC_IRQHandler            
+   .thumb_set FSMC_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      CRYP_IRQHandler            
+   .thumb_set CRYP_IRQHandler,Default_Handler
+               
+   .weak      HASH_RNG_IRQHandler                  
+   .thumb_set HASH_RNG_IRQHandler,Default_Handler   
+
+   .weak      FPU_IRQHandler                  
+   .thumb_set FPU_IRQHandler,Default_Handler  
+   
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/e407/p1_basic_template/src/stm32f4xx_it.c b/e407/p1_basic_template/src/stm32f4xx_it.c
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/src/stm32f4xx_it.c
@@ -0,0 +1,168 @@
+/**
+  ******************************************************************************
+  * @file    Project/STM32F4xx_StdPeriph_Templates/stm32f4xx_it.c 
+  * @author  MCD Application Team
+  * @version V1.8.0
+  * @date    04-November-2016
+  * @brief   Main Interrupt Service Routines.
+  *          This file provides template for all exceptions handler and 
+  *          peripherals interrupt service routine.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
+  *
+  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+  * You may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
+  *
+  *        http://www.st.com/software_license_agreement_liberty_v2
+  *
+  * Unless required by applicable law or agreed to in writing, software 
+  * distributed under the License is distributed on an "AS IS" BASIS, 
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx_it.h"
+#include "main.h"
+
+/** @addtogroup Template_Project
+  * @{
+  */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/******************************************************************************/
+/*            Cortex-M4 Processor Exceptions Handlers                         */
+/******************************************************************************/
+
+/**
+  * @brief  This function handles NMI exception.
+  * @param  None
+  * @retval None
+  */
+void NMI_Handler(void)
+{
+}
+
+/**
+  * @brief  This function handles Hard Fault exception.
+  * @param  None
+  * @retval None
+  */
+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
+  */
+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 */
+  while (1)
+  {
+  }
+}
+
+/**
+  * @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
+  * @retval None
+  */
+void SysTick_Handler(void)
+{
+/*  TimingDelay_Decrement(); */
+}
+
+/******************************************************************************/
+/*                 STM32F4xx Peripherals Interrupt Handlers                   */
+/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
+/*  available peripheral interrupt handler's name please refer to the startup */
+/*  file (startup_stm32f4xx.s).                                               */
+/******************************************************************************/
+
+/**
+  * @brief  This function handles PPP interrupt request.
+  * @param  None
+  * @retval None
+  */
+/*void PPP_IRQHandler(void)
+{
+}*/
+
+/**
+  * @}
+  */ 
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/e407/p1_basic_template/src/system_stm32f4xx.c b/e407/p1_basic_template/src/system_stm32f4xx.c
new file mode 100644
--- /dev/null
+++ b/e407/p1_basic_template/src/system_stm32f4xx.c
@@ -0,0 +1,1395 @@
+/**
+  ******************************************************************************
+  * @file    system_stm32f4xx.c
+  * @author  MCD Application Team
+  * @version V1.8.0
+  * @date    04-November-2016
+  * @brief   CMSIS Cortex-M4 Device Peripheral Access Layer System Source File.
+  *          This file contains the system clock configuration for STM32F4xx devices.
+  *             
+  * 1.  This file provides two functions and one global variable to be called from 
+  *     user application:
+  *      - SystemInit(): Setups the system clock (System clock source, PLL Multiplier
+  *                      and Divider factors, AHB/APBx prescalers and Flash settings),
+  *                      depending on the configuration made in the clock xls tool. 
+  *                      This function is called at startup just after reset and 
+  *                      before branch to main program. This call is made inside
+  *                      the "startup_stm32f4xx.s" file.
+  *
+  *      - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
+  *                                  by the user application to setup the SysTick 
+  *                                  timer or configure other parameters.
+  *                                     
+  *      - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
+  *                                 be called whenever the core clock is changed
+  *                                 during program execution.
+  *
+  * 2. After each device reset the HSI (16 MHz) is used as system clock source.
+  *    Then SystemInit() function is called, in "startup_stm32f4xx.s" file, to
+  *    configure the system clock before to branch to main program.
+  *
+  * 3. If the system clock source selected by user fails to startup, the SystemInit()
+  *    function will do nothing and HSI still used as system clock source. User can 
+  *    add some code to deal with this issue inside the SetSysClock() function.
+  *
+  * 4. The default value of HSE crystal is set to 25MHz, refer to "HSE_VALUE" define
+  *    in "stm32f4xx.h" file. When HSE is used as system clock source, directly or
+  *    through PLL, and you are using different crystal you have to adapt the HSE
+  *    value to your own configuration.
+  *
+  * 5. This file configures the system clock as follows:
+  *=============================================================================
+  *=============================================================================
+  *                    Supported STM32F40xxx/41xxx devices
+  *-----------------------------------------------------------------------------
+  *        System Clock source                    | PLL (HSE)
+  *-----------------------------------------------------------------------------
+  *        SYSCLK(Hz)                             | 168000000
+  *-----------------------------------------------------------------------------
+  *        HCLK(Hz)                               | 168000000
+  *-----------------------------------------------------------------------------
+  *        AHB Prescaler                          | 1
+  *-----------------------------------------------------------------------------
+  *        APB1 Prescaler                         | 4
+  *-----------------------------------------------------------------------------
+  *        APB2 Prescaler                         | 2
+  *-----------------------------------------------------------------------------
+  *        HSE Frequency(Hz)                      | 25000000
+  *-----------------------------------------------------------------------------
+  *        PLL_M                                  | 25
+  *-----------------------------------------------------------------------------
+  *        PLL_N                                  | 336
+  *-----------------------------------------------------------------------------
+  *        PLL_P                                  | 2
+  *-----------------------------------------------------------------------------
+  *        PLL_Q                                  | 7
+  *-----------------------------------------------------------------------------
+  *        PLLI2S_N                               | NA
+  *-----------------------------------------------------------------------------
+  *        PLLI2S_R                               | NA
+  *-----------------------------------------------------------------------------
+  *        I2S input clock                        | NA
+  *-----------------------------------------------------------------------------
+  *        VDD(V)                                 | 3.3
+  *-----------------------------------------------------------------------------
+  *        Main regulator output voltage          | Scale1 mode
+  *-----------------------------------------------------------------------------
+  *        Flash Latency(WS)                      | 5
+  *-----------------------------------------------------------------------------
+  *        Prefetch Buffer                        | ON
+  *-----------------------------------------------------------------------------
+  *        Instruction cache                      | ON
+  *-----------------------------------------------------------------------------
+  *        Data cache                             | ON
+  *-----------------------------------------------------------------------------
+  *        Require 48MHz for USB OTG FS,          | Disabled
+  *        SDIO and RNG clock                     |
+  *-----------------------------------------------------------------------------
+  *=============================================================================
+  *=============================================================================
+  *                    Supported STM32F42xxx/43xxx devices
+  *-----------------------------------------------------------------------------
+  *        System Clock source                    | PLL (HSE)
+  *-----------------------------------------------------------------------------
+  *        SYSCLK(Hz)                             | 180000000
+  *-----------------------------------------------------------------------------
+  *        HCLK(Hz)                               | 180000000
+  *-----------------------------------------------------------------------------
+  *        AHB Prescaler                          | 1
+  *-----------------------------------------------------------------------------
+  *        APB1 Prescaler                         | 4
+  *-----------------------------------------------------------------------------
+  *        APB2 Prescaler                         | 2
+  *-----------------------------------------------------------------------------
+  *        HSE Frequency(Hz)                      | 25000000
+  *-----------------------------------------------------------------------------
+  *        PLL_M                                  | 25
+  *-----------------------------------------------------------------------------
+  *        PLL_N                                  | 360
+  *-----------------------------------------------------------------------------
+  *        PLL_P                                  | 2
+  *-----------------------------------------------------------------------------
+  *        PLL_Q                                  | 7
+  *-----------------------------------------------------------------------------
+  *        PLLI2S_N                               | NA
+  *-----------------------------------------------------------------------------
+  *        PLLI2S_R                               | NA
+  *-----------------------------------------------------------------------------
+  *        I2S input clock                        | NA
+  *-----------------------------------------------------------------------------
+  *        VDD(V)                                 | 3.3
+  *-----------------------------------------------------------------------------
+  *        Main regulator output voltage          | Scale1 mode
+  *-----------------------------------------------------------------------------
+  *        Flash Latency(WS)                      | 5
+  *-----------------------------------------------------------------------------
+  *        Prefetch Buffer                        | ON
+  *-----------------------------------------------------------------------------
+  *        Instruction cache                      | ON
+  *-----------------------------------------------------------------------------
+  *        Data cache                             | ON
+  *-----------------------------------------------------------------------------
+  *        Require 48MHz for USB OTG FS,          | Disabled
+  *        SDIO and RNG clock                     |
+  *-----------------------------------------------------------------------------
+  *=============================================================================
+  *=============================================================================
+  *                         Supported STM32F401xx devices
+  *-----------------------------------------------------------------------------
+  *        System Clock source                    | PLL (HSE)
+  *-----------------------------------------------------------------------------
+  *        SYSCLK(Hz)                             | 84000000
+  *-----------------------------------------------------------------------------
+  *        HCLK(Hz)                               | 84000000
+  *-----------------------------------------------------------------------------
+  *        AHB Prescaler                          | 1
+  *-----------------------------------------------------------------------------
+  *        APB1 Prescaler                         | 2
+  *-----------------------------------------------------------------------------
+  *        APB2 Prescaler                         | 1
+  *-----------------------------------------------------------------------------
+  *        HSE Frequency(Hz)                      | 25000000
+  *-----------------------------------------------------------------------------
+  *        PLL_M                                  | 25
+  *-----------------------------------------------------------------------------
+  *        PLL_N                                  | 336
+  *-----------------------------------------------------------------------------
+  *        PLL_P                                  | 4
+  *-----------------------------------------------------------------------------
+  *        PLL_Q                                  | 7
+  *-----------------------------------------------------------------------------
+  *        PLLI2S_N                               | NA
+  *-----------------------------------------------------------------------------
+  *        PLLI2S_R                               | NA
+  *-----------------------------------------------------------------------------
+  *        I2S input clock                        | NA
+  *-----------------------------------------------------------------------------
+  *        VDD(V)                                 | 3.3
+  *-----------------------------------------------------------------------------
+  *        Main regulator output voltage          | Scale1 mode
+  *-----------------------------------------------------------------------------
+  *        Flash Latency(WS)                      | 2
+  *-----------------------------------------------------------------------------
+  *        Prefetch Buffer                        | ON
+  *-----------------------------------------------------------------------------
+  *        Instruction cache                      | ON
+  *-----------------------------------------------------------------------------
+  *        Data cache                             | ON
+  *-----------------------------------------------------------------------------
+  *        Require 48MHz for USB OTG FS,          | Disabled
+  *        SDIO and RNG clock                     |
+  *-----------------------------------------------------------------------------
+  *=============================================================================
+  *=============================================================================
+  *                Supported STM32F411xx/STM32F410xx devices
+  *-----------------------------------------------------------------------------
+  *        System Clock source                    | PLL (HSI)
+  *-----------------------------------------------------------------------------
+  *        SYSCLK(Hz)                             | 100000000
+  *-----------------------------------------------------------------------------
+  *        HCLK(Hz)                               | 100000000
+  *-----------------------------------------------------------------------------
+  *        AHB Prescaler                          | 1
+  *-----------------------------------------------------------------------------
+  *        APB1 Prescaler                         | 2
+  *-----------------------------------------------------------------------------
+  *        APB2 Prescaler                         | 1
+  *-----------------------------------------------------------------------------
+  *        HSI Frequency(Hz)                      | 16000000
+  *-----------------------------------------------------------------------------
+  *        PLL_M                                  | 16
+  *-----------------------------------------------------------------------------
+  *        PLL_N                                  | 400
+  *-----------------------------------------------------------------------------
+  *        PLL_P                                  | 4
+  *-----------------------------------------------------------------------------
+  *        PLL_Q                                  | 7
+  *-----------------------------------------------------------------------------
+  *        PLLI2S_N                               | NA
+  *-----------------------------------------------------------------------------
+  *        PLLI2S_R                               | NA
+  *-----------------------------------------------------------------------------
+  *        I2S input clock                        | NA
+  *-----------------------------------------------------------------------------
+  *        VDD(V)                                 | 3.3
+  *-----------------------------------------------------------------------------
+  *        Main regulator output voltage          | Scale1 mode
+  *-----------------------------------------------------------------------------
+  *        Flash Latency(WS)                      | 3
+  *-----------------------------------------------------------------------------
+  *        Prefetch Buffer                        | ON
+  *-----------------------------------------------------------------------------
+  *        Instruction cache                      | ON
+  *-----------------------------------------------------------------------------
+  *        Data cache                             | ON
+  *-----------------------------------------------------------------------------
+  *        Require 48MHz for USB OTG FS,          | Disabled
+  *        SDIO and RNG clock                     |
+  *-----------------------------------------------------------------------------
+  *=============================================================================
+  *=============================================================================
+  *                         Supported STM32F446xx devices
+  *-----------------------------------------------------------------------------
+  *        System Clock source                    | PLL (HSE)
+  *-----------------------------------------------------------------------------
+  *        SYSCLK(Hz)                             | 180000000
+  *-----------------------------------------------------------------------------
+  *        HCLK(Hz)                               | 180000000
+  *-----------------------------------------------------------------------------
+  *        AHB Prescaler                          | 1
+  *-----------------------------------------------------------------------------
+  *        APB1 Prescaler                         | 4
+  *-----------------------------------------------------------------------------
+  *        APB2 Prescaler                         | 2
+  *-----------------------------------------------------------------------------
+  *        HSE Frequency(Hz)                      | 8000000
+  *-----------------------------------------------------------------------------
+  *        PLL_M                                  | 8
+  *-----------------------------------------------------------------------------
+  *        PLL_N                                  | 360
+  *-----------------------------------------------------------------------------
+  *        PLL_P                                  | 2
+  *-----------------------------------------------------------------------------
+  *        PLL_Q                                  | 7
+  *-----------------------------------------------------------------------------
+  *        PLL_R                                  | NA
+  *-----------------------------------------------------------------------------
+  *        PLLI2S_M                               | NA
+  *-----------------------------------------------------------------------------
+  *        PLLI2S_N                               | NA
+  *-----------------------------------------------------------------------------
+  *        PLLI2S_P                               | NA
+  *-----------------------------------------------------------------------------
+  *        PLLI2S_Q                               | NA
+  *-----------------------------------------------------------------------------
+  *        PLLI2S_R                               | NA
+  *-----------------------------------------------------------------------------
+  *        I2S input clock                        | NA
+  *-----------------------------------------------------------------------------
+  *        VDD(V)                                 | 3.3
+  *-----------------------------------------------------------------------------
+  *        Main regulator output voltage          | Scale1 mode
+  *-----------------------------------------------------------------------------
+  *        Flash Latency(WS)                      | 5
+  *-----------------------------------------------------------------------------
+  *        Prefetch Buffer                        | ON
+  *-----------------------------------------------------------------------------
+  *        Instruction cache                      | ON
+  *-----------------------------------------------------------------------------
+  *        Data cache                             | ON
+  *-----------------------------------------------------------------------------
+  *        Require 48MHz for USB OTG FS,          | Disabled
+  *        SDIO and RNG clock                     |
+  *-----------------------------------------------------------------------------
+  *=============================================================================
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
+  *
+  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+  * You may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
+  *
+  *        http://www.st.com/software_license_agreement_liberty_v2
+  *
+  * Unless required by applicable law or agreed to in writing, software 
+  * distributed under the License is distributed on an "AS IS" BASIS, 
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  *
+  ******************************************************************************
+  */
+
+/** @addtogroup CMSIS
+  * @{
+  */
+
+/** @addtogroup stm32f4xx_system
+  * @{
+  */  
+  
+/** @addtogroup STM32F4xx_System_Private_Includes
+  * @{
+  */
+
+#include "stm32f4xx.h"
+
+/**
+  * @}
+  */
+
+/** @addtogroup STM32F4xx_System_Private_TypesDefinitions
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/** @addtogroup STM32F4xx_System_Private_Defines
+  * @{
+  */
+
+/************************* Miscellaneous Configuration ************************/
+/*!< Uncomment the following line if you need to use external SRAM or SDRAM mounted
+     on STM324xG_EVAL/STM324x7I_EVAL/STM324x9I_EVAL boards as data memory  */     
+#if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F469_479xx) || defined(STM32F413_423xx)
+/* #define DATA_IN_ExtSRAM */
+#endif /* STM32F40_41xxx || STM32F427_437x || STM32F429_439xx || STM32F469_479xx || STM32F413_423xx */
+
+#if defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F446xx) || defined(STM32F469_479xx)
+/* #define DATA_IN_ExtSDRAM */
+#endif /* STM32F427_437x || STM32F429_439xx || STM32F446xx || STM32F469_479xx */ 
+
+#if defined(STM32F410xx) || defined(STM32F411xE)
+/*!< Uncomment the following line if you need to clock the STM32F410xx/STM32F411xE by HSE Bypass
+     through STLINK MCO pin of STM32F103 microcontroller. The frequency cannot be changed
+     and is fixed at 8 MHz. 
+     Hardware configuration needed for Nucleo Board:
+     � SB54, SB55 OFF
+     � R35 removed
+     � SB16, SB50 ON */
+/* #define USE_HSE_BYPASS */
+
+#if defined(USE_HSE_BYPASS)     
+#define HSE_BYPASS_INPUT_FREQUENCY   8000000
+#endif /* USE_HSE_BYPASS */    
+#endif /* STM32F410xx || STM32F411xE */
+    
+/*!< Uncomment the following line if you need to relocate your vector Table in
+     Internal SRAM. */
+/* #define VECT_TAB_SRAM */
+#define VECT_TAB_OFFSET  0x00 /*!< Vector Table base offset field. 
+                                   This value must be a multiple of 0x200. */
+/******************************************************************************/
+
+/************************* PLL Parameters *************************************/
+#if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F401xx) || defined(STM32F469_479xx)
+ /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
+ #define PLL_M      25
+#elif defined(STM32F412xG) || defined(STM32F413_423xx) || defined (STM32F446xx)
+ #define PLL_M      8
+#elif defined (STM32F410xx) || defined (STM32F411xE)
+ #if defined(USE_HSE_BYPASS)
+  #define PLL_M      8    
+ #else /* !USE_HSE_BYPASS */
+  #define PLL_M      16
+ #endif /* USE_HSE_BYPASS */
+#else
+#endif /* STM32F40_41xxx || STM32F427_437xx || STM32F429_439xx || STM32F401xx || STM32F469_479xx */  
+
+/* USB OTG FS, SDIO and RNG Clock =  PLL_VCO / PLLQ */
+#define PLL_Q      7
+
+#if defined(STM32F446xx)
+/* PLL division factor for I2S, SAI, SYSTEM and SPDIF: Clock =  PLL_VCO / PLLR */
+#define PLL_R      7
+#elif defined(STM32F412xG) || defined(STM32F413_423xx)
+#define PLL_R      2
+#else
+#endif /* STM32F446xx */ 
+
+#if defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F446xx) || defined(STM32F469_479xx)
+#define PLL_N      360
+/* SYSCLK = PLL_VCO / PLL_P */
+#define PLL_P      2
+#endif /* STM32F427_437x || STM32F429_439xx || STM32F446xx || STM32F469_479xx */
+
+#if defined (STM32F40_41xxx)
+#define PLL_N      336
+/* SYSCLK = PLL_VCO / PLL_P */
+#define PLL_P      2
+#endif /* STM32F40_41xxx */
+
+#if defined(STM32F401xx)
+#define PLL_N      336
+/* SYSCLK = PLL_VCO / PLL_P */
+#define PLL_P      4
+#endif /* STM32F401xx */
+
+#if defined(STM32F410xx) || defined(STM32F411xE) || defined(STM32F412xG) || defined(STM32F413_423xx)
+#define PLL_N      400
+/* SYSCLK = PLL_VCO / PLL_P */
+#define PLL_P      4   
+#endif /* STM32F410xx || STM32F411xE || STM32F412xG || STM32F413_423xx */
+
+/******************************************************************************/
+
+/**
+  * @}
+  */
+
+/** @addtogroup STM32F4xx_System_Private_Macros
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/** @addtogroup STM32F4xx_System_Private_Variables
+  * @{
+  */
+
+#if defined(STM32F40_41xxx)
+  uint32_t SystemCoreClock = 168000000;
+#endif /* STM32F40_41xxx */
+
+#if defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F446xx) || defined(STM32F469_479xx)
+  uint32_t SystemCoreClock = 180000000;
+#endif /* STM32F427_437x || STM32F429_439xx || STM32F446xx || STM32F469_479xx */
+
+#if defined(STM32F401xx)
+  uint32_t SystemCoreClock = 84000000;
+#endif /* STM32F401xx */
+
+#if defined(STM32F410xx) || defined(STM32F411xE) || defined(STM32F412xG) || defined(STM32F413_423xx)
+  uint32_t SystemCoreClock = 100000000;
+#endif /* STM32F410xx || STM32F401xE || STM32F412xG || STM32F413_423xx */
+
+__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
+
+/**
+  * @}
+  */
+
+/** @addtogroup STM32F4xx_System_Private_FunctionPrototypes
+  * @{
+  */
+
+static void SetSysClock(void);
+
+#if defined(DATA_IN_ExtSRAM) || defined(DATA_IN_ExtSDRAM)
+static void SystemInit_ExtMemCtl(void); 
+#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
+
+/**
+  * @}
+  */
+
+/** @addtogroup STM32F4xx_System_Private_Functions
+  * @{
+  */
+
+/**
+  * @brief  Setup the microcontroller system
+  *         Initialize the Embedded Flash Interface, the PLL and update the 
+  *         SystemFrequency variable.
+  * @param  None
+  * @retval None
+  */
+void SystemInit(void)
+{
+  /* FPU settings ------------------------------------------------------------*/
+  #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
+    SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */
+  #endif
+  /* Reset the RCC clock configuration to the default reset state ------------*/
+  /* Set HSION bit */
+  RCC->CR |= (uint32_t)0x00000001;
+
+  /* Reset CFGR register */
+  RCC->CFGR = 0x00000000;
+
+  /* Reset HSEON, CSSON and PLLON bits */
+  RCC->CR &= (uint32_t)0xFEF6FFFF;
+
+  /* Reset PLLCFGR register */
+  RCC->PLLCFGR = 0x24003010;
+
+  /* Reset HSEBYP bit */
+  RCC->CR &= (uint32_t)0xFFFBFFFF;
+
+  /* Disable all interrupts */
+  RCC->CIR = 0x00000000;
+
+#if defined(DATA_IN_ExtSRAM) || defined(DATA_IN_ExtSDRAM)
+  SystemInit_ExtMemCtl(); 
+#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
+         
+  /* Configure the System clock source, PLL Multiplier and Divider factors, 
+     AHB/APBx prescalers and Flash settings ----------------------------------*/
+  SetSysClock();
+
+  /* Configure the Vector Table location add offset address ------------------*/
+#ifdef VECT_TAB_SRAM
+  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
+#else
+  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
+#endif
+}
+
+/**
+   * @brief  Update SystemCoreClock variable according to Clock Register Values.
+  *         The SystemCoreClock variable contains the core clock (HCLK), it can
+  *         be used by the user application to setup the SysTick timer or configure
+  *         other parameters.
+  *           
+  * @note   Each time the core clock (HCLK) changes, this function must be called
+  *         to update SystemCoreClock variable value. Otherwise, any configuration
+  *         based on this variable will be incorrect.         
+  *     
+  * @note   - The system frequency computed by this function is not the real 
+  *           frequency in the chip. It is calculated based on the predefined 
+  *           constant and the selected clock source:
+  *             
+  *           - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
+  *                                              
+  *           - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
+  *                          
+  *           - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) 
+  *             or HSI_VALUE(*) multiplied/divided by the PLL factors.
+  *         
+  *         (*) HSI_VALUE is a constant defined in stm32f4xx.h file (default value
+  *             16 MHz) but the real value may vary depending on the variations
+  *             in voltage and temperature.   
+  *    
+  *         (**) HSE_VALUE is a constant defined in stm32f4xx.h file (default value
+  *              25 MHz), user has to ensure that HSE_VALUE is same as the real
+  *              frequency of the crystal used. Otherwise, this function may
+  *              have wrong result.
+  *                
+  *         - The result of this function could be not correct when using fractional
+  *           value for HSE crystal.
+  *     
+  * @param  None
+  * @retval None
+  */
+void SystemCoreClockUpdate(void)
+{
+  uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2;
+#if defined(STM32F412xG) || defined(STM32F413_423xx) || defined(STM32F446xx)  
+  uint32_t pllr = 2;
+#endif /* STM32F412xG || STM32F413_423xx || STM32F446xx */
+  /* Get SYSCLK source -------------------------------------------------------*/
+  tmp = RCC->CFGR & RCC_CFGR_SWS;
+
+  switch (tmp)
+  {
+    case 0x00:  /* HSI used as system clock source */
+      SystemCoreClock = HSI_VALUE;
+      break;
+    case 0x04:  /* HSE used as system clock source */
+      SystemCoreClock = HSE_VALUE;
+      break;
+    case 0x08:  /* PLL P used as system clock source */
+       /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N
+         SYSCLK = PLL_VCO / PLL_P
+         */    
+      pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22;
+      pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
+      
+#if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F401xx) || defined(STM32F412xG) || defined(STM32F413_423xx) || defined(STM32F446xx) || defined(STM32F469_479xx)
+      if (pllsource != 0)
+      {
+        /* HSE used as PLL clock source */
+        pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
+      }
+      else
+      {
+        /* HSI used as PLL clock source */
+        pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
+      }
+#elif defined(STM32F410xx) || defined(STM32F411xE)
+#if defined(USE_HSE_BYPASS)
+      if (pllsource != 0)
+      {
+        /* HSE used as PLL clock source */
+        pllvco = (HSE_BYPASS_INPUT_FREQUENCY / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
+      }  
+#else  
+      if (pllsource == 0)
+      {
+        /* HSI used as PLL clock source */
+        pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
+      }  
+#endif /* USE_HSE_BYPASS */  
+#endif /* STM32F40_41xxx || STM32F427_437xx || STM32F429_439xx || STM32F401xx || STM32F412xG || STM32F413_423xx ||  STM32F446xx || STM32F469_479xx */  
+      pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2;
+      SystemCoreClock = pllvco/pllp;      
+      break;
+#if defined(STM32F412xG) || defined(STM32F413_423xx) || defined(STM32F446xx)      
+      case 0x0C:  /* PLL R used as system clock source */
+       /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N
+         SYSCLK = PLL_VCO / PLL_R
+         */    
+      pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22;
+      pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
+      if (pllsource != 0)
+      {
+        /* HSE used as PLL clock source */
+        pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
+      }
+      else
+      {
+        /* HSI used as PLL clock source */
+        pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);      
+      }
+ 
+      pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >>28) + 1 ) *2;
+      SystemCoreClock = pllvco/pllr;      
+      break;
+#endif /* STM32F412xG || STM32F413_423xx || STM32F446xx */
+    default:
+      SystemCoreClock = HSI_VALUE;
+      break;
+  }
+  /* Compute HCLK frequency --------------------------------------------------*/
+  /* Get HCLK prescaler */
+  tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
+  /* HCLK frequency */
+  SystemCoreClock >>= tmp;
+}
+
+/**
+  * @brief  Configures the System clock source, PLL Multiplier and Divider factors, 
+  *         AHB/APBx prescalers and Flash settings
+  * @Note   This function should be called only once the RCC clock configuration  
+  *         is reset to the default reset state (done in SystemInit() function).   
+  * @param  None
+  * @retval None
+  */
+static void SetSysClock(void)
+{
+#if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F401xx) || defined(STM32F412xG) || defined(STM32F413_423xx) || defined(STM32F446xx)|| defined(STM32F469_479xx)
+/******************************************************************************/
+/*            PLL (clocked by HSE) used as System clock source                */
+/******************************************************************************/
+  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
+  
+  /* Enable HSE */
+  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
+ 
+  /* Wait till HSE is ready and if Time out is reached exit */
+  do
+  {
+    HSEStatus = RCC->CR & RCC_CR_HSERDY;
+    StartUpCounter++;
+  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
+
+  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
+  {
+    HSEStatus = (uint32_t)0x01;
+  }
+  else
+  {
+    HSEStatus = (uint32_t)0x00;
+  }
+
+  if (HSEStatus == (uint32_t)0x01)
+  {
+    /* Select regulator voltage output Scale 1 mode */
+    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
+    PWR->CR |= PWR_CR_VOS;
+
+    /* HCLK = SYSCLK / 1*/
+    RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
+
+#if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) ||  defined(STM32F412xG) || defined(STM32F446xx) || defined(STM32F469_479xx)    
+    /* PCLK2 = HCLK / 2*/
+    RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
+    
+    /* PCLK1 = HCLK / 4*/
+    RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
+#endif /* STM32F40_41xxx || STM32F427_437x || STM32F429_439xx  || STM32F412xG || STM32F446xx || STM32F469_479xx */
+
+#if defined(STM32F401xx) || defined(STM32F413_423xx)
+    /* PCLK2 = HCLK / 1*/
+    RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;
+    
+    /* PCLK1 = HCLK / 2*/
+    RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;
+#endif /* STM32F401xx || STM32F413_423xx */
+
+#if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F401xx) || defined(STM32F469_479xx)    
+    /* Configure the main PLL */
+    RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
+                   (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
+#endif /* STM32F40_41xxx || STM32F401xx || STM32F427_437x || STM32F429_439xx || STM32F469_479xx */
+
+#if  defined(STM32F412xG) || defined(STM32F413_423xx) || defined(STM32F446xx)
+    /* Configure the main PLL */
+    RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
+                   (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24) | (PLL_R << 28);
+#endif /* STM32F412xG || STM32F413_423xx || STM32F446xx */    
+    
+    /* Enable the main PLL */
+    RCC->CR |= RCC_CR_PLLON;
+
+    /* Wait till the main PLL is ready */
+    while((RCC->CR & RCC_CR_PLLRDY) == 0)
+    {
+    }
+   
+#if defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F446xx) || defined(STM32F469_479xx)
+    /* Enable the Over-drive to extend the clock frequency to 180 Mhz */
+    PWR->CR |= PWR_CR_ODEN;
+    while((PWR->CSR & PWR_CSR_ODRDY) == 0)
+    {
+    }
+    PWR->CR |= PWR_CR_ODSWEN;
+    while((PWR->CSR & PWR_CSR_ODSWRDY) == 0)
+    {
+    }      
+    /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
+    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
+#endif /* STM32F427_437x || STM32F429_439xx || STM32F446xx || STM32F469_479xx */
+
+#if defined(STM32F40_41xxx)  || defined(STM32F412xG)  
+    /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
+    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
+#endif /* STM32F40_41xxx  || STM32F412xG */
+
+#if defined(STM32F413_423xx)  
+    /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
+    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_3WS;
+#endif /* STM32F413_423xx */
+
+#if defined(STM32F401xx)
+    /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
+    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_2WS;
+#endif /* STM32F401xx */
+
+    /* Select the main PLL as system clock source */
+    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
+    RCC->CFGR |= RCC_CFGR_SW_PLL;
+
+    /* Wait till the main PLL is used as system clock source */
+    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
+    {
+    }
+  }
+  else
+  { /* If HSE fails to start-up, the application will have wrong clock
+         configuration. User can add here some code to deal with this error */
+  }
+#elif defined(STM32F410xx) || defined(STM32F411xE)
+#if defined(USE_HSE_BYPASS) 
+/******************************************************************************/
+/*            PLL (clocked by HSE) used as System clock source                */
+/******************************************************************************/
+  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
+  
+  /* Enable HSE and HSE BYPASS */
+  RCC->CR |= ((uint32_t)RCC_CR_HSEON | RCC_CR_HSEBYP);
+ 
+  /* Wait till HSE is ready and if Time out is reached exit */
+  do
+  {
+    HSEStatus = RCC->CR & RCC_CR_HSERDY;
+    StartUpCounter++;
+  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
+
+  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
+  {
+    HSEStatus = (uint32_t)0x01;
+  }
+  else
+  {
+    HSEStatus = (uint32_t)0x00;
+  }
+
+  if (HSEStatus == (uint32_t)0x01)
+  {
+    /* Select regulator voltage output Scale 1 mo

[Diff truncated. Use the raw view or local clone for the full content.]