本文介绍使用Zynq平台上的ARM核使用SPI总线对LMK04828芯片进行配置。其基本步骤是首先建立一个Zynq工程,配置好SPI总线约束,然后利用LMK04828_Config_Cal程序计算寄存器值,最终利用SPI总线将寄存器值配置下载进LMK04828芯片。下面将使用IW-RFSOC-2T2R作为样例,演示配置过程。
新建一个Vivado工程,向"Block Design"中加入"Zynq UltraScale+ MPSoC"实例。先根据文档将DDR等配置好,如果你使用的是IW-RFSOC-2T2R板卡,则可以参考"快速开始"这篇教程进行基础配置。
配置好后,如下图所示,启用一个SPI接口。如果LMK04828直接连接在PS端的话,请做出相应配置。这里使用的板卡将SPI连接在PL端,因此我选择"EMIO"。
如图所示将"SPI_0"接口引出。
添加对应的约束,这里以IW-RFSOC-2T2R板卡作为例子。
set_property PACKAGE_PIN A10 [get_ports lmk_spi_ss_io]
set_property PACKAGE_PIN G11 [get_ports lmk_spi_sck_io]
set_property PACKAGE_PIN B11 [get_ports lmk_spi_io0_io]
set_property PACKAGE_PIN E12 [get_ports lmk_spi_io1_io]
set_property IOSTANDARD LVCMOS33 [get_ports lmk_spi_io0_io]
set_property IOSTANDARD LVCMOS33 [get_ports lmk_spi_io1_io]
set_property IOSTANDARD LVCMOS33 [get_ports lmk_spi_sck_io]
set_property IOSTANDARD LVCMOS33 [get_ports lmk_spi_ss_io]
set_property SLEW FAST [get_ports lmk_spi_io0_io]
set_property SLEW FAST [get_ports lmk_spi_io1_io]
set_property SLEW FAST [get_ports lmk_spi_sck_io]
set_property SLEW FAST [get_ports lmk_spi_ss_io]
利用上述生成的工程,并利用Vitis中的"Hello World"模板建立初始工程,并将LMK04828_Config_Cal中所有文件复制进"src"文件夹中。
在"main"函数前,添加头文件、函数和变量定义。
#include "xspips.h"
#include "LMK_ClockTree.h"
static XSpiPs SPI_inst;
#define SPI_DEVICE_ID XPAR_XSPIPS_0_DEVICE_ID
static int SpiPsInit(XSpiPs *SpiInstancePtr, u16 SpiDeviceId);
加入SPI接口初始化函数:
int SpiPsInit(XSpiPs *SpiInstancePtr, u16 SpiDeviceId)
{
int Status;
XSpiPs_Config *SpiConfig;
/*
* Initialize the SPI driver so that it's ready to use
*/
SpiConfig = XSpiPs_LookupConfig(SpiDeviceId);
if (NULL == SpiConfig) {
return XST_FAILURE;
}
Status = XSpiPs_CfgInitialize(SpiInstancePtr, SpiConfig,
SpiConfig->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform a self-test to check hardware build
*/
Status = XSpiPs_SelfTest(SpiInstancePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the Spi device as a master. External loopback is required.
*/
XSpiPs_SetOptions(SpiInstancePtr, XSPIPS_MASTER_OPTION |
XSPIPS_FORCE_SSELECT_OPTION);
XSpiPs_SetClkPrescaler(SpiInstancePtr, XSPIPS_CLK_PRESCALE_64);
return XST_SUCCESS;
}
在"main"函数中,添加初始化SPI接口代码如下:
int Status;
Status = SpiPsInit(&SPI_inst, SPI_DEVICE_ID);
if (Status != XST_SUCCESS)
{
return XST_FAILURE;
}
对于IW-RFSOC-2T2R板卡,可以首先修改"LMK_Preset.h"中的配置为下面所示,对应的固定配置已经预置。
//#define LMK_PRESET_NONE
#define LMK_PRESET_IW_RFSOC_2T2R_INTERNAL
//#define LMK_PRESET_IW_RFSOC_2T2R_EXTERNAL
在"main"函数中添加下面的内容,即可实现配置的计算和配置。
LMK_Config LMK_inst;
LMK_Simple LMK_simple;
// Set reference clock rate
LMK_simple.RefClockRate = 30720000;
// Set expected VCO clock rate
LMK_simple.VCOXClockRate = 122880000;
// Set SYSREF
LMK_simple.SYSREFRate = 7680000;
// DClockRate[n] for DCLKout(2n), the SDCLKout(2n+1) are all set to SYSREF
LMK_simple.DClockRate[0] = 491520000;
LMK_simple.DClockRate[1] = 491520000;
LMK_simple.DClockRate[2] = 491520000;
LMK_simple.DClockRate[3] = 0;
LMK_simple.DClockRate[4] = 0;
LMK_simple.DClockRate[5] = 0;
LMK_simple.DClockRate[6] = 0;
// Config the interface instance for LMK
LMK_simple.InterfaceInst = &SPI_inst;
// Generate config using LMK_simple
LMK_ConfigMake(&LMK_inst, &LMK_simple);
// Download to LMK
LMK_Init(&LMK_inst);