AD9361 SPI no-os 文件移植 SoftConsole MPFS250T 初学(五) ad9361_check_cal_done 卡死
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

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; }
浙公网安备 33010602011771号