391 lines
13 KiB
C
391 lines
13 KiB
C
/**
|
||
* @file app.c
|
||
* @author xxx
|
||
* @date 2023-08-30 08:58:43
|
||
* @brief app初始化和app启动
|
||
* @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
|
||
*/
|
||
#include "file_storage.h"
|
||
#include "app.h"
|
||
#include "adcs.h"
|
||
#include "menus.h"
|
||
#include "test_bsp.h"
|
||
#include "bootload.h"
|
||
#include "wl_flash.h"
|
||
#include "mode_diagnosis.h"
|
||
|
||
// https://blog.51cto.com/u_15427821/4586693
|
||
__IO device_reset_flag_e reset_flag __attribute__((section("NOINIT"), zero_init)); ///< 复位标志
|
||
__IO udevice_t udevice __attribute__((section("NOINIT"), zero_init)); ///< 设备参数
|
||
__IO rt_save_param_t rt_save __attribute__((section("NOINIT"), zero_init)); ///< 实时参数
|
||
__IO calib_param_t calib_param[CALIBPARA_MAX] __attribute__((section("NOINIT"), zero_init)); ///< 校准参数
|
||
pressure_calib_param_t pressure_calib_param[PRESSURE_PARAM_MAX] __attribute__((section("NOINIT"), zero_init)); ///< 压力校准参数
|
||
|
||
pid_t _pid; ///< pid参数
|
||
real_time_data_t rt_data; ///< 实时参数
|
||
driver_icon_enable_u driver_icon_enable; ///< 驱动使能图标
|
||
file_storage_t nvm1_file_storage; ///< 保存报警日志、出厂信息
|
||
|
||
// 模拟量
|
||
__IO uint16_t adc_raw[ADC1_MAX]; // ADC原始值
|
||
__IO const static uint32_t cupid_encrypt = 0xFFFFFFFF;
|
||
|
||
/**
|
||
* @brief 保存板载数据到Flash
|
||
*
|
||
* 该函数首先擦除存储板载数据的Flash区域,然后将板载数据写入到该区域。
|
||
*
|
||
*/
|
||
void board_data_save(void)
|
||
{
|
||
wl_flash_erase(&wl_flash_board_data);
|
||
wl_flash_write(&wl_flash_board_data, (uint8_t*)&board_data, sizeof(board_data_t));
|
||
}
|
||
|
||
#ifndef BOOTLOAD // 非bootload模式
|
||
static void bootload_preload(void)
|
||
{
|
||
set_app_preload_bootload_flag(BOOTLOAD_UNSET_FLAG);
|
||
|
||
if (get_app_preload_bootload_jump_flag() == APP_PRELOAD_BOOTLOAD_JUMP_IMMEDIATELY) // 通过标志位判断是否跳转到BOOTLOAD
|
||
{
|
||
DBG_ASSERT(FALSE __DBG_LINE);
|
||
set_app_preload_bootload_jump_flag(APP_PRELOAD_BOOTLOAD_JUMP_NONE);
|
||
// 反初始化所有硬件
|
||
board_dinit();
|
||
LL_APB2_GRP1_DisableClock(LL_APB2_GRP1_PERIPH_SYSCFG);
|
||
LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_PWR);
|
||
bootload_jump(BOOTLOAD_START_ADDRESS);
|
||
}
|
||
}
|
||
|
||
static void app_preload_logo(BOOL is_first)
|
||
{
|
||
if (is_first)
|
||
{
|
||
menus_init(udevice.display_language);
|
||
}
|
||
else
|
||
{
|
||
menus_set_work_index(get_work_page_index());
|
||
menus_set_language(get_language());
|
||
}
|
||
|
||
if (is_lcd_ext_board() == TRUE)
|
||
{
|
||
get_menus()->accelerate = TRUE;
|
||
#if LCD_DESIGN == FALSE
|
||
menus_loading_draw(is_first);
|
||
#else
|
||
menus_jump(MENUS_MAIN, TRUE);
|
||
#endif
|
||
gui_flush();
|
||
}
|
||
}
|
||
|
||
static void app_preload(void)
|
||
{
|
||
get_cpu_id((uint8_t*)rt_data.cpuid);
|
||
get_cpu_id_32((uint32_t*)rt_data.cpuid_32);
|
||
#if CPU_ENCRYPT_ENABLE == TRUE
|
||
if (cpu_judge_encrypt(board_data.app_preload_cupid_encrypt) == FALSE)
|
||
{
|
||
board_dinit();
|
||
leds_on_all();
|
||
// 加密错误
|
||
while (1)
|
||
{
|
||
__NOP(); // 程序被拷贝才会运行到这里
|
||
}
|
||
}
|
||
#endif
|
||
|
||
bootload_preload();
|
||
|
||
if (is_lcd_ext_board() == TRUE)
|
||
{
|
||
#if LCD_DESIGN == FALSE
|
||
app_preload_logo(FALSE);
|
||
#endif
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief BOOTLOAD传输数据
|
||
* @param {uint8_t} *data
|
||
* @param {uint16_t} len
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
static void bootload_transmit(const uint8_t data_src, const uint8_t* data, const uint16_t len)
|
||
{
|
||
extern uart_t* uarts[APP_UART_MAX];
|
||
uart_send_data(uarts[data_src], (uint8_t*)data, len);
|
||
}
|
||
|
||
/**
|
||
* @brief BOOTLOAD更新完成处理
|
||
* @return {*}
|
||
* @note BOOTLOAD更新完成恢复业务流程,这个时候不要重启
|
||
*/
|
||
static void bootload_end(BOOL bootload_write_flag)
|
||
{
|
||
set_app_preload_bootload_flag(BOOTLOAD_UNSET_FLAG); // 更新完成恢复业务流程
|
||
if (bootload_write_flag == TRUE)
|
||
{
|
||
set_app_preload_bootload_jump_flag(APP_PRELOAD_BOOTLOAD_JUMP_WAIT); // 更新完成等待用户通知跳转到bootload
|
||
}
|
||
else
|
||
{
|
||
set_app_preload_bootload_jump_flag(APP_PRELOAD_BOOTLOAD_JUMP_NONE);
|
||
// 更新失败 通知用户
|
||
}
|
||
}
|
||
#endif
|
||
|
||
// 启动电压电量检查
|
||
static void startup_power_on_diagnosis(void)
|
||
{
|
||
BOOL is_low_battery = FALSE;
|
||
float32 voltage = 0.0f;
|
||
float32 current = 0.0f;
|
||
static float32 voltage_last = 0.0f;
|
||
static float32 current_last = 0.0f;
|
||
BOOL voltage_right = FALSE;
|
||
BOOL current_right = FALSE;
|
||
|
||
for (;;)
|
||
{
|
||
LL_mDelay(200);
|
||
voltage = get_cpu_volt();
|
||
current = get_current_by_resistance();
|
||
if (IS_BETWEEN(voltage, CPU_VREF_RUN_MIN, CPU_VREF_RUN_MAX) && current >= INPUT_CURRENT_RUN)
|
||
{
|
||
break;
|
||
}
|
||
|
||
// 这里需要在LCD上显示电量不足的LOG
|
||
if (is_low_battery == FALSE || (voltage_last != voltage || current_last != current))
|
||
{
|
||
voltage_right = IS_BETWEEN(voltage, CPU_VREF_RUN_MIN, CPU_VREF_RUN_MAX);
|
||
current_right = current >= INPUT_CURRENT_RUN;
|
||
voltage_last = voltage;
|
||
current_last = current;
|
||
|
||
menus_init(CHINESE);
|
||
if (is_lcd_ext_board() == TRUE)
|
||
{
|
||
menus_low_battery_draw(voltage, voltage_right, current, current_right);
|
||
gui_flush();
|
||
}
|
||
|
||
is_low_battery = TRUE;
|
||
}
|
||
}
|
||
|
||
if (reset_flag != DEVICE_IS_ON)
|
||
{
|
||
reset_flag = DEVICE_IS_POWER_DOWN;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 判断当前是否在正确的型号下
|
||
*
|
||
* 检查当前是否处于正确的型号下,用于确保程序运行环境的正确性。
|
||
*
|
||
* @return 如果在正确的型号下,返回 TRUE;否则返回 FALSE。
|
||
*/
|
||
BOOL in_correct_model(void)
|
||
{
|
||
if (udevice.dev_model == POSITIONER_MODEL_GPS2000 || udevice.dev_model == POSITIONER_MODEL_GPS3000)
|
||
{
|
||
return TRUE;
|
||
}
|
||
else
|
||
{
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
// 设置设备重启后仪器模式和控制模式
|
||
static void device_reset_set_mode(void)
|
||
{
|
||
if (udevice.restart_inst_mode != RST_RESUME_INST)
|
||
{
|
||
udevice.inst_mode = udevice.restart_inst_mode;
|
||
}
|
||
|
||
if (udevice.restart_ctrl_mode != RST_RESUME_CTRL)
|
||
{
|
||
udevice.control_mode = udevice.restart_ctrl_mode;
|
||
}
|
||
}
|
||
|
||
// 考虑到主频加速,除非PVD中断响应不一定成功
|
||
/**
|
||
* @brief PVD掉电检测功能回调处理
|
||
*
|
||
* 将系统切换到低功耗模式,关闭特定定时器、关闭特定电源、反初始化外设和驱动等。
|
||
*
|
||
* @return 无返回值
|
||
*/
|
||
// static void pvd_low(void)
|
||
// {
|
||
// // 设置掉电标志位
|
||
// {
|
||
// power_on.flag = PVD_RESET_FLAG;
|
||
// osel_memcpy(power_on.time.data, (uint8_t *)rt_save.real_time.data, ARRAY_LEN(rt_save.real_time.data));
|
||
// wl_flash_write(&wl_flash_power_on, (uint8_t *)&power_on, sizeof(device_reset_t));
|
||
// }
|
||
// }
|
||
|
||
/**
|
||
* @brief app初始化
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void app_init(void)
|
||
{
|
||
osel_memset((uint8_t*)&rt_data, 0, sizeof(real_time_data_t));
|
||
rt_data.storage_used_page_count = BUSINESS_START_PAGE;
|
||
#if DEBUG_ENABLE == TRUE
|
||
|
||
#endif
|
||
rt_data.flag.bits.app_init_over = FALSE;
|
||
#ifndef BOOTLOAD // 非bootload模式
|
||
{
|
||
LCD_POWER_ON(); // 打开LCD,3000的LED电源来自LCD供电
|
||
leds_on(LEDS_RED);
|
||
startup_power_on_diagnosis(); // 启动电源检查,内部电压>=CPU_VREF,且输入电流>=INPUT_CURRENT_RUN
|
||
leds_off_all();
|
||
|
||
wl_flash_init(&wl_flash_board_data);
|
||
system_clock_config_high(); // 系统时钟配置为高速模式
|
||
timer_cycle_update(); // 定时器周期
|
||
params_storage_init(); // 参数存储初始化
|
||
|
||
if (board_data.app_preload_version == CURRENT_VERSION && board_data.app_preload_first_flag == APP_PRELOAD_FIRST)
|
||
{
|
||
device_reset_set_mode(); // 设置设备重启后仪器模式和控制模式
|
||
if (reset_flag == DEVICE_IS_ON)
|
||
{
|
||
if (in_correct_model())
|
||
{
|
||
mode_init(); // 工作模式初始化
|
||
mode_master_detection(); // 工作模式控制管理
|
||
ENABLE_TIM(MODE_TIM); // MODE_TIM用于算法控制
|
||
ENABLE_TIM(MODE_GATHE_TIM); // Enable MODE_GATHE_TIM
|
||
}
|
||
}
|
||
}
|
||
|
||
app_preload_logo(TRUE);
|
||
leds_on(LEDS_GREEN);
|
||
params_init(); // 参数初始化
|
||
device_reset_set_mode(); // 设置设备重启后仪器模式和控制模式
|
||
timer_cycle_update(); // 定时器周期
|
||
|
||
key_init(); // 按键初始化
|
||
diagnosis_init(); // 诊断模块初始化
|
||
|
||
{
|
||
file_storage_init(&nvm1_file_storage, _M95M02_, 2, eeprom_m95_1_read, eeprom_m95_1_write); // 文件存储初始化
|
||
|
||
uint16_t diagnosis_log_max_node = 30000;
|
||
uint32_t diagnosis_log_start_addr = 0;
|
||
file_storage_block_params_t diagnosis_log =
|
||
{
|
||
.is_node = TRUE,
|
||
.is_cycle_write = TRUE, // 诊断数据需要循环写入
|
||
.node_size = sizeof(diagnosis_log_data_node_t),
|
||
.start_node = rt_save.diagnosis_log_node_start_offset_index, // 诊断日志起始偏移索引
|
||
.used_node = rt_save.diagnosis_log_node_write_count, // 已写入节点数
|
||
.node_max = diagnosis_log_max_node,
|
||
|
||
.start_addr = diagnosis_log_start_addr,
|
||
.end_addr = diagnosis_log_start_addr + (diagnosis_log_max_node + 1) * sizeof(diagnosis_log_data_node_t),
|
||
.used_size = rt_save.diagnosis_log_node_write_count * sizeof(diagnosis_log_data_node_t),
|
||
};
|
||
file_storage_block_create(&nvm1_file_storage, FILE_BLOCK_DIAGNOSIS_LOG, &diagnosis_log);
|
||
|
||
/**
|
||
* 设备溯源信息
|
||
* 1. 设计存储10条记录,每条记录占用64字节
|
||
* 2. 读取的时候按照诊断数据的格式读取,每次读取一条记录,每次读取64字节
|
||
* 3. 写入的时候按照诊断数据的格式写入,每次写入一条记录,每次写入64字节
|
||
*/
|
||
uint16_t instrument_information_max_node = 10;
|
||
uint32_t instrument_information_start_addr = diagnosis_log.end_addr;
|
||
file_storage_block_params_t instrument_information =
|
||
{
|
||
.is_node = TRUE,
|
||
.is_cycle_write = FALSE, // 设备溯源信息不需要循环写入
|
||
.node_size = PACKED64_LEN,
|
||
.start_node = 0,
|
||
.used_node = 0,
|
||
.node_max = instrument_information_max_node,
|
||
|
||
.start_addr = instrument_information_start_addr,
|
||
.end_addr = instrument_information_start_addr + instrument_information_max_node * PACKED64_LEN,
|
||
.used_size = 0,
|
||
};
|
||
file_storage_block_create(&nvm1_file_storage, FILE_BLOCK_EQUIPMENT_TRACEABILITY_INFORMATION, &instrument_information);
|
||
}
|
||
|
||
if (reset_flag == DEVICE_IS_POWER_DOWN && in_correct_model())
|
||
{
|
||
mode_init(); // 工作模式初始化
|
||
ENABLE_TIM(MODE_TIM); // MODE_TIM用于算法控制
|
||
}
|
||
ENABLE_TIM(MODE_GATHE_TIM); // Enable MODE_GATHE_TIM
|
||
app_preload(); // 预加载
|
||
app_hart_init(); // HART初始化,mode中的模拟诊断需要用到HART变量
|
||
flow_init(); // 流程初始化
|
||
mode_diagnosis_init(); // 控制模块诊断初始化
|
||
power_on_diagnosis(); // 自检
|
||
bootload_init(bootload_transmit, bootload_end); // 在用户代码中接受更新文件需要初始化bootload
|
||
}
|
||
|
||
#if (HART_SOFTWARE_TEST_ENABLE == TRUE || HART_HARDWARE_TEST_ENABLE == TRUE)
|
||
ENABLE_TIM(HART_TIM);
|
||
// HART测试不允许有中断,否则串口异常会丢失导致测试失败
|
||
DISABLE_TIM(MODE_TIM);
|
||
DISABLE_TIM(MODE_GATHE_TIM);
|
||
#endif
|
||
rt_data.flag.bits.app_init_over = TRUE;
|
||
reset_flag = DEVICE_IS_ON;
|
||
ENABLE_TIM(TASK_TIM); // Enable TASK_TIM
|
||
#else // bootload模式
|
||
// 在BOOTLOAD模式下需要关闭所有外设,且不需要接受用户代码,所以不需要初始化
|
||
board_dinit();
|
||
leds_off_all(); // 关闭所有LED
|
||
ENABLE_TIM(TASK_TIM); // Enable TASK_TIM
|
||
#endif
|
||
|
||
#if DEBUG_ENABLE == TRUE
|
||
|
||
#endif
|
||
}
|
||
|
||
/**
|
||
* @brief app反初始化
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void app_dinit(void)
|
||
{
|
||
hart_uart_dinit();
|
||
hart_ble_dinit();
|
||
}
|
||
|
||
/**
|
||
* @brief 业务流程启动
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void app_start(void)
|
||
{
|
||
flow_start();
|
||
}
|