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

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.mfbz.cn/a/111558.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

驾驶技巧_新手

人人都是老司机 1> 快速起步(手动挡)2> 窄路会车3> 转弯4> 变道 1> 快速起步(手动挡) 【B站】视频讲解 Step 1> 【快 停 慢放】左脚离合&#xff0c;快速抬到半联动点&#xff1b; Step 2> 离合器慢放同时加油&#xff01; 2> 窄路会车 3> 转弯 4&…

C++学习初探---‘C++面向对象‘-继承函数重载与运算符重载

文章目录 前言继承继承是什么&#xff1f;三种访问权限的继承&#xff1a; 函数重载与运算符重载函数重载运算符重载可重载运算符&不可重载运算符 前言 第三次学习记录&#xff0c;依旧是C面向对象的内容。 继承 继承是什么&#xff1f; C中的继承是一种面向对象编程&am…

Kubuntu安装教程

目录 1.介绍 2.安装 3.配置 更新软件 中文输入法 美化 1.介绍 Kubuntu&#xff0c;是众多Ubuntu分支的一种&#xff0c;它采用KDE Plasma桌面为其默认桌面环境。它和Ubuntu采用同样的底层系统和软件库。基本上&#xff0c;Kubuntu和Ubuntu没有太大的差异&#xff0c;只是…

Spring Boot 3系列之一(初始化项目)

近期&#xff0c;JDK 21正式发布&#xff0c;而Spring Boot 3也推出已有一段时间。作为这两大技术领域的新一代标杆&#xff0c;它们带来了许多令人振奋的新功能和改进。尽管已有不少博客和文章对此进行了介绍&#xff0c;但对于我们这些身处一线的开发人员来说&#xff0c;有些…

【Truffle】二、自定义合约测试

一、准备测试 上期我们自己安装部署了truffle&#xff0c;并且体验了测试用例的整个测试流程&#xff0c;实际开发中&#xff0c;我们可以对自己的合约进行测试。 我们首先先明白自定义合约测试需要几个文件 合约文件&#xff1a;既然要测试合约&#xff0c;肯定要有合约的源码…

[EFI]asus strix b760-i 13900F电脑 Hackintosh 黑苹果efi引导文件

硬件型号驱动情况主板 asus strix b760-i 处理器 I9 13900F 已驱动内存crucial ddr5-5200 64gb(32gb*2)(overclock 5600)已驱动硬盘 WD black sn850 500g*2 已驱动显卡rx570已驱动声卡Realtek ALCS1220A已驱动网卡Intel I225-V 2.5 Gigabit Ethernet已驱动无线网卡蓝牙Fevi T91…

通过内网穿透快速搭建公网可访问的Spring Boot接口调试环境

文章目录 前言1. 本地环境搭建1.1 环境参数1.2 搭建springboot服务项目 2. 内网穿透2.1 安装配置cpolar内网穿透2.1.1 windows系统2.1.2 linux系统 2.2 创建隧道映射本地端口2.3 测试公网地址 3. 固定公网地址3.1 保留一个二级子域名3.2 配置二级子域名3.2 测试使用固定公网地址…

Spring Cloud Alibaba 之 Sentinel

系列文章目录 第一章 Java线程池技术应用 第二章 CountDownLatch和Semaphone的应用 第三章 Spring Cloud 简介 第四章 Spring Cloud Netflix 之 Eureka 第五章 Spring Cloud Netflix 之 Ribbon 第六章 Spring Cloud 之 OpenFeign 第七章 Spring Cloud 之 GateWay 第八章 Sprin…

C++学习笔记之四(标准库、标准模板库、vector类)

C 1、C标准库2、C标准模板库2.1、vector2.1.1、vector与array2.1.2、vector与函数对象2.1.3、vector与迭代器2.1.4、vector与算法 1、C标准库 C C C标准库指的是标准程序库( S t a n d a r d Standard Standard L i b a r a y Libaray Libaray)&#xff0c;它定义了十个大类…

x3daudio1 7.dll丢失怎么修复?多种x3daudio1 7.dll修复方法对比

x3daudio1_7.dll是Windows操作系统中的一个动态链接库文件&#xff0c;它主要负责处理音频相关的功能。当这个文件缺失或损坏时&#xff0c;可能会导致一些音频播放问题&#xff0c;如无声、杂音等。那么&#xff0c;x3daudio1_7.dll缺失的原因是什么呢&#xff1f;又该如何修复…

Unity 粒子特效-第五集-烟雾缭绕合并特效

一、特效预览 二、制作原理 1.素材介绍 我们之前几章做了有光球&#xff0c;星星&#xff0c;烟雾 我们把他们结合起来&#xff0c;做一些调整 2.合并方法 我们还是建一个粒子游戏物体 我们把所有的效果取消 再重置一下transform 现在这个物体就是一个可以控制粒子特效的空…

钢琴培训答题服务预约小程序的效果怎样

很多家长都会从小培养孩子的兴趣&#xff0c;钢琴便是其中热度较高的一种&#xff0c;而各城市也不乏线下教育培训机构&#xff0c;除了青少年也有成年人参加培训&#xff0c;市场教育高需求下&#xff0c;需要商家不断拓展客户和转化。 那么通过【雨科】平台制作钢琴培训服务…

【LeetCode力扣】42. 接雨水

目录 1、题目介绍 2、解题思路 2.1、暴力破解法 2.2、双指针法 1、题目介绍 原题链接&#xff1a; 42. 接雨水 - 力扣&#xff08;LeetCode&#xff09; 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1]输出&#xff1a;6解释&#xff1a;上面是由…

七、W5100S/W5500+RP2040树莓派Pico<UDP 组播>

文章目录 1. 前言2. 相关简介2.1 简述2.2 优点2.3 应用 3. WIZnet以太网芯片4. UDP 组播回环测试4.1 程序流程图4.2 测试准备4.3 连接方式4.4 相关代码4.5 测试现象 5. 注意事项6. 相关链接 1. 前言 UDP组播是一种基于UDP协议的通信方式&#xff0c;它允许一台计算机通过发送单…

HEC-RAS 1D/2D水动力与水环境模拟技术

水动力与水环境模型的数值模拟是实现水资源规划、环境影响分析、防洪规划以及未来气候变化下预测和分析的主要手段。然而&#xff0c;一方面水动力和水环境模型的使用非常复杂&#xff0c;理论繁复&#xff1b;另一方面&#xff0c;免费的水动力和水环境软件往往缺少重要功能&a…

rcore 笔记 第一个裸机程序

文章目录 环境应用程序与基本执行环境应用程序执行环境与基本操作平台执行应用程序应用程序执行环境目标平台与目标三元组 移除标准库依赖移除 println! 宏提供 panic_handler 功能应对致命错误移除 main 函数 编译运行内核指令程序内存布局与编译流程 内核第一条指令编写内核第…

计算机毕业设计选题推荐-短文写作竞赛微信小程序/安卓APP-项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

操作系统的内存管理之虚拟空间

操作系统的内存管理&#xff0c;主要分为三个方面。 第一&#xff0c;物理内存的管理&#xff0c;相当于会议室管理员管理会议室。 第二&#xff0c;虚拟地址的管理&#xff0c;也即在项目组的视角&#xff0c;会议室的虚拟地址应该如何组织。 第三&#xff0c;虚拟地址和物…

瑞萨e2studio(28)----SPI 驱动WS2812灯珠

瑞萨e2studio.28--SPI 驱动WS2812灯珠 概述视频教学样品申请芯片级联方法数据传输时序新建工程软件准备保存工程路径芯片配置开始SPI配置SPI属性配置时钟配置SPI配置CPHA配置代码hal_entry.cws2812.cws2812.h 概述 本文介绍了如何使用瑞萨RA微控制器&#xff0c;结合E2STUDIO…

【深度学习实验】网络优化与正则化(二):基于自适应学习率的优化算法详解:Adagrad、Adadelta、RMSprop

文章目录 一、实验介绍二、实验环境1. 配置虚拟环境2. 库版本介绍 三、实验内容0. 导入必要的库1. 随机梯度下降SGD算法a. PyTorch中的SGD优化器b. 使用SGD优化器的前馈神经网络 2.随机梯度下降的改进方法a. 学习率调整b. 梯度估计修正 3. 梯度估计修正&#xff1a;动量法Momen…
最新文章