#include "global.h" #include "hw_flash_data.h" #include "poweroff_save_app.h" #include "variable.h" #include "board.h" #include #include "MathHelper.h" #include "log_app.h" //下次保存地址 uint32_t next_save_posi = POWEROFF_SAVE_ADDRESS; //上电标志 static unsigned char power_on_flag = 0; //定时器 static sw_timer_t timer; static int power_off_sample = 0; //记录对象实体 //static tiny_log_t tinylog; //unsigned char log_data[256]; /** * 掉电工作初始化 * 每次上电时先调用这个函数检查下第一块是否有空的位置让参数去保存,没有就先擦除第二块,然后将第一块的有效参数保存进去 * 然后擦除第一块 * * @author lxz (2019/5/31/鍛ㄤ簲) * * @param void */ void poweroff_app_init(void) { int block_size = POWEROFF_SAVE_BLOCK_SIZE; int block_number = POWEROFF_SAVE_SECTOR_SIZE / block_size; int date_NoEmpty = 0; int NoEmpty_index = 0; int i = 0; int retry=0; while (hw_dma_uart_write_finish(2) == 0); //等待一断时间,检测下看电源是否稳定再操作 sw_timer_start(&timer, POWER_OFF_FUNCTION_DELAY, 0); while (sw_timer_expire(&timer) == 0); power_on_flag = hw_power_is_on(); i = block_number; do { i--; //查找下非空的flash地址 if (hw_flash_data_check_empty(POWEROFF_SAVE_ADDRESS + i * block_size, block_size) != 0) { date_NoEmpty=1; NoEmpty_index=i;//数据非空的地址编号 break; } } while (i > 0); //说明已经写满了,这时候,需要先清除第二块flash,并将第一块的数据存到第二块去 if (i >= block_number - 1) { //检测下是否有24V供电,没供电不要进行这个操作 if (hw_power_is_on()) { //读取第一块中的有效数据 do { //必须保证CRC校验成功 hw_flash_data_read(POWEROFF_SAVE_ADDRESS + (i)*block_size, user_datas, block_size); if (mh_crc16_calc((unsigned char *)&user_datas[0], block_size) == 0) { //读取到有效数据,存到第二块去 hw_flash_data_write(POWEROFF_BACKUP_ADDRESS, user_datas, block_size); break; } i--; }while (i >= 0); if(i<0) //没有有效数据 { memset(user_datas, 0, block_size); } } //如果擦除完了后读取到是掉电的标志位,就不能进行存储工作,因为可能24V没电了 //这时候还原工作交给下次上电比较好 if (hw_power_is_on()) { //擦除旧块 hw_flash_data_erase(POWEROFF_SAVE_ADDRESS); } next_save_posi = POWEROFF_SAVE_ADDRESS; } else { //读取存储的数据 //读取有效数据 if (date_NoEmpty==0)//第一块数据都为空 { //检测是否第二块是空的, 不是就读出来 if (hw_flash_data_check_empty(POWEROFF_BACKUP_ADDRESS, block_size) != 0) { for(retry=0;retry<3;retry++) { hw_flash_data_read(POWEROFF_BACKUP_ADDRESS, user_datas, block_size); //校验数据是否有效 if (mh_crc16_calc((unsigned char *)&user_datas[0], block_size) == 0) { break; } } if(retry>=3)//没有有效数据 { memset(user_datas, 0, block_size); next_save_posi = POWEROFF_SAVE_ADDRESS; } } else { //如果没有数据就清零 memset(user_datas, 0, block_size); next_save_posi = POWEROFF_SAVE_ADDRESS; } } else { //读取第一块中的有效数据 do { //必须保证CRC校验成功 hw_flash_data_read(POWEROFF_SAVE_ADDRESS + (i)*block_size, user_datas, block_size); if (mh_crc16_calc((unsigned char *)&user_datas[0], block_size) == 0) { break; } i--; }while (i >= 0); if(i<0) //没有有效数据 { //检测是否第二块是空的, 不是就读出来 if (hw_flash_data_check_empty(POWEROFF_BACKUP_ADDRESS, block_size) != 0) { for(retry=0;retry<3;retry++) { hw_flash_data_read(POWEROFF_BACKUP_ADDRESS, user_datas, block_size); //校验数据是否有效 if (mh_crc16_calc((unsigned char *)&user_datas[0], block_size) == 0) { break; } } if(retry>=3)//没有有效数据 { memset(user_datas, 0, block_size); } } else { memset(user_datas, 0, block_size); } } //下次存储在数据为空的地址,避免掉电保存时还要进行擦除操作 next_save_posi = POWEROFF_SAVE_ADDRESS + (NoEmpty_index+1) * block_size; } } //将该位置定义成一个记录保存块,它的有效内容大小为128 - 18 //tiny_log_init(&tinylog, &user_datas[512],128); } /** * 保存参数 * * @author lxz (2019/6/12/鍛ㄤ笁) * * @param void */ void app_save_parameter(void) { hw_board_enter_powerless(); hw_run_status_off(); //保存一次记录 log_app_save(); //计算校验码 user_datas[POWEROFF_SAVE_BLOCK_SIZE / 2 - 1] = mh_crc16_calc((unsigned char *)&user_datas[0], POWEROFF_SAVE_BLOCK_SIZE - 2); //写拉flash hw_flash_data_write(next_save_posi, user_datas, POWEROFF_SAVE_BLOCK_SIZE); hw_run_status_on(); } long testDisplay; /** * 掉电的处理函数 * * @author lxz (2019/6/12/鍛ㄤ笁) * * @param void */ void poweroff_app_run(void) { //当第一次上电有上电标志的时间,才检测掉电保存 if (power_on_flag) { //周期检测,管脚滤波 if (sw_timer_expire(&timer)) { if (hw_power_is_off()) { power_off_sample++; } else if (power_off_sample > 0) { power_off_sample--; } sw_timer_start(&timer, 0, POWER_OFF_SAMPLE_TIME); } //确定检测到断电 if (power_off_sample >= POWER_OFF_SAMPLE_COUNT) { //这里需要调用一次保存 testDisplay++; //保存参数 app_save_parameter(); //hw_run_status_set(3); while (1) { hw_run_status_show(); } } } else { //当在掉电状态的时候,程序在运行则一直在执行上电的检测,检测时间为连续的200ms if (sw_timer_expire(&timer)) { if (hw_power_is_on()) { power_off_sample++; } else if (power_off_sample > 0) { power_off_sample--; } sw_timer_start(&timer, 0, POWER_OFF_SAMPLE_TIME); } if (power_off_sample >= POWER_ON_SAMPLE_COUNT) { power_on_flag = hw_power_is_on(); } } }