1. 总结RT-Thread的启动流程。
  2. 非运行时与运行时的image文件分别是什么样的,请画下来。是谁将 RW 段中的  RW-data(初始化的全局变量)搬运到 RAM 中?
  3. MDK环境下各种数据段存储的什么数据?
  4. 在RT-Thread启动时,关了中断,那么在什么时候开启的中断?
  5. 总结自动初始化原理。
  6. 总结BSP制作过程。

1RT-Thread启动流程

 

这部分启动代码,大致可以分为四个部分:

(1) 初始化与系统相关的硬件;

(2) 初始化系统内核对象,例如定时器、调度器、信号;

(3) 创建 main 线程,在 main 线程中对各类模块依次进行初始化;

(4) 初始化定时器线程、空闲线程,并启动调度器。

启动流程中蓝色部分是自动初始化的数据段,使用自动初始化宏导出的函数放置到相应的数据段,在启动流程中对函   数进行遍历初始化。2、加载时地址与运行时地址映射

image文件

STM32 在上电启动之后默认从 Flash 启动,启动之后会将 RW 段中的 RW-data(初始化的全局变量)搬运到 RAM 中,但不会搬运 RO 段,即 CPU 的执行代码从 Flash 中读取,另外根据编译器给出的 ZI 地址和大小分配出 ZI 段,并将这块 RAM 区域清零。

分散装载配置文件里会有配置,关于code的地址,有两个设置,一个是存储地址(这个地址配置的是烧写器把代码  段写到flashrom的何处),一个是装载运行地址,也就是你程序在什么地方运行

【如果想要深入了解的话,可以看看arm的连接器手册,或者是《ARM体系结构与编程》中也讲到了】

3MDK环境下各种数据段存储的什么数据?

code:代码段,存放程序

RO:只读数据段,存放程序中定义的常量RW:读写数据段,存放非0全局变量

ZI:0数据段,存放未初始化的全局变量与初始化为0的变量

MDK 在编译完成之后

Total RO Size (Code + RO Data) 53668 ( 52.41kB) Total RW Size (RW Data + ZI Data) 2728 ( 2.66kB)

Total ROM Size (Code + RO Data + RW Data) 53780 ( 52.52kB)

1) RO Size 包含了 Code 及 RO-data,表示程序占用 Flash 空间的大小;

2) RW Size 包含了 RW-data 及 ZI-data,表示运行时占用的 RAM 的大小;

3) ROM Size 包含了 Code、RO Data 以及 RW Data,表示烧写程序所占用的 Flash 空间的大小;

4、在RT-Thread启动时,关了中断,那么在什么时候开启的中断?

在启动调度器,切换到第一个线程时开启的中断【直接使用CPSIE I 开了中断的】。代码详见:

rt_system_scheduler_start() rt_hw_context_switch_to((rt_ubase_t)&to_thread->sp);

5、总结自动初始化原理。

RT-Thread 的自动初始化机制使用了自定义 RTI  符号段,将需要在启动时进行初始化的函数指针放到了该段中,形成一张初始化函数表,在系统启动过程中会遍历该表,并调用表中的函数,达到自动初始化的目的。

用来实现自动初始化功能的宏接口定义详细描述如下表所示:

初始化顺序

宏接口

描述

1

INIT_BOARD_EXPORT(fn)

非常早期的初始化,此时调度器还未启动

2

INIT_PREV_EXPORT(fn)

主要是用于纯软件的初始化、没有太多依赖的函数

3

INIT_DEVICE_EXPORT(fn)

外设驱动初始化相关,比如网卡设备

4

INIT_COMPONENT_EXPORT(fn)

组件初始化,比如文件系统或者 LWIP

5

INIT_ENV_EXPORT(fn)

系统环境初始化,比如挂载文件系统

6

INIT_APP_EXPORT(fn)

应用初始化,比如 GUI 应用

初始化函数主动通过这些宏接口进行申明,如 INIT_BOARD_EXPORT(rt_hw_usart_init),链接器会自动收集所有被申明的初始化函数,放到 RTI 符号段中,该符号段位于内存分布的 RO 段中,该 RTI 符号段中的所有函数在系统初始化时会被自动调用。

原理:

在rtdef.h中,使用SECTION(x)定义: 

#define SECTION(x)  attribute ((section(x)))

attribute ((section("name"))):将作用的函数或数据放入指定名为"name"的输入段中。(在不同的编译器中实现的方式也有所不同。)

将SECTION(".rti_fn."level)使用 INIT_EXPORT(fn, level) 这个宏进行定义,fn是函数

#define INIT_EXPORT(fn, level)  RT_USED const init_fn_t rt_init_##fn SECTION(".rti_fn."level) = fn

分段:

compnents.c中:

static int rti_start(void)
{
return ;
}
INIT_EXPORT(rti_start, ""); static int rti_board_start(void)
{
return ;
}
INIT_EXPORT(rti_board_start, "0.end"); static int rti_board_end(void)
{
return ;
}
INIT_EXPORT(rti_board_end, "1.end"); static int rti_end(void)
{
return ;
}
INIT_EXPORT(rti_end, "6.end");

所以就有:

段名

函数指针/

.rti_fn.0

rt_init_rti_start

.rti_fn.0.end

rt_init_rti_board_start

.rti_fn.1

INIT_BOARD_EXPORT(fn)

.rti_fn.1.end

rt_init_rti_board_end

.rti_fn.2

INIT_PREV_EXPORT(fn)

.rti_fn.3

INIT_DEVICE_EXPORT(fn)

.rti_fn.4

INIT_COMPONENT_EXPORT(fn)

.rti_fn.5

INIT_ENV_EXPORT(fn)

.rti_fn.6

INIT_APP_EXPORT(fn)

.rti_fn.6.end

rt_init_rti_end

非调试模式下rt_components_board_init():for循环会遍历位于 rt_init_rti_board_start 到

rt_init_rti_board_end 之间保存的函数指针,然后依次执行这些函数

void rt_components_board_init(void)
{
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_components_init():for循环会遍历位于  rt_init_rti_board_end 到  rt_init_rti_end 之间保存的函数指针,然后依次执行这些函数

void rt_components_init(void)
{
const init_fn_t *fn_ptr; for (fn_ptr = & rt_init_rti_board_end; fn_ptr < & rt_init_rti_end; fn_ptr ++)
{
(*fn_ptr)();
}
#endif
}

举例:

main函数中添加了函数pin_beep_sample(),并使用INIT_APP_EXPORT()进行自动初始化。

INIT_APP_EXPORT(pin_beep_sample);

那么,展开为:

INIT_APP_EXPORT(pin_beep_sample) 即 INIT_EXPORT(pin_beep_sample, "6")

也就是

const init_fn_t rt_init_pin_beep_sample SECTION(".rti_fn.""") = pin_beep_sample

表示把函数pin_beep_sample的地址赋值给常量函数指针 rt_init_pin_beep_sample,然后放入名称为".rti_fn.6"的数据段中。(其中init_fn_t是一个函数指针类型,原型为typedef int (*init_fn_t)(void) 。)

在编译后的.map文件中可以查看到:

Symbol Name Value Ov Type Size Object(Section)

RTT学习之启动流程的更多相关文章

  1. activiti学习6:启动流程后动态获取流程图

    目录 activiti学习6:启动流程后动态获取流程图 一.绘图原理 二.根据流程定义id绘图 三.根据流程实例id绘图 3.1 基本原理 3.2 当前节点的获取 3.3 走过的节点的获取 3.4 绘 ...

  2. Android FM模块学习之一 FM启动流程

    最近在学习FM模块,FM是一个值得学习的模块,可以从上层看到底层. 上层就是FM的按扭操作和界面显示,从而调用到FM底层驱动来实现广播收听的功能. FM启动流程:如下图: 先进入FMRadio.jav ...

  3. ASP.NET Core MVC 源码学习:MVC 启动流程详解

    前言 在 上一篇 文章中,我们学习了 ASP.NET Core MVC 的路由模块,那么在本篇文章中,主要是对 ASP.NET Core MVC 启动流程的一个学习. ASP.NET Core 是新一 ...

  4. nginx学习十一 nginx启动流程

    今天用了一天的时间看nginx的启动流程,流程还是非常复杂.基本的函数调用有十几个之多.通过看源代码和上网查资料,弄懂了一些函数.有些函数还在学习中,有些函数还待日后学习,这里记录一下今天所学.加油! ...

  5. dubbo源码学习(一)dubbo容器启动流程简略分析

    最近在学习dubbo,dubbo的使用感觉非常的简单,方便,基于Spring的容器加载配置文件就能直接搭建起dubbo,之前学习中没有养成记笔记的习惯,时间一久就容易忘记,后期的复习又需要话费较长的时 ...

  6. 嵌入式Linux驱动学习之路(五)u-boot启动流程分析

    这里说的u-boot启动流程,值得是从上电开机执行u-boot,到u-boot,到u-boot加载操作系统的过程.这一过程可以分为两个过程,各个阶段的功能如下. 第一阶段的功能: 硬件设备初始化. 加 ...

  7. Tomcat学习 HttpConnector和HttpProcessor启动流程和线程交互

    一.tomat启动流程 1.启动HttpConnector connector等待连接请求,只负责接受socket请求,具体处理过程交给HttpProcessor处理. tomcat用户只能访问到co ...

  8. ThinkPHP5.0源码学习之框架启动流程

    ThinkPHP5框架的启动流程图如下: ThinkPHP5的启动流程按照文件分为三步: 1.请求入口(public/index.php) 2.框架启动(thinkphp/start.php) 3.应 ...

  9. Centos的启动流程学习

    Centos 6 的启动流程: POST ---> Boot sequence(BOIS) ---> Boot loader (MBR) --->  kernel(ramdiskfs ...

随机推荐

  1. [BJWC2010] 外星联络 - 后缀数组

    [BJWC2010] 外星联络 Description 求一个 \(01\) 串中所有重复出现次数大于 \(1\) 的子串所出现的次数,按照字典序排序输出. Solution 预处理出后缀数组和高度数 ...

  2. C# 获取变量的指针(IntPtr)

     1. 获取数组的指针(IntPtr) 通过Marshal.UnsafeAddrOfPinnedArrayElement(Array,Int32)方法获得一个数组的第某个元素的内存地址. Array是 ...

  3. 一次列表页伪静态的实现;结合nginx rewrite

    nginx伪静态: rewrite ^/(.*)-htm-(.*)$ /$1.php?$2; 将 list-html-t-3-p-4.html 转到list.php?t-3-p-4 t-3-p-4 用 ...

  4. Request功能

    1.获取请求消息数据 获取请求行数据 获取请求头数据 获取请求体数据 请求空行没必要获取 1.获取请求行数据 GET /虚拟目录 /servlet路径  ?请求参数 HTTP/1.1 GET/day1 ...

  5. 【原】mac电脑保存服务器账号/密码登录操作

    一.说明 mac电脑自带终端神奇iterm2,日常登录服务器操作一般场景为ssh user@ip,确认后再输入密码操作. 该操作较为麻烦且需通过hostname判断所在主机. 通过ssh生成秘钥方式较 ...

  6. sqlserver数据库导入大批量数据

    参考: https://www.cnblogs.com/zhangliangzlee/p/3585862.html

  7. 2019牛客多校第二场F Partition problem 暴力+复杂度计算+优化

    Partition problem 暴力+复杂度计算+优化 题意 2n个人分成两组.给出一个矩阵,如果ab两个在同一个阵营,那么就可以得到值\(v_{ab}\)求如何分可以取得最大值 (n<14 ...

  8. 一些 NuGet 程序包是使用不同于当前目标框架的目标框架安装的,可能需要重新安装

    如果 NuGet 检测到包受到重定向或升级项目的影响,它会将 packages.config 中的 requireReinstallation="true" 属性添加到所有受影响的 ...

  9. python开发基础03-列表、元组、字典、集合操作方法汇总

    列表 创建列表: li = [1, 12, 9, "age", ["石振文", ["19", 10], "庞麦郎"], ...

  10. 【安卓逆向】反编译ELF的另类技巧

    IDA 反编译 ObjDump反编译 ObjDump是ndk环境自带的一个脚本,在android-ndk-r10c/toolchains/arm-linux-androideabi-4.9/prebu ...