s3c2440时钟+nandflash拷贝至SDRAM+开启mmu

来源:互联网 发布:天天向上网络版权费 编辑:程序博客网 时间:2024/06/05 15:50
涉及6个文件
head.S,init.c,main.c,makefile,nand.c,out.lds

head.S
.text.global _start_start:    b   ResetHandleUndef:    b   HandleUndef HandleSWI:    b   HandleSWIHandlePrefetchAbort:    b   HandlePrefetchAbortHandleDataAbort:    b   HandleDataAbortHandleNotUsed:    b   HandleNotUsed    b   HandleIRQHandleFIQ:    b   HandleFIQReset:ldr r0, =0x53000000mov r1, #0x0str r1, [r0]@disable watchdogmsr cpsr_c, #0xd2@IRQ mode,ARM mode,IRQ disableldr sp, =3072 msr cpsr_c, #0xd3@Supervisor mode,ARM mode,IRQ disableldr sp, =1024*4@set up stack,4Kmsr cpsr_c, #0x53@Supervisor mode,ARM mode,IRQ enableldr sp, =4096bl clock_initbl memsetupbl nand_init       ldr r0, =0x30000000@target address(sdram),nand_read 1parameter       mov r1, #4096@start address,nand_read 2parameter       mov r2, #2048*2@size copy to sdram,nand_read 3parameterbl nand_readbl  create_page_tablebl  mmu_init ldr sp, =0xB4000000@pstack go to sdramldr lr, =halt_loopldr pc, =mainhalt_loop:b halt_loopHandleIRQ:sub lr, lr, #4stmdb sp!, {r0-r12,lr}   ldr lr, =int_return             ldr pc, =TIMER_Handle            int_return:ldmia sp!, { r0-r12,pc }^

init.c
#defineBWSCON(*(volatile unsigned long *)0x48000000)  #defineBANKCON0(*(volatile unsigned long *)0x48000004)#defineBANKCON1(*(volatile unsigned long *)0x48000008)#defineBANKCON2(*(volatile unsigned long *)0x4800000C)#defineBANKCON3(*(volatile unsigned long *)0x48000010)#defineBANKCON4(*(volatile unsigned long *)0x48000014)#defineBANKCON5    (*(volatile unsigned long *)0x48000018)#defineBANKCON6    (*(volatile unsigned long *)0x4800001C)#defineBANKCON7    (*(volatile unsigned long *)0x48000020)#defineREFRESH       (*(volatile unsigned long *)0x48000024)#defineBANKSIZE     (*(volatile unsigned long *)0x48000028)#defineMRSRB6(*(volatile unsigned long *)0x4800002C)#defineMRSRB7(*(volatile unsigned long *)0x48000030)#defineCLKDIVN(*(volatile unsigned long *)0x4C000014)#defineMPLLCON(*(volatile unsigned long *)0x4C000004)#define S3C2440_MPLL_400MHZ 0x5C011void memsetup(){BWSCON=0x22011110;BANKCON0=0x00000700;//sramBANKCON1=0x00000700;//romBANKCON2=0x00000700;BANKCON3=0x00000700;BANKCON4=0x00000700;BANKCON5=0x00000700;BANKCON6=0x00018005;//sdramBANKCON7=0x00018005;REFRESH=0x008C04F4;BANKSIZE=0x000000B1;MRSRB6=0x00000030;MRSRB7=0x00000030;}void clock_init(){CLKDIVN=0x05;__asm__(    "mrc    p15, 0, r1, c1, c0, 0\n"    "orr    r1, r1, #0xc0000000\n"    "mcr    p15, 0, r1, c1, c0, 0\n"    );      MPLLCON=S3C2440_MPLL_400MHZ;}void create_page_table(void){#define MMU_FULL_ACCESS     (3 << 10) #define MMU_DOMAIN          (0 << 5)#define MMU_SPECIAL         (1 << 4)  #define MMU_CACHEABLE       (1 << 3) #define MMU_BUFFERABLE      (1 << 2) #define MMU_SECTION         (2)     #define MMU_SECDESC         (MMU_FULL_ACCESS | MMU_DOMAIN | MMU_SPECIAL | MMU_SECTION)#define MMU_SECDESC_WB      (MMU_FULL_ACCESS | MMU_DOMAIN | MMU_SPECIAL | \                             MMU_CACHEABLE | MMU_BUFFERABLE | MMU_SECTION)#define MMU_SECTION_SIZE    0x00100000    unsigned long virtuladdr, physicaladdr;    unsigned long *mmu_tlb_base = (unsigned long *)0x30000000;    virtuladdr = 0;    physicaladdr = 0;    *(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) | MMU_SECDESC_WB;//0~4096 the same        virtuladdr = 0x56000000;    physicaladdr = 0x56000000;    *(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) | MMU_SECDESC;    virtuladdr = 0x4A000000;    physicaladdr = 0x4A000000;    *(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) | MMU_SECDESC;    virtuladdr = 0x51000000;    physicaladdr = 0x51000000;    *(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) | MMU_SECDESC;    /*SDRAM to 0xB0000000~0xB4000000*/    virtuladdr = 0xB0000000;    physicaladdr = 0x30000000;    while (virtuladdr < 0xB4000000)    {        *(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) | MMU_SECDESC_WB;        virtuladdr += 0x100000;        physicaladdr += 0x100000;    }}/* * 启动MMU */void mmu_init(void){    unsigned long ttb = 0x30000000;__asm__(    "mov    r0, #0\n"    "mcr    p15, 0, r0, c7, c7, 0\n"      "mcr    p15, 0, r0, c7, c10, 4\n"    "mcr    p15, 0, r0, c8, c7, 0\n"      "mov    r4, %0\n"                  "mcr    p15, 0, r4, c2, c0, 0\n"      "mvn    r0, #0\n"                       "mcr    p15, 0, r0, c3, c0, 0\n"       "mrc    p15, 0, r0, c1, c0, 0\n"     "bic    r0, r0, #0x3000\n"       "bic    r0, r0, #0x0300\n"      "bic    r0, r0, #0x0087\n"     "orr    r0, r0, #0x0002\n"     "orr    r0, r0, #0x0004\n"    "orr    r0, r0, #0x1000\n"     "orr    r0, r0, #0x0001\n"     "mcr    p15, 0, r0, c1, c0, 0\n"      :    : "r" (ttb) );}

main.c
/*led1 f4,led2 f5,led3 f6,int0 f0*/#defineGPFCON(*(volatile unsigned long *)0x56000050)#defineGPFDAT(*(volatile unsigned long *)0x56000054)#defineGPF4_OUT(1<<(4*2))#defineGPF5_OUT(1<<(5*2))#defineGPF6_OUT(1<<(6*2))#defineGPF4_CON_MSK(3<<(4*2))#defineGPF5_CON_MSK(3<<(5*2))#defineGPF6_CON_MSK(3<<(6*2))#defineGPF4_DAT_MSK(1<<(4))#defineGPF5_DAT_MSK(1<<(5))#defineGPF6_DAT_MSK(1<<(6))#define TIMER0_MSK(1<<(10))#defineTCFG0(*(volatile unsigned long *)0x51000000)#defineTCON(*(volatile unsigned long *)0x51000008)#defineTCNTB0(*(volatile unsigned long *)0x5100000C)#define INTOFFSET(*(volatile unsigned long *)0x4A000014)#define SRCPND(*(volatile unsigned long *)0X4A000000)#define INTMSK(*(volatile unsigned long *)0X4A000008)#define PRIORITY(*(volatile unsigned long *)0x4A00000C)#define INTPND(*(volatile unsigned long *)0X4A000010)void init_timer0(){SRCPND=0x0;INTMSK=~TIMER0_MSK;TCFG0=0xff;TCNTB0=0xffff;TCON=0xa;TCON=0x9;}void led_set_out(){GPFCON&=~(GPF4_CON_MSK|GPF5_CON_MSK|GPF6_CON_MSK);    GPFCON|=GPF4_OUT|GPF5_OUT|GPF6_OUT;GPFDAT&=~(GPF4_DAT_MSK);GPFDAT&=~(GPF5_DAT_MSK);GPFDAT&=~(GPF6_DAT_MSK);GPFDAT|=(1<<4);GPFDAT|=(1<<5);GPFDAT|=(1<<6);}void led_reset(int ledn){if(ledn==1){GPFDAT|=(1<<4);}else if(ledn==2){GPFDAT|=(1<<5);}else{GPFDAT|=(1<<6);}}void led_set(int ledn){if(ledn==1){GPFDAT&=~(GPF4_DAT_MSK);}else if(ledn==2){GPFDAT&=~(GPF5_DAT_MSK);}else{GPFDAT&=~(GPF6_DAT_MSK);}}void TIMER_Handle(){int i;led_set(1);for(i=0;i<1000000;i++);led_reset(1);SRCPND=1<<INTOFFSET;INTPND=1<<INTOFFSET;}int main(){int i;led_set_out();init_timer0();while(1){led_reset(2);for(i=0;i<10000000;i++);led_set(2);for(i=0;i<10000000;i++);}return 0;}

makefile
out.bin : head.S  main.c nand.c init.carm-linux-gcc -c -o head.o head.Sarm-linux-gcc -c -o main.o main.carm-linux-gcc -c -o nand.o nand.carm-linux-gcc -c -o init.o init.carm-linux-ld -Tout.lds head.o main.o nand.o init.o -o out_elfarm-linux-objcopy -O binary -S out_elf out.binarm-linux-objdump -D -m arm  out_elf > out.dis#rm -f out.dis out_elf *.oclean:rm -f out.dis out.bin out_elf *.o

nand.c
#define LARGER_NAND_PAGE#define GSTATUS1        (*(volatile unsigned int *)0x560000B0)#define BUSY            1#define NAND_SECTOR_SIZE    512#define NAND_BLOCK_MASK     (NAND_SECTOR_SIZE - 1)#define NAND_SECTOR_SIZE_LP    2048#define NAND_BLOCK_MASK_LP     (NAND_SECTOR_SIZE_LP - 1)typedef unsigned int S3C24X0_REG32;/* NAND FLASH (see S3C2410 manual chapter 6) */typedef struct {    S3C24X0_REG32   NFCONF;    S3C24X0_REG32   NFCMD;    S3C24X0_REG32   NFADDR;    S3C24X0_REG32   NFDATA;    S3C24X0_REG32   NFSTAT;    S3C24X0_REG32   NFECC;} S3C2410_NAND;/* 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   NFDATA;    S3C24X0_REG32   NFMECCD0;    S3C24X0_REG32   NFMECCD1;    S3C24X0_REG32   NFSECCD;    S3C24X0_REG32   NFSTAT;    S3C24X0_REG32   NFESTAT0;    S3C24X0_REG32   NFESTAT1;    S3C24X0_REG32   NFMECC0;    S3C24X0_REG32   NFMECC1;    S3C24X0_REG32   NFSECC;    S3C24X0_REG32   NFSBLK;    S3C24X0_REG32   NFEBLK;} S3C2440_NAND;typedef struct {    void (*nand_reset)(void);    void (*wait_idle)(void);    void (*nand_select_chip)(void);    void (*nand_deselect_chip)(void);    void (*write_cmd)(int cmd);    void (*write_addr)(unsigned int addr);    unsigned char (*read_data)(void);}t_nand_chip;static S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;static S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;static t_nand_chip nand_chip;/* 供外部调用的函数 */void nand_init(void);void nand_read(unsigned char *buf, unsigned long start_addr, int size);/* NAND Flash操作的总入口, 它们将调用S3C2410或S3C2440的相应函数 */static void nand_reset(void);static void wait_idle(void);static void nand_select_chip(void);static void nand_deselect_chip(void);static void write_cmd(int cmd);static void write_addr(unsigned int addr);static unsigned char read_data(void);/* S3C2410的NAND Flash处理函数 */static void s3c2410_nand_reset(void);static void s3c2410_wait_idle(void);static void s3c2410_nand_select_chip(void);static void s3c2410_nand_deselect_chip(void);static void s3c2410_write_cmd(int cmd);static void s3c2410_write_addr(unsigned int addr);static unsigned char s3c2410_read_data();/* S3C2440的NAND Flash处理函数 */static void s3c2440_nand_reset(void);static void s3c2440_wait_idle(void);static void s3c2440_nand_select_chip(void);static void s3c2440_nand_deselect_chip(void);static void s3c2440_write_cmd(int cmd);static void s3c2440_write_addr(unsigned int addr);static unsigned char s3c2440_read_data(void);/* S3C2410的NAND Flash操作函数 *//* 复位 */static void s3c2410_nand_reset(void){    s3c2410_nand_select_chip();    s3c2410_write_cmd(0xff);  // 复位命令    s3c2410_wait_idle();    s3c2410_nand_deselect_chip();}/* 等待NAND Flash就绪 */static void s3c2410_wait_idle(void){    int i;    volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFSTAT;    while(!(*p & BUSY))        for(i=0; i<10; i++);}/* 发出片选信号 */static void s3c2410_nand_select_chip(void){    int i;    s3c2410nand->NFCONF &= ~(1<<11);    for(i=0; i<10; i++);    }/* 取消片选信号 */static void s3c2410_nand_deselect_chip(void){    s3c2410nand->NFCONF |= (1<<11);}/* 发出命令 */static void s3c2410_write_cmd(int cmd){    volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFCMD;    *p = cmd;}/* 发出地址 */static void s3c2410_write_addr(unsigned int addr){    int i;    volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFADDR;        *p = addr & 0xff;    for(i=0; i<10; i++);    *p = (addr >> 9) & 0xff;    for(i=0; i<10; i++);    *p = (addr >> 17) & 0xff;    for(i=0; i<10; i++);    *p = (addr >> 25) & 0xff;    for(i=0; i<10; i++);}/* 读取数据 */static unsigned char s3c2410_read_data(void){    volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFDATA;    return *p;}/* S3C2440的NAND Flash操作函数 *//* 复位 */static void s3c2440_nand_reset(void){    s3c2440_nand_select_chip();    s3c2440_write_cmd(0xff);  // 复位命令    s3c2440_wait_idle();    s3c2440_nand_deselect_chip();}/* 等待NAND Flash就绪 */static void s3c2440_wait_idle(void){    int i;    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFSTAT;    while(!(*p & BUSY))        for(i=0; i<10; i++);}/* 发出片选信号 */static void s3c2440_nand_select_chip(void){    int i;    s3c2440nand->NFCONT &= ~(1<<1);    for(i=0; i<10; i++);    }/* 取消片选信号 */static void s3c2440_nand_deselect_chip(void){    s3c2440nand->NFCONT |= (1<<1);}/* 发出命令 */static void s3c2440_write_cmd(int cmd){    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFCMD;    *p = cmd;}/* 发出地址 */static void s3c2440_write_addr(unsigned int addr){    int i;    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR;        *p = addr & 0xff;    for(i=0; i<10; i++);    *p = (addr >> 9) & 0xff;    for(i=0; i<10; i++);    *p = (addr >> 17) & 0xff;    for(i=0; i<10; i++);    *p = (addr >> 25) & 0xff;    for(i=0; i<10; i++);}static void s3c2440_write_addr_lp(unsigned int addr){int i;volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR;int col, page;col = addr & NAND_BLOCK_MASK_LP;page = addr / NAND_SECTOR_SIZE_LP;*p = col & 0xff;/* Column Address A0~A7 */for(i=0; i<10; i++);*p = (col >> 8) & 0x0f; /* Column Address A8~A11 */for(i=0; i<10; i++);*p = page & 0xff;/* Row Address A12~A19 */for(i=0; i<10; i++);*p = (page >> 8) & 0xff;/* Row Address A20~A27 */for(i=0; i<10; i++);*p = (page >> 16) & 0x03;/* Row Address A28~A29 */for(i=0; i<10; i++);}/* 读取数据 */static unsigned char s3c2440_read_data(void){    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFDATA;    return *p;}/* 在第一次使用NAND Flash前,复位一下NAND Flash */static void nand_reset(void){    nand_chip.nand_reset();}static void wait_idle(void){    nand_chip.wait_idle();}static void nand_select_chip(void){    int i;    nand_chip.nand_select_chip();    for(i=0; i<10; i++);}static void nand_deselect_chip(void){    nand_chip.nand_deselect_chip();}static void write_cmd(int cmd){    nand_chip.write_cmd(cmd);}static void write_addr(unsigned int addr){    nand_chip.write_addr(addr);}static unsigned char read_data(void){    return nand_chip.read_data();}/* 初始化NAND Flash */void nand_init(void){#define TACLS   0#define TWRPH0  3#define TWRPH1  0    /* 判断是S3C2410还是S3C2440 */    if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))    {        nand_chip.nand_reset         = s3c2410_nand_reset;        nand_chip.wait_idle          = s3c2410_wait_idle;        nand_chip.nand_select_chip   = s3c2410_nand_select_chip;        nand_chip.nand_deselect_chip = s3c2410_nand_deselect_chip;        nand_chip.write_cmd          = s3c2410_write_cmd;        nand_chip.write_addr         = s3c2410_write_addr;        nand_chip.read_data          = s3c2410_read_data;/* 使能NAND Flash控制器, 初始化ECC, 禁止片选, 设置时序 */        s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);    }    else    {        nand_chip.nand_reset         = s3c2440_nand_reset;        nand_chip.wait_idle          = s3c2440_wait_idle;        nand_chip.nand_select_chip   = s3c2440_nand_select_chip;        nand_chip.nand_deselect_chip = s3c2440_nand_deselect_chip;        nand_chip.write_cmd          = s3c2440_write_cmd;#ifdef LARGER_NAND_PAGE        nand_chip.write_addr         = s3c2440_write_addr_lp;#elsenand_chip.write_addr = s3c2440_write_addr;#endif        nand_chip.read_data          = s3c2440_read_data;/* 设置时序 */        s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);        /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */        s3c2440nand->NFCONT = (1<<4)|(1<<1)|(1<<0);    }        /* 复位NAND Flash */    nand_reset();}/* 读函数 */void nand_read(unsigned char *buf, unsigned long start_addr, int size){    int i, j;#ifdef LARGER_NAND_PAGE    if ((start_addr & NAND_BLOCK_MASK_LP) || (size & NAND_BLOCK_MASK_LP)) {        return ;    /* 地址或长度不对齐 */    }#else    if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {        return ;    /* 地址或长度不对齐 */    }#endif    /* 选中芯片 */    nand_select_chip();    for(i=start_addr; i < (start_addr + size);) {      /* 发出READ0命令 */      write_cmd(0);      /* Write Address */      write_addr(i);#ifdef LARGER_NAND_PAGE      write_cmd(0x30);#endif      wait_idle();#ifdef LARGER_NAND_PAGE      for(j=0; j < NAND_SECTOR_SIZE_LP; j++, i++) {#else  for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {#endif          *buf = read_data();          buf++;      }    }    /* 取消片选信号 */    nand_deselect_chip();        return ;}

out.lds
SECTIONS {   firtst  0x00000000 : { head.o nand.o init.o}  second 0xB0000000 : AT(4096) { main.o }} 



0 0
原创粉丝点击