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

Zynq-Linux移植学习笔记之64- 国产ZYNQ在linux下配置国产5396芯片
1、背景介绍 复旦微ZYNQ通过SPI配置国产JEM5396,框图如下: 现在需要在linux下的应用程序内配置JEM5396的寄存器。其中FMQL和进口的XILINX ZYNQ类似,JEM5396和进口的BCM5396兼容。因此可以参考进口ZYNQ在linux下配置BCM5396过程。Zynq-Linux移…...
系统架构设计师-第19章-大数据架构设计理论与实践-软考学习笔记
传统数据处理系统存在的问题 传统数据处理系统存在以下问题: 1. 数据孤岛问题:不同部门或系统之间的数据隔离,数据无法共享和整合。 2. 数据不一致性问题:由于数据维护分散,同一数据在不同系统或部门中可能存在不同…...

论坛搭建.
目录 一.配置软件仓库 二.安装http php miriadb 三.配置数据库 四.源码拖拽并解压 五.防火墙通过 六.浏览器安装测试 七.界面参数设置 一.配置软件仓库 1.进入仓库目录 cd /etc/yum.repos.d 2.创建仓库文件 vim local.repo 3.在 local.repo中写入:(粘贴的时候注意位…...
三种前端埋点方式
什么是埋点 埋点是数据采集领域(尤其是用户行为数据采集领域)的术语,指的是针对特定用户行为或事件进行捕获、处理和发送的相关技术及其实施过程。比如用户某个icon点击次数、观看某个视频的时长等等。 我们可以知道埋点实际上是对特定事件或…...

html获取网络数据,列表展示 第二种
html获取网络数据,列表展示 第二种 js遍历json数组中的json对象 image.png || - 判断数据是否为空,为空就显示 - <!DOCTYPE html> <html><head><meta charset"utf-8"><title>网页列表</title><script …...

【Python 算法】信号处理通过陷波滤波器准确去除工频干扰
对于一个信号来说通常汇入工频噪声往往是因为交流电产生的电泳,影响了我们信号采集导致信号上存在工频干扰。 那么matlab去除工频干扰可以通过陷波滤波器实现。 通常使用scipy.signal实现信号的处理。 Scipy的信号处理模块(scipy.signal)来创…...

Redis(08)| 线程模型
一、redis 的线程模型 redis 内部使用文件事件处理器 file event handler,它是单线程的,所以redis才叫做单线程模型。它采用IO多路复用机制同时监听多个 socket,将产生事件的 socket 压入内存队列中,事件分派器根据 socket 上的事…...
Java14-16新特性
目录 一、Java14新特性 1、instanceof模式匹配 2、友好的空指针(NullPointerException)提示 3、record类型 二、Java15新特性 1、Sealed Classes 2、CharSequence新增方法 3、TreeMap新增方法 4、文本块 5、无需配置环境变量 三、Java16新特性 1、包装类构造方法的…...

中兴再推爆款,双2.5G网口的巡天AX3000Pro+仅需299元
10月30日消息,中兴新款路由器中兴巡天AX3000Pro将于10月31日20:00正式开售,当前可在天猫、京东及红魔商城进行预约,首发价格299元。 据了解,中兴巡天AX3000Pro是中兴智慧家庭推出的巡天系列新品,也是当前市场上唯一一款300元价位内配备双2.5G网口的路由器。 中兴巡天AX3000Pro…...
【系统架构】架构风格专题
目录 1、定义 2、通用架构风格分类 3、架构风格比较 4、示例:管道-过滤 VS 数据仓库)比较因素分析 1、定义 架构风格:描述某一特定应用领域中系统组织方式的惯用模式,反映了领域中众多系统所共有的结构和语义特性,…...

【Qt】盒子布局、网格布局、表单布局和堆栈布局
盒子布局 QBoxLayout可以在水平方向或垂直方向上排列控件,分别派生了QHBoxLayout、QVBoxLayout子类。 QHBoxLayout:水平布局,在水平方向上排列控件,即:左右排列。QVBoxLayout:垂直布局,在垂直…...
GO语言,半自动打怪
仅供学习参考,切勿用于商业用途 package mainimport ("fmt""github.com/go-vgo/robotgo""math/rand""time" )const (taskNum 7 )type Task struct {Name stringSleepTime1 intSleepTime2 intFunc func() }fu…...

【Java 进阶篇】Java登录案例详解
登录是Web应用程序中常见的功能,它允许用户提供凭证(通常是用户名和密码)以验证其身份。本文将详细介绍如何使用Java创建一个简单的登录功能,并解释登录的工作原理。我们将覆盖以下内容: 登录的基本概念创建一个简单的…...

Vue 菜单导航栏,轮播图
导航菜单栏结构和样式代码实现 一级导航栏 views/HomeView.vue <template><div><Shortcut></Shortcut><Header></Header><div class"inner"><Navigation></Navigation></div><div>我是主页&l…...

讲述为什么要学习Adobe XD以及 Adobe XD下载安装
首先 我们要了解 Adobe XD 是个什么东西 XD是Adobe公司专门开发出来面向交互、界面设计的矢量绘图工具。 然后是 他可以做什么? 最基本的 可以做UI界面设置 所有 手机 平板 电脑等设备的UI界面 我们都可以通过XD完成 还有就是原型设置 我们可以做各种界面图 还有…...
Netty复习:(1)Http server: hello world
一、加依赖 <dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.72.Final</version></dependency>二、创建自定义的handler package cn.edu.tju.handler;import io.netty.buffer.ByteB…...
【Python 千题 —— 基础篇】加法计算
题目描述 题目描述 编写一个程序,接受用户输入的两个数字,然后计算这两个数字的和,并输出结果。 输入描述 输入两个数字,用回车隔开两个数字。 输出描述 程序将计算这两个数字的和,并输出结果。 示例 示例 ① …...

基于纵横交叉算法的无人机航迹规划-附代码
基于纵横交叉算法的无人机航迹规划 文章目录 基于纵横交叉算法的无人机航迹规划1.纵横交叉搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要:本文主要介绍利用纵横交叉算法来优化无人机航迹规划。 …...
D-Bus:数据类型
D-Bus中描述接口的属性和方法,有其自己定义的一套签名描述方式: 数据类型描述符号对应C++数据类型avector/array数组, ai表示的是vector<int32_t>bboolddouble双精度浮点数iint32_t,32位有符号整数nint16_t,16位有符号整数oobject_path对象路径quint16_t,16位无符号…...

BI零售数据分析,告别拖延症,及时掌握一线信息
在日常的零售数据分析中,经常会因为数据量太大,分析指标太多且计算组合多变而导致数据分析报表难产,零售运营决策被迫拖延症。随着BI数据可视化分析技术的发展,智能化、可视化、自助分析的BI数据分析逐渐成熟,形成一套…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...

2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...

基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...

android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...

WPF八大法则:告别模态窗口卡顿
⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题:…...
HTML前端开发:JavaScript 获取元素方法详解
作为前端开发者,高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法,分为两大系列: 一、getElementBy... 系列 传统方法,直接通过 DOM 接口访问,返回动态集合(元素变化会实时更新)。…...

ubuntu22.04有线网络无法连接,图标也没了
今天突然无法有线网络无法连接任何设备,并且图标都没了 错误案例 往上一顿搜索,试了很多博客都不行,比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动,重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...