AD9026芯片开发实录6-example code

news2024/12/28 18:39:36

        官方发布的软件包中,带了一份example code,用于向客户展示API的调用方法以及基于官方的验证版ADRV902X最简单的bring up的流程。

        该 example 位于软件包的路径下:“\Adi.Adrv9025.Api\src\c_src\app\example\”。

        代码组成:

        

  1. initdata.c / initdata.h 定义了一组默认的初始化配置参数和多片同步后初始化(PostMCS)的配置。这两个文件可以通过官方提供的GUI生成得到。在example code的工程中,initdata.c 源文件定义的 `adrv9025InitInst` 初始化配置结构体,并不会被用到,在后续的章节中会进行说明。

  2. main.c 文件给出了example 工程的具体实现,包括单板的初始化,FPGA/时钟芯片的初始化,以及ADRV902X的bringup,这些流程都是通过调用官方提供的API来实现的。

  3. makefile文件给出了构建example工程的方法,在Linux的环境中makefile较为通用,同时该makefile文件也给出了API的构建集成方式。

        下面的章节会重点介绍这几个文件中的代码实现以及如何在官方提供的验证板上构建并运行example code

        main函数的开头,就是单板的一些初始化准备工作:

        

int main(){    uint32_t rxChannelMaskGet = 0x00;    uint32_t txChannelMaskGet = 0x00;    uint32_t rxChannelMaskSet = 0x0F;    uint32_t txChannelMaskSet = 0x0F;    int inputSelection = 0x00;    recoveryAct = discoverPlatform();    if (recoveryAct != ADI_COMMON_ACT_NO_ACTION)    {        printf("\nERROR: : %s:%u has failed.\n", __func__, __LINE__);    }

       官方给的函数名称也比较有实际意义,`discoverPlatform`的字面意思是发现平台,也就是说在正式开始各种初始化工作前,需要先确定单板信息以及做一些软件层面的准备工作。

        ADRV902X官方指定的验证板是ADS9-V2EBZ,但由于该数字板的价格偏高,且单板的bringup时间较长,所以一般会选用价格较为便宜的ADS8作为其数字验证板使用,但是官方的example code例程并不支持ADS8 验证板。话题回到软件层面,`discoverPlatform`函数就是用来识别当前使用的验证板平台。

       在软件层面,ADI把数字板抽象为母板(motherboard),而ADRV902X 射频验证板抽象为子板(daughterboard),motherboard和daughterboard各有一个抽象出来的结构体,分别是 `adi_motherboard_trx_t`  和 `adi_daughterboard_trx_t`,这两个结构体采用了面向对象的思想,其中包含了单板的相关属性和操作方法。motherboard结构体中包含了daughterboard的结构体,这个也比较好理解,对比到硬件上,ADRV902X的验证平台,是由数字母版和扣在母版上的子板一并构成的。

函数`discoverPlatform`的实现如下:

{    printf("\n*** Begin Platform Discover *** ");    /********************************************************************************************/    /**************** Discover motherboard ******************************************************/    /********************************************************************************************/    /* This API creates a generic structure to hold all the necessary motherboard information ***/    recoveryAct = adi_motherboard_Discover(&motherboard);    if ((recoveryAct != ADI_COMMON_HAL_OK) || (motherboard == NULL))    {        printf("ERROR: adi_Motherboard_Discover has failed.\n");        return ADI_COMMON_ACT_ERR_RESET_FULL;    }    /**************** END: Discover motherboard *************************************************/    /********************************************************************************************/    /**************** Discover daughterboard ****************************************************/    /********************************************************************************************/    /* This API creates a generic structure to hold all the necessary daughterboard information */    recoveryAct = adi_daughterboard_Discover(motherboard);    if ((recoveryAct != ADI_COMMON_HAL_OK) || (motherboard == NULL))    {        printf("ERROR: ERPC-SERVER: %s:%u has failed.\n", __func__, __LINE__);        return failureReturn;    }    ...}    

        可以看到这个函数的主要作用是完成母版和子板的识别以及完成相关的硬件初始化的预备工作,比如配置结构体的初始化,hal层接口的挂接,硬件设备的资源配置等。

adi_motherboard_Discover

该函数的主要功能包括:

  1. 实例化子板结构体 `adi_daughterboard_trx_t`,并初始化其成为0;

  2. 实例化母板的设备层抽象,包括LOG和TIMER这两个模块;

  3. 识别母版类型;

  4. 完成platform 的hal层函数钩子注册挂接;

  5. 调用hal层设备打开接口,打开log模块;

注意这里很重要的一步是第4步,也是实际开发人员在集成的时候需要注意的步骤。

adi_daughterboard_Discover

在完成motherboard 的发现之旅后,便开始启动子板的发现之旅。该函数的主要功能包括:

1. 实例化子版的设备抽象,包括I2C/LOG/TIMER 这三个模块;

2. 挂接daughterboard对象中的方法(钩子函数们);

3. 通过daughterBoard->DeviceCreate,完成Clock/FPGA/TrxBoard 的Dispatch方法注册,用于后续的Clock/FPGA/TrxBoard的硬件初始化和配置操作,然后实例化Clock/FPGA/ADRV902X设备,在代码中对应结构体`adi_ad9528_Device_t`/`adi_adrv9025_Device_t`/`adi_fpga9010_Device_t`;

4. 通过daughterBoard->DeviceInit,实例化Clock/FPGA/TrxBoard的设备层抽象,这其中包含各个设备的SPI/I2C 总线接口,LOG 和 TIMER 模块,并调用 `adi_hal_HwOpen` 完成设备的打开。

        完成上述所有工作后,会将子板中实例化的Clock/FPGA/TrxBoard设备保存到三个全局对象中,分别为 `ad9528Device`/`adrv9025Device`和`fpga9025Device`中,方便后续的代码使用。

        总而言之,在真正program ADRV902X之前,官方示例代码通过子母板的抽象,完成了底层钩子函数的挂接、设备软件资源的分配、设备对应的控制总线(SPI/I2C)以及LOG 的基本配置和打开,为后续ADRV902X的初始化和Program做准备。

        这部分内容对用户做代码集成的时候有一定的指导作用。

ADRV902X 初始化及API使用方法

        回到示例main函数的主流程中,完成子母板以及子母板上设备的实例化和HAL抽象层初始化后,正式开始对ADRV902X 芯片进行初始化和配置。

        配置加载

        首先需要从UseCase的profile文件中加载配置,在实际的应用项目上,这一步可以跳过,如前文所说,可以使用GUI生成的initdata.h/initdata.c 文件,initdata.c 中保存了GUI根据实际修改配置所生成的所有关于ADRV902X的配置。在示例代码中使用了 `adi_adrv9025_ConfigFileLoad` 这个API来完成的这个任务,这也是在示例工程中第一个显式地调用ADRV902X API的例子:​​​​

static void configFileLoad(adi_adrv9025_Device_t *adrv9025_Device,                           adi_adrv9025_Init_t   *adrv9025_Init){    recoveryAct = ADI_COMMON_ACT_ERR_RESET_FULL;    /* Load ADRV9010 Init structure */    /* adiProfileFilePath is defined as const global at top of this file */    recoveryAct = adi_adrv9025_ConfigFileLoad(adrv9025_Device, adiProfileFilePath, adrv9025_Init);    if (recoveryAct != ADI_COMMON_ACT_NO_ACTION)    {        printf("ERROR: : %s:%u has failed.\n", __func__, __LINE__);        exit(EXIT_FAILURE);    }}

        这个例子也很好地说明了如何调用官方提供的API,ADI提供的API命名格式均为 `adi_adrv9025_functionName`,至少有一个入参 `adi_adrv9025_Device_t *adrv9025_Device`,返回值为 init32_t 类型的运行结果;所以调用时一般会先申明一个返回值变量,用来保存API的执行结果。API的第一个参数即为上一章节中提到的实例化的设备结构指针 adrv9025Device 。

        函数 `configFileLoad` 执行成功后会将加载的配置保存在全局变量 `adrv9025InitInst`中,也即initdata.c 中的配置结构体变量,这也是前面提到的,example code中initdata.c 的配置不会被用到的原因。关于ADRV902X的配置结构,以后有时间会更新专门的文章进行描述。

        在加载配置完成后,会通过usecase中的device clock/vcxo/reference clock 的值生成时钟的配置参数并保存。

        随后的操作是单板的PreProgram,其中会检查设备结构体是否实例化,并再次加载配置,感觉有点多余。

        最后的一部分是FPGA和clock的硬件初始化与配置,主要包括FPGA的AXI总线配置,MMCM配置,JESD配置等。至此完成了配置文件的加载和FPGA以及时钟的配置信息,历程运行到这里,可以看到ADRV902X子板上的时钟指示灯处于锁定状态。

        ADRV902X初始化

在完成上述的基本配置加载后,正式开始ADRV902X的初始化配置,配置的主要流程如下:

1. HWReset:ADRV902X芯片要求在上电配置之前,需要对芯片做一次硬件复位,API `adi_adrv9025_HwReset`即完成这个任务,但这个API同时也会检查hal层钩子函数的挂接状态以及硬件SPI的校验。

2. PreMcsInit:这一步是ADRV902X的具体初始化的第一步,通过调用API `adi_adrv9025_PreMcsInit_v2`来完成,这一步会初始化ADRV902X相关外设,加载ADRV902X的相关资源,比如固件版本、stream 二进制文件,增益补偿表等,然后尝试启动ADRV902X的arm芯片。

这里注意,API `adi_adrv9025_PreMcsInit_v2`需要提供初始化配置结构体,固件版本在BBIC侧单板操作系统中的路径,stream 二进制文件在BBIC侧单板操作系统中的路径,RX和TX的增益表。

3. NonBroadCast: 这一步主要是在上一步的基础上,等待ADRV902X 中的arm启动成功,并对TX和RX的通道参数进行配置,生成JESD的参数,通过调用API `adi_adrv9025_PreMcsInit_NonBroadCast` 实现。

4. MCS:这一步是完成多片ADRV902X的同步,需要时钟芯片的参与,MCS的控制是通过API `adi_adrv9025_MultichipSyncSet` 来实现,具体代码实现可参考example code。

5. PostMcsInit: 在完成多片同步后,还有一些初始化工作,比如TRX通道的使能,TXORX mapping,ADRV902X的InitialCal 的使能,这些工作都是在PostMcs阶段完成,通过调用API `adi_adrv9025_PostMcsInit` 实现。

6. JESD Link setup: 截止到上一步,芯片相关的基本配置和初始化已经完成,此时需要进行JESD建链操作,这个步骤稍微复杂一些,因为涉及到FPGA,clock和ADRV902X三个芯片的配合和设置,在example code中可以查看 `jesdBringup`这个函数。

7. Pa protection init: 在建链完成后,为了保护后继的PA,需要打开ADRV902X的PA 保护功能,通过调用 API `adi_adrv9025_TxRampDownInit` 来实现。

8. GP Int init: 这一步是打开GP INT的状态监控,这样我们就可以通过ADRV902X的两个GPIO管脚来监控芯片内部的事件,通过API `adi_adrv9025_GpIntInit` 来实现。

        上述的所有流程在main.c 中都被封装到了接口`programMadura`中,具体实现可以参考main.c 中该函数的源码。

        截止到这里,整个ADRV902X的初始化和板级的初始化已经结束,后续可以调用ADRV902X相关的功能API对其进行测试和控制,比如打开芯片的tracking calibration,TRX通道开关控制,ATT设置等。

        上述的流程涵盖了最基本的ADRV902X 设备的初始化流程,用户或开发者可以按照该流程将ADRV902X的初始化集成到自己的软件工程中。

 代码编译与环境部署

        ADI官方提供的构建工具为make,在example code的目录下可以看到Makefile,通过该makefile,可以直接在交叉编译环境,或者是官方的EVB板(ADS9/8) 上对代码进行编译构建。

        先说一下官方软件包中的makefile结构,除了device文件夹外,其他项目的次顶层文件夹下均有一个makefile,device文件夹下除了share_utils外的文件夹下,也均有makefile,这些makefile的构建目标,均为静态编译库,也就是说,这些文件夹内的文件相对独立,只会以接口形式调用其他文件夹下的函数。

        这些库的构建,均可以通过./c_src/boards下的makefile触发。这些库都会被example code工程构建所使用。对于example code 的makefile,通过调用上述./c_src/boards 下的makefile触发所有的静态库的编译,并链接到最终的输出应用的方式,构建完成整个example code工程:

        需要注意的一点是,官方提供的makefile中,是不包含debug编译选项的,如果所以如果是移植makefile并包含调试符号表时,可以增加debug编译选项为g1。作为编译的演示,使用指令 `make all -j4`即可启动编译,其中生成的'main'即为example code工程的应用程序:

        在构建完成后,我们需要在构建平台的文件系统上上传ADRV902X初始化需要的资源,如 固件版本,增益表,usecase profile等,存放的位置可以参考example code中的这两个变量:

const char adiProfileFilePath[] = "/home/analog/adrv9025_c_example/resources/adrv9025/profiles/public/ADRV9025Init_StdUseCase13_nonLinkSharing.profile";static adi_adrv9025_PlatformFiles_t platformFiles = { { "/home/analog/adrv9025_server/resources/ADRV9025_FW.bin;/home/analog/adrv9025_server/resources/ADRV9025_DPDCORE_FW.bin" },                                                      { "/home/analog/adrv9025_c_example/resources/adrv9025/arm_firmware/stream_image.bin" },                                                      { { { "/home/analog/adrv9025_c_example/resources/adrv9025/gain_tables/RxGainTable.csv" }, 0xFF } },                                                      1,                                                      { { { "/home/analog/adrv9025_c_example/resources/adrv9025/gain_tables/TxAttenTable.csv" }, 0x0F } },                                                      1 };

运行结果

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

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

相关文章

[开源软件] 支持链接汇总

“Common rules: 1- If the repo is on github, the support/bug link is also on the github with issues”" label; 2- Could ask questions by email list;" 3rd party software support link Note gcc https://gcc.gnu.org openssh https://bugzilla.mindrot.o…

CAN通信波形【示波器抓取】

在测试bms系统过程中,在上位机发现无法读取CAN通信,尝试使用示波器抓取CAN通信波形,,去确定CAN通信是否正常。 做一想要从车上测出can总线上的数据还不太容易。 于是我首先使用示波器(我使用的示波器型号是TDS 220&am…

Python爬虫与数据可视化:构建完整的数据采集与分析流程

Python爬虫技术概述 Python爬虫是一种自动化的数据采集工具,它可以模拟浏览器行为,访问网页并提取所需信息。Python爬虫的实现通常涉及以下几个步骤: 发送网页请求:使用requests库向目标网站发送HTTP请求。获取网页内容&#xf…

雷电模拟器9 开启指针位置但是,没有任何作用,解决方法

问题:雷电模拟器9 开启指针位置,但是没有作用。 参考文档: https://blog.csdn.net/qq_39587350/article/details/127234421解决方法: 1.找到雷电模拟器的安装位置 2.进入安装位置,找到vms 文件夹,并创建 …

想要打造超高性能的接口API?试试这12条小技巧。

1. 并行处理 简要说明 举个例子:在价格查询链路中,我们需要获取多种独立的价格配置项信息,如基础价、折扣价、商户活动价、平台活动价等等。 CompletableFuture 是银弹吗? 使用 CompletableFuture 的确能够帮助我们解决许多独…

从零开始实现大语言模型(二):文本数据处理

1. 前言 神经网络不能直接处理自然语言文本,文本数据处理的核心是做tokenization,将自然语言文本分割成一系列tokens。 本文介绍tokenization的基本原理,OpenAI的GPT系列大语言模型使用的tokenization方法——字节对编码(BPE, byte pair en…

VUE3 播放RTSP实时、回放(NVR录像机)视频流(使用WebRTC)

1、下载webrtc-streamer,下载的最新window版本 Releases mpromonet/webrtc-streamer GitHub 2、解压下载包 3、webrtc-streamer.exe启动服务 (注意:这里可以通过当前文件夹下用cmd命令webrtc-streamer.exe -o这样占用cpu会很少&#xff0c…

echarts用pictorialBar实现3D柱状图

先看下效果 实现思路 描绘一个普通的柱状图通过象形柱图&#xff08;pictorialBar&#xff09;在柱状图的顶部添加一个图形类型&#xff08;symbol&#xff09;菱形 代码实现 <template><div id"symbolBar"></div> </template> <scrip…

jenkins在使用pipeline时,为何没有方块形视图

项目场景&#xff1a; 安装完Jenkins时后&#xff0c;通过pipeline创建的项目任务。 问题描述 在立即构建后&#xff0c;没有显示每个阶段的视图。 原因分析&#xff1a; 原因是&#xff0c;刚安装的Jenkins&#xff0c;这个视图不是Jenkins自带的功能&#xff0c;而必须安装…

分班查询系统,老师们应该如何制作?

新学期的开始&#xff0c;作为教师&#xff0c;我们面临的一项关键任务就是组织分班。传统分班方法往往需要处理大量的数据&#xff0c;这个过程不仅耗时&#xff0c;而且容易出错。为了简化这一流程&#xff0c;提高效率&#xff0c;我们可以利用现代技术&#xff0c;创建一个…

不要再被骗了!电脑无法进入系统的原因可能是这个硬件坏了而已……

前言 前段时间小白在抖音上发了很多很多很多的视频&#xff0c;其中应该是有很多商家关注了小白。 然后就会出现很多很多很多的赚钱小门道…… 电脑开机没有显示&#xff1f;换显卡&#xff01; 电脑还是不开机&#xff1f;换CPU 电脑还是一样不开机…… 经过了一番大折腾…

三步学会使用WebSocekt

目录 一 什么是websocket 二 如何使用websocket 1.导入websocket的maven坐标 2.创建websocket的服务类 3.创建websocket的配置类 4.按需求实现业务逻辑 5.前端实现websocket 一 什么是websocket websocket和HTTP一样是基于TCP的一个通信协议。不过他是支持客户端和服务端…

鸿蒙开发Ability Kit(程序访问控制):【使用粘贴控件】

使用粘贴控件 粘贴控件是一种特殊的系统安全控件&#xff0c;它允许应用在用户的授权下无提示地读取剪贴板数据。 在应用集成粘贴控件后&#xff0c;用户点击该控件&#xff0c;应用读取剪贴板数据时不会弹窗提示。可以用于任何应用需要读取剪贴板的场景&#xff0c;避免弹窗…

JDK动态代理-AOP编程

AOPTest.java&#xff0c;相当于main函数&#xff0c;经过代理工厂出来的Hello类对象就不一样了&#xff0c;这是Proxy.newProxyInstance返回的对象&#xff0c;会hello.addUser会替换为invoke函数&#xff0c;比如这里的hello.addUser("sun", "13434");会…

将数据切分成N份,采用NCCL异步通信,让all_gather+matmul尽量Overlap

将数据切分成N份,采用NCCL异步通信,让all_gathermatmul尽量Overlap 一.测试数据二.测试环境三.普通实现四.分块实现 本文演示了如何将数据切分成N份,采用NCCL异步通信,让all_gathermatmul尽量Overlap 一.测试数据 1.测试规模:8192*8192 world_size22.单算子:all_gather:0.035…

数字化供应链:背景特点

​背景 1、外部环境 近年来&#xff0c;供应链脆弱性凸显&#xff0c;企业供应链压力难以缓解。 美国媒体针对美国零售联合会、美国服装和鞋类协会、美国供应链管理专业委员会等主体进行的一项供应链调查显示&#xff1a; 61%的供应链经理预计&#xff0c;供应链紊乱问题至少…

在IDEA中创建Maven项目

相关内容&#xff1a; Maven的安装与配置 在IDEA中配置Maven环境 IDEA中导入Maven项目 2023版IDEA创建Maven项目&#xff08;新版&#xff09; 1.打开IDEA&#xff0c;点击 文件 -> 新建 -> 项目 2.创建Maven项目 3.编写java文件并运行 在src -> java -> 创建…

xcode运行ios项目报错Sandbox: rsync.samba(24352) deny(1) file-write-create

xcode运行ios项目报错 Sandbox: rsync.samba(24352) deny(1) file-write-create 解决方案&#xff1a; Update your Xcode project build option ENABLE_USER_SCRIPT_SANDBOXING to No.

谷歌GenType:1分钟生成AI艺术字母表,小众但好用,完全免费!(附教程)

文章首发于公众号&#xff1a;X小鹿AI副业 大家好&#xff0c;我是程序员X小鹿&#xff0c;前互联网大厂程序员&#xff0c;自由职业2年&#xff0c;也一名 AIGC 爱好者&#xff0c;持续分享更多前沿的「AI 工具」和「AI副业玩法」&#xff0c;欢迎一起交流~ 最近发现一个好玩的…

2024最新版Redis常见面试题包含详细讲解

Redis适用于哪些场景&#xff1f; 缓存分布式锁降级限流消息队列延迟消息队 说一说缓存穿透 缓存穿透的概念 用户频繁的发起恶意请求查询缓存中和数据库中都不存在的数据&#xff0c;查询积累到一定量级导致数据库压力过大甚至宕机。 缓存穿透的原因 比如正常情况下用户发…