使用libiio v0.26实现接收缓冲区到发送缓冲区数据拷贝的问题求助
使用libiio v0.26实现接收缓冲区到发送缓冲区数据拷贝的问题求助
各位好,我目前在基于AD9361芯片开发,想用libiio把接收缓冲区里的IQ数据直接转发到发送缓冲区,实现一个简单的回环功能。我试了两种不同的拷贝方式,但都没能成功实现数据的转发,想请社区的大佬帮忙排查下问题。
以下是我的完整代码:
#include <error.h> #include <iio.h> #include <stdio.h> #include <string.h> #include <sys/time.h> #include <unistd.h> #define rx_b_s p_dat = iio_buffer_first(rxbuf, rx0_i) #define tx_b_s p_dat2 = iio_buffer_first(txbuf, tx0_i) #define rx_inc p_dat += p_inc #define tx_inc p_dat2 += p_inc2 #define rx_con p_dat < p_end #define tx_con p_dat2 < p_end2 #define BUFF_SIZE 1000000 #define KHZ(x) ((long long)(x * 100000.0 + .5)) #define MHZ(x) ((long long)(x * 1000000.0 + .5)) #define GHZ(x) ((long long)(x * 1000000000.0 + .5)) void receive(struct iio_context *ctx, struct iio_channel *RX_LO) { struct timeval start_tv, end_tv; long long start_us, end_us; double elapsed_ms, elapsed_ms2, elapsed_ms3; struct iio_device *dev; struct iio_device *dev2; struct iio_channel *rx0_i, *rx0_q; struct iio_channel *tx0_i, *tx0_q; struct iio_buffer *rxbuf; struct iio_buffer *txbuf; dev = iio_context_find_device(ctx, "cf-ad9361-lpc"); dev2 = iio_context_find_device(ctx, "cf-ad9361-dds-core-lpc"); rx0_i = iio_device_find_channel(dev, "voltage0", false); rx0_q = iio_device_find_channel(dev, "voltage1", false); tx0_i = iio_device_find_channel(dev2, "voltage2", true); tx0_q = iio_device_find_channel(dev2, "voltage3", true); if (iio_channel_is_scan_element(rx0_i)) { iio_channel_enable(rx0_i); printf("RX0_I enabled\n"); } else { printf("RX0_I cannot be enabled\n"); } if (iio_channel_is_scan_element(rx0_q)) { iio_channel_enable(rx0_q); printf("RX0_Q enabled\n"); } else { printf("RX0_Q cannot be enabled\n"); } if (iio_channel_is_scan_element(tx0_i)) { iio_channel_enable(tx0_i); printf("TX0_I enabled\n"); } else { printf("TX0_I cannot be enabled\n"); } if (iio_channel_is_scan_element(tx0_q)) { iio_channel_enable(tx0_q); printf("TX0_Q enabled\n"); } else { printf("RX0_Q cannot be enabled\n"); // 这里疑似笔误,应该是TX0_Q? } rxbuf = iio_device_create_buffer(dev, BUFF_SIZE, false); txbuf = iio_device_create_buffer(dev2, BUFF_SIZE, false); if (!rxbuf) { perror("Could not create RX buffer\n"); shutdown(); } if (!txbuf) { perror("Could not create TX buffer\n"); shutdown(); } ssize_t num, num2; while (true) { void *p_dat1; ptrdiff_t p_inc = iio_buffer_step(rxbuf); void *p_dat2; ptrdiff_t p_inc2 = iio_buffer_step(txbuf); void *p_end = iio_buffer_end(rxbuf); void *p_end2 = iio_buffer_end(txbuf); void *p_start2 = iio_buffer_start(txbuf); void *p_start = iio_buffer_start(rxbuf); // first variant //========================================================================== // num=iio_buffer_refill(rxbuf); // memcpy(p_start2,p_start,4*BUFF_SIZE); // num2=iio_buffer_push(txbuf); //========================================================================== // second variant num = iio_buffer_refill(rxbuf); if (num > 0) { printf("Refilled:%d\n", num); } for (p_dat1 = iio_buffer_first(rxbuf, rx0_i), p_dat2 = iio_buffer_start(txbuf); p_dat1 < p_end; p_dat1 += p_inc, p_dat2 += p_inc2) { const int16_t i = ((int16_t *)p_dat1)[0]; const int16_t q = ((int16_t *)p_dat1)[1]; ((int16_t *)p_dat2)[0] = i; ((int16_t *)p_dat2)[1] = q; } num2 = iio_buffer_push(txbuf); if (num2 > 0) { printf("Pushed:%d\n", num2); } } iio_buffer_destroy(rxbuf); iio_buffer_destroy(txbuf); } int main() { struct iio_context *ctx; struct iio_device *phy; struct iio_channel *rec; struct iio_channel *transmit; struct iio_channel *RX_LO; struct iio_channel *TX_LO; ctx = iio_create_context_from_uri("ip:192.168.2.1"); phy = iio_context_find_device(ctx, "ad9361-phy"); rec = iio_device_find_channel(phy, "voltage0", false); transmit = iio_device_find_channel(phy, "voltage0", true); RX_LO = iio_device_find_channel(phy, "altvoltage0", true); TX_LO = iio_device_find_channel(phy, "altvoltage1", true); iio_channel_attr_write_longlong(RX_LO, "frequency", 120000000); /* RX LO frequency 120MHz */ iio_channel_attr_write_longlong(rec, "rf_bandwidth", 50000000); iio_channel_attr_write_longlong(rec, "hardwaregain", 40); iio_channel_attr_write_longlong(rec, "sampling_frequency", 50000000); iio_channel_attr_write_longlong(TX_LO, "frequency", 1080000000); /*TX LO frequency 1080MHz*/ iio_channel_attr_write_longlong(transmit, "rf_bandwidth", 50000000); iio_channel_attr_write_longlong(transmit, "hardwaregain", 60); iio_channel_attr_write_longlong(transmit, "sampling_frequency", 50000000); receive(ctx, RX_LO); iio_context_destroy(ctx); return 0; }
我注意到代码里有个小细节:TX0_Q启用失败的打印信息写成了RX0_Q cannot be enabled,这应该是个笔误,但暂时不确定是否会影响功能。
回到核心问题:我尝试了两种数据转发方式:
- 第一种是直接调用
memcpy批量拷贝整个接收缓冲区的数据到发送缓冲区 - 第二种是循环遍历接收缓冲区的每个IQ样本,逐个拷贝到发送缓冲区对应位置
两种方式运行时,控制台都能正常打印Refilled和Pushed的日志,说明缓冲区的iio_buffer_refill和iio_buffer_push操作都返回了成功,但实际上并没有数据被正确发送出去。
我是参考旧版libiio的实现示例来写的,但在新版libiio的文档里没找到关于缓冲区直接转发的详细说明,不确定是不是API使用方式有变化,或者是AD9361的设备配置遗漏了关键步骤?
麻烦大家帮我看看代码里有没有明显错误,或者有没有什么libiio的使用细节我没注意到?
内容来源于stack exchange




