注:以下内容学习于韦东山老师arm裸机第一期视频教程
1、门电路:GPIO接口
2、协议类接口:UART、I2C…
CPU把某些值写给某些寄存器,然后由对应的控制器发出特定的波形
CPU怎么去选择不同的寄存器?
CPU由地址去选择不同的寄存器
由于CPU根据地址去选择不同的寄存器,所以我们需要有一个 控制单元(内存控制器)
这两种接口CPU发出的数据并不会输出到外部电路去,只是控制相对于的控制模块
CPU只是根据地址选择不同的寄存器,把数据发送到控制模块的寄存器(至于数据和地址起什么作用由不同模块的控制器决定)
3、内存接口:内存类设备(NOR、网卡、SDRAM)
CPU发出的地址可以直接发送
片选引脚概念:
只有使得某个片选引脚输出低电平的时候,对应的芯片才会开始工作,
内存控制器根据CPU发出的地址,设置不同的片选引脚,只有被选中的芯片才会工作
地址与片选引脚关系如下图:
每个片选信号选择的地址范围为:128M =2^27(0x0800,0000)(至少需要A0,A1…A26共27条地址线)
CPU是32位,怎么只用到27条地址线?
ldr r0, = addr
str r1,[r0]
ldr r1,[r0]
对于GPIO、UART、I2C、SDRAM、DM9000、NOR都是CPU统一编制的,但是对于NAND原理图如下
上面并没有地址总线,所以不属于CPU统一编址
那么nand片选信号是由谁发出的呢?是由nand flash 控制器发出的
:
SDARM
NOR
laddr -->A0,
laddr -->A1,
…
当使用一个8位的芯片时,CPU的A0接芯片的A0
当使用两个8位的芯片拼接(DATA0-7接一个芯片,DATA8-15接一个芯片,也就是组成了一个16位的芯片)的时候,CPU的A1接芯片的A0(CPU的A0用来判断高8位有效还是低8位有效)
当使用四个8位的芯片拼接(也就是组成了一个32位的芯片)的时候,CPU的A2接芯片的A0
假设CPU执行
MOV R0,#3
LDRB R1,[R0]
# 读地址3的一个字节
过程 | cpu发出地址 | ROM收到地址 | ROM返回数据 | 内存控制器转发数据给CPU |
---|---|---|---|---|
8bit | 000011 | 000011 | 编号3的存储单元中的8bit数据 | 返回数据 |
16bit | 000011 | 00001 | 编号1的存储单元中的16bit数据 | 根据”A0=1”,挑出编号为1的8bit数据 |
32bit | 000011 | 0000 | 编号0的存储单元中的32bit数据 | 跟根据“A0=1,A1=1”,挑出编号为3的8bit数据 |
MOV R0,#4
LDR R1,[R0]
# 去地址 4 去取 4,5,6,7 这4个字节
过程 | cpu发出地址 | 内存控制器转发给ROM | ROM返回数据 | 内存控制器,组装返回数据给CPU |
---|---|---|---|---|
8bitROM | 000100 | 000100—>ROM 000101—>ROM 000110—>ROM 000111—>ROM |
得到地址4上的1byte 得到地址5上的1byte 得到地址6上的1byte 得到地址7上的1byte |
组装4、5、6、7之后返回给CPU |
16bitROM | 000100 | 00010—>ROM 00011—>ROM |
得到第二个16bit数据 得到第三个16bit数据 |
组装第2、3 (16bit数据)返回数据给CPU |
32bitROM | 000100 | 0001 —>ROM | 得到第一个32bit数据 | 把第一个32bit数据返回CPU |
怎么确定芯片访问地址:
1、根据片选信号确定基地址
2、根据芯片所接地址线确定范围
NOR | NET | SDRAM | |
---|---|---|---|
基地址(base) | 0 | 0x2000,0000 | 0x3000.0000 |
片选 | 0 | 4 | 6 |
范围 | 用到A20,A19…A1,A0共21条线 2^21=2M空间 范围:base+0b0…0–>0b1…1= 0—>2^21 |
用到A2,A0 范围:base+0b000->0b101 = 0x2000,0000—>0x2000,0005 |
比较特殊以后补充 |
以NOR Flash 为例:
NOR Flash 的原理图如下:
LADDRn:地址线
LDaTAn: 数据线
nGC0: 片选信号
nOE: 读信号
WE: 写信号
先发出地址信号,经过Tacs时间发出片选信号(nGCS),然后经过Tcos时间发出读信号,过一会数据才有效,把数据读走,然后把读信号释放掉,把片选信号释放掉,然后才开始新的地址周期
Tacs ,Tcos,Tacc,Tacp...这些需要根据不同的芯片来进行设置
因为J2440可以接不同类型的内存类芯片,这些内存内芯片性能不同,所以所用的时间周期也不同。
只需要设置 bit[2:1],bit[2:1]是只读的,表示外界NOR是多少位的,因此不需要设置
#include "s3c2440_soc.h"
#include "uart.h"
#include "setTacc.h"
#include "led.h"
int main(void)
{
unsigned char c;
int i;
uart_init();
puts("Enter the Tacc val: \n\r");
while(1)
{
c = getchar();
putchar(c);
if (c >= '0' && c <= '7')
{
setTacc(c-'0');
led_test();
}
else
puts("Error val,tacc should betwen 0-7\n\r");
}
return 0;
}
### setTacc.c
void setTacc(int tacc)
{
BANKCON0 = (tacc<<8);
}