/* 包含系统配置头文件,提供芯片时钟、电源管理等底层硬件配置 */ #include "sys_config.h" /* 包含基础头文件集合,提供常用类型定义和宏 */ #include "basic_include.h" /* 包含ADC(模数转换器)驱动头文件,用于模拟信号采集 */ #include "hal/adc.h" /* 包含CPU间RPC(远程过程调用)通信库,用于CPU0和CPU1之间的消息传递 */ #include "lib/rpc/cpurpc.h" /* 包含AT命令解析库,用于通过串口发送AT指令进行模块配置 */ #include "lib/atcmd/libatcmd.h" /* 包含通用AT命令定义,提供系统常用的AT命令接口 */ #include "lib/common/atcmd.h" /* 包含IEEE 802.11无线网络协议定义,提供WiFi MAC帧结构等 */ #include "lib/umac/ieee80211.h" /* 包含低层MAC(LMAC)驱动,提供WiFi底层硬件访问接口 */ #include "lib/lmac/lmac.h" /* 包含BLE(低功耗蓝牙)演示程序头文件,提供蓝牙配网等功能 */ #include "lib/bluetooth/uble/ble_demo.h" /* 包含lwIP(轻量级TCP/IP协议栈)错误码定义 */ #include "lwip/err.h" /* 包含lwIP套接字接口,提供类似BSD socket的API */ #include "lwip/sockets.h" /* 包含lwIP网络域名解析接口,提供gethostbyname等DNS功能 */ #include "lwip/netdb.h" /* 包含lwIP系统抽象层,提供线程、信号量等操作系统抽象 */ #include "lwip/sys.h" /* 包含lwIP IP地址操作接口,提供IP地址的解析和转换功能 */ #include "lwip/ip_addr.h" /* 包含lwIP TCP/IP协议栈核心初始化接口 */ #include "lwip/tcpip.h" /* 包含以太网网络接口驱动,提供以太网底层收发功能 */ #include "netif/ethernetif.h" /* 包含DHCP服务器头文件,用于设备作为AP时为客户端分配IP地址 */ #include "lib/net/dhcpd/dhcpd.h" /* 包含网络工具函数,提供IP地址转换等网络辅助功能 */ #include "lib/net/utils.h" /* 包含网络Socket监控模块,用于监控socket状态和连接信息 */ #include "lib/net/skmonitor/skmonitor.h" /* 包含系统配置管理头文件,提供系统参数的读写和存储功能 */ #include "syscfg.h" /* 包含用户应用层头文件,提供FPV、对讲机等应用初始化接口 */ #include "app/user_app.h" /* 包含CPU1内存管理头文件,提供CPU1侧的堆内存获取接口 */ #include "cpu1_mem.h" /* 外部引用:SRAM内存池的起始地址(由链接脚本定义) */ extern uint32 srampool_start; /* 外部引用:SRAM内存池的结束地址(由链接脚本定义) */ extern uint32 srampool_end; /* 外部引用:PSRAM(伪静态RAM)内存池的起始地址(由链接脚本定义) */ extern uint32 psrampool_start; /* 外部引用:PSRAM内存池的结束地址(由链接脚本定义) */ extern uint32 psrampool_end; /* 定义主循环工作队列结构体,用于定时执行系统主循环任务 */ static struct os_work main_wk; /* 定义全局系统状态结构体变量,保存系统运行时的各种状态标志 */ struct system_status sys_status; /* 外部引用:系统事件处理函数,处理WiFi连接、网络状态等系统事件 */ extern sysevt_hdl_res sys_event_hdl(uint32 event_id, uint32 data, uint32 priv); /* 外部引用:WiFi设备状态查询函数,用于获取WiFi模块的调试信息 */ extern void wifi_dev_status(uint32 dev_id); /* 外部引用:系统AT命令初始化函数,注册系统支持的AT命令 */ extern void sys_atcmd_init(void); /* 外部引用:WiFi测试模式初始化函数,用于产线射频测试 */ extern void sys_wifi_test_mode_init(void); /* 外部引用:WiFi模块初始化函数,初始化WiFi硬件和协议栈 */ extern void sys_wifi_init(void); /* 外部引用:网络初始化函数,配置网络接口和协议参数 */ extern void sys_network_init(void); /* 外部引用:DHCP服务器启动函数,在AP模式下为客户端分配IP */ extern void sys_dhcpd_start(void); /* 外部引用:DHCP客户端检查函数,检查STA模式下是否成功获取IP */ extern void sys_dhcpc_check(void); /* CPU间RPC通信初始化函数,标记为__init表示仅在系统启动时执行一次 */ static __init void sys_cpurpc_init() { /* 初始化CPU0的消息邮箱通信,指定邮箱基地址和收发中断号 */ cpu_rpc_init(CPU0_MSGBOX_BASE, CPU_RECV_MAIL_IRQn, CPU_SEND_MAIL_IRQn); } /* 系统配置加载函数,从Flash中读取保存的系统配置参数 */ __init static void sys_cfg_load(void) { /* 尝试从Flash中加载名为"syscfg"的配置数据,如果成功则直接返回 */ if (syscfg_init("syscfg", &sys_cfgs, sizeof(sys_cfgs)) == RET_OK) { return; } /* 如果加载失败(首次启动或数据损坏),打印提示信息 */ os_printf("use default params.\r\n"); /* 使用默认的出厂配置参数填充sys_cfgs结构体 */ syscfg_default(); /* 将默认配置保存到Flash中,以便下次启动时可以直接加载 */ syscfg_save(); } /* 系统调试时间打印函数,用于定时打印当前系统时间(SNTP同步后) */ static void sys_print_dbgtime(uint32 *buff, uint32 size) { #if SYS_APP_SNTP /* 定义timeval结构体变量,用于获取当前的秒和微秒时间 */ struct timeval tv; /* 调用gettimeofday获取当前系统时间 */ gettimeofday(&tv, 0); /* 将时间加上8小时(东八区/北京时间)的偏移量 */ tv.tv_sec += 8 * 3600; /* 将时间戳转换为可读的字符串格式并打印 */ os_printf("system time: %s\r\n", ctime((const time_t *)&tv.tv_sec)); #endif } /* 系统调试Cache命中率打印函数,用于监控CPU Cache的效率 */ static void sys_print_dbgcache(uint32 *buff, uint32 size) { /* 仅在调试开关打开时执行Cache统计信息打印 */ if (sys_status.dbg_cache) { /* 获取CPU侧CSI(指令)Cache的未命中次数,参数1表示打印后重置统计 */ uint32 csi_miss = sys_csi_cache_static(sysctrl_get_cpu_id(), 1); /* 获取CLD(数据)Cache的未命中次数,参数1表示打印后重置统计 */ uint32 cld_miss = sys_cld_cache_static(1); /* 根据Cache未命中率动态调整PSRAM效率优化策略 */ sys_psram_eff_static((cld_miss > 20) || (csi_miss > 30)); } } /* 系统调试CPU使用率打印函数,用于监控各任务的CPU占用情况 */ static void sys_print_dbgtop(uint32 *buff, uint32 size) { /* 仅在调试开关打开时执行CPU使用率打印 */ if (sys_status.dbg_top) { /* 打印CPU各任务的使用率信息,参数1表示是否打印详细信息(dbg_top==2时) */ cpu_loading_print(sys_status.dbg_top == 2, (struct os_task_info *)buff, size / sizeof(struct os_task_info)); } } /* 系统调试Heap内存使用情况打印函数,用于监控SRAM和PSRAM的内存分配 */ static void sys_print_dbgheap(uint32 *buff, uint32 size) { /* 仅在调试开关打开时执行Heap使用情况打印 */ if (sys_status.dbg_heap) { /* 打印SRAM Heap的使用状况(空闲块数、最大连续空闲空间等) */ sysheap_status(&sram_heap, buff, size / 4, 0); #ifdef PSRAM_HEAP /* 如果启用了PSRAM作为Heap,也打印PSRAM Heap的使用状况 */ sysheap_status(&psram_heap, buff, size / 4, 0); #endif } } /* 系统调试WiFi MAC层信息打印函数,用于排查WiFi连接问题 */ static void sys_print_dbgumac(uint32 *buff, uint32 size) { /* 仅在调试开关打开时执行WiFi调试信息打印 */ if (sys_status.dbg_umac) { /* 打印WiFi设备(设备ID为HG_WIFI0_DEVID)的当前状态信息 */ wifi_dev_status(HG_WIFI0_DEVID); } } /* 系统调试网络信息打印函数,用于显示当前网络接口的IP地址和DHCP状态 */ static void sys_print_dbgnet(uint32 *buff, uint32 size) { /* 定义指向网络接口结构体的指针 */ struct netif *nif; /* 仅在调试开关打开时执行网络信息打印 */ if (sys_status.dbg_net){ /* 打印分隔线,美化输出格式 */ os_printf("-----------------------------------------------------\r\n"); /* 打印网络信息标题 */ os_printf("Network Info:\r\n"); /* 查找名为"w0"的无线网络接口 */ nif = netif_find("w0"); /* 如果找到无线接口,打印其IP地址、子网掩码和网关地址 */ if(nif){ /* 打印WiFi接口的IP配置,同时显示是DHCP获取还是静态配置 */ os_printf(" w0: (%s) "IPSTR"/"IPSTR"/"IPSTR"\r\n", (sys_cfgs.dhcpc_en && sys_status.dhcpc_done)?"DHCP":"Static", IP2STR_N(nif->ip_addr.addr), IP2STR_N(nif->netmask.addr), IP2STR_N(nif->gw.addr)); } /* 查找名为"e0"的有线以太网网络接口 */ nif = netif_find("e0"); /* 如果找到以太网接口,打印其IP地址、子网掩码和网关地址 */ if(nif){ /* 打印以太网接口的IP配置信息 */ os_printf(" e0: (%s) "IPSTR"/"IPSTR"/"IPSTR"\r\n", sys_cfgs.dhcpc_en?"DHCP":"Static", IP2STR_N(nif->ip_addr.addr), IP2STR_N(nif->netmask.addr), IP2STR_N(nif->gw.addr)); } #if IP_NAT /* 如果启用了NAT(网络地址转换),打印NAT映射表状态 */ os_printf("-----------------------------------------------------\r\n"); ip4_nat_status(); #endif /* 如果启用了DHCP服务器,打印当前已分配的IP地址池信息 */ if(sys_cfgs.dhcpd_en){ os_printf("-----------------------------------------------------\r\n"); dhcpd_dump_ippool(); } } } /* 系统调试信息汇总打印函数,每隔5秒定时调用一次各子打印函数 */ static void sys_dbginfo_print(void) { /* 静态变量记录打印间隔计数器,用于控制每5秒打印一次 */ static int8 print_interval = 0; #if 0 /* 静态缓冲区方案(常驻内存,不占用任务栈空间) */ static uint32 _print_buf[256]; #else /* 局部缓冲区方案(使用任务栈空间,函数返回后自动释放) */ uint32 _print_buf[256]; /* 断言检查:确保缓冲区大小不超过1600字节,防止任务栈溢出 */ ASSERT(sizeof(_print_buf) < 1600); #endif /* 计数器递增,当达到5时(即5秒后)执行一轮调试信息打印 */ if (print_interval++ >= 5) { /* 打印Cache命中率和PSRAM效率统计 */ sys_print_dbgcache(_print_buf, sizeof(_print_buf)); /* 打印CPU各任务的使用率 */ sys_print_dbgtop(_print_buf, sizeof(_print_buf)); /* 打印SRAM和PSRAM的Heap内存使用情况 */ sys_print_dbgheap(_print_buf, sizeof(_print_buf)); /* 打印WiFi MAC层的调试信息 */ sys_print_dbgumac(_print_buf, sizeof(_print_buf)); /* 打印当前系统时间(SNTP同步后) */ sys_print_dbgtime(_print_buf, sizeof(_print_buf)); /* 打印网络接口的IP地址和DHCP信息 */ sys_print_dbgnet(_print_buf, sizeof(_print_buf)); /* 重置计数器,开始下一个5秒周期 */ print_interval = 0; } } /* 系统Heap内存布局信息打印函数,在启动时显示各内存区域的分配情况 */ __init static void sys_heap_info() { /* 打印分隔线 */ os_printf("------------------------------------------------------------\r\n"); /* 打印系统Heap的总体信息:总大小和起始地址范围 */ os_printf("System Heaps Info, Total: %d (%p ~ %p)\r\n", SRAM_POOL_SIZE, SRAM_POOL_START, SRAM_POOL_START+SRAM_POOL_SIZE); /* 定义CPU1 Heap内存区域的起始指针 */ uint8_t *cpu1_heap; /* 定义CPU1 SKB(Socket缓冲区)内存池的起始指针 */ uint8_t *skb_heap; /* 定义CPU1接收缓冲区内存池的起始指针 */ uint8_t *rxbuf_heap; /* 定义CPU1 Heap内存区域的大小 */ uint32_t cpu1_heap_size; /* 定义CPU1 SKB内存池的大小 */ uint32_t skb_heap_size; /* 定义CPU1接收缓冲区内存池的大小 */ uint32_t rxbuf_heap_size; /* 获取CPU1 Heap内存区域的起始地址和大小 */ cpu1_heap = (uint8_t*)cpu1_heap_get(&cpu1_heap_size); /* 获取CPU1 SKB(Socket Buffer)内存池的起始地址和大小 */ skb_heap = (uint8_t*)cpu1_skb_heap_get(&skb_heap_size); /* 获取CPU1接收缓冲区内存池的起始地址和大小 */ rxbuf_heap = (uint8_t*)cpu1_RXBUF_heap_get(&rxbuf_heap_size); /* 打印CPU1 Heap的地址范围和大小 */ os_printf("| CPU1 HEAP : %p ~ %p, Size:%-8d |\r\n", cpu1_heap, cpu1_heap+cpu1_heap_size, cpu1_heap_size); /* 打印CPU1接收缓冲区的地址范围和大小 */ os_printf("| CPU1 RXBUF : %p ~ %p, Size:%-8d |\r\n", rxbuf_heap, rxbuf_heap+rxbuf_heap_size, rxbuf_heap_size); /* 打印CPU1 SKB内存池的地址范围和大小 */ os_printf("| CPU1 SKBPOOL: %p ~ %p, Size:%-8d |\r\n", skb_heap, skb_heap+skb_heap_size, skb_heap_size); /* 打印CPU0 AVHEAP(音视频堆)的地址范围和大小(已注释掉) */ //os_printf("| CPU0 AVHEAP : %p ~ %p, Size:%-8d |\r\n", CONFIG_AVHEAP_START, CONFIG_AVHEAP_START+CONFIG_AVHEAP_SIZE, CONFIG_AVHEAP_SIZE); /* 打印CPU0系统Heap的地址范围和大小 */ os_printf("| CPU0 HEAP : %p ~ %p, Size:%-8d |\r\n", SYS_HEAP_START, SYS_HEAP_START+SYS_HEAP_SIZE, SYS_HEAP_SIZE); /* 打印分隔线 */ os_printf("------------------------------------------------------------\r\n"); /* 释放CPU1信息查询时分配的内存资源 */ cpu1_info_free(); } /* 系统主循环函数,每1000ms被工作队列调度执行一次 */ static int32 sys_main_loop(struct os_work *work) { /* 喂MCU看门狗,防止系统死机时看门狗超时复位 */ mcu_watchdog_feed(); /* 调用调试信息打印函数,定时输出系统运行状态 */ sys_dbginfo_print(); #if SYS_NETWORK_SUPPORT /* 如果系统支持网络功能,检查DHCP客户端是否成功获取IP地址 */ sys_dhcpc_check(); #endif /* 将主循环工作项重新加入队列,1000ms后再次执行本函数 */ os_run_work_delay(&main_wk, 1000); /* 返回0表示函数执行成功 */ return 0; } /* 系统应用层初始化函数,根据不同的宏配置启动对应的应用模块 */ __init static void sys_app_init(void) { #if SYS_APP_DHCPD && SYS_NETWORK_SUPPORT /* 如果启用了DHCP服务器且支持网络,启动DHCP服务器为连接的客户端分配IP */ sys_dhcpd_start(); #endif #if SYS_APP_SNTP && SYS_NETWORK_SUPPORT /* 如果启用了SNTP时间同步且支持网络,连接阿里云NTP服务器进行时间同步,超时2秒 */ sntp_client_init("ntp.aliyun.com", 2); #endif #ifdef SYS_APP_FPV /* 如果启用了FPV(第一人称视角)图传应用,初始化FPV模块 */ sys_app_fpv_init(); #endif #ifdef SYS_APP_DEMO /* 如果启用了通用Demo应用,初始化Demo模块 */ sys_app_demo_init(); #endif #ifdef SYS_APP_IPC /* 如果启用了IPC(网络摄像头)应用,初始化IPC模块 */ sys_app_ipc_init(); #endif #ifdef SYS_APP_BBM_LCD /* 如果启用了BBM(婴儿监视器)LCD显示端应用,初始化LCD显示模块 */ sys_app_bbm_lcd_init(); #endif #ifdef SYS_APP_WALKIE_TALKIE /* 如果启用了对讲机应用,初始化对讲机模块 */ sys_app_walkie_talkie_init(); #endif #ifdef SYS_APP_BBM_CAM /* 如果启用了BBM(婴儿监视器)摄像头端应用,初始化摄像头模块 */ sys_app_bbm_cam_init(); #endif #if SYS_APP_BLENC /* 如果启用了BLE配网功能,初始化蓝牙网络配置模块 */ sys_ble_netconfig_init(); #endif #if SYS_WIFI_PAIR /* 如果启用了WiFi配对功能,初始化WiFi配对模块 */ sys_wifi_pair_init(); #endif #if SYS_WIFI_PAIR_LED /* 如果启用了WiFi配对LED指示灯功能,初始化配对状态的LED显示 */ sys_wifi_pair_led_init(); #endif #ifdef SYS_APP_ISP_TUNNING /* 如果启用了ISP调参应用,初始化ISP图像调参模块 */ sys_app_isp_tunning_init(); #endif } /* 用户应用初始化函数,用户可在此添加自定义的应用初始化代码 */ __init static void usr_app_init(void) { /* 添加用户App代码初始化 */ } /* 看门狗喂狗循环函数,仅在WiFi测试模式下使用,防止测试时看门狗复位 */ static int32 watchdog_loop(struct os_work *work) { /* 喂MCU看门狗,保持系统运行 */ mcu_watchdog_feed(); /* 将看门狗喂狗工作项重新加入队列,1000ms后再次执行 */ os_run_work_delay(&main_wk, 1000); /* 返回0表示函数执行成功 */ return 0; } /* 系统主入口函数,芯片上电后首先执行此函数 */ int main(void) { /* 设置MCU看门狗超时时间为0(禁用MCU看门狗),防止调试时意外复位 */ mcu_watchdog_timeout(0); /* 初始化CPU间RPC通信通道,建立CPU0和CPU1之间的消息传递机制 */ sys_cpurpc_init(); /* 打印系统各内存区域的布局信息(Heap、PSRAM、SKB池等) */ sys_heap_info(); /* 从Flash加载系统配置参数,如果加载失败则使用默认配置并保存 */ sys_cfg_load(); /* 初始化系统事件队列,设置队列深度为32个事件 */ sys_event_init(32); /* 初始化系统AT命令模块,注册所有支持的AT命令 */ sys_atcmd_init(); /* 检查系统是否处于WiFi产线测试模式 */ if (system_is_wifi_test_mode()) { /* 进入WiFi测试模式,初始化射频测试所需的硬件和参数 */ sys_wifi_test_mode_init(); /* 测试完成后重启进入正常工作模式 */ system_reboot_normal_mode(); /* 初始化看门狗喂狗工作项,绑定watchdog_loop回调函数 */ OS_WORK_INIT(&main_wk, watchdog_loop, 0); /* 延时1000ms后开始执行看门狗喂狗循环 */ os_run_work_delay(&main_wk, 1000); }else{ /* 正常工作模式:初始化WiFi硬件和协议栈 */ sys_wifi_init(); /* 初始化网络接口,配置IP地址和协议参数 */ sys_network_init(); /* 调用所有C++全局对象的构造函数(如果项目中包含C++代码) */ do_global_ctors(); /* 根据宏配置初始化对应的应用模块(FPV、对讲机等) */ sys_app_init(); /* 执行用户自定义的应用初始化代码 */ usr_app_init(); /* 启动系统事件处理循环,接收并分发系统事件(WiFi连接、断开等) */ sys_event_take(0xffffffff, sys_event_hdl, 0); /* 初始化主循环工作项,绑定sys_main_loop回调函数 */ OS_WORK_INIT(&main_wk, sys_main_loop, 0); /* 延时1000ms后开始执行系统主循环 */ os_run_work_delay(&main_wk, 1000); } /* 设置PMU(电源管理单元)看门狗超时时间为0(禁用PMU看门狗), 放在sys_wifi_init之后是因为WiFi初始化可能需要较长耗时 */ pmu_watchdog_timeout(0); /* 主函数返回0(实际上RTOS环境下不会执行到此处) */ return 0; }