AD9026芯片开发实录6-example code

        官方发布的软件包中,带了一份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.mzph.cn/bicheng/39279.shtml

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

相关文章

使用ElementUI组件库

引入ElementUI组件库 1.安装插件 npm i element-ui -S 2.引入组件库 import ElementUI from element-ui; 3.引入全部样式 import element-ui/lib/theme-chalk/index.css; 4.使用 Vue.use(ElementUI); 5.在官网寻找所需样式 饿了么组件官网 我这里以button为例 6.在组件中使用…

【QT】常用控件|widget|QPushButton|RadioButton|核心属性

目录 ​编辑 概念 信号与槽机制 控件的多样性和定制性 核心属性 enabled geometry ​编辑 windowTiltle windowIcon toolTip styleSheet PushButton RadioButton 概念 QT 控件是构成图形用户界面(GUI)的基础组件,它们是实现与…

搜维尔科技:数据手套为什么要选择SenseGlove

了解 SenseGlove SenseGlove 是一支由电子工程师、触觉研究人员和计算机视觉专家、XR 开发人员、UX 设计师和产品创新者组成的科幻爱好者团队,他们拥有丰富人类能力和赋予 Metaverse 意义的技能和热情。 推进触觉技术是我们实现这一目标的方式。 公司及产品背景 S…

【C++知识点总结全系列 (02)】:C++中的语句、运算符和表达式详细总结

文章目录 1、语句(1)简单语句A.空语句B.复合语句 (2)条件语句(3)迭代语句A.常规for循环B.范围for循环C.while和do...while (4)跳转语句A.break语句B.continue语句C.goto语句 (5)异常处理语句A.标准异常B.throw抛出异常 (6)try语句 2、运算符(1)算术运算符(2)关系运算符(3)逻辑运…

Cybervadis认证是什么?

Cybervadis认证是一种全面且深入的网络安全评估和认证服务,旨在帮助组织提高其网络安全实践的成熟度,并有效应对不断变化的网络威胁和攻击。以下是关于Cybervadis认证的一些关键信息: 认证目的: 评估和验证组织在网络安全方面的能…

Andrej Karpathy提出未来计算机2.0构想: 完全由神经网络驱动!网友炸锅了

昨天凌晨,知名人工智能专家、OpenAI的联合创始人Andrej Karpathy提出了一个革命性的未来计算机的构想:完全由神经网络驱动的计算机,不再依赖传统的软件代码。 嗯,这是什么意思?全部原生LLM硬件设备的意思吗&#xff1f…

HarmonyOS开发实战:UDP通讯示例规范

1. UDP简介 UDP协议是传输层协议的一种,它不需要建立连接,是不可靠、无序的,相对于TCP协议报文更简单,在特定场景下有更高的数据传输效率,在现代的网络通讯中有广泛的应用,以最新的HTTP/3为例,…

vmware虚拟机安装openEuler

一、openEuler简介 openEuler是一款开源操作系统。当前openEuler内核源于Linux,支持鲲鹏及其它多种处理器,能够充分释放计算芯片的潜能,是由全球开源贡献者构建的高效、稳定、安全的开源操作系统,适用于数据库、大数据、云计算、…

EEPROM内部原理

A2, A1, A0是EEPROM的地址引脚,用于设置设备地址。它们的作用如下: 设备寻址: 这三个引脚允许在I2C总线上唯一地标识EEPROM芯片。通过不同的连接方式(接高、接低或悬空),可以为同一类型的EEPROM芯片设置不同…

1uH电感SK6615电流1.5A频率2MHz输入5.5V同步降压转换器

SK6615C 1.5A 2MHz 5.5V同步降压转换器 SK6615 SOT23-5封装和丝印LA 描述 该SK6615C是一款高效、DC-DC降压型开关稳压器,能够提供高达1.5A的输出电流。该器件的工作输入电压范围为 2.6V 至 5.5V,输出电压范围为 0.6V 至 VIN。工作频率为2MHz&#xff0c…

02.C1W1.Sentiment Analysis with Logistic Regression

目录 Supervised ML and Sentiment AnalysisSupervised ML (training)Sentiment analysis Vocabulary and Feature ExtractionVocabularyFeature extractionSparse representations and some of their issues Negative and Positive FrequenciesFeature extraction with freque…

玩具租赁系统(安装+讲解+源码)

技术栈: 后端: SpringBoot Mysql MybatisPlus 前端: Vue Element 分为 管理员端 用户端 功能: 用户端 管理员端 观看地址: B站搜: 【毕设者】玩具租赁系统(安装讲解源码)

Java高级重点知识点-13-数据结构、List集合、List集合的子类

文章目录 数据结构List集合List的子类(ArrayList集、LinkedList集) 数据结构 栈 stack,又称堆栈,它是运算受限的线性表,其限制是仅允许在标的一端进行插入和删除操作,不允许在其他任何位置进行添加、查找、删除等操作…

cesium 添加 Echarts图层(人口迁徒图)

cesium 添加 Echarts 人口迁徒图(下面附有源码) 1、实现思路 1、在scene上面新增一个canvas画布 2、通坐标转换,将经纬度坐标转为屏幕坐标来实现 3、将ecarts 中每个series数组中元素都加 coordinateSystem: ‘cesiumEcharts’ 2、示例代码 <!DOCTYPE html> <ht…

PCIe Switch

如图所示&#xff0c;pcie Switch 被定义为多个虚拟PCI-to-PCI Bridge设备的逻辑集合。所有交换机由以下基本规则管理。 . Switch在配置软件中表现为两个或多个逻辑PCI-to-PCI桥 不需要支持下行端口作为锁定请求的发起端口. 每个enable的端口必须符合“流量控制”规范。 .S…

Linux之进程控制(上)

目录 进程创建 进程终止 进程退出码 进程终止的方式 进程等待 进程等待的方式 status概述 总结 上期我们学习了Linux中进程地址空间的概念&#xff0c;至此进程的所有基本概念已经全部学习完成&#xff0c;今天我们将开始学习进程相关的操作。 进程创建 进程创建其实…

理解MySQL存储引擎:掌握数据存储与管理

在工作或学习过程中&#xff0c;作为一名数据库管理员或开发者&#xff0c;我们常常需处理大量数据&#xff0c;同时确保数据的可靠性与高效性。MySQL作为最受欢迎的开源数据库之一&#xff0c;其强大的性能和灵活性广为人知。而在MySQL背后的存储引擎则起到了至关重要的作用。…

强对抗的 SquidLoader 针对中国企业发起攻击

研究人员近期发现了一种高对抗强度的 Loader&#xff0c;其通过钓鱼邮件附件传递给受害者。根据恶意软件所具备的引诱和规避行为&#xff0c;研究人员将其命名为 SquidLoader。SquidLoader 最早在 2024 年 4 月下旬被发现&#xff0c;但研究人员认为其至少已经活跃了一个月以上…

Vue 数据大屏适配

1、准备俩个盒子 .dataScreen-content 盒子内容根据设计稿给的px单位进行正常的布局就行 2、盒子的CSS样式 .dataScreen-container {width: 100%;height: 100%;// 有背景图需要的样式background: url("./images/bg.png") no-repeat;background-repeat: no-repeat;b…

入门PHP就来我这(纯干货)04

~~~~ 有胆量你就来跟着路老师卷起来&#xff01; -- 纯干货&#xff0c;技术知识分享 ~~~~ 路老师给大家分享PHP语言的知识了&#xff0c;旨在想让大家入门PHP&#xff0c;并深入了解PHP语言。 我们接着《想入门PHP就来我这&#xff08;纯干货&#xff09;03》继续往下学习&am…