实验手册上说了安装DNW驱动,这个软件我没有细查,不过根据它的功能,它用的是USB上传文件到开发板,所以比那种用串口上传文件要方便很多。
USB转串口支持驱动之前已经安装了,现在为了支持USB传输文件当然也要安装驱动,安装时有些文档里面没有说清楚,这里说下。
- 启动DNW,先在Configure里面设置一下,然后再点击Serial Port/connect,接着再打开开发板开关,输入dnw,会自动提示缺少驱动;
- 驱动文件先按照安装步骤先签名一下,然后再更新驱动;
- 安装完驱动,先回车输入dnw 40008000,然后再点击USB Por/Transmit/Transmit,添加文件到Transmit,添加完成后接着是传输文件,再次选择Transmit/led.bin,上传文件;
- 显示传输成功后,记得输入go 40008000把程序指针指向这个地址,CPU会到这个地方执行二进制机器代码,会看到灯闪烁,完成。
?
?
还是把例程代码写一遍吧,led裸板实验一共有三个文件
- start.S
- led.c
- Makefile
?
?
start.S需要完成的事情有
首先关看门狗(尽管IROM已经这样做了?),看门狗的作用还是不太清楚?
首先在手册中搜watchdog,找到watchdog这章,大概浏览下,然后找到这章
定位到26章看门狗定时器,大概浏览一下overview
对于硬件的操作无非是操作寄存器,寄存器就好比面向对象中的接口API,只不过这里封装的是硬件而已。通常而言,寄存器无非两大类:控制寄存器和数据寄存器,4412中的设备寄存器一般都是32位,然后具体的设备还有额外的寄存器。此处我们需要关闭看门狗,所以能够想到应该到控制寄存器里面找对应的位去设置一下。
这里呢,我们把控制器寄存器全部置零,也就是关闭所以可以控制的功能,反正暂时不要用,代码如下:
我们只要把Reset和Interrupt关闭就可以了,这样就无法产生复位信号或者中断信号,当然这里把所有位都置零也没问题:
关完了看门狗,接下来就是打开icache
这里插播一段广告,什么是icache?参考Tiny4412裸机程序之操作ICache |
CPU访问内存取指顺序执行,但是访问寄存器还是太慢了,所以在CPU通用寄存器和内存之间插入了高速缓存cache,特点是高速但是容量小,CPU会把一部分常用的指令放到里面去,cache常见的分成两类:icache和dcache。 icache使用比较简单,系统刚上电的时候是无效的,并且它是关闭的,往CP15协处理器中的寄存器C1的bit[12]写1可以启动icache,写0可以关闭icache。icache关闭时,CPU每次取指都要读主存,性能非常低。因为icache可随时启动,越早开icache越好。 dcache刚上电的时候也是无效并且是关闭的,在CP15寄存器C1中的bit[2]中写1可以启动dcache,写0可以关闭dcache。因为dcache必须在启动mmu之后才能启动,而对于裸机而言,没必要开启mmu,mmu是什么?所以这里就不启动了。 |
启动了icache,这样取指令命令就快了,这次的裸机测试程序的电灯程序是C语言写的,所以要设置栈空间(也就是设置栈指针)
下面介绍一下为什么要设置栈?参考和拷贝了文章Tiny4412之C语言实现流水灯,Tiny4412裸机程序 |
在Linux系统编程中,我们写了一段C代码然后就直接执行了,也没有设置栈空间。其实是C库帮我们这些事情做了,至于具体怎么做的暂时还不太清楚。大概的情况是这样的:在编译C源码时,编译器通常会在我们的代码中加上几个被称为启动文件的代码(crtl.o crti.o crtend.o crtn.o等),它们是标准的库文件。这些代码就负责设置C程序的堆栈等等,然后设置好C程序执行的堆栈环境(怎么设置的暂时十分不清楚),然后调用main函数。要注意的是,这些函数和我们的裸板程序设置堆栈的方法不同,因为还要和操作系统打交道,所以这些代码是不能用在裸板上的。 |
栈:调用C语言之前必须设置栈,栈用于保存运行时环境,给局部变量分配空间。 ?? |
具体把栈指针设置到哪里呢?先来看一下4412的启动流程吧,参考手册SEC_Android_Exynos4212_iROM_Secure_Booting_Guide_Ver.1.00.00.pdf 参考代码上给的ldr sp, =0x02050000,我不知道为什么设置0x02050000这个地址作为栈顶指针,参考了Tiny4412之C语言实现流水灯,Tiny4412裸机程序。 查手册发现内部的IRAM的地址是从0x02020000开始的,而根据IRAM的内部存储映射知道,还要划5K给IROM用,划8K给BL1用,划16K给BL2用(BL2实际14K),按道理说剩下的空间就没有用了,我们可以把剩下的空间0x02027400到0x02060000中划一段出来作为栈空间,只不过我奇怪的是为什么不在内存空间(我还不知道内存地址映射到哪段上去了?)呢? 其实选取1K就足够了,其实对于led.bin来说,根本用不了这么大,而他这里选择了0x02050000,我不懂。 其实按道理说,设置 0x02020000 (iRAM基地址) + 5K(iROM代码用) + 8K(BL1用) + 16K(BL2用) + 1K(用作栈))也是可以的,这里设置的是0x02050000? |
?
?
好了,设置完了栈空间,就可以调到C程序那里去执行了:
下面来实现led_blink函数,可见这里不需要main函数,原因是这是逻辑程序,而对mian函数的要求是C编译器的要求。
第一步首先找到led的原理图,因为有了原理图,才能知道led连接到了哪个引脚上,然后才能控制这个引脚,从而控制led。
下面是led的原理图:
从上图可以知道连接led的引脚网络标号,然后通过网络标号找到和连接器相连的引脚:
?
?
然后再通过连接器上的网络标号到核心板原理图pdf上去找对应的处理器的引脚:
?
?
?
?
好了现在知道了处理器引脚名称了,接着到4412手册pdf上搜到这两个引脚相关的寄存器,然后控制即可。
这里的话控制很简单,只要先设置为输出,然后输出高电平就点亮,输出低电平就熄灭即可:
?
?
?
?
?
?
?
?
led2 |
GPL2_0 |
?? |
led3 |
GPK1_1 |
?? |
?
?
?
?
?
?
?
?
?
?
下面写流水灯的C程序:
接下来是Makefile的编写:
接下来就是执行了,但是出现了如下错误:
不知道怎么回事,上次还有用的。不管了,既然没检测到,肯定是路径没添加,所以添加下:
添加:
使 .bashrc生效
再次运行make,OK! 执行成功:
?
?
接下来就是把led.bin下载到开发板上:
- 先把led.bin拖到桌面上,我习惯用Xmanager文件传输,十分方便;
- 接着打开dnw.exe,如果端口号变了,需要先重新Configuration/Options;
- 然后点击Serial Port/Connet;
- 接着按下iTOP-4412开发板的电源开关,dnw输出信息,及时按下回车;
- 输入dnw 40008000;
- 然后下载led.bin到开发板上:USB Port/Transmit/;
- 下载成功后,不要忘了输入 go 40008000 执行代码;
- 经测试,本次流水灯实验成功。
?
?
说明:
得到了led.bin,根据 裸机教程.pdf ,通过现成的uboot功能,把led.bin下载到了0x40008000这个地址,不是太清楚这个地址是干嘛用的。原以为程序当然是加载到内存中运行的,但是我不知道这里的意思是什么?是不是把程序搬到了这个地址0x40008000,然后还要搬到再搬到内存里面去执行?还是说0x4000800本来就是内存地址也就是下载到了DRAM上?不过按道理说,应该不是直接下载到内存上吧,应该是先下载到eMMC上吧。
?
?
我看了4412手册描述存储映射的那章:
但是不太清楚这个DMC到底是个什么地址,而且也没有找到DDR的映射区域,不知道怎么回事???
用折半法试了下,只有0x40000000到0x5FFFFF0A这段地址段可以通过dnw.exe把led.bin下载过去,led.bin占232字节(指的是教程提供的led.bin,自己的led.bin大小不是这个)。也就是大概511M的空间,我奇怪的是为什么其他区域不可以呢,毕竟这块板子的eMMC有4G的空间???不明所以。
?
?
0x5ffffe22+0xe8=0x5FFFFF0A
0x5FFFFF0A-0x4000000=0x1FFFFF0A=536870666(10)
536870666B/1024/1024=511.9998
512MB=536870912B
?
?
先把当下的事情干好,想一下是不是。
?
?