32位ARM寄存器是如何只传递8位、16位数据的——由uboot nand 操作想到的

来源:互联网 发布:玻璃激光内雕机软件 编辑:程序博客网 时间:2024/06/05 11:58

  uboot中可以通过指令对nand操作,以AM3359为例,假设读取CS0连接的nand,读取地址0处的数据:

指令寄存器地址 5000007c

地址寄存器地址 50000080

数据寄存器地址 50000084

mw memory write     

md  memory read

mw.b   写入一个字节 mw.w  写2个字节     mw.l 写4个字节

流程:写入复位指令->写入指令0->写入地址0->写入指令30->读取数据

mw.b 5000007c ff    //复位指令
mw.b 5000007c 0   //指令寄存器写入0
mw.b 50000080 0  //写入地址0,分5次写入
mw.b 50000080 0
mw.b 50000080 0
mw.b 50000080 0
mw.b 50000080 0
mw.b 5000007c 30  //写入指令0x30
md.b 50000084 1   //读取数据寄存器中的数据

我们看到这里全部使用的mw.b,也就是写入一个字节,寄存器是一个32位的寄存器,真的是写入一个字节就

发送一个字节,而不是发送4个字节?经过多次试验,发现确实如此。那是如何做到的呢?

当你读取这几个寄存器的时候读到全是ffffffff,也就是说写入的数据发送完之后立马变为ff。那我们把上面的

mw.b 50000080 0往地址写入数据,写4次试试行不行,发现读不到nand的数据。但是我把5次写入地址改为:

mw.b 50000080 0
mw.l 50000080 0

发现可以正确读到数据了,说明mw.l 50000080 0使32寄存器全为0后,地址寄存器向nand发送了4个字节的0。

同样改为:

mw.b 50000080 0

mw.w 50000080 0

mw.w 50000080 0

也是成功的。

那md.b对应的uboot中的语句是 *((u_char *)addr) = (u_char)writeval,这句C语言转换为汇编语言就是

STRB   R0,[R1] 

R0存储的是0x00000000,R1存储的是0x50000080。STRB就是把R0的低8位00存储到0x50000080寄存器

的低8位,高24位保持不变

同样mw.w和mw.l也对应:

md.b     *((u_char *)addr) = (u_char)writeval STRB   R0,[R1]   发送低8位
md.w *((ushort *)addr) = (ushort)writevalSTRH   R0,[R1]   发送低16位
md.l *((ulong  *)addr) = (ulong )writevalSTR    R0,[R1]     发送32位

GPMC的这三个指令、地址、数据寄存器还有一个比较特殊的功能,那就是只向外发送寄存器中被重新赋值的位。

也就是说,如果只改变低8位,那么它只发送一个字节;如果改变了低16位,那么将分两次发送两个自己;

32位全改变的话,将分4次发送四个字节。

另一类常见的寄存器一些配置寄存器,写入数据之后寄存器值会保持。这样的话我们也可以通过一个寄存器来

验证mw.b w l的实际效果。

以0x50000090寄存器为例:

md.l 50000090 1   

mw.b 50000090 55

md.l 50000090 1

mw.w 50000090 3333

md.l 50000090 1

mw.l 50000090 55555555

md.l 50000090 1


0 0
原创粉丝点击