疯雨-版权所有,转载请注明【http://blog.csdn.net/u010346967】
欢迎加入朱老师物联网大课堂qq群 一起学习进步
群号:397164505
串口是调试的利器,单纯靠led来调试是很痛苦的一件事,所以当务之急是初始化串口。注意:我这里是初始化的串口0.
首先,从需求开始,先想象一下软件需要做些什么?串口无非就是要实现接收和发送数据,那么从哪里发送或者接收数据呢?所以就要求配置GPIO为UART模式,说明从这里接收或发送数据。发送数据的速度多快呢?所以要设置波特率。然后,一次发送的数据长度为多少?是否使用奇偶校验,停止位设为多少位?这就要配置ULCON。当然,外设都得配置时钟源,所以UCON少不了。用不用FIFO应当要可配置,那么UFCON是必须的。还有流控开不开,这个如果不懂的话可以看我的另一篇文章,串口通信原理。
1.六步轻松搞定串口初始化
1.1 配置相应GPIO口为串口模式
1.2 配置ULCON
1.3 配置UCON
1.4配置UFCON
1.5配置UMCON
1.6设置波特率
2.具体初始化细节
2.1 通过datasheet也就是S5PV210_UM_REV1.1.pdf文件,找到UART0接在GPA0口。配置GPA0CON为0x22222222,这里把UART1也配置了。
2.2 配置ULCON0(如果是串口2则配置ULCON2)为 0x3
2.3 配置UCON0(串口2是UCON2)为0x305
2.4 配置UFCON0(串口2为UFCON2)为 0x1,这个简单使能fifo就可以了。其他几个状态寄存器不用管
2.5 配置UMCON0(串口2为UMCON2)为0x0,不使用流控,不管他
2.6 波特率设置为115200
需配置两个寄存器UBRDIV0(串口2为UBRDIV2)为34(注意十进制哦)和UDIVSLOT0(串口2为UDIVSLOT2)为0xDFDD
这个要计算了 计算公式手册上有,直接看手册提供的例子40000000是UART的时钟频率,也就是PCLK,我们的PCLK配置为66MHz。
DIV_VAL=(66000000/(115200X16))-1 = 34.8 0.8X16= 13 查表得到 UBRDIV0 = 0xDFDD
初始化代码贴下面:
uart_init: /* set GPIO to enable UART0-UART4 */ mov r0, r8 ldr r1, =0x22222222 str r1, [r0, #0x0] @ config UART0 and UART1 ldr r1, =0x00002222 str r1, [r0, #0x20] @ config UART2 ldr r0,=S5PC110_UART_BASE @如果是使用串口2,只需将这里改为 ldr r0,=S5PC110_UART2_BASE ldr r1,=0x3 str r1,[r0] @ULCON=3 ldr r1,=0x305 str r1,[r0,#0x4] @UCON=0x305 ldr r1,=0x1 str r1,[r0,#0x8] @UFCON=1 ldr r1,=0x0 str r1,[r0,#0xc] @UMCON=0 ldr r1,=34 str r1,[r0,#0x28] @Baud rate 115200 ldr r1,=0xDFDD str r1,[r0,#0x2c] @UDIVSLOT mov pc,lr
3.串口测试
往串口写一个字符U并打印出来。串口数据是ASCII编码,百度一下U的ASCII码(0x55),0x55直接写入UTH0寄存器即可。
直接在uart_init 子过程的末尾mov pc,lr 的前一行增加代码,修改后如下图所示:
再检测下代码,看看有没有问题,好了确定没什么问题,现在可以编译了
root@crazyrain:/home/share/uboot/u-boot-2012.10# make
make成功
然后进行烧录,但是发现每次都要敲同样的命令效率太低,于是写个烧写脚本burnBootloader.sh
root@crazyrain:/home/share/uboot/u-boot-2012.10# vim burnBootloader.sh
脚本内容如下:
./mkv210 u-boot.bin u-boot_16k.bin dd if=u-boot_16k.bin of=/dev/sdb seek=1并为烧写脚本提供可执行权限:
root@crazyrain:/home/share/uboot/u-boot-2012.10# chmod a+x burnBootloader.sh
将SD卡插入电脑,进行烧录
root@crazyrain:/home/share/uboot/u-boot-2012.10# ./burnBootloader.sh
拔出SD卡,插入开发板,连接串口0,并配置好SecureCRT连接。发现串口并没有打印出字符。
这时候纠结了,分析下原因?有两种可能,第一,代码有问题。第二,代码不在前16k。所以看看lowlevel_init是不是位于前16k,反汇编一下
root@crazyrain:/home/share/uboot/u-boot-2012.10# arm-linux-objdump -D u-boot > u-boot.dis
root@crazyrain:/home/share/uboot/u-boot-2012.10# vim u-boot.dis
查找lowlevel_init,看下图
一眼看出确实不在前16k,为啥呢?链接起始地址为0x34800000 0x3481fa14-0x34800000=0x1fa14 大于 16k=16*2^10=16*16^2*4=4*16^3=0x4000
记住几个常用值 0x1000为4k 那么16k就是4*0x1000=0x4000 0x100000为1M 比如5M 就是0x500000 能一下子看出来
那么接下来怎么把代码移动到前16k呢?
有两个办法,第一,修改Makefile。第二,修改链接脚本。
第一种办法我试过了,下面先试试第二种办法,
root@crazyrain:/home/share/uboot/u-boot-2012.10# vim u-boot.lds
在arch/arm/cpu/armv7/start.o (.text)后面添加一句,如下面所示:
arch/arm/cpu/armv7/start.o (.text)
board/samsung/x210v3/lowlevel_init.o (.text)
board/samsung/x210v3/lowlevel_init.o (.text)
再次编译,记得先make clean 再make 如下:
root@crazyrain:/home/share/uboot/u-boot-2012.10# make clean
root@crazyrain:/home/share/uboot/u-boot-2012.10# make
查看反汇编文件,这里还有另一种方式可以查看,就是编译后顶层目录下的u-boot.map文件,打开搜索lowlevel_init:
发现没点变化,因为前面犯了个错,前面修改的是顶层目录下的u-boot.lds,这个文件是临时生成的。真正的文件位于arch/arm/cpu/u-boot.lds
好,按照上面的修改,编译发现如下错误:重复定义错误,因为libx210.o里面也有一个lowlevel_init
board/samsung/x210v3/libx210v3.o: In function `lowlevel_init': /home/share/uboot/u-boot-2012.10/board/samsung/x210v3/lowlevel_init.S:46: multiple definition of `lowlevel_init' board/samsung/x210v3/lowlevel_init.o:/home/share/uboot/u-boot-2012.10/board/samsung/x210v3/lowlevel_init.S:46: first defined here make: *** [u-boot] 错误 1
那么我干脆把libx210v3.o链接过去,而不是链接lowlevel_init.o,试试,竟然成功了
接着,查看下 u-boot.map,位于前16k了吧
好了,烧录运行下试试,竟然出现了,神奇的U。。。