贵港网站建设代理,成都专业网站建设套餐,游戏ui设计网站,wordpress多网店主题1、背景介绍
复旦微ZYNQ通过SPI配置国产JEM5396#xff0c;框图如下#xff1a; 现在需要在linux下的应用程序内配置JEM5396的寄存器。其中FMQL和进口的XILINX ZYNQ类似#xff0c;JEM5396和进口的BCM5396兼容。因此可以参考进口ZYNQ在linux下配置BCM5396过程。Zynq-Linux移…1、背景介绍
复旦微ZYNQ通过SPI配置国产JEM5396框图如下 现在需要在linux下的应用程序内配置JEM5396的寄存器。其中FMQL和进口的XILINX ZYNQ类似JEM5396和进口的BCM5396兼容。因此可以参考进口ZYNQ在linux下配置BCM5396过程。Zynq-Linux移植学习笔记之41-linux下通过SPI访问broadcom 5396交换芯片_bcm5396-CSDN博客 2、内核配置
内核中将spidev.c编到内核内同时在spidev.c中添加jem5396设备 3、设备树配置
设备树中在spi节点下添加jem5396设备 4、应用修改
由于复旦微FMQL中采用的SPI控制器不是SPI-CADENCE IP所以不需要和进口ZYNQ那样改驱动。但是需要在应用APP中修改。参考JEM5396提供的差异说明 我司配套SPI驱动使用ARM STM32F107VC型芯片内建的SPI IP实现SPI Master与5396 SPI Slave的通信。配置时需注意以下几点 经过测试5396 spi的CPHA选择必须为2EgdeCPOL可以为High或Low才能保证与5396正常通信。 2. 由于内部设计原因导致spi接口的cs控制与sck时钟信号两者可能出现信号对齐或大体重合继而导致采样数据不准。因此在时序上需要 cs触发后的第一个时钟沿向后延几个相位。如红框图位置 应用代码如下
#include stdio.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include unistd.h
#include sys/ioctl.h
#include linux/types.h
#include linux/spi/spidev.h
#include stdint.h
#include stdio.h
#include string.h
#include errno.h#define NREAD (0x60)
#define NWRITE (0x61)#define SIO (0xF0)
#define STS (0xFE)
#define SPG (0xFF)#define SPIF (0x80)
#define RACK (0x20)
#define RXRDY (0x02)
#define TXRDY (0x01)uint8_t mode SPI_CPHA|SPI_CPOL;
uint8_t bits 8;
uint32_t speed 2000000;
uint16_t delay0;unsigned int readBCM5396Reg(unsigned char page,unsigned char offset,unsigned char regType)
{unsigned char wr_buf[32],rd_buf[32],*bp;int len, status;struct spi_ioc_transfer xfer[2];int file;unsigned int result;int ret0;file open(/dev/spidev2.0, O_RDWR);if (file0) {printf(open 5396 error\n);return 1;}if (ioctl(file, SPI_IOC_WR_MODE, mode) 0){printf(SPI_IOC_WR_MODE failed\n);}if (ioctl(file, SPI_IOC_RD_MODE, mode) 0){printf(SPI_IOC_RD_MODE failed\n);}memset(wr_buf, 0, sizeof(wr_buf));memset(rd_buf, 0, sizeof(rd_buf));memset(xfer,0,sizeof(xfer));wr_buf[0] NREAD;wr_buf[1] STS;xfer[0].tx_buf (unsigned long) wr_buf;xfer[0].rx_buf (unsigned long) rd_buf;xfer[0].len 3;status ioctl(file, SPI_IOC_MESSAGE(1), xfer);printf(#1 status is %d\n,status);usleep(10000);printf(#1 NREAD response(%d): , status);for (bp rd_buf; len; len--)printf(%02x , *bp);printf(\n);wr_buf[0] NWRITE;wr_buf[1] SPG;wr_buf[2] page;xfer[0].tx_buf (unsigned long) wr_buf;xfer[0].rx_buf (unsigned long) rd_buf;xfer[0].len 3;status ioctl(file, SPI_IOC_MESSAGE(1), xfer);//printf(#2 status is %d\n,status);//usleep(10000);printf(#2 NWRITE response(%d): , status);for (bp rd_buf; len; len--)printf(%02x , *bp);printf(\n);wr_buf[0] NREAD;wr_buf[1] offset;xfer[0].tx_buf (unsigned long) wr_buf;xfer[0].rx_buf (unsigned long) rd_buf;xfer[0].len 3;status ioctl(file, SPI_IOC_MESSAGE(1), xfer);//printf(#3 status is %d\n,status);//usleep(10000);printf(#3 NREAD response(%d): , status);for (bp rd_buf; len; len--)printf(%02x , *bp);printf(\n);wr_buf[0] NREAD;wr_buf[1] STS;xfer[0].tx_buf (unsigned long) wr_buf;xfer[0].rx_buf (unsigned long) rd_buf;xfer[0].len 3;status ioctl(file, SPI_IOC_MESSAGE(1), xfer);//printf(#4 status is %d\n,status);//usleep(10000);printf(#4 NREAD response(%d): , status);for (bp rd_buf; len; len--)printf(%02x , *bp);printf(\n);wr_buf[0] NREAD;wr_buf[1] SIO;xfer[0].tx_buf (unsigned long) wr_buf;xfer[0].rx_buf (unsigned long) rd_buf;xfer[0].len 2regType/8;status ioctl(file, SPI_IOC_MESSAGE(1), xfer);//printf(#5 status is %d\n,status);lenstatus;if (status 0) {perror(SPI_IOC_MESSAGE);return -1;}printf(#5 NREAD response(%d): , status);for (bp rd_buf; len; len--)printf(%02x , *bp);printf(\n);bp rd_buf;memcpy(result,bp2,regType/8);printf(read result is 0x%x\n,result);close(file);return result;
}unsigned int writeBCM5396Reg(unsigned char page,unsigned char offset,unsigned char *pBuffer,unsigned char regType)
{unsigned char wr_buf[32],rd_buf[32],*bp;int len, status;struct spi_ioc_transfer xfer[2];int file,i;unsigned int result;file open(/dev/spidev2.0, O_RDWR);if (file0) {printf(open 5396 error\n);return 1;}if (ioctl(file, SPI_IOC_WR_MODE, mode) 0){printf(SPI_IOC_WR_MODE failed\n);}if (ioctl(file, SPI_IOC_RD_MODE, mode) 0){printf(SPI_IOC_RD_MODE failed\n);}memset(wr_buf, 0, sizeof(wr_buf));memset(rd_buf, 0, sizeof(rd_buf));memset(xfer,0,sizeof(xfer));wr_buf[0] NREAD;wr_buf[1] STS;xfer[0].tx_buf (unsigned long) wr_buf;xfer[0].rx_buf (unsigned long) rd_buf;xfer[0].len 3;status ioctl(file, SPI_IOC_MESSAGE(1), xfer);wr_buf[0] NWRITE;wr_buf[1] SPG;wr_buf[2] page;xfer[0].tx_buf (unsigned long) wr_buf;xfer[0].rx_buf (unsigned long) rd_buf;xfer[0].len 3;status ioctl(file, SPI_IOC_MESSAGE(1), xfer);wr_buf[0] NWRITE;wr_buf[1] offset;for(i0;iregType/8;i){wr_buf[2i] pBuffer[i];}xfer[0].tx_buf (unsigned long) wr_buf;xfer[0].rx_buf (unsigned long) rd_buf;xfer[0].len 2(regType/8);status ioctl(file, SPI_IOC_MESSAGE(1), xfer);close(file);return status;
}int main()
{unsigned int temp;unsigned char buf[10];int res0;buf[0]0x00;buf[1]0x0f;buf[2]0x00;tempreadBCM5396Reg(0x2,0x30,32);printf(page 0x2 offset 0x30 is 0x%x\n,temp);sleep(1);//连续读之间需要加时延tempreadBCM5396Reg(0x31,0x00,32);printf(before write page 0x31 offset 0x0 is 0x%x\n,temp);reswriteBCM5396Reg(0x31, 0x00, buf,32);//Port 0 - Slot 10if(res0){printf(write bcm5396 error\n);}tempreadBCM5396Reg(0x31,0x00,32);printf(after write page 0x31 offset 0x0 is 0x%x\n,temp);return 0;
}5、测试验证
系统启动后执行应用可以看到能够正常读写 注意国产JEM5396在连续读写寄存器时存在问题连续两次读之间需要加1s延迟。具体看应用示例。 另外调试时发现有个小工具很好用spidev_test这样就不需要自己写代码直接模拟SPI读写时序
spidev_test -D /dev/spidev2.0 -s 2000000 -H -O -p \x60\xFE\x00 -v #NREAD,STS,rd_sts_spif(0x00)spidev_test -D /dev/spidev2.0 -s 2000000 -H -O -p \x61\xFF\x02 -v #NWRITE,SPG,page(0x02)spidev_test -D /dev/spidev2.0 -s 2000000 -H -O -p \x60\x30\x00 -v #NREAD,reg(0x30),rd_nonespidev_test -D /dev/spidev2.0 -s 2000000 -H -O -p \x60\xFE\x00 -v #NREAD,STS,rd_sts_rack(0xA0)spidev_test -D /dev/spidev2.0 -s 2000000 -H -O -p \x60\xF0\x00 -v #NREAD,SIO,rd_5396_id(0x60) 上图为读出JEM5396的ID操作
Spidev_test具体用法如下 当然使用这个工具的前提是有个正确的时序然后通过spidev_test去实现这个时序比如spidev_test中设置-H配置CPHA和-O配置CPOL这个与芯片说明中的“经过测试5396 spi的CPHA选择必须为2EgdeCPOL可以为High或Low才能保证与5396正常通信 ”描述一致。