aboutsummaryrefslogtreecommitdiffstats
path: root/src/stm32f
diff options
context:
space:
mode:
Diffstat (limited to 'src/stm32f')
-rw-r--r--src/stm32f/.gitignore1
l---------src/stm32f/FreeRTOS1
-rw-r--r--src/stm32f/Makefile131
-rw-r--r--src/stm32f/bin/.gitignore2
l---------src/stm32f/bsp1
-rw-r--r--src/stm32f/obj/.gitignore2
-rw-r--r--src/stm32f/src/Core/FreeRTOSConfig.h3
-rw-r--r--src/stm32f/src/Core/common.c7
-rw-r--r--src/stm32f/src/Core/main.c74
-rw-r--r--src/stm32f/src/Core/usart.c280
l---------src/stm32f/tm_stm32f4_ds18b20.c1
l---------src/stm32f/tm_stm32f4_ds18b20.h1
l---------src/stm32f/tm_stm32f4_onewire.c1
l---------src/stm32f/tm_stm32f4_onewire.h1
14 files changed, 506 insertions, 0 deletions
diff --git a/src/stm32f/.gitignore b/src/stm32f/.gitignore
new file mode 100644
index 0000000..6533942
--- /dev/null
+++ b/src/stm32f/.gitignore
@@ -0,0 +1 @@
+vc.h
diff --git a/src/stm32f/FreeRTOS b/src/stm32f/FreeRTOS
new file mode 120000
index 0000000..51f4e96
--- /dev/null
+++ b/src/stm32f/FreeRTOS
@@ -0,0 +1 @@
+../FreeRTOS \ No newline at end of file
diff --git a/src/stm32f/Makefile b/src/stm32f/Makefile
new file mode 100644
index 0000000..a26cdbd
--- /dev/null
+++ b/src/stm32f/Makefile
@@ -0,0 +1,131 @@
+###
+# GNU ARM Embedded Toolchain
+CC=arm-none-eabi-gcc
+LD=arm-none-eabi-ld
+AR=arm-none-eabi-ar
+AS=arm-none-eabi-as
+CP=arm-none-eabi-objcopy
+OD=arm-none-eabi-objdump
+SIZE=arm-none-eabi-size
+
+###
+# Directory Structure
+BINDIR=bin
+SRCDIR=.
+ODIR=obj
+
+###
+# Find source files
+ASOURCES=$(shell find -L $(SRCDIR) -name '*.s')
+CSOURCES+=$(shell find -L $(SRCDIR) -name '*.c')
+# Find header directories
+INC=$(shell find -L . -name '*.h' -exec dirname {} \; | uniq)
+INCLUDES=$(INC:%=-I%) -I ../common/includes/
+# Create object list
+OBJECTS=$(ASOURCES:%.s=%.o)
+OBJECTS+=$(CSOURCES:%.c=obj/%.o)
+# Define output files ELF & IHEX
+BINELF=outp.elf
+BINHEX=outp.hex
+
+###
+# MCU FLAGS
+MCFLAGS=-mcpu=cortex-m4 -mthumb -mlittle-endian \
+-mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb-interwork
+# COMPILE FLAGS
+DEFS=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DARM_MATH_CM4 -D__FPU_PRESENT=1
+CFLAGS =-Wall -ggdb -std=c99 -c $(MCFLAGS) $(DEFS) $(INCLUDES)
+# LINKER FLAGS
+LDSCRIPT= bsp/stm32_flash.ld
+LDFLAGS =-T $(LDSCRIPT) --specs=nosys.specs $(MCFLAGS) -Wl,-Map=$(BINDIR)/outp.map
+
+###
+# Optimizations
+OPT?='O2 O3 O6'
+# O1 and O4 are irrelevant
+# O5 breaks FreeRTOS somehow
+# I'm not trusting O7
+
+ifneq ($(filter O1,$(OPT)),)
+CXXFLAGS+=-fno-exceptions # Uncomment to disable exception handling
+DEFS+=-DNO_EXCEPTIONS # The source code has to comply with this rule
+endif
+
+ifneq ($(filter O2,$(OPT)),)
+CFLAGS+=-Os # Optimize for size https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
+CXXFLAGS+=-Os
+LDFLAGS+=-Os # Optimize for size https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
+endif
+
+ifneq ($(filter O3,$(OPT)),)
+CFLAGS+=-ffunction-sections -fdata-sections # Place each function or data item into its own section in the output file
+CXXFLAGS+=-ffunction-sections -fdata-sections # -||-
+LDFLAGS+=-Wl,-gc-sections # Remove isolated unused sections
+endif
+
+ifneq ($(filter O4,$(OPT)),)
+CFLAGS+=-fno-builtin # Disable C++ exception handling
+CXXFLAGS+=-fno-builtin # Disable C++ exception handling
+endif
+
+ifneq ($(filter O5,$(OPT)),)
+CFLAGS+=-flto # Enable link time optimization
+CXXFLAGS+=-flto # Enable link time optimization
+LDFLAGS+=-flto # Enable link time optimization
+endif
+
+ifneq ($(filter O6,$(OPT)),)
+CXXFLAGS+=-fno-rtti # Disable type introspection
+endif
+
+ifneq ($(findstring O7,$(OPT)),)
+LDFLAGS+=--specs=nano.specs # Use size optimized newlib
+endif
+
+###
+# Build Rules
+.PHONY: all release debug clean
+
+all: release
+
+release: $(BINDIR)/$(BINHEX)
+
+debug: CFLAGS+=-g
+debug: LDFLAGS+=-g
+debug: release
+
+$(BINDIR)/$(BINHEX): $(BINDIR)/$(BINELF)
+ $(CP) -O ihex $< $@
+
+$(BINDIR)/$(BINELF): $(OBJECTS) vc.h
+ $(CC) $(LDFLAGS) $(OBJECTS) -o $@
+ $(SIZE) $(BINDIR)/$(BINELF)
+
+dir_guard=@mkdir -p $(@D)
+
+obj/%.o: %.c $(INC)
+ $(dir_guard)
+ $(CC) $(CFLAGS) $< -o $@
+
+obj/%.o: %.s
+ $(dir_guard)
+ $(CC) $(CFLAGS) $< -o $@
+
+vc.h: ../../.git/logs/HEAD
+ echo "// This file is generated by Makefile." > vc.h
+ echo "// Do not edit this file!" >> vc.h
+ git log -1 --format="format:#define GIT_VERSION \"%h\"" >> vc.h
+ echo >> vc.h
+ echo >> vc.h
+
+clean:
+ rm -f $(OBJECTS) $(BINDIR)/$(BINELF) $(BINDIR)/$(BINHEX)
+
+# Connect to openocd's gdb server on port 3333
+deploy: $(BINDIR)/$(BINELF)
+ifeq ($(wildcard /opt/openocd/bin/openocd),)
+ /usr/bin/openocd -f /usr/share/openocd/scripts/board/stm32f4discovery.cfg -c "program bin/"$(BINELF)" verify reset" -c "init" -c "reset" -c "exit"
+else
+ /opt/openocd/bin/openocd -f /opt/openocd/share/openocd/scripts/board/stm32f4discovery.cfg -c "program bin/"$(BINELF)" verify reset" -c "init" -c "reset" -c "exit"
+endif
+
diff --git a/src/stm32f/bin/.gitignore b/src/stm32f/bin/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/src/stm32f/bin/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/src/stm32f/bsp b/src/stm32f/bsp
new file mode 120000
index 0000000..5d9120a
--- /dev/null
+++ b/src/stm32f/bsp
@@ -0,0 +1 @@
+../bsp \ No newline at end of file
diff --git a/src/stm32f/obj/.gitignore b/src/stm32f/obj/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/src/stm32f/obj/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/src/stm32f/src/Core/FreeRTOSConfig.h b/src/stm32f/src/Core/FreeRTOSConfig.h
new file mode 100644
index 0000000..8d6f128
--- /dev/null
+++ b/src/stm32f/src/Core/FreeRTOSConfig.h
@@ -0,0 +1,3 @@
+#include "../../../common/src/Core/FreeRTOSConfig.h"
+
+#define configCHECK_FOR_STACK_OVERFLOW 2 // Default: 2
diff --git a/src/stm32f/src/Core/common.c b/src/stm32f/src/Core/common.c
new file mode 100644
index 0000000..a647d26
--- /dev/null
+++ b/src/stm32f/src/Core/common.c
@@ -0,0 +1,7 @@
+#include <stm32f4xx.h>
+
+#include "../../../common/src/Core/common.c"
+
+void hard_fault_handler_extra() {
+ usart_debug("SCB_SHCSR = %x\n", SCB->SHCSR);
+}
diff --git a/src/stm32f/src/Core/main.c b/src/stm32f/src/Core/main.c
new file mode 100644
index 0000000..65d535e
--- /dev/null
+++ b/src/stm32f/src/Core/main.c
@@ -0,0 +1,74 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Matthias P. Braendli, Maximilien Cuony
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+*/
+
+#include "stm32f4xx_conf.h"
+
+
+#define GPIOD_BOARD_LED_GREEN GPIO_Pin_12
+#define GPIOD_BOARD_LED_ORANGE GPIO_Pin_13
+#define GPIOD_BOARD_LED_RED GPIO_Pin_14
+#define GPIOD_BOARD_LED_BLUE GPIO_Pin_15
+
+#include "../../../common/src/Core/main.c"
+
+
+void init() {
+ /* Initialise the onboard peripherals
+ * Four LEDs and one push-button
+ */
+ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
+ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
+
+ // Configure PD12, PD13, PD14 and PD15 in output pushpull mode
+ GPIO_InitTypeDef GPIO_InitStructure;
+ GPIO_InitStructure.GPIO_Pin =
+ GPIOD_BOARD_LED_GREEN |
+ GPIOD_BOARD_LED_ORANGE |
+ GPIOD_BOARD_LED_RED |
+ GPIOD_BOARD_LED_BLUE;
+
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+ GPIO_Init(GPIOD, &GPIO_InitStructure);
+
+ // Init PushButton
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; // TODO is there an external pullup ?
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
+
+
+ /* Setup Watchdog
+ * The IWDG runs at 32kHz. With a prescaler of 32 -> 1kHz.
+ * Counting to 2000 / 1000 = 2 seconds
+ */
+ IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
+ IWDG_SetPrescaler(IWDG_Prescaler_32);
+ IWDG_SetReload(2000);
+ IWDG_Enable();
+}
diff --git a/src/stm32f/src/Core/usart.c b/src/stm32f/src/Core/usart.c
new file mode 100644
index 0000000..29c8a20
--- /dev/null
+++ b/src/stm32f/src/Core/usart.c
@@ -0,0 +1,280 @@
+
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Matthias P. Braendli
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+*/
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <inttypes.h>
+#include "Core/common.h"
+#include "Core/usart.h"
+#include <stm32f4xx.h>
+#include <stm32f4xx_usart.h>
+#include <stm32f4xx_conf.h>
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+
+/* USART 3 on PD8 and PD9
+ * See pio.txt for PIO allocation details */
+const uint16_t GPIOD_PIN_USART3_TX = GPIO_Pin_8;
+const uint16_t GPIOD_PIN_USART3_RX = GPIO_Pin_9;
+
+/* USART 2 on PA2 and PA3 */
+const uint16_t GPIOA_PIN_USART2_RX = GPIO_Pin_3;
+const uint16_t GPIOA_PIN_USART2_TX = GPIO_Pin_2;
+
+// The ISR writes into this buffer
+static char nmea_sentence[MAX_NMEA_SENTENCE_LEN];
+static int nmea_sentence_last_written = 0;
+
+// Once a completed NMEA sentence is received in the ISR,
+// it is appended to this queue
+static QueueHandle_t usart_nmea_queue;
+
+void usart_init()
+{
+ // ============== PC DEBUG USART ===========
+ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
+ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
+
+ GPIO_InitTypeDef GPIO_InitStruct;
+ GPIO_InitStruct.GPIO_Pin = GPIOA_PIN_USART2_RX | GPIOA_PIN_USART2_TX;
+ GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
+ GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
+ GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
+ GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
+ GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+ GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
+ GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);
+
+ // Setup USART2 for 9600,8,N,1
+ USART_InitTypeDef USART_InitStruct;
+ USART_InitStruct.USART_BaudRate = 9600;
+ USART_InitStruct.USART_WordLength = USART_WordLength_8b;
+ USART_InitStruct.USART_StopBits = USART_StopBits_1;
+ USART_InitStruct.USART_Parity = USART_Parity_No;
+ USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
+ USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
+ USART_Init(USART2, &USART_InitStruct);
+
+#if USART2_RECEIVE_ENABLE
+ // enable the USART2 receive interrupt
+ USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
+
+ NVIC_InitTypeDef NVIC_InitStructure;
+ NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
+ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 6;
+ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
+ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+ NVIC_Init(&NVIC_InitStructure);
+
+ NVIC_SetPriority(USART2_IRQn, 6);
+#endif
+
+ // finally this enables the complete USART2 peripheral
+ USART_Cmd(USART2, ENABLE);
+}
+
+void usart_gps_init()
+{
+ usart_nmea_queue = xQueueCreate(15, MAX_NMEA_SENTENCE_LEN);
+ if (usart_nmea_queue == 0) {
+ while(1); /* fatal error */
+ }
+
+ // ============== GPS USART ===========
+ // Setup GPIO D and connect to USART 3
+ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
+ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
+
+ GPIO_InitTypeDef GPIO_InitStruct;
+ GPIO_InitStruct.GPIO_Pin = GPIOD_PIN_USART3_RX | GPIOD_PIN_USART3_TX;
+ GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
+ GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
+ GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
+ GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
+ GPIO_Init(GPIOD, &GPIO_InitStruct);
+
+ GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_USART3);
+ GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_USART3);
+
+ // Setup USART3 for 9600,8,N,1
+ USART_InitTypeDef USART_InitStruct;
+ USART_InitStruct.USART_BaudRate = 9600;
+ USART_InitStruct.USART_WordLength = USART_WordLength_8b;
+ USART_InitStruct.USART_StopBits = USART_StopBits_1;
+ USART_InitStruct.USART_Parity = USART_Parity_No;
+ USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
+ USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
+ USART_Init(USART3, &USART_InitStruct);
+
+
+ // enable the USART3 receive interrupt
+ USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
+
+ NVIC_InitTypeDef NVIC_InitStructure;
+ NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
+ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 6;
+ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
+ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+ NVIC_Init(&NVIC_InitStructure);
+
+ NVIC_SetPriority(USART3_IRQn, 6);
+
+ // finally this enables the complete USART3 peripheral
+ USART_Cmd(USART3, ENABLE);
+}
+
+// Make sure Tasks are suspended when this is called!
+static void usart_puts(USART_TypeDef* USART, const char* str)
+{
+ while(*str) {
+ // wait until data register is empty
+ USART_SendData(USART, *str);
+ while(USART_GetFlagStatus(USART, USART_FLAG_TXE) == RESET) ;
+ str++;
+ }
+}
+
+void usart_gps_puts(const char* str)
+{
+ vTaskSuspendAll();
+ return usart_puts(USART3, str);
+ xTaskResumeAll();
+}
+
+#define MAX_MSG_LEN 80
+static char usart_debug_message[MAX_MSG_LEN];
+
+void usart_debug_timestamp()
+{
+ // Don't call printf here, to reduce stack usage
+ uint64_t now = timestamp_now();
+ if (now == 0) {
+ usart_puts(USART2, "[0] ");
+ }
+ else {
+ char ts_str[64];
+ int i = 63;
+
+ ts_str[i--] = '\0';
+ ts_str[i--] = ' ';
+ ts_str[i--] = ']';
+
+ while (now > 0 && i >= 0) {
+ ts_str[i--] = '0' + (now % 10);
+ now /= 10;
+ }
+ ts_str[i] = '[';
+
+ usart_puts(USART2, &ts_str[i]);
+ }
+}
+
+void usart_debug(const char *format, ...)
+{
+ va_list list;
+ va_start(list, format);
+ vsnprintf(usart_debug_message, MAX_MSG_LEN-1, format, list);
+
+ vTaskSuspendAll();
+ usart_debug_timestamp();
+ usart_puts(USART2, usart_debug_message);
+ xTaskResumeAll();
+
+ va_end(list);
+}
+
+void usart_debug_puts(const char* str)
+{
+ vTaskSuspendAll();
+ usart_debug_timestamp();
+ usart_puts(USART2, str);
+ xTaskResumeAll();
+}
+
+int usart_get_nmea_sentence(char* nmea)
+{
+ return xQueueReceive(usart_nmea_queue, nmea, portMAX_DELAY);
+}
+
+
+static void usart_clear_nmea_buffer(void)
+{
+ for (int i = 0; i < MAX_NMEA_SENTENCE_LEN; i++) {
+ nmea_sentence[i] = '\0';
+ }
+ nmea_sentence_last_written = 0;
+}
+
+void USART3_IRQHandler(void)
+{
+ if (USART_GetITStatus(USART3, USART_IT_RXNE)) {
+ char t = USART3->DR;
+
+ if (nmea_sentence_last_written == 0) {
+ if (t == '$') {
+ // Likely new start of sentence
+ nmea_sentence[nmea_sentence_last_written] = t;
+ nmea_sentence_last_written++;
+ }
+ }
+ else if (nmea_sentence_last_written < MAX_NMEA_SENTENCE_LEN) {
+ nmea_sentence[nmea_sentence_last_written] = t;
+ nmea_sentence_last_written++;
+
+ if (t == '\n') {
+ int success = xQueueSendToBackFromISR(
+ usart_nmea_queue,
+ nmea_sentence,
+ NULL);
+
+ if (success == pdFALSE) {
+ trigger_fault(FAULT_SOURCE_USART);
+ }
+
+ usart_clear_nmea_buffer();
+ }
+ }
+ else {
+ // Buffer overrun without a meaningful NMEA message.
+ usart_clear_nmea_buffer();
+ }
+ }
+}
+
+void USART2_IRQHandler(void)
+{
+ if (USART_GetITStatus(USART2, USART_IT_RXNE)) {
+ char t = USART2->DR;
+ if (t == 'h') {
+ usart_debug_puts("help: no commands supported yet!\r\n");
+ }
+ else {
+ usart_debug("Unknown command %c\r\n", t);
+ }
+ }
+}
diff --git a/src/stm32f/tm_stm32f4_ds18b20.c b/src/stm32f/tm_stm32f4_ds18b20.c
new file mode 120000
index 0000000..1dca5f5
--- /dev/null
+++ b/src/stm32f/tm_stm32f4_ds18b20.c
@@ -0,0 +1 @@
+../ds18b20/tm_stm32f4_ds18b20.c \ No newline at end of file
diff --git a/src/stm32f/tm_stm32f4_ds18b20.h b/src/stm32f/tm_stm32f4_ds18b20.h
new file mode 120000
index 0000000..6b8bae8
--- /dev/null
+++ b/src/stm32f/tm_stm32f4_ds18b20.h
@@ -0,0 +1 @@
+../ds18b20/tm_stm32f4_ds18b20.h \ No newline at end of file
diff --git a/src/stm32f/tm_stm32f4_onewire.c b/src/stm32f/tm_stm32f4_onewire.c
new file mode 120000
index 0000000..21e6c82
--- /dev/null
+++ b/src/stm32f/tm_stm32f4_onewire.c
@@ -0,0 +1 @@
+../ds18b20/tm_stm32f4_onewire.c \ No newline at end of file
diff --git a/src/stm32f/tm_stm32f4_onewire.h b/src/stm32f/tm_stm32f4_onewire.h
new file mode 120000
index 0000000..1779648
--- /dev/null
+++ b/src/stm32f/tm_stm32f4_onewire.h
@@ -0,0 +1 @@
+../ds18b20/tm_stm32f4_onewire.h \ No newline at end of file