uboot下读写nand flash以及nand_read()函数的实现

1、uboot下NAND操作指令 

       指令              Flash内地址        擦除长度

 nand erase     0x100000            0x200000 
       指令              内存中地址         Flash内地址 写入长度

 nand write     0x20000000        0x100000     0x200000 

nand read      0x20000000        0x100000     0x200000 

关于nand flash的时序分析,http://blog.chinaunix.net/uid-20178794-id-4111272.html这篇文章写得不错

2、分析读nand flash操作的时序图
(1)时序图

(2)相关分析

(3)步骤归纳

  • 发出片选信号,选中nand flash芯片
  • 发出00h命令
  • 发出5个地址序列,前两个对应的是列地址(对应一页中的某一列),后三个是行地址(对应的是某一页)
  • 发出30h命令
  • 等待nand flash准备好数据
  • nand flash准备好数据后,从nand flash 中读取数据
  • 取消片选信号,以确保进行其他与nand flash无关的操作影响到nand flash。

nand_read()函数的实

从nand flash的地址start_addr开始,读取数据大小为size的数据到buf指定的地址里。

void nand_read(unsigned char *buf, unsigned long start_addr, int size)
{
    int i, j;


#ifdef LARGER_NAND_PAGE(由于此宏在源程序中有定义,因而走下面第一路径)

//因为nand flash每次读操作是以page为单位的,而一个page 是2048字节(不同nand flash的page大小不一定相同)

//一个数如果是2048的倍数,低11位必须是0.这里&是按位与的意思,也就是size和start_addr是16进制数,而NAND_BLOCK_MASK_LP是十进制,它们都会转换成二进制,进行按位与操作。这里定义NAND_BLOCK_MASK_LP为2047,也就是首位为0,后11位为1,与2048的二进制首位为1,后11位为0按位相与后为0.
    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);) {
 /*发出00h命令*/
      write_cmd(0);

 /* 发出5个周期的地址序列 */
      write_addr(i);
#ifdef LARGER_NAND_PAGE(程序中有定义,因为要区分nand flash 的大小页构造)

 /*发出30h命令*/

 write_cmd(0x30);
#endif

 /*发出空闲等待信号*/

   wait_idle();


#ifdef LARGER_NAND_PAGE

/*开始读取数据*/
      for(j=0; j < NAND_SECTOR_SIZE_LP; j++, i++) {     //这里的NAND_SECTOR_SIZE_LP定义为2048
#else
 for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
#endif

         *buf = read_data();
          buf++;
      }
    }


 /*取消片选信号*/

    nand_deselect_chip();
    
    return ;
}


  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
U-Boot(Universal Bootloader)是一款开源的、通用的、模块化的嵌入式系统引导加载程序。它可以被用于各种嵌入式系统中,如计算机主板、网络设备、无线设备等。 在U-Boot中,对于Nor Flash读写,主要是通过SPI接口进行的。下面是Nor Flash读写代码的走读: 1. 首先需要定义Nor Flash的设备结构体,其中包括了Nor Flash的基本信息以及对应的读写函数指针。 ``` struct flash_info { char* name; /* 设备名称 */ unsigned long base; /* 设备物理地址 */ unsigned long size; /* 设备大小 */ unsigned long sector_size; /* 扇区大小 */ unsigned long block_size; /* 块大小 */ void (*erase)(unsigned long); /* 擦除函数指针 */ void (*write)(unsigned long, const uchar*, unsigned long); /* 写函数指针 */ uchar (*read)(unsigned long); /* 读函数指针 */ }; ``` 2. 在U-Boot的配置文件中,需要定义Nor Flash的类型以及对应的设备结构体。 ``` #define CONFIG_SPI_FLASH_SST #define CONFIG_SPI_FLASH_WINBOND #define CONFIG_SPI_FLASH_MACRONIX #define CONFIG_SPI_FLASH_SPANSION #define CONFIG_SPI_FLASH_STMICRO #define CONFIG_SPI_FLASH_SST #define CONFIG_SPI_FLASH_ISSI #define CONFIG_SPI_FLASH_EON #define CONFIG_SPI_FLASH_GIGADEVICE #ifdef CONFIG_SPI_FLASH_SST #define CONFIG_FLASH_CFI_DRIVER #define CONFIG_SYS_MAX_FLASH_BANKS_DETECT 1 #define CONFIG_SYS_FLASH_CFI #define CONFIG_SYS_FLASH_PROTECTION #define CONFIG_SYS_FLASH_BASE 0x80000000 #define CONFIG_SYS_FLASH_EMPTY_INFO #define CONFIG_SYS_FLASH_USE_BUFFER_WRITE #endif #ifdef CONFIG_SPI_FLASH_STMICRO #define CONFIG_FLASH_CFI_DRIVER #define CONFIG_SYS_MAX_FLASH_BANKS_DETECT 1 #define CONFIG_SYS_FLASH_CFI #define CONFIG_SYS_FLASH_PROTECTION #define CONFIG_SYS_FLASH_BASE 0x80000000 #define CONFIG_SYS_FLASH_EMPTY_INFO #define CONFIG_SYS_FLASH_USE_BUFFER_WRITE #endif ``` 3. 在Nor Flash的驱动中,需要实现读写、擦除等具体操作函数。 ``` static void spi_flash_cmd_write(struct spi_flash *flash, const void *buf, size_t size, uint32_t addr) { /* 发送写命令 */ spi_flash_cmd_write_enable(flash); spi_flash_cmd_addr(flash, addr, flash->cmd.write); spi_flash_cmd_buf(flash, buf, size); spi_flash_cmd_wait_ready(flash); } static void spi_flash_cmd_read(struct spi_flash *flash, void *buf, size_t size, uint32_t addr) { /* 发送读命令 */ spi_flash_cmd_addr(flash, addr, flash->cmd.read); spi_flash_cmd_buf(flash, NULL, size); spi_flash_cmd_read_data(flash, buf, size); } ``` 4. 在Nor Flash的驱动中,还需要实现设备初始化、扇区擦除等操作。 ``` static int spi_flash_probe(struct spi_flash *flash) { /* 初始化设备 */ spi_flash_cmd_init(flash); /* 读取设备ID */ spi_flash_cmd_read_id(flash); /* 设置读写擦除函数指针 */ flash->write = spi_flash_cmd_write; flash->read = spi_flash_cmd_read; flash->erase = spi_flash_cmd_erase; return 0; } static int spi_flash_erase_sector(struct spi_flash *flash, uint32_t addr) { /* 发送擦除命令 */ spi_flash_cmd_write_enable(flash); spi_flash_cmd_addr(flash, addr, flash->cmd.erase); spi_flash_cmd_wait_ready(flash); return 0; } ``` 5. 在main函数中,需要初始化SPI总线以及Nor Flash设备,并进行读写操作。 ``` int main(void) { /* 初始化SPI总线 */ spi_init(); /* 初始化Nor Flash设备 */ spi_flash_init(); /* 读取数据 */ spi_flash_read_data(FLASH_BASE_ADDR, buf, sizeof(buf)); /* 写入数据 */ spi_flash_write_data(FLASH_BASE_ADDR, buf, sizeof(buf)); /* 擦除扇区 */ spi_flash_erase_sector(FLASH_BASE_ADDR); return 0; } ``` 以上就是Nor Flash读写的主要代码走读。在实际应用中,还需要根据具体的Nor Flash型号以及使用场景进行相应的优化和调整。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值