我正在开发运行uClinux的AD Blackfin BF537 DSP。我总共有32MB SD-RAM。我附加了一个ADC,我可以使用对read()
的简单阻塞调用来访问它。
我的代码中最有趣的部分如下。运行该程序似乎工作得很好,我得到一个很好的数据包,我可以从SD卡和绘图中获取。但是,如果我注释掉浮点计算部分(如代码中所述),我在ft_all.raw文件中只得到零。如果我将优化级别从-O3更改为-O0,则会出现相同的情况。
我已经尝试了各种各样的组合,有时它可以工作,有时它不会 - 早些时候(稍微修改一下),代码只有在禁用优化时才能工作。如果我在文件中添加其他内容,它也可能会中断。
我怀疑read()
- 函数传输的数据可能没有完全传输(即使它返回正确的字节数,也可能这样做)。这也是我第一次使用直接内存地址初始化指针,我不知道编译器如何对此作出反应 - 也许我错过了什么,在这里?
我现在在这个问题上花了好几天,而且我已经绝望了 - 我真的很感激这个问题的一些帮助!提前谢谢。
// Clear the top 16M memory for data processing
memset((int *)0x01000000,0x0000,(size_t)SIZE_16M);
/* Prep some pointers for data processing */
int16_t *buffer;
int16_t *buf16I, *buf16Q;
buffer = (int16_t *)(0x1000000);
buf16I = (int16_t *)(0x1600000);
buf16Q = (int16_t *)(0x1680000);
/* Read data from ADC */
int rbytes = read(Sportfd, (int16_t*)buffer, 0x200000);
if (rbytes != 0x200000) {
printf("could not sample data! %X\n",rbytes);
goto end;
} else {
printf("Read %X bytes\n",rbytes);
}
FILE *outfd;
int wbytes;
/* Commenting this region results in all zeroes in ft_all.raw */
float a,b;
int c;
b = 0;
for (c = 0; c < 1000; c++) {
a = c;
b = b+pow(a,3);
}
printf("b is %.2f\n",b);
/* Only 12 LSBs of each 32-bit word is actual data.
* First 20 bits of nothing, then 12 bits I, then 20 bits
* nothing, then 12 bits Q, etc...
* Below, the I and Q parts are scaled with a factor of 16
* and extracted to buf16I and buf16Q.
* */
int32_t *buf32;
buf32 = (int32_t *)buffer;
uint32_t i = 0;
uint32_t n = 0;
while (n < 0x80000) {
buf16I[i] = buf32[n] << 4;
n++;
buf16Q[i] = buf32[n] << 4;
i++;
n++;
}
printf("Saving to /mnt/sd/d/ft_all.raw...");
outfd = fopen("/mnt/sd/d/ft_all.raw", "w+");
if (outfd == NULL) {
printf("Could not open file.\n");
}
wbytes = fwrite((int*)0x1600000, 1, 0x100000, outfd);
fclose(outfd);
if (wbytes < 0x100000) {
printf("wbytes not correct (= %d) \n", (int)wbytes);
}
printf(" done.\n");
编辑:如果我使用read()从简单文件而不是ADC读取数据,代码似乎运行得很好。这让我相信,在提取输入的I和Q部分时,看起来相当hacky的代码正在按预期工作。检查编译器生成的程序集确认了这一点。
我正在尝试与ADC驱动程序的开发人员联系,看他是否对此行为有解释。
ADC通过SPORT连接,并按此打开:
sportfd = open("/dev/sport1", O_RDWR);
ioctl(sportfd, SPORT_IOC_CONFIG, spconf);
以下是配置SPORT时使用的选项:
spconf->int_clk = 1;
spconf->word_len = 32;
spconf->serial_clk = SPORT_CLK;
spconf->fsync_clk = SPORT_CLK/34;
spconf->fsync = 1;
spconf->late_fsync = 1;
spconf->act_low = 1;
spconf->dma_enabled = 1;
spconf->tckfe = 0;
spconf->rckfe = 1;
spconf->txse = 0;
spconf->rxse = 1;
还包括ADI公司的bfin_sport.h文件:https://gist.github.com/tausen/5516954
更新 在与项目的前任开发人员进行了长时间的调试之后,事实证明该问题与上面显示的代码无关。正如克里斯所说,这确实是SPORT驱动程序和ADC配置的问题。
在调试时,只要数据“损坏”,就会出现此错误消息:bfin_sport: sport ffc00900 status error: TUVF
。虽然这在应用程序中没有多大意义,但从打印数据可以清楚地看出,某些内容不同步:缓冲区中的数据只有状态0x12000000,0x34000000,...
而不是0x00000012,0x00000034,...
。显示错误。这似乎很清楚,为什么buf16I和buf16Q只包含零(因为我提取了12个LSB)。
在ADC初始化和配置阶段之间对usleep()
进行一些调用似乎已经解决了这个问题 - 我希望它能保持这种状态!