原创 【博客大赛】【小梅哥FPGA】Cyclone V SoC 中为HPS添加SPI控制器并使用 ... ... ... ...

2018-5-9 22:37 7629 33 5 分类: FPGA/CPLD 文集: FPGA深入学习

    关于如何在Cyclone V SoC FPGA系统中为HPS添加一个SPI外设,这个实验我已经进行了有相当长的一段时间了,但直到今日方才有所突破,顺利的完成了SPI控制器的添加,驱动加载和基本测试。主要是因为自己对Linux方面知之甚少。

  这里先简要介绍自己的操作过程,然后说明自己遇到的问题,再记录自己解决问题的方法。

  在一个现成的Qsys系统中,例如友晶的DE1-SoC开发板的DE1_SOC_Linux_FB工程,打开Qsys,在Qsys系统中添加一个SPI外设,设定想要的SCLK时钟频率,例如这里设置为2M,实际上得到的应该是1.92M。将其salve端口连接到h2f_lw_axi_master上。导出相应的管脚,添加到Quartus的顶层文件中。


 

  这里需要将SPI的四个信号作为顶层管脚导出。实际使用时我并未分配实际的管脚,因为这仅仅算是我盲目探索过程,所以没有做完整的系统。但是测试时候是需要验证的,怎么办呢,这里我使用Signaltap直接抓取这几个引脚的信号,通过查看引脚的波形就能大致判断是否能正确的使用该SPI核了。例如我最终抓取到的测试波形如下图所示。当然了,这是后话,成功之后才能看到这个波形的,之前一直是不识别SPI设备,也就无法编程控制了。

  添加好SPI控制器之后需要全编译Quartus工程,并生成dts和dtb文件,dts文件是设备树,是用来供Linux读取硬件信息并对应加载设备驱动的,dtb文件是dts编译之后的二进制格式。这里我直接在SOCEDS command shell中将路径切换到工程目录下,输入make dts来生成dts文件,然后输入make dtb命令来生成dtb文件。

  生成dts的时候很顺利,没有遇到什么困难,但是在生成dtb的时候,遇到了如下报错:

  提示dts文件中有错误,pll_stream这个节点不存在。这个IP我知道,是生成一个时钟供FrameReader读取数据的,其并没有连接到HPS的总线上,也不需要受HPS控制,因此这个地方即使有错误也不会影响系统正常的运行。因此,参考提示信息说的方法,使用该-f参数来强制输出dtb文件。命令为:dtc -I dts -fo soc_system.dtb soc_system.dts。这样就能够正确的生成dtb文件了。

  生成dtb文件后,将其重命名为socfpga.dtb,并拷贝到开发板的启动SD卡中。

  然后将工程编译得到的sof文件转换得到rbf文件,命名为soc_system.rbf,也拷贝到开发板的启动SD卡中。这个rbf文件就是包含了有spi控制器的soc系统的FPGA部分的配置数据。该数据会在HPS启动的时候配置到FPGA中。

  以上只是完成了第一步,接下来,要想Linux系统能够自动的加载SPI驱动,需要配置Linux内核以使能该SPI控制器的驱动编译。

 

  使能之后,保存配置并编译得到内核镜像文件zImage文件。将zImage同样拷贝到开发板的启动SD卡中。

  这样,从理论上来说,为HPS添加SPI控制器和驱动支持的工作就算是完成了,接下来只需要将SD卡插入SOC开发板中,上电启动,芯片就会自动引导加载,并运行Linux操作系统,通过dtb读取到支持的SPI控制器,并识别到HPS总线上挂载的altera SPI控制器,为其注册驱动。然后当Linux系统启动完成后,就可以在/dev下看到spi设备了。

  但是实际上,当我按照这个流程操作之后,确实在系统启动的打印信息中看到了SPI控制器已经被识别,如下所示:

 

  但是在Linux的/dev路径下,却死活找不到SPI设备。网友帮忙分析说是设备确实已经识别了,但是可能dts中缺少一些描述信息,没能匹配上驱动信息,因此没有成功的加载驱动,创建设备。

  正当自己想破脑袋也不知道怎么办时,网友发过来一个连接,是一个博主的博客,为表尊重,这里附上其博文链接。https://blog.csdn.net/u013625961/article/details/56282731

  在这个博文里,有这样一段话:

以下为博客原文:

修改device tree的描述

spi_0: spi@0x100000100 {

    compatible = "altr,spi-16.1", "altr,spi-1.0";

    reg = <0x00000001 0x00000100 0x00000020>;

    interrupt-parent = <&hps_0_arm_gic_0>;

    interrupts = <0 43 4>;

    clocks = <&clk_0>;

    #address-cells = <1>;   /* embeddedsw.dts.params.#address-cells type NUMBER */

    #size-cells = <0>;  /* embeddedsw.dts.params.#size-cells type NUMBER */

    bus-num = <0>;  /* embeddedsw.dts.params.bus-num type NUMBER */

    num-chipselect = <1>;   /* embeddedsw.dts.params.num-chipselect type NUMBER */

    status = "okay";    /* embeddedsw.dts.params.status type STRING */

    spidev0: spidev@0 {

        compatible = "rohm,dh2228fv";   /* appended from boardinfo */

        reg = <0>;  /* appended from boardinfo */

        spi-max-frequency = <1000000>;  /* appended from boardinfo */

    }; //end spidev@0 (spidev1)

}; //end spi@0x100000100 (spi_0)

其中#address-cells = <1>;#size-cells = <0>; 两行必须用。

spi-max-frequency = <1000000>; 这个信息在设备注册时必须使用,否则会导致注册不成功。1000000 clock frequency要符合。

博客原文结束。

  意思是需要我们手动修改dts文件的内容,既然要手动修改,我就对自动生成的dts文件的内容和这个修改后的内容的差别产生了兴趣,于是打开自动生成的dts文件中的内容进行对比,对比如下所示:

 

  左侧的是博主的修改后的内容,而右侧的是SoC EDS软件自动生成的dts文件,可以看到,自动生成的内容里缺少了很多信息。

  既然这样,就先按照博主的说明,将这部分原本没有的内容手动添加进自动生成的dts文件的相应位置,然后使用该dts重新编译得到dtb文件,并替换掉SD卡中的dtb文件。然后重新启动开发板。

  只是在添加这部分内容的时候,同样也遇到了一点小插曲,我最开始是直接将这部分内容复制粘贴到我的dts文件中的。然后编译时会报如下错误:

 

ERROR (duplicate_label): Duplicate label 'spidev0' on /sopc@0/spi@0xfff00000/spidev@0 and /sopc@0/bridge@0xc0000000/spi@0x1000100e0/spidev@0

  意思是说有两个spidev@0设备,冲突了。好吧,那是哪里冲突了呢?在dts文件中尝试以spidev@0作为关键词搜索,发现文件中有两个地方涉及到了spidev@0,第一处是我刚刚添加的地方,第二处在HPS中,是HPS中的硬核SPI控制器。如下图所示:

 

  既然这样,那就自己手动将SPI_0下面的spidev0节点修改巍峨spidev1,保存后再次执行编译dtb操作,就能够成功的生成dtb文件了,将新的dtb文件拷贝到sd卡中替换之前的dtb文件。然后重启开发板,当系统启动之后,在/dev路径下就能看到一个名为spidev32766.0的设备了,编写一个简单的C语言测试程序,对该设备执行简单的读写测试,程序源码如下所示:


  然后拷贝到系统中执行,通过signaltap抓取SPI信号线上的波形,确实能够看到标准的SPI传输过程。

 

  至此,终于完成了SPI控制器的添加和使用,困扰我一个多月的问题总算是解决了。(PS:我这一个月可不是因为这个问题卡住了别的啥事都不干哈,只是因为遇到困难,每天事情又太多,就暂时搁置了。)


附:今天看到前两天写的一篇博文被网友评论了,对方应该是个专家,所以指出了我文章中存在的很多问题,说的很有道理,一瞬间感觉自己挺“白”的,挺打击积极性的,虽然话说的很难听,不过还是很感谢他,让我意识到了自己的很多不足,由于他提出的问题确实值得深思,所以我暂时将文章删除了,待日后好好学习论证之后,补充完善了再发吧。虽然写了两三年博客,遇到过各种评论,很多评论也挺打击积极性的,不过心态还是要好,坚持写作,不断的提升自己。


文章评论1条评论)

登录后参与讨论

用户3880491 2018-5-9 23:32

小梅哥666
相关推荐阅读
小梅哥 2019-09-04 22:10
小梅哥FPGA时序分析笔记(6.2)深入现象看本质——庖丁解牛之FPGA内数据传输模型
通过上一节,我们了解了FPGA内部数据的传输形式,接下来我们就可以根据上一节的内容来总结一下FPGA内部的数据传输模型了。 时钟和数据传输路径 通过上一节内容中,我绘制的那个FPGA内部数据在逻辑...
小梅哥 2019-09-01 21:28
小梅哥FPGA时序分析笔记(6.1)深入现象看本质——庖丁解牛之FPGA可编程原理
上一次发博客,已经是2个月前了,这中间两个月,干了件很有意义的事情,尤其是对于自己来说,感觉学到了非常多的知识和经验,每天都很忙,忙到没时间逛网站博客,终于忙完闲下来了,连载的事情可不能忘,终于可以书...
小梅哥 2019-07-02 08:57
小梅哥FPGA时序分析笔记(五)I/O约束显神威——深入龙潭
大家一定对我上一节的突然结尾表示一脸茫然:我是来学习时序约束的,然后你告诉我时序约束里面IO约束很重要,然我又跟着你的文章继续往下看,本以为你就要讲如何进行IO约束了,结果呢,你一个取反时钟就把我们打...
小梅哥 2019-06-30 11:07
小梅哥FPGA时序分析笔记(四)I/O时序定成败——化险为夷
小梅哥FPGA时序分析从遥望到领悟系列没有遇见过I/O时序问题,没有通过I/O约束方式实际解决过I/O时序问题,就很难明白I/O约束的重要性,也很难相信各种EDA软件真的有那么的傻白甜。 我遇到的最...
小梅哥 2019-06-22 10:32
小梅哥FPGA时序分析笔记(三)时钟约束真重要——事实说话
小梅哥FPGA时序分析从遥望到领悟系列以前,那是在以前,经常有网友(原谅我行文动不动就是网友说,网友问,毕竟我是卖开发板的,正面接触学FPGA的网友相对多一些,所以这些也都是事实存在的事情)问我:小梅...
小梅哥 2019-06-21 10:33
小梅哥FPGA时序分析笔记(二)时钟质量是生命——初遇时序
小梅哥FPGA时序分析从遥望到领悟系列第一次遇到时序问题并通过相应的手段解决问题,算是2年前做百兆以太网图像传输的时候了吧。当时遇到的问题为:同一个工程,每次编译结果的效果都不一样,有的时候编译了,下...
我要评论
1
33
关闭 站长推荐上一条 /2 下一条