改编版K9F2G08U0A程序

来源:互联网 发布:unity3d前景 编辑:程序博客网 时间:2024/04/20 00:30
根据韦东山老师教材编写的K9F2G08U0A的驱动程序编写方法 ,改编K9F2G08U0A驱动代码,在天嵌开发板上验证成功,下面给出完整工程。芯片datasheet详见:http://wenku.baidu.com/link?url=NAiybcJG_7IR28CXapf4kLtlaXpwscozV3zOPnSIfACrppXfboAhKHYcWfcSWBYkvjz6MOo_hBSXxPmmvWCiqs9JLThoL8v7BGOAqmPfgo7

附录:
(1)head.S
@******************************************************************************
@ File:head.s
@ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行
@******************************************************************************       
  
.text
.global _start
_start:
                                            @函数disable_watch_dog, memsetup, init_nand, nand_read_ll在init.c中定义
            ldr     sp, =4096               @设置堆栈 
            bl      disable_watch_dog       @关WATCH DOG
   bl      clock_init
            bl      memsetup                @初始化SDRAM
            bl      nand_init               @初始化NAND Flash
   bl      RdNF2SDRAM1
            ldr     sp, =0x34000000         @设置栈
            ldr     lr, =halt_loop          @设置返回地址
            ldr     pc, =main               @b指令和bl指令只能前后跳转32M的范围,所以这里使用向pc赋值的方法进行跳转
halt_loop:
            b       halt_loop
(2)inc.c

/* WOTCH DOG register */
#define WTCON(*(volatile unsigned long *)0x53000000)
#defineCLKDIVN(*(volatile unsigned long *)0x4c000014)
#defineMPLLCON(*(volatile unsigned long *)0x4c000004)

/* SDRAM regisers */
#define S3C2440_MPLL_400MHZ     ((0x7f<<12)|(0x02<<4)|(0x01))
#define MEM_CTL_BASE0x48000000
void disable_watch_dog();
void memsetup();
void clock_init(void);
/*上电后,WATCH DOG默认是开着的,要把它关掉 */
void disable_watch_dog()
{
WTCON= 0;
}

void clock_init(void)
{
    // LOCKTIME = 0x00ffffff;   // 使用默认值即可
    CLKDIVN  = 0x05;            // FCLK:HCLK:PCLK=1:4:8, HDIVN=2,PDIVN=1

    /* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
__asm__(
    "mrc    p15, 0, r1, c1, c0, 0\n"        /* 读出控制寄存器 */ 
    "orr    r1, r1, #0xc0000000\n"          /* 设置为“asynchronous bus mode” */
    "mcr    p15, 0, r1, c1, c0, 0\n"        /* 写入控制寄存器 */
    );

   MPLLCON = S3C2440_MPLL_400MHZ;  /* 现在,FCLK=400MHz,HCLK=100MHz,PCLK=50MHz */
}
/* 设置控制SDRAM的13个寄存器 */
void memsetup()
{
int i = 0;
unsigned long *p = (unsigned long *)MEM_CTL_BASE;

    /* SDRAM 13个寄存器的值 */
    unsigned long  const    mem_cfg_val[]={ 0x22011110,     //BWSCON
                                            0x00000700,     //BANKCON0
                                            0x00000700,     //BANKCON1
                                            0x00000700,     //BANKCON2
                                            0x00000700,     //BANKCON3  
                                            0x00000700,     //BANKCON4
                                            0x00000700,     //BANKCON5
                                            0x00018005,     //BANKCON6
                                            0x00018005,     //BANKCON7
                                            0x008C07A3,     //REFRESH
                                            0x000000B1,     //BANKSIZE
                                            0x00000030,     //MRSRB6
                                            0x00000030,     //MRSRB7
                                    };

for(; i < 13; i++)
p[i] = mem_cfg_val[i];
}
 
(3)main.c
#define GPBCON      (*(volatile unsigned long *)0x56000010)      


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


#define led1out (1<<2*5)       

//实验中跑马灯有四个灯要循环,故此需要四组输出控制来配置GPBCON 
#define led2out (1<<2*6) 
#define led3out (1<<2*7) 
#define led4out (1<<2*8) 
void delay(unsigned long i) 
  while(i--);     
 
int main() 
{   
GPBCON |= led1out|led2out|led3out|led4out;    //配置GPB5到GPB8端口输出属性
int i=0;  
while(1) 
    { 
  GPBDAT = ~(1<<(i%4+5));                      //亮灯
  delay(10000);                                          //延时
  i++;                                                            //换灯变量
    } 
    return 0;
}  
 
(4)nand.c

#define TACLS   1

#define TWRPH0  5

#define TWRPH1  0

#define NFDATA        (*(volatile unsigned char *)0x4e000010)//nand flash数据寄存器

typedef unsigned int S3C24X0_REG32;
/* NAND FLASH (see S3C2440 manual chapter 6, www.100ask.net) */
typedef struct {
    S3C24X0_REG32   NFCONF;
    S3C24X0_REG32   NFCONT;
    S3C24X0_REG32   NFCMD;
    S3C24X0_REG32   NFADDR;
    S3C24X0_REG32   NFDATA0;
    S3C24X0_REG32   NFMECCD0;
    S3C24X0_REG32   NFMECCD1;
    S3C24X0_REG32   NFSECCD;
    S3C24X0_REG32   NFSTAT;
} S3C2440_NAND;

static S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;


void SendAD(unsigned long AD)
{
//s3c2440nand->NFADDR=AD;
volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR;
*p=AD;

}
/* 发出片选信号 */
static void s3c2440_nand_select_chip(void)
{
    s3c2440nand->NFCONT &= ~(1<<1);
}

/* 取消片选信号 */
static void s3c2440_nand_deselect_chip(void)
{
    s3c2440nand->NFCONT |= (1<<1);
}

/* S3C2440的NAND Flash操作函数 */

/* 复位 */
static void s3c2440_nand_reset(void)
{
    s3c2440nand->NFCONT &= ~(1<<1);

s3c2440nand->NFSTAT |= (1<<2);

s3c2440nand->NFCMD  = (0xff); 

while(!(s3c2440nand->NFSTAT&(1<<2)));  //test busy

s3c2440nand->NFCONT |= (1<<1);
}

/* 等待NAND Flash就绪 */
void s3c2440_wait_idle(void)
{
    int i;
    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFSTAT;
    while(!(*p & (1<<2)));
}



/* 初始化NAND Flash */
void nand_init(void)
{

        s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(3<<2)|(1<<1);
        s3c2440nand->NFCONT =  (1<<4)|(1<<1)|(1<<0);
        s3c2440nand->NFSTAT =0x0;      
        s3c2440_nand_reset();
}

void nand_read(unsigned int block,unsigned int page,unsigned char *dstaddr)
{
    int i;
unsigned int blockpage=(block<<6)+page;
   
s3c2440_nand_reset();
        s3c2440nand->NFCONT &= ~(1<<1);
s3c2440nand->NFSTAT |= (1<<2);
s3c2440nand->NFCMD  = (0x00);//send_cmd(readp1); 
SendAD(0x00);
SendAD(0x00);
SendAD((blockpage)&0xff);
SendAD((blockpage>>8)&0xff);
SendAD((blockpage>>16)&0x01);
s3c2440nand->NFCMD  = (0x30);//send_cmd(readp2);
while(!(s3c2440nand->NFSTAT&(1<<2)));  //test busy
for(i=0;i<2048;i++)
{
dstaddr[i]=NFDATA;
}
s3c2440nand->NFCONT |= (1<<1);

    
    return ;
}

void RdNF2SDRAM(void)//将nand flash的代码复制到sdram中去
{
unsigned int i;
unsigned int start_addr =4096;//4096表示第4096个字节
unsigned char * dstaddr = (unsigned char *)0x30000000;/*留心指针类型转换*/ 
unsigned int size = 2048;  //大小2018 B
for(i = (start_addr >> 11); size > 0;i ++ )//因为NAND_SECTOR_SIZE等于2048个字节,所以page就等于start_addr右移了11位,因为
{//2^11=2048。这里i表示页的绝对地址,即该页距离第0页的绝对地址
nand_read(i/64,i%64, dstaddr);
size -= 2048;
dstaddr += 2048;

}
}
/* 发出地址 */
static void s3c2440_write_addr(unsigned int addr)
{
    int i;
    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR;
    *p = addr&0xff;

*p = addr&0xf0;
    
    *p = (addr >> 11) & 0xff;
    
*p = (addr >> 19) & 0xff;
    *p = (addr >> 27) & 0x01;
   
}

void RdNF2SDRAM1(void)//将nand flash的代码复制到sdram中去
{
unsigned int i,j;
unsigned int start_addr =4096;//4096表示第4096个字节
unsigned char * dstaddr = (unsigned char *)0x30000000;/*留心指针类型转换*/ 
unsigned int size = 2048;  //大小2048B

unsigned int blockpage=start_addr>>11;
   for(i=start_addr;i<start_addr+size;)
{
s3c2440_nand_reset();
    s3c2440nand->NFCONT &= ~(1<<1);
s3c2440nand->NFSTAT |= (1<<2);
s3c2440nand->NFCMD  = (0x00);//send_cmd(readp1); 
    s3c2440_write_addr(i);

s3c2440nand->NFCMD  = (0x30);//send_cmd(readp2);
while(!(s3c2440nand->NFSTAT&(1<<2)));  //test busy
for(j=0;j<size;j++,i++)
{
dstaddr[j]=NFDATA;
}
s3c2440nand->NFCONT |= (1<<1);
}
}

(5)Makefile
objs := head.o init.o  nand.o main.o

nand.bin : $(objs)
arm-linux-ld -Tnand.lds-o nand_elf $^
arm-linux-objcopy -O binary -S nand_elf $@
arm-linux-objdump -D -m arm  nand_elf > nand.dis

%.o:%.c
arm-linux-gcc -nostdlib -Wall -c  -o $@ $<

%.o:%.S
arm-linux-gcc -nostdlib -Wall -c  -o $@ $<

clean:
rm -f  nand.dis nand.bin nand_elf *.o
(6)nand.lds
SECTIONS { 
  firtst  0x00000000 : { head.o init.o  nand.o }
  second0x30000000 : AT(4096){main.o}
 
0 0
原创粉丝点击