工程开发中,我们想做一些使用频率不高但精度要求高的FFT运算,用FPGA做浮点FFT会占用大量资源,定点FFT又有截位的问题存在,因此用PS做浮点FFT是一个不错的选择
适用于armA9的FFT库有FFTw,Ne10和CMSIS-DSP。
CMSIS-DSP库包含各种信号处理库,但大部分都可以用PL来做,且其FFT最高只支持4096点,不是很好用。
Ne10库要求有系统,不能裸机运行,同时也只支持2的N次方倍FFT
而FFTw库支持任意点数FFT,虽然不支持定点,但也非常好的契合我们的需求(使用频率不高但精度要求高)
交叉编译工具链
安装交叉编译工具链,进入arm官网下载适用于自己系统的工具链
Downloads | GNU Arm Embedded Toolchain Downloads – Arm Developer
下面以Linux系统为例,将下载的压缩包复制到任意路径,执行以下命令,win系统则双击exe文件安装
tar -xjvf gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2 -C gcc-arm-none-eabi --strip-components=1
sudo mv gcc-arm-none-eabi /opt/
sudo chmod -R 755 /opt/gcc-arm-none-eabi
添加环境变量,vim ~/.bashrc,添加以下代码,source ~/.bashrc
#arm工具链
export PATH="/opt/gcc-arm-none-eabi/bin:$PATH"
win环境也要把添加工具链bin文件添加到环境变量
执行which arm-none-eabi-gcc命令验证环境变量是否添加正确
编译FFTW库
下载源码
下载最新的FFTW库
wget http://www.fftw.org/fftw-3.3.10.tar.gz
tar -xvzf fftw-3.3.10.tar.gz
cd fftw-3.3.10
配置FFTW
运行以下命令配置 FFTW 以进行裸机运行
注意:记得将 --prefix=/home/milad/build 更改为你自己的地址。
./configure
--host=arm-none-eabi
--enable-float
--enable-neon
--disable-threads
--enable-static
--disable-shared
--prefix=/home/milad/build
CFLAGS="-O3 -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=hard -ffast-math -ffreestanding -DFFTW_NO_TIMER"
LDFLAGS="-lm --specs=nosys.specs"
编译
make
make install
得到如下目录结构,注意看lib文件夹下有没有libfftw3f.a
build
├── bin
│ ├── fftwf-wisdom
│ └── fftw-wisdom-to-conf
├── include
│ ├── fftw3.f
│ ├── fftw3.f03
│ ├── fftw3.h
│ ├── fftw3l.f03
│ └── fftw3q.f03
├── lib
│ ├── cmake
│ │ └── fftw3
│ │ ├── FFTW3fConfig.cmake
│ │ └── FFTW3fConfigVersion.cmake
│ ├── libfftw3f.a
│ ├── libfftw3f.la
│ └── pkgconfig
│ └── fftw3f.pc
└── share
├── info
│ ├── dir
│ ├── fftw3.info
│ ├── fftw3.info-1
│ └── fftw3.info-2
└── man
└── man1
├── fftwf-wisdom.1
└── fftw-wisdom-to-conf.1
工程配置
打开vitis工程,进入userconfig.cmake文件
添加头文件路径
添加FFTW库
添加编译器杂项(Other flags)
"-mfpu=neon-vfpv4 -mcpu=cortex-a9 -mfloat-abi=hard"
FFT测试
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include <fftw3.h>
void _gettimeofday(void){};
int main() {
//100点FFT测试
int N = 100;
fftwf_complex in[N], out[N];
fftwf_plan p;
p = fftwf_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
// Set input values
for (int i = 0; i < N; i++) {
in[i][0] = i; // Real part
in[i][1] = 0; // Imaginary part
}
fftwf_execute(p);
fftwf_destroy_plan(p);
print("FFTOKn");
//Print output
for (int i = 0; i < N; i++)
printf("out[%d] = %f + %fin", i, out[i][0], out[i][1]);
return 0;
}
串口打印结果如下
FFTOK
out[0] = 4950.000000 + 0.000000i
out[1] = -49.999977 + 1591.025879i
out[2] = -49.999981 + 794.727295i
out[3] = -50.000000 + 528.944702i
out[4] = -50.000031 + 395.790741i
out[5] = -50.000000 + 315.687592i
out[6] = -49.999985 + 262.109161i
out[7] = -49.999996 + 223.687149i
out[8] = -50.000031 + 194.737122i
out[9] = -50.000008 + 172.101135i
out[10] = -50.000000 + 153.884186i
...


Comments NOTHING