【BES2500x系列 -- RTX5操作系统】系统执行流程 -- 应用初始化 -- app_init() --(十二)

  • 💌 所属专栏:【BES2500x系列】

  • 😀 作  者:我是夜阑的狗🐶

  • 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询!

  • 💖 欢迎大家:这里是CSDN,我总结知识的地方,喜欢的话请三连,有问题请私信 😘 😘 😘

您的点赞、关注、收藏、评论,是对我最大的激励和支持!!!🤩 🤩 🤩

文章目录

  • 前言
  • [1 应用初始化 app_init()](#1 应用初始化 app_init())
      • [1.1 app_os_init()](#1.1 app_os_init())
      • [1.2 app_battery_open()](#1.2 app_battery_open())
      • [1.3 app_audio_open()](#1.3 app_audio_open())
  • 总结

<<【系列文章索引】>>

前言

大家好,又见面了,我是夜阑的狗🐶,本文是专栏【BES2500x系列】专栏的第12篇文章;

今天开始学习BES2500x系列的一天💖💖💖,开启新的征程,记录最美好的时刻🎉,每天进步一点点。

专栏地址:【BES2500x系列】, 此专栏是我是夜阑的狗对BES2500x系列开发过程的总结,希望能够加深自己的印象,以及帮助到其他的小伙伴😉😉。对了,前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站

如果文章有什么需要改进的地方还请大佬不吝赐教👏👏。


1 应用初始化 app_init()

前面学习了嵌入式系统启动的基本流程,可以分为 引导程序系统初始化程序 这两部分,并系统初始化 中 main 函数进行了详细讲解。接下来就学习 main 函数中 应用初始化 具体是怎么跑的吧。话不多说,让我们原文再续,书接上回吧。

从上一篇文章可以了解到系统的 main 函数是如何跑到的,并且在讲解 main 函数中各个函数的作用,接下来就看一下 main 中的应用初始化具体都干了些什么吧,可以在 app.cpp 文件中看到该 app_init 函数。

  • 代码

这里由于 app_init 函数代码过多,这里不就放出来了,只讲解一下其中的各个函数作用。

c 复制代码
/*
 * 函数名:app_init
 * 功能:应用程序初始化
 * 参数:无
 * 返回值:初始化结果,0表示成功,非0表示失败
 * 描述:本函数用于在应用程序启动时进行初始化操作,包括环境变量加载、电源键检测和USB插拔状态检查。
 */
int app_init(void)
{
    // 初始化返回值为成功
    int nRet = 0;
    // 定义并初始化nvrecord环境变量结构体指针
    struct nvrecord_env_t *nvrecord_env;
	......省略后续
	......
}

注意:该函数并不是完整的函数,只截取部分代码

  • 参数/函数讲解

app_init() 函数详细介绍,这些函数调用涉及到了蓝牙、存储、系统状态、电源管理以及音频等方面的初始化和配置:

序号 函数 说明
1 app_bt_add_string_test_table() 添加蓝牙字符串测试表的函数,用于在蓝牙测试中使用。
2 nv_record_init() 初始化 flash,用于存储一些系统配置和状态信息。
3 factory_section_init() 初始化工厂设置部分的函数,用于读取和设置设备的出厂默认参数。
4 app_sysfreq_req() 请求系统频率的函数,用于调整系统的工作频率以满足当前的性能需求。
5 list_init() 初始化链表数据结构,以便后续的数据操作和管理。
6 app_os_init() 初始化操作系统相关的资源和数据结构。
7 app_status_indication_init() 初始化应用程序状态指示的函数,用于在设备上指示当前的工作状态。
8 app_battery_open() 初始化电池管理模块,用于监控电池状态和电量,充电检测,并返回电池状态。
9 hal_sw_bootmode_set() 设置了软件引导模式为重启模式,以便系统在下次启动时执行重启操作。
10 app_poweron_key_init() 初始化开机按键的函数,用于检测用户的开机按键操作。
11 app_bt_init() 初始化蓝牙模块,包括协议栈的初始化和配置。
12 af_open() 初始化音频框架(Audio Framework)的函数,用于音频处理和管理。
13 app_audio_open() 初始化音频模块,包括音频设备的打开和配置。
14 app_audio_manager_open() 初始化音频管理器的函数,用于管理音频资源和会话。
15 app_overlay_open() 打开应用程序覆盖区的函数,用于加载和管理应用程序的覆盖资源。主要是创建一个互斥锁。
16 nv_record_env_init() 初始化环境变量的 flash。
17 nvrec_dev_data_open() 打开设备数据的非易失性记录(NV Record),用于存储和读取设备相关的数据信息。
18 factory_section_open() 用于打开工厂设置部分的函数,用于读取工厂设置的参数信息。
19 nv_record_env_get() 获取环境变量的 flash,用于读取环境变量信息。
20 audio_process_init() 初始化音频处理模块的函数,用于音频数据的处理和转换。
21 app_bt_stream_volume_ptr_update(NULL) 更新蓝牙音频流的音量指针,可能在音频设备或会话发生变化时调用。
22 app_start_bt_module_thread() 该函数创建并启动了一个用于初始化蓝牙模块的线程,并设置应用线程的优先级为高于正常优先级。
23 btdrv_start_bt() 启动蓝牙设备的函数,用于初始化和启动蓝牙协议栈。

1.1 app_os_init()

接下来对 app_init 函数中个别函数进行讲解,app_os_init() 是一个应用程序操作系统初始化函数的实现

  • 代码
c 复制代码
/**
 * 初始化操作系统环境
 * 
 * 该函数负责初始化应用程序的操作系统环境它首先尝试初始化邮箱,然后创建一个应用线程
 * 这是应用程序启动的入口点,确保操作系统环境正确初始化,以便应用程序能够正常运行
 * 
 * @return 返回-1表示初始化失败,0表示成功
 */
int app_os_init(void)
{
    // 初始化邮箱系统,如果失败则返回-1
    if (app_mailbox_init())
        return -1;

    // 创建应用线程,如果创建失败则返回0
    app_thread_tid = osThreadCreate(osThread(app_thread), NULL);
    if (app_thread_tid == NULL)  {
        TRACE(0,"Failed to Create app_thread\n");
        return 0;
    }
    return 0;
}
  • 参数/函数讲解
序号 函数 说明
1 app_mailbox_init() 初始化应用程序的邮箱,邮箱通常用于线程间的通信和消息传递。如果初始化失败,函数会返回非零值。
2 osThreadCreate() 创建了一个名为 app_thread 的线程,并将其标识符保存在 app_thread_tid 变量中。osThreadCreate 是操作系统提供的函数,用于创建一个新的线程。osThread 宏用于指定要创建的线程的名称。

总的来说,这个函数的作用是初始化应用程序的操作系统环境,包括初始化邮箱和创建一个新的线程用于应用程序的执行。

1.2 app_battery_open()

在应用初始化中,电池模块肯定必不可少的,接下来让我们来看看充电检测执行流程如下步骤所示:

Step 1 、充电检测(电池状态,充电状态或是充电使用状态) ;

Step 2 、定时检测电量 ---> 可以通过中断方式检测当前电压值 ;

Step 3、将检测到的电压通过邮箱发送,并进行相应处理 ;

  • 代码
c 复制代码
/*
 * 函数功能:打开电池管理模块的初始化函数
 * 
 * 描述:该函数负责初始化电池管理模块,包括创建定时器,设置电池测量参数,
 *       配置外部充电器检测器和使能引脚,以及根据充电状态设置模块状态。
 *       
 * 参数:无
 *       
 * 返回值:电池模块打开模式,包括无效模式、正常模式、充电模式、上电充电模式
 */
int app_battery_open(void)
{
    // 打印电池范围跟踪信息
    APP_BATTERY_TRACE(3,"%s batt range:%d~%d",__func__, APP_BATTERY_MIN_MV, APP_BATTERY_MAX_MV);
    // 初始化返回值为无效模式
    int nRet = APP_BATTERY_OPEN_MODE_INVALID;

    // 如果电池定时器未创建,则创建之
    if (app_battery_timer == NULL)
        app_battery_timer = osTimerCreate (osTimer(APP_BATTERY), osTimerPeriodic, NULL);

    // 如果电池插拔抖动定时器未创建,则创建之
    if (app_battery_pluginout_debounce_timer == NULL)
        app_battery_pluginout_debounce_timer = osTimerCreate (osTimer(APP_BATTERY_PLUGINOUT_DEBOUNCE), osTimerOnce, &app_battery_pluginout_debounce_ctx);

    // 设置电池测量状态为正常
    app_battery_measure.status = APP_BATTERY_STATUS_NORMAL;

    // 根据是否支持互联确定电池信息初始化
	......

    // 初始化电池电压参数
	......

    // 设置电池测量周期和回调函数
    ......

    // 初始化电池充电状态参数
    ......
    
    // 设置应用电池处理线程
    app_set_threadhandle(APP_MODUAL_BATTERY, app_battery_handle_process);

    // 配置外部充电器检测器引脚
    if (app_battery_ext_charger_detecter_cfg.pin != HAL_IOMUX_PIN_NUM)
    {
        hal_iomux_init((struct HAL_IOMUX_PIN_FUNCTION_MAP *)&app_battery_ext_charger_detecter_cfg, 1);
        hal_gpio_pin_set_dir((enum HAL_GPIO_PIN_T)app_battery_ext_charger_detecter_cfg.pin, HAL_GPIO_DIR_IN, 1);
    }

    // 配置外部充电器使能引脚
    if (app_battery_ext_charger_enable_cfg.pin != HAL_IOMUX_PIN_NUM)
    {
    	// 它将初始化引脚的复用功能,并设置引脚为输出模式,输出高电平
        hal_iomux_init((struct HAL_IOMUX_PIN_FUNCTION_MAP *)&app_battery_ext_charger_detecter_cfg, 1);
        hal_gpio_pin_set_dir((enum HAL_GPIO_PIN_T)app_battery_ext_charger_detecter_cfg.pin, HAL_GPIO_DIR_OUT, 1);
    }

    // 检测并处理充电状态
    if (app_battery_charger_indication_open() == APP_BATTERY_CHARGER_PLUGIN)
    {
        // 设置充电状态
        app_battery_measure.status = APP_BATTERY_STATUS_CHARGING;
        // 记录开始充电时间
        app_battery_measure.start_time = hal_sys_timer_get();
        // 配置充电器插入参数
		......

        // 根据充电器拔出重置配置返回值
		......
    }
    else
    {
        // 设置正常状态
        app_battery_measure.status = APP_BATTERY_STATUS_NORMAL;
        // 配置充电器拔出参数
		......
        // 设置返回值为正常模式
        ......
    }
    // 返回电池模块打开模式
    return nRet;
}

注意:该函数并不是完整的函数,只截取部分代码

  • 参数/函数讲解
序号 函数 说明
1 osTimerCreate(osTimerPeriodic) 创建电池电量检测定时器
2 osTimerCreate(osTimerOnce) 创建出入盒定时器,这个定时器一般用于处理电池插拔事件的去抖动,以防止误触发。
3 app_set_threadhandle() 设置电池模块的线程处理函数。这个函数在电池状态发生变化时被调用,用于处理相关的逻辑。
4 hal_iomux_init() 初始化GPIO引脚
5 hal_gpio_pin_set_dir() 设置对应的引脚,以及输出电平

1.3 app_audio_open()

这个函数的作用是初始化音频管理模块,并执行一些初始化操作,如铃声合并的初始化、设置线程处理函数、蓝牙音频流的初始化,并将初始化标志位置为 true。

  • 代码
c 复制代码
/**
 * @brief 打开应用音频模块
 * 
 * 该函数负责初始化应用音频模块。包括创建互斥量、内存池、音频列表等。
 * 如果音频模块已经初始化,则直接返回。否则,执行一系列初始化操作。
 */
void app_audio_open(void)
{
    // 检查音频模块是否已经初始化
    if(app_audio_init)
    {
        // 如果已经初始化,直接返回
        return;
    }

    // 创建音频队列互斥量
    if (g_app_audio_queue_mutex_id == NULL)
    {
        g_app_audio_queue_mutex_id = osMutexCreate((osMutex(g_app_audio_queue_mutex)));
    }
    else
    {
        // 如果互斥量ID已经存在,则断言失败
        ASSERT(0, "[%s] ERROR: g_app_audio_queue_mutex_id != NULL", __func__);
    }

    // 创建音频状态内存池
    if (app_audio_status_mempool == NULL)
        app_audio_status_mempool = osPoolCreate(osPool(app_audio_status_mempool));
    // 确保内存池创建成功
    ASSERT(app_audio_status_mempool, "[%s] ERROR: app_audio_status_mempool != NULL", __func__);

    // 根据编译选项,可能创建音频队列
	......

    // 根据编译选项,可能初始化提示列表
    ......

    // 初始化音频合并功能
    app_ring_merge_init();

    // 设置音频模块的处理线程
    app_set_threadhandle(APP_MODUAL_AUDIO, app_audio_handle_process);

    // 初始化蓝牙音频流
    app_bt_stream_init();

    // 标记音频模块已经初始化
    app_audio_init = true;
}

注意:该函数并不是完整的函数,只截取部分代码

  • 参数/函数讲解
序号 函数 说明
1 osMutexCreate() 创建一个互斥锁,用于保护音频队列的访问。
2 osPoolCreate() 创建一个内存池,用于存储音频状态。
3 app_ring_merge_init() 初始化混合提示音功能。铃声合并通常用于在设备同时需要播放多个声音时,将它们合并成一个声音输出,以防止声音混叠或干扰。
4 app_set_threadhandle() 设置音频模块的线程处理函数。这个函数可能会在音频状态发生变化时被调用,用于处理相关的逻辑。
5 app_bt_stream_init() 这个函数调用可能是用于初始化蓝牙音频流功能。在蓝牙设备中,这个函数可能会设置蓝牙音频相关的参数和配置。

<<【系列文章索引】>>


总结

**  感谢观看,这里就是 应用初始化 -- app_init() 的讲解,如果觉得有帮助,请给文章点个赞吧,让更多的人看到。🌹 🌹 🌹**

**  也欢迎你,关注我。👍 👍 👍**

**  原创不易,还希望各位大佬支持一下,你们的点赞、收藏和留言对我真的很重要!!!💕 💕 💕 最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!下期再见。🎉**

更多专栏订阅:

订阅更多,你们将会看到更多的优质内容!!

相关推荐
johnny_hhh42 分钟前
在Rocky Linux 9上部署NFS服务并对其进行权限配额管理以及监控
linux·运维·服务器
╰⋛⋋⊱⋋翅膀⋌⊰⋌⋚╯1 小时前
linux-下载抖音作品
linux
e调布鲁斯1 小时前
恢复Ubuntu+Windows10双系统安装前状态及分区还原详细步骤
linux·运维·ubuntu
Lin2012302 小时前
STM32 + CubeMX + 硬件SPI + W5500 +TcpClient
stm32·单片机·嵌入式硬件
极客小张2 小时前
基于STM32的智能温室环境监测与控制系统设计(代码示例)
c语言·arm开发·stm32·单片机·嵌入式硬件·物联网·毕业设计
玉树临风江流儿2 小时前
STM32标准库-待机模式
stm32·单片机·嵌入式硬件
程序猿进阶3 小时前
系统上云-流量分析和链路分析
java·后端·阿里云·面试·性能优化·系统架构·云计算
demodashi6663 小时前
ARM64的Mac Node.js前置工作,nvm在线安装
linux·运维·macos
这题怎么做?!?3 小时前
【Linux】网络编程:实现一个简易的基于HTTP协议格式、TCP传输的服务器,处理HTTP请求并返回HTTP响应;GET方法再理解
linux·服务器·c语言·网络·c++·tcp/ip·http
vvw&4 小时前
使用Ubuntu快速部署MinIO对象存储
linux·运维·服务器·ubuntu·minio·cos·oss