求一个黑苹果内核10.13.6的内核文件kernel或者mach_kernel

本文主要介绍RT Thread操作系统在cortex-m3内核上嘚移植接口文件通过本篇博客你将深入了解RTOS操作系统是怎么通过触发软中断实现任务切换的,怎么实现内核异常信息的打印功能

RT-Thread操作系统的移植接口文件主要用cpuport.ccontext_rvds.sbacktrace.cdiv0.cshowmem.c。其中最重要的文件是cpuport.ccontext_rvds.s这两个文件其他三个文件在cortex-M3内核移植时没有实际的应用,这三个文件实际┅些辅助的功能打印内存,除数为0后台跟踪等操作,内容很简单可以自行查看。

这是一个汇编语言的文件这个文件实现了任务切換,触发软件中断硬件异常错误处理等操作,是操作系统移植时要实现的最重要的功能程序的内部逻辑根cortex-m3内核的编程模型有关,想了解此程序逻辑需要对cortex-m3内核的编程模块有一定的了解。

操作系统进行初始化芯片的时钟必要的外设后,开始进行第一个任务/线程调度时会调用rt_hw_context_switch_to,函数的输入参数是进行切换的任务(线程)的堆栈指针这个函数的具体功能如下:

请详细查看我增加的中文注释,有你不会嘚干货

26 ; 设置pendsv软件中断的优先级为最低
34 ;触发pendsv软件中断,此时中断关闭并不会产生中断
40 ;这段代码实际是可以没有的,移植时这样做有了┅个好处就是增加了MSP堆栈的使用空间
41 ;cortex-m3内核复位时使用msp堆栈从复位到进行初始化操作时会调用很多函数,会进行一些压栈操作
42 ;占用一部分msp堆栈由于程序不会退出到复位的位置,压栈占用的msp空间永远不会释放产生了堆栈的
43 ;的空间浪费一小部分。
44 ; 下面的代码实现的功能是读取SCB_VTOR寄存器这个寄存器保存了中断向量表的起始位置,此位置的字
45 ; 就是MSP堆栈的指针即启动代码里面分配出来的堆栈的栈顶。经过2次 LDR r0, [r0]就是楿当于取到
46 ;堆栈的栈顶,最后设置msp为栈顶

  

pendsv中断是真正进行了线程切换操作的前面介绍的2个函数主要在进行线程切换前,把要切换的线程嘚堆栈指针记录到这个汇编的程序的变量中在pendsv中断中进行线程切换时使用,并且触发中断下面介绍pendsv中断内部实现线程切换的原理,一萣要仔细看呀

 6 ;根据cortext-m3内核的编程模型,进行pendsv中断前内核已经自动的psr, pc, lr, r12, r3, r2, r1, r0把这些寄存器压入到发生切换的线程的堆栈psp中的去了,跳到中断程序使用的堆栈自动切换成msp
 9 ; 记录primask中断开关寄存器的值到r2寄存器中,用于退出中断后再打开中断用
26 ;判断此变量为0表示切入第一个线程
31 ;不为0时紦r4-r11这8个寄存器保存到当前要切换出去的线程堆栈psp中去,并且把当前线程的堆栈指针psp记录到rt_interrupt_from_thread变量中来
38 ;把要切入的线程的堆栈指针取出到r1寄存器中
43 ;从要切入线程堆栈中弹出这个线程中的寄存器r4-r11,把线程堆栈指针赋值到psp中
52 ;cortex-m3内核中发生中断时,在中断程序中使用的堆栈是msp操作系統线程设计使用的是psp线程,所以上面的线程切换就是实现是两个线程的堆栈指针的切换即把当前线程的堆栈psp保存到rt_interrupt_from_thread
53为量中,把要切入的堆栈赋值到psp中去
54 ;由于中断中使用的msp堆栈,退出中断是如果不做任何操作还是使用msp堆栈而线程使用的是psp堆栈,所以对lr寄存的位3进行置1就控制退出中断后使用psp中断

线程切换的核心就在上面的代码注释中,不懂的话要多看几次同时参考cortex-m3的内核编程手册来看上面的代码主要實现的是对切换进入和切换退出的线程堆栈指针的变换,即保存当前线程的psp把要切入的线程的堆栈指针赋值到psp中去。

可能读者关心线程切换不仅要切换线程的上下文还要从一个线程跳到另外一个线程,这个是怎么实现的呢

从一个线程跳到另外一个线程中上面的代码确實没有实现,实际是靠cortex-m3内核自动完成的发生pendsv中断前,内核硬件自动(不用程序操作)把当前线程的上下文(psr, pc, lr, r12, r3, r2, r1, r0)压入线程自己的堆栈可鉯看到发生中断时的程序位置的pc指针已经自动保存到堆栈中,pendsv中断程序把新切入的线程堆栈换到psp中当中断程序退出,新切入的线程的中斷上下文(psr, pc, lr, r12, r3, r2, r1, r0)会自动(硬件执行不用程序)的从线程中弹出,程序指针pc就获得了新线程的pc和这个线程中使用的寄存器的值程序就运行箌新线程中去了。这就是cortex-m3线程切换的核心与精髓你明白了么?

harfault_Handler中断中当发生了硬件错误中断时比如非法内存访问,外设初始化操作非法会发生。这个中断函数中实现了出打印出发生中断异常点的函数的指针

 4 ;中断程序中lr表示的是EXC_RETURN寄存器的状态,这个寄存器的位2表示進入中断前使用的是psp还是
 5 ;msp堆栈在rt-thread中,如果硬件错误中断发生在线程中使用的是psp如果是从另外一个中断发生
 6 ;硬件故障产生的中断,使用嘚是msp
 9 ;把发生中断前的堆栈指针赋值到r0寄存器中去
13 ;手动把r4-r11压入堆栈中再压入lr寄存器,记住这里多压入了9个寄存器的值
14 ; 这里这样操作的原洇是为了rt_hw_hard_fault_exception函数中定义的结构体能对齐访问到全部寄存器
21 ;上面压完堆栈后把更新后的堆栈指针重新写入到psp或msp中去,r0寄存器保存的是发生hardfaultΦ

rt_hw_hard_fault_exception函数中实现打印发生错误中断前的程序的位置的上下位即发生中断时程序的出现故障的位置。还记得上面的程序段中如下的这些操作这些操作是向堆中多压入了9个寄存器,进入此函数中使用结构体来struct exception_info来进行访问使用的

1;手动把r4-r11压入堆栈中,再压入lr寄存器记住这里哆压入了9个寄存器的值
2; 这里这样操作的原因是为了rt_hw_hard_fault_exception函数中定义的结构体能对齐访问到全部寄存器

  

  

从结构体的定义可以看出r0成员变量前面还囿exc_return,r4-r11这9个成员变量所以手动向堆栈中压入9个寄存器,使用这个结构体来访问发生中断前的程序位置的pc通过pc值就能找到哪段程序发生了錯误中断。


  

rt_hw_stack_init函数在创建线程时对分配的线程的堆栈进行初始化,一个线程中使用全部的cortex-m3的16个寄存器所以这个函数在线程的堆栈的栈顶位置向下的16个字进行初始化,按照内核进入中断时压入堆栈的寄存器顺序排列进行初始化特别说明一下lr是返回地址,即线程退出后返回箌rt_thread_exit函数中pc是线程的入口函数地址。


  

  

至此已经完成了全部cortext-m3内核移植部分的关键代码的讲解如有不懂的地方可以在下面留言。

摘 要:EtherCAT 是开放的实时以太网通讯協议由德国倍福自动化有限公司研发。EtherCAT 具有高性能、低成本、容易使用等特点目前在工业自动化领域有着广泛的应用。Zynq-7000 是赛灵思公司(Xilinx)推出的行业第一个全可编程 SoC 产品, 它将双核 ARM Cortex-A9 处理器低功耗可编程逻辑以及常用的外设紧密集成在一起。ZedBoard 是基于

KPA EtherCAT 主站是一套质量稳定、知名度和性价比较高的 EtherCAT 协议栈有较大参考价值。本文将介绍 KPA EtherCAT 主站在 Zynq 平台的移植与测试


版权声明:本文为博主原创文章遵循 版权协议,转载请附上原文出处链接和本声明

发布了25 篇原创文章 · 获赞 10 · 访问量 4万+

我要回帖

更多关于 黑苹果内核 的文章

 

随机推荐