mini2440 nandflash简单读写调试成功 代码记录

又裸奔了两天,把mini2440上面的nandflash(型号是K9F1G08U0C 128M*8bit)的简单的页读写和擦除操作调通了,代码先记录下来,复杂的nandflash操作以后有时间再说,现在能够实现代码的搬移已经够了。

head.s

@this is a test program of nandflash, the properties of com0 is the same as usual (115200,8, 1, n, n)

.text
.global _start
_start:
	b		Reset
	b		. @undefined instruction
	b		. @swi
	b		. @pregetch instruction
	b		. @data abort
	b		. @Reserved
	b		HandleIRQ @irq
	b		. @fiq
	
Reset:
	ldr		sp, =4096 @set the stack pointer of sys mode to 4096
	bl		disable_watchdog
	bl		init_led
	bl		init_sdram
	bl		copy_sdram
	ldr		pc, =on_sdram
on_sdram:
	msr		cpsr_c, #0xd2 @set cpu to irq mode
	ldr		sp, =0x31000000 @set the stack pointer of irq mode to sdram
	msr		cpsr_c, #0xdf @reset cpu to sys mode
	ldr		sp, =0x32000000
	
	bl		init_clock
	mov		r0, #1
	mov		r1, #10
	bl		blink
	bl		init_timer0
	mov		r0, #2
	mov		r1, #10
	bl		blink
	bl		init_com0
	mov		r0, #3
	mov		r1, #10
	bl		blink
	bl		init_nandflash
	bl		init_irq
	msr		cpsr_c, #0x5f @enable irq
	bl 		main
	b		.
	
	.ltorg
	.ltorg
	.ltorg
	
HandleIRQ:
	sub		lr, lr, #4
	stmdb	sp!, {r0-r12, lr}
	ldr		lr, =next
	ldr		pc, =interrupt_func
next:
	ldmia	sp!, {r0-r12, pc}^ @return to main
	
	.ltorg
	.ltorg
	


 

init.c

#define		GPBCON		(*((volatile unsigned long*)(0x56000010)))
#define		GPBDAT		(*((volatile unsigned long*)(0x56000014)))
#define		WTCON       (*((volatile unsigned long*)(0x53000000)))
#define		LOCKTIME	(*((volatile unsigned long*)(0x4C000000)))
#define		CLKDIVN		(*((volatile unsigned long*)(0x4C000014)))
#define		MPLLCON		(*((volatile unsigned long*)(0x4C000004)))
#define		TCFG0		(*((volatile unsigned long*)(0x51000000)))
#define		TCFG1		(*((volatile unsigned long*)(0x51000004)))
#define		TCNTB0		(*((volatile unsigned long*)(0x5100000C)))
#define		TCON		(*((volatile unsigned long*)(0x51000008)))
#define		INTMSK		(*((volatile unsigned long*)(0X4A000008)))
#define		INTSUBMASK	(*((volatile unsigned long*)(0X4A00001C)))

#define		GPHCON		(*((volatile unsigned long*)(0x56000070)))
#define		GPHUP		(*((volatile unsigned long*)(0x56000078)))
//control register of com0
#define		ULCON0		(*((volatile unsigned long*)(0x50000000)))
#define		UCON0		(*((volatile unsigned long*)(0x50000004)))
#define		UFCON0		(*((volatile unsigned long*)(0x50000008)))
#define		UMCON0		(*((volatile unsigned long*)(0x5000000C)))
#define		UBRDIV0		(*((volatile unsigned long*)(0x50000028)))


//initilize GPB to output mode
void init_led()
{
	GPBCON  &= (~(0xff<<10));
	GPBCON  |= (0X55<<10);
}

void delay(int times)
{
	int i, j;
	for(i=0; i<times; i++)
	{
		for(j=0; j<1000; j++);	
	}	
}

//blink function is used to debug
void blink(int number, int delay_num)
{	
	GPBDAT	|= (0X0F<<5);
	GPBDAT	&= (~(number<<5));
	delay(delay_num);
	GPBDAT	|= (0X0F<<5);
	delay(delay_num);
}

void disable_watchdog()
{
	WTCON = 0;
}

void init_clock()
{
	LOCKTIME = 0xffffffff;
	CLKDIVN = 0X03; //fclk:hclk:pclk=1:2:4
	__asm__
	(
		"mrc	p15, 0, r1, c1, c0, 0\n"
		"orr	r1, r1, #0xc0000000\n"
		"mcr	p15, 0, r1, c1, c0, 0\n"	
	);
	MPLLCON = (92<<12)|(1<<4)|(2<<0); //fclk=200M, hclk=100M, pclk=50M 
}

void init_sdram()
{
	volatile unsigned long *p = (volatile unsigned long *)(0x48000000);

    p[0] = 0x22011110;     //BWSCON
    p[1] = 0x00000700;     //BANKCON0
    p[2] = 0x00000700;     //BANKCON1
    p[3] = 0x00000700;     //BANKCON2
    p[4] = 0x00000700;     //BANKCON3  
    p[5] = 0x00000700;     //BANKCON4
    p[6] = 0x00000700;     //BANKCON5
    p[7] = 0x00018005;     //BANKCON6
    p[8] = 0x00018005;     //BANKCON7
    p[9]  = 0x008C04F4;		//REFRESH value is different than before, because the clock is different
    p[10] = 0x000000B1;     //BANKSIZE
    p[11] = 0x00000030;     //MRSRB6
    p[12] = 0x00000030;     //MRSRB7
}

void copy_sdram()
{
	unsigned long* src = (unsigned long *)(0);
	unsigned long* des = (unsigned long *)(0x30000000);
	int i;
	
	for(i=0; i<1024; i++)
	{
		des[i] = src[i];
	}
}

void init_timer0()
{
	TCFG0 = 99; //set prescaler value to 100
	TCFG1 = 0x03; //set MUX to 16
	TCNTB0 = 15625;
	TCON = (1<<1);
	TCON = 0x09; //start timer0
}

void init_irq()
{
	//enable interrupt of rxd0 txd0
	INTSUBMASK &= (~(0b11));
	//enable interrupt of uart0
	INTMSK &= (~(1<<28));
}

void init_com0()
{
	//set gph[2:3] used as txd and rxd for com0
	GPHCON &= (~(0xff<<4));
	GPHCON |= (0x0a<<4);

	//disable pull up functon for gph[2:3]
	GPHUP = 0x0c;
	//set properties of com0
	ULCON0 = 0b00000011;
	//enable the rxd and txd, and interrupt will happen when con0 received data or the send buffer is empty in non-fifo mode
	UCON0 = 0b00000101;
	//disable fifo
	UFCON0 = 0x00;
	//disable fifo
	UMCON0 = 0x00;
	//set baud-rate to 115200
	UBRDIV0 = (int)(50000000/(115200*16)) -1;
}


 

com0.c

#define		UTRSTAT0	(*((volatile unsigned long*)(0x50000010)))
#define		UTXH0		(*((volatile unsigned long*)(0x50000020)))
#define		URXH0		(*((volatile unsigned long*)(0x50000024)))

#define		SUBSRCPND	(*((volatile unsigned long*)(0X4A000018)))
#define		SRCPND		(*((volatile unsigned long*)(0X4A000000)))
#define		INTPND		(*((volatile unsigned long*)(0X4A000010)))

extern void blink(int, int);

void put_char(char ch)
{
	while (!(UTRSTAT0 & (1<<2)));
	UTXH0 = ch;
}

unsigned char get_char()
{
	while (!(UTRSTAT0 & (1<<0)));
	return URXH0;
}


void put_string(char *string)
{
	int i = 0;
	while(string[i] != '\0')
		put_char(string[i++]);
}

void com0_read(char *ch)
{
	*ch = URXH0;
}

void com0_write(char ch)
{
	UTXH0 = ch;
}

//the function to serve the uart0 interrupt
void interrupt_func()
{
	char ch;
	//rxd sub interrupt
	if(SUBSRCPND & (1<<0))
	{
		blink(15, 1);
		com0_read(&ch);
		com0_write(ch);
	}
	else if(SUBSRCPND & (1<<1)) //txd interrupt
	{	
		blink(10, 1);
	}

	//clear the interrupt of uart0
	SUBSRCPND = SUBSRCPND;
	SRCPND |= (1<<28);
	INTPND = INTPND;
}


 

nandflash.c

#define		NFCONF		(*((volatile unsigned long*)(0x4E000000)))
#define		NFCONT		(*((volatile unsigned long*)(0x4E000004)))
#define		NFCMMD		(*((volatile unsigned char*)(0x4E000008)))
#define		NFADDR		(*((volatile unsigned char*)(0x4E00000C)))
#define		NFDATA		(*((volatile unsigned char*)(0x4E000010)))
#define		NFSTAT		(*((volatile unsigned long*)(0x4E000020)))

#define		GPACON		(*((volatile unsigned char*)(0x56000000)))

#define		TACLS		1
#define		TWPRH0		1
#define		TWPRH1		1

//command
#define		READ1			0x00
#define		READ2			0X30
#define		RESET			0xff
#define		RANDOM_READ1	0x05
#define		RANDOM_READ2	0xe0
#define		WRITE1			0x80
#define		WRITE2			0x10
#define		RADOM_WRITE		0X85
#define		ERASE1			0X60
#define		ERASE2			0xd0
#define		STATUS			0X70


void nandflash_reset();
void init_nandflash();
void nandflash_select_chip();
void nandflash_deselect_chip();
void nandflash_wait_ready();

extern void put_string(char *);
extern void delay(int);

//initilize the nandflash
void init_nandflash()
{
	//make gpa[17:22] used for nandflash controler
	GPACON |= (0x3f<<17);

	NFCONF = (TACLS<<12)|(TWPRH0<<8)|(TWPRH1<<4);
	NFCONT = (1<<4)|(1<<1)|(1<<0);
	put_string("init nandflash over!\r\n");
	nandflash_reset();
}

//reset the nandflash
void nandflash_reset()
{
	nandflash_select_chip();
	NFCMMD = RESET;
	nandflash_wait_ready();
	nandflash_deselect_chip();
}

void nandflash_select_chip()
{
	NFCONT &= (~(1<<1));
	delay(3);
}

void nandflash_deselect_chip()
{
	NFCONT |= (1<<1);
	delay(3);
}

void nandflash_wait_ready()
{
	while(1)
	{
		if( (NFSTAT&(1<<0)) )
			break;

		delay(1);
	}	
}

void nandflash_read_page(unsigned int page_num, unsigned int length, unsigned char *buffer)
{
	int i;
	nandflash_select_chip();
	NFCMMD = READ1;
	NFADDR = 0x00;
	NFADDR = 0x00;
	NFADDR = (unsigned char)(page_num&0xff);
	NFADDR = (unsigned char)((page_num>>8)&0xff);
	NFCMMD = READ2;
	nandflash_wait_ready();

	for(i=0; i<length;i++)
	{
		buffer[i] = NFDATA;
	}

	nandflash_deselect_chip();
}

unsigned char nandflash_write_page(unsigned int page_num, unsigned int length, unsigned char *buffer)
{
	int i;
	unsigned char status;

	nandflash_select_chip();
	NFCMMD = WRITE1;
	delay(3);
	NFADDR = 0x00;
	NFADDR = 0x00;
	NFADDR = (unsigned char)(page_num&0xff);
	NFADDR = (unsigned char)((page_num>>8)&0xff);
	delay(3);

	for(i=0; i<length;i++)
	{
		NFDATA = buffer[i];
	}
	delay(3);
	NFCMMD = WRITE2;
	delay(30);
	nandflash_wait_ready();

	delay(20);
	NFCMMD = STATUS;
	delay(3);
	status = NFDATA;

	nandflash_deselect_chip();

	if(status & 0x01)
	{
		put_string("write error!\r\n");
		return 0;
	}
	else
	{
		put_string("write compelete!\r\n");
		return 1;
	}
}

unsigned char nandflash_erase_block(unsigned int block_num)
{
	unsigned char status;

	nandflash_select_chip();
	NFCMMD = ERASE1;
	NFADDR = ((block_num<<6)&0b11000000);
	NFADDR = ((block_num>>2)&0xff);
	NFCMMD = ERASE2;

	delay(30);
	nandflash_wait_ready();

	delay(20);
	NFCMMD = STATUS;
	delay(3);
	status = NFDATA;

	nandflash_deselect_chip();

	if(status & 0x01)
	{
		put_string("erase error!\r\n");
		return 0;
	}
	else
	{
		put_string("erase compelete!\r\n");
		return 1;
	}

	nandflash_deselect_chip();
}


main.c

 

extern void put_char(char);
extern unsigned char get_char();
extern void put_string(char *);
extern void blink(int, int);
extern void put_string(char*);
extern void delay(int);

extern void nandflash_read_page(unsigned int page_num, unsigned int length, unsigned char *buffer);
extern unsigned char nandflash_erase_block(unsigned int block_num);
extern unsigned char nandflash_write_page(unsigned int page_num, unsigned int length, unsigned char *buffer);


void change_num_string(unsigned char num, char *buffer)
{
	unsigned char num1, num0;
	num1 = num%16;
	num0 = num/16;
	if(num1 <= 9)
		buffer[1] = num1+'0';
	else
		buffer[1] = num1-10+'A';
	
	if(num0 <= 9)
		buffer[0] = num0+'0';
	else
		buffer[0] = num0-10+'A';

	buffer[2] = '\0';
}


int main(void)
{
	int i;
	unsigned char read_buffer[20];
	unsigned char write_buffer[20];
 	char num[3];

 	for(i=0; i<20; i++)
 	{
 		write_buffer[i] = i;
 	}
 	
 	if(!nandflash_erase_block(1))
 	{
 		return -1;
 	}

 	if(!nandflash_write_page(64, 20, write_buffer))
 	{
 		return -1;
 	}
 	
	nandflash_read_page(64, 20, read_buffer);

	for(i=0; i<20; i++)
	{
		change_num_string(read_buffer[i], num);
		put_string("0x");
		put_string(num);
		put_string("\r\n");
	}

	while(1);
	return 0;
}

 

运行结果:


总结:

        以后调裸机程序一定要好好看datasheet里面的时序图然后再写程序,要不然效率极低,调试太蛋疼。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值