GPIO
内置寄存器,BASE地址由外设所在设备接口处决定,这样就可以确定每个寄存器的地址;
要使用输出先要使能,要用中断也先要使能;
测试实验-数码管驱动
数码管与GPIO的输出接口连接
编写汇编语言
1.使能输出端口
2.禁止中断
3.写入输出寄存器
.org 0x0
.set noat
.set noreorder
.set nomacro
.global _start
_start:
lui $1,0x2000
ori $1,$1,0x0008
lui $2,0xffff
ori $2,$2,0xffff
sw $2,0x0($1)
lui $1,0x2000
ori $1,$1,0x000c
lui $2,0x0000
ori $2,$2,0x0000
sw $2,0x0($1)
lui $1,0x2000
ori $1,$1,0x0004
lui $2,0x4740
ori $2,$2,0x4106
sw $2,0x0($1)
修改链接语言的入口地址,起始地址为flash的地址
MEMORY
{
ram : ORIGIN = 0x30000000, LENGTH = 0x00000300
}
UART
当Line Control Register (LCR)寄存器的第7bit为1时,地址Base + 0x0、base +0x1对应的就是两个分频系数寄存器,反之,对应的是上表的寄存器。
UART测试实验
汇编语言测试代码:
1.设置分频系数寄存器(先对LCR寄存器最高位置1)
2.UART寄存器初始化,设置LCR寄存器(设置接收数据格式)
置UART收、发数据格式为8位数据位、没有奇偶校验位、1位停止位。
3.写入发送数据(在地址0x10000000THR用于发送写入的数据)
4.检查UART控制器是否发送数据完毕,如果发送完毕,那么回到第三段,将寄存器$3加1,再次通过UART发送,否则,等待数据发送完毕。其中,检查是否发送完毕的方法就是读取Line Status寄存器的值,Line Status寄存器的第5bit是发送FIFO空标志,如果数据发送完毕,那么会设置该位为1。
在通过UART发送数据时注意,虽然UART控制器具有了FIFO,但是最好也不要连续快速发送数据,否则容易发生FIFO满的情况,导致数据丢失。所以,在测试程序中,在发送数据前都要先判断发送FIFO是否为空。
.org 0x0
.set noat
.set noreorder
.set nomacro
.global _start
_start:
lui $1,0x1000
ori $1,$1,0x0003
ori $2,$0,0x80
sb $2,0x0($1)
lui $1,0x1000
ori $1,$1,0x0001
ori $2,$0,0x00
sb $2,0x0($1) # MSB of divisor latch
lui $1,0x1000
ori $1,$1,0x0000
ori $2,$0,0xB0
sb $2,0x0($1) # LSB of divisor latch
lui $1,0x1000
ori $1,$1,0x0003
ori $2,$0,0x03
sb $2,0x0($1) # 8bit, no parity, 1 stop bit
ori $3,$0,0x0
_loop1:
addi $3,$3,0x1
lui $1,0x1000
ori $1,$1,0x0000
sb $3,0x0($1) # transmit $3
_loop2:
lui $1,0x1000
ori $1,$1,0x0005
lb $2,0x0($1) # get line status register
andi $2,$2,0x20
beq $2,$0,_loop2
nop
j _loop1
nop
Flash
读时序如上图,其中tacc表示给出地址到数据输出的延时,这个需要根据flash'的型号来确定(查询芯片手册找到tacc的最大值)
如最大70ns,那么用50MHZ的(20ns)时钟周期需要等待4个时钟周期(这里需要修改原程序代码,原程序是基于27MHZ)
另外本flash是NOR flash(使用字进行访问),还需要查看芯片手册确定数据线宽,如果是8位,那么需要对32位指令读四次
SDRAM
SDRAM (Synchronous Dynamic Random Access Memory)是同步(时钟同步)动态(存储列阵需要不断刷新)随机(自定义读写地址)访问存储器
如何确定读写地址?
内部是多个阵列(Bank)组成,寻址时给出Bank编号,Bank内部通过行列地址确定:
容量计算?
SDRAM的容量就等于“Bank数量*存储单元宽度*地址数(行地址*列地址)”
配置计算?
需要查看手册确定参数
有以下几点说明。
(1)模式寄存器配置为1000000000表示CAS延迟为3个时钟周期,突发长度为2 (一次读出16bit, 2次正好32bit),突发模式是线性(Linear)。
(2)参数cfg_ sdr_ cas是CAS延迟的值,应该等于模式寄存器中配置的值,但是笔者在实验的过程中发现该值不能等于模式寄存器中配置的值,而是要比后者的值大1,所以此处设置为3"b100。
(3) A3V64S40ETP-G6芯片的每个Bank有4096 行,此处设置每次刷新的最大行数cfg_sdr_rfmax为4,所以在64ms内要求有1024次刷新,每次刷新之间的时间间隔是(64/1024)ms。另外,小型SOPC计划使用DE2开发平台上提供的27MHz时钟源作为工作时钟,(64/1024) ms即大约1688个时钟周期,所以设置cfg_ sdr_ rfsh 为12'b01101001 1000。
如果50MHZ的时钟,(64/1024) ms即大约3125个时钟周期,所以设置cfg_ sdr_ rfsh =12'b1100 0011 0101。