Compare commits

...

9 Commits

34 changed files with 955 additions and 107 deletions

3
.gitignore vendored
View File

@ -1,5 +1,6 @@
bootloader/build/*
lark1fq/build/*
test/build/*
tools/*.exe
tools/*.xls
.vscode/*

View File

@ -14,10 +14,31 @@ set(CMAKE_AR "${TOOLCHAIN}ar")
set(CMAKE_RANLIB "${TOOLCHAIN}ranlib")
set(LINKER_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/flash.ld")
set(MCU_FLAGS "-mcpu=cortex-m4 -mthumb -g -O2 -Wall -nostartfiles -mfloat-abi=hard -mfpu=vfpv4-d16 -fdata-sections")
set(CMAKE_C_FLAGS "${MCU_FLAGS}")
set(CMAKE_ASM_FLAGS "${MCU_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${MCU_FLAGS} -T${LINKER_SCRIPT} -Wl,-Map=bootloader.map")
set(CMAKE_C_FLAGS " \
-mcpu=cortex-m4 \
-mthumb \
-g3 \
-O2 \
-Wall \
-nostartfiles \
-mfloat-abi=hard \
-mfpu=vfpv4-d16 \
-ffunction-sections \
-fdata-sections \
")
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS " \
-ffunction-sections \
-fdata-sections \
-Wl,--gc-sections \
-T${LINKER_SCRIPT} \
-Wl,-Map=${PROJ_NAME}.map \
--specs=nano.specs \
-Wl,--print-memory-usage \
-Wl,--print-output-format \
")
add_definitions(-DSTM32F40_41xxx)
add_definitions(-DUSE_STDPERIPH_DRIVER)
@ -37,5 +58,24 @@ target_link_libraries(${PROJ_NAME}.elf src)
add_custom_command(TARGET ${PROJ_NAME}.elf POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${PROJ_NAME}.elf> ${BIN_FILE}
COMMAND ${CMAKE_OBJDUMP} -d -S $<TARGET_FILE:${PROJ_NAME}.elf> >${ASM_FILE}
COMMENT "Generate ${BIN_FILE}\r\n"
# COMMENT "Generate ${BIN_FILE}\r\n"
COMMAND size ${PROJ_NAME}.elf
COMMAND echo "Calculating SHA-256 checksum for ${BIN_FILE}:"
COMMAND sha256sum ${BIN_FILE}
)
# get git tag
execute_process(
COMMAND git describe --abbrev=40 --tags --dirty --always
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GIT_TAG
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
if(GIT_TAG)
set(PROJECT_SDK_VERSION ${GIT_TAG})
else()
message(WARNING "No Valid version info found for SDK!")
set(PROJECT_SDK_VERSION "version-unknown-panic")
endif()
message(STATUS "Project SDK Version: ${PROJECT_SDK_VERSION}")

18
bootloader/Makefile Normal file
View File

@ -0,0 +1,18 @@
CMAKE = cmake # use user cmake
cmake_generator = "Unix Makefiles"
RM = $(CMAKE) -E remove_directory
MAKEFLAGS += --no-print-directory
TOOLCHAIN ?= arm-none-eabi-
#cmake definition config
cmake_definition+= -DTOOLCHAIN=${TOOLCHAIN}
build:Makefile
$(CMAKE) -S . -B build -G $(cmake_generator) $(cmake_definition)
$(MAKE) -C build -j
clean::
$(RM) build
.PHONY:build clean

View File

@ -1,14 +1,15 @@
ENTRY(Reset_Handler)
StackSize = 0x4000; /* 16KB */
MEMORY
{
FLASH (rx) :ORIGIN = 0x08000000, LENGTH = 128K
RAM (xrw) :ORIGIN = 0x20000000, LENGTH = 112K
CCM (rw) :ORIGIN = 0x10000000, LENGTH = 48K
CCM_STACK (rw) :ORIGIN = 0x1000C000, LENGTH = 16K
CCM (rw) :ORIGIN = 0x10000000, LENGTH = 64K - StackSize
}
_stack_top = ORIGIN(CCM_STACK) + LENGTH(CCM_STACK);
_stack_top = ORIGIN(CCM) + LENGTH(CCM) + StackSize;
SECTIONS
{

View File

@ -31,14 +31,12 @@ void file_to_flash(void)
void system_init(void)
{
led_init(LED1 | LED2);
led_on(LED1 | LED2);
led_delay_ms(500);
led_off(LED1 | LED2);
}
void led_blink(void)
{
for (uint32_t i=0; i<2; i++) {
for (uint32_t i=0; i<1; i++) {
led_delay_ms(250);
led_on(LED1 | LED2);
led_delay_ms(250);

View File

@ -1,3 +1,4 @@
#include "led.h"
#include "partition.h"
#include "file.h"
#include "bitmap.h"
@ -15,7 +16,7 @@ void file_write_flash_0(uint32_t flash, uint32_t len)
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
for (i = 0; i < len / 4; i++) {
if (FLASH_ProgramWord(flash + i * 4, 0) != FLASH_COMPLETE) {
while (1);
led_indicate_error();
}
}
FLASH_Lock();
@ -23,7 +24,7 @@ void file_write_flash_0(uint32_t flash, uint32_t len)
p_flash = (volatile uint32_t *)flash;
for (i = 0; i < len / 4; i++) {
if (p_flash[i] != 0) {
while (1);
led_indicate_error();
}
}
}
@ -39,14 +40,14 @@ void file_bitmap_update(uint32_t mask)
/* first open file */
ret = f_open(&f, file_name[FILE_IDX_MAIN], FA_READ);
if (ret != FR_OK) {
while (1);
led_indicate_error();
}
/* second program data to flash */
idx = 0;
while (1) {
ret = f_read(&f, file_buffer, FILE_BUFF_SIZE, &bc);
if (ret != FR_OK) {
while (1);
led_indicate_error();
}
file_write_flash(ADDR_MAIN + idx * FILE_BUFF_SIZE, file_buffer, (uint32_t)bc);
if ((uint32_t)bc != FILE_BUFF_SIZE) {
@ -60,14 +61,14 @@ void file_bitmap_update(uint32_t mask)
/* first open file */
ret = f_open(&f, file_name[FILE_IDX_GAS1], FA_READ);
if (ret != FR_OK) {
while (1);
led_indicate_error();
}
/* second program data to flash */
idx = 0;
while (1) {
ret = f_read(&f, file_buffer, FILE_BUFF_SIZE, &bc);
if (ret != FR_OK) {
while (1);
led_indicate_error();
}
file_write_flash(ADDR_GAS1 + idx * FILE_BUFF_SIZE, file_buffer, (uint32_t)bc);
if ((uint32_t)bc != FILE_BUFF_SIZE) {
@ -84,14 +85,14 @@ void file_bitmap_update(uint32_t mask)
/* first open file */
ret = f_open(&f, file_name[FILE_IDX_GAS2], FA_READ);
if (ret != FR_OK) {
while (1);
led_indicate_error();
}
/* second program data to flash */
idx = 0;
while (1) {
ret = f_read(&f, file_buffer, FILE_BUFF_SIZE, &bc);
if (ret != FR_OK) {
while (1);
led_indicate_error();
}
file_write_flash(ADDR_GAS2 + idx * FILE_BUFF_SIZE, file_buffer, (uint32_t)bc);
if ((uint32_t)bc != FILE_BUFF_SIZE) {
@ -108,14 +109,14 @@ void file_bitmap_update(uint32_t mask)
/* first open file */
ret = f_open(&f, file_name[FILE_IDX_GAS3], FA_READ);
if (ret != FR_OK) {
while (1);
led_indicate_error();
}
/* second program data to flash */
idx = 0;
while (1) {
ret = f_read(&f, file_buffer, FILE_BUFF_SIZE, &bc);
if (ret != FR_OK) {
while (1);
led_indicate_error();
}
file_write_flash(ADDR_GAS3 + idx * FILE_BUFF_SIZE, file_buffer, (uint32_t)bc);
if ((uint32_t)bc != FILE_BUFF_SIZE) {
@ -132,14 +133,14 @@ void file_bitmap_update(uint32_t mask)
/* first open file */
ret = f_open(&f, file_name[FILE_IDX_GAS4], FA_READ);
if (ret != FR_OK) {
while (1);
led_indicate_error();
}
/* second program data to flash */
idx = 0;
while (1) {
ret = f_read(&f, file_buffer, FILE_BUFF_SIZE, &bc);
if (ret != FR_OK) {
while (1);
led_indicate_error();
}
file_write_flash(ADDR_GAS4 + idx * FILE_BUFF_SIZE, file_buffer, (uint32_t)bc);
if ((uint32_t)bc != FILE_BUFF_SIZE) {

View File

@ -1,5 +1,6 @@
#include "stm32f4xx_flash.h"
#include "partition.h"
#include "led.h"
#include "file.h"
#include "config.h"
#include "ff.h"
@ -17,14 +18,14 @@ static void file_config_write(uint32_t addr, struct file_config_s *cfg)
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
for (uint32_t i = 0; i < 4; i++) {
if (FLASH_ProgramWord(addr + i * 4, p[i]) != FLASH_COMPLETE) {
while (1);
led_indicate_error();
}
}
FLASH_Lock();
p = (volatile uint32_t *)addr;
if (p[0] != addr || (p[0] + p[1] + p[2]) != p[3]) {
/* program flash error */
while (1);
led_indicate_error();
}
}

View File

@ -2,6 +2,7 @@
#include "file.h"
#include "sdio_sd.h"
#include "partition.h"
#include "led.h"
#define RETRY_MAX (5)
@ -189,14 +190,14 @@ void file_secctor_erase(uint16_t sector)
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | \
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
if (FLASH_EraseSector(sector, VoltageRange_3) != FLASH_COMPLETE) {
while (1);
led_indicate_error();
}
FLASH_Lock();
for (uint32_t i = 0; i < size; i += 4) {
if (*(volatile uint32_t *)(addr + i) == 0xFFFFFFFF) {
continue;
} else {
while (1);
led_indicate_error();
}
}
}
@ -215,7 +216,7 @@ void file_write_flash(uint32_t flash, uint8_t *buff, uint32_t len)
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
for (i = 0; i < len / 4; i++) {
if (FLASH_ProgramWord(flash + i * 4, p_buff[i]) != FLASH_COMPLETE) {
while (1);
led_indicate_error();
}
}
FLASH_Lock();
@ -223,7 +224,7 @@ void file_write_flash(uint32_t flash, uint8_t *buff, uint32_t len)
p_flash = (volatile uint32_t *)flash;
for (i = 0; i < len / 4; i++) {
if (p_flash[i] != p_buff[i]) {
while (1);
led_indicate_error();
}
}
}

View File

@ -1,6 +1,7 @@
#include "partition.h"
#include "file.h"
#include "firmware.h"
#include "led.h"
#include "ff.h"
void file_firmware_update(void)
@ -11,14 +12,14 @@ void file_firmware_update(void)
ret = f_open(&f, file_name[FILE_IDX_FW], FA_READ);
if (ret != FR_OK) {
while (1);
led_indicate_error();
}
idx = 0;
byte_cnt = 0;
while (1) {
ret = f_read(&f, file_buffer, FILE_BUFF_SIZE, &bc);
if (ret != FR_OK) {
while (1);
led_indicate_error();
}
/* check whether sector need to be erase */
if ((byte_cnt == 0) && (bc != 0)) {

View File

@ -64,6 +64,16 @@ void led_delay_ms(uint16_t ms)
TIM_Cmd(TIM3, DISABLE);
}
void led_indicate_error(void)
{
while (1) {
led_delay_ms(100);
led_on(LED1 | LED2);
led_delay_ms(100);
led_off(LED1 | LED2);
}
}
void led_deinit(void)
{
TIM_DeInit(TIM3);

View File

@ -16,6 +16,7 @@ void led_off(uint16_t led);
void led_on(uint16_t led);
void led_toggle(uint16_t led);
void led_delay_ms(uint16_t ms);
void led_indicate_error(void);
void led_deinit(void);
#ifdef __cplusplus

View File

@ -15,10 +15,16 @@ stddriver/src/system_stm32f4xx.c
sdcard/fatfs_drv.c
sdcard/sdio_lowlevel.c
sdcard/sdio_sd.c
stdio/mini_printf.c
coredump/coredump.c
)
add_library(driver STATIC ${FILELIST})
target_include_directories(driver PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/stddriver/inc)
target_include_directories(driver PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/cmsis/inc)
target_include_directories(driver PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/sdcard)
target_include_directories(driver PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/stdio)
target_include_directories(driver PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/coredump)
target_include_directories(driver PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../component/fatfs/inc)

56
driver/coredump/coredump.c Executable file
View File

@ -0,0 +1,56 @@
#include "coredump.h"
#include "mini_printf.h"
extern uint32_t _stack_top;
extern uint32_t _data_run;
extern uint32_t _data_run_end;
extern uint32_t _data_ccm_run;
extern uint32_t _data_ccm_run_end;
extern uint32_t _bss_run;
extern uint32_t _bss_run_end;
extern uint32_t _bss_ccm_run;
extern uint32_t _bss_ccm_run_end;
static void coredump_registers(struct coredump_regs_s *sp, char *thread)
{
mini_printf("\nregister@%s\n", thread);
mini_printf("R0: 0x%p\n", sp->r0);
mini_printf("R1: 0x%p\n", sp->r1);
mini_printf("R2: 0x%p\n", sp->r2);
mini_printf("R3: 0x%p\n", sp->r3);
mini_printf("R4: 0x%p\n", sp->r4);
mini_printf("R5: 0x%p\n", sp->r5);
mini_printf("R6: 0x%p\n", sp->r6);
mini_printf("R7: 0x%p\n", sp->r7);
mini_printf("R8: 0x%p\n", sp->r8);
mini_printf("R9: 0x%p\n", sp->r9);
mini_printf("R10: 0x%p\n", sp->r10);
mini_printf("R11: 0x%p\n", sp->r11);
mini_printf("R12: 0x%p\n", sp->r12);
mini_printf("R13(SP): 0x%p\n", (uint32_t)sp + sizeof(*sp));
mini_printf("R14(LR): 0x%p\n", sp->lr);
mini_printf("R15(PC): 0x%p\n", sp->pc);
mini_printf("xPSR: 0x%p\n", sp->xpsr);
}
static void coredump_memory(uint32_t *start, uint32_t *end, char *comment)
{
mini_printf("\nmemory@%s, length=%d", comment, end - start);
for (uint32_t p = (uint32_t)start & 0xFFFFFFF0; p < (uint32_t)end; p += 4) {
if ((p & 0xF) == 0) {
mini_printf("\n0x%p:", p);
}
mini_printf(" %p", *(uint32_t *)p);
}
}
void coredump(struct coredump_regs_s *sp)
{
mini_printf_init();
coredump_registers(sp, "main_thread");
coredump_memory((uint32_t*)sp, &_stack_top, "stack");
coredump_memory(&_data_run, &_data_run_end, "data");
coredump_memory(&_data_ccm_run, &_data_ccm_run_end, "data_ccm");
coredump_memory(&_bss_run, &_bss_run_end, "bss");
coredump_memory(&_bss_ccm_run, &_bss_ccm_run_end, "bss_ccm");
}

37
driver/coredump/coredump.h Executable file
View File

@ -0,0 +1,37 @@
#ifndef __COREDUMP_H__
#define __COREDUMP_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct coredump_regs_s {
/* register saved by software */
uint32_t exc_return;
uint32_t r4;
uint32_t r5;
uint32_t r6;
uint32_t r7;
uint32_t r8;
uint32_t r9;
uint32_t r10;
uint32_t r11;
/* saved in sp */
uint32_t r0;
uint32_t r1;
uint32_t r2;
uint32_t r3;
uint32_t r12;
uint32_t lr;
uint32_t pc;
uint32_t xpsr;
} coredump_regs;
#ifdef __cplusplus
}
#endif
#endif /* __COREDUMP_H__ */

125
driver/stdio/mini_printf.c Executable file
View File

@ -0,0 +1,125 @@
#include "mini_printf.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_usart.h"
void mini_printf_init(void)
{
USART_ITConfig(USART3, USART_IT_TC, DISABLE);
USART_ClearITPendingBit(USART3, USART_IT_TC);
USART_DMACmd(USART3, USART_DMAReq_Tx, DISABLE);
}
static void uart_putc_raw(char c) {
while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
USART_SendData(USART3, (uint16_t)c);
}
static void uart_putc(char c) {
if (c == '\n')
uart_putc_raw('\r');
uart_putc_raw(c);
}
#include <stdbool.h>
#include <stdarg.h>
void mini_printf(const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
while (*fmt) {
char c = *fmt++;
if (c == '%') {
char c2 = *fmt++;
switch (c2) {
case '%':
uart_putc(c);
break;
case 's': {
const char *v = va_arg(va, const char *);
while (*v) {
uart_putc(*v++);
}
break;
}
case 'd': {
int v = va_arg(va, int);
if (v < 0) {
v = -v;
uart_putc('-');
}
static const int tens[] = {
1000000000,
100000000,
1000000,
100000,
10000,
1000,
100,
10,
1,
};
if (!v) {
uart_putc('0');
} else {
bool had = false;
for(int i = 0; i < sizeof(tens) / sizeof(tens[0]); i++) {
int d = 0;
while (tens[i] <= v) {
v -= tens[i];
d++;
}
if (d || had) {
uart_putc((char)('0'+d));
had = true;
}
}
}
break;
}
case 'p': {
uint32_t v = va_arg(va, uint32_t);
for(int pos=7;pos>=0;pos--) {
int d = (v >> (pos * 4)) & 0xf;
if (d < 10) uart_putc((char)('0'+d));
else uart_putc((char)('a'+d - 10));
}
break;
}
case '0': {
uint32_t v = va_arg(va, uint32_t);
if (fmt[0] > '0' && fmt[0] < '9' && fmt[1] == 'x') {
int zeros = fmt[0]-'1';
bool had_digit=false;
for(int pos=7;pos>=0;pos--) {
int d = (v >> (pos * 4)) & 0xf;
if (!d && pos > zeros && !had_digit) continue;
had_digit = true;
if (d < 10) uart_putc((char)('0'+d));
else uart_putc((char)('a'+d - 10));
}
fmt+=2;
break;
}
__attribute__((fallthrough));
}
default:
uart_putc('%');
uart_putc(c2);
uart_putc('?');
uart_putc('?');
}
} else {
uart_putc(c);
}
}
va_end(va);
}
void mini_puts(const char *str) {
while (*str) {
uart_putc(*str++);
}
uart_putc('\n');
}

17
driver/stdio/mini_printf.h Executable file
View File

@ -0,0 +1,17 @@
#ifndef __MINI_PRINTF_H__
#define __MINI_PRINTF_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32f4xx.h"
void mini_printf_init(void);
void mini_printf(const char *fmt, ...);
#ifdef __cplusplus
}
#endif
#endif /* __MINI_PRINTF_H__ */

View File

@ -14,10 +14,31 @@ set(CMAKE_AR "${TOOLCHAIN}ar")
set(CMAKE_RANLIB "${TOOLCHAIN}ranlib")
set(LINKER_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/flash.ld")
set(MCU_FLAGS "-mcpu=cortex-m4 -mthumb -g -O2 -Wall -nostartfiles -mfloat-abi=hard -mfpu=vfpv4-d16 -ffunction-sections -fdata-sections")
set(CMAKE_C_FLAGS "${MCU_FLAGS}")
set(CMAKE_ASM_FLAGS "${MCU_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${MCU_FLAGS} -T${LINKER_SCRIPT} -Wl,-Map=lark1fq.map")
set(CMAKE_C_FLAGS " \
-mcpu=cortex-m4 \
-mthumb \
-g3 \
-O2 \
-Wall \
-nostartfiles \
-mfloat-abi=hard \
-mfpu=vfpv4-d16 \
-ffunction-sections \
-fdata-sections \
")
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS " \
-ffunction-sections \
-fdata-sections \
-Wl,--gc-sections \
-T${LINKER_SCRIPT} \
-Wl,-Map=${PROJ_NAME}.map \
--specs=nano.specs \
-Wl,--print-memory-usage \
-Wl,--print-output-format \
")
add_definitions(-DSTM32F40_41xxx)
add_definitions(-DUSE_STDPERIPH_DRIVER)
@ -40,5 +61,24 @@ target_link_libraries(${PROJ_NAME}.elf m) # math library
add_custom_command(TARGET ${PROJ_NAME}.elf POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${PROJ_NAME}.elf> ${BIN_FILE}
COMMAND ${CMAKE_OBJDUMP} -d -S $<TARGET_FILE:${PROJ_NAME}.elf> >${ASM_FILE}
COMMENT "Generate ${BIN_FILE}\r\n"
# COMMENT "Generate ${BIN_FILE}\r\n"
COMMAND size ${PROJ_NAME}.elf
COMMAND echo "Calculating SHA-256 checksum for ${BIN_FILE}:"
COMMAND sha256sum ${BIN_FILE}
)
# get git tag
execute_process(
COMMAND git describe --abbrev=40 --tags --dirty --always
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GIT_TAG
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
if(GIT_TAG)
set(PROJECT_SDK_VERSION ${GIT_TAG})
else()
message(WARNING "No Valid version info found for SDK!")
set(PROJECT_SDK_VERSION "version-unknown-panic")
endif()
message(STATUS "Project SDK Version: ${PROJECT_SDK_VERSION}")

18
lark1fq/Makefile Normal file
View File

@ -0,0 +1,18 @@
CMAKE = cmake # use user cmake
cmake_generator = "Unix Makefiles"
RM = $(CMAKE) -E remove_directory
MAKEFLAGS += --no-print-directory
TOOLCHAIN ?= arm-none-eabi-
#cmake definition config
cmake_definition+= -DTOOLCHAIN=${TOOLCHAIN}
build:Makefile
$(CMAKE) -S . -B build -G $(cmake_generator) $(cmake_definition)
$(MAKE) -C build -j
clean::
$(RM) build
.PHONY:build clean

View File

@ -1,14 +1,15 @@
ENTRY(Reset_Handler)
StackSize = 0x4000; /* 16KB */
MEMORY
{
FLASH (rx) :ORIGIN = 0x08020000, LENGTH = 384K
RAM (xrw) :ORIGIN = 0x20000000, LENGTH = 112K
CCM (rw) :ORIGIN = 0x10000000, LENGTH = 48K
CCM_STACK (rw) :ORIGIN = 0x1000C000, LENGTH = 16K
CCM (rw) :ORIGIN = 0x10000000, LENGTH = 64K - StackSize
}
_stack_top = ORIGIN(CCM_STACK) + LENGTH(CCM_STACK);
_stack_top = ORIGIN(CCM) + LENGTH(CCM) + StackSize;
SECTIONS
{

View File

@ -1,5 +1,6 @@
#include "misc.h"
#include "user_misc.h"
#include "button.h"
#include "ltc1867.h"
#include "modbus.h"
#include "filter.h"
@ -24,20 +25,11 @@ void system_tick_init(void)
SysTick_Config(rcc_clocks.HCLK_Frequency / 1000);
}
void led_loop(void)
{
static uint32_t tick = 0;
if (system_tick_cnt - tick > 500) {
led_toggle(LED1);
tick = system_tick_cnt;
}
}
void device_init(void)
{
flag.filter = data_ltc1867.calc_flag;
flag.concentration = flag.filter;
flag.gas_fault = 0xFFFFFFFF;
}
void system_init(void)
@ -47,6 +39,7 @@ void system_init(void)
cali_update_from_flash();
led_init(LED1 | LED2);
heat_init();
button_init();
ltc1867_init();
modbus_init();
filter_init();
@ -58,6 +51,7 @@ void system_init(void)
device_init();
ltc2640_init();
ms5611_init();
led_det_temperature_init();
}
int main(void)
@ -72,9 +66,12 @@ int main(void)
filter_loop();
concentration_loop();
adc_loop();
led_det_temperature_loop();
led_sig_loop();
cli_loop();
ltc2640_loop();
ms5611_loop();
button_loop();
}
return 0;
}

View File

@ -7,6 +7,7 @@ add_definitions(-DDET_TEMPERATURE_LTC1867)
file(GLOB FILELIST
device.c
user_misc.c
button.c
ltc1867.c
filter.c
concentration.c

138
lark1fq/src/button.c Executable file
View File

@ -0,0 +1,138 @@
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "button.h"
#include "device.h"
#include "cali.h"
#include "user_misc.h"
volatile uint8_t flag_cali_by_button = 0;
static void button_cali_zero(void)
{
uint8_t ret;
uint8_t count = 0;
flag_cali_by_button = 1;
/* cali zero record */
for (uint8_t ch = 0; ch < 4; ch++) {
ret = cali_zero_record(ch);
if (ret == 0xFF) {
/* invalid/reference channel */
continue;
} else if (ret == 0) {
/* cali zero record success */
device_status.cali_zero_record_status[ch] = 0;
} else {
/* cali zero record failed */
device_status.cali_zero_record_status[ch] = ret;
return;
}
}
/* cali zero active */
for (uint8_t ch = 0; ch < 4; ch++) {
ret = cali_zero_activate(ch);
if (ret == 0xFF) {
/* invalid/reference channel */
count++;
continue;
} else if (ret == 0) {
/* cali zero active success */
device_status.cali_activate_status &= ~(1 << ch);
count++;
} else {
/* cali zero active failed */
device_status.cali_activate_status |= (1 << ch);
return;
}
}
flag_cali_by_button = 0;
/* failed or success */
if (count >= 4) {
data_cali_flash.word_remain = CALI_FLASH_WORD_CNT;
led_ctrl[1].times_volatile = 0;
led_ctrl[1].times = 3;
led_ctrl[1].on_volatile = 0;
led_ctrl[1].on = 5;
led_ctrl[1].off = 5;
led_ctrl[1].state_save = led_ctrl[1].state;
led_ctrl[1].state = LED_BLINK_ON;
}
}
static void button_cali_restore(void)
{
flag_cali_by_button = 1;
for (uint8_t ch = 0; ch < 4; ch++) {
cali_restore(ch);
device_status.cali_restore_status &= ~(1 << ch);
}
flag_cali_by_button = 0;
data_cali_flash.word_remain = CALI_FLASH_WORD_CNT;
led_ctrl[1].times_volatile = 0;
led_ctrl[1].times = 5;
led_ctrl[1].on_volatile = 0;
led_ctrl[1].on = 5;
led_ctrl[1].off = 5;
led_ctrl[1].state_save = led_ctrl[1].state;
led_ctrl[1].state = LED_BLINK_ON;
}
static void button_reset_system(void)
{
NVIC_SystemReset();
}
void button_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {
.GPIO_Pin = PIN_BUTTON,
.GPIO_Mode = GPIO_Mode_IN,
.GPIO_OType = GPIO_OType_PP,
.GPIO_Speed = GPIO_Speed_2MHz,
.GPIO_PuPd = GPIO_PuPd_UP,
};
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_Init(PORT_BUTTON, &GPIO_InitStructure);
}
int button_is_pressed(void)
{
if (GPIO_ReadInputDataBit(PORT_BUTTON, PIN_BUTTON)) {
return 0;
} else {
return 1;
}
}
void button_loop(void)
{
static uint32_t ms = 0;
static uint32_t cnt_pressed = 0;
static uint32_t cnt_released = 0;
if (system_tick_cnt < (ms + 100)) {
return;
}
ms = system_tick_cnt;
if (button_is_pressed()) {
cnt_pressed++;
cnt_released = 0;
} else {
cnt_released++;
if ((cnt_pressed > 0) && (cnt_released > 2)) {
if (cnt_pressed < 3) {
/* do nothing */
} else if (cnt_pressed < 30) {
button_cali_zero();
} else if (cnt_pressed < 75) {
button_cali_restore();
} else {
button_reset_system();
}
cnt_released = 0;
cnt_pressed = 0;
}
}
}

23
lark1fq/src/button.h Executable file
View File

@ -0,0 +1,23 @@
#ifndef __BUTTON_H__
#define __BUTTON_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32f4xx.h"
#define PORT_BUTTON (GPIOB)
#define PIN_BUTTON (GPIO_Pin_14)
extern uint32_t system_tick_cnt;
void button_init(void);
int button_is_pressed(void);
void button_loop(void);
#ifdef __cplusplus
}
#endif
#endif /* __BUTTON_H__ */

View File

@ -365,7 +365,9 @@ uint8_t cali_zero_activate(uint8_t ch)
data_cali_flash.sig_zero[ch - 1] = data_cali_ram.sig_zero[ch - 1];
data_cali_flash.temperature_zero[ch - 1] = data_cali_ram.temperature_zero[ch - 1];
data_cali_flash.stage[ch - 1] = CALI_STAGE_ACTIVED; /* bit[3:0] for zero, bit[7:4] for span */
if (flag_cali_by_button == 0) {
data_cali_flash.word_remain = CALI_FLASH_WORD_CNT;
}
return 0;
}
@ -434,8 +436,10 @@ void cali_restore(uint8_t ch)
data_cali_flash.concentration[ch - 1] = 0;
data_cali_flash.temperature_zero[ch - 1] = 0;
data_cali_flash.temperature_span[ch - 1] = 0;
if (flag_cali_by_button == 0) {
data_cali_flash.word_remain = CALI_FLASH_WORD_CNT;
}
}
void cali_zero_parse_from_flash(uint8_t ch)
{

View File

@ -35,6 +35,7 @@ struct data_cali_s {
extern struct data_cali_s data_cali_flash;
extern struct data_cali_s data_cali_ram;
extern volatile uint8_t flag_cali_by_button;
uint8_t cali_get_zero_stage(uint8_t stage);
uint8_t cali_get_span_stage(uint8_t stage);

View File

@ -38,6 +38,49 @@ void concentration_init(void)
}
}
int32_t concentration_neg_drift_compensation(uint8_t ch, int32_t reading)
{
static uint8_t drift_update_enable[4] = {1, 1, 1, 1};
static uint8_t neg_reading_num[4] = {0, 0, 0, 0};
static int32_t neg_reading_sum[4] = {0, 0, 0, 0};
static int32_t zero_neg_drift[4] = {0, 0, 0, 0};
static int32_t reading_fixed[4] = {0, 0, 0, 0};
static uint8_t neg_fixed_num[4] = {0, 0, 0, 0};
reading_fixed[ch] = reading;
if(drift_update_enable[ch]) {
if (reading < 0) {
neg_reading_sum[ch] += reading;
neg_reading_num[ch] ++;
reading_fixed[ch] = 0;
if(neg_reading_num[ch] >= 10) {
zero_neg_drift[ch] = neg_reading_sum[ch] / neg_reading_num[ch];
drift_update_enable[ch] = 0;
neg_reading_num[ch] = 0;
neg_reading_sum[ch] = 0;
}
} else {
neg_reading_num[ch] = 0;
neg_reading_sum[ch] = 0;
}
}
if (zero_neg_drift[ch]) {
reading_fixed[ch] = reading - zero_neg_drift[ch];
if (reading_fixed[ch] < 0) {
neg_fixed_num[ch]++;
if (neg_fixed_num[ch] >= 10) {
drift_update_enable[ch] = 1;
neg_fixed_num[ch] = 0;
}
} else {
neg_fixed_num[ch] = 0;
}
}
return ((reading_fixed[ch] > 0) ? reading_fixed[ch] : 0);
}
int32_t concentration_calc(uint8_t ch)
{
struct data_lookup_table_s *p; /* just for reduce text char in code */
@ -118,16 +161,20 @@ void concentration_loop(void)
for (uint8_t i = 0; i < 4; i++) {
if ((data_gas_info.id[i] != GAS_ID_INVALID) && (data_gas_info.id[i] != GAS_ID_REF)) {
device_data.gas_concentration[i] = concentration_calc(i);
device_data.gas_neg_concentration[i] = concentration_neg_drift_compensation(i, device_data.gas_concentration[i]);
} else {
device_data.gas_concentration[i] = 0;
device_data.gas_neg_concentration[i] = 0;
}
}
} else if (data_gas_info.comb == GAS_COMB_2_2) {
for (uint8_t i = 0; i < 4; i++) {
if ((data_gas_info.id[i] != GAS_ID_INVALID) && (data_gas_info.id[i] != GAS_ID_REF)) {
device_data.gas_concentration[i] = concentration_calc(i);
device_data.gas_neg_concentration[i] = concentration_neg_drift_compensation(i, device_data.gas_concentration[i]);
} else {
device_data.gas_concentration[i] = 0;
device_data.gas_neg_concentration[i] = 0;
}
}
} else if (data_gas_info.comb == GAS_COMB_3_1) {
@ -138,15 +185,18 @@ void concentration_loop(void)
if ((data_gas_info.id[i] != GAS_ID_INVALID) && (data_gas_info.id[i] != GAS_ID_REF)) {
conc = concentration_calc(i);
device_data.gas_concentration[i] = conc;
device_data.gas_neg_concentration[i] = concentration_neg_drift_compensation(i, device_data.gas_concentration[i]);
sum += conc;
} else {
ref = i;
}
}
device_data.gas_concentration[ref] = sum / 3;
device_data.gas_neg_concentration[ref] = concentration_neg_drift_compensation(ref, device_data.gas_concentration[ref]);
} else {
for (uint8_t i = 0; i < 4; i++) {
device_data.gas_concentration[i] = 0;
device_data.gas_neg_concentration[i] = 0;
}
}
}

View File

@ -25,6 +25,7 @@ extern struct data_lookup_table_s data_lookup_table[4];
void concentration_lookup_table_copy(uint8_t ch);
void concentration_init(void);
int32_t concentration_neg_drift_compensation(uint8_t ch, int32_t reading);
int32_t concentration_calc(uint8_t ch);
void concentration_loop(void);

View File

@ -102,7 +102,11 @@ const uint8_t * const modbus_map_ro[] = {
[OFFSET_MAIN + 61] = (uint8_t *)(&bitmap_main->gasn_avail_bitmap) + 2,
[OFFSET_MAIN + 62] = (uint8_t *)(&bitmap_main->gasn_avail_bitmap) + 1,
[OFFSET_MAIN + 63] = (uint8_t *)(&bitmap_main->gasn_avail_bitmap) + 0,
[(OFFSET_MAIN + 64) ... (OFFSET_MAIN + 511)] = (uint8_t *)0,
[OFFSET_MAIN + 64] = (uint8_t *)(&flag.gas_fault) + 3,
[OFFSET_MAIN + 65] = (uint8_t *)(&flag.gas_fault) + 2,
[OFFSET_MAIN + 66] = (uint8_t *)(&flag.gas_fault) + 1,
[OFFSET_MAIN + 67] = (uint8_t *)(&flag.gas_fault) + 0,
[(OFFSET_MAIN + 68) ... (OFFSET_MAIN + 511)] = num_tab_ro + 0,
[OFFSET_GAS1 + 0] = (uint8_t *)(&bitmap_main->gas1_sub_id) + 3,
[OFFSET_GAS1 + 1] = (uint8_t *)(&bitmap_main->gas1_sub_id) + 2,
@ -356,7 +360,7 @@ const uint8_t * const modbus_map_ro[] = {
[OFFSET_GAS1 + 249] = (uint8_t *)&((*bitmap_gas)[0].user_cali.span_data[4][6]) + 2,
[OFFSET_GAS1 + 250] = (uint8_t *)&((*bitmap_gas)[0].user_cali.span_data[4][6]) + 1,
[OFFSET_GAS1 + 251] = (uint8_t *)&((*bitmap_gas)[0].user_cali.span_data[4][6]) + 0,
[(OFFSET_GAS1 + 252) ... (OFFSET_GAS1 + 511)] = (uint8_t *)0,
[(OFFSET_GAS1 + 252) ... (OFFSET_GAS1 + 511)] = num_tab_ro + 0,
[OFFSET_GAS2 + 0] = (uint8_t *)(&bitmap_main->gas2_sub_id) + 3,
[OFFSET_GAS2 + 1] = (uint8_t *)(&bitmap_main->gas2_sub_id) + 2,
@ -642,7 +646,7 @@ const uint8_t * const modbus_map_ro[] = {
[OFFSET_GAS2 + 249] = (uint8_t *)&((*bitmap_gas)[1].user_cali.span_data[4][6]) + 2,
[OFFSET_GAS2 + 250] = (uint8_t *)&((*bitmap_gas)[1].user_cali.span_data[4][6]) + 1,
[OFFSET_GAS2 + 251] = (uint8_t *)&((*bitmap_gas)[1].user_cali.span_data[4][6]) + 0,
[(OFFSET_GAS2 + 252) ... (OFFSET_GAS2 + 511)] = (uint8_t *)0,
[(OFFSET_GAS2 + 252) ... (OFFSET_GAS2 + 511)] = num_tab_ro + 0,
[OFFSET_GAS3 + 0] = (uint8_t *)(&bitmap_main->gas3_sub_id) + 3,
[OFFSET_GAS3 + 1] = (uint8_t *)(&bitmap_main->gas3_sub_id) + 2,
@ -928,7 +932,7 @@ const uint8_t * const modbus_map_ro[] = {
[OFFSET_GAS3 + 249] = (uint8_t *)&((*bitmap_gas)[2].user_cali.span_data[4][6]) + 2,
[OFFSET_GAS3 + 250] = (uint8_t *)&((*bitmap_gas)[2].user_cali.span_data[4][6]) + 1,
[OFFSET_GAS3 + 251] = (uint8_t *)&((*bitmap_gas)[2].user_cali.span_data[4][6]) + 0,
[(OFFSET_GAS3 + 252) ... (OFFSET_GAS3 + 511)] = (uint8_t *)0,
[(OFFSET_GAS3 + 252) ... (OFFSET_GAS3 + 511)] = num_tab_ro + 0,
[OFFSET_GAS4 + 0] = (uint8_t *)(&bitmap_main->gas4_sub_id) + 3,
[OFFSET_GAS4 + 1] = (uint8_t *)(&bitmap_main->gas4_sub_id) + 2,
@ -1214,7 +1218,7 @@ const uint8_t * const modbus_map_ro[] = {
[OFFSET_GAS4 + 249] = (uint8_t *)&((*bitmap_gas)[3].user_cali.span_data[4][6]) + 2,
[OFFSET_GAS4 + 250] = (uint8_t *)&((*bitmap_gas)[3].user_cali.span_data[4][6]) + 1,
[OFFSET_GAS4 + 251] = (uint8_t *)&((*bitmap_gas)[3].user_cali.span_data[4][6]) + 0,
[(OFFSET_GAS4 + 252) ... (OFFSET_GAS4 + 511)] = (uint8_t *)0,
[(OFFSET_GAS4 + 252) ... (OFFSET_GAS4 + 511)] = num_tab_ro + 0,
[OFFSET_DATA + 0] = (uint8_t *)&(device_data.detector_temperature) + 3,
[OFFSET_DATA + 1] = (uint8_t *)&(device_data.detector_temperature) + 2,
@ -1256,7 +1260,7 @@ const uint8_t * const modbus_map_ro[] = {
[OFFSET_DATA + 37] = (uint8_t *)&(device_data.gas_sig[0]) + 2,
[OFFSET_DATA + 38] = (uint8_t *)&(device_data.gas_sig[0]) + 1,
[OFFSET_DATA + 39] = (uint8_t *)&(device_data.gas_sig[0]) + 0,
[(OFFSET_DATA + 40) ... (OFFSET_DATA + 47)] = (uint8_t *)0,
[(OFFSET_DATA + 40) ... (OFFSET_DATA + 47)] = num_tab_ro + 0,
[OFFSET_DATA + 48] = (uint8_t *)&(device_data.gas_concentration[1]) + 3,
[OFFSET_DATA + 49] = (uint8_t *)&(device_data.gas_concentration[1]) + 2,
[OFFSET_DATA + 50] = (uint8_t *)&(device_data.gas_concentration[1]) + 1,
@ -1265,7 +1269,7 @@ const uint8_t * const modbus_map_ro[] = {
[OFFSET_DATA + 53] = (uint8_t *)&(device_data.gas_sig[1]) + 2,
[OFFSET_DATA + 54] = (uint8_t *)&(device_data.gas_sig[1]) + 1,
[OFFSET_DATA + 55] = (uint8_t *)&(device_data.gas_sig[1]) + 0,
[(OFFSET_DATA + 56) ... (OFFSET_DATA + 63)] = (uint8_t *)0,
[(OFFSET_DATA + 56) ... (OFFSET_DATA + 63)] = num_tab_ro + 0,
[OFFSET_DATA + 64] = (uint8_t *)&(device_data.gas_concentration[2]) + 3,
[OFFSET_DATA + 65] = (uint8_t *)&(device_data.gas_concentration[2]) + 2,
[OFFSET_DATA + 66] = (uint8_t *)&(device_data.gas_concentration[2]) + 1,
@ -1274,7 +1278,7 @@ const uint8_t * const modbus_map_ro[] = {
[OFFSET_DATA + 69] = (uint8_t *)&(device_data.gas_sig[2]) + 2,
[OFFSET_DATA + 70] = (uint8_t *)&(device_data.gas_sig[2]) + 1,
[OFFSET_DATA + 71] = (uint8_t *)&(device_data.gas_sig[2]) + 0,
[(OFFSET_DATA + 72) ... (OFFSET_DATA + 79)] = (uint8_t *)0,
[(OFFSET_DATA + 72) ... (OFFSET_DATA + 79)] = num_tab_ro + 0,
[OFFSET_DATA + 80] = (uint8_t *)&(device_data.gas_concentration[3]) + 3,
[OFFSET_DATA + 81] = (uint8_t *)&(device_data.gas_concentration[3]) + 2,
[OFFSET_DATA + 82] = (uint8_t *)&(device_data.gas_concentration[3]) + 1,
@ -1283,8 +1287,24 @@ const uint8_t * const modbus_map_ro[] = {
[OFFSET_DATA + 85] = (uint8_t *)&(device_data.gas_sig[3]) + 2,
[OFFSET_DATA + 86] = (uint8_t *)&(device_data.gas_sig[3]) + 1,
[OFFSET_DATA + 87] = (uint8_t *)&(device_data.gas_sig[3]) + 0,
[(OFFSET_DATA + 88) ... (OFFSET_DATA + 95)] = (uint8_t *)0,
[(OFFSET_DATA + 96) ... (OFFSET_DATA + 511)] = (uint8_t *)0,
[(OFFSET_DATA + 88) ... (OFFSET_DATA + 95)] = num_tab_ro + 0,
[OFFSET_DATA + 96] = (uint8_t *)&(device_data.gas_neg_concentration[0]) + 3,
[OFFSET_DATA + 97] = (uint8_t *)&(device_data.gas_neg_concentration[0]) + 2,
[OFFSET_DATA + 98] = (uint8_t *)&(device_data.gas_neg_concentration[0]) + 1,
[OFFSET_DATA + 99] = (uint8_t *)&(device_data.gas_neg_concentration[0]) + 0,
[OFFSET_DATA + 100] = (uint8_t *)&(device_data.gas_neg_concentration[1]) + 3,
[OFFSET_DATA + 101] = (uint8_t *)&(device_data.gas_neg_concentration[1]) + 2,
[OFFSET_DATA + 102] = (uint8_t *)&(device_data.gas_neg_concentration[1]) + 1,
[OFFSET_DATA + 103] = (uint8_t *)&(device_data.gas_neg_concentration[1]) + 0,
[OFFSET_DATA + 104] = (uint8_t *)&(device_data.gas_neg_concentration[2]) + 3,
[OFFSET_DATA + 105] = (uint8_t *)&(device_data.gas_neg_concentration[2]) + 2,
[OFFSET_DATA + 106] = (uint8_t *)&(device_data.gas_neg_concentration[2]) + 1,
[OFFSET_DATA + 107] = (uint8_t *)&(device_data.gas_neg_concentration[2]) + 0,
[OFFSET_DATA + 108] = (uint8_t *)&(device_data.gas_neg_concentration[3]) + 3,
[OFFSET_DATA + 109] = (uint8_t *)&(device_data.gas_neg_concentration[3]) + 2,
[OFFSET_DATA + 110] = (uint8_t *)&(device_data.gas_neg_concentration[3]) + 1,
[OFFSET_DATA + 111] = (uint8_t *)&(device_data.gas_neg_concentration[3]) + 0,
[(OFFSET_DATA + 112) ... (OFFSET_DATA + 511)] = num_tab_ro + 0,
[OFFSET_STAT + 0] = (uint8_t *)&(device_status.cali_zero_record_status[0]) + 1,
[OFFSET_STAT + 1] = (uint8_t *)&(device_status.cali_zero_record_status[0]) + 0,
@ -1308,5 +1328,5 @@ const uint8_t * const modbus_map_ro[] = {
[OFFSET_STAT + 19] = (uint8_t *)&(device_status.cali_restore_status) + 0,
[OFFSET_STAT + 20] = (uint8_t *)&(device_status.heat_on_off_status) + 1,
[OFFSET_STAT + 21] = (uint8_t *)&(device_status.heat_on_off_status) + 0,
[(OFFSET_STAT + 22) ... (OFFSET_STAT + 511)] = (uint8_t *)0,
[(OFFSET_STAT + 22) ... (OFFSET_STAT + 511)] = num_tab_ro + 0,
};

View File

@ -39,12 +39,10 @@ struct bitmap_main_s {
uint32_t gas4_unit_code;
uint8_t gas4_unit_name[8];
uint32_t ch1_filter_length;
uint32_t ch2_filter_length;
uint32_t ch3_filter_length;
uint32_t ch4_filter_length;
uint32_t filter_median[4];
uint32_t filter_window[4];
uint8_t res[204];
uint8_t res[188];
uint32_t checksum;
uint32_t gasn_avail_bitmap;
};
@ -161,7 +159,7 @@ struct device_data_s {
uint32_t gas_sig[4];
// uint32_t gas_sig_fliter[4];
int32_t gas_concentration[4];
// int32_t gas_neg_concentration[4];
int32_t gas_neg_concentration[4];
};
struct device_status_s {
@ -177,6 +175,7 @@ struct flag_s {
uint32_t filter;
uint32_t concentration;
uint32_t filter_climb;
uint32_t gas_fault;
};
extern const uint8_t * const modbus_map_ro[];

View File

@ -8,44 +8,56 @@ static uint32_t sum_gas1[FILTER_SUM_LEN_GAS1] __attribute__((section(".bss_ccm")
static uint32_t sum_gas2[FILTER_SUM_LEN_GAS2] __attribute__((section(".bss_ccm")));
static uint32_t sum_gas3[FILTER_SUM_LEN_GAS3] __attribute__((section(".bss_ccm")));
static uint32_t sum_gas4[FILTER_SUM_LEN_GAS4] __attribute__((section(".bss_ccm")));
static struct list_s median_gas1[FILTER_MEDIAN_LEN_GAS1] __attribute__((section(".bss_ccm")));
static struct list_s median_gas2[FILTER_MEDIAN_LEN_GAS2] __attribute__((section(".bss_ccm")));
static struct list_s median_gas3[FILTER_MEDIAN_LEN_GAS3] __attribute__((section(".bss_ccm")));
static struct list_s median_gas4[FILTER_MEDIAN_LEN_GAS4] __attribute__((section(".bss_ccm")));
static uint32_t window_gas1[FILTER_WINDOW_LEN_GAS1] __attribute__((section(".bss_ccm")));
static uint32_t window_gas2[FILTER_WINDOW_LEN_GAS2] __attribute__((section(".bss_ccm")));
static uint32_t window_gas3[FILTER_WINDOW_LEN_GAS3] __attribute__((section(".bss_ccm")));
static uint32_t window_gas4[FILTER_WINDOW_LEN_GAS4] __attribute__((section(".bss_ccm")));
static uint8_t filter_pool[32 * 1024] __attribute__((section(".bss_ccm"))) __attribute__((aligned(4)));
struct data_filter_s data_filter[4] __attribute__((section(".bss_ccm")));
const uint16_t median_length[4] = {1024, 128, 128, 128};
const uint16_t window_length[4] = {256, 64, 64, 64};
void filter_init(void)
{
uint32_t length;
/* data_filter parameter init */
data_filter[0].sum_len = FILTER_SUM_LEN_GAS1;
data_filter[0].sum_buff = sum_gas1;
data_filter[0].median_len = FILTER_MEDIAN_LEN_GAS1;
data_filter[0].median_buff = median_gas1;
data_filter[0].window_len = FILTER_WINDOW_LEN_GAS1;
data_filter[0].window_buff = window_gas1;
data_filter[1].sum_len = FILTER_SUM_LEN_GAS2;
data_filter[1].sum_buff = sum_gas2;
data_filter[1].median_len = FILTER_MEDIAN_LEN_GAS2;
data_filter[1].median_buff = median_gas2;
data_filter[1].window_len = FILTER_WINDOW_LEN_GAS2;
data_filter[1].window_buff = window_gas2;
data_filter[2].sum_len = FILTER_SUM_LEN_GAS3;
data_filter[2].sum_buff = sum_gas3;
data_filter[2].median_len = FILTER_MEDIAN_LEN_GAS3;
data_filter[2].median_buff = median_gas3;
data_filter[2].window_len = FILTER_WINDOW_LEN_GAS3;
data_filter[2].window_buff = window_gas3;
data_filter[3].sum_len = FILTER_SUM_LEN_GAS4;
data_filter[3].sum_buff = sum_gas4;
data_filter[3].median_len = FILTER_MEDIAN_LEN_GAS4;
data_filter[3].median_buff = median_gas4;
data_filter[3].window_len = FILTER_WINDOW_LEN_GAS4;
data_filter[3].window_buff = window_gas4;
/* get data_filter length init parameters */
for (uint8_t i = 0; i < 4; i++) {
data_filter[i].median_len = bitmap_main->filter_median[i];
data_filter[i].window_len = bitmap_main->filter_window[i];
}
/* check whether pool is enough */
length = 0;
for (uint8_t i = 0; i < 4; i++) {
if (data_gas_info.id[i] == GAS_ID_INVALID) {
continue;
} else {
data_filter[i].median_buff = (struct list_s *)(filter_pool + length);
length += (data_filter[i].median_len * sizeof(struct list_s));
data_filter[i].window_buff = (uint32_t *)(filter_pool + length);
length += (data_filter[i].window_len * sizeof(uint32_t));
}
}
/* use default length para when para is too big */
if (length > sizeof(filter_pool)) {
length = 0;
for (uint8_t i = 0; i < 4; i++) {
data_filter[i].median_buff = (struct list_s *)(filter_pool + length);
data_filter[i].median_len = median_length[i];
length += (data_filter[i].median_len * sizeof(struct list_s));
data_filter[i].window_buff = (uint32_t *)(filter_pool + length);
data_filter[i].window_len = window_length[i];
length += (data_filter[i].window_len * sizeof(uint32_t));
}
}
for (uint8_t i = 0; i < 4; i++) {
uint16_t len;
@ -88,7 +100,7 @@ void filter_init(void)
data_filter[i].window_sum = 0;
data_filter[i].window_idx = 0;
}
flag.filter_climb = FILTER_WINDOW_LEN_GAS1 + FILTER_MEDIAN_LEN_GAS1;
flag.filter_climb = data_filter[0].median_len + data_filter[0].window_len;
}
void filter_input_data(uint8_t channel, uint32_t data)
@ -125,6 +137,9 @@ void filter_median_process(void)
uint16_t idx, len;
for (uint8_t i = 0; i < 4; i++) {
if (data_gas_info.id[i] == GAS_ID_INVALID) {
continue;
}
idx = data_filter[i].median_idx;
list = &(data_filter[i].median_buff[idx]);
/* delete old node */
@ -170,6 +185,9 @@ void filter_window_process(void)
uint16_t idx;
for (uint8_t i = 0; i < 4; i++) {
if (data_gas_info.id[i] == GAS_ID_INVALID) {
continue;
}
idx = data_filter[i].window_idx;
sum = data_filter[i].window_sum;
val = data_filter[i].median_output;
@ -186,14 +204,88 @@ void filter_window_process(void)
}
}
static int flag_for_sig_init_error(uint8_t ch, uint32_t sig)
{
const struct lookup_table_s *p; /* just for reduce text char in code */
float temp, temp_quantum;
float k; /* delta_b = y1 + (y2 - y1) / (x2 - x1) * (temp - x1) */
float sig_fixed;
uint8_t idx_t = 0; /* temperature index */
if (data_gas_info.id[ch] == GAS_ID_INVALID) {
return 0;
}
/* step1: initialization variable */
p = &((*bitmap_gas)[ch].lookup_table);
temp = (float)(device_data.detector_temperature);
/* step2: get temperature index */
for (idx_t = 0; idx_t < p->temperature_points; idx_t++) {
if (temp < p->detector_temperature[idx_t]) {
break;
}
}
if (idx_t == 0) {
idx_t = 1; /* temperature is less than lowest temperature */
} else if (idx_t >= p->temperature_points) {
idx_t = p->temperature_points - 1; /* temperature is more than highest temperature */
} else {
/* calc with linear relation */
}
/* step3: calc const variable of temperature */
temp = temp - p->detector_temperature[idx_t - 1];
temp_quantum = p->detector_temperature[idx_t] - p->detector_temperature[idx_t - 1];
/* step4: calc sig0 value by temperature */
k = ((float)(p->sig[0][idx_t]) - (float)(p->sig[0][idx_t - 1])) / temp_quantum;
sig_fixed = k * temp + p->sig[0][idx_t - 1];
/* laset sig > sig_fixed * 80% */
if (sig < sig_fixed * 0.8f) {
return 1;
} else {
return 0;
}
}
static void flag_for_sig_init_error_process(void)
{
uint32_t flag_fault = 0xFFFFFFFF;
for (uint8_t ch = 0; ch < 4; ch++) {
if (data_gas_info.id[ch] == GAS_ID_INVALID) {
flag_fault |= (1 << ch);
continue;
}
if (flag_for_sig_init_error(ch, data_filter[ch].window_output)) {
flag_fault |= (1 << ch);
} else {
flag_fault &= ~(1 << ch);
}
}
flag.gas_fault = flag_fault;
}
void filter_output_process(void)
{
if (flag.filter_climb > 0) {
flag.filter_climb--;
if (system_tick_cnt > 25 * 1000) {
while (flag.filter_climb) {
filter_sum_process();
filter_median_process();
filter_window_process();
flag.filter_climb--;
}
}
if (flag.filter_climb == 0) {
flag_for_sig_init_error_process();
}
return;
}
for (uint8_t i = 0; i < 4; i++) {
if (data_gas_info.id[i] == 0xFFFFFFFF) {
if (data_gas_info.id[i] == GAS_ID_INVALID) {
device_data.gas_sig[i] = 0;
} else {
device_data.gas_sig[i] = data_filter[i].window_output;

View File

@ -12,16 +12,6 @@
#define FILTER_SUM_LEN_GAS3 (8 * 2)
#define FILTER_SUM_LEN_GAS4 (8 * 2)
#define FILTER_MEDIAN_LEN_GAS1 (128)
#define FILTER_MEDIAN_LEN_GAS2 (64)
#define FILTER_MEDIAN_LEN_GAS3 (64)
#define FILTER_MEDIAN_LEN_GAS4 (64)
#define FILTER_WINDOW_LEN_GAS1 (256)
#define FILTER_WINDOW_LEN_GAS2 (32)
#define FILTER_WINDOW_LEN_GAS3 (32)
#define FILTER_WINDOW_LEN_GAS4 (32)
struct list_s {
struct list_s *prev;
struct list_s *next;
@ -49,6 +39,8 @@ struct data_filter_s {
uint32_t window_output;
};
extern uint32_t system_tick_cnt;
extern void filter_init(void);
extern void filter_input_data(uint8_t channel, uint32_t data);
extern void filter_sum_process(void);

View File

@ -4,6 +4,7 @@
#include "stm32f4xx_gpio.h"
struct data_gas_info_s data_gas_info __attribute__((section(".bss_ccm")));
struct led_ctrl_s led_ctrl[2];
void led_init(uint16_t led)
{
@ -18,6 +19,9 @@ void led_init(uint16_t led)
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
GPIO_Init(PORT_LED, &GPIO_InitStructure);
led_off(led);
for (uint8_t i = 0; i < 2; i++) {
led_ctrl[i].state = 0;
}
}
void led_off(uint16_t led)
@ -35,6 +39,124 @@ void led_toggle(uint16_t led)
GPIO_ToggleBits(PORT_LED, led);
}
void led_det_temperature_init(void)
{
led_ctrl[0].times_volatile = 0;
led_ctrl[0].times = ~0;
led_ctrl[0].on_volatile = 0;
led_ctrl[0].on = 10;
led_ctrl[0].off = 10;
led_ctrl[0].state = LED_BLINK_ON;
}
void led_det_temperature_loop(void)
{
static uint32_t ms = 0;
static uint32_t det_temp = 0;
uint32_t diff;
if (system_tick_cnt < (ms + 1000 * 60)) {
return;
}
ms = system_tick_cnt;
if (det_temp < device_data.detector_temperature) {
diff = device_data.detector_temperature - det_temp;
} else {
diff = det_temp - device_data.detector_temperature;
}
det_temp = device_data.detector_temperature;
if (diff < 20) {
/* deterator temperature is stable */
led_ctrl[0].state = LED_ON;
} else {
/* deterator temperature is not stable */
led_det_temperature_init();
}
}
void led_sig_loop(void)
{
static uint32_t ms = 0;
uint8_t count = 0;
uint8_t led;
if (system_tick_cnt < (ms + 100)) {
return;
}
ms = system_tick_cnt;
for (uint8_t ch = 0; ch < 4; ch++) {
if (data_gas_info.id[ch] == GAS_ID_INVALID) {
count++;
continue;
} else {
if (device_data.gas_sig[ch] < 10) {
break;
} else {
count++;
}
}
}
if (count >= 4) {
/* sig is all normal, LED on */
led = LED_ON;
} else {
/* sig is not all normal, LED off */
led = LED_OFF;
}
if (led_ctrl[1].state == LED_BLINK_OFF || led_ctrl[1].state == LED_BLINK_ON) {
led_ctrl[1].state_save = led;
} else {
led_ctrl[1].state = led;
}
}
void led_loop(void)
{
static uint32_t ms = 0;
uint16_t led;
if (system_tick_cnt < (ms + 100)) {
return;
}
ms = system_tick_cnt;
for (uint8_t i = 0; i < 2; i++) {
led = (i == 0) ? LED1 : LED2;
if (led_ctrl[i].state == LED_OFF) {
led_off(led);
} else if (led_ctrl[i].state == LED_ON) {
led_on(led);
} else {
if (led_ctrl[i].state == LED_BLINK_OFF) {
led_off(led);
led_ctrl[i].off_volatile++;
if (led_ctrl[i].off_volatile >= led_ctrl[i].off) {
led_ctrl[i].off_volatile = 0;
led_ctrl[i].on_volatile = 0;
led_ctrl[i].state = LED_BLINK_ON;
led_ctrl[i].times_volatile++;
if (led_ctrl[i].times == ~0) {
/* blink forever */
} else if (led_ctrl[i].times_volatile >= led_ctrl[i].times) {
led_ctrl[i].state = led_ctrl[i].state_save;
}
}
} else if (led_ctrl[i].state == LED_BLINK_ON) {
led_on(led);
led_ctrl[i].on_volatile++;
if (led_ctrl[i].on_volatile >= led_ctrl[i].on) {
led_ctrl[i].on_volatile = 0;
led_ctrl[i].off_volatile = 0;
led_ctrl[i].state = LED_BLINK_OFF;
}
}
}
}
}
void heat_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {

View File

@ -29,13 +29,37 @@ struct data_gas_info_s {
uint8_t comb;
};
#define LED_OFF (0)
#define LED_ON (1)
#define LED_BLINK_ON (2)
#define LED_BLINK_OFF (3)
struct led_ctrl_s {
uint8_t state_save; /* saved state before blink */
uint8_t state; /* 0:off, 1:of, 2:blink_on, 3:blink_off */
uint8_t on; /* led on time when blink, unit:0.1s */
uint8_t off; /* led off time when blink, unit:0.1s */
uint8_t times; /* times of blink */
uint8_t on_volatile;
uint8_t off_volatile;
uint8_t times_volatile;
};
extern struct led_ctrl_s led_ctrl[2];
extern struct data_gas_info_s data_gas_info;
extern uint32_t system_tick_cnt;
void led_init(uint16_t led);
void led_off(uint16_t led);
void led_on(uint16_t led);
void led_toggle(uint16_t led);
void led_det_temperature_init(void);
void led_det_temperature_loop(void);
void led_sig_loop(void);
void led_loop(void);
void heat_init(void);
void heat_on(void);
void heat_off(void);

View File

@ -66,8 +66,19 @@ Reset_Handler:
.section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
b Infinite_Loop
MRS r0, msp
STMFD r0!, {r4 - r11}
STMFD r0!, {lr}
MSR msp, r0
PUSH {lr}
BL coredump
POP {lr}
POP {lr}
POP {r4 - r11}
BX lr
.size Default_Handler, .-Default_Handler
.section .isr_vector,"a",%progbits