/** * @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(); }