嵌入式arm学习第五天
相关概念:
i:输入
o:输出
clk:时钟
src:源
div:分频/降频
inv:翻转 invert
sel:选择
slave:外设
master:cpu
cpu通过uart串口访问上位机流程:
cpu以地址指针的形式访问uart控制器内部的寄存器,就是cpu通过寄存器给uart控制器发送控制命令
当uart控制器接收到控制命令,uart控制器硬件上自动操作uartrxd0和uarttxd0两个引脚,发起uart传输时序
两个引脚的时序自动操作上位机
涉及的相关重要寄存器(三星S5P6818):
看bit位从低位开始,如果有Normal用Normal
配置寄存器:
ULCON0
基地址:0xC00A1000
bit[1:0] = 11 设置数据位为8位,默认值为00 5位
bit[2] = 0 设置停止位为1位,默认值为0 1位
bit[5:3] = 000 设置为不校验,默认值为000,不校验
bit[6] = 0 设置红外模式为普通模式,默认值为0,普通模式
bit[31:7] 保留
UCON0
基地址:0xC00A1004
Receive Mode:bit[1:0] = 01 采用轮询方式CPU从接收缓冲区读取数据
因为CPU处理速度快于外设,所以计算机操作外设方式有三种:
1.轮询:当CPU读取UART接收缓冲区的数据无效时,CPU原地死等,直到接收缓冲区数据有效
当发送移位器将数据发送到TX上时,此时CPU想发送第二个数据,由于发送移位器还没有发送完毕,所以此时CPU核等待第一个数据发送完成才能向发送缓冲区写入第二个数据
2.中断(interrupt):
3.DMA:
Transmit Mode:bit[3:2] = 01 设置为轮询方式
Send Break Signal:bit[4] = 0 正常传输
Loop-back Mode:bit[5] = 0 正常传输
loop-back mode: 回环模式 自发自收 TX和RX短接 用于测试
目前采用polling,其余bit无关,所以暂时不关注
UTRSTAT0 状态寄存器 判断缓冲区是否为空,防止丢失数据
基地址:C00A1010
Receive buffer data ready:
bit[0] = 0:表示接收缓冲区为空
= 1:表示接收缓冲区非空
如果用轮询的方式获取接收到的数据,代码如下:
while(!(UTRSTST0 & 0x1));
bit[1] = 0:表示发送缓冲区非空
= 1:表示发送缓冲区为空
如果用轮询的方式实现CPU发送数据,代码如下:
while(!(UTRSTAT0 & 0x2));
UERSTAT0:错误状态寄存器
UFSTAT0:FIFO状态寄存器
UMSTAT0:CTS
UTXH0:发送缓冲区寄存器
基地址:0xC00A1020
UTXH0=“A” 将数据A写入发送缓冲区寄存器
URXH0:接收缓冲区寄存器
基地址:0xC00A1024
unsigned char data = URXH0 & 0xFF; (可读性强,一眼看出只要低八位)
UBRDIV0:波特率配置寄存器
基地址:C00A1028
如果要得到一个波特率为115200,并且SCLK_UART = 40MHz,根据波特率计算公式得出:
UBRDIV0 = 20
UFRACVAL0:波特率配置寄存器
基地址:C00A102C
如果要得到一个波特率为115200,并且SCLK_UART = 40MHz,根据波特率计算公式得出:
UFRACVAL0 = 11
公式:UBRDIV0+UFRACVAL0/16=(SCLK_UART/(bps*16))-1
UBRDIV0+UFRACVAL0/16=(40000000/(115200*16))-1 = 20.7
UBRDIV0=20(取整)
UFRACVAL0=0.7*16=11(取整)
GPIODALTFN0:复用功能选择寄存器0
基地址:0xC001D020
bit[29:28] = 01 配置为UARTRXD0功能
GPIODALTFN1:复用功能选择寄存器1
基地址:0xC001D024
bit[5:4] = 01 配置为UARTTXD0功能
SCLK_UART = 40MHz 如何让得到?
看芯片手册中clock章节
得到公式:SCLK_UART = 输入时钟源/n
查看clock中关于uart的内容得到时钟配置的两个寄存器
UARTCLKENB:UART时钟使能寄存器
基地址:0xC00A9000
bit[2] = 0 禁止UART时钟
= 1 使能UART时钟
提示:控制器初始化时,先将时钟关闭,初始化完成之后再打开
UARTCLKGEN0:UART时钟配置寄存器
基地址:0xC00A9004
bit[4:2] = 00 选择PLL[0]做为输入时钟源
bit[12:5] = CLKDIV0
n = CLKDIV0+1
如果PLL为800MHz,800/40=20,20-1=19
CLKDIV0 = 19
硬件信息掌握之后:
上位机编辑:vim x.h x.c main.c
交叉编译 arm-cortex_a9-linux-gnueabi-gcc -nostdlib -c -o x.o x.c
arm-cortex_a9-linux-gnueabi-gcc -nostdlib -c -o main.o main.c
arm-cortex_a9-linux-gnueabi-ld -nostartfiles -nostdlib -Ttext=0x48000000 -emain -o x.elf main.o x.o-ARM
arm-cortex_a9-linux-gnueabi-objcopy -O binary x.elf x.bin
arm-cortex_a9-linux-gnueabi-objdump -D x.elf > x.dis
vim x.dis 保证0x48000000地址入口函数为main函数
cp x.bin /tftpboot
下位机测试:进入uboot命令行
ping 上位机IP
tftp 0x48000000 x.bin
go 0x48000000
'\n':换行
'\r':回车