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

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

    4

    一、简介

          这一节,我们来聊聊SDRAM吧。作为NIOS系统中最重要的一个外部器件,它担任着重要的角色,大家对它也应该很熟悉。每次上电的时候,FPGA都会把FLASH中的程序送到SDRAM中运行,之所以这样来做就是因为它的速度很快,但它掉电是要丢失数据的,所以要把数据存到FLASH中。

          有关SDRAM的理论知识我在这里不说了,不知道的百度google一下都可以。其实在NIOS II开发过程中,就算你对SDRAM的理论知识不了解,也不耽误你对它的使用。SOPC builder都已经完美的将它驱动起来,我们只要知道怎么使用它就可以了。下面,我们就来讲讲他的使用方法,其实真的很简单。

          在我们讲第一节的时候,我们就已经讲了如何构建SDRAM的控制器了,我在这里不再重复了,假设你已经构建好了,我主要讲一下有关软件的部分。

    二、软件开发

          首先打开NIOS II 9.0 IDE软件,打开后,我们来看看system.h文件,确定一下SDRAM控制器模块是否已经加入进来。如果加入,有下面的内容出现

    #define SDRAM_NAME "/dev/sdram"
    
    #define SDRAM_TYPE "altera_avalon_new_sdram_controller"
    
    #define SDRAM_BASE 0x01000000
    
    ……
     

    接下来,我们开始编写有关SDRAM的软件代码,代码很简单,如下所示

    /*
     * ==================================================================
    *       Filename:  main.c
    *    Description:  SDRAM读写试验
     *        Version:  1.0.0
     *        Created:  2010.4.16
     *       Revision:  none
     *       Compiler:  Nios II 9.0 IDE
     *         Author:  马瑞 (AVIC)
     *          Email:  avic633@gmail.com  
     * =================================================================
     */
    
    /*----------------------------------------------------------------
     * Include 
     *----------------------------------------------------------------*/
    #include <stdio.h>
    #include "../inc/sopc.h"
    #include "system.h"
    #include "string.h"
    
    /*---------------------------------------------------------------
     *  Variable
     *---------------------------------------------------------------*/
    unsigned short * ram = (unsigned short *)(SDRAM_BASE+0x10000); //SDRAM地址
    
    /* 
     * ===  FUNCTION  ===================================================
     *         Name:  main
     *  Description:  函数主程序
     * =================================================================
     */
    int main(void)
    {
        int i;
        
        memset(ram,0,100);
        //向ram中写数据,当ram写完以后,ram的地址已经变为(SDRAM_BASE+0x10100)
        for(i=0;i<100;i++){
            *(ram++) = i;
        }
    
        //逆向读取ram中的数据
        for(i=0;i<100;i++){
            printf("%d\n",*(--ram));
        }
           
        return 0;
    }

          程序很简单,就是向指定的SDRAM中赋值。在这个程序里面有几个地方需要说明一下。首先,我在程序前面定义了一个unsigned short类型的指针变量ram,并将其指向SDRAM+0x10000这个位置。之所以设置为unsigned short数据类型,是因为我们用的SDRAM是16位数据总线的。而将其指向SDRAM+0x10000是因为在NIOS II运行时会用到SDRAM的部分空间,我们必须避开这部分空间,以免运行错误。0x10000这个值不是固定的,只要避开SDRAM的那部分空间就可以了。除此之外还有一个地方需要注意,就是当我们对sdram赋值以后,指针就会向后移动,指向下一个地址空间,每加一次,地址都会向后面移动16位。假如我们现在是在SDRAM+0X10000这个位置,当指针向后移动一次以后,地址就变为了SDRAM+0X10002,再加一次就变为了SDRAM+0X10004,以此类推。这些都是内部自动处理的,不需要我们来参与,我们只要知道就可以了。

          其实我讲这部分内容是想告诉大家,SDRAM控制器一旦构建好以后,我们对SDRAM的处理就像对内部地址一样,我们可以随意的进行赋值和读取。对于开发板上的64Mbit的SDRAM其实有很少一部分用给NIOS系统,其余部分都在空闲,大家是不是觉得很浪费呢。其实在有些情况下,我们就可以利用起这部分资源,比如在某个系统中,我们需要将外设接收到的数据缓存一下,我们就可以用这部分空闲的SDRAM空间来处理。

          在C语言中,如果我们要接收比较大的数据,还有另一种处理方法,那就是借助堆(heap)。可能有些人对堆和栈还分不清楚,我在这简单解释一下。栈(stack) 由系统自动分配。 例如,声明在函数中一个局部变量 int b,系统自动在栈中为b开辟空间。而堆(heap)需要程序员自己申请,并指明大小。有人用这样一个比喻来解释堆和栈的区别,非常形象贴切:使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大,这个人真是太有才了。下面我来写一个堆的代码,这部分代码是节选的,并不完全,功能是通过xmodem协议接收数据,并将其内容放到堆里面。如下所示

    /* 
     * ===  FUNCTION  ==================================================
     *         Name:  main
     *  Description:  主函数
     * =================================================================
     */
    int main()
    {    
        char *ram = (char *)malloc ( sizeof(char)* 500000 );
    
        if ( ram==NULL ) {
            fprintf ( stderr, "\ndynamic memory allocation failed\n" );
            exit (EXIT_FAILURE);
        }        
    
        uart.init();
        
        /*------------------- FLASH -----------------------------*/
        
        while(1){
            if(uart.mode_flag){ 
                xmodem.xmodem_rx();
                printf("ram_cnt:%d\n",ram_cnt);
                parse_srecord_buf(ram,ram_cnt);
                printf("successful!");
                ram_cnt = 0;
                uart.mode_flag = 0;
            }
                            
        }
    
        free (ram);
            
        return 0;
    }

          看了上面的代码大家应该了解了堆的用法了吧,它是通过malloc向系统中申请空间的。申请成功以后,就会返回申请地址的首地址,失败则返回NULL。到底申请在什么地方,我们可以通过打印指针来得知,但并没这个必要,因为这些都是系统来处理的,我们得到了首地址然后用就可以了。需要注意一点,我们申请完的地址用完以后需要释放,用free来释放就可以了。如果不释放,可能会出现内存泄露问题,到时候麻烦就大了,具体大到什么程度我也不知道,呵呵。

          可能有人会问,为什么不用栈来处理这个问题呢?这就跟编译有关系了,在编译过程中,系统会将栈需要的空间加到代码中,也就是说如果你在代码中用栈来处理大的数据,那么你编译以后的代码会非常大,你下载到flash以后,加载到sdram中的时间也会非常之长。而堆这不会,系统对堆的处理方式是何时用合适分配,并不占代码空间。

          说到这,有关SDRAM部分的内容讲完了。总结一下,使用SDRAM有两种方法,第一种是直接对SDRAM地址处理;第二种方法就是利用堆来处理。好了,这部分内容就讲到这吧,如果大家对此有疑问,或者发现我讲的内容有问题可以直接跟我联系,邮箱:avic633@gmail.com;qq:984597569。

  • 相关阅读:
    RESTful
    Node.js Express 框架
    Node.js Web 模块
    Node.js Path 模块
    JavaFX输入并显示字符串
    JavaFX手眼协调小游戏(赋源代码)
    JavaFX作业七参考
    管理运筹学(Additional Simplex Algorithm)
    JavaFX15.4 ( 创建一个簡单的计算器 ) 编写一个程序完成加法、减法、乘法和除法操作
    JavaFX移动小球
  • 原文地址:https://www.cnblogs.com/kingst/p/1725428.html
Copyright © 2011-2022 走看看