zoukankan      html  css  js  c++  java
  • 【转】[FPGA博客大赛](updated)在xilinx的FPGA系统中scanf函数的使用

    scanf函数在c语言中,常常作为标准输入函数所使用,
    而xilinx号称他支持标准的c库,所以自己很想用用这个函数。
    但是自己不管怎么尝试都无法通过终端输入一个字符。

    http://www.openhw.org/walkie/blog/09-03/166335_463bd.html 


    网上也有无数的人在说无法使用scanf,或者无法完整的使用scanf函数。
    从edk的文档OS and Libraries Document Collection(oslib_rm.pdf)上说是支持的。而且确实可以在edk的安装目录下面的stdio.h文件中找到scanf函数的定义。
    \Xilinx\EDK\gnu\microblaze\nt\microblaze-xilinx-elf\include\stdio.h

     

    但是在自己的函数中还是无法使用

    int main (void) {
      int a;
      char str[80];
      xil_printf(”– Entering main() –\r\n”);
      while(1){
        print(”Enter a name:”);
        scanf(”%s”,str);
        print(”\r\n”);
        printf(”the name entered is: %s\r\n”,str);
      }
      return 0;
    }

    这里使用了最简单的模式,通过scanf输入一个数据,再通过printf函数打印到标准输出部件。

    经过一些天的调试,总算找到了问题的核心,原来是我的heap设置太小了。程序默认是0,而scanf需要的heap的大小要大于0x400才能正常的工作。最后使用的大小是0x800。才一切正常。

     

    scanf函数以及printf函数,使用这些标准的c函数, 对于最后整个程序的大小我也是有心理准备的,知道肯定会比较的大。但是最后出来的结果还是把我吓到了,本来8k(<1fff)可以放下的东西,现在大概 需要0x132b4(>100k)这么多,大了大概15倍左右,真是让人崩溃。而且这里我已经调小了heap以及stack的大小,heap设置为 ox800byte,stack设置为0×400byte。

     

    heap不能再小了,之前heap,edk默认为0byte,因为确实在程序中看上去没有malloc这样的函数来动态申请空间,但是自己忽略了scanf这个函数中可能会有buffer。

    这个地方也是让我调试了很久的一个地方。一开始整个程序下载下去根本无法使用,终端就一直 死在那里,或者就是在打印scanf得到的str时候出现乱码。后来想想想想不对啊,scanf肯定里面会有buffer,而且这些buffer肯定是动态分配的,才想起heap的问题。

    发现edk中默认heap是0k,修改为经常使用的ox400byte之后,每次在屏幕上只能输入一个字符,于是修改为 0×800之后一切正常。stack倒是只用了默认的0×400byte。在文章的最后有一小段程序来说明一个程序中哪些是放在heap中的,哪些是放在 stack中的。

     

    再来说一下scanf的大小,它>79k,毕竟这是一个标准的函数啊,要支持那么多东西。。不过对于嵌入式的很多系统,真的有必要需要那么标 准的函数吗?碰到任何情况都可以使用一个通用的函数来解决。其实很多时候对于普通计算机这是必要的,但是对于嵌入式系统,特别是那些对于memory要求 很高的系统,大可不必使用标准的scanf。就像printf一样,xil_printf只是把printf的浮点去除了,整个函数也小了很多。要是只是 打印一句话,一个字符串出来,完全可以只用print函数来实现,而不必使用printf这样的函数。

    那么问题又来了,是否有一个比较好的scanf的替代品呢?

     

    1)如果只需要得到一个字符,或者数字之类,可以只是如下方式:
    int main()
    {
      char s;
      while(1){
      s = XUartLite_RecvByte (XPAR_UARTLITE_0_BASEADDR);
      XUartLite_SendByte (XPAR_UARTLITE_0_BASEADDR, s);
    }
      return 0;
    }
    直接只用UART底层的驱动函数就可以了。自己调试过了,是完全可以使用的。终端输出的效果也很不错,大小也非常小,只有 c7a ,4k都不到。那么如果需要输入一个字符串,那么可以写一些附加代码来实现。比如使用一个char的数组,把输入的字符一个一个的放进这个数组中。

     

    2)下面这个帖子说他提供了一个reduce的scanf函数,但是我还不知道如何来使用。
    http://groups.google.com/group/comp.arch.fpga/browse_thread/thread/22660067a5ff5a6e/f7ff7eb383fe4528?hl=en#f7ff7eb383fe4528

     

     

    3)这个版本是1)中的一个update。从标准输入一个byte一个byte的输入,然后把输入的字符拼成 一个字符串或者数字输出。Thanks to Terry O'Neal and Ricky Su.

     

    以下是完成代码:

     

    #include “xparameters.h”
    #include “stdio.h”
    #include “xutil.h”

     

    char * mygets(char *string){
    char x=0;
    while(x!= ‘\r’) {
        x=inbyte();
       *string++ = x;
       xil_printf(”%c”,x);
    }
       *(–string) = ‘\0′;
    }

     

    int main(void){

       char * input_string;
       int sectornum;

       if ((input_string = (char*)malloc(10)) == NULL) {
       print(”Unable to allocate space”);
       return 0;
    }
    mygets(input_string);

     

    sectornum = strtoul(input_string,NULL,0);//string to number

    xil_printf(”__After strtoul____%s\r\n”,input_string);
    xil_printf(”__%d____”,sectornum);
    free(input_string);
    return 0;
    }

     

    4)这里提供一种3)的改进版本。不使用malloc以及free函数,因为它们的具体实现也比较的大。所以使用char[10],字符数组来实现。这种方法可以使得程序放入8k的bram中。

    #include “xparameters.h”
    #include “stdio.h”
    #include “xutil.h”

     

     

    void mygets(char *string){
    char x=0;
    while(x!= ‘\r’){
       x=inbyte();

       *string++ = x;
       xil_printf(”%c”,x);
    }
       *(–string) = ‘\0′;
    }

     

    int main(void){
       int sectornum;
       char input_string[10];

       mygets(input_string);
       xil_printf(”\r\nIt %s\r\n”,input_string);
       sectornum = strtoul(input_string,NULL,0);
       xil_printf(”Num is %d\r\n”,sectornum);

       return 0;
    }

     

     

     

     

     

    以下是关于Heap以及Stack的装载

    -------

    Heap & Stack

     

    int x;                 /* static storage */

    void main()
    {
    int y;              /* dynamic stack storage */
    char *str;          /* dynamic stack storage */
    str = malloc(100);  /* allocates 100 bytes of dynamic heap storage */
    y = foo(23);
    free(str);          /* deallocates 100 bytes of dynamic heap storage */
    }                      /* y and str deallocated as stack frame is popped */

    int foo(int z)      /* z is dynamic stack storage */
    {
    char ch[100];     /* ch is dynamic stack storage */
    if (z == 23) foo(7);
    return 3;           /* z and ch are deallocated as stack frame is popped,
    3 put on top of stack  */
    }

     

     
  • 相关阅读:
    【转】C#中的虚方法
    【转】ASP.NET 2.0中Page事件的执行顺序
    OWC ChartSpace控件的使用
    Ext对基本类型的扩展
    OWC PivotTable的使用方法
    .net中线程同步的典型场景和问题(1)
    python中使用汉字
    如何取消后台线程的执行
    yaffs2根文件系统的构建过程
    Fuck self.delegate = self
  • 原文地址:https://www.cnblogs.com/lzhitian/p/2766408.html
Copyright © 2011-2022 走看看