rt-thread内核启动分析

2023-05-16

1.项目准备

上一节的基本环境,如rh-thread 基本环境的搭建,硬件材料stm32f103C8T6 以及st-link
rt-thread 内核启动官网分析
在分析rt-thread代码的时候,由于rt-thread的代码是十分优秀的,你完全不需要看每个函数实现的细节,就根据每个函数名字,可以分析出这个函数是干什么用的.

2.内核单步调试

在这里插入图片描述

如图程序从stm32 汇编入口开始启动,单步执行代码,会跳转到rt-thread内核启动的方法里面,为int S u b Sub Sub$main(void)函数里面代码如下:
int $Sub$$main(void)
{
    rt_hw_interrupt_disable();
    rtthread_startup();
    return 0;
}
rt_hw_interrupt_disable()读名字,为禁止硬件中断
rtthread_startup();读名字,为rt-thread开始启动

在继续单步调试,rtthread_startup()函数其代码如下:

int rtthread_startup(void)
{
    rt_hw_interrupt_disable();

    /* board level initalization
     * NOTE: please initialize heap inside board initialization.
     */
    rt_hw_board_init();

    /* show RT-Thread version */
    rt_show_version();

    /* timer system initialization */
    rt_system_timer_init();

    /* scheduler system initialization */
    rt_system_scheduler_init();

#ifdef RT_USING_SIGNALS
    /* signal system initialization */
    rt_system_signal_init();
#endif

    /* create init_thread */
    rt_application_init();

    /* timer thread initialization */
    rt_system_timer_thread_init();

    /* idle thread initialization */
    rt_thread_idle_init();

    /* start scheduler */
    rt_system_scheduler_start();

    /* never reach here */
    return 0;
}
可以发现每个函数上面都有注释,而且见函数名,我们大致都知道每个函数的作用了,具体分析可以见rt-thread官网内核分析
这里对 rt_hw_board_init();进行单步调试分析,单步进入 rt_hw_board_init()函数里面,可以看见起代码如下:
void rt_hw_board_init(void)
{
    HAL_Init();
    SystemClock_Config();
#ifdef RT_USING_HEAP
    rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END);
#endif
#ifdef RT_USING_COMPONENTS_INIT
    rt_components_board_init();
#endif
#ifdef RT_USING_CONSOLE
    rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif
}
还是看函数名字,我们就知道每个函数是什么用的
函数作用
HAL_Init()HAL库的初始化
SystemClock_Config()systick时钟初始化
rt_system_heap_init()系统内存堆的初始化
rt_components_board_init();board级组件的初始化
rt_console_set_device()为console设置一个设备(此处命令行用输入输出通过串口)
分析 rt_components_board_init(); 函数代码如下:
void rt_components_board_init(void)
{
#if RT_DEBUG_INIT
    int result;
    const struct rt_init_desc *desc;
    for (desc = &__rt_init_desc_rti_board_start;
   				  desc < &__rt_init_desc_rti_board_end; desc ++)
    {
        rt_kprintf("initialize %s", desc->fn_name);
        result = desc->fn();
        rt_kprintf(":%d done\n", result);
    }
#else
    const init_fn_t *fn_ptr;

    for (fn_ptr = &__rt_init_rti_board_start; 
    				fn_ptr < &__rt_init_rti_board_end; fn_ptr++)
    {
        (*fn_ptr)();
    }
#endif
}
此处没有定义宏RT_DEBUG_INIT,因此代码执行
   const init_fn_t *fn_ptr;

    for (fn_ptr = &__rt_init_rti_board_start; 
    				fn_ptr < &__rt_init_rti_board_end; fn_ptr++)
    {
        (*fn_ptr)();
    }
个人认为此处是rt-thread代码写的精彩的地方之一.
此处可以发现__rt_init_rti_board_start,以及__rt_init_rti_board_end从来没有定义过,但是可以编译通过,甚至调试,这里面肯定内有乾坤
const init_fn_t *fn_ptr;此处定义了一个指针 fn_ptr,在for循环里面,有(fn_ptr)();这行代码典型的函数调用代码,因此fn_ptr指针指向的是一个函数,而&__rt_init_rti_board_start肯定是一个函数的地址.继续单步调试,看栈里面fn_ptr值如图所示:在这里插入图片描述
可以发现fn_ptr指向函数,rti_board_start();这个函数在这里有定义了,其定义如下:
static int rti_board_start(void)
{
    return 0;
}
INIT_EXPORT(rti_board_start, "0.end");
观察这个几行代码,INIT_EXPORT(rti_board_start, “0.end”);这个有点像函数的调用,但是在此处,有不是在函数里面,这么可能进行函数调用?打开这个INIT_EXPORT();go to definition 去定义这个函数的地方,其定义如下:
#define INIT_EXPORT(fn, level)                          \
    				 RT_USED const init_fn_t __rt_init_##fn SECTION(".rti_fn."level) = fn
	其中RT_USED定义为
	#define RT_USED                     __attribute__((used))
	#define SECTION(x)                  __attribute__((section(x)))
因此这句宏定义代码的意思为:

定义一个变量为 const init_fn_t rt_init_rti_board_start,这个变量的位置通过__attribute((section(x)))来指定,即放在程序段".rti_fn.0.end"里面,并且指向rti_board_start()这个函数.而且此处在编译阶段就完成的过程.具体解释可以查看 attribute((section(x)))的用法

因此for循环里面的变量,__rt_init_rti_board_start变量实际上通过 INIT_EXPORT(fn, level) 宏来定义的,继续单步,你会发现,只要通过这个宏定义的内容,将在编译阶段形成一个地址段,这里面的指针指向的就是一个函数,如下此处分别指向如下函数:

rti_board_start();
rt_hw_pin_init();
rt_hw_usart_init();
rti_board_end();

以上这4个函数,在编译的时候,就按照这个顺序进行地址的分配,也就是说这个四个函数的地址是连续的,因此可以用for循环来进行遍历.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

rt-thread内核启动分析 的相关文章

  • 技术分享 | GPS无人机集群

    随着人工智能的发展 xff0c 机器人行业也进入了高速发展的阶段 xff0c 在今年春晚 xff0c 也出现了无人机的身影 xff0c 在高速发展的同时 xff0c 也让人们逐渐体会到单机器人能做的事情是有限的 xff0c 多机器人 编队
  • 技术分享 | 开源不稳?试试DJI N3飞控呢

    原创阿木实验室 1 DJI N3飞控简介 N3内置双IMU冗余设置 xff0c 结合在线故障检测算法 xff0c 可实现双IMU数据实时互为备份 xff0c 极大地提高了飞行器可靠性 集成8GB工业级SD卡的 黑匣子 数据记录系统 xff0
  • 技术分享 | P450-详解室内外指点飞行来啦

    原理说明 PX4飞控控制系统图 定点飞行就是由传感器 xff08 T265 GPS xff09 获得当前位置数据 xff0c 并且把当前位置作为期望位置 xff0c 即可实现定点飞行 xff0c 此时飞控处于position模式 指点飞行为
  • 技术分享 | P450-圆框跟踪的干货分享

    圆检测流程 xff1a 1 xff0c 利用高斯滤波做预处理 2 xff0c 边界检测部分用到了自适应Canny检测 3 xff0c 将边界分为凹弧和凸弧 xff0c 根据输入参数筛选弧段 4 xff0c 利用弧段来估计椭圆参数 xff0c
  • Linux Xampp 下安装PHP Redis扩展

    cd usr local wget http pecl php net get redis 4 0 1 tgz tar zxvf redis 4 0 1 tgz cd usr local wget http mirrors kernel o
  • 技术分享 | Prometheus(P450)-室内外避障

    原理说明 Astar进行全局路径规划 全局路径规划 1 全局算法和局部算法 全局路径规划是在已知的环境中 xff0c 给机器人规划一条路径 xff0c 路径规划的精度取决于环境获取的准确度 xff0c 全局路径规划可以找到最优解 xff0c
  • PX4官方动态 | 基于FPGA和px4的精准自主降落

    近期Ramon Roche在Twitter上发布了关于使用FPGA实现无人机在目标物体上能够进行精准自主着陆的推文 这次的功能实现是一个在读博士的学生所做的项目 xff0c 希望能在开源社区中得到推广并吸引其余有意向的开发者能一起进行研究
  • 技术分享 | 带你具体部署VINS_FUSION_GPU版本

    前期准备工作已经完成 xff0c 接下来我们就准备VINS在NX的落地 1 下载源码编译 首先VINS gpu版本需要引入OpenCV CUDA版本的加速 xff0c 由于我们的NX镜像已经安装好CUDA xff0c 这里就不在赘叙 xff
  • PX4官方动态 | 带你走进官方教学(二)

    本期是我们第二期官方教学 xff0c 不知道大家有没有跟着我们一起学习第一期的教学呢 xff0c 如果没有看过的同学可以点击链接进行第一期的学习后再来看我们第二期内容 在第一期我们告诉了大家学习方法 xff0c 以及如果从零开始使用PX4自
  • 吊舱追踪 | 车机协同作战小实验

    大家好 xff0c 我是阿木实验室的梓衡 xff0c 今天为大家带来的是我们最新研发的智能吊舱的测试 首先 xff0c 我们会把小吊舱挂载在P450无人机上 xff0c 我们所选择的地面追踪目标是我们的R300无人车 这个吊舱搭载了200W
  • 工实小报 | P450室外首飞教学

    本文将给大家介绍我们P450无人机在进行室外首次飞行时 xff0c 一些常见的注意事项及正确的使用方法 我们在使用这种PX4开源无人机时 xff0c 一定要有一个清楚的认识 它和大疆那种消费级无人机在使用和操作上 xff0c 是有非常大的不
  • 5G时代,将为无人机通讯传输带来哪些新变化?

    众所周知 xff0c 我们正在大步迈向5G时代 xff0c 在近几年的各类媒体关于5G的报道也络绎不绝 与此同时 xff0c 无人机作为空中人工智能领域的 智慧眼 xff0c 其行业应用迅速发展 xff0c 应用需求不断增加 xff0c 对
  • 超小型吊舱它来了,轻松适配多种移动机器人使用场景

    一 设计理念 在无人机 无人车 机器狗等移动机器人场景中 xff0c 往往需要一款小巧 重量轻 成本可控的三轴云台吊舱来实现无人机的航拍 机器人搜寻以及图像识别等功能 而市面上的云台吊舱体积都比较大 xff0c 一些小型增稳云台也不支持角度
  • P600旗舰视觉款正式发布,重新定义视觉追踪与精准定位!

    P600旗舰视觉款无人机是一款准行业级无人机 xff0c 搭载RTK定位系统 xff0c 定位精度可达厘米级 xff0c 飞行路径更精准 姿态更稳定 xff1b 机身搭载Allspark机载计算机 xff0c 算力可达21TOPS xff0
  • [STM32学习笔记1]GPIO初始化,点亮LED

    一 使用STM32cubeMX新建工程并初始化 1 打开STM32cubeMX并新建工程 xff0c 芯片输入STM32F103C8T6 双击芯片进入配置界面 xff0c 首先选择调试方式SYS gt debug gt serial wir
  • 开发人员调试IE9默认IE7模式打开

    IE9的默认就是IE9标准模式啊 xff0c 你可能是启用了组策略里的 打开Internet Explorer 7标准模式 功能 禁用就行 开始菜单 运行 输入gpedit msc后确定 用户设置 管理模板 Windows组件 Intern
  • visual studio屏蔽掉一段代码的组合键

    注释 xff1a Ctrl 43 k 43 c 取消注释 xff1a Ctrl 43 k 43 u
  • 如何在VS Code中运行C或C++程序

    前言 众所周知 xff0c VS Code源代码编辑器 xff0c 是目前最为流行的代码开发工具之一 xff0c 特别受到Web前端开发者的青睐 xff0c 当然还有大名鼎鼎的HBuilder X也是非常给力的 xff0c 我们可以根据自己
  • C语言指针作为形参的一些问题

    C语言中指针是个非常麻烦的事件 xff0c 本人大学学了几年指针 xff0c 用起来还是丈二和尚 xff0c 摸不着头脑 xff0c 特别是在函数中作为参数传递 xff0c 申请空间什么的 xff0c 一头雾水 xff0c 看到这篇文件写的
  • visual studio的cpp文件添加c文件的extern变量出错原因解析

    比如extern这个变量报这个错 xff1a 说这个来自c文件的extern变量为无法解析的外部符号 可以考虑将cpp文件后缀名改成c文件 xff0c 或者加个extern 34 C 34 就可以解决了 xff01 xff01

随机推荐