Zynq-Linux移植学习笔记之64- 国产ZYNQ在linux下配置国产5396芯片

news2024/9/27 23:30:35

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的通信。配置时需注意以下几点:

1.经过测试,5396 spi的CPHA选择必须为2Egde(CPOL可以为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 delay=0;


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 ret=0;

	file = open("/dev/spidev2.0", O_RDWR);
	if (file<0) {
		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 = 2+regType/8;
	status = ioctl(file, SPI_IOC_MESSAGE(1), xfer);
	//printf("#5 status is %d\n",status);
	len=status;
	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,bp+2,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 (file<0) {
		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(i=0;i<regType/8;i++)
	{
		wr_buf[2+i] = 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 res=0;

	buf[0]=0x00;
	buf[1]=0x0f;
	buf[2]=0x00;


	temp=readBCM5396Reg(0x2,0x30,32);
	printf("page 0x2 offset 0x30 is 0x%x\n",temp);

	sleep(1);//连续读之间需要加时延
	temp=readBCM5396Reg(0x31,0x00,32);
	printf("before write page 0x31 offset 0x0 is 0x%x\n",temp);

	res=writeBCM5396Reg(0x31, 0x00, buf,32);//Port 0 - Slot 10
	if(res<0)
	{
		printf("write bcm5396 error\n");
	}

	temp=readBCM5396Reg(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_none

spidev_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选择必须为2Egde(CPOL可以为High或Low),才能保证与5396正常通信 ”描述一致。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1151271.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java 进阶篇】Java HTTP响应消息详解

在Web开发中&#xff0c;HTTP&#xff08;Hypertext Transfer Protocol&#xff09;是一种用于传输数据的协议&#xff0c;它用于浏览器和Web服务器之间的通信。当你在浏览器中访问一个网页时&#xff0c;浏览器向Web服务器发送HTTP请求&#xff0c;然后Web服务器返回HTTP响应。…

YOLOv8如何添加注意力模块?

分为两种&#xff1a;有参注意力和无参注意力。 eg: 有参&#xff1a; import torch from torch import nnclass EMA(nn.Module):def __init__(self, channels, factor8):super(EMA, self).__init__()self.groups factorassert channels // self.groups > 0self.softmax …

CondaError_ Downloaded bytes did not match Content-Length

问题 使用anaconda下载包文件时&#xff0c;出现了CondaError: Downloaded bytes did not match Content-Length的错误 CondaError: Downloaded bytes did not match Content-Lengthurl: https://conda.anaconda.org/pytorch/win-64/pytorch-2.1.0-py3.11_cuda11.8_cudnn8_0.…

二维码智慧门牌管理系统升级,打造高效事件处理流程

文章目录 前言一、二维码智慧门牌管理系统的升级目标二、事件处理流程优化三、升级带来的好处 前言 随着城市化的不断推进&#xff0c;城市管理面临越来越多的挑战。为了更好地解决这些问题&#xff0c;许多城市已经开始采用二维码智慧门牌管理系统。这个系统不仅可以提高城市…

操作系统第一章-第三章大题_期末考试_详细易考

1.ABC三道作业如下表所示: 作业输入CPU输出A1505050B10060100C806050 (1) 计算在单道环境下运行时CPU的利用率;(2分) (2) 假设计算机系统中具有一个CPU、三个通道,画出ABC三道作业并发执行的情况图&#xff0c;并计算CPU利用率。(12分) 问题分析: c p u 利用率 c p u 有效…

Python对象(Object)与类型(Type)的关系

Object与Type 1、Object与Type概述2、Object与Type的关系 1、Object与Type概述 对象&#xff08;Object&#xff09;和类型&#xff08;Type&#xff09;是Python中两个最最基本的概念&#xff0c;它们是构筑Python语言大厦的基石 所有的数据类型&#xff0c;值&#xff0c;变…

[BUUCTF NewStarCTF 2023 公开赛道] week4 crypto/pwn

再补完这个就基本上完了. crypto RSA Variation II Schmidt-Samoa密码系统看上去很像RSA,其中Npqq, 给的eN给了d from secret import flag from Crypto.Util.number import *p getPrime(1024) q getPrime(1024)N p*p*qd inverse(N, (p-1)*(q-1)//GCD(p-1, q-1))m bytes…

cause: java.lang.numberformatexception: for input string

一个十分粗心的错误 我本来想要写的是name不为空&#xff0c;并且不为空字符串&#xff0c;结果不小心写成了空格&#xff01; 解决方案&#xff1a;将空格改为空字符串即可

JMeter的使用——傻瓜式学习【中】

目录 前言 1、JMeter参数化 1.1、什么是参数化 1.2、用户定义的变量 1.2.1、什么时候使用用户定义的变量 1.2.2、使用“用户定义的变量”进行参数化的步骤&#xff1a; 1.2.3、案例 1.3、用户参数 1.3.1、什么时候使用用户参数&#xff1f; 1.3.2、使用“用户参数”进…

交叉编译工具链(以STM32MP1为例)

1.什么是交叉编译工具链&#xff1f; 在一个系统上进行编译&#xff0c;在另一个系统上进行执行 2.STM32MP1交叉编译工具链 3.交叉编译器内容 4.两种工具链模式 5.两种链接模式 6.工具使用 注意&#xff1a;OpenSTLinux已经提供了编译框架&#xff0c;不需要命令行手工编译 …

Spring Cloud 实战 | 解密Feign底层原理,包含实战源码

专栏集锦&#xff0c;大佬们可以收藏以备不时之需 Spring Cloud实战专栏&#xff1a;https://blog.csdn.net/superdangbo/category_9270827.html Python 实战专栏&#xff1a;https://blog.csdn.net/superdangbo/category_9271194.html Logback 详解专栏&#xff1a;https:/…

在VM虚拟机上安装centos并了解Linux常用命令

一. centos安装 新建一个虚拟机&#xff0c;使用ISO映像文件&#xff08;在浏览器上直接搜索阿里云镜像站&#xff0c;下载合适的镜像文件&#xff09; 安装后设置密码然后重启 重启后输入账号和密码 查看IP 输入命令&#xff1a; vi ifcfg-ens33&#xff0c;进入编辑界面&a…

物联网AI MicroPython传感器学习 之 PAJ7620手势识别传感器

学物联网&#xff0c;来万物简单IoT物联网&#xff01;&#xff01; 一、产品简介 手势识别传感器PAJ7620u2是一款集成3D手势识别和运动跟踪为一体的交互式传感器&#xff0c;传感器可以在有效范围内识别手指的顺时针/逆时针转动方向和手指的运动方向等。它可以识别13种手势&a…

STM32的RTC模块的难点推导

在 S T M 32 STM32 STM32的 R e a l t i m e c l o c k , R T C Real\quad time\quad clock,RTC Realtimeclock,RTC模块中有一些功能点不太好理解&#xff0c;下面我根据我自己对这些功能难点的理解来做一些推导并记录如下。 首先来看一下平滑数字校准。假设我们目前的 R …

万字解析设计模式之原型模式与建造者模式

一、原型模式 1.1概述 原型模式是一种创建型设计模式&#xff0c;其目的是使用已有对象作为原型来创建新的对象。原型模式的核心是克隆&#xff0c;即通过复制已有对象来创建新对象&#xff0c;而不是通过创建新对象的过程中独立地分配和初始化所有需要的资源。这种方式可以节…

CMT2310A一款低功耗高性能Sub-1GHz射频收发器芯片

CMT2310A是一款超低功耗,高性能&#xff0c;适用于各种113至960 MHz无线应用的00K&#xff0c;(G)FSK 和4(G)FSK 射频收发器。它是CMOSTEK NextGenRFTM 射频产品线的一部分&#xff0c;这条产品线包含完整的发射器&#xff0c;接收器和收发器。CMT2310A的高集成度&#xff0c;简…

npm package.json属性详解

npm package.json属性详解 概述 package.json必须是一个严格的json文件&#xff0c;而不仅仅是js里边的一个对象。其中很多属性可以通过npm-config来生成 name package.json中最重要的属性是name和version两个属性&#xff0c;这两个属性是必须要有的&#xff0c;否则模块就…

【机器学习(二) 线性代数基础I(Linear Algebra Foundations)】

机器学习&#xff08;二&#xff09; 线性代数基础I&#xff08;Linear Algebra Foundations) 这一节主要介绍一些线性代数的基础。 目录 机器学习&#xff08;二&#xff09; 线性代数基础I&#xff08;Linear Algebra Foundations)1. 向量 Vectors2. 复杂度 Complexity3.线…

基于3D点云的语义分割模型调研(最新更新2023.10.30)

文章目录 3D点云分割数据集点云模型的评价指标3D点云语义分割方法发展PointSIFT模型的效果 https://blog.csdn.net/toCVer/article/details/126265782 基于深度学习的三维点云分割综述 3D点云分割数据集 传统的点云分割方法包括基于边缘检测的方法、基于区域增长的算法、基于特…

【Linux】:Linux开发工具之Linux编辑器vim的使用

&#x1f52b;1.Linux编辑器-vim使用 &#x1f4e4; vi/vim的区别简单点来说&#xff0c;它们都是多模式编辑器&#xff0c;不同的是vim是vi的升级版本&#xff0c;它不仅兼容vi的所有指令&#xff0c;而且还有一些新的特性在里面。例如语法加亮&#xff0c;可视化操作不仅可以…