Compare commits
24 Commits
error-mem-
...
v0.2-test
Author | SHA1 | Date | |
---|---|---|---|
8576bf4231 | |||
6ebd74cb31 | |||
46125ba752 | |||
6c9f90c986 | |||
74defd5384 | |||
5deac33949 | |||
666353e3b7 | |||
df40ab1be7 | |||
4c3574c2e2 | |||
289f49204d | |||
4bc98e6baf | |||
e50ce0d541 | |||
78b63c853f | |||
a25b249d77 | |||
e815442617 | |||
60104df30e | |||
5ab911b4b6 | |||
08427cc589 | |||
ba6e0880b4 | |||
6a71416d2a | |||
1ecd5edd93 | |||
1b4eba1871 | |||
e3e4a6d926 | |||
93ff4959a2 |
BIN
doc/source/hardware/hw_watchdog_delay.png
Normal file
BIN
doc/source/hardware/hw_watchdog_delay.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
BIN
doc/source/hardware/hw_watchdog_startup.png
Normal file
BIN
doc/source/hardware/hw_watchdog_startup.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
1
stm-firmware/.gitignore
vendored
1
stm-firmware/.gitignore
vendored
@@ -15,3 +15,4 @@ reflow-controller.includes
|
||||
*.config
|
||||
*.files
|
||||
*.user.*
|
||||
*.user
|
||||
|
86
stm-firmware/CMakeLists.txt
Normal file
86
stm-firmware/CMakeLists.txt
Normal file
@@ -0,0 +1,86 @@
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||
set(CMAKE_CROSSCOMPILING 1)
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
set(CMAKE_TOOLCHAIN_FILE "arm-none-eabi-gcc.cmake")
|
||||
|
||||
project(reflow-controller)
|
||||
|
||||
if(NOT WIN32)
|
||||
string(ASCII 27 Esc)
|
||||
set(ColorReset "${Esc}[m")
|
||||
set(ColorBold "${Esc}[1m")
|
||||
set(Red "${Esc}[31m")
|
||||
set(Green "${Esc}[32m")
|
||||
set(Yellow "${Esc}[33m")
|
||||
set(Blue "${Esc}[34m")
|
||||
set(Magenta "${Esc}[35m")
|
||||
set(Cyan "${Esc}[36m")
|
||||
set(White "${Esc}[37m")
|
||||
set(BoldRed "${Esc}[1;31m")
|
||||
set(BoldGreen "${Esc}[1;32m")
|
||||
set(BoldYellow "${Esc}[1;33m")
|
||||
set(BoldBlue "${Esc}[1;34m")
|
||||
set(BoldMagenta "${Esc}[1;35m")
|
||||
set(BoldCyan "${Esc}[1;36m")
|
||||
set(BoldWhite "${Esc}[1;37m")
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND bash -c "echo -n $(git describe --always --tags --dirty)"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_DESCRIBE)
|
||||
|
||||
set(ELFFILE ${PROJECT_NAME}.elf)
|
||||
set(LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/stm32f407vet6_flash.ld)
|
||||
|
||||
add_compile_options(-Wall -Wextra -Wold-style-declaration -Wuninitialized -Wmaybe-uninitialized -Wunused-parameter)
|
||||
add_compile_options(-mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork -mfloat-abi=hard -mfpu=fpv4-sp-d16 -nostartfiles -Wimplicit-fallthrough=3 -Wsign-compare)
|
||||
|
||||
|
||||
set(GIT_DESCRIBE "${GIT_DESCRIBE}")
|
||||
add_definitions(-DBASE64_LOOKUP_TABLE_SECTION=\".ccm.bss\" -DSHELLMATTA_HELP_ALIAS=\"?\" -DGIT_VER=${GIT_DESCRIBE} -DHSE_VALUE=8000000UL -DSTM32F407xx -DSTM32F4XX -DARM_MATH_CM4)
|
||||
|
||||
add_subdirectory(updater/ram-code)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
message("${BoldGreen}Version: ${GIT_DESCRIBE}${ColorReset}")
|
||||
|
||||
IF(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
add_definitions(-DDEBUGBUILD)
|
||||
add_compile_options(-O0 -g)
|
||||
ELSE()
|
||||
add_definitions(-DDEBUGBUILD)
|
||||
add_compile_options(-O3 -g)
|
||||
add_link_options(-Wl,--gc-sections)
|
||||
ENDIF(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
|
||||
add_subdirectory(base64-lib)
|
||||
|
||||
|
||||
aux_source_directory("." MAIN_SOURCES)
|
||||
aux_source_directory("config-parser" CFG_PARSER_SRCS)
|
||||
aux_source_directory("ui" UI_SRCS)
|
||||
aux_source_directory("fatfs" FAT_SRCS)
|
||||
aux_source_directory("fatfs/shimatta_sdio_driver" SDIO_SRCS)
|
||||
aux_source_directory("boot" BOOT_SRCS)
|
||||
aux_source_directory("setup" SETUP_SRCS)
|
||||
aux_source_directory("stm-periph" STM_PERIPH_SRCS)
|
||||
aux_source_directory("settings" SETTINGS_SRCS)
|
||||
aux_source_directory("safety" SAFETY_SRCS)
|
||||
aux_source_directory("shellmatta/src" SHELLMATTA_SRCS)
|
||||
aux_source_directory("updater" UPDATER_SRCS)
|
||||
|
||||
add_executable(${ELFFILE} ${MAIN_SOURCES} ${CFG_PARSER_SRCS} ${UI_SRCS}
|
||||
${FAT_SRCS} ${SDIO_SRCS} ${BOOT_SRCS} ${SETUP_SRCS}
|
||||
${STM_PERIPH_SRCS} ${SETTINGS_SRCS} ${SAFETY_SRCS} ${SHELLMATTA_SRCS} ${UPDATER_SRCS}
|
||||
)
|
||||
|
||||
add_dependencies(${ELFFILE} updater-ram-code-header-blob)
|
||||
|
||||
target_include_directories(${ELFFILE} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/shellmatta/api ${CMAKE_CURRENT_SOURCE_DIR}/config-parser/include)
|
||||
target_link_options(${ELFFILE} PRIVATE -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork -mfloat-abi=hard -mfpu=fpv4-sp-d16 --disable-newlib-supplied-syscalls -nostartfiles -T${LINKER_SCRIPT} -Wl,--print-memory-usage)
|
||||
target_link_libraries(${ELFFILE} base64-lib)
|
||||
target_include_directories(${ELFFILE} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/updater/ram-code/include/")
|
||||
|
@@ -1,224 +0,0 @@
|
||||
################################Shimatta Makefile####################################
|
||||
#CPU: STM32F407VET6
|
||||
#Compiler: arm-none-eabi
|
||||
#####################################################################################
|
||||
#Add Files and Folders below#########################################################
|
||||
CFILES = main.c syscalls.c setup/system_stm32f4xx.c systick.c boot/startup_stm32f407vx.c
|
||||
ASFILES =
|
||||
INCLUDEPATH = -Iinclude
|
||||
|
||||
OBJDIR_BASE = obj
|
||||
TARGET_BASE = reflow-controller
|
||||
LIBRARYPATH = -L.
|
||||
LIBRARIES =
|
||||
|
||||
DEFINES = -DSTM32F407xx -DSTM32F4XX -DARM_MATH_CM4 -DHSE_VALUE=8000000UL
|
||||
MAPFILE_BASE = memory-mapping
|
||||
LINKER_SCRIPT=stm32f407vet6_flash.ld
|
||||
|
||||
export GIT_VER = $(shell git describe --always --dirty --tags)
|
||||
DEFINES += -DGIT_VER=$(GIT_VER)
|
||||
|
||||
ifneq ($(VERBOSE),true)
|
||||
QUIET=@
|
||||
else
|
||||
QUIET=
|
||||
endif
|
||||
|
||||
##Custom Files###
|
||||
CFILES += adc-meas.c
|
||||
|
||||
# Shellmatta
|
||||
CFILES += shellmatta/src/shellmatta.c shellmatta/src/shellmatta_autocomplete.c shellmatta/src/shellmatta_escape.c shellmatta/src/shellmatta_history.c shellmatta/src/shellmatta_utils.c shellmatta/src/shellmatta_opt.c shell.c
|
||||
INCLUDEPATH += -Ishellmatta/api
|
||||
DEFINES += -DSHELLMATTA_HELP_ALIAS=\"?\"
|
||||
|
||||
# RCC Manager
|
||||
CFILES += stm-periph/rcc-manager.c
|
||||
CFILES += stm-periph/uart.c stm-periph/dma-ring-buffer.c stm-periph/backup-ram.c
|
||||
CFILES += stm-periph/rng.c stm-periph/spi.c
|
||||
CFILES += digio.c
|
||||
CFILES += stm-periph/unique-id.c
|
||||
CFILES += calibration.c
|
||||
CFILES += temp-converter.c
|
||||
CFILES += rotary-encoder.c button.c
|
||||
CFILES += ui/lcd.c ui/menu.c ui/gui.c
|
||||
CFILES += fatfs/diskio.c fatfs/ff.c fatfs/ffsystem.c fatfs/ffunicode.c fatfs/shimatta_sdio_driver/shimatta_sdio.c
|
||||
CFILES += pid-controller.c oven-driver.c
|
||||
CFILES += settings/settings.c settings/settings-sd-card.c settings/spi-eeprom.c settings/settings-eeprom.c
|
||||
CFILES += stm-periph/crc-unit.c
|
||||
CFILES += safety/safety-adc.c safety/safety-controller.c safety/watchdog.c safety/fault.c safety/safety-memory.c safety/stack-check.c
|
||||
CFILES += hw-version-detect.c
|
||||
CFILES += config-parser/config-parser.c
|
||||
CFILES += updater/updater.c
|
||||
INCLUDEPATH += -Iconfig-parser/include
|
||||
|
||||
CFILES += base64-lib/src/base64-lib.c
|
||||
INCLUDEPATH += -Ibase64-lib/include
|
||||
DEFINES += -DBASE64_LOOKUP_TABLE_SECTION="\".ccm.bss\""
|
||||
|
||||
|
||||
DEBUG_DEFINES = -DDEBUGBUILD
|
||||
RELEASE_DEFINES = -DUART_ON_DEBUG_HEADER
|
||||
|
||||
###################################################################################
|
||||
ifeq ($(CROSS_COMPILE),)
|
||||
CROSS_COMPILE=arm-none-eabi-
|
||||
endif
|
||||
|
||||
CC=$(CROSS_COMPILE)gcc
|
||||
OBJCOPY=$(CROSS_COMPILE)objcopy
|
||||
OBJDUMP=$(CROSS_COMPILE)objdump
|
||||
SIZE=$(CROSS_COMPILE)size
|
||||
|
||||
CFLAGS_RELEASE = -O3 -g
|
||||
CFLAGS_DEBUG = -O0 -g
|
||||
|
||||
LFLAGS_RELEASE = -Wl,--gc-sections
|
||||
LFLAGS_DEBUG =
|
||||
|
||||
CFLAGS =
|
||||
LFLAGS =
|
||||
|
||||
ifneq ($(DEBUGBUILD),true)
|
||||
DEFINES += $(RELEASE_DEFINES)
|
||||
CFLAGS += $(CFLAGS_RELEASE)
|
||||
LFLAGS += $(LFLAGS_RELEASE)
|
||||
target = $(TARGET_BASE)-release
|
||||
OBJDIR = $(OBJDIR_BASE)/release
|
||||
MAPFILE = $(MAPFILE_BASE)-release
|
||||
else
|
||||
DEFINES += $(DEBUG_DEFINES)
|
||||
target = $(TARGET_BASE)-debug
|
||||
CFLAGS += $(CFLAGS_DEBUG)
|
||||
LFLAGS += $(LFLAGS_DEBUG)
|
||||
OBJDIR = $(OBJDIR_BASE)/debug
|
||||
MAPFILE = $(MAPFILE_BASE)-debug
|
||||
endif
|
||||
|
||||
LFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork
|
||||
LFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 --disable-newlib-supplied-syscalls -nostartfiles
|
||||
LFLAGS += -T$(LINKER_SCRIPT) -Wl,-Map=$(MAPFILE).map -Wl,--print-memory-usage
|
||||
|
||||
CFLAGS += -c -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork
|
||||
CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 -nostartfiles
|
||||
CFLAGS += -Wall -Wextra -Wold-style-declaration -Wuninitialized -Wmaybe-uninitialized -Wunused-parameter -Wimplicit-fallthrough=3 -Wsign-compare
|
||||
|
||||
####################################################################################
|
||||
|
||||
OBJ = $(CFILES:%.c=$(OBJDIR)/%.c.o)
|
||||
ASOBJ += $(ASFILES:%.S=$(OBJDIR)/%.S.o)
|
||||
|
||||
default: $(target).elf
|
||||
|
||||
all: debug release
|
||||
|
||||
release:
|
||||
$(QUIET)$(MAKE) DEBUGBUILD=false
|
||||
|
||||
debug:
|
||||
$(QUIET)$(MAKE) DEBUGBUILD=true
|
||||
|
||||
%.bin: %.elf
|
||||
$(QUIET)$(OBJCOPY) -O binary $^ $@
|
||||
%.hex: %.elf
|
||||
$(QUIET)$(OBJCOPY) -O ihex $^ $@
|
||||
|
||||
|
||||
#Linking
|
||||
$(target).elf: $(OBJ) $(ASOBJ) $(LINKER_SCRIPT)
|
||||
@echo [LD] $@
|
||||
$(QUIET)$(CC) $(LFLAGS) $(LIBRARYPATH) -o $@ $(OBJ) $(ASOBJ) $(LIBRARIES)
|
||||
$(QUIET)$(SIZE) $@
|
||||
@echo "Built Version $(GIT_VER)"
|
||||
|
||||
$(OBJDIR)/updater/updater.c.o: updater/ram-code/updater-ram-code.bin.h
|
||||
|
||||
#Compiling
|
||||
$(OBJ):
|
||||
@echo [CC] $@
|
||||
$(eval OUTPATH=$(dir $@))
|
||||
@mkdir -p $(OUTPATH)
|
||||
$(QUIET)$(CC) $(CFLAGS) -MMD -MT $@ $(INCLUDEPATH) $(DEFINES) -o $@ $(@:$(OBJDIR)/%.c.o=%.c)
|
||||
$(ASOBJ):
|
||||
@echo [AS] $@
|
||||
$(eval OUTPATH=$(dir $@))
|
||||
@mkdir -p $(OUTPATH)
|
||||
$(QUIET)$(CC) $(CFLAGS) -MMD -MT $@ $(INCLUDEPATH) $(DEFINES) -o $@ $(@:$(OBJDIR)/%.S.o=%.S)
|
||||
|
||||
|
||||
.PHONY: qtproject-legacy qtproject qtproject-debug clean mrproper objcopy disassemble program program-debug updater/ram-code/updater-ram-code.bin.h
|
||||
|
||||
updater/ram-code/updater-ram-code.bin.h:
|
||||
$(QUIET)$(MAKE) -C updater/ram-code updater-ram-code.bin.h
|
||||
|
||||
program-debug:
|
||||
$(QUIET)$(MAKE) DEBUGBUILD=true program
|
||||
|
||||
program: $(target).elf
|
||||
./program-device.sh $<
|
||||
|
||||
disassemble: $(target).elf
|
||||
$(QUIET)$(OBJDUMP) -D -s $< > $(target).lss
|
||||
|
||||
objcopy: $(target).bin $(target).hex
|
||||
|
||||
mrproper: clean
|
||||
ifneq ($(DEBUGBUILD),true)
|
||||
@echo "Purging RELEASE project files"
|
||||
else
|
||||
@echo "Purging DEBUG project files"
|
||||
endif
|
||||
$(QUIET)rm -f $(target).pro $(target).creator $(target).files $(target).cflags $(target).cxxflags $(target).includes $(target).config
|
||||
ifneq ($(DEBUGBUILD),true)
|
||||
$(QUIET)$(MAKE) DEBUGBUILD=true mrproper
|
||||
endif
|
||||
|
||||
|
||||
clean:
|
||||
@echo -n "Cleaning up derived files for "
|
||||
ifneq ($(DEBUGBUILD),true)
|
||||
@echo "RELEASE build"
|
||||
else
|
||||
@echo "DEBUG build"
|
||||
endif
|
||||
$(QUIET)rm -f $(target).elf $(target).bin $(target).hex $(OBJ) $(ASOBJ) $(mapfile).map $(CFILES:%.c=$(OBJDIR)/%.c.d) $(ASFILES:%.S=$(OBJDIR)/%.S.d)
|
||||
$(QUIET)rm -rf $(OBJDIR)/*
|
||||
$(MAKE) -C updater/ram-code clean
|
||||
ifneq ($(DEBUGBUILD),true)
|
||||
$(QUIET)$(MAKE) DEBUGBUILD=true clean
|
||||
endif
|
||||
|
||||
qtproject-legacy:
|
||||
echo -e "TEMPLATE = app\nCONFIG -= console app_bundle qt" > $(target).pro
|
||||
echo -e "SOURCES += $(CFILES) $(ASFILES)" >> $(target).pro
|
||||
echo -ne "INCLUDEPATH += " >> $(target).pro
|
||||
echo "$(INCLUDEPATH)" | sed "s!-I!./!g" >> $(target).pro
|
||||
echo -ne "HEADERS += " >> $(target).pro
|
||||
find -name "*.h" | tr "\\n" " " >> $(target).pro
|
||||
echo -ne "\nDEFINES += " >> $(target).pro
|
||||
echo "$(DEFINES)" | sed "s/-D//g" >> $(target).pro
|
||||
|
||||
qtproject-debug:
|
||||
@echo "Generating debug build project"
|
||||
$(QUIET)$(MAKE) DEBUGBUILD=true qtproject
|
||||
|
||||
qtproject:
|
||||
$(QUIET)rm -f $(target).files $(target).cflags $(target).config $(target).creator $(target).includes $(target).creator.user
|
||||
@echo "Generating source file list"
|
||||
$(QUIET)echo "$(CFILES)" | tr ' ' '\n' > $(target).files
|
||||
@echo -n "Appending found header files from folders "
|
||||
@echo `echo $(INCLUDEPATH) | sed "s/-I//g"`
|
||||
$(QUIET)for dir in `echo $(INCLUDEPATH) | sed "s/-I//g"`; do \
|
||||
find `echo "$${dir}"` -name "*.h" >> $(target).files; \
|
||||
done
|
||||
@echo "Generating $(target).cflags"
|
||||
$(QUIET)echo "" > $(target).cflags
|
||||
@echo "Generating $(target).includes"
|
||||
$(QUIET)echo $(INCLUDEPATH) | sed "s/-I/,/g" | tr , '\n' | sed "/^$$/d" > $(target).includes;
|
||||
@echo "Generating $(target).config"
|
||||
$(QUIET)echo $(DEFINES) | sed "s/-D/,#define /g" | tr , '\n' | sed "/^$$/d" > $(target).config
|
||||
@echo "Generating $(target).creator"
|
||||
$(QUIET)echo "[GENERAL]" > $(target).creator
|
||||
|
||||
-include $(CFILES:%.c=$(OBJDIR)/%.c.d) $(ASFILES:%.S=$(OBJDIR)/%.S.d)
|
@@ -232,7 +232,7 @@ int adc_pt1000_get_current_resistance(float *resistance)
|
||||
*resistance = adc_pt1000_apply_calibration(pt1000_res_raw_lf);
|
||||
|
||||
if (safety_controller_get_flags_by_mask(ERR_FLAG_MEAS_ADC_OFF | ERR_FLAG_MEAS_ADC_OVERFLOW |
|
||||
ERR_FLAG_MEAS_ADC_WATCHDOG)) {
|
||||
ERR_FLAG_MEAS_ADC_WATCHDOG | ERR_FLAG_TIMING_MEAS_ADC)) {
|
||||
ret_val = -100;
|
||||
goto return_value;
|
||||
}
|
||||
|
28
stm-firmware/arm-none-eabi-gcc.cmake
Normal file
28
stm-firmware/arm-none-eabi-gcc.cmake
Normal file
@@ -0,0 +1,28 @@
|
||||
if(MINGW OR CYGWIN OR WIN32)
|
||||
set(UTIL_SEARCH_CMD where)
|
||||
elseif(UNIX OR APPLE)
|
||||
set(UTIL_SEARCH_CMD which)
|
||||
endif()
|
||||
|
||||
set(TOOLCHAIN_PREFIX arm-none-eabi-)
|
||||
|
||||
execute_process(
|
||||
COMMAND ${UTIL_SEARCH_CMD} ${TOOLCHAIN_PREFIX}gcc
|
||||
OUTPUT_VARIABLE BINUTILS_PATH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
get_filename_component(ARM_TOOLCHAIN_DIR ${BINUTILS_PATH} DIRECTORY)
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||
|
||||
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc)
|
||||
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
|
||||
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++)
|
||||
|
||||
set(CMAKE_OBJCOPY ${ARM_TOOLCHAIN_DIR}/${TOOLCHAIN_PREFIX}objcopy CACHE INTERNAL "objcopy tool")
|
||||
set(CMAKE_SIZE_UTIL ${ARM_TOOLCHAIN_DIR}/${TOOLCHAIN_PREFIX}size CACHE INTERNAL "size tool")
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH ${BINUTILS_PATH})
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
Submodule stm-firmware/base64-lib updated: 80090b4b20...251e90abf3
214
stm-firmware/config-parser/temp-profile-parser.c
Normal file
214
stm-firmware/config-parser/temp-profile-parser.c
Normal file
@@ -0,0 +1,214 @@
|
||||
/* Reflow Oven Controller
|
||||
*
|
||||
* Copyright (C) 2021 Mario Hüttel <mario.huettel@gmx.net>
|
||||
*
|
||||
* This file is part of the Reflow Oven Controller Project.
|
||||
*
|
||||
* The reflow oven controller is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with the reflow oven controller project.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <reflow-controller/config-parser/temp-profile-parser.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <fatfs/ff.h>
|
||||
|
||||
struct pl_command_list_map {
|
||||
enum pl_command_type command;
|
||||
const char * const token;
|
||||
uint8_t expected_param_count;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This list stores the command tokens and the expected number of arguments for each command
|
||||
*/
|
||||
static const struct pl_command_list_map cmd_list_map[_PL_NUM_CMDS] = {
|
||||
{PL_PID_CONF, "pid_conf", 6u},
|
||||
{PL_SET_TEMP, "temp_set", 1u},
|
||||
{PL_WAIT_FOR_TEMP, "wait_temp", 1u},
|
||||
{PL_WAIT_FOR_TIME, "wait_time", 1u},
|
||||
{PL_SET_RAMP, "temp_ramp", 2u},
|
||||
{PL_LOUDSPEAKER_SET, "beep", 1u},
|
||||
{PL_OFF, "temp_off", 0u}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Read a line in the file until a line break is detected or a comment is started.
|
||||
*
|
||||
* In case a comment is detected, it is still read form the file to ensure
|
||||
* the next line is read afterwards
|
||||
*
|
||||
* @param f File to read from
|
||||
* @param buffer Buffer to read in
|
||||
* @param buffsize buffer size
|
||||
* @return 0 if successful, -1 if disk error,
|
||||
*/
|
||||
static int read_line_until_comment(FIL *f, char *buffer, uint32_t buffsize)
|
||||
{
|
||||
char *ptr;
|
||||
uint32_t i;
|
||||
|
||||
if (!f || !buffsize || !buffer)
|
||||
return -1000;
|
||||
|
||||
buffer[0] = 0;
|
||||
/* Read the line from file */
|
||||
ptr = f_gets(buffer, (int)buffsize, f);
|
||||
if (!ptr) {
|
||||
buffer[0] = 0;
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* Go through the line until we encounter a # sign or the end of line*/
|
||||
for (i = 0; i < buffsize; i++) {
|
||||
if (buffer[i] == '\n' || buffer[i] == '#') {
|
||||
buffer[i] = 0;
|
||||
break;
|
||||
} else if (buffer[i] == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pl_command_list_map *string_to_command(const char *str)
|
||||
{
|
||||
uint32_t i;
|
||||
const struct pl_command_list_map *ret = NULL;
|
||||
|
||||
if (!str)
|
||||
return NULL;
|
||||
|
||||
for (i = 0u; i < _PL_NUM_CMDS; i++) {
|
||||
if (!strcmp(str, cmd_list_map[i].token)) {
|
||||
ret = &cmd_list_map[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int parse_line(char *line, struct pl_command *cmd)
|
||||
{
|
||||
uint8_t token_idx = 0;
|
||||
char *token;
|
||||
const char * const delim = " \t";
|
||||
const struct pl_command_list_map *map;
|
||||
char *endptr;
|
||||
struct pl_command c;
|
||||
|
||||
if (!line || !cmd)
|
||||
return -1000;
|
||||
|
||||
token = strtok(line, delim);
|
||||
|
||||
if (!token) {
|
||||
/* Empty line or command line */
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (token && token_idx <= PROFILE_LANG_MAX_NUM_ARGS) {
|
||||
switch (token_idx) {
|
||||
case 0:
|
||||
map = string_to_command(token);
|
||||
c.cmd = map->command;
|
||||
break;
|
||||
default:
|
||||
if (!map) {
|
||||
/* No valid command found */
|
||||
return -1;
|
||||
}
|
||||
c.params[token_idx - 1] = strtof(token, &endptr);
|
||||
if (endptr == token) {
|
||||
/* Invalid parameter */
|
||||
return -2;
|
||||
}
|
||||
if (token_idx > map->expected_param_count)
|
||||
return -3;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
token = strtok(NULL, delim);
|
||||
token_idx++;
|
||||
}
|
||||
|
||||
if (token_idx - 1 < map->expected_param_count) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
memcpy(cmd, &c, sizeof(struct pl_command));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum pl_ret_val temp_profile_parse_from_file(const char *filename,
|
||||
struct pl_command *cmd_list,
|
||||
uint32_t cmd_list_length,
|
||||
uint32_t *cmds_parsed)
|
||||
{
|
||||
FIL script_file;
|
||||
FRESULT fres;
|
||||
int res;
|
||||
enum pl_ret_val ret = PL_RET_SUCCESS;
|
||||
char workbuff[256];
|
||||
uint32_t cmd_idx;
|
||||
|
||||
if (!filename || !cmd_list || !cmd_list_length || !cmds_parsed)
|
||||
return PL_RET_PARAM_ERR;
|
||||
|
||||
|
||||
fres = f_open(&script_file, filename, FA_READ);
|
||||
if (fres != FR_OK) {
|
||||
ret = PL_RET_DISK_ERR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
cmd_idx = 0;
|
||||
*cmds_parsed = 0;
|
||||
|
||||
do {
|
||||
/* read in the line */
|
||||
res = read_line_until_comment(&script_file, workbuff, sizeof(workbuff));
|
||||
if (res < 0) {
|
||||
ret = PL_RET_DISK_ERR;
|
||||
goto exit_close;
|
||||
}
|
||||
|
||||
/* Check if list already full */
|
||||
if (cmd_idx >= cmd_list_length) {
|
||||
ret = PL_RET_LIST_FULL;
|
||||
goto exit_close;
|
||||
}
|
||||
|
||||
/* Parse the line */
|
||||
res = parse_line(workbuff, &cmd_list[cmd_idx]);
|
||||
if (res < 0) {
|
||||
ret = PL_RET_SCRIPT_ERR;
|
||||
goto exit_close;
|
||||
} else if (res == 0) {
|
||||
cmd_idx++;
|
||||
*cmds_parsed= cmd_idx;
|
||||
}
|
||||
|
||||
|
||||
} while (!f_eof(&script_file));
|
||||
|
||||
exit_close:
|
||||
(void)f_close(&script_file);
|
||||
exit:
|
||||
return ret;
|
||||
}
|
@@ -33,7 +33,7 @@
|
||||
/ 2: Enable with LF-CRLF conversion. */
|
||||
|
||||
|
||||
#define FF_USE_FIND 0
|
||||
#define FF_USE_FIND 1
|
||||
/* This option switches filtered directory read functions, f_findfirst() and
|
||||
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
|
||||
|
||||
|
@@ -0,0 +1,57 @@
|
||||
/* Reflow Oven Controller
|
||||
*
|
||||
* Copyright (C) 2021 Mario Hüttel <mario.huettel@gmx.net>
|
||||
*
|
||||
* This file is part of the Reflow Oven Controller Project.
|
||||
*
|
||||
* The reflow oven controller is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with the reflow oven controller project.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_PARSER_TEMP_PROFILE_PARSER_H__
|
||||
#define __CONFIG_PARSER_TEMP_PROFILE_PARSER_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum pl_command_type {
|
||||
PL_PID_CONF = 0,
|
||||
PL_SET_TEMP,
|
||||
PL_SET_RAMP,
|
||||
PL_WAIT_FOR_TEMP,
|
||||
PL_WAIT_FOR_TIME,
|
||||
PL_LOUDSPEAKER_SET,
|
||||
PL_OFF,
|
||||
_PL_NUM_CMDS,
|
||||
};
|
||||
|
||||
enum pl_ret_val {
|
||||
PL_RET_SUCCESS = 0,
|
||||
PL_RET_DISK_ERR,
|
||||
PL_RET_PARAM_ERR,
|
||||
PL_RET_LIST_FULL,
|
||||
PL_RET_SCRIPT_ERR,
|
||||
};
|
||||
|
||||
#define PROFILE_LANG_MAX_NUM_ARGS (8)
|
||||
|
||||
struct pl_command {
|
||||
enum pl_command_type cmd;
|
||||
float params[PROFILE_LANG_MAX_NUM_ARGS];
|
||||
};
|
||||
|
||||
enum pl_ret_val temp_profile_parse_from_file(const char *filename,
|
||||
struct pl_command *cmd_list,
|
||||
uint32_t cmd_list_length,
|
||||
uint32_t *cmds_parsed);
|
||||
|
||||
#endif /* __CONFIG_PARSER_TEMP_PROFILE_PARSER_H__ */
|
@@ -35,8 +35,6 @@ void oven_driver_set_power(uint8_t power);
|
||||
|
||||
void oven_driver_disable(void);
|
||||
|
||||
void oven_pid_ack_errors(void);
|
||||
|
||||
void oven_pid_init(struct pid_controller *controller_to_copy);
|
||||
|
||||
void oven_pid_handle(void);
|
||||
|
@@ -0,0 +1,52 @@
|
||||
/* Reflow Oven Controller
|
||||
*
|
||||
* Copyright (C) 2021 Mario Hüttel <mario.huettel@gmx.net>
|
||||
*
|
||||
* This file is part of the Reflow Oven Controller Project.
|
||||
*
|
||||
* The reflow oven controller is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with the reflow oven controller project.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __TEMP_PROFILE_EXECUTER_H__
|
||||
#define __TEMP_PROFILE_EXECUTER_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <reflow-controller/config-parser/temp-profile-parser.h>
|
||||
|
||||
#define MAX_PROFILE_LENGTH 50
|
||||
|
||||
enum tpe_status {
|
||||
TPE_OFF,
|
||||
TPE_RUNNING,
|
||||
TPE_ABORT,
|
||||
};
|
||||
|
||||
struct tpe_current_state {
|
||||
enum tpe_status status;
|
||||
float setpoint;
|
||||
uint64_t start_timestamp;
|
||||
uint32_t step;
|
||||
uint32_t profile_steps;
|
||||
enum pl_command_type current_command;
|
||||
};
|
||||
|
||||
enum pl_ret_val temp_profile_executer_start(const char *filename);
|
||||
|
||||
int temp_profile_executer_handle(void);
|
||||
|
||||
const struct tpe_current_state *temp_profile_executer_status(void);
|
||||
|
||||
int temp_profile_executer_stop(void);
|
||||
|
||||
#endif /* __TEMP_PROFILE_EXECUTER_H__ */
|
@@ -87,4 +87,6 @@ void menu_list_scroll_up(struct menu_list *list);
|
||||
|
||||
void menu_list_enter_selected_entry(struct menu_list *list, struct lcd_menu *menu);
|
||||
|
||||
uint32_t menu_list_get_currently_selected(struct menu_list *list);
|
||||
|
||||
#endif /* __MENU_H__ */
|
||||
|
@@ -46,7 +46,7 @@
|
||||
#include <reflow-controller/safety/safety-memory.h>
|
||||
#include <reflow-controller/safety/fault.h>
|
||||
#include <reflow-controller/updater/updater.h>
|
||||
|
||||
#include <reflow-controller/temp-profile-executer.h>
|
||||
#include <reflow-controller/settings/spi-eeprom.h>
|
||||
|
||||
static void setup_nvic_priorities(void)
|
||||
@@ -218,6 +218,7 @@ int main(void)
|
||||
shellmatta_handle_t shell_handle;
|
||||
int menu_wait_request;
|
||||
uint64_t quarter_sec_timestamp = 0ULL;
|
||||
static uint64_t IN_SECTION(.ccm.bss) main_loop_iter_count;
|
||||
|
||||
setup_system();
|
||||
|
||||
@@ -253,6 +254,9 @@ int main(void)
|
||||
menu_wait_request = gui_handle();
|
||||
handle_shell_uart_input(shell_handle);
|
||||
|
||||
/* Execute current profile step, if a profile is active */
|
||||
temp_profile_executer_handle();
|
||||
|
||||
safety_controller_handle();
|
||||
if (oven_pid_get_status() == OVEN_PID_RUNNING) {
|
||||
oven_pid_handle();
|
||||
@@ -264,6 +268,7 @@ int main(void)
|
||||
__WFI();
|
||||
else
|
||||
__NOP();
|
||||
main_loop_iter_count++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
3
stm-firmware/obj/.gitignore
vendored
3
stm-firmware/obj/.gitignore
vendored
@@ -1,3 +0,0 @@
|
||||
*
|
||||
*.*
|
||||
!.gitignore
|
@@ -65,8 +65,8 @@ static void calculate_integral(struct pid_controller *pid, float deviation)
|
||||
/* Saturate integral term to specified maximum */
|
||||
if (pid->integral > pid->integral_max)
|
||||
pid->integral = pid->integral_max;
|
||||
else if (pid->integral < -pid->integral_max)
|
||||
pid->integral = -pid->integral_max;
|
||||
else if (pid->integral < 0.0f)
|
||||
pid->integral = 0.0f;
|
||||
}
|
||||
|
||||
float pid_sample(struct pid_controller *pid, float deviation)
|
||||
|
@@ -41,6 +41,7 @@
|
||||
#include <reflow-controller/safety/fault.h>
|
||||
#include <reflow-controller/safety/safety-memory.h>
|
||||
#include <reflow-controller/hw-version-detect.h>
|
||||
#include <reflow-controller/temp-profile-executer.h>
|
||||
|
||||
#ifndef GIT_VER
|
||||
#define GIT_VER "VERSION NOT SET"
|
||||
@@ -650,6 +651,8 @@ shellmatta_retCode_t shell_cmd_overtemp_cfg(const shellmatta_handle_t handle, co
|
||||
char option;
|
||||
bool temp_passed = false;
|
||||
bool persistent = false;
|
||||
(void)args;
|
||||
(void)len;
|
||||
|
||||
static const shellmatta_opt_long_t options[] = {
|
||||
{"persistent", 'p', SHELLMATTA_OPT_ARG_NONE},
|
||||
@@ -683,6 +686,87 @@ shellmatta_retCode_t shell_cmd_overtemp_cfg(const shellmatta_handle_t handle, co
|
||||
return ret;
|
||||
}
|
||||
|
||||
shellmatta_retCode_t shell_cmd_execute(const shellmatta_handle_t handle, const char *args, uint32_t len)
|
||||
{
|
||||
enum pl_ret_val res;
|
||||
const struct tpe_current_state *state;
|
||||
static bool running = false;
|
||||
char *data;
|
||||
uint32_t dlen;
|
||||
(void)args;
|
||||
(void)len;
|
||||
int opt_stat;
|
||||
char option;
|
||||
char *argument;
|
||||
uint32_t arg_len;
|
||||
const char *script_name = NULL;
|
||||
const shellmatta_opt_long_t options[] = {
|
||||
{NULL, '\0', SHELLMATTA_OPT_ARG_NONE},
|
||||
};
|
||||
|
||||
while (1) {
|
||||
opt_stat = shellmatta_opt_long(handle, options, &option, &argument, &arg_len);
|
||||
if (opt_stat != SHELLMATTA_OK)
|
||||
break;
|
||||
switch (option) {
|
||||
case '\0':
|
||||
script_name = argument;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!script_name) {
|
||||
shellmatta_printf(handle, "No script name specified!\r\n");
|
||||
return SHELLMATTA_ERROR;
|
||||
}
|
||||
|
||||
shellmatta_read(handle, &data, &dlen);
|
||||
|
||||
if (!running) {
|
||||
res = temp_profile_executer_start(script_name);
|
||||
|
||||
if (res != PL_RET_SUCCESS) {
|
||||
switch (res) {
|
||||
case PL_RET_DISK_ERR:
|
||||
shellmatta_printf(handle, "Error reading file\r\n");
|
||||
break;
|
||||
case PL_RET_LIST_FULL:
|
||||
shellmatta_printf(handle, "Script too long!\r\n");
|
||||
break;
|
||||
case PL_RET_SCRIPT_ERR:
|
||||
shellmatta_printf(handle, "Error in script\r\n");
|
||||
break;
|
||||
default:
|
||||
shellmatta_printf(handle, "Unspecified error occured\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return SHELLMATTA_ERROR;
|
||||
}
|
||||
running = true;
|
||||
} else {
|
||||
state = temp_profile_executer_status();
|
||||
if (state->status != TPE_RUNNING) {
|
||||
shellmatta_printf(handle, "Profile executed.\r\n");
|
||||
running = false;
|
||||
if(state->status == TPE_ABORT) {
|
||||
shellmatta_printf(handle, "Profile execution aborted!\r\n");
|
||||
}
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
|
||||
if (dlen > 0 && *data == '\x03') {
|
||||
temp_profile_executer_stop();
|
||||
running = false;
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return SHELLMATTA_CONTINUE;
|
||||
}
|
||||
|
||||
//typedef struct shellmatta_cmd
|
||||
//{
|
||||
// char *cmd; /**< command name */
|
||||
@@ -692,7 +776,7 @@ shellmatta_retCode_t shell_cmd_overtemp_cfg(const shellmatta_handle_t handle, co
|
||||
// shellmatta_cmdFct_t cmdFct; /**< pointer to the cmd callack function */
|
||||
// struct shellmatta_cmd *next; /**< pointer to next command or NULL */
|
||||
//} shellmatta_cmd_t;
|
||||
static shellmatta_cmd_t cmd[20] = {
|
||||
static shellmatta_cmd_t cmd[21] = {
|
||||
{
|
||||
.cmd = "version",
|
||||
.cmdAlias = "ver",
|
||||
@@ -852,6 +936,14 @@ static shellmatta_cmd_t cmd[20] = {
|
||||
.helpText = "Overtemperature Config",
|
||||
.usageText = "",
|
||||
.cmdFct = shell_cmd_overtemp_cfg,
|
||||
.next = &cmd[20],
|
||||
},
|
||||
{
|
||||
.cmd = "execute",
|
||||
.cmdAlias = NULL,
|
||||
.helpText = "Execute Temp Profile",
|
||||
.usageText = "execute /path/to/script.tpr",
|
||||
.cmdFct = shell_cmd_execute,
|
||||
.next = NULL,
|
||||
}
|
||||
};
|
||||
|
256
stm-firmware/temp-profile-executer.c
Normal file
256
stm-firmware/temp-profile-executer.c
Normal file
@@ -0,0 +1,256 @@
|
||||
/* Reflow Oven Controller
|
||||
*
|
||||
* Copyright (C) 2021 Mario Hüttel <mario.huettel@gmx.net>
|
||||
*
|
||||
* This file is part of the Reflow Oven Controller Project.
|
||||
*
|
||||
* The reflow oven controller is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with the reflow oven controller project.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <reflow-controller/temp-profile-executer.h>
|
||||
#include <reflow-controller/systick.h>
|
||||
#include <helper-macros/helper-macros.h>
|
||||
#include <reflow-controller/oven-driver.h>
|
||||
#include <reflow-controller/temp-converter.h>
|
||||
#include <reflow-controller/adc-meas.h>
|
||||
#include <reflow-controller/digio.h>
|
||||
|
||||
static struct tpe_current_state IN_SECTION(.ccm.data) state = {
|
||||
.status = TPE_OFF,
|
||||
.start_timestamp = 0,
|
||||
};
|
||||
static bool IN_SECTION(.ccm.bss) pid_should_run;
|
||||
struct pid_controller IN_SECTION(.ccm.bss) pid;
|
||||
bool IN_SECTION(.ccm.bss) cmd_continue;
|
||||
|
||||
static struct pl_command IN_SECTION(.ccm.bss) cmd_list[MAX_PROFILE_LENGTH];
|
||||
|
||||
static void tpe_abort(void)
|
||||
{
|
||||
temp_profile_executer_stop();
|
||||
state.status = TPE_ABORT;
|
||||
}
|
||||
|
||||
enum pl_ret_val temp_profile_executer_start(const char *filename)
|
||||
{
|
||||
uint32_t parsed_count = 0;
|
||||
enum pl_ret_val res;
|
||||
|
||||
state.setpoint = 0.0f;
|
||||
state.start_timestamp = 0ULL;
|
||||
state.setpoint = 0.0f;
|
||||
state.step = 0;
|
||||
state.profile_steps = 0;
|
||||
|
||||
oven_pid_stop();
|
||||
pid_should_run = false;
|
||||
state.status = TPE_OFF;
|
||||
state.profile_steps = 0;
|
||||
cmd_continue = false;
|
||||
|
||||
res = temp_profile_parse_from_file(filename, cmd_list, MAX_PROFILE_LENGTH, &parsed_count);
|
||||
if (res == PL_RET_SUCCESS) {
|
||||
state.profile_steps = parsed_count;
|
||||
state.status = TPE_RUNNING;
|
||||
state.start_timestamp = systick_get_global_tick();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool cmd_wait_temp(struct pl_command *cmd, bool cmd_continue)
|
||||
{
|
||||
(void)cmd_continue;
|
||||
float resistance;
|
||||
int res;
|
||||
float temp;
|
||||
|
||||
res = adc_pt1000_get_current_resistance(&resistance);
|
||||
if (res < 0) {
|
||||
tpe_abort();
|
||||
return false;
|
||||
}
|
||||
|
||||
(void)temp_converter_convert_resistance_to_temp(resistance, &temp);
|
||||
|
||||
if (ABS(cmd->params[0] - temp) < 3.0f)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool cmd_wait_time(struct pl_command *cmd, bool cmd_continue)
|
||||
{
|
||||
static uint64_t temp_tick = 0UL;
|
||||
|
||||
if (cmd_continue) {
|
||||
if (systick_ticks_have_passed(temp_tick,
|
||||
(uint64_t)(cmd->params[0] * 1000.0f)))
|
||||
return true;
|
||||
} else {
|
||||
temp_tick = systick_get_global_tick();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void reactivate_pid_if_suspended(void)
|
||||
{
|
||||
if (oven_pid_get_status() == OVEN_PID_DEACTIVATED)
|
||||
oven_pid_init(&pid);
|
||||
|
||||
pid_should_run = true;
|
||||
}
|
||||
|
||||
static bool cmd_set_temp(struct pl_command *cmd, bool cmd_continue)
|
||||
{
|
||||
(void)cmd_continue;
|
||||
|
||||
reactivate_pid_if_suspended();
|
||||
oven_pid_set_target_temperature(cmd->params[0]);
|
||||
state.setpoint = cmd->params[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cmd_ramp(struct pl_command *cmd, bool cmd_continue)
|
||||
{
|
||||
static uint64_t IN_SECTION(.ccm.bss) start_timestamp;
|
||||
static float IN_SECTION(.ccm.bss) start_temp;
|
||||
static float IN_SECTION(.ccm.bss) slope;
|
||||
float secs_passed;
|
||||
bool ret = false;
|
||||
|
||||
if (!cmd_continue) {
|
||||
/* Init of command */
|
||||
start_temp = state.setpoint;
|
||||
slope = (cmd->params[0] - start_temp) / cmd->params[1];
|
||||
reactivate_pid_if_suspended();
|
||||
oven_pid_set_target_temperature(start_temp);
|
||||
start_timestamp = systick_get_global_tick();
|
||||
} else {
|
||||
secs_passed = ((float)(systick_get_global_tick() - start_timestamp)) / 1000.0f;
|
||||
if ((state.setpoint <= cmd->params[0] && start_temp < cmd->params[0]) ||
|
||||
(state.setpoint >= cmd->params[0] && start_temp > cmd->params[0])) {
|
||||
state.setpoint = start_temp + secs_passed * slope;
|
||||
} else {
|
||||
state.setpoint = cmd->params[0];
|
||||
ret = true;
|
||||
}
|
||||
oven_pid_set_target_temperature(state.setpoint);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int temp_profile_executer_handle(void)
|
||||
{
|
||||
struct pl_command *current_cmd;
|
||||
static uint64_t last_tick = 0UL;
|
||||
bool advance;
|
||||
|
||||
uint32_t next_step;
|
||||
|
||||
|
||||
/* Return if no profile is currently executed */
|
||||
if (state.status != TPE_RUNNING)
|
||||
return -1;
|
||||
|
||||
/* Abort profile execution if oven PID is aborted. This is most likely due to some error flags */
|
||||
if (oven_pid_get_status() == OVEN_PID_ABORTED && pid_should_run) {
|
||||
tpe_abort();
|
||||
oven_pid_stop();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Execute Temp Profile every 100 ms. If not yet due, return */
|
||||
if (!systick_ticks_have_passed(last_tick, 100))
|
||||
return 0;
|
||||
|
||||
current_cmd = &cmd_list[state.step];
|
||||
next_step = state.step;
|
||||
|
||||
switch (current_cmd->cmd) {
|
||||
case PL_WAIT_FOR_TIME:
|
||||
advance = cmd_wait_time(current_cmd, cmd_continue);
|
||||
break;
|
||||
case PL_WAIT_FOR_TEMP:
|
||||
advance = cmd_wait_temp(current_cmd, cmd_continue);
|
||||
break;
|
||||
case PL_SET_TEMP:
|
||||
advance = cmd_set_temp(current_cmd, cmd_continue);
|
||||
break;
|
||||
case PL_LOUDSPEAKER_SET:
|
||||
loudspeaker_set((uint16_t)current_cmd->params[0]);
|
||||
advance = true;
|
||||
break;
|
||||
case PL_OFF:
|
||||
oven_pid_stop();
|
||||
pid_should_run = false;
|
||||
advance = true;
|
||||
break;
|
||||
case PL_PID_CONF:
|
||||
pid_init(&pid, current_cmd->params[0], /* Kd */
|
||||
current_cmd->params[1], /* Ki */
|
||||
current_cmd->params[2], /* Kp */
|
||||
0.0f, 0.0f,
|
||||
current_cmd->params[3], /* Int max */
|
||||
current_cmd->params[4], /* Kd tau */
|
||||
current_cmd->params[5]); /* Period */
|
||||
oven_pid_init(&pid);
|
||||
advance = true;
|
||||
pid_should_run = true;
|
||||
break;
|
||||
case PL_SET_RAMP:
|
||||
advance = cmd_ramp(current_cmd, cmd_continue);
|
||||
break;
|
||||
default:
|
||||
tpe_abort();
|
||||
advance = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (advance)
|
||||
next_step++;
|
||||
|
||||
if (next_step != state.step) {
|
||||
state.step = next_step;
|
||||
if (next_step >= state.profile_steps) {
|
||||
(void)temp_profile_executer_stop();
|
||||
} else {
|
||||
cmd_continue = false;
|
||||
}
|
||||
} else {
|
||||
cmd_continue = true;
|
||||
}
|
||||
last_tick = systick_get_global_tick();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct tpe_current_state *temp_profile_executer_status(void)
|
||||
{
|
||||
return &state;
|
||||
}
|
||||
|
||||
int temp_profile_executer_stop(void)
|
||||
{
|
||||
if (state.status == TPE_RUNNING) {
|
||||
state.status = TPE_OFF;
|
||||
oven_pid_stop();
|
||||
}
|
||||
|
||||
loudspeaker_set(0);
|
||||
|
||||
return 0;
|
||||
}
|
@@ -36,6 +36,8 @@
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <reflow-controller/oven-driver.h>
|
||||
#include <fatfs/ff.h>
|
||||
#include <reflow-controller/temp-profile-executer.h>
|
||||
|
||||
static char IN_SECTION(.ccm.bss) display_buffer[4][21] = {0};
|
||||
static struct lcd_menu IN_SECTION(.ccm.bss) reflow_menu;
|
||||
@@ -372,6 +374,189 @@ static void gui_menu_constant_temperature_driver(struct lcd_menu *menu, enum men
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief load_temperature_file_list_from_sdcard
|
||||
* @return -1 File error, 0 successful
|
||||
*/
|
||||
static int load_temperature_file_list_from_sdcard(char (*list)[17], uint32_t len)
|
||||
{
|
||||
uint32_t i, j;
|
||||
DIR directory;
|
||||
FILINFO finfo;
|
||||
FRESULT fres;
|
||||
|
||||
if (!list)
|
||||
return -1001;
|
||||
|
||||
/* Zero out the list */
|
||||
for (i = 0; i < len; i++) {
|
||||
for (j = 0; j < sizeof(*list); j++) {
|
||||
list[i][j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* find the frist file */
|
||||
fres = f_findfirst(&directory, &finfo, "/", "*.tpr");
|
||||
i = 0;
|
||||
while (fres == FR_OK && finfo.fname[0]) {
|
||||
strncpy(list[i], finfo.fname, sizeof(*list));
|
||||
fres = f_findnext(&directory, &finfo);
|
||||
i++;
|
||||
if (i >= len)
|
||||
break;
|
||||
}
|
||||
|
||||
if (fres != FR_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int)i;
|
||||
}
|
||||
|
||||
static void gui_menu_temp_profile_execute(struct lcd_menu *menu, enum menu_entry_func_entry entry_type, void* parent)
|
||||
{
|
||||
static void *my_parent;
|
||||
const struct tpe_current_state *state;
|
||||
static uint64_t last_tick;
|
||||
float temperature;
|
||||
float resistance;
|
||||
int res;
|
||||
|
||||
if (entry_type == MENU_ENTRY_FIRST_ENTER) {
|
||||
my_parent = parent;
|
||||
menu_display_clear(menu);
|
||||
last_tick = 0ULL;
|
||||
}
|
||||
|
||||
if (systick_ticks_have_passed(last_tick, 300)) {
|
||||
state = temp_profile_executer_status();
|
||||
if (state->status == TPE_RUNNING)
|
||||
menu_lcd_outputf(menu, 0, "Profile running");
|
||||
else if (state->status == TPE_OFF) {
|
||||
menu_lcd_outputf(menu, 0, "Profile finished");
|
||||
} else {
|
||||
menu_lcd_outputf(menu, 0, "Profile aborted!");
|
||||
}
|
||||
menu_lcd_outputf(menu, 1, "Step %u/%u", state->step, state->profile_steps);
|
||||
(void)adc_pt1000_get_current_resistance(&resistance);
|
||||
res = temp_converter_convert_resistance_to_temp(resistance, &temperature);
|
||||
menu_lcd_outputf(menu, 2, "Temp: %s%.0f", (res < 0 ? "<" : (res > 0 ? ">" : "")), temperature);
|
||||
if (oven_pid_get_status() == OVEN_PID_RUNNING) {
|
||||
menu_lcd_outputf(menu, 3, "Target: %.0f", state->setpoint);
|
||||
} else {
|
||||
menu_lcd_outputf(menu, 3, "Temp Off");
|
||||
}
|
||||
|
||||
last_tick = systick_get_global_tick();
|
||||
}
|
||||
|
||||
if (menu_get_button_ready_state(menu)) {
|
||||
if (menu_get_button_state(menu) != BUTTON_IDLE) {
|
||||
temp_profile_executer_stop();
|
||||
menu_entry_dropback(menu, my_parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gui_menu_temp_profile_select(struct lcd_menu *menu, enum menu_entry_func_entry entry_type, void *parent)
|
||||
{
|
||||
static void *my_parent;
|
||||
static char profile_list[10][17];
|
||||
static bool file_error = false;
|
||||
static enum pl_ret_val profile_ret_val = PL_RET_SUCCESS;
|
||||
static uint8_t currently_selected = 0U;
|
||||
static uint8_t loaded;
|
||||
int16_t delta;
|
||||
enum button_state button;
|
||||
|
||||
int res;
|
||||
|
||||
if (entry_type == MENU_ENTRY_FIRST_ENTER) {
|
||||
menu_display_clear(menu);
|
||||
my_parent = parent;
|
||||
res = load_temperature_file_list_from_sdcard(profile_list, 10);
|
||||
file_error = false;
|
||||
loaded = 0;
|
||||
if (res < 0) {
|
||||
file_error = true;
|
||||
}
|
||||
|
||||
currently_selected = 0u;
|
||||
profile_ret_val = PL_RET_SUCCESS;
|
||||
loaded = (uint32_t)res;
|
||||
menu_lcd_outputf(menu, 0, "Select:");
|
||||
} else if (entry_type == MENU_ENTRY_DROPBACK) {
|
||||
menu_entry_dropback(menu, my_parent);
|
||||
return;
|
||||
}
|
||||
|
||||
if (menu_get_button_ready_state(menu)) {
|
||||
delta = menu_get_rotary_delta(menu);
|
||||
button = menu_get_button_state(menu);
|
||||
|
||||
if (button == BUTTON_LONG) {
|
||||
menu_entry_dropback(menu, my_parent);
|
||||
}
|
||||
|
||||
if (file_error) {
|
||||
menu_lcd_outputf(menu, 0, "Disk Error");
|
||||
menu_lcd_outputf(menu, 1, "SD inserted?");
|
||||
if (button == BUTTON_SHORT_RELEASED)
|
||||
menu_entry_dropback(menu, my_parent);
|
||||
return;
|
||||
} else if (loaded == 0) {
|
||||
menu_lcd_outputf(menu, 0, "No profiles");
|
||||
menu_lcd_outputf(menu, 1, "found");
|
||||
if (button == BUTTON_SHORT_RELEASED)
|
||||
menu_entry_dropback(menu, my_parent);
|
||||
return;
|
||||
} else if (profile_ret_val != PL_RET_SUCCESS) {
|
||||
menu_lcd_outputf(menu, 0, "ERROR");
|
||||
switch (profile_ret_val) {
|
||||
case PL_RET_SCRIPT_ERR:
|
||||
menu_lcd_outputf(menu, 1, "Syntax Error");
|
||||
break;
|
||||
case PL_RET_DISK_ERR:
|
||||
menu_lcd_outputf(menu, 1, "Disk Error");
|
||||
break;
|
||||
case PL_RET_LIST_FULL:
|
||||
menu_lcd_output(menu, 1, "Too many com-");
|
||||
menu_lcd_output(menu, 2, "mands in file");
|
||||
break;
|
||||
default:
|
||||
menu_lcd_output(menu, 1, "Unknown error");
|
||||
break;
|
||||
}
|
||||
|
||||
if (button == BUTTON_SHORT_RELEASED)
|
||||
menu_entry_dropback(menu, my_parent);
|
||||
return;
|
||||
} else if (currently_selected < loaded) {
|
||||
/* Show currently selected profile */
|
||||
menu_lcd_outputf(menu, 1, "%s", &profile_list[currently_selected][0]);
|
||||
|
||||
if (button == BUTTON_SHORT_RELEASED) {
|
||||
/* Execute selected profile */
|
||||
profile_ret_val = temp_profile_executer_start(&profile_list[currently_selected][0]);
|
||||
if (profile_ret_val == PL_RET_SUCCESS) {
|
||||
menu_entry_enter(menu, gui_menu_temp_profile_execute, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (delta >= 4) {
|
||||
menu_ack_rotary_delta(menu);
|
||||
if (currently_selected < (loaded - 1))
|
||||
currently_selected++;
|
||||
} else if (delta <= -4) {
|
||||
menu_ack_rotary_delta(menu);
|
||||
if (currently_selected > 0)
|
||||
currently_selected--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gui_menu_constant_temperature_driver_setup(struct lcd_menu *menu, enum menu_entry_func_entry entry_type, void *parent)
|
||||
{
|
||||
static void IN_SECTION(.ccm.bss) *my_parent;
|
||||
@@ -412,6 +597,7 @@ static void gui_menu_root_entry(struct lcd_menu *menu, enum menu_entry_func_entr
|
||||
bool menu_changed = false;
|
||||
static const char * const root_entry_names[] = {
|
||||
"Constant Temp",
|
||||
"Temp Profile",
|
||||
"Monitoring",
|
||||
"Error Flags",
|
||||
"About",
|
||||
@@ -419,6 +605,7 @@ static void gui_menu_root_entry(struct lcd_menu *menu, enum menu_entry_func_entr
|
||||
};
|
||||
static const menu_func_t root_entry_funcs[] = {
|
||||
gui_menu_constant_temperature_driver_setup,
|
||||
gui_menu_temp_profile_select,
|
||||
gui_menu_monitor,
|
||||
gui_menu_err_flags,
|
||||
gui_menu_about,
|
||||
|
@@ -273,3 +273,10 @@ void menu_display_clear(struct lcd_menu *menu)
|
||||
for (i = 0; i < 4; i++)
|
||||
menu->update_display(i, "");
|
||||
}
|
||||
|
||||
uint32_t menu_list_get_currently_selected(struct menu_list *list)
|
||||
{
|
||||
if (!list)
|
||||
return 0;
|
||||
return list->currently_selected;
|
||||
}
|
||||
|
46
stm-firmware/updater/ram-code/CMakeLists.txt
Normal file
46
stm-firmware/updater/ram-code/CMakeLists.txt
Normal file
@@ -0,0 +1,46 @@
|
||||
project(updater-ram-code)
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||
set(CMAKE_CROSSCOMPILING 1)
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
set(CMAKE_TOOLCHAIN_FILE "arm-none-eabi-gcc.cmake")
|
||||
|
||||
set(ELFFILE ${PROJECT_NAME}.elf)
|
||||
set(LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/ram-link.ld)
|
||||
|
||||
set(ELFFILE "${PROJECT_NAME}.elf")
|
||||
aux_source_directory("." SRCS)
|
||||
aux_source_directory("fatfs" FATFS_SRCS)
|
||||
aux_source_directory("fatfs/shimatta_sdio_driver" SDIO_SRCS)
|
||||
|
||||
add_executable(${ELFFILE} ${SRCS} ${FATFS_SRCS} ${SDIO_SRCS})
|
||||
|
||||
target_include_directories(${ELFFILE} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
target_compile_options(${ELFFILE} PRIVATE -Wall -Wextra -Wold-style-declaration -Wuninitialized -Wmaybe-uninitialized -Wunused-parameter)
|
||||
target_compile_options(${ELFFILE} PRIVATE -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork -mfloat-abi=hard -mfpu=fpv4-sp-d16 -nostartfiles -Wimplicit-fallthrough=3 -Wsign-compare -Os -g3)
|
||||
target_compile_definitions(${ELFFILE} PRIVATE -DBASE64_LOOKUP_TABLE_SECTION=\".ccm.bss\" -DSHELLMATTA_HELP_ALIAS=\"?\" -DGIT_VER=${GIT_DESCRIBE} -DHSE_VALUE=8000000UL -DSTM32F407xx -DSTM32F4XX -DARM_MATH_CM4)
|
||||
target_link_options(${ELFFILE} PRIVATE -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork -mfloat-abi=hard -mfpu=fpv4-sp-d16 --disable-newlib-supplied-syscalls -nostartfiles -T${LINKER_SCRIPT} -Wl,--print-memory-usage)
|
||||
set(GEN_HEADER_PATH "${CMAKE_CURRENT_BINARY_DIR}/include/generated")
|
||||
set(GEN_HEADER_FILE "${GEN_HEADER_PATH}/${PROJECT_NAME}.bin.h")
|
||||
target_include_directories(${ELFFILE} INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/include/")
|
||||
|
||||
set(GEN_HEADER_FILE "${CMAKE_CURRENT_BINARY_DIR}/include/generated/${PROJECT_NAME}.bin.h")
|
||||
|
||||
add_custom_target(updater-ram-code-header-blob DEPENDS ${GEN_HEADER_FILE})
|
||||
|
||||
add_custom_command(DEPENDS
|
||||
${ELFFILE}
|
||||
OUTPUT
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.bin"
|
||||
COMMAND
|
||||
${CMAKE_OBJCOPY} -O binary ${ELFFILE} "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.bin"
|
||||
)
|
||||
|
||||
add_custom_command(DEPENDS
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.bin"
|
||||
OUTPUT
|
||||
${GEN_HEADER_FILE}
|
||||
COMMAND
|
||||
mkdir -p ${GEN_HEADER_PATH} && python "${CMAKE_CURRENT_SOURCE_DIR}/bin2carray.py" "${GEN_HEADER_FILE}" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.bin"
|
||||
)
|
@@ -1,82 +0,0 @@
|
||||
RAM_CODE_TARGET = updater-ram-code
|
||||
target = $(RAM_CODE_TARGET)
|
||||
OBJDIR = obj
|
||||
CFILES = main.c startup.c hex-parser.c
|
||||
CFILES += fatfs/ff.c fatfs/diskio.c fatfs/ffsystem.c fatfs/ffunicode.c fatfs/shimatta_sdio_driver/shimatta_sdio.c
|
||||
LINKER_SCRIPT = ram-link.ld
|
||||
MAPFILE = $(RAM_CODE_TARGET)
|
||||
PREFIX = arm-none-eabi-
|
||||
|
||||
CC = $(PREFIX)gcc
|
||||
OBJCOPY = $(PREFIX)objcopy
|
||||
SIZE = $(PREFIX)size
|
||||
|
||||
ifneq ($(VERBOSE),true)
|
||||
QUIET=@
|
||||
else
|
||||
QUIET=
|
||||
endif
|
||||
|
||||
|
||||
DEFINES = -DSTM32F407xx -DSTM32F4XX -DHSE_VALUE=8000000UL
|
||||
INCLUDEPATH = -Iinclude
|
||||
|
||||
LFLAGS = -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork
|
||||
LFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 --disable-newlib-supplied-syscalls -nostartfiles
|
||||
LFLAGS += -T$(LINKER_SCRIPT) -Wl,-Map=$(MAPFILE).map -Wl,--print-memory-usage -g3
|
||||
|
||||
CFLAGS = -c -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork -Os -g3
|
||||
CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 -nostartfiles
|
||||
CFLAGS += -Wall -Wextra -Wold-style-declaration -Wuninitialized -Wmaybe-uninitialized -Wunused-parameter -Wimplicit-fallthrough=3 -Wsign-compare
|
||||
|
||||
OBJ = $(CFILES:%.c=$(OBJDIR)/%.c.o)
|
||||
|
||||
default: $(RAM_CODE_TARGET).bin.h
|
||||
|
||||
all: $(RAM_CODE_TARGET).bin.h
|
||||
|
||||
%.bin.h: %.bin
|
||||
@echo "[BIN2H] $@"
|
||||
$(QUIET)python bin2carray.py $@ $^
|
||||
|
||||
$(RAM_CODE_TARGET).bin: $(RAM_CODE_TARGET).elf
|
||||
@echo "[ELF2BIN] $@"
|
||||
$(QUIET)$(OBJCOPY) -O binary $^ $@
|
||||
|
||||
$(RAM_CODE_TARGET).elf: $(OBJ) $(LINKER_SCRIPT)
|
||||
@echo [LD] $@
|
||||
$(QUIET)$(CC) $(LFLAGS) $(LIBRARYPATH) -o $@ $(OBJ) $(ASOBJ) $(LIBRARIES)
|
||||
$(QUIET)$(SIZE) $@
|
||||
|
||||
$(OBJ):
|
||||
@echo [CC] $@
|
||||
$(eval OUTPATH=$(dir $@))
|
||||
@mkdir -p $(OUTPATH)
|
||||
$(QUIET)$(CC) $(CFLAGS) -MMD -MT $@ $(INCLUDEPATH) $(DEFINES) -o $@ $(@:$(OBJDIR)/%.c.o=%.c)
|
||||
|
||||
.PHONY: clean qtproject
|
||||
|
||||
clean:
|
||||
@echo [CLEAN]
|
||||
$(QUIET)rm -f $(OBJ) $(MAPFILE).map $(CFILES:%.c=$(OBJDIR)/%.c.d) $(RAM_CODE_TARGET).bin $(RAM_CODE_TARGET).elf $(RAM_CODE_TARGET).bin.c
|
||||
|
||||
qtproject:
|
||||
$(QUIET)rm -f $(target).files $(target).cflags $(target).config $(target).creator $(target).includes $(target).creator.user
|
||||
@echo "Generating source file list"
|
||||
$(QUIET)echo "$(CFILES)" | tr ' ' '\n' > $(target).files
|
||||
@echo -n "Appending found header files from folders "
|
||||
@echo `echo $(INCLUDEPATH) | sed "s/-I//g"`
|
||||
$(QUIET)for dir in `echo $(INCLUDEPATH) | sed "s/-I//g"`; do \
|
||||
find `echo "$${dir}"` -name "*.h" >> $(target).files; \
|
||||
done
|
||||
@echo "Generating $(target).cflags"
|
||||
$(QUIET)echo "" > $(target).cflags
|
||||
@echo "Generating $(target).includes"
|
||||
$(QUIET)echo $(INCLUDEPATH) | sed "s/-I/,/g" | tr , '\n' | sed "/^$$/d" > $(target).includes;
|
||||
@echo "Generating $(target).config"
|
||||
$(QUIET)echo $(DEFINES) | sed "s/-D/,#define /g" | tr , '\n' | sed "/^$$/d" > $(target).config
|
||||
@echo "Generating $(target).creator"
|
||||
$(QUIET)echo "[GENERAL]" > $(target).creator
|
||||
|
||||
-include $(CFILES:%.c=$(OBJDIR)/%.c.d)
|
||||
|
@@ -4,6 +4,7 @@
|
||||
# bin2carray <output file> <input file>
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
@@ -18,7 +19,7 @@ with open(source_file, "rb") as src:
|
||||
data = src.read()
|
||||
|
||||
with open(dest_file, "w") as dest:
|
||||
header_guard = "__" + dest_file.replace('.', '_').replace('-', '_') + "_H__"
|
||||
header_guard = "__" + os.path.basename(dest_file).replace('.', '_').replace('-', '_') + "_H__"
|
||||
dest.write("#ifndef %s\n" % (header_guard))
|
||||
dest.write("#define %s\n" % (header_guard))
|
||||
dest.write("static const char binary_blob[%d] = {\n" % (len(data)))
|
||||
|
@@ -20,7 +20,7 @@
|
||||
|
||||
#include <reflow-controller/updater/updater.h>
|
||||
#include <reflow-controller/safety/watchdog.h>
|
||||
#include "ram-code/updater-ram-code.bin.h"
|
||||
#include <generated/updater-ram-code.bin.h>
|
||||
#include <stm32/stm32f4xx.h>
|
||||
#include <cmsis/core_cm4.h>
|
||||
#include <stdint.h>
|
||||
|
Reference in New Issue
Block a user