龙芯ls2k1000开发板移植rt-thread的示例分析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
1.前言
2.龙芯派基本介绍
3.rt-thread在龙芯派上的运行过程
4.rtt的启动分析
4.1 启动代码引导
4.2 rt-thread的启动流程
5.关键部分驱动的初始化
6.Stack Frame
7.总结
龙芯2k1000开发板拥有非常丰富的外设资源,板子设计也非常的精致。
所以打算运行一下rt-thread,然后进行相关的开发操作。
本文主要针对龙芯2k1000的龙芯派的开发板进行rt-thread移植,通过这篇文章,基本上掌握rt-thread对于一个新的体系架构上的移植过程,同时也可以很好的掌握mips64体系架构上的相关知识,同时熟悉使用龙芯派2k1000。
由于裸机开发与rtos开发有着一定的联系,所以如果要想理解rt-thread更加底层的东西,一定需要理解芯片的设计以及各种体系架构的设计。
龙芯派就是面对普通开发群体的一个开发板,龙芯派搭载 2K1000 处理器(主频 1GHz),板载 DDR3 颗粒,实现 DDR3 的运行存储功能。实现了 GPIO 的输入输出,中断功能。板上集成 1 个网 口,集成 3 个 USB 接口,HDMI 接口,LCD 接口,音频输入/输出,集成 SD 卡接口,集成 2 个 CAN 接口,集成 RTC 计时功能。可以外扩 WIFI 模块。2K 龙芯派可以广泛应用于信息安 全、电力、轨道交通、工业控制、信号处理、数据通信、信息教育等领域。
由于其强大的性能以及多接口,也让更多方案实现变的可能。
龙芯派拥有8Mb的SPI Flash,龙芯的BIOS就是存放在这个SPI Flash中,龙芯叫pmon。可以理解为uboot,由于龙芯的pmon的使用,我们为了验证和体验效果,并且方便开发测试,我们可以利用pmon的tftp的下载功能,将固件拷贝到内存中,然后直接执行即可。这种方式有利于程序的调试和开发。
当实际应用到生产环境中时,可以将rt-thread固化到spi flash中,这样就可以很好的加快启动速度了。现在我们只讲开发阶段的启动过程。
龙芯派是通过网络下载方式将固件进行烧录的,所以首先启动了pmon,然后将rt-thread固件转移到ddr中。
上电之后,龙芯的pmon开始启动,当串口打印过程中,我们可以通过输入键盘上的c
字符进入pmon的控制台中,这样就可以利用pmon的tftp将固件加载到ddr中,然后跳转到ddr中去执行。
ifaddr syn0 192.168.12.100
load tftp://192.168.12.35/rtthread.elf;
g
其中ifaddr
为设置开发板的ip地址,syn0
表示第一个网卡,load
加载程序到内存,g
开始执行。
接着,rt-thread启动初始化流程,初始化串口,初始化中断,然后开启中断,线程开始调度,rt-thread开始进行任务调度。
这就是一个龙芯派执行的完整流程。
对于龙芯派的移植,或者说对于一个新的体系架构移植rt-thread,基本过程分为如下几个部分:
1.裸机代码引导,初始化栈空间与bss段,为运行c代码提供环境
2.关闭中断,直到所有的流程初始化完成,第一个最高优先级的线程出栈时,打开中断
3.初始化uart
4.初始化os tick中断
5.控制台输出logo
6.初始化ipc,以及组件,初始化timer()以及idle线程
这部分的主要功能就是为启动C代码做准备。
这部分的代码一般是由汇编写的,准备好sp的栈指针,然后清空bss段然后直接跳转到了rtthread_startup
函数中。
然后就进入rt-thread入口函数。
简述一下rt-thread的启动流程如下:
1.关闭全局中断
2.板级驱动初始化(关键初始化,timer、uart等,移植大部分工作)
3.初始化选中的rtt组件
4.打印logo
5.调度器初始化
6.初始化main、idle等线程
7.启动调度(出栈时开启全局中断)
8.线程开始调度
对于龙芯2k1000来说,我们需要关注的是rt_hw_board_init
里面关键外设的初始化。这里主要涉及到两个,一个是uart驱动初始化,另外一个就是timer初始化。
对于tick,我们采用mips中的c0寄存器进行比较。
HPET 控制器
通过配置,每个定时器都能独立产生中断。
这组定时器由一个向上累加的主计时器(up-counter)以及一组比较器构成。这个计时器以固定的频率(125MHz)向上累加,因此当软件两次读取计时器的值时,除非遇到计时器溢出,否则第二次读取的值总是比第一次读取的值大。而每个定时器都包含一个 match 寄存器以及一个比较器。当 match 寄存器的值与主计时器相等时,那么定时器产生中断。部分定时器可产生周期性中断。HPET 模块包括一个主计数器(main count)以及三个比较器(comparator),且他们的宽度都是 32 位。在这三个比较器中,有且仅有一个比较器支持周期性中断(periodic-capable),这三个比较器都支持非周期性中断。
而在我们的rtt中正常情况下是使用非周期性中断。相关的寄存器不展开描述,使用的过程中配置好即可。
uart控制器
作为rtt的控制台,串口这部分也是必不可少的,在使用ls2k1000的时候,需要充分考虑到uart资源使用情况。
2K1000 集成了 12 个 UART 控制器,通过 APB 总线与总线桥通信。虽然说有这么多串口控制器,但是实际上很多都是复用的串口控制器,所以实际上只能最大同时使用的是4路uart接口。
其uart控制器有如下几个部分:
1.发送和接收控制器负责将fifo中的数据进行分发或者接收
2.moden寄存器控制着串口的输出信号 DTR 和 RTS 的状以及相关的校验状态。
3.中断仲裁模块:当任何一种中断条件被满足,并且在中断使能寄存器(IER)中相应位置 1,那么 UART 的中断请求信号 UAT_INT 被置为有效状态。
4.访问寄存器模块:当 UART 模块被选中时,CPU 可通过读或写操作访问被地址线选中的寄存器。
其中中断这一块必须十分的小心,因为串口的使用,涉及到fifo的时候,需要知道空闲状态以及相关的半满或者全满或者32字节产生中断等属性。否则读取数据出来将异常复杂。
栈帧这部分与编译器相关,也与体系架构相关,所以在使用的时候,需要知道栈的活动轨迹
。函数的压栈与出栈,操作系统的调用,都和这部分相关。
rt-thread的压栈操作在libcpu的特定的体系架构的stack.c文件中。
每个线程在初始化的时候,都会进行压栈操作。出栈的操作在context_gcc.S文件中。
压栈除了压入通用寄存器外,还会涉及到状态寄存器,比如spsr或者cpsr等等,如果有FPU,也需考虑进去。
需要注意的是,压栈的顺序与出栈的顺序必须是一一对应的。这部分的调试功能比较繁琐,需要一步一步的进行跟踪。
看完上述内容,你们掌握龙芯ls2k1000开发板移植rt-thread的示例分析的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注亿速云行业资讯频道,感谢各位的阅读!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。