CPU架构移植:大部分的CPU都移植好了,不太需要用户去操作。libcpu文件夹里面就是各种的CPU架构。主要处理标红四个函数:
函数和变量 | 描述 |
---|---|
rt_base_t rt_hw_interrupt_disable(void); | 关闭全局中断 |
void rt_hw_interrupt_enable(rt_base_t level); | 打开全局中断 |
rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *stack_addr, void *texit); | 线程栈的初始化,内核在线程创建和线程初始化里面会调用这个函数 |
void rt_hw_context_switch_to(rt_uint32 to); | 没有来源线程的上下文切换,在调度器启动第一个线程的时候调用,以及在 signal 里面会调用 |
void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); | 从 from 线程切换到 to 线程,用于线程和线程之间的切换 |
void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); | 从 from 线程切换到 to 线程,用于中断里面进行切换的时候使用 |
rt_uint32_t rt_thread_switch_interrupt_flag; | 表示需要在中断里进行切换的标志 |
rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; | 在线程进行上下文切换时候,用来保存 from 和 to 线程 |
rt_tick_increase() | 时钟节拍 |
重点:BSP的移植:这里主要是针对Rt-thread下BSP下没有的芯片的移植。
三种方式:
从现有bsp修改(相同/相似型号芯片),主要是从E:\rt-thread\bsp目录下,这次项目就是选的这种方式。
基于模板移植(同一系列芯片),主要从E:\rt-thread\bsp\stm32\libraries\templates目录下,芯片系列以stm32为例。
裸机工程添加(难度最大)
1、通过看bsp下的readme.md看下芯片配置是否相似。找到后,复制一份工程出来,改一下名
2、时钟配置,通过CubeMX配置时钟,生成工程后,在main.c里 SystemClock_Config()
拷贝一份到board.c中。
3、串口引脚,通过CubeMX配置好串口后,调用E:\birld\rtOS\bsp\myOS\sixBand\board\CubeMX_Config\Src下的stm32l4xx_hal_msp.c底层配置。然后,通过menuconfig,打开串口外设,并在kernel下,控制台串口名称要对应到打印串口。
4、Flash、RAM大小
在board.h,还有链接脚本link.sct(文件在E:\birld\rtOS\bsp\myOS\sixBand\board\linker_scripts)下修改。
scons --dist,打包一个BSP。
1、选好通用模板
2、按照以下修改:
项目 | 需要修改的内容说明 |
---|---|
CubeMX_Config (文件夹) | CubeMX 工程 |
linker_scripts (文件夹) | BSP 特定的链接脚本 |
board.c/h | 系统时钟、GPIO 初始化函数、芯片存储器大小 |
Kconfig | 芯片型号、系列、外设资源(在E:\birld\rtOS\bsp\myOS\sixBand\board下) |
SConscript | 芯片启动文件、目标芯片型号(也是在E:\birld\rtOS\bsp\myOS\sixBand\board下,启动文件修改) |
其他参见:一、现有BSP修改
RTT的内核架构
移植步骤:
1、准备祼机工程(带串口打印)
2、添加RT-Thread源码(src,include,libcpu,rtconfig.h)
本人是基于stm32L431RCT6的芯片来移植,并且源工程是用CubeMX直接生成的,所以工程添加情况如下:基于nano3.13版本进行的移植。
Board文件夹存放的是board.c文件。rt-config.h与board.c都是直接拷贝nano3.13目录下bsp下:
3、实现时钟管理(Systick配置)board.c已经实现了systick的配置,所以基本上没动。至此,已经实现了大半,在工程中将main.c里的delay(),改为rt_thread_delay(500);就可以实现移植前的功能了。目的是,给系统提供时间片,这样系统才能跑起来。同时,系统切换时的延时rt_thread_delay()也是基于系统时间片的,切换也是基于systick的中断函数,所以这两步必不可少。
第一步,实现配置:
第二步实现systick中断
4、实现控制台输出(实现rt_hw_console_output()):目的是为了调用kt_printf打印调试信息。
这里主要实现coponets.c---->rt_show_version()下调用的rt_kprintf()函数。打开rt_printf()函数定义,有两种方式,一种是设备,另一种是void rt_hw_console_output(const char *str)函数。
使用最简单的,重新定义一下rt_hw_console_output().
个人遇到的问题是:
1、在重定义时,多加了一个取地址符,造成一直输出不对。
其中Usart_SendString原型为:
2、输出Log后没有换行:
解决:
以上遇到的两个问题,都和这个函数原型Usart_SendString()有关。
这个函数是输出一行,然后没有回车,所以是接着输出的,怎么办呢?最简单的办法。
解决:
5、实现动态内存管理(rt_system_headp_init()):目的是为了实现多线程。线程是要分配栈空间的,所以需要知道每个栈的起始地址和结束地址。
直接移植的nano下的board.c里已经实现了rt_system_headp_init(),只要开启两个宏就可以了。
修改一个栈大小为10K,如下图:
然后在mian()函数里面创建一个新线程试试就可以了。如下:
至此,完成一个裸机工程的移植。
完整代码,附工程见CSDN上传资源