惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Y
Y Combinator Blog
GbyAI
GbyAI
IT之家
IT之家
V
Visual Studio Blog
J
Java Code Geeks
A
About on SuperTechFans
A
Arctic Wolf
Google Online Security Blog
Google Online Security Blog
博客园 - 【当耐特】
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
W
WeLiveSecurity
L
LINUX DO - 热门话题
Application and Cybersecurity Blog
Application and Cybersecurity Blog
G
Google Developers Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
Martin Fowler
Martin Fowler
N
News and Events Feed by Topic
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
小众软件
小众软件
Scott Helme
Scott Helme
T
Tailwind CSS Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
P
Palo Alto Networks Blog
罗磊的独立博客
V2EX - 技术
V2EX - 技术
C
Cybersecurity and Infrastructure Security Agency CISA
博客园 - 叶小钗
宝玉的分享
宝玉的分享
K
Kaspersky official blog
S
Securelist
Cyberwarzone
Cyberwarzone
Schneier on Security
Schneier on Security
PCI Perspectives
PCI Perspectives
S
Schneier on Security
Security Latest
Security Latest
腾讯CDC
SecWiki News
SecWiki News
I
InfoQ
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
T
The Blog of Author Tim Ferriss
Hacker News - Newest:
Hacker News - Newest: "LLM"
Forbes - Security
Forbes - Security
Google DeepMind News
Google DeepMind News
博客园 - 司徒正美
The Last Watchdog
The Last Watchdog
C
Check Point Blog
Hacker News: Ask HN
Hacker News: Ask HN
S
Secure Thoughts
博客园_首页
Stack Overflow Blog
Stack Overflow Blog

博客园 - 所长

Software-Defined Radio for Engineers 一 频谱仪 N9020A 操作步骤记录 FPGA-CAN MAC 层 IP 核测试(二) 源码阅读 libero reg 编译时 占用 RAM 资源 而不是 LUT 资源 加扰和解扰 FPGA-CAN MAC 层 IP 核测试(一) 上板实测 Microchip SoftConsole v2022.2-RISC-V-747 polarfire soc 裸机例程中 链接文件 mpfs-envm-lma-scratchpad-vma.ld 分析 FlashPro5 导致 window11 蓝屏 libero verilog 模块例化时,信号不存在 默认是 不连接 A3P250 在线 debug 抓取信号 Identify 在线逻辑分析仪 MPFS250T MSS 引脚 上下拉配置 如何在 libero 中 写一个 axi4 slave 总线的 IP核 可以 和 CoreAXI4Interconnect 连接 (五) 官方参考 verilog 按键消抖模块 如何在 libero 中 写一个 axi4 slave 总线的 IP核 可以 和 CoreAXI4Interconnect 连接 (四) axi-lite 信号抓取 libero Active Probes 如何在 libero 中 写一个 axi4 slave 总线的 IP核 可以 和 CoreAXI4Interconnect 连接 (三) C代码测试 访问卡死 如何在 libero 中 写一个 axi4 slave 总线的 IP核 可以 和 CoreAXI4Interconnect 连接 (二) axi-lite 如何在 libero 中 写一个 axi4 slave 总线的 IP核 可以 和 CoreAXI4Interconnect 连接(一)libero 设置把模块信号变总线方式 libero 2025.2 Macro Library User Guide for SmartFusion 2 and IGLOO 2 FPGAs 如何在 libero 中 写一个 axi4 slave 总线的 IP核 可以 和 CoreAXI4Interconnect 连接 (零) MSS CFG MPFS250T FLASH 只有 128KB 调整代码优化 AD9361 SPI no-os 文件移植 SoftConsole MPFS250T 初学(七) 初始化日志记录 AD9361 SPI no-os 文件移植 SoftConsole MPFS250T 初学(六) 开启 日志打印 Calibration TIMEOUT (0x247, 0x2) AD9361 SPI no-os 文件移植 SoftConsole MPFS250T 初学(四) ad9361_init 编译报错 和 读取 AD9361 ID AD9361 SPI no-os 文件移植 SoftConsole MPFS250T 初学(三) 接口适配到自己的板子 AD9361 SPI no-os 文件移植 SoftConsole MPFS250T 初学(二) AD9361 初始化流程 熟悉 AD9361 SPI no-os 文件移植 SoftConsole MPFS250T 初学(一) 驱动代码移植 RS422 差分 逻辑分析仪 抓包 libero Simulate - ModelSim ME 仿真 串口数据处理模块 vivado axi PS-PL 封装IP 创造自定义 外设 libero Simulate - ModelSim ME (三) 实战测试 双端口 RAM 读写 libero Simulate - ModelSim ME (二) 语法分析 libero Simulate - ModelSim ME (一) 新建工程 libero smartdebug Libero SoC CMP402 PolarFire SOC MSS 时钟源选择 polarfire Temperature and Voltage Sensor 温度和电压传感器 log2 PolarFire SoC Clock Conditioning Circuitry - CCC (PLL/DLL) 时钟源介绍(二) PolarFire SoC Clock Conditioning Circuitry - CCC (PLL/DLL) 初始化(三) PolarFire SoC Clock Conditioning Circuitry - CCC (PLL/DLL) 简单介绍(一) libero export flashpro express Job Libero MPFS250T PFSoC MSS Configurator 2025.2 DDR3 ECC 配置 Libero MPFS250T 如何使用 FPExpress 2025.2 烧录 MPFS250TS Direct C 编程后,使用 JTAG 读取的 DEVICE_INFO LOG Xilinx SDK 2019.1 使用 JTAG 将 10MB 文件 复制到 ZYNQ 的 DDR中 大约 20 秒 libero PolarFire soc SPI-DirectC 实战 dp_G5M_check_cycle_count libero PolarFire soc SPI-DirectC 实战 dp_G5M_do_program libero PolarFire soc SPI-DirectC 实战 dp_G5M_erase_action libero PolarFire soc SPI-DirectC 实战 dp_G5M_verify_digest_action
AD9361 SPI no-os 文件移植 SoftConsole MPFS250T 初学(五) ad9361_check_cal_done 卡死
所长 · 2026-05-05 · via 博客园 - 所长

AD9361 SPI no-os 文件移植 SoftConsole MPFS250T 初学(一) 驱动代码移植 - 所长 - 博客园

AD9361 SPI no-os 文件移植 SoftConsole MPFS250T 初学(二) AD9361 初始化流程 熟悉 - 所长 - 博客园

AD9361 SPI no-os 文件移植 SoftConsole MPFS250T 初学(三) 接口适配到自己的板子 - 所长 - 博客园

AD9361 SPI no-os 文件移植 SoftConsole MPFS250T 初学(四) ad9361_init 编译报错 和 读取 AD9361 ID - 所长 - 博客园

AD9361 SPI no-os 文件移植 SoftConsole MPFS250T 初学(五) ad9361_check_cal_done 卡死 - 所长 - 博客园

AD9361 SPI no-os 文件移植 SoftConsole MPFS250T 初学(六) 开启 日志打印 Calibration TIMEOUT (0x247, 0x2) - 所长 - 博客园

AD9361 SPI no-os 文件移植 SoftConsole MPFS250T 初学(七) 初始化日志记录 - 所长 - 博客园

RX PLL 一直无法锁定!!!

0x02 0x47 0x40 

image

static int32_t ad9361_check_cal_done(struct ad9361_rf_phy *phy, uint32_t reg,
                     uint32_t mask, uint32_t done_state)
{
    uint32_t timeout = 20000; /* RFDC_CAL can take long */
    uint32_t state;

    do {
        state = ad9361_spi_readf(phy->spi, reg, mask);
        if (state == done_state)
            return 0;

        if (reg == REG_CALIBRATION_CTRL)
            no_os_udelay(1200);
        else
            no_os_udelay(120);
    } while (timeout--);

    dev_err(&phy->spi->dev, "Calibration TIMEOUT (0x%"PRIX32", 0x%"PRIX32")", reg,
        mask);

    return -ETIMEDOUT;
}

问题找到, 移植 SPI 驱动库时,MPFS底层库 需要告知 发送字节数和接收字节数, 因此需要修改  ad9361的库 ,适配 MPFS 的接口, 

我 在 移植时没有看 

在 ad9361_spi_writem 函数 全部是 发送数据,没有读取数据 ,因此 导致错误!
 正确做法
ret = no_os_spi_write_and_read(spi, buf, 2+num, 0 );
错误做法:
ret = no_os_spi_write_and_read(spi, buf, 2,num );

/**
 * SPI multiple bytes register write.
 * @param spi
 * @param reg The register address.
 * @param tbuf The data buffer.
 * @param num The number of bytes to read.
 * @return 0 in case of success, negative error code otherwise.
 */
static int32_t ad9361_spi_writem(struct no_os_spi_desc *spi,
                 uint32_t reg, uint8_t *tbuf, uint32_t num)
{
    uint8_t buf[10];
    int32_t ret;
    uint16_t cmd;

    if (num > MAX_MBYTE_SPI)
        return -EINVAL;

    cmd = AD_WRITE | AD_CNT(num) | AD_ADDR(reg);
    buf[0] = cmd >> 8;
    buf[1] = cmd & 0xFF;

#ifndef ALTERA_PLATFORM
    memcpy(&buf[2], tbuf, num);
#else
    int32_t i;
    for (i = 0; i < num; i++)
        buf[2 + i] =  tbuf[i];
#endif
    /* suozhang 2026/05/04 修改形参 传输字节数 改为 发送字节数和接收字节数 适配 MPFS 底层库 */
// 特别注意这里 全部是发送字节,没有读取字节,
ret = no_os_spi_write_and_read(spi, buf, 2+num, 0 ); if (ret < 0) { dev_err(&spi->dev, "Write Error %"PRId32, ret); return ret; } #ifdef _DEBUG { int32_t i; for (i = 0; i < num; i++) dev_dbg(&spi->dev, "Reg 0x%"PRIX32" val 0x%X", reg--, tbuf[i]); } #endif return 0; }
/**
 * SPI multiple bytes register read.
 * @param spi
 * @param reg The register address.
 * @param rbuf The data buffer.
 * @param num The number of bytes to read.
 * @return 0 in case of success, negative error code otherwise.
 */
int32_t ad9361_spi_readm(struct no_os_spi_desc *spi, uint32_t reg,
             uint8_t *rbuf, uint32_t num)
{
    int32_t ret = 0;
    uint16_t cmd;
    uint8_t *rbuffer;
    if (num > MAX_MBYTE_SPI)
        return -EINVAL;

    cmd = AD_READ | AD_CNT(num) | AD_ADDR(reg);
    rbuffer = no_os_malloc(num + 2);
    if (!rbuffer)
        return -ENOMEM;
    rbuffer[0] = cmd >> 8;
    rbuffer[1] = cmd & 0xFF;
    /* suozhang 2026/05/04 修改形参 传输字节数 改为 发送字节数和接收字节数 适配 MPFS 底层库 */
    ret = no_os_spi_write_and_read(spi, &rbuffer[0], 2, num);

    if (ret < 0)
        dev_err(&spi->dev, "Read Error %"PRId32, ret);
    else
        memcpy(rbuf, &rbuffer[2], num);

    no_os_free(rbuffer);
#ifdef _DEBUG
    {
        int32_t i;
        for (i = 0; i < num; i++)
            dev_dbg(&spi->dev, "%s: reg 0x%"PRIX32" val 0x%X",
                __func__, reg--, rbuf[i]);
    }
#endif

    return ret;
}
/**
 * SPI register write.
 * @param spi
 * @param reg The register address.
 * @param val The value of the register.
 * @return 0 in case of success, negative error code otherwise.
 */
int32_t ad9361_spi_write(struct no_os_spi_desc *spi,
             uint32_t reg, uint32_t val)
{
    uint8_t buf[3];
    int32_t ret;
    uint16_t cmd;

    cmd = AD_WRITE | AD_CNT(1) | AD_ADDR(reg);
    buf[0] = cmd >> 8;
    buf[1] = cmd & 0xFF;
    buf[2] = val;
    /* suozhang 2026/05/04 修改形参 传输字节数 改为 发送字节数和接收字节数 适配 MPFS 底层库 */
    ret = no_os_spi_write_and_read(spi, buf, 3, 0);
    if (ret < 0) {
        dev_err(&spi->dev, "Write Error %"PRId32, ret);
        return ret;
    }

#ifdef _DEBUG
    dev_dbg(&spi->dev, "%s: reg 0x%"PRIX32" val 0x%X", __func__, reg, buf[2]);
#endif

    return 0;
}