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。

  • 相关阅读:
    背水一战 Windows 10 (90)
    背水一战 Windows 10 (89)
    背水一战 Windows 10 (88)
    背水一战 Windows 10 (87)
    背水一战 Windows 10 (86)
    背水一战 Windows 10 (85)
    背水一战 Windows 10 (84)
    背水一战 Windows 10 (83)
    背水一战 Windows 10 (82)
    背水一战 Windows 10 (81)
  • 原文地址:https://www.cnblogs.com/kingst/p/1725428.html
Copyright © 2011-2022 走看看