關注、星標嵌入式客棧,精彩及時送達
[導讀] 前面寫過篇介紹ZYNQ基本情況的文章,今天來肝一篇實戰文章介紹AXI quad SPI 使用方法,如果你正使用ZYNQ的這個IP,希望對你有所幫助。
初識AXI quad SPI

自《PG153 AXI Quad SPI v3.2》
支持:
Legacy Mode
standard mode: 准SPI通常就稱SPI,它是一種串行外設接口規范,有4根通信腳:SCK (時鍾), CS(片選), MOSI(主出從入), MISO(主入從出)。
Dual/Quad SPI Mode:
在標准模式下,支持高達32個從站,這是非常靈活的指標。本文對於手冊中的詳細技術細節不做過多闡述,有興趣的自行深入閱讀研究。
該SPI IP能干神馬呢?
完成如下這樣一個應用場景:
所需要實現的需求用例為:
本文實現用例描述
利用AXI quad SPI 實現SPI外設控制器
實現SPI外設控制器驅動
實現多SPI從設備掛載在SPI總線
實現用戶空間訪問多從SPI物理從設備
從軟件分層的視角來看,上述的需求需要實現下面的訪問層級:
為什么要研究這個呢?實際用ZYNQ芯片做產品時,很有可能外部有多個SPI從設備芯片需要利用Linux訪問,你或許會說ZYNQ的PS端不是自帶了兩個SPI控制器嗎?但有時候項目中這兩個SPI對應的引腳可能用做其他用途了,而一個復雜的項目中又不得不使用多個SPI從設備芯片時,本文所討論的話題就能很好的解決這樣的需求場景了。通過本文,你會發現,原來ZYNQ的SPI IP是如此靈活好用!
本文目的實戰描述,如何一步一步從PL端設計:
block design
約束
綜合
導出
乃至PS端:
SPI驅動配置
設備樹修改
系統編譯部署
設備驅動測試
按照這個流程,那么第一步需要設計PL端與PS端的配置,且看:
AXI Quad SPI 之配置
從IP catalog中按下圖從ip庫中添加如下IP:
ZYNQ7 processing System
AXI interconnect
AXI Quad SPI(可根據需要添加多個)
Processing System Reset(添加ZYNQ7 processing System 點自動連線會自動添加,當然也可以手動添加)
Concat
Block設計圖
使能ZYNQ7 processing System的時鍾PL Fabric clocks,用以驅動PL端的IP:
PL Fabric clocks設置
使能M AXI GP0接口如下:
雙擊AXI interconnect,設置2主1從:
雙擊axi_quad_spi_0設置如下,設置4個從設備(最多可支持32個從設備,PS端內置的SPI控制器1個最多支持3個從設備,從這一點可看出該IP的靈活性)
同樣將axi_quad_spi_1設置為2個從設備接口。
然后按照前面的連線圖,將各塊連接好,做過硬件的盆友會比較適應,這就像畫原理圖一樣,就將各IP建立了邏輯連接關系了。除此之外,對於一個ZYNQ的板子而言,你還需要做如下的PS端設置:
DDR RAM設置,根據自身的板子的內存芯片以及內存大小進行設置
Peripheral IO外設設置,比如SD卡,UART,QUAD SPI Flash,erthernet等
clock時鍾系統設置,根據板子的情況進行設置CPU、DDR時鍾頻率、IO時鍾等
......
至於這些怎么配置,比較常見這里就不贅述了。
對於AXI quad SPI外設還有一個很重要的配置,就是其地址范圍:
該地址最終將導出到設備樹描述文件,用於SPI控制器驅動訪問,從而讓SPI控制器驅動得以與該IP通過AXI總線進行通信。
導出硬件文件
點擊open elaborated design ,然后打開io ports進行管腳分配,這需要根據各自的硬件實際情況進行設置,比如我是這樣設置的:
電平標准
是否上拉
驅動能力
.....
然后點擊Run synthesis進行綜合,成功之后點擊生成bit stream。再點擊export hardware,得到.hdf文件,這個文件用於構建內核。
將得到的硬件描述hdf文件以及bitstream文件拷貝至內核編譯文件夾下:
配置編譯內核
運行命令讀取硬件描述文件:
petalinux-config --get-hw-description ../base.sdk
注:這里將hdf文件以及.bit文件放置在petalinux編譯路徑的上級目錄的base.sdk,根據習慣可自行設置,只有上述命令傳入的路徑正確即可。
等待一段時間后,可得到一個配置界面,用於配置內核源、u-boot源、Image 等配置。
petalinux-config
根據實際情況配置好后,退出配置並保存配置。使用過的會比較熟悉,這里不贅述了。
配置設備樹
編輯用戶設備樹文件,用戶設備樹文件在下面路徑中:
./project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi
配置設備樹如下:
/include/ "system-conf.dtsi"
/ {
};
&axi_quad_spi_0 {
status = "okay";
clock-names = "axi_clk", "axi4_clk", "spi_clk";
clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>;
spi0_dev_0@0 {
compatible = "spidev";
reg = <0>;
spi-max-frequency = <500000>;
#address-cells = <1>;
#size-cells = <1>;
};
spi0_dev_1@1 {
compatible = "spidev";
reg = <1>;
spi-max-frequency = <500000>;
#address-cells = <1>;
#size-cells = <1>;
};
spi0_dev_2@2 {
compatible = "spidev";
reg = <2>;
spi-max-frequency = <500000>;
#address-cells = <1>;
#size-cells = <1>;
};
spi0_dev_3@3 {
compatible = "spidev";
reg = <3>;
spi-max-frequency = <500000>;
#address-cells = <1>;
#size-cells = <1>;
};
};
&axi_quad_spi_1 {
status = "okay";
clock-names = "axi_clk", "axi4_clk", "spi_clk";
clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>;
spi1_dev_0@0 {
compatible = "spidev";
reg = <0>;
spi-max-frequency = <500000>;
#address-cells = <1>;
#size-cells = <1>;
};
spi1_dev_1@1 {
compatible = "spidev";
reg = <1>;
spi-max-frequency = <500000>;
#address-cells = <1>;
#size-cells = <1>;
};
};
這里直接使用內置spidev兼容從設備驅動,當然如果需要自己定義一個SPI設備驅動也是非常容易的,但是對於大部分普通的SPI從芯片而言直接使用spidev設備驅動即可,只需要在讀寫時按照芯片手冊協議進行訪問即可。
配置內核
運行下面命令進行內核配置:
petalinux-config -c kernel

內核配置
對於本應用而言,需要配置SPI驅動:
Device Drivers --->
+-SPI support--->
配置如下:
SPI控制器及設備驅動配置
這里調試中遇到一個奇怪的問題,CONFIG_SUSPEND需要禁止,否則控制器驅動加載不成功,目前還沒有深入研究為什么不成功,猜想可能是主控制器驅動關於SUSPEND功能還不支持或者有bug,如果有哪位大神知道怎么解決請求留言指點。
Power management options --->
Suspend to RAM and standby
功能管理配置
退出並保存配置,然后運行下面命令編譯系統:
petalinux-build
等待編譯成功后,運行下面命令將bitstream文件包進BOOT.bin中。
petalipackage --boot --fsbl ./images/linux/zynq_fsbl.elf --fpga ../base.sdk/design_1_wrapper.bit --u-boot --force
將得到下面的輸出信息,表示操作成功:
INFO: File in BOOT BIN: "/home/zynq/ALINX/spi_ip/ax_peta/images/linux/zynq_fsbl.elf"
INFO: File in BOOT BIN: "/home/zynq/ALINX/spi_ip/base.sdk/design_1_wrapper.bit"
INFO: File in BOOT BIN: "/home/zynq/ALINX/spi_ip/ax_peta/images/linux/u-boot.elf"
INFO: Generating zynq binary package BOOT.BIN...
INFO: Binary is ready.
WARNING: Unable to access the TFTPBOOT folder /tftpboot!!!
WARNING: Skip file copy to TFTPBOOT folder!!!
注:/home/zynq/ALINX/spi_ip/ax_peta 是本文工程的目錄
測試SPI從設備
編寫驅動測試程序,代碼如下:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char **argv)
{
int fd;
int len;
unsigned char buf[10];
unsigned char tmp;
/* 驗證輸入參數個數 */
if(3 != argc)
{
printf("none para\n");
return -1;
}
/* 打開輸入的設備文件, 獲取文件句柄 */
fd = open(argv[1], O_RDWR);
if(fd < 0)
{
/* 打開文件失敗 */
printf("Can't open file %s\r\n", argv[1]);
return -1;
}
int i = 0;
int j = 0;
len =strlen(argv[2]);
for(i=0;i<len;i++)
{
if(argv[2][i]>='0' && argv[2][i]<='9')
{
tmp = argv[2][i] - '0';
}
else if(argv[2][i]>='a' && argv[2][i]<='f')
{
tmp = argv[2][i] - 'a'+10;
}
else if(argv[2][i]>='A' && argv[2][i]<='F')
{
tmp = argv[2][i] - 'A'+10;
}
else
{
printf("Invalid input parameters \r\n");
return -1;
}
if(i%2==0)
buf[j] = tmp<<4;
else
{
buf[j] += tmp;
j++;
}
}
len = j;
printf("Test wr:");
for(i=0;i<len;i++)
printf(" %x",buf[i]);
write(fd, &buf[0], len);
printf("\n");
/* 操作結束后關閉文件 */
close(fd);
return 0;
}
編譯:
arm-linux-gnueabihf-gcc test.c -o test
將編譯所得的BOOT.BIN以及image.ub文件拷貝至制作好的SD的BOOT區,test文件拷貝至/home下。然后插上SD卡上電運行電路板:
登錄控制台后,運行ls /dev查看spidev設備是否加載成功:
spidev設備掛載情況
可見spedev1.0、spidev1.1以及spidev2.0--spidev2.3加載成功,與預期一樣。
然后運行測試程序:
root@ax_peta:/run/media/mmcblk0p2/home#./test /dev/spidev1.0 78aa
Test wr: 78 aa
用示波器或者邏輯分析儀觀察對應引腳,將出現正確的SPI通信波形。
總結一下
至此,就基本實現了從PS端Linux用戶空間訪問PL端的SPI從設備了。當然實際項目中還有很多細節需要進一步研究:
CPOL/CPHA 組合四種模式設置
SPI通信速率設置
從設備應用協議程序編寫
AXI Quad SPI FIFO特性的深入應用
AXI Quad SPI 其他模式及細節研究等
對於這些更細節的內容,相信在將基本框架搭建成功后,只要深入細致研究都不會有太大的難度。從本文可看出,ZYNQ之所以如此靈活好用,是其廠家或者第三方提供了大量成熟可供使用的IP以及配套的驅動程序。如有興趣嘗試用來開發項目,相信你會很快喜歡上這個體系的芯片,真的可以做到片上即可實現系統這一目標!
—END—
往期精彩推薦,點擊即可閱讀