oldstorm

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

GPIO 通用输入/输出端口,就是一些引脚,通过它们输出高低电平或者通过它们读入引脚的状态-是高电平还是低电平

 

上拉电阻、下拉电阻的作用在于,当GPIO引脚处于第三态(既不是输出高电平,也不是输出低电平,而是呈高阻态,即相当于没接芯片)时,

它的电平状态由上拉电阻、下拉电阻确定。

 

#define GPBCON          (*(volatile unsigned long *)0x56000010)

#define GPDAT            (*(volatile unsigned long *)0x56000014)

#define GPB5_out    (1<<(5*2))

GPBCON = GPB5_out;        //GPB5引脚设为输出

GPBDAT &= ~(1<<5);       //GPB5输出低电平

 

如果某个BANK的位宽被设为n,访问此BANK时,在总线上永远只会看到地址对齐的n位操作。

 

c语言代码点亮一个LED

@******************************************************************************
@ File:crt0.S
@ 功能:通过它转入C程序
@******************************************************************************

.text
.global _start
_start:
             ldr r0, =0x56000010 @ WATCHDOG寄存器地址
             mov r1, #0x0
             str r1, [r0] @ 写入0,禁止WATCHDOG,否则CPU会不断重启

             ldr sp, =1024*4 @ 设置堆栈,注意:不能大于4k, 因为现在可用的内存只有4K
                                     @ nand flash中的代码在复位后会移到内部ram中,此ram只有4K
            bl main @ 调用C程序中的main函数
halt_loop:
            b halt_loop

 

c代码

#define GPBCON (*(volatile unsigned long *)0x56000010)
#define GPBDAT (*(volatile unsigned long *)0x56000014)

#define GPB5_out (1<<(5*2))
#define GPB6_out (1<<(6*2))
#define GPB7_out (1<<(7*2))
#define GPB8_out (1<<(8*2))

void wait(unsigned long dly)
{
         for(; dly > 0; dly--);
}

int main(void)
{
        unsigned long i = 0;

         GPBCON = GPB5_out|GPB6_out|GPB7_out|GPB8_out; // 将LED1-4对应的GPB5/6/7/8四个引脚设为输出

         while(1){
                    wait(30000);
                    GPBDAT = (~(i<<5)); // 根据i的值,点亮LED1-4
                    if(++i == 16)
                               i = 0;
                  }

          return 0;
}

 

 

s3c2410/s3c2440对外引出的27跟地址线ADDR0~ADDR26的访问范围只有128MB,CPU对外还引出了8根片选信号nGCS0~nGCS7,

对应于BANK0~BANK7,当访问BANKx的地址空间时,nGCSx引脚输出低电平用来选中外接的设备,这样8个nGCSx信号总共就对应了1GB的地址空间。

 

s3c2410/s3c2440作为32位的CPU,可以使用的地址范围理论上达到4GB,除去用于连接外设的1GB地址空间外,

还有一部分是CPU内部寄存器地址,剩下的地址空间没有使用。

 

s3c2410/s3c2440的寄存器地址范围都处于0x4800000~0x5FFFFFFF

 

SDRAM的内部是一个存储阵列,阵列就如同表格一样,将数据“填”进去。和表格的检索原理一样,先制定一个行(Row),再制定一个列(Column),

就可以准确的找到所需要的单元格,这就是SDRAM寻址的基本原理。

 

BANK0~BANK5只需要设置BWSCON和BANKCONx两个寄存器;BANK6、BANK7外接SDRAM时,出BWSCON和BANKCONx外还要设置REFRESH、BANKSIZE、MRSRB6、MRSRB7等七个寄存器。

BWSCON----位宽和等待控制寄存器

BANKCONx-----BANK控制寄存器

 

MMU---内存管理单元,负责虚拟地址到物理地址的映射,并提供硬件机制的内存访问权限检查。

4种映射长度:段 1MB、大页 64KB、小页 4KB、极小页 1KB

 

ARM CPU上的地址转换涉及3个概念:虚拟地址 VA、变换后的虚拟地址 MVA、物理地址 PA

启动MMU后,CPU核对外发出虚拟地址VA;VA被转换为MVA供cache、MMU使用,再这里MVA被转换为PA;

最后使用PA读写实际设备(s3c2410/s3c2440内部寄存器或外接的设备)。

 

如果VA<32M,需要使用进程标示号PID(通过读CP15的C13获得)来转换为MVA。

if(VA < 32M) then 

  MVA = VA | (PID<<25)   //VA < 32M

else 

  MVA = VA                        //VA >= 32M

使用PID生成MVA的目的是为了减少切换进程时的代价:不使用MVA而直接使用VA的话,当两个进程所使用的虚拟地址空间(VA)有重叠时,在切换进程时为了把重叠的VA映射到不同的PA上去,需要重建页表、使无效caches和TLBS等,代价非常大。使用MVA后,进程切换就省事多了,假设两个进程1,2运行时的VA都是0~32M,他们的MVA并不重叠,分别是0x02000000~0x03ffffff  0x4000000~0x05ffffff这样就不必进行重建页表等工作。

 

页表有一个个条目组成,每个条目存储了一段虚拟地址对应的物理地址及其访问权限,或者下一级页表的地址。

 

通过使用一个高速、容量相对较小的存储器来存储近期用到的页表条目(段/大页/小页/极小页描述符),以避免每次地址转换时都到主存去查找,这样可以大幅地提高性能。 --------------TLB (Translation Lookaside Buffers)

 

启用Cache后,CPU写数据时有写穿式(Write Through)和回写式(Write Back)

Write Through---CPU发出的写信号送到cache的同时,也写入主存。操作简单,但是由于主存慢速,降低了系统的写熟读并占用了总线时间。

Write Back------数据一般只写到cache,这样有可能出现cache中的数据得到更新而主存中的数据不变(数据陈旧)的情况,此时可在cache中设一标志地址及数据陈旧的消息,只有当cache中的数据被换出或强制进行“清空”操作时,才将原更新的数据写入主存相应的单元中。保证了cache和主存中的数据保持一致。

 

 

posted on 2014-03-01 07:46  oldstorm  阅读(262)  评论(0编辑  收藏  举报