/********************************** (C) COPYRIGHT ******************************* * File Name : main.c * Author : WCH * Version : V1.1 * Date : 2020/08/06 * Description : Peripheral slave application main function and task system initialization ********************************************************************************* * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. * Attention: This software (modified or not) and binary are used for * microcontroller manufactured by Nanjing Qinheng Microelectronics. *******************************************************************************/ /******************************************************************************/ /* Header file contains */ #include "CONFIG.h" #include "HAL.h" #include "gattprofile.h" #include "peripheral.h" #include "cmcng.h" #include #include "dbn_ble_srv.h" #include "eth_driver.h" #include "net_srv.h" #include "storage.h" #include "offlog.h" #include "snapshot.h" #include "tcp_json_srv.h" #include "loop_uart_proto.h" #include "iot_mqtt_srv.h" #include "fault_diag.h" /********************************************************************* * GLOBAL TYPEDEFS */ __attribute__((aligned(4))) uint32_t MEM_BUF[BLE_MEMHEAP_SIZE / 4]; #define KEY_GPIO (RCC_APB2Periph_GPIOA) #define KEY_BV BV(0) #define KEY_IN (GPIO_ReadInputDataBit(KEY_GPIO, KEY_BV)==0) #define HAL_PUSH_BUTTON() (KEY1_IN) //Add custom button #if(defined(BLE_MAC)) && (BLE_MAC == TRUE) const uint8_t MacAddr[6] = {0x84, 0xC2, 0xE4, 0x03, 0x02, 0x02}; // #else // uint8_t MACAddr[6] = {0x84, 0xC2, 0xE4, 0x03, 0x02, 0x02}; #endif uint8_t gMacAddr[6] = { 0x38, 0x3B, 0x26, 0x11, 0xA4 ,0x35 }; /* Used for app judgment file effectiveness */ const uint32_t Address = 0xFFFFFFFF; __attribute__((aligned(4))) uint32_t Image_Flag __attribute__((section(".ImageFlag"))) = (uint32_t)&Address; uint8_t g_dev_number[6] = ""; // �豸��� ��Ʒ��� uint8_t g_dev_password[6] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36}; uint8_t g_ble_safe_flag = 0; uint32_t g_ble_safe_counter_ori = 0; uint32_t g_ble_safe_counter_dst = 0; char g_flag_debug = 1; uint8_t g_dg_device_type = DDType_DLD950V4; // ???����????????????? uint8_t g_dg_sub_dev_type = DDType_DLD950V4; Sub_Code_Enable g_sub_code_enable = {0,}; uint32_t g_activ_counter = 0; uint32_t g_counter_bt_timeout = 0; uint8_t g_flag_bt_state = 0; uint8_t g_flag_bt_disable = 0; uint8_t g_max_counter_bt_min = 0; uint32_t g_max_counter_bt_timeout = 0; //BT_DISABLE_IDLE_TIMEOUT * 60 * 1000; // ms unit __IO uint32_t TimingDelayInc; __IO uint32_t TimingDelayDec; uint8_t trigB; Pkg_Uart g_pkg_uart_1 = { 0, 0, 0, "", 0}; Pkg_Uart g_pkg_uart_2 = { 0, 0, 0, "", 0}; Flag_Counter g_flag_counter_key = {0, 0, 0}; Flag_Counter g_flag_counter_ota = {0, 0, 0}; uint8_t g_storage_uart_num = 0; uint32_t g_storage_uart_baud = 19200;//9600; uint8_t g_storage_uart_num_2 = 1; uint32_t g_storage_uart_baud_2 = 115200; //115200; uint32_t mstick(void){ return TimingDelayInc; } void InitPkgUart(Pkg_Uart * pkg){ memset(pkg->pkg, 0, BUFF_STACK_SIZE); pkg->flag = 0; pkg->tick = 0; pkg->len = 0; pkg->offset = 0; } /********************************************************************* * @fn TIM2_Init * * @brief Initializes TIM2. * * @return none */ void TIM2_Init( void ) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure={0}; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_TimeBaseStructure.TIM_Period = SystemCoreClock / 1000000; TIM_TimeBaseStructure.TIM_Prescaler = WCHNETTIMERPERIOD * 1000 - 1; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); TIM_ITConfig(TIM2, TIM_IT_Update ,ENABLE); TIM_Cmd(TIM2, ENABLE); TIM_ClearITPendingBit(TIM2, TIM_IT_Update ); NVIC_EnableIRQ(TIM2_IRQn); } /********************************************************************* * @fn TIM3_Init * * @brief Initializes TIM3. * * @return none */ void TIM3_Init(void) { NVIC_InitTypeDef NVIC_InitStructure={0}; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = { 0 }; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); ////10ms // TIM_TimeBaseStructure.TIM_Period = SystemCoreClock / 1000000; // TIM_TimeBaseStructure.TIM_Prescaler = 10 * 1000 - 1; //1ms TIM_TimeBaseStructure.TIM_Period = SystemCoreClock / 1000000; TIM_TimeBaseStructure.TIM_Prescaler = 1 * 1000 - 1; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); TIM_Cmd(TIM3, ENABLE); TIM_ClearITPendingBit(TIM3, TIM_IT_Update); NVIC_EnableIRQ(TIM3_IRQn); } void key_event_srv(void){ // if(g_flag_counter_key.tick > 1000){ // PRINT("key_tick_timeup_______: %d\n", GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)); // g_flag_counter_key.tick = 0; // } if(g_flag_counter_key.flag){ uint8_t _pkg[7] = {0}; uint8_t i = 0; switch (g_flag_counter_key.flag) { case KEY_ET_BLE_ENABLE: { PRINT("______KEY_ET_BLE_ENABLE\n"); NVIC_SystemReset(); } break; case KEY_ET_REBOOT: { PRINT("__________KEY_ET_REBOOT\n"); _pkg[i++] = 0x7F; _pkg[i++] = 0x00; _pkg[i++] = 0x01; _pkg[i++] = 0x6D; _pkg[i++] = 0x6C; _pkg[i++] = 0x6E; UART2_SendString(_pkg, i); //1 send loop mcu reboot; Delay_Ms(10); // 2 DBN dev reboot NVIC_SystemReset(); } break; case KEY_ET_FACTORY: { PRINT("_____________KEY_ET_FACTORY\n"); _pkg[i++] = 0x7F; _pkg[i++] = 0x00; _pkg[i++] = 0x01; _pkg[i++] = 0x92; _pkg[i++] = 0x93; _pkg[i++] = 0x93; UART2_SendString(_pkg, i); //1 send loop mcu factory init } break; case KEY_ET_NETBLE_FACTORY: { //2 DBN dev factory init; factory_dev_info(); Delay_Ms(10); NVIC_SystemReset(); } break; } g_flag_counter_key.flag = 0; } } /********************************************************************* * @fn Main_Circulation * * @brief Main loop * * @return none */ __attribute__((section(".highcode"))) __attribute__((noinline)) void Main_Circulation(void) { uint32_t _counter = 0; while(1) { FAULT_MARKER(MK_LOOP_TOP); iot_watchdog_kick(); /* 无条件喂狗 (2026-08-13): 原只在 iot_mqtt_poll, tcp_json 分支不喂 */ TMOS_SystemProcess(); if(g_net_state.flag < 2) { net_srv_init(); } if(g_net_state.flag == 2) { if(g_sub_code_enable.iot_enable){ if(iot_net_info.mode == IOT_Addr_IP_Mode){ if(get_ipstr_to_array(iot_net_info.remote_addr, RemoteIP) == 0){ WCHNET_CreateTcpMqttSocket(); } } else{ //DNS } } else { WCHNET_CreateTcpSocket(); } } /*Ethernet library main task function, * which needs to be called cyclically*/ WCHNET_MainTask(); /*Query the Ethernet global interrupt, * if there is an interrupt, call the global interrupt handler*/ if(WCHNET_QueryGlobalInt()) { WCHNET_HandleGlobalInt(); } FAULT_MARKER(MK_UART_SRV_IN); uart_srv(); FAULT_MARKER(MK_UART_SRV_OUT); snap_flush(); /* 快照落盘: 无条件挂主循环 (原在 iot_enable 分支, TCP 模式不落盘) */ FAULT_MARKER(MK_POLL_BLE_IN); poll_dbn_ble(); if (g_sub_code_enable.iot_enable) { iot_mqtt_publish_sensor(); // Push 0xC0 sensor data to MQTT broker iot_mqtt_poll(); // IoT MQTT state machine + PINGREQ keepalive } else { tcp_json_push_sensor(); // Push 0xC0 sensor data to TCP JSON client tcp_json_poll(); } key_event_srv(); } } /********************************************************************* * @fn main * * @brief Main function * * @return none */ int main(void) { SystemCoreClockUpdate(); Delay_Init(); #ifdef DEBUG // USART_Printf_Init( 115200 ); USART_Printf_Init( 256000 ); #endif /* 诊断: 复位原因寄存器 (bit31=IWDG bit30=WWDG bit29=LPWR bit26=NRST bit25=POR bit24=软复位) 每次上电必打, 区分看门狗死锁 vs 掉电 vs 外部复位 */ PRINT("RST_REASON: 0x%08lx\n", (unsigned long)OFFLOG_RCC_RSTSCKR); fault_diag_init(); /* 打印上次复位现场 (HardFault mcause/mepc + 执行轨迹 marker) */ iot_watchdog_init(); /* 无条件 IWDG (2026-08-13): iot_enable=0 时 iot_mqtt_init 不调, 卡死无兜底 → 永久冻结。IWDG 4s 超时 + 主循环喂狗 */ PRINT("%s\n", VER_LIB); PRINT("SystemCoreClock:%d\n", SystemCoreClock); /* ===== 实验: 禁用全部 Flash/SPI 操作 (2026-08-12) ===== 结论: 禁用后设备稳定 → SPI 操作触发复位+乱码实锤 软件缓解: storage.c SPI 时钟降档 + GPIO 缓边沿 (见 SPI_Flash_Init) 硬件根治: NRST 加 100nF 电容 / SPI 走线远离 NRST / 串阻缓边沿 #if 0 = 恢复全部 SPI; 保留本块便于回退实验 */ #if 0 PRINT("ISOLATE: flash/SPI disabled (flash isolation test)\n"); #else GetMacAddr(gMacAddr); storage_init(); PRINT("INIT: storage ok\n"); offlog_init(); PRINT("INIT: offlog ok\n"); /* 快照区: 上电扫描恢复 (2026-08-14, printf 重入修复后恢复启用) */ snap_init(); PRINT("INIT: snap ok\n"); /* offlog_boot: 记录本次复位原因到事件日志 (2026-08-14 恢复) */ { uint32_t rcc_rst = OFFLOG_RCC_RSTSCKR; offlog_boot(rcc_rst); OFFLOG_RCC_RSTSCKR |= OFFLOG_RST_RMVF; /* RMVF (bit24): 清复位标志 */ } load_cfg_from_flash(); output_cfg_from_flash(); #endif PRINT("MAC: %02X %02X %02X %02X %02X %02X\r\n", gMacAddr[0],gMacAddr[1], gMacAddr[2], gMacAddr[3],gMacAddr[4],gMacAddr[5]); PRINT("net version:%x\n", WCHNET_GetVer()); WCHBLE_Init(); HAL_Init(); uart_init(); /* ===== 实验: 禁用 UART2 (Loop 口) 隔离测试 (2026-08-12) ===== 结论: UART2 禁用后仍复位 → 与 Loop 数据路径无关 (后定位为 SPI 串扰) #if 0 = 恢复 UART2 正常 */ #if 0 { GPIO_InitTypeDef gpio; USART_ITConfig(USART2, USART_IT_RXNE, DISABLE); USART_Cmd(USART2, DISABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); gpio.GPIO_Pin = GPIO_Pin_3; gpio.GPIO_Mode = GPIO_Mode_IPU; /* PA3 脱离 UART2, 上拉输入 */ gpio.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &gpio); PRINT("ISOLATE: UART2 disabled (Loop isolation test)\n"); } #endif TIM3_Init(); TIM2_Init(); GAPRole_PeripheralInit(); Peripheral_Init(); Main_Circulation(); } void TIM3_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); /********************************************************************* * @fn TIM3_IRQHandler, 1ms * * @brief This function handles TIM2 exception. * * @return none */ void TIM3_IRQHandler(void) { TimingDelayInc++; g_activ_counter++; if(g_pkg_uart_2.offset){ if(g_pkg_uart_2.flag == 0){ g_pkg_uart_2.tick++; if(g_pkg_uart_2.tick > 8){ g_pkg_uart_2.flag = 1; } } } // Safety: reset frame parser if stuck in non-IDLE state too long if(g_lup_parser.state != LUP_FRAME_STATE_IDLE){ if(g_pkg_uart_2.tick > 20){ lup_frame_reset(); g_pkg_uart_2.tick = 0; } } if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 0){//HAL_PUSH_BUTTON()){ g_flag_counter_key.tick++; } else{ if(g_flag_counter_key.tick){ if(g_flag_counter_key.tick < 2000){ g_flag_counter_key.flag = KEY_ET_BLE_ENABLE; } else if(g_flag_counter_key.tick < 6000){ g_flag_counter_key.flag = KEY_ET_REBOOT; } else if(g_flag_counter_key.tick < 10000){ g_flag_counter_key.flag = KEY_ET_FACTORY; } else{ g_flag_counter_key.flag = KEY_ET_NETBLE_FACTORY; } g_flag_counter_key.tick = 0; } } TIM_ClearITPendingBit(TIM3, TIM_IT_Update); } /******************************** endfile @ main ******************************/