1.首先了解一些背景知识:
    (1)实时操作系统通常都会有最基础的内核( Kernel )以及扩展模块,例如文件系统、网络协议栈和应用、设备驱动程序等模块。

    (2)嵌入式软件自底向上依次为:Driver、BSP、Middleware、Application
    驱动(Driver):与特定架构、SoC 型号相关的驱动程序。通过对寄存器操作的 C 封装,提供了对片内外设的直
    接访问。也称作硬件抽象层 HAL。
    板级支持包(BSP):与特定开发板、电路相关的程序,通常完成片内外设的时钟配置和初始化,需要根据你的
    电路情况进行调整。
    中间件(Middleware):实现了设备之间的通信协议或其他功能库,如 lwIP 库和 FatFs 库。

    (3)要在某个开发板上运行 RTOS(称为“移植”),你需要把该厂商提供的驱动放入工程,然后自己实现 BSP。
    推荐使用 RT-Thread 是因为它的代码仓库里面已经带了很多种 SoC 型号的 BSP,这样基本上你就不用自己移植 官方的 BSP,只需要调用 API 即可。

    (4)Cortex-M 处理器发生中断时,CPU 自动从中断向量表中寻找相应的中断服务程序并跳转。

    (5)时间片
    当多个线程的**优先级相同**时,调度器将按线程分配到的时间片轮流执行。
    对于 Cortex-M 处理器,在硬件初始化时,配置 SysTick 以产生固定周期的时钟中断(且中断优先级为最低)。
    时间片起到约束单次运行时长的作用 轮流进行

    (6)以 _init 结尾的初始化函数是静态的,需要手动指定存储空间,如 rt_thread_init();以 _create 结尾的函数是动态的,通过堆分配器动态创建对象,如 rt_thread_create()。

    (7)RT-Thread 中,空闲线程是在系统初始化时创建的优先级最低的线程。

    (8)每个线程都内置一个定时器,当线程需要延时时(通过 rt_thread_delay(tick) 函数),先将线程挂起,将定时器插入全局的系统定时器列表 rt_timer_list,节点按延时时间长度升序排列。在中断服务程序中将更新系统 tick 计数器,并检查是否有线程的时间片用完,或者有线程的状态就绪,则进行调度。
    (如果使用 ST 公司的 HAL 库而非 stdPeriph 库,要注意 HAL 中的延时是通过 SysTick 实现的,会和 RT-Thread 冲突。因此需要覆盖 HAL 中的三个 __weak 函数:HAL_InitTick()、HAL_GetTick()、HAL_Delay(),通过利用 Cortex-M 的 DWT(Data Watchpoint and Trace)外设中的 CYCCNT 计数器来实现)

    (9)静态内存管理和动态内存管理的区别:是否在编译期栈、线程对象等所需的空间(动态在运行期才确定)

    (10)$Sub$$main() 函数将在 main 执行前被调用。
    RT-Thread 在 $Sub$$Main() 中调用了 rtthread_startup() 函数:

    RTT学习笔记(一) - 图1

    (11)当添加 RT-Thread 之后,裸机中的 main() 函数会自动变成 RT-Thread 系统中 main 线程 的入口函数。
    由于线程不能一直独占 CPU,所以此时在 main() 中使用 while(1) 时,需要有让出 CPU 的动作,比如使用
    rt_thread_mdelay() 系列的函数让出 CPU。
    **