16.操作外设及重定位基本原理

本文详细介绍了操作外设,如看门狗定时器的原理和设置,以及如何在S5PV210中配置栈以调用C语言。内容涵盖了栈的设置、CPU模式下的栈管理和汇编调用C函数的方法。此外,还讨论了开启iCache的重要性,以及重定位和链接脚本在程序执行过程中的作用。
摘要由CSDN通过智能技术生成

16.1.操作某个外设的套路
(1)看门狗定时器(watch-dog-timer)现实中因为一些外部因素,电子设备经常会跑飞或者死机(譬如极端炎热、极端寒冷、工业复杂场合),在这种情况下我们希望设备自动复位而不需要人工干预(无人值守),看门狗用来完成这个工作;看门狗是我们SoC内部的1个定时器,定好时间后看门狗定时器会去计时,时间到之前(狗饿了之前)必须去重新置位看门狗定时器(喂狗),如果没有喂狗则系统会被强制复位。
(2)系统在正常工作时,系统软件会自己去喂狗,所以看门狗定时器不会复位;但系统一旦故障跑飞啥的,看门狗就没人喂了,然后下一个周期就会自动复位,达到我们期望的效果。
(3)硬件物理特性->看门狗其实是个定时器(类似闹钟),硬件上就是SoC内部的某个内部外设;原理图->看门狗不用分析原理图,因为看门狗属于内部外设,且没有外部相关的元件与它有关,所以不需要原理图分析,原理图上根本找不到和看门狗有关的地方;数据手册->在数据手册的Section7.3部分,如果直接看不懂数据手册,可以百度看门狗,然后看别人的博客来学习。
(4)找到关键性操作SFR(特殊功能寄存器)->WTCON(0xE2700000),其中bit5是看门狗的开关(0代表关,1代表开);编写汇编代码。
(5)210中看门狗特性(iROM中已经关看门狗)->一般的CPU设计中,在CPU启动后看门狗默认是工作的(防止程序在启动代码前端就死机了或者跑飞了没人管),好处就是没有空当和漏洞,坏处就是在启动代码段我们不方便去喂狗(或者说懒得去喂狗)时看门狗会复位,所以为了偷懒我们就在启动代码前端先去关闭看门狗,然后在后面系统启动起来之后再根据需要决定是否要打开看门狗(一旦打开就必须同时提供喂狗)。
(6)在S5PV210内部的iROM代码(BL0)中,其实已经关过看门狗了,所以我们的启动代码实际上是不用去关也没事的,很多CPU内部是没有BL0的,因此也没人给你关看门狗,都要在启动代码前段自己写代码关看门狗。


16.2.设置栈和调用C语言
(1)C语言运行时需要和栈的意义->C语言运行时(runtime)需要一定的条件,这些条件由汇编来提供;C语言运行时主要是需要栈(C语言中的局部变量都是用栈来实现的);如果我们汇编部分没有给C部分预先设置合理合法的栈地址,则C代码中定义的局部变量就会落空,整个程序就OVER了。
(2)我们平时在编写单片机程序(譬如51单片机)或者编写应用程序时并没有去设置栈,但是C程序还是可以运行的;在单片机中由硬件初始化时提供了1个默认可用的栈;在应用程序中我们编写的C程序其实并不是全部,编译器(gcc)在链接的时候会帮我们自动添加1个头,该头就是1段引导我们的C程序能够执行的1段汇编实现的代码(该代码会设置C程序中需要的栈及其它运行时需要)。
(3)CPU模式和各种模式下的栈->在ARM中37个寄存器中,每种模式下都有自己的独立的SP寄存器(r13);如果各种模式都使用同1个SP,那么就意味着整个程序(操作系统内核程序+用户自己编写的应用程序)都是用1个栈的,你的应用程序一旦出错(譬如栈溢出),则会连累操作系统的栈也损坏,整个操作系统的程序就会崩溃,这种操作系统的设计是非常脆弱的;解决方案就是各种模式下用不同的栈,操作系统内核使用独立的栈,每个应用程序也使用独立的栈,这样就不会株连。
(4)我们现在要设置栈,不可能也懒的而且也没有必要去设置所有的栈,我们先要找到自己的模式,然后设置自己的模式下的栈到合理合法的位置即可(系统在复位后默认是进入SVC模式);正常我们应该先把CPU工作模式设置为SVC,再直接操作SP,但因为我们复位后就已经是SVC模式了,所以直接设置SP即可。
(5)栈必须是当前1段可用的内存(可用->该地方必须有被初始化过可以访问的内存,而且该段内存只会被我们用作栈,不会被其它程序征用),当前CPU刚复位(刚启动),外部的DRRAM尚未初始化,目前可用的内存只有内部的SRAM(它不需初始化即可使用),则我们只能在SRAM中找1段内存来作为SVC的栈。
(6)栈有四种->满减栈(进栈->先移动指针再存,指针向下移动;出栈->先出数据再移动指针,指针向上移动)+满增栈+空减栈+空增栈;在ARM中,ATPCS(ARM关于程序应该怎么实现的1个规范)要求使用满减栈,结合iROM_application_note中的memory-map(图1)可知SVC栈应该设置为0xd0037D80地址处。


16.3.汇编程序和C程序互相调用
(1)C函数的编写和被汇编调用->在工程中新建并且添加1个C语言源文件(led.c),注意添加后要修改Makefile,在汇编启动代码中设置好栈后,使用bl-xxx的方式来调用C中的函数xxx。
(2)使用C语言来访问寄存器的语法->寄存器的地址类似于内存地址(IO与内存统一编址),则用C语言读写寄存器<=>用C语言来读写内存地址,用C语言来访问内存,则要用到指针(((volatile-unsigned-int-)0x0xE0200240)=0x11111111;)。
(3)神奇的volatile->volatile的作用是让程序在编译时,编译器不对程序做优化,如果程序中某个变量是易变的,不希望编译器帮我们做优化,则在该变量定义时加volatile修饰;加不加有没有差别,取决于编译器,如果编译器做了优化则有差异,如果编译器本身没做优化,那就没有差别(测试编译器arm-2009q3时发现加不加效果相同)。
(4)编译报错(实际上是链接阶段报错)->undefined-reference-to-‘__aeabi_unwind_cpp_pr1’;在编译时添加-nostdlib该编译选项即可解决,nostdlib即不使用标准函数库,标准函数库是编译器中自带的函数库,用-nostdlib可以让编译器链接器优先选择我程序内自己写的函数库。


16.4.开启iCache
(1)cache是1种内存(高速缓存),从容量来说(CPU-小于-寄存器-小于-cache-小于-DDR),从速度来说(CPU-大于-寄存器-大于-cache-大于-DDR),cache的存在是因为寄存器和ddr之间速度差异太大,ddr的速度远不能满足寄存器的需要(更加不能满足cpu的需要,所以没有cache会拉低整个系统的整体速度);整个系统中CPU的供应链=寄存器+cache+DDR+硬盘/flash四阶组成,这是综合考虑了性能+成本后得到的妥协的结果;210内部有32KB的icache和32kb的dcache,icache是用来缓存指令的;dcache是用来缓存数据的。
(2)cache的意义=指令平时是放在硬盘/flash中的,运行时读取到DDR中,再从DDR中读给寄存器,再由寄存器送给cpu;但DDR的速度和寄存器(代表的就是CPU)的速度相差太大,如果CPU运行完1句再去DDR读取下1句,则CPU的速度完全就被DDR给拖慢了,则解决方案就是icache;icache工作时,会把我们CPU正在运行的指令的旁边几句指令事先给读取到icache中(CPU设计有1个基本原理->代码执行时,下一句执行当前1句代码旁边代码的可能性要大很多);当下1句CPU要指令时,cache首先检查自己事先准备的缓存指令中有没这句,如果有就直接拿给CPU,如果没有则需要从DDR中重新去读取拿给CPU,并同时做1系列的动作->清缓存+重新缓存。
(3)S5PV210中iROM中的BL0对cache的操作->icache的一切动作都是自动的,不需人为干预,我们所需要做的就是打开/关闭icache;在210的iROM中BL0已经打开了icache,则之前看到的现象都是icache打开时的现象。
(4)3种情况下的实验现象->直接使用BL0中对icache的操作(irom中确实是打开了icache);关icache(icache关闭确实比icache打开时led闪烁变慢,说明指令执行速度变慢);开icache(现象和”直接使用BL0中对icache的操作”相同)。


16.5.重定位和链接脚本引入
(1)大部分指令是位置有关编码;位置无关编码(PIC->position-independent-code)->汇编源文件被编码成二进制可执行程序时编码方式与位置(内存地址)无关;位置有关编码->汇编源码编码成二进制可执行程序时编码方式和内存地址有关;链接地址->链接时指定的地址(Makefile中用-Ttext/链接脚本);运行地址->程序实际运行时地址(由实际运行时被加载到内存的哪个位置说了算);相比而言,位置无关代码要好些,适应性强,放在哪里都能正常运行;位置有关代码就必须运行在链接时指定的地址上,适应性差;位置无关码有一些限制,不能完成所有功能,有时候不得不使用位置有关代码。
(2)链接地址和运行地址这两者可能相同也可能不同;对于位置有关代码来说,最终执行时的运行地址和编译链接时给定的链接地址必须相同,否则一定出错;我们之前的裸机程序中的Makefile中用”-Ttext-0x0”来指定链接地址是0x0,裸机程序实际上的运行时的地址是0xd0020010,这两个地址看似不同,但是实际相同,因为S5PV210内部做了映射,把SRAM映射到了0x0地址上去。
(3)再解S5PV210的启动过程(三星推荐的启动方式和uboot的具体实现方式不同);三星推荐的启动方式->bootloader必须小于96KB并大于16KB,假定bootloader为80KB,先开机上电后BL0运行,BL0会加载外部启动设备中的bootloader的前16KB(BL1)到SRAM中去运行,BL1运行时会加载BL2(bootloader中80-16=64KB)到SRAM中(从SRAM的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值