uboot烧写

下载

这里使用uboot-2015对应的编译器用arm-linux-gcc-4.4.3
uboot-2015
arm-linux-gcc-4.4.3

编译
cd u-boot-2015.10-mini2440/
make mini2440_defconfig
make CROSS_COMPILE=/root/git/arm-linux-gcc-4.4.3/bin/arm-linux-

烧写到Norflash运行

clipboard.png

uboot下Norflash测试

开发板使用的IC型号是SST33VF1601

芯片手册里的命令列表

clipboard.png

读取norflash的0地址和uboot验证

可以看出完全一样
clipboard.png
clipboard.png

读Manufacturer ID和Device ID
Norflash接收
读/写 地址 数据
0x5555 0xAA
0x2AAA 0x55
0x5555 0x90
0x0 Manufacturer ID
0x1 Device ID
因为CPU的A1接到Nor的A0所以地址需要在Nor的地址上左移1位发出
读/写 地址 数据 Uboot命令
0xAAAA 0xAA mw.w aaaa aa
0x5554 0x55 mw.w 5554 55
0xAAAA 0x90 mw.w aaaa 90
0x0 Manufacturer ID md.w 0 1
0x2 Device ID md.w 2 1

clipboard.png

clipboard.png
可以看出实验结果完全一致,然后使用命令往任意地址写0xF0退出读ID状态

读CFI信息

clipboard.png

进入CFI模式(uboot运行命令)
读/写 地址 数据 Uboot命令
0xAAAA 0xAA mw.w aaaa aa
0x5554 0x55 mw.w 5554 55
0xAAAA 0x98 mw.w aaaa 98
进入CFI模式后读数据(部分命令,完整命令请查阅手册)
读/写 地址 数据 Uboot命令
0x20 0x51(ASCII - Q) md.w 20 1
0x22 0x52 (ASCII - R) md.w 22 1
0x24 0x59 (ASCII - Y) md.w 24 1
0x4E Device size = 2^N md.w 4E 1

实验结果
clipboard.png
完成之后使用命令往任意地址写0xF0退出读CFI状态

写数据

首先测试norflash无法直接写入,往0x100000(1M)的地方写入1234,结果没有任何改变

clipboard.png

再继续测试往0x30000000(SDRAM起始地址)写入1234发现可以写入

clipboard.png

往norflash写入数据之前要保证写入的地方数据是全1的即需要先进行擦除

读/写 地址 数据 Uboot命令
0xAAAA 0xAA mw.w aaaa aa
0x5554 0x55 mw.w 5554 55
0xAAAA 0xA0 mw.w aaaa a0
地址 数据 mw.w WA Data

clipboard.png

擦除操作
Sector擦除
读/写 地址 数据 Uboot命令
0xAAAA 0xAA mw.w aaaa aa
0x5554 0x55 mw.w 5554 55
0xAAAA 0x80 mw.w aaaa 80
0xAAAA 0xAA mw.w aaaa aa
0x5554 0x55 mw.w 5554 55
擦除地址 0x30 mw.w WA 30

clipboard.png
要保证操作在复位状态下才可以擦除

C语言实现Norflash擦读写等命令

Norflash启动时基地址base为0,并且norflash可以像内存一样访问可以通过指针直接操作。
下面代码的offset可以看成是norflash接收到的命令,因为CPU的A1 -> NORflash的A0,所以发出的地址需要左移1位(即乘2),*p = val往p变量里保存的地址直接赋值。
char *p类型指针说明指向的数据是8位的,因为命令就是8位。
printf("%08x ", sector_addr)表示以8个16进制字符打印高位补0

写命令代码
void nor_write_word(unsigned int base, unsigned int offset, char val){
    volatile char *p = (volatile char *)(base + (offset << 1));
    *p = val;
}
读命令代码
unsigned short nor_read_word(unsigned int base, unsigned int offset){
    volatile unsigned short *p = (volatile unsigned short *)(base + (offset << 1));
    return *p;
}
读Norflash部分代码
void do_scan_nor_flash(){
    unsigned short m_id, d_id;
     char str[4];
    unsigned int size;
    unsigned short sector_num, sector_size;
    unsigned short block_num, block_size;
    int i, j;
    unsigned int sector_addr; 
    
    //进入cfi模式
    nor_cmd(0x5555, 0xaa);  
    nor_cmd(0x2aaa, 0x55);
    nor_cmd(0x5555, 0x98);
    
    //打印string
    str[0] = nor_dat(0x10);
    str[1] = nor_dat(0x11);
    str[2] = nor_dat(0x12);
    str[3] = '\0';
    printf("str = %s\n\r", str);
    
    //打印容量
    size = 1 << (nor_dat(0x27));
    printf("nor size = 0x%x, %dM\n\r", size, size/(1024*1024));
    
    //读sectors数量
    sector_num = ((nor_dat(0x2e) << 8) | nor_dat(0x2d)) + 1;
    printf("sector_num = %d\n\r", sector_num);
    //读sectors大小
    sector_size = ((nor_dat(0x30) << 8) | nor_dat(0x2f)) * 256 / 1024;
    printf("sector_size = %dKByte/sector\n\r", sector_size);
    
    //读block数量
    block_num = ((nor_dat(0x32) << 8) | nor_dat(0x31)) + 1;
    printf("block_num = %d\n\r", block_num);
    //读block大小
    block_size = ((nor_dat(0x34) << 8) | nor_dat(0x33)) * 256 / 1024;
    printf("block_size = %dKByte/block\n\r", block_size);
    
    
    nor_cmd(0x0, 0xf0);//退出
    
    //打印厂家ID、设备ID
    nor_cmd(0x5555, 0xaa);
    nor_cmd(0x2aaa, 0x55);
    nor_cmd(0x5555, 0x90);
    m_id = nor_dat(0x00);
    d_id = nor_dat(0x01);
    nor_cmd(0x0, 0xf0);//退出
    
    printf("Manufacturer ID = %x\n\r", m_id);
    printf("Device ID = %x\n\r", d_id);
    
    //打印所有sectors的起始地址
    printf("Sectors : \n\r");
    sector_addr = 0;
    for(i=0; i<64; i++){
        for(j=0; j<8; j++){
            //printf("%x ", *p);
            //p++;//指向下一个数据
            printf("%08x ", sector_addr);
            sector_addr = sector_addr + 0x1000;
        }
        printf("\n\r");
    }
    
/*     printf("0 = %x\n\r", *(volatile char *)0);
    printf("1 = %x\n\r", *(volatile char *)1);
    printf("2 = %x\n\r", *(volatile char *)2);
    printf("3 = %x\n\r", *(volatile char *)3);
    printf("4 = %x\n\r", *(volatile char *)4);
    printf("5 = %x\n\r", *(volatile char *)5);
    printf("6 = %x\n\r", *(volatile char *)6);
    printf("7 = %x\n\r", *(volatile char *)7); */
    printf("=================\n\r");
}

Sector起始地址(4KB/sector)

00000000 00001000 00002000 00003000 00004000 00005000 00006000 00007000
00008000 00009000 0000a000 0000b000 0000c000 0000d000 0000e000 0000f000
00010000 00011000 00012000 00013000 00014000 00015000 00016000 00017000
00018000 00019000 0001a000 0001b000 0001c000 0001d000 0001e000 0001f000
00020000 00021000 00022000 00023000 00024000 00025000 00026000 00027000
00028000 00029000 0002a000 0002b000 0002c000 0002d000 0002e000 0002f000
00030000 00031000 00032000 00033000 00034000 00035000 00036000 00037000
00038000 00039000 0003a000 0003b000 0003c000 0003d000 0003e000 0003f000
00040000 00041000 00042000 00043000 00044000 00045000 00046000 00047000
00048000 00049000 0004a000 0004b000 0004c000 0004d000 0004e000 0004f000
00050000 00051000 00052000 00053000 00054000 00055000 00056000 00057000
00058000 00059000 0005a000 0005b000 0005c000 0005d000 0005e000 0005f000
00060000 00061000 00062000 00063000 00064000 00065000 00066000 00067000
00068000 00069000 0006a000 0006b000 0006c000 0006d000 0006e000 0006f000
00070000 00071000 00072000 00073000 00074000 00075000 00076000 00077000
00078000 00079000 0007a000 0007b000 0007c000 0007d000 0007e000 0007f000
00080000 00081000 00082000 00083000 00084000 00085000 00086000 00087000
00088000 00089000 0008a000 0008b000 0008c000 0008d000 0008e000 0008f000
00090000 00091000 00092000 00093000 00094000 00095000 00096000 00097000
00098000 00099000 0009a000 0009b000 0009c000 0009d000 0009e000 0009f000
000a0000 000a1000 000a2000 000a3000 000a4000 000a5000 000a6000 000a7000
000a8000 000a9000 000aa000 000ab000 000ac000 000ad000 000ae000 000af000
000b0000 000b1000 000b2000 000b3000 000b4000 000b5000 000b6000 000b7000
000b8000 000b9000 000ba000 000bb000 000bc000 000bd000 000be000 000bf000
000c0000 000c1000 000c2000 000c3000 000c4000 000c5000 000c6000 000c7000
000c8000 000c9000 000ca000 000cb000 000cc000 000cd000 000ce000 000cf000
000d0000 000d1000 000d2000 000d3000 000d4000 000d5000 000d6000 000d7000
000d8000 000d9000 000da000 000db000 000dc000 000dd000 000de000 000df000
000e0000 000e1000 000e2000 000e3000 000e4000 000e5000 000e6000 000e7000
000e8000 000e9000 000ea000 000eb000 000ec000 000ed000 000ee000 000ef000
000f0000 000f1000 000f2000 000f3000 000f4000 000f5000 000f6000 000f7000
000f8000 000f9000 000fa000 000fb000 000fc000 000fd000 000fe000 000ff000
00100000 00101000 00102000 00103000 00104000 00105000 00106000 00107000
00108000 00109000 0010a000 0010b000 0010c000 0010d000 0010e000 0010f000
00110000 00111000 00112000 00113000 00114000 00115000 00116000 00117000
00118000 00119000 0011a000 0011b000 0011c000 0011d000 0011e000 0011f000
00120000 00121000 00122000 00123000 00124000 00125000 00126000 00127000
00128000 00129000 0012a000 0012b000 0012c000 0012d000 0012e000 0012f000
00130000 00131000 00132000 00133000 00134000 00135000 00136000 00137000
00138000 00139000 0013a000 0013b000 0013c000 0013d000 0013e000 0013f000
00140000 00141000 00142000 00143000 00144000 00145000 00146000 00147000
00148000 00149000 0014a000 0014b000 0014c000 0014d000 0014e000 0014f000
00150000 00151000 00152000 00153000 00154000 00155000 00156000 00157000
00158000 00159000 0015a000 0015b000 0015c000 0015d000 0015e000 0015f000
00160000 00161000 00162000 00163000 00164000 00165000 00166000 00167000
00168000 00169000 0016a000 0016b000 0016c000 0016d000 0016e000 0016f000
00170000 00171000 00172000 00173000 00174000 00175000 00176000 00177000
00178000 00179000 0017a000 0017b000 0017c000 0017d000 0017e000 0017f000
00180000 00181000 00182000 00183000 00184000 00185000 00186000 00187000
00188000 00189000 0018a000 0018b000 0018c000 0018d000 0018e000 0018f000
00190000 00191000 00192000 00193000 00194000 00195000 00196000 00197000
00198000 00199000 0019a000 0019b000 0019c000 0019d000 0019e000 0019f000
001a0000 001a1000 001a2000 001a3000 001a4000 001a5000 001a6000 001a7000
001a8000 001a9000 001aa000 001ab000 001ac000 001ad000 001ae000 001af000
001b0000 001b1000 001b2000 001b3000 001b4000 001b5000 001b6000 001b7000
001b8000 001b9000 001ba000 001bb000 001bc000 001bd000 001be000 001bf000
001c0000 001c1000 001c2000 001c3000 001c4000 001c5000 001c6000 001c7000
001c8000 001c9000 001ca000 001cb000 001cc000 001cd000 001ce000 001cf000
001d0000 001d1000 001d2000 001d3000 001d4000 001d5000 001d6000 001d7000
001d8000 001d9000 001da000 001db000 001dc000 001dd000 001de000 001df000
001e0000 001e1000 001e2000 001e3000 001e4000 001e5000 001e6000 001e7000
001e8000 001e9000 001ea000 001eb000 001ec000 001ed000 001ee000 001ef000
001f0000 001f1000 001f2000 001f3000 001f4000 001f5000 001f6000 001f7000
001f8000 001f9000 001fa000 001fb000 001fc000 001fd000 001fe000 001ff000
norflash指定地址读数据

Norflash的读写擦除发出的地址直接对应Norflash的内部地址不需要移位也就是CPU操作0地址对应Norflash的0地址

//从指定地址读4096字节数据
void do_read_nor_flash(){
    unsigned int addr;
    volatile char * p;
    int i, j;
    unsigned char str[16];
    
    printf("Enter the address to read: ");
    addr = get_uint();
    
    p = (volatile char *)addr;
    printf("Data : \n\r");
    
    for(i=0; i<256; i++){
        for(j=0; j<16; j++){
            printf("%02x ", *p);
            str[j] = *p;
            p++;//指向下一个数据
        }
        printf("    ");
        
        //输出ascii字符
        for (j=0; j<16; j++){
            /* 后打印字符 */
            if (str[j] < 0x20 || str[j] > 0x7e)  /* 不可视字符 */
                SendChar('.');
            else
                SendChar(str[j]);
        }
        
        printf("\n\r");
    }
    printf("=================\n\r");
}
norflash指定扇区擦除数据
//扇区擦除
void do_erase_nor_flash(){ 
    unsigned int addr;
    printf("Enter the sector address to erase: ");
    addr = get_uint();
    
    printf("erasing ...\n\r");
    
    nor_cmd(0x5555, 0xaa);  
    nor_cmd(0x2aaa, 0x55);
    nor_cmd(0x5555, 0x80);
    nor_cmd(0x5555, 0xaa); 
    nor_cmd(0x2aaa, 0x55);
    nor_cmd(addr >> 1, 0x30);//扇区擦除 右移1位 抵消nor_cmd里面的左移
    
    wait_ready(addr);//等待擦除结束
    printf("erase success!\n\r");
    printf("=================\n\r");
}
norflash指定地址写入数据
//word写入(16bit)
void do_write_nor_flash(){
    unsigned int addr;
    int i, j;
    unsigned char str[100];
    unsigned int val;
    
    //获得地址
    printf("Enter the address of sector to write: ");
    addr = get_uint();
    
    printf("Enter the string to write: ");
    gets(str);

    printf("writing ...\n\r");
    
    i = 0;
    j = 1;
    while(str[i] && str[j]){
        val = str[i] + (str[j] << 8);//拼接两个字节写入
        
        nor_cmd(0x5555, 0xaa);  
        nor_cmd(0x2aaa, 0x55);
        nor_cmd(0x5555, 0xa0);
        nor_cmd_16bit(addr>>1, val);
        
        wait_ready(addr);
        
        i += 2;
        j += 2;
        addr += 2;
    }    
    
    val = str[i];//写最后一个字节

    nor_cmd(0x5555, 0xaa);  
    nor_cmd(0x2aaa, 0x55);
    nor_cmd(0x5555, 0xa0);
    
    nor_cmd_16bit(addr>>1, val);

    wait_ready(addr);

    printf("write success!\n\r");
    printf("=================\n\r");
}
void nor_cmd_16bit(unsigned int offset, unsigned int cmd){
    //nor_write_word(NOR_FLASH_BASE, offset, cmd);
    volatile unsigned short *p = (volatile unsigned short *)(NOR_FLASH_BASE + (offset << 1));
    *p = cmd;
}

makefile中加入-march=armv4

clipboard.png

完整代码


Kyseng
1 声望3 粉丝

电子爱好者一枚,利用工作空余时间记录一下学习过程