【BES2500x系列 -- RTX5操作系统】系统执行流程 -- 系统初始化 -- main函数 --(十一)

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

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

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

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

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

文章目录

  • 前言
  • [1 系统初始化](#1 系统初始化)
      • [1.1 系统启动(System Startup)](#1.1 系统启动(System Startup))
      • [1.2 系统 main 函数](#1.2 系统 main 函数)
  • 总结

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

前言

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

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

专栏地址:【BES2500x系列】, 此专栏是我是夜阑的狗对BES2500x系列开发过程的总结,希望能够加深自己的印象,以及帮助到其他的小伙伴😉😉。

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


1 系统初始化

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

1.1 系统启动(System Startup)

mian 函数不再以一个线程的形式运行,因此在 main 函数运行之前,RTX5 不会干预系统的启动。main 函数运行之后,推荐按照以下的流程初始化硬件并启动内核:

Step1 、硬件的初始化和配置,包括外设,内存,引脚,时钟和中断系统。

Step2 、使用 CMSIS-Core 函数更新系统核心时钟。

Step3 、使用 osKernelInitialize 函数初始化 CMSIS-RTOS 内核。

Step4 、使用 osThreadNew 函数创建一个主线程(例如 app_mian ),然后在这个线程中创建和启动对象。当然也可以直接在main函数中创建和启动对象。

Step5 、使用 OSKernelStart 启动 RTOS 调度器,该函数会配置 system tick定时器以及初始化 RTOS 相关中断。如果这个函数运行成功,则不会在返回,因此该函数之后的代码将不会被执行。

🚨 🚨 🚨 注意:在上述流程之后,不推荐应用程序修改NVIC的优先级和分组;在执行 osKernelStart 之前,只能调用 osKernelGetInfoosKernelGetState 和对象创建函数(osXxxNew)。

  • 代码
c 复制代码
__WEAK void software_init_hook (void) {
    __asm (
      ".syntax unified\n"
      ".thumb\n"
      "movs r0,#0\n"
      "movs r1,#0\n"
      "mov  r4,r0\n"
      "mov  r5,r1\n"
      "bl   SystemCoreClockUpdate\n"
      "bl   osKernelInitialize\n"
      "ldr  r0,= __libc_fini_array\n"
      "bl   atexit\n"
      "bl   __libc_init_array\n"
      "mov  r0,r4\n"
      "mov  r1,r5\n"
      "bl   set_main_stack\n"
      "ldr  r0,=main\n"
      "movs r1,#0\n"
      "ldr r2,=os_thread_attr_main\n"
      "bl   osThreadNew\n"
      "bl   osKernelStart\n"
      "bl   exit\n"
    );
}
  • 参数/函数讲解

这段代码是一个软件初始化钩子函数,使用了 __WEAK 关键字,表示这是一个弱符号,允许在其他地方重新定义同名函数。函数内部包含了一段嵌入式汇编代码,执行了一系列初始化操作,主要用于系统启动时进行一些必要的初始化工作。

序号 汇编指令 说明
1 .syntax unified 和 .thumb 指定汇编语法和指令集。在这里,使用了 Thumb 指令集。
2 movs r0,#0movs r1,#0 用于将寄存器 r0 和 r1 中的值设置为 0。
3 mov r4,r0mov r5,r1 将 r0 和 r1 中的值分别复制到 r4 和 r5 寄存器中。
4 bl SystemCoreClockUpdate 调用 SystemCoreClockUpdate 函数更新系统核心时钟。
5 bl osKernelInitialize 调用 osKernelInitialize 函数初始化操作系统内核。
6 ldr r0,= __libc_fini_array 加载 __libc_fini_array 的地址到寄存器 r0。
7 bl atexit 调用 atexit 注册退出处理函数。
8 bl __libc_init_array 调用 __libc_init_array 函数初始化 C 库数组。
9 mov r0,r4 将 r4 中的值分别复制回 r0 寄存器中。
10 mov r1,r5 将 r5 中的值分别复制回 r1 寄存器中。
11 bl set_main_stack 调用 set_main_stack 函数设置主栈。
12 ldr r0,=main 加载 main 函数的地址到寄存器 r0,并调用 osThreadNew 创建主线程。
13 movs r1,#0 将常量值 0 移动到寄存器 r1
14 ldr r2,=os_thread_attr_main 加载 os_thread_attr_main 的地址到寄存器 r2
15 bl osThreadNew 调用 osThreadNew 创建主线程,这个过程用于初始化操作系统的线程环境,将 main 函数作为新线程的入口点。
16 bl osKernelStart 调用 osKernelStart 启动操作系统内核。
17 bl exit 调用 exit 函数以退出程序

1.2 系统 main 函数

执行完成这些创建好主线程后,就能来到 main 函数了,因为第一个线程os_thread_attr_main 就是 main,可以在 main.cpp 文件中看到该 main 函数。

  • 代码

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

c 复制代码
int main(void)
{
    uint8_t sys_case = 0;
    int ret = 0;
#if !defined(BLE_ONLY_ENABLED)
    app_wdt_open(15);
#else
    app_wdt_open(30);
#endif
	......省略后续
	......
}
  • 参数/函数讲解

main 函数详细讲解,这些函数调用涉及到了系统的初始化、配置以及关机过程的一些操作:

序号 参数/函数 说明
1 app_wdt_open(30) 开启打开应用程序看门狗定时器,间隔为30秒;
2 tgt_hardware_setup() 硬件初始化,输入输出IO初始化;
3 osThreadGetId() 返回当前线程ID;
4 hwtimer_init(void) 初始化硬件定时器,用于在系统中进行定时操作或者时钟管理;
5 hal_dma_set_delay_func 设置了一个 DMA(Direct Memory Access,直接内存访问)延迟函数,它将 osDelay 函数作为参数传入。这通常是为了在 DMA 操作中引入延迟,以便与其他系统操作进行同步。
6 hal_audma_open() 初始化音频 DMA,即用于音频数据传输的 DMA 控制器。
7 hal_gpdma_open() 初始化通用 DMA(General Purpose DMA,通用目的 DMA),用于处理非音频数据的高速数据传输。
8 norflash_api_init() 初始化 NOR Flash 存储器,把 flash 中从 0 到NORFLASH_API_MODULE_ID_COUNT 的空间清零,以便系统能够正确地与 NOR Flash 进行通信和操作。
9 hal_iomux_set_uart0() 设置 UART0 的 I/O 多路复用(I/O Multiplexing),以确保 UART0 的引脚正确配置为 UART 功能,从而可以进行串口通信
10 hal_trace_open 打开了追踪功能,并指定了 UART0 作为传输通道。追踪功能通常用于在调试或日志记录时输出系统状态、错误信息等,简单点就是打开串口。
11 hal_iomux_ispi_access_init() 初始化 SPI(Serial Peripheral Interface,串行外设接口)的 I/O 多路复用,以确保 SPI 接口的引脚正确配置,并且可以被使用。
12 hal_iomux_ispi_access_disable() 禁用 SPI 接口的访问。可能在某些情况下,系统需要在初始化时先禁用 SPI 接口,待需要时再启用。
13 pmu_open() 初始化电源管理单元(PMU),以便系统能够正确管理电源,包括电池管理、供电管理等。
14 analog_open() 初始化模拟外设,例如模拟输入输出、模拟信号处理等。
15 mpu_setup() 设置 MPU(Memory Protection Unit,内存保护单元),以保护系统的内存不受未经授权的访问和修改。具体操作是先open mpu() 然后mpu_init_table() ,mpu_fast_ram_protect()
16 srand(hal_sys_timer_get()) 设置了随机数发生器的种子,通常使用系统时钟来生成一个初始种子,以便在后续的随机数生成中产生不同的随机序列。
17 app_audio_buffer_check() 检查音频缓冲区的状态,以确保音频数据的准备和处理工作正常进行。
18 app_init() 应用程序的初始化函数,用于执行应用程序的各种初始化任务,例如初始化变量、配置参数等。
19 system_shutdown_wdt_config(10) 配置了系统的看门狗定时器(Watchdog Timer,WDT),设置了定时器的超时时间为10秒。看门狗定时器通常用于监视系统运行状态,如果系统出现异常或停滞,超过了设置的时间,系统会自动重启以恢复正常运行。
20 app_deinit(ret) 在应用程序结束时进行一些清理工作,
21 hal_sw_bootmode_clear() 清除软件引导模式(Software Boot Mode)的状态,以确保系统下次启动时不会处于特定的引导模式下。
22 pmu_shutdown() 关闭电源管理单元(PMU),以准备系统关机。

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


总结

**  感谢观看,这里就是 系统初始化 -- main函数的讲解,如果觉得有帮助,请给文章点个赞吧,让更多的人看到。🌹 🌹 🌹**

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

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

更多专栏订阅:

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

相关推荐
小狗爱吃黄桃罐头43 分钟前
江协科技STM32学习- P14 示例程序(定时器定时中断和定时器外部时钟)
stm32·江科大stm32
@@庆1 小时前
stm32 PWR电源控制(修改主频&睡眠模式&停机模式&待机模式)
stm32·单片机·嵌入式硬件
JT灬新一1 小时前
STM32巡回研讨会总结(2024)
stm32·单片机·嵌入式硬件
傻傻虎虎13 小时前
【系统架构设计】信息系统基础知识
系统架构
有颜有货14 小时前
低代码开发平台系统架构概述
低代码·系统架构
z2014z14 小时前
系统架构设计师教程 第5章 5.3 系统分析与设计 笔记
笔记·系统架构
辰哥单片机设计15 小时前
门磁模块详解(防盗感应开关 STM32)
stm32·单片机·嵌入式硬件·传感器
yrx02030716 小时前
stm32 IIC总线busy解决方法
stm32·单片机·嵌入式硬件
h1771134720517 小时前
基于区块链的相亲交易系统源码解析
大数据·人工智能·安全·系统架构·交友
Liii40318 小时前
【ARM】中断的处理
arm开发·arm