zoukankan      html  css  js  c++  java
  • 【连载】【FPGA黑金开发板】NIOS II那些事儿FLASH实验(十五)

    声明:本文为原创作品,版权归本博文作者所有,如需转载,请注明出处http://www.cnblogs.com/kingst/

    P5101981

          这一节,我们来讲一讲如何使用FLASH。在嵌入式系统中,Flash 是最常用组件之一。许多使用过 FLASH的都知道,FLASH 的特点是“读来容易写来难”。通常情况,我们是可以直接读出 FLASH中的内容的,但如果要写入数据,就要发送一长串命令,比如像:555 ,AA,2AA,55,555,A0,PA,PD就表示对PA地址写入数据PD。

          而在NIOS开发过程中,FLASH的这些繁琐的擦写过程ALTERA都帮我们做好了,它通过API给我们提供了完善的读写函数,我们只需要调用函数就可以完成读写FLASH的操作了。不过这些也是有前提条件的,那就是FLASH要满足CFI标准或者是EPCSX串行FLASH(与EPCSX兼容的也是可以的)。也就是说,不满足满足这个条件的 FLASH还需要您自己处理了,呵呵!下面我们来研究一下NIOS下的FLASH是如何操作的。

          在前面,我们就已经详细讲述了FLASH和EPCS模块的构建过程,在这里,我们假设您已经构建好了CFI FLASH模块或者EPCS控制模块,由于CFI FLASH和EPCS的软件操作方式完全一致,所以我们以下内容不对他们加以区分。下面我们主要来讲FLASH的软件操作是如何实现的。

          Altera提供了两种类型的函数,提供给客户:Simple Flash Access(简单的Flash访问),以及Fine-Grained Flash Access(细粒度Flash访问)。

    一般情况下,我还是推荐大家使用 Fine-Grained Flash Access(细粒度 Flash 访问)函数, 比 Simple Flash Access 也复杂不了多少,但可以避免通常的跨块擦除问题。Flash 是按照 Block组织起来的,通常一次擦除一整个块。例如,我们如果写 Flash的时候跨越了两个块,而其后还跟随了其他数据,这样我们就有可能将其他数据同时擦除掉,导致数据的丢失,这样后果就很严重了。

    在这里,我们介绍几个常用的函数,如果想了解的更详细,请参考ALTERA提供的文档资料。

          首先介绍第一步: 打开 Flash,就像C程序打开硬盘中的数据文件一样, 使用之前要打开 FLASH。我们使用 alt_flash_open_dev()打开 Flash,成功打开后返回一个句柄。比如,下面是使用这个函数的片断:

    alt_flash_fd* fd; 
    fd = alt_flash_open_dev(FLASH_NAME);

          其中,FLASH_NAME可以在system.h中找到它的定义,我的定义如下所示

    CFI FLASH定义为
    #define CFI_FLASH_NAME "/dev/cfi_flash"
    EPCSX定义为
    #define EPCS_FLASH_NAME "/dev/epcs_flash"

          读出 Flash 使用函数:alt_read_flash,原型如下:

    int alt_read_flash( alt_flash_fd* fd, 
    int offset, 
    void* dest_addr, 
    int length );

          使用完以后需要将FLASH关掉,其原型如下:

    void alt_flash_close_dev(alt_flash_fd* fd );

    Fine-Grained Flash Access 机制还提供了如下几个函数: alt_get_flash_info(),

    alt_erase_flash_block(), alt_write_flash_block()。

    alt_get_flash_info()可以提取 Flash 的信息,比如包含几个区域,每个区域有几个块,每个块的大小等等。它的原型如下:

    int ret_code = 0; 
    int number_of_regions=0; 
    flash_region* regions; 
    ret_code = alt_get_flash_info(fd, &regions, &number_of_regions);

    这里涉及到一个结构:flash_region,原型如下:

    typedef struct flash_region {
            int offset; /* region相对FLASH首地址的偏移量 */
            int region_size;        /* region的大小*/ 
            int number_of_blocks;   /* 每个region中block的数量 */ 
            int block_size;/* block的大小*/ 
    }flash_region;

          擦除一个块使用函数:alt_flash_fd,函数原型如下:

    int alt_erase_flash_block( alt_flash_fd* fd,int offset,int length);

          写入一个块使用函数:alt_write_flash_block,函数原型如下:

    int alt_write_flash_block( alt_flash_fd* fd, 
                                    int block_offset, 
                                    int data_offset, 
                                    const void *data, 
                                    int length);

          几个常用的函数就介绍完了,下面我们就用这几个函数来操作FLASH吧。

    #include "sys/alt_flash.h" 
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h> 
     
    #define BUF_SIZE 100
    #define FLASH_OFFSET 0x5000
     /* 
     * ===  FUNCTION  ===================================================
     *         Name:  main
     *  Description:  主函数,函数入口
     * =================================================================
     */
    int main (void)
    {   
    	int i;
        alt_flash_fd* fd;
        flash_region* regions;
        int number_of_regions;
        int ret_code = 0x0;
        unsigned char source[BUF_SIZE];
        unsigned char dest[BUF_SIZE];
    
        for(i=0;i<100;i++){
                source[i] = i;
        }
        fd = alt_flash_open_dev("/dev/cfi_flash");
        //fd = alt_flash_open_dev(“/dev/epcs_flash”);//EPCSX   
        if (fd){ 
        /*得到FLASH信息*/
                ret_code = alt_get_flash_info(fd, &regions, &number_of_regions);  
                for(i=0;i<number_of_regions;i++){ 
                        printf("Start 0x%8x End 0x%8x Number of Blocks %3d Block Size 0x%8x \n", (regions+i)->offset, 
                                    (regions+i)->region_size+(regions+i)->offset, 
                       (regions+i)->number_of_blocks, 
                       (regions+i)->block_size); 
                    }
                    
                    alt_erase_flash_block(fd, FLASH_OFFSET, BUF_SIZE);
                    //读FLASH中的数据,成功后返回值为0
                    ret_code = alt_read_flash(fd,FLASH_OFFSET,dest,BUF_SIZE);
        
                    if(ret_code != 0){
                            printf("Can't read flash device\n");
                            exit(-1);
                    }
                    else{
                            printf("Read Flash Device Successfully.\n");
                    }
        
                    //打印读取的数据
                    for(i=0;i<100;i++){
                            printf("%d\n",dest[i]);
                    }  
                    //向FLASH中写数据,成功后返回值为0
                    ret_code = alt_write_flash(fd,FLASH_OFFSET,source,BUF_SIZE);
        
                    if(ret_code != 0){
                            printf("Can't write flash device\n");
                            exit(-1);
                    }
                    else{
                            printf("Write Flash Device Successfully.\n");
                    }
        
                    //读FLASH中的数据,成功后返回值为0
                    ret_code = alt_read_flash(fd,FLASH_OFFSET,dest,BUF_SIZE);
        
                    if(ret_code != 0){
                            printf("Can't read flash device\n");
                            exit(-1);
                    }
                    else{
                            printf("Read Flash Device Successfully.\n");
                    }
        
                    //打印读取的数据
                    for(i=0;i<100;i++){
                            printf("%d\n",dest[i]);
                    }              
            }
            
            alt_flash_close_dev(fd);
    }

          上述程序对于CFI FLASH 和EPCSX是通用的,如果操作EPCSX,则将alt_flash_open_dev("/dev/cfi_flash")参数改为”/dev/epcs_flash”就可以了。

          下面我们来看一看通过alt_get_flash_info(fd, &regions, &number_of_regions)得到的一些CFI FLASH信息,

    Start 0x0     End 0x4000   Number of Blocks  1   Block Size 0x4000 
    
    Start 0x4000  End 0x8000   Number of Blocks  2   Block Size 0x2000 
    
    Start 0x8000  End 0x10000  Number of Blocks  1   Block Size 0x8000 
    
    Start 0x10000 End 0x200000 Number of Blocks 31   Block Size 0x10000

          通过上面的信息,我们可以看出,AM29LV160B这款FLASH的包括了1个16Kbyte,2个8Kbyte,1个32Kbyte和31个64Kbyte字节的block,这个是FLASH处在8位模式下的情况,结构很奇怪吧。

          我们再来看通过alt_get_flash_info(fd, &regions, &number_of_regions)得到的一些EPCSX的信息,

    Start 0x0    End 0x80000    Number of Blocks   8     Block Size 0x10000

    通过上面信息我们可以发现,我用的这款EPCSX是EPCS4,包括了8个128Kbit的block。这个结构就相对比较简单了。

          好了,这一节内容就讲完了。如果大家对此有疑问,或者发现我讲的内容有问题可以直接跟我联系,邮箱:avic633@gmail.com;qq:984597569,同时欢迎大家加入我们的NIOS群:109711029,大家共同探讨NIOS技术!

  • 相关阅读:
    Linux CentOS7.0 (04)systemctl vs chkconfig、service
    SpringCloud是否值得引入?
    SpringCloud的Hystrix(二) 某消费者应用(如:ui、网关)访问的多个微服务的断路监控
    SpringCloud的Hystrix(一) 一个消费者内的两个服务监控
    SpringCloud的Bus(一)消息中间件的概念和用途
    api-gateway实践(13)新服务网关
    SpringCloud应用入库后乱码问题
    SpringCloud的应用发布(四)vmvare+linux,网关代理
    SpringCloud的DataRest(四)restful特性展示
    win10 如何让其他机器访问自己机器上的mysql
  • 原文地址:https://www.cnblogs.com/kingst/p/1743837.html
Copyright © 2011-2022 走看看