shuichan_old/V1.5/STM32F103_App1/HardWare/SYSINIT/app_loop.c

400 lines
14 KiB
C
Raw Normal View History

/* app_loop.c - FreeRTOS <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD>װ
*
* <EFBFBD><EFBFBD><EFBFBD>񻮷֣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* net_task(<EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD>3, ջ3KB) - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD> NET_process<EFBFBD><EFBFBD>4G/WiFi <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>շ<EFBFBD><EFBFBD><EFBFBD>OTA <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* app_task(<EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD>2, ջ2KB) - ҵ<EFBFBD>񣺼̵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͷι<EFBFBD>ӡ<EFBFBD>״̬<EFBFBD>ϱ<EFBFBD><EFBFBD><EFBFBD>OTA ȷ<EFBFBD><EFBFBD>
* sys_task(<EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD>1, ջ1KB) - ϵͳ<EFBFBD><EFBFBD>LED<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӡ
* idle <EFBFBD><EFBFBD><EFBFBD><EFBFBD> - ι IWDG<EFBFBD><EFBFBD>ֻҪ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ź<EFBFBD><EFBFBD>Ͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD>ռ CPU ʱ idle <EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD> <EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>
*
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD>
* g_net_at_mutex - NET_publish_* <EFBFBD> AT <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>ֱ<EFBFBD>Ӷ<EFBFBD><EFBFBD><EFBFBD>
* s_storage_mutex - EEPROM(<EFBFBD><EFBFBD><EFBFBD><EFBFBD>I2C) / W25Q64(<EFBFBD><EFBFBD><EFBFBD><EFBFBD>SPI) <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʻ<EFBFBD><EFBFBD>storage_lock<EFBFBD><EFBFBD>
* log <EFBFBD><EFBFBD><EFBFBD><EFBFBD> - log.c <EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD>֯
*/
#include "app_loop.h"
#include "app_common.h"
#include "user_cmd.h"
#include "relay.h"
#include "network.h"
#include "led.h"
#include "adc.h"
#include "feed_scale.h"
#include "iic.h"
#include "24c02.h"
#include "uart.h"
#include "log_cn.h"
#include "ble_at.h"
#include "hlw8032.h"
#include "oled.h"
#include "reset_log.h"
#include "../W25Q64/w25q64.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/*==== <20><EFBFBD><E6B4A2><EFBFBD>߻<EFBFBD><DFBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>EEPROM/W25Q64 <20><><EFBFBD><EFBFBD>һ<EFBFBD>ѵݹ<D1B5><DDB9><EFBFBD><EFBFBD><EFBFBD>====*/
static SemaphoreHandle_t s_storage_mutex = NULL;
void storage_lock_init(void)
{
s_storage_mutex = xSemaphoreCreateRecursiveMutex();
}
void storage_lock(void)
{
if (s_storage_mutex && xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) {
xSemaphoreTakeRecursive(s_storage_mutex, portMAX_DELAY);
}
}
void storage_unlock(void)
{
if (s_storage_mutex && xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) {
xSemaphoreGiveRecursive(s_storage_mutex);
}
}
/*==== ҵ<><D2B5>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>£<EFBFBD>====*/
void app_init(void)
{
log_info("");
log_info("* * * * * * * * * * * * * * * * * *");
log_info("* <20>汾: %s (RTOS) *", FIRMWARE_VERSION_STR);
log_info("* * * * * * * By Helei * * * *");
/* EEPROM <20>е<EFBFBD> MQTT/<2F><EFBFBD><E6B1BE><EFBFBD><EFBFBD> */
iicInit();
eepromReadInfo();
log_load_level(); /* <20>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־<EFBFBD>ȼ<EFBFBD> */
log_info("> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: %s:%d", MqttInfoStr.ServerIP, MqttInfoStr.ServerPort);
log_info("> <20>ͻ<EFBFBD><CDBB><EFBFBD>ID: %s", MqttInfoStr.ClientID);
log_info("> <20>û<EFBFBD><C3BB><EFBFBD>: %s", MqttInfoStr.Username);
log_info("> <20><EFBFBD><E6B1BE><EFBFBD><EFBFBD>: %u", MqttInfoStr.Ver);
/* W25Q64 <20>ⲿ Flash<73><68><EFBFBD><EFBFBD><EFBFBD><EFBFBD> OTA <20>̼<EFBFBD><CCBC>ݴ<EFBFBD> */
W25Q64_Init();
/* <20><><EFBFBD>ɱ<EFBFBD><C9B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC>ԭ<EFBFBD><D4AD>+<2B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӡ<EFBFBD><D3A1><EFBFBD><EFBFBD> 10 <20><> */
reset_log_boot();
/* <20>̵<EFBFBD><CCB5><EFBFBD> GPIO<49><4F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> + <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>룩 */
relayInit();
/* RS485 ι<>ϳӿ<CFB3><D3BF><EFBFBD>ģ<EFBFBD><C4A3> */
feedScaleInit();
/* LED<45><44>LED2 <20><><EFBFBD><EFBFBD>ͬʱ<CDAC><CAB1><EFBFBD><EFBFBD><EFBFBD>ⲿ<EFBFBD><E2B2BF><EFBFBD>Ź<EFBFBD> TPL5010 ι<><CEB9><EFBFBD><EFBFBD> */
ledInit();
/* ADC <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
adcInit();
update_batter();
/* HLW8032 <20><><EFBFBD>ܼ<EFBFBD><DCBC><EFBFBD><EFBFBD><EFBFBD>UART5 PD2<44><32>ֻ<EFBFBD>ۼƵ<DBBC><C6B5><EFBFBD><EFBFBD><EFBFBD> */
hlw8032_init();
/* OLED <20><>Ļ<EFBFBD><C4BB>128x64 + GB2312 <20>ֿ<EFBFBD> IC<49><43> */
oled_init();
oled_locate(1, 0); oled_print("<EFBFBD>̵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ն<EFBFBD>");
oled_locate(2, 2); oled_print("V" FIRMWARE_VERSION_STR " RTOS");
log_info("> OLED: <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
/* <20><><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD> EEPROM <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϴγɹ<CEB3><C9B9><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD>ȣ<EFBFBD>4G <20><> WiFi<46><69> */
NET_init();
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><C2B7><EFBFBD>ڽ<EFBFBD><DABD><EFBFBD> */
USART2_StartRx(); /* RS485 ι<>ϳ<EFBFBD> */
USART3_StartRx(); /* 4G MQTT <20><>Ϣ<EFBFBD><CFA2>DMA+IDLE */
USART1_StartRx(); /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
/* <20>ϵ<EFBFBD><CFB5><EFBFBD> HLK-B40 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ MQTT ClientID<49><44><EFBFBD><EFBFBD>̨<EFBFBD><EFBFBD><E8B1B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
ble_at_init();
ble_setup_name();
}
/*==== net_task<73><6B><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD>4G/WiFi <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>շ<EFBFBD><D5B7><EFBFBD>OTA<54><41>====*/
static void net_task(void *arg)
{
(void)arg;
for (;;) {
NET_process();
vTaskDelay(5);
}
}
/*==== app_task<73><6B>ҵ<EFBFBD><D2B5><EFBFBD>߼<EFBFBD><DFBC><EFBFBD><EFBFBD>̵<EFBFBD><CCB5><EFBFBD>/<2F><>/<2F>ϱ<EFBFBD>/OTA ȷ<>ϣ<EFBFBD>====*/
static void app_task(void *arg)
{
(void)arg;
/* <20><>ѭ<EFBFBD><D1AD>״̬<D7B4><CCAC><EFBFBD><EFBFBD> */
static uint8_t ota_confirmed = 0;
static uint8_t ota_simulate_fail = 0; /* =1<><31><EFBFBD>ԣ<EFBFBD>ģ<EFBFBD><C4A3> OTA ȷ<><C8B7>ʧ<EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD>֤<EFBFBD><D6A4><EFBFBD>ˣ<EFBFBD> */
static uint8_t ota_fail_logged = 0;
static uint32_t ota_confirm_tick = 0;
static uint32_t mqtt_ready_tick = 0;
static uint8_t mqtt_ready_recorded = 0;
static uint8_t mqtt_first_status_reported = 0;
for (;;) {
/* <20><>¼ MQTT <20>״ξ<D7B4><CEBE><EFBFBD>ʱ<EFBFBD><CAB1> */
if (!mqtt_ready_recorded && g_net_mqtt_ready) {
mqtt_ready_recorded = 1;
mqtt_ready_tick = HAL_GetTick();
}
/* MQTT <20>״ξ<D7B4><CEBE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȱ<EFBFBD> EEPROM <20>ָ<EFBFBD><D6B8>̵<EFBFBD><CCB5><EFBFBD><EFBFBD>ϴ<EFBFBD>״̬<D7B4><CCAC><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD><E4A3A9>
* <EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƽ̨ˢ<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>ʵ״̬ */
if (g_net_mqtt_ready && !mqtt_first_status_reported) {
mqtt_first_status_reported = 1;
relayRestoreState();
relayStatueUpdata();
log_info("> Main: MQTT Ready <20><><EFBFBD>״<EFBFBD>״̬<D7B4>ϱ<EFBFBD>");
ota_confirm_tick = HAL_GetTick();
}
/* <20>״η<D7B4><CEB7><EFBFBD><EFBFBD>ɹ<EFBFBD><C9B9><EFBFBD><EFBFBD>ӳ<EFBFBD> 3s <20><> OTA ȷ<><C8B7> */
if (!ota_confirmed && g_net_mqtt_ready && g_net_first_publish_ok &&
(HAL_GetTick() - ota_confirm_tick) > 3000) {
if (ota_simulate_fail) {
if (!ota_fail_logged) {
ota_fail_logged = 1;
log_info("> OTA ȷ<><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3>ʧ<EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD>ڻ<EFBFBD><DABB>˲<EFBFBD><CBB2>ԣ<EFBFBD>");
}
/* <20><><EFBFBD><EFBFBD>λ ota_confirmed<65><64><EFBFBD><EFBFBD> 1 <20><><EFBFBD>ӽ<EFBFBD><D3BD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ */
} else {
ota_confirmed = 1;
NET_ota_confirm();
log_info("> OTA <20><>ȷ<EFBFBD>ϣ<EFBFBD>MQTT Ready + <20>״η<D7B4><CEB7><EFBFBD><EFBFBD>ɹ<EFBFBD> + <20>ӳ<EFBFBD>3s<33><73>");
}
}
/* MQTT <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD>״<EFBFBD> MPUB<55><42><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ */
if (!ota_confirmed && mqtt_ready_recorded &&
(HAL_GetTick() - mqtt_ready_tick) > OTA_HEALTH_TIMEOUT_MS) {
log_warn("> OTA <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ: MQTT Ready <20><> 1 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> MPUB<55><42><EFBFBD><EFBFBD>λ");
reset_log_mark(RSN_OTA_HEALTH);
W25Q64_OTA_IncTrial(); /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ BL <20><><EFBFBD>ƴΣ<C6B4><CEA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>Դ<EFBFBD> */
HAL_Delay(100);
NVIC_SystemReset();
}
/* <20>̵<EFBFBD><CCB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ״̬<D7B4><CCAC> */
relayCmdProcess();
/* <20>ӳ<EFBFBD>״̬<D7B4>ϱ<EFBFBD> */
if (relay_report_pending && (HAL_GetTick() - relay_report_tick) > 100) {
relay_report_pending = 0;
relayStatueUpdata();
}
/* ι<>ϳ<EFBFBD><CFB3><EFBFBD>ѯ<EFBFBD><D1AF>Ͷι<CDB6><CEB9><EFBFBD><EFBFBD> */
feedScaleProcess();
vTaskDelay(10);
}
}
/*==== OLED <20><><EFBFBD><EFBFBD>ˢ<EFBFBD>£<EFBFBD>1s һ<>Σ<EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD>/<EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬/<EFBFBD><EFBFBD><EFBFBD><EFBFBD>+<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>
* δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> g_net_ui_phase <EFBFBD><EFBFBD>ʾ 4G/WiFi <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD>WiFi <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ 10s <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 0/2/4px <EFBFBD>ֻ<EFBFBD> ====*/
static void oled_home_refresh(uint32_t up_ms);
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׶Σ<D7B6>app_init <20><><EFBFBD><EFBFBD> 4G <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* sys_task <EFBFBD><EFBFBD>û<EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD> bg_delay ÿ 500ms <EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ˢ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ */
void app_oled_presched_tick(void)
{
static uint32_t last = 0;
if (HAL_GetTick() - last < 500) return;
last = HAL_GetTick();
oled_home_refresh(0);
}
static void oled_home_refresh(uint32_t up_ms)
{
char buf[24];
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ 10s <20><>һ<EFBFBD><D2BB>ˮƽƫ<C6BD>ƣ<EFBFBD>0/2/4px<70><78> */
uint8_t xoff = (uint8_t)((HAL_GetTick() / 10000u) % 3u) * 2u;
if (g_net_mqtt_ready) {
/*---- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ----*/
/* R0: <20><><EFBFBD><EFBFBD> + <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><E4A3A8>:ʱ:<3A>֣<EFBFBD> */
uint32_t mins = up_ms / 60000u;
const char *nt = (NET_GetActiveBackend() == NET_BACKEND_WIFI) ? "WiFi" : "4G";
snprintf(buf, sizeof(buf), "%s %02u:%02u:%02u", nt,
(unsigned)(mins / 1440u),
(unsigned)((mins % 1440u) / 60u),
(unsigned)(mins % 60u));
oled_locate(0, 0); oled_xoff(xoff); oled_print_line(buf);
/* R1/R2: <20><><EFBFBD>ܲ<EFBFBD><DCB2><EFBFBD> */
if (hlw8032_online()) {
snprintf(buf, sizeof(buf), "%.1fV %.2fA",
(double)hlw8032_get_voltage_v(), (double)hlw8032_get_current_a());
oled_locate(1, 0); oled_xoff(xoff); oled_print_line(buf);
snprintf(buf, sizeof(buf), "%.1fW %.2fkWh",
(double)hlw8032_get_power_w(), (double)hlw8032_get_energy_kwh());
oled_locate(2, 0); oled_xoff(xoff); oled_print_line(buf);
} else {
oled_locate(1, 0); oled_xoff(xoff); oled_print_line("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>оƬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
oled_locate(2, 0); oled_xoff(xoff); oled_print_line("");
}
/* R3: <20><><EFBFBD><EFBFBD>״̬ */
snprintf(buf, sizeof(buf), "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>:%s%s%s%s",
MqttInfoStr.Relay_State[1] ? "<EFBFBD><EFBFBD>" : "<EFBFBD><EFBFBD>",
MqttInfoStr.Relay_State[2] ? "<EFBFBD><EFBFBD>" : "<EFBFBD><EFBFBD>",
MqttInfoStr.Relay_State[3] ? "<EFBFBD><EFBFBD>" : "<EFBFBD><EFBFBD>",
MqttInfoStr.Relay_State[4] ? "<EFBFBD><EFBFBD>" : "<EFBFBD><EFBFBD>");
oled_locate(3, 0); oled_xoff(xoff); oled_print_line(buf);
} else {
/*---- δ<><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6A3BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ----*/
net_ui_phase_t ph = g_net_ui_phase;
oled_locate(0, 0); oled_xoff(xoff); oled_print_line("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
if (ph == NET_UI_WIFI_FIXED || ph == NET_UI_WIFI_SMART ||
NET_GetActiveBackend() == NET_BACKEND_WIFI) {
if (ph == NET_UI_WIFI_FIXED) {
oled_locate(1, 0); oled_xoff(xoff); oled_print_line("WiFi<EFBFBD>̶<EFBFBD>ģʽ");
oled_locate(2, 0); oled_xoff(xoff); oled_print_line("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȵ<EFBFBD>");
} else if (ph == NET_UI_WIFI_SMART) {
oled_locate(1, 0); oled_xoff(xoff); oled_print_line("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
oled_locate(2, 0); oled_xoff(xoff); oled_print_line("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>APP<EFBFBD>");
} else {
oled_locate(1, 0); oled_xoff(xoff); oled_print_line("WiFiģʽ");
oled_locate(2, 0); oled_xoff(xoff); oled_print_line("<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>...");
}
snprintf(buf, sizeof(buf), "ʣ<EFBFBD><EFBFBD> %ds", g_net_ui_countdown);
oled_locate(3, 0); oled_xoff(xoff); oled_print_line(g_net_ui_countdown > 0 ? buf : "");
} else {
/* 4G <20><><EFBFBD>ȣ<EFBFBD><C8A3><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɵĽ׶<C4BD> */
const char *step = "<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>";
switch (ph) {
case NET_UI_4G_RESET: step = "ģ<EFBFBD>鸴λ<EFBFBD>ɹ<EFBFBD>"; break;
case NET_UI_4G_AT: step = "ATָ<EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>"; break;
case NET_UI_4G_SIM: step = "SIM<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>"; break;
case NET_UI_4G_ATTACH: step = "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>"; break;
case NET_UI_4G_MQTT: step = "<EFBFBD><EFBFBD><EFBFBD>ӷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"; break;
case NET_UI_4G_NOSIM: step = "<EFBFBD><EFBFBD>SIM<EFBFBD><EFBFBD>!"; break;
default: break;
}
oled_locate(1, 0); oled_xoff(xoff); oled_print_line("<EFBFBD><EFBFBD><EFBFBD>ڵȴ<EFBFBD>4G<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
oled_locate(2, 0); oled_xoff(xoff); oled_print_line(step);
oled_locate(3, 0); oled_xoff(xoff); oled_print_line("");
}
}
}
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־/<2F>ϱ<EFBFBD><CFB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD>ʾ͸<CABE><CDB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EAA3A8>λ ms<6D><73> */
#define ENERGY_REPORT_INTERVAL_MS 10000u
/*==== sys_task<73><6B>ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>LED/<2F><><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>====*/
static void sys_task(void *arg)
{
(void)arg;
uint32_t batt_tick = HAL_GetTick();
uint32_t up_last = HAL_GetTick();
uint32_t up_print = HAL_GetTick();
uint32_t en_print = HAL_GetTick();
uint64_t up_ms = 0;
for (;;) {
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
process_usart1_command();
/* <20><><EFBFBD><EFBFBD>ָʾ<D6B8><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˸<EFBFBD><CBB8><EFBFBD><EFBFBD><EFBFBD>ϳ<EFBFBD><CFB3><EFBFBD><EFBFBD><EFBFBD>led.c activeEvents <20>ݴ˿<DDB4><CBBF><EFBFBD> PA1<41><31> */
g_net_led_connected = g_net_mqtt_ready ? 1 : 0;
/* LED <20><><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD>ָʾ */
activeEvents();
/* <20><><EFBFBD><EFBFBD> 1s <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
if (HAL_GetTick() - batt_tick >= 1000) {
batt_tick = HAL_GetTick();
update_batter();
hlw8032_tick(); /* <20>ܹ<EFBFBD>Լ 0.1kWh дһ<D0B4><D2BB> EEPROM */
oled_home_refresh(up_ms); /* OLED <20><><EFBFBD><EFBFBD> 1s ˢ<><CBA2> */
reset_log_tick((uint32_t)(up_ms / 1000)); /* <20><><EFBFBD><EFBFBD> RAM <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȸ<EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD> */
}
/* <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ 60s <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>Σ<EFBFBD><CEA3><EFBFBD>/ʱ/<2F>֣<EFBFBD><D6A3><EFBFBD>
* δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>־<EFBFBD><EFBFBD>
* 64 λ<EFBFBD>ۼƣ<EFBFBD>HAL_GetTick Լ 49 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӱ<EFBFBD><EFBFBD> */
{
uint32_t now = HAL_GetTick();
up_ms += (uint32_t)(now - up_last); /* 32λ<32><CEBB>ֵ<EFBFBD><D6B5>Ȼ<EFBFBD><C8BB><EFBFBD>̻<EFBFBD><CCBB><EFBFBD> */
up_last = now;
if (now - up_print >= 60000) {
up_print = now;
if (g_net_mqtt_ready) {
uint32_t mins = (uint32_t)(up_ms / 60000);
log_info(FMT_UPTIME,
(unsigned)(mins / 1440),
(unsigned)((mins % 1440) / 60),
(unsigned)(mins % 60));
}
}
}
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־+<2B>ϱ<EFBFBD><CFB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҽ<EFBFBD><D2BC><EFBFBD>оƬ<D0BE><C6AC><EFBFBD><EFBFBD>ʱÿ ENERGY_REPORT_INTERVAL_MS һ<><D2BB> */
if (g_net_mqtt_ready && hlw8032_online() &&
(HAL_GetTick() - en_print) >= ENERGY_REPORT_INTERVAL_MS) {
en_print = HAL_GetTick();
float kwh = hlw8032_get_energy_kwh();
NET_publish_energy(kwh);
log_info(FMT_ENERGY, (double)kwh,
(double)hlw8032_get_voltage_v(),
(double)hlw8032_get_current_a(),
(double)hlw8032_get_power_w());
}
vTaskDelay(20);
}
}
/*==== FreeRTOS <20><><EFBFBD><EFBFBD> ====*/
/* idle <20><><EFBFBD>ӣ<EFBFBD>ι<EFBFBD><CEB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ź<EFBFBD><C5B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD>ռ CPU ʱ idle <20><><EFBFBD><EFBFBD> <20><> IWDG <20><>λ */
void vApplicationIdleHook(void)
{
IWDG_Feed();
}
void vApplicationMallocFailedHook(void)
{
log_error("> RTOS: malloc ʧ<>ܣ<EFBFBD><DCA3>Ѻľ<D1BA><C4BE><EFBFBD>");
taskDISABLE_INTERRUPTS();
for (;;) { }
}
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)
{
(void)xTask;
log_error("> RTOS: <20><><EFBFBD><EFBFBD> %s ջ<><D5BB><EFBFBD><EFBFBD>", pcTaskName);
taskDISABLE_INTERRUPTS();
for (;;) { }
}
/*==== <20><><EFBFBD>񴴽<EFBFBD><F1B4B4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>main <20><><EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD>ٷ<EFBFBD><D9B7>أ<EFBFBD>====*/
void app_rtos_start(void)
{
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>񴴽<EFBFBD> */
log_lock_init();
storage_lock_init();
NET_LockInit();
xTaskCreate(net_task, "net", 768, NULL, 3, NULL); /* ջ 3KB<4B><42>AT/OTA <20>д<EFBFBD><D0B4><EFBFBD> sprintf <20><><EFBFBD><EFBFBD> */
xTaskCreate(app_task, "app", 512, NULL, 2, NULL); /* ջ 2KB */
xTaskCreate(sys_task, "sys", 512, NULL, 1, NULL); /* ջ 2KB<4B><42><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־һ<D6BE><D2BB> 4 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD>ܳ<EFBFBD>ջ */
vTaskStartScheduler();
/* <20><><EFBFBD><EFBFBD><EFBFBD>ߵ<EFBFBD><DFB5><EFBFBD><EFBFBD><EFBFBD>Ѳ<EFBFBD><D1B2><EFBFBD><E3B4B4>ʧ<EFBFBD>ܲŻᣩ */
log_error("> RTOS: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>");
for (;;) { }
}