3. 内存控制器与SDRAM

内存控制器(内存接口设备)在这里插入图片描述

地址处于不同的范围,会发出不同的片选引脚,换句话说,SOC外接的不同内存芯片,会有不同的地址范围。
CPU统一编址包括GPIO,各种协议类接口控制器(UART,I2C…),内存设备接口,nand flash控制器(nand flash芯片本身不受cpu统一编址)。每个片选信号可选择的地址范围空间为128M,至少需要27条地址线。

CPU发送32为地址 -> 内存控制器 -> 发出27为地址信号和片选信号

时序图分析

可编程访问周期
2440读时序图
在这里插入图片描述
Nor Flash芯片时序图
在这里插入图片描述
在这里插入图片描述
要根据内存芯片手册,修改时序图中的各种值。芯片默认值都是最保险的,无法发挥cpu的性能。
为简单起见,我们设置2440芯片片选(CE#)读信号(OE#)地址信号同时发出,保持70nm

内存控制器相关寄存器(Nor Flash)

总线位宽和等待控制寄存器
在这里插入图片描述在这里插入图片描述
Bank控制寄存器
在这里插入图片描述
设置Tacc[10:8] = 100
init.c

#include "s3c2440_soc.h"

void bank0_tacc_set(int val)
{
	BANKCON0 = val << 8;
}

init.h

#ifndef _INIT_H
#define _INIT_H

void bank0_tacc_set(int val);

#endif

uart.c

#include "s3c2440_soc.h"


/* 115200,8n1 */
void uart0_init()
{
	/* 设置引脚用于串口 */
	/* GPH2,3用于TxD0, RxD0 */
	GPHCON &= ~((3<<4) | (3<<6));
	GPHCON |= ((2<<4) | (2<<6));

	GPHUP &= ~((1<<2) | (1<<3));  /* 使能内部上拉 */
	

	/* 设置波特率 */
	/* UBRDIVn = (int)( UART clock / ( buad rate x 16) ) –1
	 *  UART clock = 50M
	 *  UBRDIVn = (int)( 50000000 / ( 115200 x 16) ) –1 = 26
	 */
	UCON0 = 0x00000005; /* PCLK,中断/查询模式 */
	UBRDIV0 = 26;

	/* 设置数据格式 */
	ULCON0 = 0x00000003; /* 8n1: 8个数据位, 无较验位, 1个停止位 */

	/*  */

}

int putchar(int c)
{
	/* UTRSTAT0 */
	/* UTXH0 */

	while (!(UTRSTAT0 & (1<<2)));
	UTXH0 = (unsigned char)c;
	
}

int getchar(void)
{
	while (!(UTRSTAT0 & (1<<0)));
	return URXH0;
}

int puts(const char *s)
{
	while (*s)
	{
		putchar(*s);
		s++;
	}
}

uart.h

#ifndef _UART_H
#define _UART_H

void uart0_init();
int putchar(int c);
int getchar(void);
int puts(const char *s);

#endif

main.c

#include "s3c2440_soc.h"
#include "uart.h"
#include "init.h"

int main(void)
{
	unsigned char c;
	
	uart0_init();
	puts("Enter the Tacc val: \n\r");
	
	while(1)
	{
		c = getchar();
		putchar(c);
		if (c >= '0' && c <= '7')
		{
			bank0_tacc_set(c - '0');
			led_test();
		}
		else
		{
			puts("Error, val should between 0~7\n\r");
			puts("Enter the Tacc val: \n\r");
		}
	}
	return 0;
}

设置将程序烧写到nor flash上,设置为nor启动,用串口设置不同的值,观察灯的闪烁。

SDRAM基础知识

看本专栏《内存SDRAM》

2440内存控制器设置

我们SDRAM的地址是在Bnak6上
在这里插入图片描述

  • 我们用两个芯片位宽位16位的SDRAM芯片,组成32位物理位宽 DW6[25:24] = 10
  • 当cpu发出读写信号,芯片还是没有准备好数据,可以向cpu发送一个wait信号,我们不需要,WS6[26] = 0
  • 读写是否精确到byte。不需要,读出一个32位数据,内存控制器选择byte即可。ST6[26] = 0

在这里插入图片描述
设置SDRAM,只需要设置MT[16:15]、Trcd[3:2]、SCAN[1:0]。
SCAN[1:0]:列地址,查看芯片手册,得到9位。
Trcd[3:2]:行地址和列地址之间delay多长时间。看芯片手册时20ns

SDRAM在使用过程中需要不断去刷新它
刷新寄存器
在这里插入图片描述
使能刷新,自动刷新
Refresh Counter[10:0] :
在这里插入图片描述
查看芯片手册,可以算到1269

在这里插入图片描述
在这里插入图片描述
CL[6:4]:sdram收到列地址后,等一会才会返回数据

SDRAM测试程序
在SDRAM中写一个值,再读取,测试是否正确。

init.c init.h

#include "s3c2440_soc.h"

void sdram_init(void)
{
	BWSCON = 0x22000000;

	BANKCON6 = 0x18001;
	BANKCON7 = 0x18001;

	REFRESH  = 0x8404f5;

	BANKSIZE = 0xb1;

	MRSRB6   = 0x20;
	MRSRB7   = 0x20;
}

int sdram_test(void)
{
	volatile unsigned char *p = (volatile unsigned char *)0x30000000;
	int i;

	// write sdram
	for (i = 0; i < 1000; i++)
		p[i] = 0x55;

	// read sdram
	for (i = 0; i < 1000; i++)
		if (p[i] != 0x55)
			return -1;

	return 0;
}
#ifndef _INIT_H
#define _INIT_H

void sdram_init(void);
int sdram_test(void);

#endif

main.c

#include "s3c2440_soc.h"
#include "uart.h"
#include "init.h"

int main(void)
{
	uart0_init();

	sdram_init();

	if (sdram_test() == 0)
		led_test();
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值