qinyunti

  • 2025-04-03
  • 发表了主题帖: 【米尔-STM32MP257开发板试用体验】音频实时处理_回声消除与降噪应用评估

    前言 本文评估开发板上进行音频实时处理,移植speex算法,进行回声消除和降噪处理,主要关注算法执行时间。 移植speex Speex的移植可以参考公众号文章 https://mp.weixin.qq.com/s/zJPNgyOaKNpIbHfshe6CjQ https://mp.weixin.qq.com/s/-nRwGWvYfl6wtvFSSul1DQ https://mp.weixin.qq.com/s/p6cOppuoFYCTw6a-bu299Q 我这里分享了测试demo, https://github.com/qinyunti/speex_test.git 测试 git clone https://github.com/qinyunti/speex_test.git 编译 source /opt/st/myd-ld25x/4.2.4-snapshot/environment-setup-cortexa35-ostl-linux 修改build.sh gcc为$CC chmod +x ./build.sh ./build.sh 导入测试文件到开发板 导入程序到开发板 chmod +x speexecho ./speexecho mic3.wav spk3.wav out3.wav 可以看到执行时间大概是1.8mS 导出out3.wav查看波形 可以看到回声消除和降噪效果。 这里对比其他 某个M4F平台N=256点,TAIL=1024需要14~15mS 这里只需要1.8mS,和之前测试的fft的效率比例相当,所以算法主要执行时间就是取决于fft运算时间,当然还有很多内存搬运的时间和平台相关。   总结 以上可以看到进行16k音频的实时处理,对应时间为16mS,需要算法时间为1.8ms, 所以算法完全足够,如果按照48k采样率,数据量变为3倍,按倍数估计也只需要5.4ms, 占比16ms也很少,所以进行实时音频处理是毫无压力的。

  • 发表了主题帖: 【米尔-STM32MP257开发板试用体验】软件fft测试

    本帖最后由 qinyunti 于 2025-4-3 12:33 编辑 代码 前言 后面移植音频处理算法需要大量调用fft算法。其执行时间影响音频算法是否能实时处理,所以我们先来进行实测,评估fft执行时间。刚好前面也评测了一款H系类的M4F核的MCU,可以对比下。 移植KISSFFT Kissfft是常用的fft实现库,后面的音频算法中也会使用,所以基于该库进行测试。 需要的文件如下 qinyunti@qinyunti:/mnt/d/BaiduSyncdisk/BOARD/ld25x/kissfftt$ tree . . ├── kiss_fft_port.c ├── kiss_fft_port.h ├── kissfft │   ├── _kiss_fft_guts.h │   ├── kfc.c │   ├── kfc.h │   ├── kiss_fft.c │   ├── kiss_fft.h │   ├── kiss_fft_log.h │   ├── kiss_fftnd.c │   ├── kiss_fftnd.h │   ├── kiss_fftndr.c │   ├── kiss_fftndr.h │   ├── kiss_fftr.c │   ├── kiss_fftr.h │   └── kissfft.hh ├── kissfft_test.c └── kissfft_test.h 1 directory, 17 files 其中 kiss_fft_port.c中的kiss_fft_port_malloc和 kiss_fft_port_free使用标准库的malloc和free kiss_fft_port.c中 #include <stddef.h> #include <stdlib.h> void* kiss_fft_port_malloc(size_t size) { return malloc(size); } void kiss_fft_port_free(void* p) { free(p); } kissfft_test.c是测试代码 其中事件测量需要获取时间戳 #include <time.h> static uint64_t get_tm(void){   struct timespec ts;   clock_gettime(CLOCK_MONOTONIC,&ts);   return ts.tv_sec*1000000000ull + ts.tv_nsec; } 编译 $CC kissfft/*.c kiss_fft_port.c kissfft_test.c -I. -Ikissfft -o kissfft_test -lm 测试 导入kissfft_test到开发板 chmod +x kissfft_test 执行 ./kissfft_test 256 1000 打印如下 root@myd-ld25x:~# ./kissfft_test 256 1000 [in] (1.000000,0.000000),(1.049083,0.000000),(1.098135,0.000000),(1.147129,0.000000),(1.196034,0.000000),(1.244821,0.000000),(1.293461,0.000000),(1.341924,0.000000),(1.390181,0.000000),(1.438203,0.000000),(1.485960,0.000000),(1.533426,0.000000),(1.580569,0.000000),(1.627363,0.000000),(1.673780,0.000000),(1.719790,0.000000),(1.765367,0.000000),(1.810483,0.000000),(1.855110,0.000000),(1.899223,0.000000),(1.942793,0.000000),(1.985796,0.000000),(2.028205,0.000000),(2.069995,0.000000),(2.111140,0.000000),(2.151617,0.000000),(2.191399,0.000000),(2.230463,0.000000),(2.268787,0.000000),(2.306346,0.000000),(2.343118,0.000000),(2.379081,0.000000),(2.414214,0.000000),(2.448494,0.000000),(2.481902,0.000000),(2.514418,0.000000),(2.546021,0.000000),(2.576693,0.000000),(2.606415,0.000000),(2.635170,0.000000),(2.662939,0.000000),(2.689707,0.000000),(2.715457,0.000000),(2.740174,0.000000),(2.763843,0.000000),(2.786448,0.000000),(2.807979,0.000000),(2.828420,0.000000),(2.847759,0.000000),(2.865986,0.000000),(2.883088,0.000000),(2.899056,0.000000),(2.913881,0.000000),(2.927552,0.000000),(2.940063,0.000000),(2.951404,0.000000),(2.961571,0.000000),(2.970555,0.000000),(2.978353,0.000000),(2.984959,0.000000),(2.990369,0.000000),(2.994581,0.000000),(2.997591,0.000000),(2.999398,0.000000),(3.000000,0.000000),(2.999398,0.000000),(2.997591,0.000000),(2.994581,0.000000),(2.990369,0.000000),(2.984959,0.000000),(2.978353,0.000000),(2.970555,0.000000),(2.961571,0.000000),(2.951404,0.000000),(2.940063,0.000000),(2.927552,0.000000),(2.913881,0.000000),(2.899056,0.000000),(2.883088,0.000000),(2.865986,0.000000),(2.847759,0.000000),(2.828419,0.000000),(2.807979,0.000000),(2.786448,0.000000),(2.763843,0.000000),(2.740174,0.000000),(2.715457,0.000000),(2.689707,0.000000),(2.662939,0.000000),(2.635170,0.000000),(2.606415,0.000000),(2.576693,0.000000),(2.546021,0.000000),(2.514418,0.000000),(2.481902,0.000000),(2.448494,0.000000),(2.414214,0.000000),(2.379081,0.000000),(2.343118,0.000000),(2.306346,0.000000),(2.268786,0.000000),(2.230463,0.000000),(2.191398,0.000000),(2.151616,0.000000),(2.111140,0.000000),(2.069995,0.000000),(2.028205,0.000000),(1.985796,0.000000),(1.942793,0.000000),(1.899223,0.000000),(1.855110,0.000000),(1.810483,0.000000),(1.765367,0.000000),(1.719790,0.000000),(1.673780,0.000000),(1.627363,0.000000),(1.580570,0.000000),(1.533425,0.000000),(1.485960,0.000000),(1.438202,0.000000),(1.390181,0.000000),(1.341924,0.000000),(1.293461,0.000000),(1.244821,0.000000),(1.196034,0.000000),(1.147129,0.000000),(1.098135,0.000000),(1.049082,0.000000),(1.000000,0.000000),(0.950917,0.000000),(0.901865,0.000000),(0.852871,0.000000),(0.803965,0.000000),(0.755178,0.000000),(0.706539,0.000000),(0.658076,0.000000),(0.609819,0.000000),(0.561797,0.000000),(0.514040,0.000000),(0.466574,0.000000),(0.419430,0.000000),(0.372636,0.000000),(0.326220,0.000000),(0.280210,0.000000),(0.234633,0.000000),(0.189517,0.000000),(0.144890,0.000000),(0.100777,0.000000),(0.057206,0.000000),(0.014203,0.000000),(-0.028206,0.000000),(-0.069995,0.000000),(-0.111141,0.000000),(-0.151617,0.000000),(-0.191399,0.000000),(-0.230463,0.000000),(-0.268787,0.000000),(-0.306346,0.000000),(-0.343118,0.000000),(-0.379081,0.000000),(-0.414214,0.000000),(-0.448494,0.000000),(-0.481902,0.000000),(-0.514418,0.000000),(-0.546021,0.000000),(-0.576693,0.000000),(-0.606415,0.000000),(-0.635170,0.000000),(-0.662940,0.000000),(-0.689708,0.000000),(-0.715457,0.000000),(-0.740174,0.000000),(-0.763843,0.000000),(-0.786449,0.000000),(-0.807979,0.000000),(-0.828420,0.000000),(-0.847759,0.000000),(-0.865986,0.000000),(-0.883088,0.000000),(-0.899056,0.000000),(-0.913881,0.000000),(-0.927552,0.000000),(-0.940063,0.000000),(-0.951404,0.000000),(-0.961571,0.000000),(-0.970555,0.000000),(-0.978353,0.000000),(-0.984959,0.000000),(-0.990369,0.000000),(-0.994581,0.000000),(-0.997591,0.000000),(-0.999398,0.000000),(-1.000000,0.000000),(-0.999398,0.000000),(-0.997591,0.000000),(-0.994581,0.000000),(-0.990369,0.000000),(-0.984959,0.000000),(-0.978353,0.000000),(-0.970555,0.000000),(-0.961571,0.000000),(-0.951404,0.000000),(-0.940062,0.000000),(-0.927552,0.000000),(-0.913880,0.000000),(-0.899056,0.000000),(-0.883088,0.000000),(-0.865986,0.000000),(-0.847759,0.000000),(-0.828419,0.000000),(-0.807978,0.000000),(-0.786448,0.000000),(-0.763843,0.000000),(-0.740174,0.000000),(-0.715457,0.000000),(-0.689707,0.000000),(-0.662939,0.000000),(-0.635169,0.000000),(-0.606415,0.000000),(-0.576693,0.000000),(-0.546021,0.000000),(-0.514418,0.000000),(-0.481902,0.000000),(-0.448494,0.000000),(-0.414213,0.000000),(-0.379081,0.000000),(-0.343118,0.000000),(-0.306346,0.000000),(-0.268786,0.000000),(-0.230463,0.000000),(-0.191398,0.000000),(-0.151616,0.000000),(-0.111141,0.000000),(-0.069995,0.000000),(-0.028205,0.000000),(0.014204,0.000000),(0.057207,0.000000),(0.100778,0.000000),(0.144890,0.000000),(0.189517,0.000000),(0.234633,0.000000),(0.280210,0.000000),(0.326221,0.000000),(0.372637,0.000000),(0.419431,0.000000),(0.466575,0.000000),(0.514040,0.000000),(0.561798,0.000000),(0.609820,0.000000),(0.658077,0.000000),(0.706540,0.000000),(0.755179,0.000000),(0.803966,0.000000),(0.852871,0.000000),(0.901865,0.000000),(0.950918,0.000000), used:105119450 [FFT] (256.000000,0.000000),(0.000019,-256.000000),(-0.000000,0.000006),(0.000002,0.000007),(-0.000000,0.000003),(0.000000,0.000003),(0.000001,0.000005),(0.000000,0.000002),(-0.000001,0.000003),(-0.000002,-0.000000),(-0.000000,-0.000000),(-0.000000,0.000000),(-0.000002,0.000001),(-0.000001,0.000003),(-0.000000,0.000001),(-0.000002,0.000005),(0.000001,-0.000000),(0.000001,-0.000003),(0.000001,0.000002),(0.000001,0.000002),(-0.000001,0.000000),(-0.000001,-0.000001),(-0.000000,0.000001),(-0.000001,0.000004),(0.000000,0.000001),(-0.000002,-0.000000),(-0.000002,0.000001),(-0.000000,-0.000001),(-0.000001,0.000002),(-0.000001,-0.000000),(-0.000000,0.000002),(-0.000005,0.000003),(0.000000,0.000000),(0.000001,-0.000002),(-0.000004,-0.000001),(-0.000007,-0.000001),(-0.000002,-0.000006),(0.000001,-0.000005),(0.000001,-0.000006),(0.000006,-0.000001),(0.000004,-0.000002),(-0.000001,-0.000000),(-0.000000,0.000000),(-0.000001,0.000003),(0.000002,-0.000002),(0.000003,-0.000003),(-0.000001,0.000001),(-0.000001,0.000002),(0.000001,0.000001),(0.000001,-0.000001),(0.000002,-0.000002),(0.000004,0.000001),(-0.000001,0.000000),(-0.000002,-0.000001),(0.000000,0.000001),(-0.000001,-0.000001),(-0.000001,-0.000000),(0.000001,0.000002),(-0.000001,0.000002),(0.000000,-0.000001),(-0.000000,0.000001),(0.000000,0.000001),(0.000001,-0.000001),(0.000001,-0.000001),(0.000000,0.000000),(0.000001,-0.000001),(0.000001,0.000001),(-0.000000,-0.000002),(0.000000,0.000001),(0.000004,0.000002),(-0.000000,0.000002),(0.000002,-0.000002),(0.000000,0.000006),(-0.000001,0.000001),(-0.000000,0.000007),(0.000000,-0.000003),(-0.000003,0.000003),(-0.000003,-0.000002),(-0.000000,-0.000001),(-0.000000,0.000001),(-0.000001,-0.000000),(-0.000000,0.000005),(-0.000000,-0.000000),(0.000001,-0.000002),(-0.000001,-0.000001),(-0.000001,-0.000000),(0.000001,0.000000),(-0.000001,-0.000001),(0.000000,-0.000002),(-0.000001,0.000002),(-0.000000,0.000000),(0.000000,0.000001),(-0.000000,-0.000001),(0.000001,0.000000),(-0.000001,-0.000000),(-0.000004,-0.000004),(0.000000,0.000000),(0.000001,0.000002),(-0.000002,0.000001),(-0.000000,0.000000),(-0.000000,-0.000001),(-0.000002,0.000000),(-0.000001,-0.000000),(-0.000001,0.000003),(0.000000,-0.000001),(-0.000002,0.000001),(-0.000001,0.000000),(-0.000002,-0.000004),(-0.000001,0.000002),(-0.000001,-0.000004),(0.000001,-0.000002),(0.000004,-0.000001),(0.000002,-0.000002),(-0.000002,-0.000002),(0.000001,0.000003),(-0.000001,-0.000001),(0.000001,0.000001),(0.000001,-0.000002),(-0.000001,0.000000),(0.000002,0.000002),(0.000001,0.000000),(-0.000002,0.000002),(0.000000,0.000000),(0.000000,-0.000001),(-0.000002,-0.000001),(0.000000,-0.000001),(-0.000001,0.000001),(0.000001,0.000008),(0.000000,0.000000),(0.000001,-0.000008),(-0.000001,-0.000001),(0.000000,0.000001),(-0.000002,0.000001),(0.000000,0.000001),(0.000000,-0.000000),(-0.000002,-0.000002),(0.000001,-0.000000),(0.000002,-0.000002),(-0.000001,-0.000000),(0.000001,0.000002),(0.000001,-0.000001),(-0.000001,0.000001),(0.000001,-0.000003),(-0.000002,0.000002),(0.000002,0.000002),(0.000004,0.000001),(0.000001,0.000002),(-0.000001,0.000004),(-0.000001,-0.000002),(-0.000002,0.000004),(-0.000001,-0.000000),(-0.000002,-0.000001),(0.000000,0.000001),(-0.000001,-0.000003),(-0.000001,0.000000),(-0.000002,-0.000000),(-0.000000,0.000001),(-0.000000,-0.000000),(-0.000002,-0.000001),(0.000001,-0.000002),(0.000000,0.000000),(-0.000004,0.000004),(-0.000001,0.000000),(0.000001,-0.000000),(-0.000000,0.000001),(0.000000,-0.000001),(-0.000000,-0.000000),(-0.000001,-0.000002),(0.000000,0.000002),(-0.000001,0.000001),(0.000001,-0.000000),(-0.000001,0.000000),(-0.000001,0.000001),(0.000001,0.000002),(-0.000000,0.000000),(-0.000000,-0.000005),(-0.000001,0.000000),(-0.000000,-0.000001),(-0.000000,0.000001),(-0.000003,0.000002),(-0.000003,-0.000003),(0.000000,0.000003),(-0.000000,-0.000007),(-0.000001,-0.000001),(0.000000,-0.000006),(0.000002,0.000002),(-0.000000,-0.000002),(0.000004,-0.000002),(0.000000,-0.000001),(-0.000000,0.000002),(0.000001,-0.000001),(0.000001,0.000001),(0.000000,0.000000),(0.000001,0.000001),(0.000001,0.000001),(0.000000,-0.000001),(-0.000000,-0.000001),(0.000000,0.000001),(-0.000001,-0.000002),(0.000001,-0.000002),(-0.000001,0.000000),(-0.000001,0.000001),(0.000000,-0.000001),(-0.000002,0.000001),(-0.000001,-0.000000),(0.000004,-0.000001),(0.000002,0.000002),(0.000001,0.000001),(0.000001,-0.000001),(-0.000001,-0.000002),(-0.000001,-0.000001),(0.000003,0.000003),(0.000002,0.000002),(-0.000001,-0.000003),(-0.000000,-0.000000),(-0.000001,0.000000),(0.000004,0.000002),(0.000006,0.000001),(0.000001,0.000006),(0.000001,0.000005),(-0.000002,0.000006),(-0.000007,0.000001),(-0.000004,0.000001),(0.000001,0.000002),(0.000000,0.000000),(-0.000005,-0.000003),(-0.000000,-0.000002),(-0.000001,0.000000),(-0.000001,-0.000002),(-0.000000,0.000001),(-0.000002,-0.000001),(-0.000002,0.000000),(0.000000,-0.000001),(-0.000001,-0.000004),(-0.000000,-0.000001),(-0.000001,0.000001),(-0.000001,-0.000000),(0.000001,-0.000002),(0.000001,-0.000002),(0.000001,0.000003),(0.000001,0.000000),(-0.000002,-0.000005),(-0.000000,-0.000001),(-0.000001,-0.000003),(-0.000002,-0.000001),(-0.000000,-0.000000),(-0.000000,0.000000),(-0.000002,0.000000),(-0.000001,-0.000003),(0.000000,-0.000002),(0.000001,-0.000005),(0.000000,-0.000003),(-0.000000,-0.000003),(0.000002,-0.000007),(-0.000000,-0.000006),(0.000019,256.000000), used:97374875 [IFFT] (1.000000,0.000000),(1.049083,0.000000),(1.098135,0.000000),(1.147129,-0.000000),(1.196034,-0.000000),(1.244821,-0.000000),(1.293461,0.000000),(1.341924,0.000000),(1.390181,-0.000000),(1.438203,-0.000000),(1.485960,0.000000),(1.533426,0.000000),(1.580569,-0.000000),(1.627363,-0.000000),(1.673780,0.000000),(1.719790,0.000000),(1.765367,0.000000),(1.810483,-0.000000),(1.855110,-0.000000),(1.899223,0.000000),(1.942793,0.000000),(1.985796,-0.000000),(2.028205,0.000000),(2.069995,0.000000),(2.111140,0.000000),(2.151617,-0.000000),(2.191399,-0.000000),(2.230463,-0.000000),(2.268787,-0.000000),(2.306345,-0.000000),(2.343118,-0.000000),(2.379081,0.000000),(2.414214,0.000000),(2.448494,0.000000),(2.481902,-0.000000),(2.514418,-0.000000),(2.546021,0.000000),(2.576693,0.000000),(2.606415,-0.000000),(2.635170,0.000000),(2.662940,-0.000000),(2.689708,-0.000000),(2.715457,-0.000000),(2.740173,-0.000000),(2.763843,-0.000000),(2.786448,-0.000000),(2.807979,-0.000000),(2.828420,0.000000),(2.847759,0.000000),(2.865985,0.000000),(2.883088,-0.000000),(2.899056,-0.000000),(2.913881,0.000000),(2.927552,0.000000),(2.940063,-0.000000),(2.951404,0.000000),(2.961571,-0.000000),(2.970555,-0.000000),(2.978353,-0.000000),(2.984959,-0.000000),(2.990369,-0.000000),(2.994581,-0.000000),(2.997591,-0.000000),(2.999398,0.000000),(3.000000,0.000000),(2.999398,-0.000000),(2.997591,-0.000000),(2.994581,0.000000),(2.990369,-0.000000),(2.984959,0.000000),(2.978353,-0.000000),(2.970555,0.000000),(2.961570,-0.000000),(2.951404,-0.000000),(2.940063,-0.000000),(2.927552,-0.000000),(2.913881,0.000000),(2.899056,0.000000),(2.883088,-0.000000),(2.865986,0.000000),(2.847759,0.000000),(2.828419,-0.000000),(2.807979,-0.000000),(2.786448,0.000000),(2.763843,0.000000),(2.740174,-0.000000),(2.715457,0.000000),(2.689707,0.000000),(2.662939,0.000000),(2.635170,-0.000000),(2.606415,0.000000),(2.576692,0.000000),(2.546021,0.000000),(2.514418,0.000000),(2.481902,0.000000),(2.448494,-0.000000),(2.414214,-0.000000),(2.379081,-0.000000),(2.343118,-0.000000),(2.306346,0.000000),(2.268786,-0.000000),(2.230463,0.000000),(2.191398,-0.000000),(2.151616,0.000000),(2.111140,0.000000),(2.069995,-0.000000),(2.028205,-0.000000),(1.985796,-0.000000),(1.942793,0.000000),(1.899222,-0.000000),(1.855110,0.000000),(1.810483,-0.000000),(1.765367,0.000000),(1.719790,-0.000000),(1.673779,0.000000),(1.627363,0.000000),(1.580570,-0.000000),(1.533425,-0.000000),(1.485960,-0.000000),(1.438202,-0.000000),(1.390180,0.000000),(1.341923,0.000000),(1.293460,-0.000000),(1.244821,0.000000),(1.196034,0.000000),(1.147129,0.000000),(1.098135,-0.000000),(1.049082,-0.000000),(1.000000,0.000000),(0.950917,-0.000000),(0.901865,-0.000000),(0.852871,0.000000),(0.803965,0.000000),(0.755178,0.000000),(0.706539,0.000000),(0.658076,-0.000000),(0.609819,0.000000),(0.561798,0.000000),(0.514039,0.000000),(0.466574,-0.000000),(0.419430,-0.000000),(0.372637,0.000000),(0.326220,0.000000),(0.280210,-0.000000),(0.234633,0.000000),(0.189517,0.000000),(0.144890,-0.000000),(0.100777,0.000000),(0.057207,0.000000),(0.014204,-0.000000),(-0.028206,0.000000),(-0.069995,-0.000000),(-0.111140,-0.000000),(-0.151617,0.000000),(-0.191399,-0.000000),(-0.230463,-0.000000),(-0.268787,-0.000000),(-0.306346,-0.000000),(-0.343118,-0.000000),(-0.379081,-0.000000),(-0.414214,0.000000),(-0.448494,-0.000000),(-0.481902,-0.000000),(-0.514418,-0.000000),(-0.546021,0.000000),(-0.576693,0.000000),(-0.606415,-0.000000),(-0.635170,-0.000000),(-0.662940,0.000000),(-0.689708,0.000000),(-0.715457,0.000000),(-0.740174,-0.000000),(-0.763843,0.000000),(-0.786449,-0.000000),(-0.807979,0.000000),(-0.828420,-0.000000),(-0.847759,0.000000),(-0.865986,-0.000000),(-0.883088,0.000000),(-0.899056,0.000000),(-0.913881,-0.000000),(-0.927552,-0.000000),(-0.940063,0.000000),(-0.951404,-0.000000),(-0.961571,0.000000),(-0.970555,0.000000),(-0.978353,0.000000),(-0.984959,0.000000),(-0.990370,-0.000000),(-0.994581,0.000000),(-0.997591,0.000000),(-0.999398,-0.000000),(-1.000000,0.000000),(-0.999398,0.000000),(-0.997591,0.000000),(-0.994581,-0.000000),(-0.990369,0.000000),(-0.984959,-0.000000),(-0.978353,0.000000),(-0.970555,0.000000),(-0.961570,0.000000),(-0.951404,0.000000),(-0.940063,0.000000),(-0.927552,0.000000),(-0.913881,0.000000),(-0.899056,-0.000000),(-0.883088,0.000000),(-0.865986,0.000000),(-0.847759,0.000000),(-0.828419,0.000000),(-0.807978,0.000000),(-0.786448,-0.000000),(-0.763843,-0.000000),(-0.740174,-0.000000),(-0.715457,-0.000000),(-0.689707,0.000000),(-0.662939,0.000000),(-0.635169,-0.000000),(-0.606415,-0.000000),(-0.576693,0.000000),(-0.546021,-0.000000),(-0.514418,-0.000000),(-0.481902,-0.000000),(-0.448494,-0.000000),(-0.414213,-0.000000),(-0.379081,0.000000),(-0.343118,0.000000),(-0.306346,0.000000),(-0.268786,-0.000000),(-0.230463,0.000000),(-0.191398,-0.000000),(-0.151616,0.000000),(-0.111141,0.000000),(-0.069995,-0.000000),(-0.028205,0.000000),(0.014204,0.000000),(0.057207,0.000000),(0.100778,-0.000000),(0.144890,-0.000000),(0.189517,0.000000),(0.234633,0.000000),(0.280210,-0.000000),(0.326221,-0.000000),(0.372637,-0.000000),(0.419431,-0.000000),(0.466575,0.000000),(0.514040,-0.000000),(0.561798,-0.000000),(0.609819,0.000000),(0.658077,-0.000000),(0.706540,-0.000000),(0.755179,0.000000),(0.803966,0.000000),(0.852871,-0.000000),(0.901865,-0.000000),(0.950918,0.000000), [KISS IN] 1.000000,1.049083,1.098135,1.147129,1.196034,1.244821,1.293461,1.341924,1.390181,1.438203,1.485960,1.533426,1.580569,1.627363,1.673780,1.719790,1.765367,1.810483,1.855110,1.899223,1.942793,1.985796,2.028205,2.069995,2.111140,2.151617,2.191399,2.230463,2.268787,2.306346,2.343118,2.379081,2.414214,2.448494,2.481902,2.514418,2.546021,2.576693,2.606415,2.635170,2.662939,2.689707,2.715457,2.740174,2.763843,2.786448,2.807979,2.828420,2.847759,2.865986,2.883088,2.899056,2.913881,2.927552,2.940063,2.951404,2.961571,2.970555,2.978353,2.984959,2.990369,2.994581,2.997591,2.999398,3.000000,2.999398,2.997591,2.994581,2.990369,2.984959,2.978353,2.970555,2.961571,2.951404,2.940063,2.927552,2.913881,2.899056,2.883088,2.865986,2.847759,2.828419,2.807979,2.786448,2.763843,2.740174,2.715457,2.689707,2.662939,2.635170,2.606415,2.576693,2.546021,2.514418,2.481902,2.448494,2.414214,2.379081,2.343118,2.306346,2.268786,2.230463,2.191398,2.151616,2.111140,2.069995,2.028205,1.985796,1.942793,1.899223,1.855110,1.810483,1.765367,1.719790,1.673780,1.627363,1.580570,1.533425,1.485960,1.438202,1.390181,1.341924,1.293461,1.244821,1.196034,1.147129,1.098135,1.049082,1.000000,0.950917,0.901865,0.852871,0.803965,0.755178,0.706539,0.658076,0.609819,0.561797,0.514040,0.466574,0.419430,0.372636,0.326220,0.280210,0.234633,0.189517,0.144890,0.100777,0.057206,0.014203,-0.028206,-0.069995,-0.111141,-0.151617,-0.191399,-0.230463,-0.268787,-0.306346,-0.343118,-0.379081,-0.414214,-0.448494,-0.481902,-0.514418,-0.546021,-0.576693,-0.606415,-0.635170,-0.662940,-0.689708,-0.715457,-0.740174,-0.763843,-0.786449,-0.807979,-0.828420,-0.847759,-0.865986,-0.883088,-0.899056,-0.913881,-0.927552,-0.940063,-0.951404,-0.961571,-0.970555,-0.978353,-0.984959,-0.990369,-0.994581,-0.997591,-0.999398,-1.000000,-0.999398,-0.997591,-0.994581,-0.990369,-0.984959,-0.978353,-0.970555,-0.961571,-0.951404,-0.940062,-0.927552,-0.913880,-0.899056,-0.883088,-0.865986,-0.847759,-0.828419,-0.807978,-0.786448,-0.763843,-0.740174,-0.715457,-0.689707,-0.662939,-0.635169,-0.606415,-0.576693,-0.546021,-0.514418,-0.481902,-0.448494,-0.414213,-0.379081,-0.343118,-0.306346,-0.268786,-0.230463,-0.191398,-0.151616,-0.111141,-0.069995,-0.028205,0.014204,0.057207,0.100778,0.144890,0.189517,0.234633,0.280210,0.326221,0.372637,0.419431,0.466575,0.514040,0.561798,0.609820,0.658077,0.706540,0.755179,0.803966,0.852871,0.901865,0.950918, used:57727425 [KISS FFTR] (256.000000,0.000000),(0.000015,-255.999985),(-0.000000,0.000006),(0.000001,0.000007),(-0.000000,0.000003),(0.000002,0.000004),(0.000001,0.000005),(-0.000000,0.000001),(-0.000001,0.000003),(-0.000003,-0.000003),(-0.000000,-0.000000),(0.000001,0.000001),(-0.000002,0.000001),(-0.000000,0.000001),(-0.000000,0.000001),(-0.000001,0.000002),(0.000001,-0.000000),(-0.000001,-0.000003),(0.000001,0.000002),(0.000001,0.000001),(-0.000001,0.000000),(0.000000,-0.000001),(-0.000000,0.000001),(-0.000003,0.000005),(0.000000,0.000001),(0.000001,0.000003),(-0.000002,0.000001),(0.000004,-0.000001),(-0.000001,0.000002),(-0.000003,-0.000002),(-0.000000,0.000002),(-0.000003,-0.000001),(0.000000,0.000000),(-0.000001,-0.000008),(-0.000004,-0.000001),(-0.000005,-0.000001),(-0.000002,-0.000006),(-0.000000,-0.000005),(0.000001,-0.000006),(0.000005,-0.000002),(0.000004,-0.000002),(0.000001,0.000002),(-0.000000,0.000000),(-0.000001,0.000002),(0.000002,-0.000002),(0.000002,-0.000003),(-0.000001,0.000001),(-0.000001,0.000002),(0.000001,0.000001),(0.000002,-0.000002),(0.000002,-0.000002),(0.000003,0.000000),(-0.000001,0.000000),(-0.000001,-0.000000),(0.000000,0.000001),(-0.000000,0.000000),(-0.000001,-0.000000),(0.000001,0.000003),(-0.000001,0.000002),(-0.000000,-0.000001),(-0.000000,0.000001),(-0.000001,0.000002),(0.000001,-0.000001),(0.000008,0.000000),(0.000000,-0.000000),(-0.000004,-0.000015),(0.000001,0.000001),(-0.000000,-0.000001),(0.000000,0.000001),(0.000005,0.000002),(-0.000000,0.000002),(-0.000000,-0.000003),(0.000000,0.000006),(-0.000003,-0.000000),(-0.000000,0.000007),(-0.000001,-0.000004),(-0.000003,0.000003),(-0.000003,-0.000003),(-0.000000,-0.000001),(-0.000001,0.000000),(-0.000001,-0.000000),(-0.000001,0.000003),(-0.000000,-0.000000),(0.000000,-0.000000),(-0.000001,-0.000001),(-0.000002,0.000001),(0.000001,0.000000),(0.000001,0.000000),(0.000000,-0.000002),(-0.000001,0.000002),(-0.000000,0.000000),(0.000000,0.000003),(-0.000000,-0.000001),(0.000001,-0.000001),(-0.000001,-0.000000),(-0.000002,0.000001),(0.000000,-0.000000),(0.000003,-0.000003),(-0.000002,0.000001),(0.000001,0.000002),(-0.000000,-0.000001),(-0.000002,0.000000),(-0.000001,-0.000000),(-0.000001,0.000003),(0.000000,-0.000001),(0.000000,0.000000),(-0.000001,0.000000),(-0.000003,-0.000004),(-0.000001,0.000002),(-0.000001,-0.000005),(0.000001,-0.000002),(0.000003,-0.000002),(0.000002,-0.000002),(0.000003,-0.000002),(0.000001,0.000003),(0.000000,-0.000002),(0.000001,0.000001),(0.000003,-0.000001),(-0.000001,0.000000),(0.000002,0.000002),(0.000001,0.000000),(0.000001,0.000002),(0.000000,0.000000),(-0.000002,-0.000001),(-0.000002,-0.000001),(0.000000,-0.000001),(-0.000001,0.000001),(-0.000008,0.000000),(0.000000,0.000000), used:58225225 [KISS FFTRI] 255.999969,268.565186,281.122650,293.665039,306.184753,318.674286,331.125916,343.532471,355.886292,368.179901,380.405823,392.556885,404.625732,416.605042,428.487549,440.266174,451.933868,463.483582,474.908142,486.200928,497.355133,508.363831,519.220520,529.918701,540.451904,550.813782,560.997925,570.998535,580.809387,590.424561,599.838135,609.044678,618.038696,626.814575,635.366943,643.690857,651.781311,659.633423,667.242188,674.603333,681.712524,688.565063,695.156982,701.484375,707.543701,713.330811,718.842407,724.075378,729.026245,733.692322,738.070496,742.158325,745.953430,749.453369,752.655884,755.559448,758.161987,760.462097,762.458313,764.149475,765.534485,766.612671,767.383240,767.845764,768.000061,767.845825,767.383240,766.612610,765.534546,764.149536,762.458313,760.462097,758.161987,755.559448,752.655945,749.453308,745.953430,742.158447,738.070435,733.692261,729.026306,724.075317,718.842407,713.330811,707.543701,701.484619,695.156982,688.565002,681.712402,674.603333,667.242188,659.633240,651.781433,643.690857,635.366943,626.814453,618.038696,609.044739,599.838135,590.424438,580.809326,570.998535,560.997925,550.813843,540.451904,529.918701,519.220459,508.363800,497.355133,486.200928,474.908203,463.483582,451.933838,440.266205,428.487549,416.604980,404.625854,392.556915,380.405853,368.179779,355.886230,343.532410,331.125885,318.674316,306.184784,293.664948,281.122589,268.565155,255.999939,243.434799,230.877350,218.334961,205.815186,193.325592,180.874100,168.467499,156.113663,143.820160,131.594131,119.443008,107.374207,95.394958,83.512375,71.733780,60.066132,48.516418,37.091751,25.798996,14.644867,3.636124,-7.220596,-17.918610,-28.451874,-38.813828,-48.997955,-58.998550,-68.809402,-78.424576,-87.838135,-97.044708,-106.038696,-114.814484,-123.366913,-131.690857,-139.781311,-147.633423,-155.242157,-162.603455,-169.712494,-176.565079,-183.156921,-189.484406,-195.543671,-201.330917,-206.842438,-212.075378,-217.026337,-221.692337,-226.070511,-230.158325,-233.953430,-237.453339,-240.655884,-243.559464,-246.161987,-248.462097,-250.458313,-252.149521,-253.534592,-254.612732,-255.383240,-255.845779,-256.000061,-255.845795,-255.383240,-254.612656,-253.534607,-252.149506,-250.458313,-248.462097,-246.161987,-243.559418,-240.655945,-237.453308,-233.953430,-230.158417,-226.070480,-221.692230,-217.026306,-212.075287,-206.842346,-201.330719,-195.543671,-189.484589,-183.156982,-176.564941,-169.712372,-162.603271,-155.242188,-147.633316,-139.781448,-131.690857,-123.366913,-114.814453,-106.038574,-97.044754,-87.838150,-78.424438,-68.809326,-58.998535,-48.997925,-38.813690,-28.451935,-17.918747,-7.220551,3.636200,14.644928,25.799118,37.091919,48.516373,60.066147,71.733856,83.512451,95.395035,107.374390,119.443268,131.594086,143.820190,156.113754,168.467606,180.874115,193.325806,205.815338,218.334991,230.877350,243.434906, 256点 1000次,用时如下 复数fft 复数ifft 105119450ns 97374875ns 实数fft 实数ifft 57727425ns 58225225ns 所以一次实数fft计算大概在58uS左右。 对比上面提到的MCU平台,快了5倍以上   如果按照-O3编译 $CC kissfft/*.c kiss_fft_port.c kissfft_test.c -I. -Ikissfft -o kissfft_test -lm -O3   则 复数fft 复数ifft 19674850ns 19976350ns 实数fft 实数ifft 15674675ns 15648700ns 则一次实数fft计算大概在16uS左右,大概是不优化的1/4。 速度是上述MCU平台的17倍。

  • 发表了主题帖: 【米尔-STM32MP257开发板试用体验】基于alsa的音频应用开发

    基于alsa的音频应用开发 获取音频设备驱动信息与录放音测试 设备信息 查看音频设备信息,如下有两个 cat /proc/asound/cards 0 [ES8388SOUNDCARD]: simple-card - ES8388-SOUND-CARD ES8388-SOUND-CARD 1 [HDMISOUNDCARD ]: HDMI-SOUND-CARD - HDMI-SOUND-CARD HDMI-SOUND-CARD root@myd-ld25x:/etc/myir_test# 查看音频设备文件 ls /dev/snd/ -al total 0 drwxr-xr-x 3 root root 200 3月 3 18:10 . drwxr-xr-x 17 root root 4680 3月 3 18:10 .. drwxr-xr-x 2 root root 80 3月 3 18:10 by-path crw-rw---- 1 root audio 116, 4 3月 3 18:10 controlC0 crw-rw---- 1 root audio 116, 7 3月 3 18:10 controlC1 crw-rw---- 1 root audio 116, 3 3月 3 18:10 pcmC0D0c crw-rw---- 1 root audio 116, 2 3月 3 18:10 pcmC0D0p crw-rw---- 1 root audio 116, 6 3月 3 18:10 pcmC1D0c crw-rw---- 1 root audio 116, 5 3月 3 18:10 pcmC1D0p crw-rw---- 1 root audio 116, 33 3月 3 18:10 timer 所以声卡0对应ES8388, controlC0为ES8388声卡控制 pcmC0D0c读该文件对应ES8388声卡采集 后缀c表示capture pcmC0D0p写该文件对应ES8388声卡播放 后缀p表示playback 测试 先进行录音播放测试,确认硬件OK。 连接带MIC的耳机。 播放,确认耳机能听到音乐。 cd /etc/myir_test/ ./myir_audio_play ctrl+c退出 录音 amixer -c 0 set "Capture ZC" on amixer -c 0 set "Capture Digital" 120 arecord -D hw:0,0 -f cd test.wav Ctrl+c停止录音 aplay -D hw:0,0 test.wav 声卡读写 使用alsa库,参考 https://www.alsa-project.org/alsa-doc/alsa-lib/index.html 查看sdk中asoundlib.h头文件位置 qinyunti@qinyunti:~$ find /opt/st/myd-ld25x/4.2.4-snapshot/ -name asoundlib.h find: ‘/opt/st/myd-ld25x/4.2.4-snapshot/sysroots/cortexa35-ostl-linux/etc/polkit-1/rules.d’: Permission denied find: ‘/opt/st/myd-ld25x/4.2.4-snapshot/sysroots/cortexa35-ostl-linux/etc/cups/ssl’: Permission denied find: ‘/opt/st/myd-ld25x/4.2.4-snapshot/sysroots/cortexa35-ostl-linux/var/spool/cups’: Permission denied find: ‘/opt/st/myd-ld25x/4.2.4-snapshot/sysroots/cortexa35-ostl-linux/var/cache/cups’: Permission denied find: ‘/opt/st/myd-ld25x/4.2.4-snapshot/sysroots/cortexa35-ostl-linux/var/lib/tee’: Permission denied find: ‘/opt/st/myd-ld25x/4.2.4-snapshot/sysroots/cortexa35-ostl-linux/var/lib/sudo’: Permission denied find: ‘/opt/st/myd-ld25x/4.2.4-snapshot/sysroots/cortexa35-ostl-linux/home/root’: Permission denied find: ‘/opt/st/myd-ld25x/4.2.4-snapshot/sysroots/cortexa35-ostl-linux/usr/share/polkit-1/rules.d’: Permission denied /opt/st/myd-ld25x/4.2.4-snapshot/sysroots/cortexa35-ostl-linux/usr/include/alsa/asoundlib.h /opt/st/myd-ld25x/4.2.4-snapshot/sysroots/cortexa35-ostl-linux/usr/include/asoundlib.h /opt/st/myd-ld25x/4.2.4-snapshot/sysroots/cortexa35-ostl-linux/usr/include/sys/asoundlib.h qinyunti@qinyunti:~$ 查看板子上lib文件的位置 root@myd-ld25x:/etc/myir_test# find / -name libasound.so.* /usr/lib/libasound.so.2 /usr/lib/libasound.so.2.0.0 root@myd-ld25x:/etc/myir_test# Alsa应用程序开发 新建alsa_test.c文件,内容如下 /* * This extra small demo sends a random samples to your speakers. */ #include <alsa/asoundlib.h> static char *device = "default"; /* playback device */ unsigned char buffer[16*1024]; /* some random data */ int main(void) { int err; unsigned int i; snd_pcm_t *handle; snd_pcm_sframes_t frames; for (i = 0; i < sizeof(buffer); i++) buffer[i] = random() & 0xff; if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { printf("Playback open error: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } if ((err = snd_pcm_set_params(handle, SND_PCM_FORMAT_U8, SND_PCM_ACCESS_RW_INTERLEAVED, 1, 48000, 1, 500000)) < 0) { /* 0.5sec */ printf("Playback open error: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } for (i = 0; i < 16; i++) { frames = snd_pcm_writei(handle, buffer, sizeof(buffer)); if (frames < 0) frames = snd_pcm_recover(handle, frames, 0); if (frames < 0) { printf("snd_pcm_writei failed: %s\n", snd_strerror(frames)); break; } if (frames > 0 && frames < (long)sizeof(buffer)) printf("Short write (expected %li, wrote %li)\n", (long)sizeof(buffer), frames); } /* pass the remaining samples, otherwise they're dropped in close */ err = snd_pcm_drain(handle); if (err < 0) printf("snd_pcm_drain failed: %s\n", snd_strerror(err)); snd_pcm_close(handle); return 0; }   编译 $CC alsa_test.c -o alsa_test -lasound Cp到win下 cp alsa_test /mnt/d/ Win下使用crt,rz导入到开发板 chmod +x alsa_test ./alsa_test 运行 此时耳机播放的是噪声,随机数。 总结 得益于官方提供了完整的SDK开发环境,以及板子极影部署了alsa,所以基于alsa进行音频开发变得很简单,这一篇先进行了简单的开发过程体验,后面来实现音频的采集与播放,为后面的音频试试处理算法应用demo做准备。

  • 发表了主题帖: 【米尔-STM32MP257开发板试用体验】C应用开发环境搭建

    本帖最后由 qinyunti 于 2025-4-3 11:03 编辑 准备 供电,Type-C USB供电 Boot模式选择EMMC B3 B2 B1 B0 0010 连接串口 使用串口终端连接 115200--8-n-1 输入root登录   一.应用编译环境 我这里使用WSL+Ubuntu 下载的03-Tools.zip下解压Compile Toolchain/myir-image-full-openstlinux-weston-myd-ld25x-x86_64-toolchain-4.2.4-snapshot.sh ./myir-image-full-openstlinux-weston-myd-ld25x-x86_64-toolchain-4.2.4-snapshot.sh 指定路径回车默认 输入y 每次使用初始化环境 source /opt/st/myd-ld25x/4.2.4-snapshot/environment-setup-cortexa35-ostl-linux 查看 $CC和$XCC qinyunti@qinyunti:~$ echo $CC aarch64-ostl-linux-gcc -mcpu=cortex-a35 -march=armv8-a+crc -mbranch-protection=standard --sysroot=/opt/st/myd-ld25x/4.2.4-snapshot/sysroots/cortexa35-ostl-linux qinyunti@qinyunti:~$ echo $CXX aarch64-ostl-linux-g++ -mcpu=cortex-a35 -march=armv8-a+crc -mbranch-protection=standard --sysroot=/opt/st/myd-ld25x/4.2.4-snapshot/sysroots/cortexa35-ostl-linux qinyunti@qinyunti:~$ 二.HelloWorld mkdir ld25x cd ld25x/ nano helloworld.c 输入 #include <stdio.h> int main(void){ printf("Hello World\r\n"); return 0; } ctrl+o回车保存 ctrl+x退出 编译 $CC helloworld.c -o helloworld 导出到win下 cp helloworld /mnt/d Win下使用crt登录终端 rz导入helloworld文件 chmod +x helloworld 运行 三.总结 以上简单分享下交叉编译环境搭建,与c程序编译执行测试。为后面开发做准备。  

  • 2025-04-01
  • 回复了主题帖: 【国民技术高性能MCU N32H487开发板】软件fft性能测试

    秦天qintian0303 发表于 2025-4-1 11:55 H4的主频是多大?    240MHz

  • 发表了主题帖: 【国民技术高性能MCU N32H487开发板】音频实时处理应用_回声消除与降噪

    前言 前面我们准备好了环境,移植好了文件系统,方便进行文件的导入导出以及操作。现在就来评估基于N32H487的音频实时处理应用。目前还未搭建好音频的采集与播放通道,所以暂时通过文件系统的wav音频文件作为输入输出,重点验证音频处理算法的执行时间,是否能满足实时处理要求。 代码见:https://github.com/qinyunti/N32H487.git Speex移植 Speex的移植可以参考公众号文章 https://mp.weixin.qq.com/s/zJPNgyOaKNpIbHfshe6CjQ https://mp.weixin.qq.com/s/-nRwGWvYfl6wtvFSSul1DQ https://mp.weixin.qq.com/s/p6cOppuoFYCTw6a-bu299Q 代码如下 添加头文件包含路径 定义宏 HAVE_CONFIG_H os_support_custom.h中实现malloc,free和打印接口 math_approx.h中实现math函数 测试 这里准备了两个wav文件spk.wav表示回采的远程音频数据,mic.wav是本地采集的mic音频数据(包含了本地声音和远程说话声)。 测试代码见 speexecho.c shell_func.c中添加命令行 static void speexfunc(uint8_t* param); { (uint8_t*)"speex", speexfunc, (uint8_t*)"speex mic spk out"}, extern int speex_main(int argc, char **argv); void speexfunc(uint8_t* param) { char* cmd = "speex"; char mic[32]; char spk[32]; char out[32]; char* argv[4]={cmd,mic,spk,out}; if(3 == sscanf((const char*)param, "%*s %s %s %s", mic, spk, out)) { xprintf("speex %s %s %S\r\n",mic, spk, out); speex_main(4, argv); } } 导入mic.wav spk.wav 堆先设置大一点,后面再去确认消耗量 执行 speex 0:/mic.wav 0:/spk.wav 0:/out.wav NN=256 TAIL=1024 最大执行时间为15mS左右。 生成out.wav如下 导出out.wav 查看输出的文件,可以看到降噪效果明显,回声消除效果有不是很好,因为输入文件的质量不是很好,spk没有处于线性范围,需要调整spk和mic的音量范围最好相当,并且要保证同步性。 再测量其他配置 config.h中 //#define FIXED_POINT #define FLOATING_POINT 修改使用浮点还是固定点 浮点/定点 NN TAIL 时间 浮点 256 1024 14~15mS 256 512 12~13mS 128 1024 8~9ms 128 512 7~8mS 定点 256 1024 14~15mS 256 512 12~13mS 128 1024 8~9mS 128 512 7~8mS 对于16k,256个点,时间为16ms,算法时间需要15ms,所以基本满足不了 确认堆消耗量 参考 os_support_custom.c记录malloc和free的数量,确定最大消耗量 执行完后打印消耗堆信息   uint32_t curused; uint32_t maxused; speex_heap_info(&curused, &maxused); xprintf("heap used max:%d cur:%d\r\n",maxused,curused); NN TAIL 最大堆使用 256 1024 73090 256 512 64894 128 1024 45962 128 512 37762 总结 N32H487有RAM192KB,在典型应用256点,滤波时间1024点时消耗73090B.对于SPK,MIC采集同步的,TAIL无需1024点,512点就足够此时RAM只需要,要减小RAM使用还可以一次处理点数NN减少,根据实际减小TAIL。 对于8k采样,256点时间为32mS,算法需要的执行时间14~15ms,占50%不到,还有一半以上时间可以处理其他业务,所以可以实现实时处理。 以上测试结果看出,得益于较高的性能和资源,在N32H487上也可以实现音频的实时处理。

  • 2025-03-31
  • 发表了主题帖: 【国民技术高性能MCU N32H487开发板】软件fft性能测试

    前言 后面移植音频处理算法需要大量调用fft算法,由于没有硬件fft模块,只能使用软件进行计算。其执行时间影响音频算法是否能实时处理,所以我们先来进行实测,评估fft执行时间。 代码见 https://github.com/qinyunti/N32H487.git 移植kissfft Kissfft是常用的fft实现库,后面的音频算法中也会使用,所以基于该库进行测试。 添加代码,并设置对应的头文件包含路径 需要实现 kiss_fft_port.c中的kiss_fft_port_malloc和 kiss_fft_port_free 这里使用库自带的malloc和free,配置startup_n32h487.s中 Heap_Size EQU 0x00000200大一点为 Heap_Size EQU 0x00004000 kiss_fft_port.c中 #include <stddef.h> #include <stdlib.h> void* kiss_fft_port_malloc(size_t size) { return malloc(size); } void kiss_fft_port_free(void* p) { free(p); } 测试 shell_func.c中添加命令 #include "kissfft_test.h" static void ffttestfunc(uint8_t* param); { (uint8_t*)"ffttest", ffttestfunc, (uint8_t*)"ffttest nfft cnt"}, void ffttestfunc(uint8_t* param) { int cnt; int nfft; if(2 == sscanf((const char*)param, "%*s %d %d", &nfft, &cnt)) { kiss_fft_test_cpx(nfft, cnt); kiss_fft_test_real(nfft, cnt); } } 输入ffttest 256 1000回车 打印如下 [in] (1.000000,0.000000),(1.049083,0.000000),(1.098135,0.000000),(1.147129,0.000000),(1.196034,0.000000),(1.244821,0.000000),(1.293461,0.000000),(1.341924,0.000000),(1.390181,0.000000),(1.438203,0.000000),(1.485960,0.000000),(1.533426,0.000000),(1.580569,0.000000),(1.627363,0.000000),(1.673780,0.000000),(1.719790,0.000000),(1.765367,0.000000),(1.810483,0.000000),(1.855110,0.000000),(1.899223,0.000000),(1.942793,0.000000),(1.985796,0.000000),(2.028205,0.000000),(2.069995,0.000000),(2.111140,0.000000),(2.151616,0.000000),(2.191399,0.000000),(2.230463,0.000000),(2.268787,0.000000),(2.306346,0.000000),(2.343118,0.000000),(2.379081,0.000000),(2.414214,0.000000),(2.448494,0.000000),(2.481902,0.000000),(2.514418,0.000000),(2.546021,0.000000),(2.576693,0.000000),(2.606415,0.000000),(2.635170,0.000000),(2.662939,0.000000),(2.689707,0.000000),(2.715457,0.000000),(2.740174,0.000000),(2.763843,0.000000),(2.786448,0.000000),(2.807979,0.000000),(2.828420,0.000000),(2.847759,0.000000),(2.865986,0.000000),(2.883088,0.000000),(2.899056,0.000000),(2.913881,0.000000),(2.927552,0.000000),(2.940063,0.000000),(2.951404,0.000000),(2.961571,0.000000),(2.970555,0.000000),(2.978353,0.000000),(2.984959,0.000000),(2.990369,0.000000),(2.994581,0.000000),(2.997591,0.000000),(2.999398,0.000000),(3.000000,0.000000),(2.999398,0.000000),(2.997591,0.000000),(2.994581,0.000000),(2.990369,0.000000),(2.984959,0.000000),(2.978353,0.000000),(2.970555,0.000000),(2.961571,0.000000),(2.951404,0.000000),(2.940063,0.000000),(2.927552,0.000000),(2.913881,0.000000),(2.899056,0.000000),(2.883088,0.000000),(2.865986,0.000000),(2.847759,0.000000),(2.828419,0.000000),(2.807979,0.000000),(2.786448,0.000000),(2.763842,0.000000),(2.740174,0.000000),(2.715457,0.000000),(2.689707,0.000000),(2.662939,0.000000),(2.635170,0.000000),(2.606415,0.000000),(2.576693,0.000000),(2.546021,0.000000),(2.514418,0.000000),(2.481902,0.000000),(2.448494,0.000000),(2.414214,0.000000),(2.379081,0.000000),(2.343118,0.000000),(2.306346,0.000000),(2.268786,0.000000),(2.230463,0.000000),(2.191398,0.000000),(2.151616,0.000000),(2.111140,0.000000),(2.069995,0.000000),(2.028205,0.000000),(1.985796,0.000000),(1.942793,0.000000),(1.899223,0.000000),(1.855110,0.000000),(1.810483,0.000000),(1.765367,0.000000),(1.719790,0.000000),(1.673780,0.000000),(1.627363,0.000000),(1.580569,0.000000),(1.533425,0.000000),(1.485960,0.000000),(1.438202,0.000000),(1.390181,0.000000),(1.341924,0.000000),(1.293461,0.000000),(1.244821,0.000000),(1.196034,0.000000),(1.147129,0.000000),(1.098135,0.000000),(1.049082,0.000000),(1.000000,0.000000),(0.950917,0.000000),(0.901865,0.000000),(0.852871,0.000000),(0.803965,0.000000),(0.755178,0.000000),(0.706539,0.000000),(0.658076,0.000000),(0.609819,0.000000),(0.561797,0.000000),(0.514040,0.000000),(0.466574,0.000000),(0.419430,0.000000),(0.372636,0.000000),(0.326220,0.000000),(0.280210,0.000000),(0.234633,0.000000),(0.189517,0.000000),(0.144890,0.000000),(0.100777,0.000000),(0.057206,0.000000),(0.014203,0.000000),(-0.028206,0.000000),(-0.069995,0.000000),(-0.111141,0.000000),(-0.151617,0.000000),(-0.191399,0.000000),(-0.230463,0.000000),(-0.268787,0.000000),(-0.306346,0.000000),(-0.343118,0.000000),(-0.379081,0.000000),(-0.414214,0.000000),(-0.448494,0.000000),(-0.481902,0.000000),(-0.514418,0.000000),(-0.546021,0.000000),(-0.576693,0.000000),(-0.606415,0.000000),(-0.635170,0.000000),(-0.662939,0.000000),(-0.689707,0.000000),(-0.715457,0.000000),(-0.740174,0.000000),(-0.763842,0.000000),(-0.786449,0.000000),(-0.807979,0.000000),(-0.828420,0.000000),(-0.847759,0.000000),(-0.865986,0.000000),(-0.883088,0.000000),(-0.899056,0.000000),(-0.913881,0.000000),(-0.927552,0.000000),(-0.940063,0.000000),(-0.951404,0.000000),(-0.961571,0.000000),(-0.970555,0.000000),(-0.978353,0.000000),(-0.984959,0.000000),(-0.990370,0.000000),(-0.994581,0.000000),(-0.997591,0.000000),(-0.999398,0.000000),(-1.000000,0.000000),(-0.999398,0.000000),(-0.997591,0.000000),(-0.994581,0.000000),(-0.990369,0.000000),(-0.984959,0.000000),(-0.978353,0.000000),(-0.970555,0.000000),(-0.961571,0.000000),(-0.951404,0.000000),(-0.940062,0.000000),(-0.927552,0.000000),(-0.913881,0.000000),(-0.899056,0.000000),(-0.883088,0.000000),(-0.865986,0.000000),(-0.847759,0.000000),(-0.828419,0.000000),(-0.807978,0.000000),(-0.786448,0.000000),(-0.763842,0.000000),(-0.740174,0.000000),(-0.715457,0.000000),(-0.689707,0.000000),(-0.662939,0.000000),(-0.635169,0.000000),(-0.606415,0.000000),(-0.576693,0.000000),(-0.546021,0.000000),(-0.514418,0.000000),(-0.481902,0.000000),(-0.448494,0.000000),(-0.414213,0.000000),(-0.379081,0.000000),(-0.343118,0.000000),(-0.306346,0.000000),(-0.268786,0.000000),(-0.230463,0.000000),(-0.191398,0.000000),(-0.151616,0.000000),(-0.111141,0.000000),(-0.069995,0.000000),(-0.028205,0.000000),(0.014204,0.000000),(0.057207,0.000000),(0.100778,0.000000),(0.144890,0.000000),(0.189517,0.000000),(0.234633,0.000000),(0.280210,0.000000),(0.326221,0.000000),(0.372637,0.000000),(0.419431,0.000000),(0.466575,0.000000),(0.514040,0.000000),(0.561798,0.000000),(0.609820,0.000000),(0.658077,0.000000),(0.706540,0.000000),(0.755179,0.000000),(0.803966,0.000000),(0.852871,0.000000),(0.901865,0.000000),(0.950918,0.000000), used:424 [FFT] (256.000000,0.000000),(0.000019,-255.999985),(0.000000,0.000007),(0.000001,0.000009),(0.000001,0.000002),(0.000001,-0.000001),(-0.000001,0.000005),(0.000001,0.000005),(0.000000,0.000001),(-0.000004,0.000001),(0.000001,-0.000001),(0.000000,-0.000004),(-0.000002,0.000002),(0.000000,0.000006),(-0.000000,0.000001),(-0.000003,0.000005),(0.000002,0.000001),(0.000004,-0.000005),(-0.000001,0.000000),(0.000000,0.000002),(-0.000001,0.000002),(-0.000001,-0.000001),(0.000000,0.000001),(-0.000001,0.000002),(-0.000001,0.000000),(-0.000000,0.000000),(-0.000002,0.000001),(-0.000002,0.000001),(-0.000001,0.000001),(-0.000000,-0.000002),(-0.000001,0.000001),(-0.000005,0.000001),(0.000000,0.000000),(-0.000001,0.000001),(-0.000004,-0.000001),(-0.000005,-0.000002),(-0.000002,-0.000005),(0.000002,-0.000004),(0.000002,-0.000007),(0.000006,-0.000001),(0.000003,0.000000),(-0.000001,0.000001),(-0.000001,-0.000000),(0.000001,0.000001),(0.000002,-0.000002),(0.000002,-0.000001),(0.000000,0.000001),(-0.000001,0.000000),(0.000000,0.000001),(0.000002,0.000000),(0.000002,-0.000001),(0.000002,0.000000),(-0.000001,0.000000),(-0.000002,-0.000001),(-0.000001,0.000000),(-0.000000,-0.000000),(-0.000000,-0.000000),(0.000001,0.000001),(0.000001,0.000002),(-0.000001,0.000000),(-0.000001,0.000001),(-0.000000,-0.000001),(0.000000,-0.000001),(0.000006,0.000000),(0.000000,0.000000),(-0.000002,0.000000),(0.000001,0.000001),(0.000001,-0.000001),(-0.000001,-0.000000),(0.000003,0.000001),(0.000000,0.000002),(0.000002,-0.000002),(0.000000,0.000005),(-0.000002,0.000002),(-0.000000,0.000008),(0.000002,-0.000004),(-0.000002,0.000003),(-0.000002,-0.000001),(0.000001,-0.000001),(-0.000003,0.000000),(0.000000,-0.000001),(0.000001,0.000003),(-0.000001,-0.000000),(0.000000,-0.000002),(-0.000000,-0.000001),(-0.000000,-0.000000),(-0.000001,0.000001),(-0.000001,-0.000000),(-0.000000,-0.000002),(-0.000001,0.000001),(-0.000001,-0.000001),(-0.000000,0.000000),(-0.000000,-0.000001),(0.000001,-0.000000),(-0.000001,-0.000001),(0.000001,0.000000),(0.000000,0.000000),(-0.000003,0.000000),(-0.000000,0.000001),(-0.000000,-0.000000),(0.000000,-0.000000),(-0.000001,0.000000),(-0.000001,-0.000000),(-0.000001,0.000003),(0.000001,0.000000),(-0.000001,0.000001),(-0.000002,0.000000),(-0.000003,-0.000003),(-0.000002,0.000001),(-0.000001,-0.000004),(0.000000,-0.000002),(0.000001,-0.000005),(0.000002,-0.000001),(0.000001,0.000001),(0.000001,0.000002),(0.000000,-0.000001),(-0.000000,0.000000),(0.000000,-0.000001),(0.000000,-0.000001),(0.000002,0.000001),(0.000000,0.000001),(-0.000002,0.000001),(0.000001,0.000000),(0.000001,-0.000000),(-0.000001,-0.000000),(-0.000000,-0.000000),(-0.000001,0.000000),(0.000000,0.000015),(0.000000,0.000000),(0.000000,-0.000015),(-0.000001,-0.000000),(-0.000000,0.000000),(-0.000001,0.000000),(0.000001,0.000000),(0.000001,-0.000000),(-0.000002,-0.000001),(0.000000,-0.000001),(0.000002,-0.000001),(0.000000,0.000001),(0.000000,0.000001),(-0.000000,-0.000000),(0.000000,0.000001),(0.000001,-0.000002),(0.000001,-0.000001),(0.000002,0.000001),(0.000001,0.000005),(0.000000,0.000002),(-0.000001,0.000004),(-0.000002,-0.000001),(-0.000003,0.000003),(-0.000002,-0.000000),(-0.000001,-0.000001),(0.000001,-0.000000),(-0.000001,-0.000003),(-0.000001,0.000000),(-0.000001,-0.000000),(0.000000,0.000000),(-0.000000,0.000000),(-0.000000,-0.000001),(-0.000003,-0.000000),(0.000000,0.000000),(0.000001,-0.000000),(-0.000001,0.000001),(0.000001,0.000000),(-0.000000,0.000001),(-0.000000,-0.000000),(-0.000001,0.000001),(-0.000001,-0.000001),(-0.000000,0.000002),(-0.000001,0.000000),(-0.000001,-0.000001),(-0.000000,0.000000),(-0.000000,0.000001),(0.000000,0.000002),(-0.000001,0.000000),(0.000001,-0.000003),(0.000000,0.000001),(-0.000003,-0.000000),(0.000001,0.000001),(-0.000002,0.000001),(-0.000002,-0.000003),(0.000002,0.000004),(-0.000000,-0.000008),(-0.000002,-0.000002),(0.000000,-0.000005),(0.000002,0.000002),(0.000000,-0.000002),(0.000003,-0.000001),(-0.000001,0.000000),(0.000001,0.000001),(0.000001,-0.000001),(-0.000002,-0.000000),(0.000000,0.000000),(0.000006,-0.000000),(0.000000,0.000001),(-0.000000,0.000001),(-0.000001,-0.000001),(-0.000001,-0.000000),(0.000001,-0.000002),(0.000001,-0.000001),(-0.000000,0.000000),(-0.000000,0.000000),(-0.000001,-0.000000),(-0.000002,0.000001),(-0.000001,-0.000000),(0.000002,-0.000000),(0.000002,0.000001),(0.000002,-0.000000),(0.000000,-0.000001),(-0.000001,-0.000000),(0.000000,-0.000001),(0.000002,0.000001),(0.000002,0.000002),(0.000001,-0.000001),(-0.000001,0.000000),(-0.000001,-0.000001),(0.000003,-0.000000),(0.000006,0.000001),(0.000002,0.000007),(0.000002,0.000004),(-0.000002,0.000005),(-0.000005,0.000002),(-0.000004,0.000001),(-0.000001,-0.000001),(0.000000,0.000000),(-0.000005,-0.000001),(-0.000001,-0.000001),(-0.000000,0.000002),(-0.000001,-0.000001),(-0.000002,-0.000001),(-0.000002,-0.000001),(-0.000000,-0.000000),(-0.000001,-0.000000),(-0.000001,-0.000002),(0.000000,-0.000001),(-0.000001,0.000001),(-0.000001,-0.000002),(0.000000,-0.000002),(-0.000001,-0.000000),(0.000004,0.000005),(0.000002,-0.000001),(-0.000003,-0.000005),(-0.000000,-0.000001),(0.000000,-0.000006),(-0.000002,-0.000002),(0.000000,0.000004),(0.000001,0.000001),(-0.000004,-0.000001),(0.000000,-0.000001),(0.000001,-0.000005),(-0.000001,-0.000005),(0.000001,0.000001),(0.000001,-0.000002),(0.000001,-0.000009),(0.000000,-0.000007),(0.000019,255.999985), used:419 [IFFT] (1.000000,0.000000),(1.049083,-0.000000),(1.098135,0.000000),(1.147129,0.000000),(1.196034,-0.000000),(1.244821,0.000000),(1.293461,0.000000),(1.341924,-0.000000),(1.390181,-0.000000),(1.438202,-0.000000),(1.485960,0.000000),(1.533426,-0.000000),(1.580570,0.000000),(1.627363,-0.000000),(1.673780,0.000000),(1.719790,-0.000000),(1.765367,0.000000),(1.810483,-0.000000),(1.855110,0.000000),(1.899222,0.000000),(1.942793,-0.000000),(1.985796,-0.000000),(2.028205,-0.000000),(2.069995,0.000000),(2.111140,0.000000),(2.151616,-0.000000),(2.191399,0.000000),(2.230463,0.000000),(2.268787,0.000000),(2.306345,0.000000),(2.343118,0.000000),(2.379081,-0.000000),(2.414214,0.000000),(2.448494,-0.000000),(2.481902,-0.000000),(2.514418,0.000000),(2.546021,-0.000000),(2.576693,0.000000),(2.606415,0.000000),(2.635169,-0.000000),(2.662939,-0.000000),(2.689707,0.000000),(2.715457,-0.000000),(2.740173,-0.000000),(2.763843,-0.000000),(2.786448,0.000000),(2.807979,-0.000000),(2.828419,-0.000000),(2.847759,0.000000),(2.865985,0.000000),(2.883088,0.000000),(2.899056,-0.000000),(2.913881,0.000000),(2.927552,0.000000),(2.940063,-0.000000),(2.951404,0.000000),(2.961571,-0.000000),(2.970555,-0.000000),(2.978353,-0.000000),(2.984959,0.000000),(2.990369,0.000000),(2.994581,0.000000),(2.997591,-0.000000),(2.999398,0.000000),(3.000000,0.000000),(2.999398,0.000000),(2.997591,-0.000000),(2.994581,0.000000),(2.990369,-0.000000),(2.984959,0.000000),(2.978353,-0.000000),(2.970555,0.000000),(2.961571,0.000000),(2.951404,-0.000000),(2.940063,-0.000000),(2.927552,-0.000000),(2.913881,-0.000000),(2.899056,0.000000),(2.883088,-0.000000),(2.865985,0.000000),(2.847759,0.000000),(2.828419,0.000000),(2.807979,-0.000000),(2.786448,0.000000),(2.763842,0.000000),(2.740174,0.000000),(2.715457,-0.000000),(2.689707,0.000000),(2.662939,-0.000000),(2.635169,-0.000000),(2.606415,0.000000),(2.576692,-0.000000),(2.546021,0.000000),(2.514417,0.000000),(2.481902,-0.000000),(2.448494,0.000000),(2.414214,-0.000000),(2.379081,0.000000),(2.343118,-0.000000),(2.306346,-0.000000),(2.268786,-0.000000),(2.230463,-0.000000),(2.191399,-0.000000),(2.151616,0.000000),(2.111140,-0.000000),(2.069995,-0.000000),(2.028205,-0.000000),(1.985796,-0.000000),(1.942793,0.000000),(1.899222,-0.000000),(1.855110,-0.000000),(1.810483,0.000000),(1.765367,0.000000),(1.719790,-0.000000),(1.673779,0.000000),(1.627363,0.000000),(1.580569,0.000000),(1.533425,-0.000000),(1.485960,0.000000),(1.438202,-0.000000),(1.390180,-0.000000),(1.341923,0.000000),(1.293460,-0.000000),(1.244821,-0.000000),(1.196034,-0.000000),(1.147129,0.000000),(1.098135,-0.000000),(1.049082,0.000000),(1.000000,0.000000),(0.950917,-0.000000),(0.901865,-0.000000),(0.852871,0.000000),(0.803965,0.000000),(0.755178,0.000000),(0.706539,-0.000000),(0.658076,0.000000),(0.609819,-0.000000),(0.561798,-0.000000),(0.514039,0.000000),(0.466574,0.000000),(0.419430,-0.000000),(0.372637,-0.000000),(0.326220,-0.000000),(0.280210,0.000000),(0.234633,0.000000),(0.189517,-0.000000),(0.144890,-0.000000),(0.100777,-0.000000),(0.057207,0.000000),(0.014204,0.000000),(-0.028206,0.000000),(-0.069995,-0.000000),(-0.111141,0.000000),(-0.151616,0.000000),(-0.191399,-0.000000),(-0.230463,-0.000000),(-0.268787,-0.000000),(-0.306346,-0.000000),(-0.343118,0.000000),(-0.379081,0.000000),(-0.414214,0.000000),(-0.448494,-0.000000),(-0.481902,-0.000000),(-0.514418,-0.000000),(-0.546021,0.000000),(-0.576693,-0.000000),(-0.606415,-0.000000),(-0.635169,0.000000),(-0.662939,-0.000000),(-0.689707,0.000000),(-0.715457,0.000000),(-0.740174,-0.000000),(-0.763843,0.000000),(-0.786449,-0.000000),(-0.807979,0.000000),(-0.828419,-0.000000),(-0.847759,0.000000),(-0.865985,-0.000000),(-0.883088,0.000000),(-0.899056,0.000000),(-0.913881,-0.000000),(-0.927552,-0.000000),(-0.940063,0.000000),(-0.951404,-0.000000),(-0.961571,0.000000),(-0.970555,0.000000),(-0.978353,0.000000),(-0.984959,0.000000),(-0.990370,-0.000000),(-0.994581,-0.000000),(-0.997591,0.000000),(-0.999398,-0.000000),(-1.000000,0.000000),(-0.999398,-0.000000),(-0.997591,0.000000),(-0.994581,-0.000000),(-0.990369,0.000000),(-0.984959,-0.000000),(-0.978353,0.000000),(-0.970555,-0.000000),(-0.961571,0.000000),(-0.951404,0.000000),(-0.940063,0.000000),(-0.927552,0.000000),(-0.913880,0.000000),(-0.899056,-0.000000),(-0.883088,0.000000),(-0.865985,-0.000000),(-0.847759,0.000000),(-0.828419,0.000000),(-0.807978,0.000000),(-0.786448,-0.000000),(-0.763842,-0.000000),(-0.740174,-0.000000),(-0.715457,-0.000000),(-0.689707,-0.000000),(-0.662939,-0.000000),(-0.635169,-0.000000),(-0.606415,0.000000),(-0.576693,-0.000000),(-0.546021,0.000000),(-0.514417,-0.000000),(-0.481902,0.000000),(-0.448494,-0.000000),(-0.414213,-0.000000),(-0.379081,0.000000),(-0.343118,0.000000),(-0.306346,0.000000),(-0.268786,-0.000000),(-0.230463,0.000000),(-0.191398,0.000000),(-0.151616,-0.000000),(-0.111140,0.000000),(-0.069995,-0.000000),(-0.028205,0.000000),(0.014204,-0.000000),(0.057207,0.000000),(0.100778,0.000000),(0.144890,0.000000),(0.189517,-0.000000),(0.234633,0.000000),(0.280210,0.000000),(0.326221,-0.000000),(0.372637,-0.000000),(0.419431,-0.000000),(0.466575,-0.000000),(0.514040,-0.000000),(0.561798,0.000000),(0.609820,0.000000),(0.658077,-0.000000),(0.706540,0.000000),(0.755179,-0.000000),(0.803966,0.000000),(0.852871,0.000000),(0.901865,0.000000),(0.950918,-0.000000), [KISS IN] 1.000000,1.049083,1.098135,1.147129,1.196034,1.244821,1.293461,1.341924,1.390181,1.438203,1.485960,1.533426,1.580569,1.627363,1.673780,1.719790,1.765367,1.810483,1.855110,1.899223,1.942793,1.985796,2.028205,2.069995,2.111140,2.151616,2.191399,2.230463,2.268787,2.306346,2.343118,2.379081,2.414214,2.448494,2.481902,2.514418,2.546021,2.576693,2.606415,2.635170,2.662939,2.689707,2.715457,2.740174,2.763843,2.786448,2.807979,2.828420,2.847759,2.865986,2.883088,2.899056,2.913881,2.927552,2.940063,2.951404,2.961571,2.970555,2.978353,2.984959,2.990369,2.994581,2.997591,2.999398,3.000000,2.999398,2.997591,2.994581,2.990369,2.984959,2.978353,2.970555,2.961571,2.951404,2.940063,2.927552,2.913881,2.899056,2.883088,2.865986,2.847759,2.828419,2.807979,2.786448,2.763842,2.740174,2.715457,2.689707,2.662939,2.635170,2.606415,2.576693,2.546021,2.514418,2.481902,2.448494,2.414214,2.379081,2.343118,2.306346,2.268786,2.230463,2.191398,2.151616,2.111140,2.069995,2.028205,1.985796,1.942793,1.899223,1.855110,1.810483,1.765367,1.719790,1.673780,1.627363,1.580569,1.533425,1.485960,1.438202,1.390181,1.341924,1.293461,1.244821,1.196034,1.147129,1.098135,1.049082,1.000000,0.950917,0.901865,0.852871,0.803965,0.755178,0.706539,0.658076,0.609819,0.561797,0.514040,0.466574,0.419430,0.372636,0.326220,0.280210,0.234633,0.189517,0.144890,0.100777,0.057206,0.014203,-0.028206,-0.069995,-0.111141,-0.151617,-0.191399,-0.230463,-0.268787,-0.306346,-0.343118,-0.379081,-0.414214,-0.448494,-0.481902,-0.514418,-0.546021,-0.576693,-0.606415,-0.635170,-0.662939,-0.689707,-0.715457,-0.740174,-0.763842,-0.786449,-0.807979,-0.828420,-0.847759,-0.865986,-0.883088,-0.899056,-0.913881,-0.927552,-0.940063,-0.951404,-0.961571,-0.970555,-0.978353,-0.984959,-0.990370,-0.994581,-0.997591,-0.999398,-1.000000,-0.999398,-0.997591,-0.994581,-0.990369,-0.984959,-0.978353,-0.970555,-0.961571,-0.951404,-0.940062,-0.927552,-0.913881,-0.899056,-0.883088,-0.865986,-0.847759,-0.828419,-0.807978,-0.786448,-0.763842,-0.740174,-0.715457,-0.689707,-0.662939,-0.635169,-0.606415,-0.576693,-0.546021,-0.514418,-0.481902,-0.448494,-0.414213,-0.379081,-0.343118,-0.306346,-0.268786,-0.230463,-0.191398,-0.151616,-0.111141,-0.069995,-0.028205,0.014204,0.057207,0.100778,0.144890,0.189517,0.234633,0.280210,0.326221,0.372637,0.419431,0.466575,0.514040,0.561798,0.609820,0.658077,0.706540,0.755179,0.803966,0.852871,0.901865,0.950918, used:266 [KISS FFTR] (256.000000,0.000000),(0.000015,-256.000000),(0.000000,0.000007),(0.000000,0.000008),(0.000001,0.000002),(0.000003,-0.000000),(-0.000001,0.000005),(0.000000,0.000003),(0.000000,0.000001),(-0.000005,-0.000000),(0.000001,-0.000001),(0.000002,-0.000004),(-0.000002,0.000002),(-0.000001,0.000004),(-0.000000,0.000001),(-0.000001,0.000002),(0.000002,0.000001),(0.000004,-0.000004),(-0.000001,0.000000),(0.000001,0.000001),(-0.000001,0.000002),(-0.000002,0.000000),(0.000000,0.000001),(-0.000002,0.000001),(-0.000001,0.000000),(0.000001,0.000002),(-0.000002,0.000001),(0.000001,0.000002),(-0.000001,0.000001),(-0.000002,-0.000003),(-0.000001,0.000001),(-0.000004,0.000000),(0.000000,0.000000),(-0.000005,-0.000009),(-0.000004,-0.000001),(-0.000003,-0.000002),(-0.000002,-0.000005),(0.000001,-0.000004),(0.000002,-0.000007),(0.000004,-0.000001),(0.000003,0.000000),(0.000001,0.000001),(-0.000001,-0.000000),(0.000002,0.000001),(0.000002,-0.000002),(0.000002,-0.000002),(0.000000,0.000001),(0.000002,-0.000000),(0.000000,0.000001),(0.000000,-0.000003),(0.000002,-0.000001),(0.000000,-0.000000),(-0.000001,0.000000),(-0.000000,-0.000001),(-0.000001,0.000000),(0.000000,0.000003),(-0.000000,-0.000000),(0.000000,0.000003),(0.000001,0.000002),(-0.000002,-0.000001),(-0.000001,0.000001),(-0.000001,0.000000),(0.000000,-0.000001),(0.000008,0.000008),(0.000000,0.000000),(-0.000000,-0.000015),(0.000001,0.000001),(0.000000,-0.000000),(-0.000001,-0.000000),(0.000003,0.000002),(0.000000,0.000002),(0.000002,-0.000005),(0.000000,0.000005),(-0.000001,0.000001),(-0.000000,0.000008),(-0.000000,-0.000004),(-0.000002,0.000003),(-0.000002,-0.000002),(0.000001,-0.000001),(-0.000003,0.000001),(0.000000,-0.000001),(-0.000000,-0.000000),(-0.000001,-0.000000),(0.000000,-0.000000),(-0.000000,-0.000001),(-0.000002,0.000001),(-0.000001,0.000001),(-0.000003,-0.000000),(-0.000000,-0.000002),(-0.000003,0.000001),(-0.000001,-0.000001),(0.000000,0.000002),(-0.000000,-0.000001),(0.000000,0.000000),(-0.000001,-0.000001),(-0.000003,0.000000),(0.000000,0.000000),(0.000000,-0.000002),(-0.000000,0.000001),(0.000001,0.000001),(0.000000,-0.000000),(-0.000002,-0.000001),(-0.000001,-0.000000),(-0.000001,0.000003),(0.000001,0.000000),(-0.000001,-0.000001),(-0.000002,0.000000),(-0.000003,-0.000003),(-0.000002,0.000001),(-0.000001,-0.000006),(0.000000,-0.000002),(0.000000,-0.000003),(0.000002,-0.000001),(0.000001,-0.000001),(0.000001,0.000002),(0.000001,-0.000001),(-0.000000,0.000000),(0.000002,-0.000000),(0.000000,-0.000001),(0.000004,0.000002),(0.000000,0.000001),(0.000002,0.000003),(0.000001,0.000000),(-0.000000,-0.000001),(-0.000001,-0.000000),(-0.000000,-0.000001),(-0.000001,0.000000),(-0.000000,0.000008),(0.000000,0.000000), used:271 [KISS FFTRI] 255.999985,268.565155,281.122681,293.665039,306.184814,318.674255,331.125977,343.532471,355.886230,368.179810,380.405884,392.556885,404.625793,416.605103,428.487549,440.266235,451.933899,463.483582,474.908203,486.200928,497.355103,508.363831,519.220581,529.918701,540.451904,550.813721,560.998047,570.998535,580.809387,590.424561,599.838135,609.044739,618.038696,626.814575,635.367004,643.690857,651.781372,659.633423,667.242065,674.603333,681.712463,688.564941,695.156982,701.484375,707.543762,713.330811,718.842407,724.075439,729.026306,733.692322,738.070496,742.158325,745.953491,749.453369,752.656006,755.559509,758.162048,760.462158,762.458374,764.149536,765.534546,766.612793,767.383240,767.845764,768.000061,767.845825,767.383240,766.612671,765.534607,764.149536,762.458313,760.462158,758.162109,755.559509,752.655945,749.453308,745.953491,742.158447,738.070435,733.692261,729.026306,724.075378,718.842407,713.330811,707.543579,701.484436,695.156860,688.564941,681.712402,674.603394,667.242188,659.633301,651.781433,643.690918,635.366882,626.814453,618.038696,609.044800,599.838135,590.424500,580.809326,570.998535,560.997986,550.813843,540.451965,529.918762,519.220459,508.363831,497.355042,486.201050,474.908142,463.483582,451.933868,440.266205,428.487518,416.604980,404.625732,392.556946,380.405853,368.179810,355.886292,343.532410,331.125885,318.674316,306.184753,293.665039,281.122559,268.565125,255.999924,243.434814,230.877319,218.334961,205.815125,193.325638,180.874039,168.467529,156.113693,143.820190,131.594131,119.443008,107.374146,95.394913,83.512344,71.733749,60.066086,48.516418,37.091721,25.798996,14.644852,3.636108,-7.220612,-17.918701,-28.451920,-38.813812,-48.998016,-58.998550,-68.809433,-78.424576,-87.838135,-97.044739,-106.038696,-114.814545,-123.367004,-131.690857,-139.781403,-147.633438,-155.242157,-162.603409,-169.712479,-176.565033,-183.156982,-189.484436,-195.543777,-201.330917,-206.842438,-212.075409,-217.026367,-221.692368,-226.070511,-230.158371,-233.953522,-237.453400,-240.655975,-243.559525,-246.162048,-248.462158,-250.458282,-252.149551,-253.534607,-254.612701,-255.383240,-255.845810,-256.000061,-255.845856,-255.383240,-254.612671,-253.534607,-252.149567,-250.458313,-248.462158,-246.162109,-243.559509,-240.655945,-237.453308,-233.953461,-230.158478,-226.070450,-221.692261,-217.026306,-212.075378,-206.842316,-201.330750,-195.543625,-189.484497,-183.156860,-176.564941,-169.712372,-162.603302,-155.242218,-147.633377,-139.781448,-131.690948,-123.366882,-114.814453,-106.038605,-97.044815,-87.838165,-78.424515,-68.809326,-58.998566,-48.997925,-38.813721,-28.451981,-17.918762,-7.220490,3.636169,14.644958,25.799088,37.091965,48.516373,60.066132,71.733795,83.512482,95.395065,107.374344,119.443253,131.594086,143.820145,156.113708,168.467606,180.874176,193.325806,205.815414,218.334915,230.877380,243.434875, 256点 1000次,用时如下 复数fft 复数ifft 424ms 419ms 实数fft 实数ifft 266ms 271ms 所以一次实数fft计算大概在270uS左右。 对比某个risc平台soc,跑525MHz,大概在100uS左右,性能是相当的。

  • 发表了主题帖: 【国民技术高性能MCU N32H487开发板】文件传输以及文件操作命令集

    前言 前面实现了文件系统,可以进行文件的读写,继续来实现文件的传输和基本的文件操作命令集,方便后续操作。   代码见 https://github.com/qinyunti/N32H487.git 文件操作命令集合 shell_func.c中 添加命令 static void lsfilefunc(uint8_t* param); static void rmfilefunc(uint8_t* param); static void renamefilefunc(uint8_t* param); static void touchfunc(uint8_t* param); static void mkdirfunc(uint8_t* param); static void pwdfunc(uint8_t* param); static void cdfunc(uint8_t* param); static void cpfilefunc(uint8_t* param); static void freefunc(uint8_t* param); { (uint8_t*)"ls ", lsfilefunc, (uint8_t*)"ls path"}, { (uint8_t*)"rm ", rmfilefunc, (uint8_t*)"rm path"}, { (uint8_t*)"rename ", renamefilefunc, (uint8_t*)"rename path newpath"}, { (uint8_t*)"touch ", touchfunc, (uint8_t*)"touch path size"}, { (uint8_t*)"mkdir ", mkdirfunc, (uint8_t*)"mkdir path"}, { (uint8_t*)"pwd ", pwdfunc, (uint8_t*)"pwd"}, { (uint8_t*)"cd ", cdfunc, (uint8_t*)"cd path"}, { (uint8_t*)"cp", cpfilefunc, (uint8_t*)"cp srcpath dstpath"}, { (uint8_t*)"free", freefunc, (uint8_t*)"free path"}, 实现如下 /*************** * 文件操作部分 **************/ /* List contents of a directory */ static FRESULT list_dir (const char *path) { FRESULT res; DIR dir; FILINFO fno; int nfile, ndir; res = f_opendir(&dir, path); /* Open the directory */ if (res == FR_OK) { nfile = ndir = 0; for (;;) { res = f_readdir(&dir, &fno); /* Read a directory item */ if (res != FR_OK || fno.fname[0] == 0) break; /* Error or end of dir */ if (fno.fattrib & AM_DIR) { /* Directory */ xprintf(" <DIR> %s\n", fno.fname); ndir++; } else { /* File */ xprintf("%10u %s\n", fno.fsize, fno.fname); nfile++; } } f_closedir(&dir); xprintf("%d dirs, %d files.\n", ndir, nfile); } else { xprintf("Failed to open \"%s\". (%u)\n", path, res); } return res; } void lsfilefunc(uint8_t* param) { char path[128]; if(1 == sscanf((const char*)param, "%*s %s", path)) { list_dir((const char *)path); } else { xprintf("param err"); } } void rmfilefunc(uint8_t* param) { FRESULT res; char path[128]; if(1 == sscanf((const char*)param, "%*s %s", path)) { if(FR_OK != (res = f_unlink((const char *)path))) { xprintf("unlink %s err %d\r\n",path,res); } } else { xprintf("param err"); } } void renamefilefunc(uint8_t* param) { FRESULT res; char path[128]; char newpath[128]; if(2 == sscanf((const char*)param, "%*s %s %s", path, newpath)) { if(FR_OK != (res = f_rename((const char *)path, (const char*)newpath))) { xprintf("rename %s to %s err %d\r\n",path,newpath,res); } } else { xprintf("param err"); } } void touchfunc(uint8_t* param) { FIL fil; char path[128]; int size; if(2 == sscanf((const char*)param, "%*s %s %d", path, &size)) { FRESULT res = f_open(&fil, path, FA_CREATE_NEW | FA_WRITE); if (FR_OK == res) { if(FR_OK != (res = f_expand(&fil,size,1))) { xprintf("expand %s size to %d err %d\r\n",path,size,res); } if(FR_OK != (res = f_close(&fil))) { xprintf("close %s err %d\r\n",path,res); } } else { xprintf("open %s err %d\r\n",path,res); } } else { xprintf("param err"); } } void mkdirfunc(uint8_t* param) { char path[128]; FRESULT res; if(1 == sscanf((const char*)param, "%*s %s", path)) { if(FR_OK != (res=f_mkdir((const char*)path))) { xprintf("mkdir %s err %d",path,res); } } else { xprintf("param err"); } } void pwdfunc(uint8_t* param) { (void)param; FRESULT fr; TCHAR str[128]; if(1 == sscanf((const char*)param, "%*s %s", str)){ if(FR_OK != (fr = f_getcwd(str, 128))) /* Get current directory path */ { xprintf("getcwd err %d\r\n",fr); } else { xprintf("%s\r\n",str); } }else { xprintf("param err"); } } void cdfunc(uint8_t* param) { char path[128]; FRESULT res; if(1 == sscanf((const char*)param, "%*s %s", path)) { if(FR_OK != (res=f_chdir((const char*)path))) { xprintf("chdir to %s err %d",path,res); } } else { xprintf("param err"); } } void freefunc(uint8_t* param) { char path[128]; FRESULT res; if(1 == sscanf((const char*)param, "%*s %s", path)) { FATFS *fs; DWORD fre_clust, fre_sect, tot_sect; /* Get volume information and free clusters of drive 1 */ res = f_getfree(path, &fre_clust, &fs); if(res == FR_OK) { /* Get total sectors and free sectors */ tot_sect = (fs->n_fatent - 2) * fs->csize; fre_sect = fre_clust * fs->csize; /* Print the free space (assuming 512 bytes/sector) */ xprintf("%10lu KiB total drive space.\n%10lu KiB available.\n", tot_sect / 2, fre_sect / 2); } else { xprintf("getfree %s err %d\r\n",path,res); } } else { xprintf("param err"); } } static int cp(const char* src, const char* dst) { FIL fr; FIL fw; BYTE buf[64] = {0x00}; FRESULT res; size_t write_size; /*剩余待写入字节数*/ DWORD pos = 0; UINT btr; /*一次试图写入字节数*/ UINT br; /*一次实际读到字节数*/ UINT bw; /*一次实际写入字节数*/ UINT size; res = f_open(&fr, src, FA_READ); if (res != FR_OK) { return -1; } res = f_open(&fw, dst, FA_WRITE | FA_CREATE_ALWAYS); if (res != FR_OK) { f_close(&fr); return -1; } write_size = f_size( &fr ); size = write_size; do { btr = (write_size > sizeof(buf)) ? sizeof(buf) : write_size; //res = f_lseek(&fr, pos); res = f_read (&fr, buf, btr, &br); if(res != FR_OK) { f_close(&fw); f_close(&fr); return -1; } //res = f_lseek(&fw, pos); res = f_write(&fw, buf, br, &bw); if((res != FR_OK) || (br != bw)) { f_close(&fw); f_close(&fr); return -1; } //f_sync(&fw); pos += br; write_size -= br; xprintf("\b\b%02d", 100 * (pos + 1) / size); }while(write_size > 0); xprintf("\b\b\b%d\r\n", 100); res = f_close(&fw); res = f_close(&fr); return 0; } static void cpfilefunc(uint8_t * cmdbuf) { int len; int res; char path[32] = {0x00}; char dst[32] = {0x00}; char regexp[32]; memset((void *)path, 0, sizeof(path)); len = sscanf((char const *)cmdbuf, "%*s %31s %31s %31s", path,dst,regexp); if (len == 2) { xprintf("\tcopy \"%s\" to \"%s\"...\r\n", path, dst); res = cp(path, dst); xprintf("f_cp result = %d\r\n", res); } else {} } 查看添加的命令 测试ls 0: 其他命令都测试OK。 Xmodem移植 时间戳获取函数 Main.c中初始化时 RCC_ClocksType RCC_clock; RCC_GetClocksFreqValue(&RCC_clock); SysTick_Config(RCC_clock.SysclkFreq/1000); n32h47x_48x_it.c中 uint32_t g_sys_tick = 0; void SysTick_Handler(void) { g_sys_tick++; } extern uint32_t g_sys_tick; static uint32_t getms(void) { return g_sys_tick; } Xmodem的实现参考公众号文章 https://mp.weixin.qq.com/s/QSYKxND3DTyQZ0JtnSqkzQ Xmodem.c #include <string.h> #include "xmodem.h" /* 符号定义 */ #define SOH 0x01 #define STX 0x02 #define EOT 0x04 #define ACK 0x06 #define NAK 0x15 #define CAN 0x18 #define CTRLZ 0x1A /* 状态 */ #define XMODEM_STATE_IDLE 0 #define XMODEM_STATE_RX_START_WAIT 1 #define XMODEM_STATE_RX_START_WAIT_HEAD 2 #define XMODEM_STATE_RX_DATA_WAIT 3 #define XMODEM_STATE_RX_DATA_WAIT_HEAD 4 #define XMODEM_STATE_TX_START_WAIT 1 #define XMODEM_STATE_TX_DATA 2 #define XMODEM_STATE_TX_ACK_WAIT 3 /** * \struct xmodem_state_st * 状态机结构体 */ typedef struct { uint8_t state; /**< 状态机的状态 */ uint32_t getlen; /**< 接收到的数据个数 */ uint8_t pnum; /**< 包ID */ uint32_t ms; /**< 上一个状态mS时间戳 */ } xmodem_state_st; static xmodem_cfg_st* s_cfg_pst = 0; /* 接口指针,用户初始化 */ static xmodem_state_st s_state_st; /** * crc计算参考https://www.iar.com/knowledge/support/technical-notes/general/checksum-generation/ */ static const uint16_t t[] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, }; static uint16_t crc_nibble_rom(uint16_t sum, uint8_t* p, uint32_t len) { while (len--) { // hi nibble sum = t[(sum>>12)^(*p >> 4)]^(sum<<4); // lo nibble sum = t[(sum>>12)^(*p++ & 0xF)]^(sum<<4); } return sum; } static int xmodem_check(uint16_t crc, uint8_t *buf, uint32_t sz) { if (crc != 0) { uint16_t crc = crc_nibble_rom(0, buf, sz); uint16_t tcrc = ((uint16_t)(buf[sz]) << 8) + (uint16_t)(buf[sz + 1]); if (crc == tcrc) { return 0; } } else { uint8_t cks = 0; for (uint32_t i = 0; i < sz; i++) { cks += buf[i]; } if (cks == buf[sz]) { return 0; } } return -1; } static uint16_t xmodem_check_cal(uint16_t crc, uint8_t *buf, uint32_t sz) { if (crc != 0) { uint16_t check; check = crc_nibble_rom(0, buf, sz); buf[sz+1] = check & 0xFF; buf[sz] = (check>>8) & 0xFF; return check; } else { uint8_t cks = 0; uint32_t i; for (i = 0; i < sz; i++) { cks += buf[i]; } buf[i] = cks; return cks; } } /** * \fn xmodem_rx * 接收处理, 在此之前必须要先调用xmodem_init_rx初始化 * \retval 0 正在处理,需要循环继续调用xmodem_rx处理 * \retval 1 接收正常完成 * \retval -1 参数错误,未初始化对应的接口 * \retval -2 未初始化,处于空闲状态 * \retval -3 发送方提前结束 * \retval -4 启动后超时未收到包头 * \retval -5 传输过程中,等待包头超时 * \retval -6 传输过程中,包ID错误,取消传输 * \retval -7 传输过程中,等待数据超时 * \retval -8 传输过程中,发送方取消 * \retval -9 传输过程中,写数据错误 */ int xmodem_rx(void) { int res = 0; uint8_t tmp = NAK; uint32_t t = s_cfg_pst->getms(); uint8_t* buf; uint16_t len; uint32_t getlen; if(s_cfg_pst == 0) { return -1; } if((s_cfg_pst->io_read == 0) || \ (s_cfg_pst->io_write == 0) || \ (s_cfg_pst->mem_write == 0) || \ (s_cfg_pst->buffer == 0) || \ (s_cfg_pst->getms == 0)) { return -1; } switch(s_state_st.state) { case XMODEM_STATE_IDLE: res = -2; break; case XMODEM_STATE_RX_START_WAIT: /* 根据使用校验方式发送不同的启动字符, * 然后等待对方发送第一个包的包头 */ if(s_cfg_pst->crccheck) { tmp = 'C'; } else { tmp = NAK; } s_cfg_pst->io_write(&tmp,1); s_state_st.ms = t; s_state_st.state = XMODEM_STATE_RX_START_WAIT_HEAD; s_cfg_pst->xferlen = 0; break; case XMODEM_STATE_RX_START_WAIT_HEAD: case XMODEM_STATE_RX_DATA_WAIT_HEAD: buf = s_cfg_pst->buffer; buf[0] = 0; if(0 != s_cfg_pst->io_read(buf,1)) { if((buf[0] == SOH) || (buf[0] == STX)) { s_cfg_pst->plen = (buf[0] == SOH) ? 128 : 1024; s_state_st.ms = t; s_state_st.state = XMODEM_STATE_RX_DATA_WAIT; s_state_st.getlen = 1; } /* 发送方结束 */ if(buf[0] == EOT) { tmp = ACK; s_cfg_pst->io_write(&tmp,1); s_state_st.state = XMODEM_STATE_IDLE; if(s_cfg_pst->xferlen >= s_cfg_pst->totallen) { res = 1; } else { res = -3; } } /* 发送方取消 */ if(buf[0] == CAN) { s_state_st.state = XMODEM_STATE_IDLE; res = -8; } } if((buf[0] != SOH) && (buf[0] != STX)) { /* 非法值或者没有收到数据,继续等待直到超时 */ if((t - s_state_st.ms) >= s_cfg_pst->ack_timeout) { /* 超时未收到响应,继续重复发送启动字符 * 如果超过了设置的超时时间则退出 */ if(s_cfg_pst->start_timeout <= 1) { /* 超时退出 */ s_state_st.state = XMODEM_STATE_IDLE; res = -4; } else { /* 重新发送启动 */ if(s_state_st.state == XMODEM_STATE_RX_START_WAIT_HEAD) { s_cfg_pst->start_timeout--; s_state_st.state = XMODEM_STATE_RX_START_WAIT; } else { /* 数据阶段等待头超时, 结束传输 */ s_state_st.state = XMODEM_STATE_IDLE; res = -5; } } } else { /* 未超时继续等待*/ } } break; case XMODEM_STATE_RX_DATA_WAIT: buf = s_cfg_pst->buffer; len = s_cfg_pst->plen + 3 + ((s_cfg_pst->crccheck == 0) ? 1 : 2); getlen = s_cfg_pst->io_read(buf+s_state_st.getlen, len - s_state_st.getlen); s_state_st.getlen += getlen; if(s_state_st.getlen >= len) { /* 接收完,准备判断合法性 */ if(((uint8_t)(s_state_st.pnum + 1) != buf[1]) || ((buf[1] + buf[2]) != (uint8_t)255)) { /* 包ID错误,取消传输 */ tmp = CAN; s_cfg_pst->io_write(&tmp,1); s_state_st.state = XMODEM_STATE_IDLE; res = -6; } else { /* 校验正确 */ if(0 == xmodem_check(s_cfg_pst->crccheck, buf+3, s_cfg_pst->plen)) { s_state_st.pnum = buf[1]; s_state_st.state = XMODEM_STATE_RX_DATA_WAIT_HEAD; s_state_st.ms = t; /* 调用写接口存储数据 */ if((s_cfg_pst->xferlen + s_cfg_pst->plen) >= s_cfg_pst->totallen) { if(s_cfg_pst->xferlen >= s_cfg_pst->totallen) { /* 已经收到了指定的数据量,但是发送方还在发送,则主动取消 */ tmp = CAN; s_cfg_pst->io_write(&tmp,1); s_state_st.state = XMODEM_STATE_IDLE; res = 1; } else { tmp = ACK; s_cfg_pst->io_write(&tmp,1); s_cfg_pst->mem_write(s_cfg_pst->addr+s_cfg_pst->xferlen, buf+3 ,s_cfg_pst->totallen-s_cfg_pst->xferlen); s_cfg_pst->xferlen = s_cfg_pst->totallen; } } else { tmp = ACK; s_cfg_pst->io_write(&tmp,1); if(0 == s_cfg_pst->mem_write(s_cfg_pst->addr+s_cfg_pst->xferlen, buf+3 ,s_cfg_pst->plen)) { /* 写错误,取消传输 */ tmp = CAN; s_cfg_pst->io_write(&tmp,1); s_state_st.state = XMODEM_STATE_IDLE; res = -9; } else { s_cfg_pst->xferlen += s_cfg_pst->plen; } } } else { tmp = NAK; s_cfg_pst->io_write(&tmp,1); s_state_st.state = XMODEM_STATE_RX_DATA_WAIT_HEAD; } } } else { /* 未接收完判断超时 */ if((t - s_state_st.ms) >= s_cfg_pst->packet_timeout) { /* 超时退出 */ tmp = NAK; s_cfg_pst->io_write(&tmp,1); s_state_st.state = XMODEM_STATE_IDLE; res = -7; } else { /* 未超时继续等待*/ } } break; } return res; } /** * \fn xmodem_init_rx * 接收初始化 * 以下成员必须初始化 * \param[in] cfg \ref xmodem_cfg_st 配置信息 */ void xmodem_init_rx(xmodem_cfg_st* cfg) { s_cfg_pst = cfg; s_state_st.state = XMODEM_STATE_RX_START_WAIT; s_state_st.getlen = 0; s_state_st.pnum = 0; if(s_cfg_pst != 0) { if(s_cfg_pst->io_read_flush != 0) { s_cfg_pst->io_read_flush(); } } } /** * \fn xmodem_tx * 发送处理, 在此之前必须要先调用xmodem_init_tx初始化 * \retval 0 正在处理,需要循环继续调用xmodem_tx处理 * \retval 1 发送正常完成 * \retval -1 参数错误,未初始化对应的接口 * \retval -2 未初始化,处于空闲状态 * \retval -3 接收方提前取消 * \retval -4 启动阶段超时未收到响应 * \retval -5 数据阶段超时未收到响应 */ int xmodem_tx(void) { int res = 0; uint8_t tmp = 0; uint32_t t = s_cfg_pst->getms(); uint8_t* buf; uint16_t len; if(s_cfg_pst == 0) { return -1; } if((s_cfg_pst->io_read == 0) || \ (s_cfg_pst->io_write == 0) || \ (s_cfg_pst->mem_read == 0) || \ (s_cfg_pst->buffer == 0) || \ (s_cfg_pst->getms == 0)) { return -1; } switch(s_state_st.state) { case XMODEM_STATE_IDLE: res = -2; break; case XMODEM_STATE_TX_START_WAIT: buf = s_cfg_pst->buffer; if(0 != s_cfg_pst->io_read(buf,1)) { if((buf[0] == 'C') || (buf[0] == NAK)) { s_cfg_pst->crccheck = (buf[0] == 'C') ? 1 : 0; s_state_st.ms = t; s_state_st.state = XMODEM_STATE_TX_DATA; } if(buf[0] == CAN) { s_state_st.state = XMODEM_STATE_IDLE; res = -3; } } if((buf[0] != 'C') && (buf[0] != NAK) && (buf[0] != CAN)) { /* 非法值或者没有收到数据,继续等待直到超时 */ if((t - s_state_st.ms) >= s_cfg_pst->ack_timeout) { /* 超时未收到响应,继续重复发送启动字符 * 如果超过了设置的超时时间则退出 */ if(s_cfg_pst->start_timeout <= 1) { /* 超时退出 */ s_state_st.state = XMODEM_STATE_IDLE; res = -4; } else { s_cfg_pst->start_timeout--; } s_state_st.ms = t; } else { /* 未超时继续等待*/ } } break; case XMODEM_STATE_TX_DATA: buf = s_cfg_pst->buffer; buf[0] = (s_cfg_pst->plen == 1024)? STX : SOH; buf[1] = s_state_st.pnum; buf[2] = ~buf[1]; if((s_cfg_pst->xferlen + s_cfg_pst->plen) >= s_cfg_pst->totallen) { len = s_cfg_pst->mem_read(s_cfg_pst->addr+s_cfg_pst->xferlen, buf+3,s_cfg_pst->totallen-s_cfg_pst->xferlen); } else { len = s_cfg_pst->mem_read(s_cfg_pst->addr+s_cfg_pst->xferlen, buf+3,s_cfg_pst->plen); } if((len < s_cfg_pst->plen) && (len > 0)) { memset(buf+3+len, CTRLZ, s_cfg_pst->plen - len); } if(len > 0) { xmodem_check_cal(s_cfg_pst->crccheck, buf+3, s_cfg_pst->plen); len = s_cfg_pst->plen + 3 + ((s_cfg_pst->crccheck == 0) ? 1 : 2); s_cfg_pst->io_write(buf,len); s_state_st.state = XMODEM_STATE_TX_ACK_WAIT; s_state_st.ms = t; } else { /* 读完 */ tmp = EOT; s_cfg_pst->io_write(&tmp,1); s_state_st.state = XMODEM_STATE_IDLE; res = 1; } break; case XMODEM_STATE_TX_ACK_WAIT: buf = s_cfg_pst->buffer; if(0 != s_cfg_pst->io_read(buf,1)) { if(buf[0] == ACK) { /* 判断是否传输完,未传输完则发送下一包 */ if((s_cfg_pst->xferlen + s_cfg_pst->plen) >= s_cfg_pst->totallen) { /* 发送完 */ s_state_st.state = XMODEM_STATE_IDLE; s_state_st.pnum++; s_cfg_pst->xferlen += s_cfg_pst->plen; if(s_cfg_pst->xferlen >= s_cfg_pst->totallen) { s_cfg_pst->xferlen = s_cfg_pst->totallen; } tmp = EOT; s_cfg_pst->io_write(&tmp,1); res = 1; } else { /* 发送下一包 */ s_state_st.state = XMODEM_STATE_TX_DATA; s_state_st.pnum++; s_cfg_pst->xferlen += s_cfg_pst->plen; } } if(buf[0] == NAK) { /* 重发 */ s_state_st.state = XMODEM_STATE_TX_DATA; } if(buf[0] == CAN) { s_state_st.state = XMODEM_STATE_IDLE; res = -3; } } if((buf[0] != ACK) && (buf[0] != NAK) && (buf[0] != CAN)) { /* 非法值或者没有收到数据,继续等待直到超时 */ if((t - s_state_st.ms) >= s_cfg_pst->ack_timeout) { /* 超时退出 */ s_state_st.state = XMODEM_STATE_IDLE; res = -5; } else { /* 未超时继续等待*/ } } break; } return res; } /** * \fn xmodem_init_tx * 发送初始化 * 以下成员必须初始化 * \param[in] cfg \ref xmodem_cfg_st 配置信息 */ void xmodem_init_tx(xmodem_cfg_st* cfg) { s_cfg_pst = cfg; s_state_st.state = XMODEM_STATE_TX_START_WAIT; /* 等待接收端发送启动 */ s_state_st.getlen = 0; s_state_st.pnum = 1; if(s_cfg_pst != 0) { s_state_st.ms = s_cfg_pst->getms(); s_cfg_pst->xferlen = 0; if(s_cfg_pst->io_read_flush != 0) { s_cfg_pst->io_read_flush(); } } }   Xmodem.h #ifndef XMODEM_H #define XMODEM_H #ifdef __cplusplus extern "C" { #endif #include <stdint.h> typedef uint32_t (*xmodem_io_read_pf)(uint8_t* buffer, uint32_t len); /**< 通讯接收接口 */ typedef uint32_t (*xmodem_io_write_pf)(uint8_t* buffer, uint32_t len);/**< 通讯发送接口 */ typedef void (*xmodem_read_flush_pf)(void); /**< 通讯接收flush接口 */ typedef void (*xmodem_write_flush_pf)(void); /**< 通讯发送flush接口 */ typedef uint32_t (*xmodem_mem_read_pf)(uint32_t addr, uint8_t* buffer, uint32_t len); /**< 读存储接口 */ typedef uint32_t (*xmodem_mem_write_pf)(uint32_t addr, uint8_t* buffer, uint32_t len); /**< 写存储接口 */ typedef uint32_t (*xmodem_getms_pf)(void); /**< 获取mS时间戳 */ /** * \struct xmodem_cfg_st * 接口,参数配置结构体 */ typedef struct { xmodem_io_read_pf io_read; /**< 通讯接收接口 */ xmodem_io_read_pf io_write; /**< 通讯发送接口 */ xmodem_read_flush_pf io_read_flush; /**< 通讯接收flush接口 */ xmodem_write_flush_pf io_write_flush; /**< 通讯发送flush接口 */ xmodem_mem_read_pf mem_read; /**< 读存储接口 */ xmodem_mem_write_pf mem_write; /**< 写存储接口 */ xmodem_getms_pf getms; /**< 获取mS时间戳接口 */ uint32_t start_timeout; /**< 等待启动超时次数,单位每次超时为ack_timeout */ uint32_t packet_timeout; /**< 等待数据包超时时间mS */ uint32_t ack_timeout; /**< 等待响应(头)超时时间mS*/ uint8_t crccheck; /**< 对于接收时有效1使用CRC校验 0使用累加和校验 */ uint16_t plen; /**< 对于发送时有效指定包长时128还是1024 */ uint8_t* buffer; /**< 包缓冲区,用户提供,1024字节包需要1024+5 */ uint32_t addr; /**< 存储地址 */ uint32_t totallen; /**< 传输长度 */ uint32_t xferlen; /**< 已经传输长度 */ } xmodem_cfg_st; /** * \fn xmodem_rx * 接收处理, 在此之前必须要先调用xmodem_init_rx初始化 * \retval 0 正在处理,需要循环继续调用xmodem_rx处理 * \retval 1 接收正常完成 * \retval -1 参数错误,未初始化对应的接口 * \retval -2 未初始化,处于空闲状态 * \retval -3 发送方提前结束 * \retval -4 启动后超时未收到包头 * \retval -5 传输过程中,等待包头超时 * \retval -6 传输过程中,包ID错误,取消传输 * \retval -7 传输过程中,等待数据超时 * \retval -8 传输过程中,发送方取消 * \retval -9 传输过程中,写数据错误 */ int xmodem_rx(void); /** * \fn xmodem_init_rx * 接收初始化 * 以下成员必须初始化 * \param[in] cfg \ref xmodem_cfg_st 配置信息 */ void xmodem_init_rx(xmodem_cfg_st* cfg); /** * \fn xmodem_tx * 发送处理, 在此之前必须要先调用xmodem_init_tx初始化 * \retval 0 正在处理,需要循环继续调用xmodem_tx处理 * \retval 1 发送正常完成 * \retval -1 参数错误,未初始化对应的接口 * \retval -2 未初始化,处于空闲状态 * \retval -3 接收方提前取消 * \retval -4 启动阶段超时未收到响应 * \retval -5 数据阶段超时未收到响应 */ int xmodem_tx(void); /** * \fn xmodem_init_tx * 发送初始化 * 以下成员必须初始化 * \param[in] cfg \ref xmodem_cfg_st 配置信息 */ void xmodem_init_tx(xmodem_cfg_st* cfg); #ifdef __cplusplus } #endif #endif   Shell_func.h中 #include "xmodem.h" static void rxfilefunc(uint8_t* param); static void sxfilefunc(uint8_t* param); { (uint8_t*)"rxfile", rxfilefunc, (uint8_t*)"rxfile name len"}, { (uint8_t*)"sxfile", sxfilefunc, (uint8_t*)"sxfile name len"}, /*************** * 文件传输部分 **************/ static uint8_t rxtx_buf[1029]; extern uint32_t g_sys_tick; static uint32_t getms(void) { return g_sys_tick; } static uint32_t io_read(uint8_t* buffer, uint32_t len) { return uart_read(0,buffer, len); } static void io_read_flush(void) { uint8_t tmp; while(0 != uart_read(0,&tmp, 1)); } static uint32_t io_write(uint8_t* buffer, uint32_t len) { uart_send(0,buffer, len); return len; } static FIL rx_fil; /* File object */ static int rx_file_open_flag = 0; static int rx_file_open(char* name) { FRESULT res = f_open(&rx_fil, name, FA_CREATE_NEW | FA_WRITE); if (FR_OK == res) { rx_file_open_flag = 1; return 0; } else { xprintf("open %s err %d\r\n",name,res); return -1; } } static int rx_file_close(char* name) { (void)name; if(rx_file_open_flag != 0) { rx_file_open_flag = 0; FRESULT res = f_close(&rx_fil); if(res != FR_OK) { xprintf("close err %d\r\n",res); } return 0; } else { return -1; } } static uint32_t rx_file_write(uint32_t addr, uint8_t* buffer, uint32_t len) { (void)addr; if(rx_file_open_flag != 0) { UINT bw; FRESULT res = f_write(&rx_fil, buffer, len, &bw); if ((bw != len) || (res != FR_OK)) { xprintf("write err %d %d\r\n",bw,res); } return bw; } else { return 0; } } void rxfilefunc(uint8_t* param) { char name[64]; uint32_t len; int res = 0; if(2 == sscanf((const char*)param, "%*s %s %d", name, &len)) { xprintf("rxfile %s %ld\r\n",name,len); if(0 == rx_file_open(name)) { xmodem_cfg_st cfg= { .buffer = rxtx_buf, .crccheck = 1, .getms = getms, .io_read = io_read, .io_read_flush = io_read_flush, .io_write = io_write, .start_timeout = 60, .packet_timeout = 2000, .ack_timeout = 2000, .mem_write = rx_file_write, .addr = 0, .totallen = len, }; xmodem_init_rx(&cfg); while((res = xmodem_rx()) == 0); rx_file_close(name); xprintf("res:%d\r\n",res); } else { xprintf("open:%s err\r\n",name); } } } static FIL tx_fil; /* File object */ static int tx_file_open_flag = 0; static int tx_file_open(char* name) { FRESULT res = f_open(&tx_fil, name, FA_READ); if (FR_OK == res) { tx_file_open_flag = 1; return 0; } else { xprintf("open %s err %d\r\n",name,res); return -1; } } static int tx_file_close(char* name) { (void)name; if(tx_file_open_flag != 0) { tx_file_open_flag = 0; FRESULT res = f_close(&tx_fil); if(res != FR_OK) { xprintf("close err %d\r\n",res); } return 0; } else { return -1; } } static uint32_t tx_file_read(uint32_t addr, uint8_t* buffer, uint32_t len) { (void)addr; UINT br; FRESULT res = f_read(&tx_fil, buffer, len, &br); if(res != 0) { xprintf("read err %d\r\n",res); } return br; } void sxfilefunc(uint8_t* param) { char name[64]; uint32_t len; int res = 0; if(2 == sscanf((const char*)param, "%*s %s %d", name, &len)) { xprintf("sxfile %s %ld\r\n",name,len); if(0 == tx_file_open(name)) { xmodem_cfg_st cfg= { .buffer = rxtx_buf, .plen = 1024, .getms = getms, .io_read = io_read, .io_read_flush = io_read_flush, .io_write = io_write, .start_timeout = 60, .packet_timeout = 1000, .ack_timeout = 5000, .mem_read = tx_file_read, .addr = 0, .totallen = len, }; xmodem_init_tx(&cfg); while((res = xmodem_tx()) == 0); tx_file_close(name); xprintf("res:%d\r\n",res); } else { xprintf("open:%s err\r\n",name); } } } 看到添加的命令 导入文件测试,这里因为spi速度设置的比较低所以文件写比较慢,慢于xmodem传输速度。 导出文件测试 这里读文件比写文件块,速度大于xmodem传输速度,所以115200波特率,9KB/s基本跑满。 总结 以上完成了文件传输,和基本文件操作命令,后面就可以方便导入导出文件,以及进行文件操作。

  • 发表了主题帖: 【国民技术高性能MCU N32H487开发板】移植FATFS文件系统读写文件测试

    前言 前面实现了SPI FLASH的读写,这一篇来基于SPI FLASH来移植FATFS文件系统。 代码见: https://github.com/qinyunti/N32H487.git 源码 添加源文件 设置头文件包含路径 配置 没有使用OS ffconf.h中 #define FF_FS_REENTRANT0 不支持动态内存分配 Ffconf.h中 #define FF_USE_LFN2 此时无需ffsystem.c diskio.c中,调用flash_itf.c的接口实现读写。 手里的是W25Q32FW 4MB diskio.c中 根据实际大小修改 case GET_SECTOR_COUNT: *(DWORD*)buff = 8192; /* 8192*512=4MB */ res = RES_OK; 测试 初始化挂载文件系统 #include ff.h static FATFS fs; /* Filesystem object */ static BYTE work[FF_MAX_SS]; /* Work area (larger is better for processing time) */ static void fs_init(void) { FRESULT res; /* API result code */ if(FR_OK != (res = f_mount (&fs, "0:", 1))) { xprintf("mount err %d, mkfs\r\n",res); res = f_mkfs("0:",0,work,sizeof(work)); if(res == 0) { xprintf("mkfs ok\r\n"); if(FR_OK == f_mount (&fs, "0:", 1)) { xprintf("mount ok\r\n"); } else { xprintf("mount err\r\n"); } } else { xprintf("mkfs err %d\r\n",res); } } else { xprintf("mount ok\r\n"); } } shell_func.c中添加两个命令行 #include "ff.h" static void printfilefunc(uint8_t* param); static void writefilefunc(uint8_t* param); { (uint8_t*)"printfile", printfilefunc, (uint8_t*)"printfile path addr size"}, { (uint8_t*)"writefile", writefilefunc, (uint8_t*)"writefile path addr[hex] hexstr"}, void printfilefunc(uint8_t* param) { char path[128]; uint8_t tmp[16]; uint32_t addr; uint32_t size; FRESULT res; FIL fil; UINT br; uint32_t offset = 0; if(3 == sscanf((const char*)param, "%*s %s %x %d", path, &addr, &size)) { xprintf("hexdump %s 0x%x %d\r\n",path,addr,size); if(FR_OK == (res=f_open(&fil,(const char*)path, FA_READ))) { xprintf("\r\n"); do { br = 0; if(FR_OK == (res = f_read(&fil,tmp,(size>16)?16:size,&br))) { xprintf("%08x ",offset); offset+=br; for(uint32_t i=0;i<br;i++) { xprintf("%02x",(uint32_t)tmp); } xprintf(":"); for(uint32_t i=0;i<br;i++) { xprintf("%c",((tmp>0x1F)&&(tmp<0x7F))?(char)tmp:'.'); } xprintf("\r\n"); size -= br; } else { break; } }while(br > 0); if(FR_OK != (res = f_close(&fil))) { xprintf("close %s err %d\r\n",path,res); } } else { xprintf("open %s err %d",path,res); } } else { xprintf("param err"); } } void writefilefunc(uint8_t* param) { char path[128]; uint8_t hexstr[32+1]; uint8_t tmp[16]; uint32_t hexnum = 0; uint32_t addr; FRESULT res; FIL fil; UINT bw; if(3 == sscanf((const char*)param, "%*s %s %x %s", path, &addr, hexstr)) { xprintf("hexwrite %s 0x%x %s\r\n",path,addr,hexstr); if(FR_OK == (res=f_open(&fil,(const char*)path, FA_WRITE | FA_CREATE_ALWAYS))) { xprintf("\r\n"); hexnum = str2hex((const char*)hexstr,tmp,32); if(hexnum > 0) { if(FR_OK == (res=(f_lseek(&fil,addr)))) { if(FR_OK != (res = f_write(&fil,tmp,hexnum,&bw))) { xprintf("write err %d\r\n",res); } } else { xprintf("seek %d err %d\r\n",addr,res); } } if(FR_OK != (res = f_close(&fil))) { xprintf("close %s err %d\r\n",path,res); } } else { xprintf("open %s err %d",path,res); } } else { xprintf("param err"); } } 第一次运行,flash中没有文件系统,会执行格格式化,需要时间会久点。 Help查看增加的命令 些文件再读出 writefile 0:/test.txt 0 12345678 printfile 0:/test.txt 0 16 可以看到写入和读出的数据一致。 问题 杜邦线较长可能影响信号质量,可以适当降低spi速率   等待发送完改为 while(SPI_I2S_GetStatus(SPI1, SPI_I2S_BUSY_FLAG) != 0); 而不是SPI_I2S_TE_FLAG   CS初始化要拉高 GPIO_WriteBits(GPIOA, GPIO_PIN_4, Bit_SET);   FLASH大小至少要设置为4M *(DWORD*)buff = 8192; 如果设置为2M *(DWORD*)buff = 4096; 会 Nclst为0 nclst = (tsect - sysect) / fs->csize;/* Number of clusters */ if (nclst == 0) return FR_NO_FILESYSTEM;/* (Invalid volume size) */

  • 发表了主题帖: 【国民技术高性能MCU N32H487开发板】spi测试与spi flash驱动

    前言 这一篇,继续来测试SPI接口,实现SPI FLASH驱动,为后面文件系统做准备。 SPI驱动 添加spi的库 引脚这里使用SPI1 PA4/5/6/7 AF1 使用杜邦线外接SPI FLASH模块 Spi.c 初始化 #include "uart.h" #include "fifo.h" #include "n32h47x_48x.h" #include "n32h47x_48x_spi.h" #include "n32h47x_48x_rcc.h" #include "n32h47x_48x_gpio.h" void spi_init(int id, uint32_t baud, int mode) { if(id == 0){ /* PA4 NSS GPIO * PB5 SCK AF1 * PB6 MISO AF1 * PB7 MOSI AF1 */ RCC_EnableAHB1PeriphClk(RCC_AHB_PERIPHEN_GPIOA,ENABLE); RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_SPI1,ENABLE);   GPIO_InitType GPIO_InitStructure; /* Initialize GPIO_InitStructure */ GPIO_InitStruct(&GPIO_InitStructure); GPIO_InitStructure.Pin = GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7; GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP; GPIO_InitStructure.GPIO_Alternate = GPIO_AF1; GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP; GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);   GPIO_InitStructure.Pin = GPIO_PIN_4; GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP; GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);   SPI_InitType SPI_InitStruct; RCC_ClocksType RCC_clock; RCC_GetClocksFreqValue(&RCC_clock);   uint32_t clk = RCC_clock.Pclk2Freq; uint32_t div = clk/baud; if(div<=2){ SPI_InitStruct.BaudRatePres = SPI_BR_PRESCALER_2; }else if(div<=4){ SPI_InitStruct.BaudRatePres = SPI_BR_PRESCALER_4; }else if(div<=8){ SPI_InitStruct.BaudRatePres = SPI_BR_PRESCALER_8; }else if(div<=16){ SPI_InitStruct.BaudRatePres = SPI_BR_PRESCALER_16; }else if(div<=32){ SPI_InitStruct.BaudRatePres = SPI_BR_PRESCALER_32; }else if(div<=64){ SPI_InitStruct.BaudRatePres = SPI_BR_PRESCALER_64; }else if(div<=128){ SPI_InitStruct.BaudRatePres = SPI_BR_PRESCALER_128; }else{ SPI_InitStruct.BaudRatePres = SPI_BR_PRESCALER_256; } if(mode & 0x01){ SPI_InitStruct.CLKPHA = SPI_CLKPHA_SECOND_EDGE; }else{ SPI_InitStruct.CLKPHA = SPI_CLKPHA_FIRST_EDGE; } if(mode & 0x02){ SPI_InitStruct.CLKPOL = SPI_CLKPOL_HIGH; }else{ SPI_InitStruct.CLKPOL = SPI_CLKPOL_LOW; } SPI_InitStruct.CRCPoly = 0x0f; SPI_InitStruct.DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX; SPI_InitStruct.DataLen = SPI_DATA_SIZE_8BITS; SPI_InitStruct.FirstBit = SPI_FB_MSB; SPI_InitStruct.NSS = SPI_NSS_SOFT; SPI_InitStruct.SpiMode = SPI_MODE_MASTER; SPI_Init(SPI1,&SPI_InitStruct); SPI_Enable(SPI1,ENABLE); }else if(id == 1){ } } 传输接口 uint32_t spi_trans(int id, int cs, uint8_t* tx_buffer, uint8_t* rx_buffer, uint32_t len, int flag) { uint8_t rx; if(id == 0){ if(cs == 0){ GPIO_WriteBits(GPIOA, GPIO_PIN_4, Bit_RESET); }else if(cs == 1){ } for(uint32_t i=0; i<len; i++){ while(SPI_I2S_GetStatus(SPI1, SPI_I2S_TE_FLAG) == 0); if(tx_buffer != (uint8_t*)0){ SPI_I2S_TransmitData(SPI1, tx_buffer); }else{ SPI_I2S_TransmitData(SPI1, 0xFF); }   while(SPI_I2S_GetStatus(SPI1, SPI_I2S_RNE_FLAG) == 0); rx = SPI_I2S_ReceiveData(SPI1); if(rx_buffer != (uint8_t*)0){ rx_buffer = rx; } }   if(flag){ if(cs == 0){ GPIO_WriteBits(GPIOA, GPIO_PIN_4, Bit_SET); }else if(cs == 1){ } } }else if(id == 1){ } return len; } Spi.h #ifndef SPI_H #define SPI_H #ifdef __cplusplus extern "C" { #endif #include <stdint.h> void spi_init(int id, uint32_t baud, int mode); uint32_t spi_trans(int id, int cs, uint8_t* tx_buffer, uint8_t* rx_buffer, uint32_t len, int flag); #ifdef __cplusplus } #endif #endif SPI FLASH驱动 添加flash.c/h完全可移植 flash.c #include <string.h> #include "flash.h" #define FLASH_CMD_WEL 0x06 #define FLASH_CMD_PAGEPROGRAM 0x02 #define FLASH_CMD_READ 0x03 #define FLASH_CMD_ERASESECTOR 0x20 #define FLASH_CMD_READSR1 0x05 #define FLASH_CMD_READSR2 0x35 #define FLASH_CMD_READSR3 0x15 #define FLASH_CMD_WRITESR1 0x01 #define FLASH_CMD_WRITESR2 0x31 #define FLASH_CMD_WRITESR3 0x11 #define FLASH_SR1_BUSY (1 << 0) int flash_write_enable(flash_dev_st* dev) { uint8_t cmd = FLASH_CMD_WEL; dev->spi_trans(&cmd, 0, 1, 1); return 0; } int flash_read_sr1(flash_dev_st* dev, uint8_t* sr) { uint8_t cmd[2] = {FLASH_CMD_READSR1,0xFF}; uint8_t rx[2]; dev->spi_trans(cmd, rx, 2, 1); *sr = rx[1]; return 0; } int flash_read_sr2(flash_dev_st* dev, uint8_t* sr) { uint8_t cmd[2] = {FLASH_CMD_READSR2,0xFF}; uint8_t rx[2]; dev->spi_trans(cmd, rx, 2, 1); *sr = rx[1]; return 0; } int flash_read_sr3(flash_dev_st* dev, uint8_t* sr) { uint8_t cmd[2] = {FLASH_CMD_READSR3,0xFF}; uint8_t rx[2]; dev->spi_trans(cmd, rx, 2, 1); *sr = rx[1]; return 0; } int flash_write_sr1(flash_dev_st* dev, uint8_t val) { uint8_t cmd[2] = {FLASH_CMD_WRITESR1,0}; cmd[1] = val; dev->spi_trans(cmd, 0, 2, 1); return 0; } int flash_write_sr2(flash_dev_st* dev, uint8_t val) { uint8_t cmd[2] = {FLASH_CMD_WRITESR2,0}; cmd[1] = val; dev->spi_trans(cmd, 0, 2, 1); return 0; } int flash_write_sr3(flash_dev_st* dev, uint8_t val) { uint8_t cmd[2] = {FLASH_CMD_WRITESR3,0}; cmd[1] = val; dev->spi_trans(cmd, 0, 2, 1); return 0; } int flash_wait_busy(flash_dev_st* dev) { uint8_t sr = 0; do{ flash_read_sr1(dev, &sr); } while(FLASH_SR1_BUSY & sr); return 0; } int flash_erase_sector(flash_dev_st* dev, uint32_t addr) { uint8_t cmd[4]; flash_write_enable(dev); cmd[0] = FLASH_CMD_ERASESECTOR; cmd[1] = (uint8_t)(addr >> 16 & 0xFF); cmd[2] = (uint8_t)(addr >> 8 & 0xFF); cmd[3] = (uint8_t)(addr >> 0 & 0xFF); dev->spi_trans(cmd, 0, 4, 1); flash_wait_busy(dev); return 0; } int flash_pageprogram(flash_dev_st* dev, uint8_t* buffer, uint32_t addr, uint32_t len) { uint8_t cmd[4]; cmd[0] = FLASH_CMD_PAGEPROGRAM; cmd[1] = (uint8_t)(addr >> 16 & 0xFF); cmd[2] = (uint8_t)(addr >> 8 & 0xFF); cmd[3] = (uint8_t)(addr >> 0 & 0xFF); flash_write_enable(dev); dev->spi_trans(cmd, 0, 4, 0); dev->spi_trans(buffer, 0, len, 1); flash_wait_busy(dev); return 0; } uint32_t flash_read(flash_dev_st* dev, uint8_t* buffer, uint32_t addr, uint32_t len) { uint8_t cmd[4]; cmd[0] = FLASH_CMD_READ; cmd[1] = (uint8_t)(addr >> 16 & 0xFF); cmd[2] = (uint8_t)(addr >> 8 & 0xFF); cmd[3] = (uint8_t)(addr >> 0 & 0xFF); dev->spi_trans(cmd, 0, 4, 0); dev->spi_trans(0, buffer, len, 1); return 0; } uint32_t flash_write(flash_dev_st* dev, uint8_t* buffer, uint32_t addr, uint32_t len) { /** * | | | | | * | | * < len > * addr * <sec_head > < sec_tail > * start_addr */ uint32_t sec_head; uint32_t sec_tail = 0; uint32_t sec_mid_num; uint32_t start_addr; uint32_t end_addr; uint32_t fill; start_addr = addr & (~(dev->sector_size-1)); end_addr = (addr+len) & (~(dev->sector_size-1)); sec_head = addr & (dev->sector_size-1); if((end_addr != start_addr) || (sec_head == 0)){ sec_tail = (addr + len) & (dev->sector_size-1); } sec_mid_num = (end_addr - start_addr) >> dev->sector_bits; if((sec_head != 0) || (sec_tail != 0)){ if(sec_mid_num > 1){ sec_mid_num--; }else{ sec_mid_num = 0; } } /* head */ if(sec_head > 0) { flash_read(dev,dev->buffer, start_addr, dev->sector_size); fill =( len > (dev->sector_size-sec_head)) ? (dev->sector_size-sec_head) : len; memcpy(dev->buffer+sec_head,buffer,len); flash_erase_sector(dev,start_addr); for (uint32_t j=0; j<16; j++) { flash_pageprogram(dev,dev->buffer + (j<<dev->page_bits),start_addr + (j<<dev->page_bits), dev->page_size); } buffer += fill; start_addr += dev->sector_size; } /* mid */ for(uint32_t i=0; i<sec_mid_num; i++) { flash_erase_sector(dev,start_addr); for (uint32_t j=0; j<16; j++) { flash_pageprogram(dev, buffer + (j<<dev->page_bits), start_addr + (j<<dev->page_bits), dev->page_size); } buffer += dev->sector_size; start_addr += dev->sector_size; } /* tail */ if(sec_tail > 0) { flash_read(dev,dev->buffer+sec_tail, start_addr+sec_tail, dev->sector_size - sec_tail); memcpy(dev->buffer,buffer,sec_tail); flash_erase_sector(dev,start_addr); for (uint32_t j=0; j<16; j++) { flash_pageprogram(dev, dev->buffer + (j<<dev->page_bits),start_addr + (j<<dev->page_bits), dev->page_size); } } return len; } flash.h #ifndef FLASH_H #define FLASH_H #ifdef __cplusplus extern "C" { #endif #include <stdint.h> typedef uint32_t (*flash_spi_io)(uint8_t* tx_buffer, uint8_t* rx_buffer, uint32_t len, int flag); /** * \struct flash_dev_st * FLASH结构. */ typedef struct { flash_spi_io spi_trans; /**< spi传输接口 */ void* buffer; /**< sector缓存 */ uint32_t sector_size; /**< sector大小 */ uint32_t sector_bits; /**< sector大小 位数 */ uint32_t page_size; /**< page大小 */ uint32_t page_bits; /**< page大小 位数 */ } flash_dev_st; /** * \fn flash_read * 读数据 * \param[in] dev \ref flash_dev_st * \param[in] addr 读开始地址 * \param[out] buffer 存储读出的数据 * \param[in] len 待读出的长度 * \retval 返回实际读出的数据长度 */ uint32_t flash_read(flash_dev_st* dev, uint8_t* buffer, uint32_t addr, uint32_t len); /** * \fn flash_write * 写数据 * \param[in] dev \ref flash_dev_st * \param[in] addr 写开始地址 * \param[out] buffer 存储待写的数据 * \param[in] len 待写入的长度 * \retval 返回实际写入的数据长度 */ uint32_t flash_write(flash_dev_st* dev, uint8_t* buffer, uint32_t addr, uint32_t len); #ifdef __cplusplus } #endif #endif   Flash_itf.c/h实现接口 flash_itf.c #include "flash_itf.h" #include "flash.h" #include "spi.h" static flash_dev_st s_flash; static uint8_t s_spiflash_buffer[4096]; static uint32_t spi_io(uint8_t* tx_buffer, uint8_t* rx_buffer, uint32_t len, int flag) { return spi_trans(0, 0, tx_buffer, rx_buffer, len, flag); } int flash_itf_init(void) { s_flash.spi_trans = spi_io; s_flash.page_bits = 8; s_flash.page_size = 256; s_flash.sector_bits = 12; s_flash.sector_size = 4096; s_flash.buffer = s_spiflash_buffer; return 0; } int flash_itf_deinit(void) { return 0; } uint32_t flash_itf_read(uint8_t* buffer, uint32_t addr, uint32_t len) { return flash_read(&s_flash, buffer, addr, len); } uint32_t flash_itf_write(uint8_t* buffer, uint32_t addr, uint32_t len) { return flash_write(&s_flash, buffer, addr, len); } flash_itf.h #ifndef FLASH_ITF_H #define FLASH_ITF_H #ifdef __cplusplus extern "C" { #endif #include <stdint.h> /** * \fn flash_itf_init * 初始化 */ int flash_itf_init(void); /** * \fn flash_itf_deinit * 反初始化 */ int flash_itf_deinit(void); /** * \fn flash_itf_read * 读数据 * \param[in] addr 读开始地址 * \param[out] buffer 存储读出的数据 * \param[in] len 待读出的长度 * \retval 返回实际读出的数据长度 */ uint32_t flash_itf_read(uint8_t* buffer, uint32_t addr, uint32_t len); /** * \fn flash_itf_write * 写数据 * \param[in] addr 写开始地址 * \param[out] buffer 存储待写的数据 * \param[in] len 待写入的长度 * \retval 返回实际写入的数据长度 */ uint32_t flash_itf_write(uint8_t* buffer, uint32_t addr, uint32_t len); #ifdef __cplusplus } #endif #endif   测试 shell_func.c中 #include "flash_itf.h" static void printflashfunc(uint8_t* param); static void writeflashfunc(uint8_t* param); 添加两行命令 { (uint8_t*)"printflash", printflashfunc, (uint8_t*)"printflash addr[hex] len"}, { (uint8_t*)"writeflash", writeflashfunc, (uint8_t*)"writeflash addr[hex] hexstr"}, 实现如下 static int ascii2uc(const char c, unsigned char *uc) { if ((c >= '0') && (c <= '9')) { *uc = c - '0'; } else if ((c >= 'a') && (c <= 'f')) { *uc = c - 'a' + 10; } else if ((c >= 'A') && (c <= 'F')) { *uc = c - 'A' + 10; } else { return -1; } return 0; } static uint32_t str2hex(const char* str, unsigned char *buff, uint32_t len) { uint32_t num = 0; uint8_t hex = 0; while(1) { uint8_t tmp1; uint8_t tmp2; if(ascii2uc(*str++, &tmp1) < 0) { break; } if(ascii2uc(*str++, &tmp2) < 0) { break; } hex = tmp1*16 + tmp2; *buff++ = hex; num++; if(num >= len) { break; } } return num; } static void printflashfunc(uint8_t* param) { uint8_t buffer[16]; uint32_t addr; uint32_t len; if(2 == sscanf((const char*)param, "%*s %x %d", &addr, &len)) { uint32_t toread; uint32_t read = 0; while(read < len) { toread = ((len-read) > sizeof(buffer)) ? sizeof(buffer) : (len-read); flash_itf_read(buffer, addr+read, toread); read += toread; for(uint32_t i=0; i<toread ;i++) { xprintf("%02x ",buffer); } xprintf("\r\n"); } } } static void writeflashfunc(uint8_t* param) { uint8_t buffer[32+1]; uint8_t hex[16];   uint32_t addr; uint32_t len; if(2 == sscanf((const char*)param, "%*s %x %s", &addr, buffer)) { len = str2hex((const char*)buffer, hex, strlen((char*)buffer)); if(len>0) { flash_itf_write(hex,addr,len); } } } Main.c中初始化 #include "spi.h" #include "flash_itf.h" spi_init(0, 36000000ul, 0); flash_itf_init(); 看到增加了两个命令 读 写 读 可以看到写入后读出正确。 总结 以上实现了SPI驱动基于SPI FLASH驱动,可以进行FLASH的读写了,后面就可以基于此移植文件系统了。

  • 发表了主题帖: 【国民技术高性能MCU N32H487开发板】标准输入输出和shell移植

    前言 前面实现了串口的收发,基于此继续移植shell和printf,方便后面调试使用。 移植printf 这里移植xprintf,一个精简的标准输入输出库。 参考公众号文章 https://mp.weixin.qq.com/s/y4MHV3cd4T0b51L5M4J5Xg 代码xprintf.c /*------------------------------------------------------------------------/ / Universal String Handler for Console Input and Output /-------------------------------------------------------------------------/ / / Copyright (C) 2021, ChaN, all right reserved. / / xprintf module is an open source software. Redistribution and use of / xprintf module in source and binary forms, with or without modification, / are permitted provided that the following condition is met: / / 1. Redistributions of source code must retain the above copyright notice, / this condition and the following disclaimer. / / This software is provided by the copyright holder and contributors "AS IS" / and any warranties related to this software are DISCLAIMED. / The copyright owner or contributors be NOT LIABLE for any damages caused / by use of this software. / /-------------------------------------------------------------------------*/ #include "xprintf.h" #define SZB_OUTPUT 32 #if XF_USE_OUTPUT #include <stdarg.h> void (*xfunc_output)(int); /* Pointer to the default output device */ static char *strptr; /* Pointer to the output memory (used by xsprintf) */ #if XF_USE_FP /*----------------------------------------------*/ /* Floating point output */ /*----------------------------------------------*/ #include <math.h> static int ilog10 (double n) /* Calculate log10(n) in integer output */ { int rv = 0; while (n >= 10) { /* Decimate digit in right shift */ if (n >= 100000) { n /= 100000; rv += 5; } else { n /= 10; rv++; } } while (n < 1) { /* Decimate digit in left shift */ if (n < 0.00001) { n *= 100000; rv -= 5; } else { n *= 10; rv--; } } return rv; } static double i10x (int n) /* Calculate 10^n */ { double rv = 1; while (n > 0) { /* Left shift */ if (n >= 5) { rv *= 100000; n -= 5; } else { rv *= 10; n--; } } while (n < 0) { /* Right shift */ if (n <= -5) { rv /= 100000; n += 5; } else { rv /= 10; n++; } } return rv; } static void ftoa ( char* buf, /* Buffer to output the generated string */ double val, /* Real number to output */ int prec, /* Number of fractinal digits */ char fmt /* Notation */ ) { int d; int e = 0, m = 0; char sign = 0; double w; const char *er = 0; if (isnan(val)) { /* Not a number? */ er = "NaN"; } else { if (prec < 0) prec = 6; /* Default precision (6 fractional digits) */ if (val < 0) { /* Nagative value? */ val = -val; sign = '-'; } else { sign = '+'; } if (isinf(val)) { /* Infinite? */ er = "INF"; } else { if (fmt == 'f') { /* Decimal notation? */ val += i10x(-prec) / 2; /* Round (nearest) */ m = ilog10(val); if (m < 0) m = 0; if (m + prec + 3 >= SZB_OUTPUT) er = "OV"; /* Buffer overflow? */ } else { /* E notation */ if (val != 0) { /* Not a true zero? */ val += i10x(ilog10(val) - prec) / 2; /* Round (nearest) */ e = ilog10(val); if (e > 99 || prec + 6 >= SZB_OUTPUT) { /* Buffer overflow or E > +99? */ er = "OV"; } else { if (e < -99) e = -99; val /= i10x(e); /* Normalize */ } } } } if (!er) { /* Not error condition */ if (sign == '-') *buf++ = sign; /* Add a - if negative value */ do { /* Put decimal number */ w = i10x(m); /* Snip the highest digit d */ d = val / w; val -= d * w; if (m == -1) *buf++ = XF_DPC; /* Insert a decimal separarot if get into fractional part */ *buf++ = '0' + d; /* Put the digit */ } while (--m >= -prec); /* Output all digits specified by prec */ if (fmt != 'f') { /* Put exponent if needed */ *buf++ = fmt; if (e < 0) { e = -e; *buf++ = '-'; } else { *buf++ = '+'; } *buf++ = '0' + e / 10; *buf++ = '0' + e % 10; } } } if (er) { /* Error condition? */ if (sign) *buf++ = sign; /* Add sign if needed */ do *buf++ = *er++; while (*er); /* Put error symbol */ } *buf = 0; /* Term */ } #endif /* XF_USE_FLOAT */ /*----------------------------------------------*/ /* Put a character */ /*----------------------------------------------*/ void xputc ( int chr /* Character to be output */ ) { xfputc(xfunc_output, chr); /* Output it to the default output device */ } void xfputc ( /* Put a character to the specified device */ void(*func)(int), /* Pointer to the output function (null:strptr) */ int chr /* Character to be output */ ) { if (XF_CRLF && chr == '\n') xfputc(func, '\r'); /* CR -> CRLF */ if (func) { func(chr); /* Write a character to the output device */ } else if (strptr) { *strptr++ = chr; /* Write a character to the memory */ } } /*----------------------------------------------*/ /* Put a null-terminated string */ /*----------------------------------------------*/ void xputs ( /* Put a string to the default device */ const char* str /* Pointer to the string */ ) { xfputs(xfunc_output, str); } void xfputs ( /* Put a string to the specified device */ void(*func)(int), /* Pointer to the output function */ const char* str /* Pointer to the string */ ) { while (*str) { /* Put the string */ xfputc(func, *str++); } } /*----------------------------------------------*/ /* Formatted string output */ /*----------------------------------------------*/ /* xprintf("%d", 1234); "1234" xprintf("%6d,%3d%%", -200, 5); " -200, 5%" xprintf("%-6u", 100); "100 " xprintf("%ld", 12345678); "12345678" xprintf("%llu", 0x100000000); "4294967296" <XF_USE_LLI> xprintf("%lld", -1LL); "-1" <XF_USE_LLI> xprintf("%04x", 0xA3); "00a3" xprintf("%08lX", 0x123ABC); "00123ABC" xprintf("%016b", 0x550F); "0101010100001111" xprintf("%*d", 6, 100); " 100" xprintf("%s", "String"); "String" xprintf("%5s", "abc"); " abc" xprintf("%-5s", "abc"); "abc " xprintf("%-5s", "abcdefg"); "abcdefg" xprintf("%-5.5s", "abcdefg"); "abcde" xprintf("%-.5s", "abcdefg"); "abcde" xprintf("%-5.5s", "abc"); "abc " xprintf("%c", 'a'); "a" xprintf("%12f", 10.0); " 10.000000" <XF_USE_FP> xprintf("%.4E", 123.45678); "1.2346E+02" <XF_USE_FP> */ static void xvfprintf ( void(*func)(int), /* Pointer to the output function */ const char* fmt, /* Pointer to the format string */ va_list arp /* Pointer to arguments */ ) { unsigned int r, i, j, w, f; int n, prec; char str[SZB_OUTPUT], c, d, *p, pad; #if XF_USE_LLI long long v; unsigned long long uv; #else long v; unsigned long uv; #endif for (;;) { c = *fmt++; /* Get a format character */ if (!c) break; /* End of format? */ if (c != '%') { /* Pass it through if not a % sequense */ xfputc(func, c); continue; } f = w = 0; /* Clear parms */ pad = ' '; prec = -1; c = *fmt++; /* Get first char of the sequense */ if (c == '0') { /* Flag: left '0' padded */ pad = '0'; c = *fmt++; } else { if (c == '-') { /* Flag: left justified */ f = 2; c = *fmt++; } } if (c == '*') { /* Minimum width from an argument */ n = va_arg(arp, int); if (n < 0) { /* Flag: left justified */ n = 0 - n; f = 2; } w = n; c = *fmt++; } else { while (c >= '0' && c <= '9') { /* Minimum width */ w = w * 10 + c - '0'; c = *fmt++; } } if (c == '.') { /* Precision */ c = *fmt++; if (c == '*') { /* Precision from an argument */ prec = va_arg(arp, int); c = *fmt++; } else { prec = 0; while (c >= '0' && c <= '9') { prec = prec * 10 + c - '0'; c = *fmt++; } } } if (c == 'l') { /* Prefix: Size is long */ f |= 4; c = *fmt++; #if XF_USE_LLI if (c == 'l') { /* Prefix: Size is long long */ f |= 8; c = *fmt++; } #endif } if (!c) break; /* End of format? */ switch (c) { /* Type is... */ case 'b': /* Unsigned binary */ r = 2; break; case 'o': /* Unsigned octal */ r = 8; break; case 'd': /* Signed decimal */ case 'u': /* Unsigned decimal */ r = 10; break; case 'x': /* Hexdecimal (lower case) */ case 'X': /* Hexdecimal (upper case) */ r = 16; break; case 'c': /* A character */ xfputc(func, (char)va_arg(arp, int)); continue; case 's': /* String */ p = va_arg(arp, char*); /* Get a pointer argument */ if (!p) p = ""; /* Null ptr generates a null string */ j = strlen(p); if (prec >= 0 && j > (unsigned int)prec) j = prec; /* Limited length of string body */ for ( ; !(f & 2) && j < w; j++) xfputc(func, pad); /* Left pads */ while (*p && prec--) xfputc(func, *p++);/* String body */ while (j++ < w) xfputc(func, ' '); /* Right pads */ continue; #if XF_USE_FP case 'f': /* Float (decimal) */ case 'e': /* Float (e) */ case 'E': /* Float (E) */ ftoa(p = str, va_arg(arp, double), prec, c); /* Make fp string */ for (j = strlen(p); !(f & 2) && j < w; j++) xfputc(func, pad); /* Left pads */ while (*p) xfputc(func, *p++); /* Value */ while (j++ < w) xfputc(func, ' '); /* Right pads */ continue; #endif default: /* Unknown type (passthrough) */ xfputc(func, c); continue; } /* Get an integer argument and put it in numeral */ #if XF_USE_LLI if (f & 8) { /* long long argument? */ v = (long long)va_arg(arp, long long); } else { if (f & 4) { /* long argument? */ v = (c == 'd') ? (long long)va_arg(arp, long) : (long long)va_arg(arp, unsigned long); } else { /* int/short/char argument */ v = (c == 'd') ? (long long)va_arg(arp, int) : (long long)va_arg(arp, unsigned int); } } #else if (f & 4) { /* long argument? */ v = (long)va_arg(arp, long); } else { /* int/short/char argument */ v = (c == 'd') ? (long)va_arg(arp, int) : (long)va_arg(arp, unsigned int); } #endif if (c == 'd' && v < 0) { /* Negative value? */ v = 0 - v; f |= 1; } i = 0; uv = v; do { /* Make an integer number string */ d = (char)(uv % r); uv /= r; if (d > 9) d += (c == 'x') ? 0x27 : 0x07; str[i++] = d + '0'; } while (uv != 0 && i < sizeof str); if (f & 1) str[i++] = '-'; /* Sign */ for (j = i; !(f & 2) && j < w; j++) xfputc(func, pad); /* Left pads */ do xfputc(func, str[--i]); while (i != 0); /* Value */ while (j++ < w) xfputc(func, ' '); /* Right pads */ } } void xprintf ( /* Put a formatted string to the default device */ const char* fmt, /* Pointer to the format string */ ... /* Optional arguments */ ) { va_list arp; va_start(arp, fmt); xvfprintf(xfunc_output, fmt, arp); va_end(arp); } void xfprintf ( /* Put a formatted string to the specified device */ void(*func)(int), /* Pointer to the output function */ const char* fmt, /* Pointer to the format string */ ... /* Optional arguments */ ) { va_list arp; va_start(arp, fmt); xvfprintf(func, fmt, arp); va_end(arp); } void xsprintf ( /* Put a formatted string to the memory */ char* buff, /* Pointer to the output buffer */ const char* fmt, /* Pointer to the format string */ ... /* Optional arguments */ ) { va_list arp; strptr = buff; /* Enable destination for memory */ va_start(arp, fmt); xvfprintf(0, fmt, arp); va_end(arp); *strptr = 0; /* Terminate output string */ strptr = 0; /* Disable destination for memory */ } #if XF_USE_DUMP /*----------------------------------------------*/ /* Dump a line of binary dump */ /*----------------------------------------------*/ void put_dump ( const void* buff, /* Pointer to the array to be dumped */ unsigned long addr, /* Heading address value */ int len, /* Number of items to be dumped */ size_t width /* Size of buff[0] (1, 2 or 4) */ ) { int i; const unsigned char *bp; const unsigned short *sp; const unsigned long *lp; xprintf("%08lX ", addr); /* address */ switch (width) { case sizeof (char): bp = buff; for (i = 0; i < len; i++) { /* Hexdecimal dump in (char) */ xprintf(" %02X", bp[i]); } xputs(" "); for (i = 0; i < len; i++) { /* ASCII dump */ xputc((unsigned char)((bp[i] >= ' ' && bp[i] <= '~') ? bp[i] : '.')); } break; case sizeof (short): sp = buff; do { /* Hexdecimal dump in (short) */ xprintf(" %04X", *sp++); } while (--len); break; case sizeof (long): lp = buff; do { /* Hexdecimal dump in (short) */ xprintf(" %08lX", *lp++); } while (--len); break; } xputc('\n'); } #endif /* XF_USE_DUMP */ #endif /* XF_USE_OUTPUT */ #if XF_USE_INPUT int (*xfunc_input)(void); /* Pointer to the default input stream */ /*----------------------------------------------*/ /* Get a line from the input */ /*----------------------------------------------*/ int xgets ( /* 0:End of stream, 1:A line arrived */ char* buff, /* Pointer to the buffer */ int len /* Buffer length */ ) { int c, i; if (!xfunc_input) return 0; /* No input function is specified */ i = 0; for (;;) { c = xfunc_input(); /* Get a char from the incoming stream */ if (c < 0 || c == '\r') break; /* End of stream or CR? */ if (c == '\b' && i) { /* BS? */ i--; if (XF_INPUT_ECHO) xputc(c); continue; } if (c >= ' ' && i < len - 1) { /* Visible chars? */ buff[i++] = c; if (XF_INPUT_ECHO) xputc(c); } } if (XF_INPUT_ECHO) { xputc('\r'); xputc('\n'); } buff[i] = 0; /* Terminate with a \0 */ return (int)(c == '\r'); } /*----------------------------------------------*/ /* Get a value of integer string */ /*----------------------------------------------*/ /* "123 -5 0x3ff 0b1111 0377 w " ^ 1st call returns 123 and next ptr ^ 2nd call returns -5 and next ptr ^ 3rd call returns 1023 and next ptr ^ 4th call returns 15 and next ptr ^ 5th call returns 255 and next ptr ^ 6th call fails and returns 0 */ int xatoi ( /* 0:Failed, 1:Successful */ char **str, /* Pointer to pointer to the string */ long *res /* Pointer to the valiable to store the value */ ) { unsigned long val; unsigned char c, r, s = 0; *res = 0; while ((c = **str) == ' ') (*str)++; /* Skip leading spaces */ if (c == '-') { /* negative? */ s = 1; c = *(++(*str)); } if (c == '0') { c = *(++(*str)); switch (c) { case 'x': /* hexdecimal */ r = 16; c = *(++(*str)); break; case 'b': /* binary */ r = 2; c = *(++(*str)); break; default: if (c <= ' ') return 1; /* single zero */ if (c < '0' || c > '9') return 0; /* invalid char */ r = 8; /* octal */ } } else { if (c < '0' || c > '9') return 0; /* EOL or invalid char */ r = 10; /* decimal */ } val = 0; while (c > ' ') { if (c >= 'a') c -= 0x20; c -= '0'; if (c >= 17) { c -= 7; if (c <= 9) return 0; /* invalid char */ } if (c >= r) return 0; /* invalid char for current radix */ val = val * r + c; c = *(++(*str)); } if (s) val = 0 - val; /* apply sign if needed */ *res = val; return 1; } #if XF_USE_FP /*----------------------------------------------*/ /* Get a value of the real number string */ /*----------------------------------------------*/ /* Float version of xatoi */ int xatof ( /* 0:Failed, 1:Successful */ char **str, /* Pointer to pointer to the string */ double *res /* Pointer to the valiable to store the value */ ) { double val; int s, f, e; unsigned char c; *res = 0; s = f = 0; while ((c = **str) == ' ') (*str)++; /* Skip leading spaces */ if (c == '-') { /* Negative? */ c = *(++(*str)); s = 1; } else if (c == '+') { /* Positive? */ c = *(++(*str)); } if (c == XF_DPC) { /* Leading dp? */ f = -1; /* Start at fractional part */ c = *(++(*str)); } if (c <= ' ') return 0; /* Wrong termination? */ val = 0; while (c > ' ') { /* Get a value of decimal */ if (c == XF_DPC) { /* Embedded dp? */ if (f < 0) return 0; /* Wrong dp? */ f = -1; /* Enter fractional part */ } else { if (c < '0' || c > '9') break; /* End of decimal? */ c -= '0'; if (f == 0) { /* In integer part */ val = val * 10 + c; } else { /* In fractional part */ val += i10x(f--) * c; } } c = *(++(*str)); } if (c > ' ') { /* It may be an exponent */ if (c != 'e' && c != 'E') return 0; /* Wrong character? */ c = *(++(*str)); if (c == '-') { c = *(++(*str)); s |= 2; /* Negative exponent */ } else if (c == '+') { c = *(++(*str)); /* Positive exponent */ } if (c <= ' ') return 0; /* Wrong termination? */ e = 0; while (c > ' ') { /* Get value of exponent */ c -= '0'; if (c > 9) return 0; /* Not a numeral? */ e = e * 10 + c; c = *(++(*str)); } val *= i10x((s & 2) ? -e : e); /* Apply exponent */ } if (s & 1) val = -val; /* Negate sign if needed */ *res = val; return 1; } #endif /* XF_USE_FP */ #endif /* XF_USE_INPUT */   Xprintf.h /*------------------------------------------------------------------------*/ /* Universal string handler for user console interface (C)ChaN, 2021 */ /*------------------------------------------------------------------------*/ #ifndef XPRINTF_DEF #define XPRINTF_DEF #include <string.h> #ifdef __cplusplus extern "C" { #endif #define XF_USE_OUTPUT 1 /* 1: Enable output functions */ #define XF_CRLF 1 /* 1: Convert \n ==> \r\n in the output char */ #define XF_USE_DUMP 1 /* 1: Enable put_dump function */ #define XF_USE_LLI 1 /* 1: Enable long long integer in size prefix ll */ #define XF_USE_FP 1 /* 1: Enable support for floating point in type e and f */ #define XF_DPC '.' /* Decimal separator for floating point */ #define XF_USE_INPUT 1 /* 1: Enable input functions */ #define XF_INPUT_ECHO 0 /* 1: Echo back input chars in xgets function */ #if defined(__GNUC__) && __GNUC__ >= 10 #pragma GCC diagnostic ignored "-Wcast-function-type" #endif #if XF_USE_OUTPUT #define xdev_out(func) xfunc_output = (void(*)(int))(func) extern void (*xfunc_output)(int); void xputc (int chr); void xfputc (void (*func)(int), int chr); void xputs (const char* str); void xfputs (void (*func)(int), const char* str); void xprintf (const char* fmt, ...); void xsprintf (char* buff, const char* fmt, ...); void xfprintf (void (*func)(int), const char* fmt, ...); void put_dump (const void* buff, unsigned long addr, int len, size_t width); #endif #if XF_USE_INPUT #define xdev_in(func) xfunc_input = (int(*)(void))(func) extern int (*xfunc_input)(void); int xgets (char* buff, int len); int xatoi (char** str, long* res); int xatof (char** str, double* res); #endif #ifdef __cplusplus } #endif #endif   适配接口 static void xprintf_out_port(int ch) { uint8_t val = ch; uart_send(0,&val,1); } static int xprintf_in_port(void) { uint32_t len; uint8_t val; do { len = uart_read(0,&val,1); }while(len == 0); return val; } 初始化指定接口 #include "xprintf.h" xdev_out(xprintf_out_port); xdev_in(xprintf_in_port); 移植shell 参考公众号文章 https://mp.weixin.qq.com/s/XLmbJn0SKoDT1aLdxHDrbg 适配接口 #include "shell.h" #include "shell_func.h" uint32_t shell_read(uint8_t *buff, uint32_t len) { return uart_read(0,buff,len); } void shell_write(uint8_t *buff, uint32_t len) { uart_send(0,buff,len); } shell_set_itf(shell_read, shell_write, (shell_cmd_cfg*)g_shell_cmd_list_ast, 1); 代码 Shell.c #include <stdint.h> #include "shell.h" shell_read_pf s_input_pf = 0; /* 输入接口指针 */ shell_write_pf s_output_pf = 0; /* 输出接口指针 */ shell_cmd_cfg* s_cmd_cfg_pst = 0; /* 命令列表指针 */ uint8_t s_enableecho_u8 = 0; /* 是否使能echo标志 */ static uint8_t s_cmd_buf_au8[SHELL_CMD_LEN]="\r"; /* 命令缓冲区 */ static uint32_t s_cmd_buf_index_u32 = 0; /* 当前命令缓冲区中字符数 */ /** * 输出字符接口 */ static void shell_putchar(uint8_t val) { uint8_t tmp; if(s_output_pf != 0) { tmp = val; s_output_pf(&tmp, 1); } } /** * 输出字符串接口 */ static void shell_putstring(char* str) { uint32_t len = 0; uint8_t*p = (uint8_t*)str; while(*str++) { len++; } s_output_pf(p, len); } /** * 读字符接口 */ static int shell_getchar(uint8_t *data) { if(s_input_pf == 0) { return -1; } if(0 == s_input_pf(data, 1)) { return -1; } else { return 0; } } /** * 判断命令字符串的长度 * 命令字符串不能有空格 */ static uint32_t shell_cmd_len(uint8_t *cmd) { uint8_t *p = cmd; uint32_t len = 0; while((*p != ' ') && (*p != 0)) { p++; len++; } return len; } /** * 判断两个字符串是否相等,相等返回0 */ static int shell_cmd_check(uint8_t *cmd, uint8_t *str) { uint32_t len1 = shell_cmd_len(cmd); uint32_t len2 = shell_cmd_len(str); if(len1 != len2) { return -1; } for(uint32_t i=0; i<len1; i++) { if(*cmd++ != *str++) { return -1; } } return 0; } /** * 读取一行命令 */ static uint32_t shell_read_line(void) { uint8_t ch; uint32_t count; /* 初始打印sh> */ if(s_cmd_buf_au8[0]=='\r') { shell_putstring("sh>\r\n"); s_cmd_buf_au8[0] = 0; } /* 非阻塞读取一个字符 */ if(shell_getchar(&ch) !=0 ) { return 0; } /* 遇到除了退格之外的不可打印字符,则认为收到一行命令 * 退格需要单独处理,需要删除一个字符 */ if((ch == '\r' || ch == '\n' || ch < ' ' || ch > '~') && (ch != '\b')) { if(s_cmd_buf_index_u32==0) { /* 缓冲区没有数据就收到了非打印字符串,则打印提示sh> */ shell_putstring("sh>\r\n"); } else { /* 收到了非打印字符,且缓冲区有数据则认为收到了一行 * 返回缓冲区数据长度,并清零计数,打印回车换行 * 并且添加结束符0 */ count = s_cmd_buf_index_u32; s_cmd_buf_au8[s_cmd_buf_index_u32]=0; s_cmd_buf_index_u32 =0; shell_putstring("\r\n"); return count; } } else { if(ch == '\b') { /* 退格处理,注意只有有数据才会删除一个字符,添加结束符 */ if(s_cmd_buf_index_u32 != 0) { s_cmd_buf_index_u32--; shell_putchar('\b'); shell_putchar(' '); shell_putchar('\b'); s_cmd_buf_au8[s_cmd_buf_index_u32]= '\0'; } } else { /* 可打印字符,添加到缓冲区 * 如果数据量已经到了缓冲区大小-1,则也认为是一行命令 * -1是保证最后有结束符0空间 */ if(s_enableecho_u8 != 0) { shell_putchar(ch); } s_cmd_buf_au8[s_cmd_buf_index_u32++] = ch; if(s_cmd_buf_index_u32>=(sizeof(s_cmd_buf_au8)-1)) { count = s_cmd_buf_index_u32; s_cmd_buf_au8[s_cmd_buf_index_u32]=0; s_cmd_buf_index_u32 =0; shell_putstring("\r\n"); return count; } } } return 0; } /** * 搜寻命令列表处理命令 */ static int shell_exec_cmdlist(uint8_t* cmd) { int i; if(s_cmd_cfg_pst == 0) { return -1; } for (i=0; s_cmd_cfg_pst[i].name != 0; i++) { if (shell_cmd_check(cmd, s_cmd_cfg_pst[i].name) == 0) { s_cmd_cfg_pst[i].func(cmd); return 0; } } if(s_cmd_cfg_pst[i].name == 0) { shell_putstring("unkown command\r\n"); return -1; } return 0; } /** * 对外接口,周期执行 */ void shell_exec(void) { if(shell_read_line() > 0) { shell_exec_cmdlist(s_cmd_buf_au8); } } /** * 对外接口,初始化配置接口 */ void shell_set_itf(shell_read_pf input, shell_write_pf output, shell_cmd_cfg* cmd_list, uint8_t enableecho) { s_input_pf = input; s_output_pf = output; s_cmd_cfg_pst = cmd_list; s_enableecho_u8 = enableecho; }   Shell.h #ifndef SHELL_H #define SHELL_H #ifdef __cplusplus extern "C" { #endif #include <stdint.h> #define SHELL_CMD_LEN 64 /**< 命令缓冲区大小 */ typedef void (*shell_command_pf)(uint8_t *); /**< 命令回调函数 */ typedef uint32_t (*shell_read_pf)(uint8_t *buff, uint32_t len); /**< 底层收接口 */ typedef void (*shell_write_pf)(uint8_t *buff, uint32_t len); /**< 底层发接口 */ /** * \struct shell_cmd_cfg * 命令信息 */ typedef struct { uint8_t * name; /**< 命令字符串 */ shell_command_pf func; /**< 命令回调函数 */ uint8_t * helpstr; /**< 命令帮助信息 */ }shell_cmd_cfg; /** * \fn shell_exec * 周期调用该函数,读取底层输入,并判断是否有命令进行处理 * 非阻塞 */ void shell_exec(void); /** * \fn shell_set_itf * 设置底层输入输出接口,以及命令列表 * 调用shell_exec_shellcmd之前,需要先调用该接口初始化 * \param[in] input \ref shell_read_pf 输入接口 * \param[in] output \ref shell_write_pf 输出接口 * \param[in] cmd_list \ref shell_cmd_cfg 命令列表 * \param[in] enableecho 0:不使能回显, 其他值:使能回显 */ void shell_set_itf(shell_read_pf input, shell_write_pf output, shell_cmd_cfg* cmd_list, uint8_t enableecho); #ifdef __cplusplus } #endif #endif   Shell_func.c #include <stdio.h> #include "shell.h" #include "shell_func.h" #include "xprintf.h" #include "uart.h" static void helpfunc(uint8_t* param); /** * 最后一行必须为0,用于结束判断 */ const shell_cmd_cfg g_shell_cmd_list_ast[ ] = { { (uint8_t*)"help", helpfunc, (uint8_t*)"help"}, { (uint8_t*)0, 0 , 0}, }; static void helpfunc(uint8_t* param) { (void)param; unsigned int i; xprintf("\r\n"); xprintf("**************\r\n"); xprintf("* SHELL *\r\n"); xprintf("* V1.0 *\r\n"); xprintf("**************\r\n"); xprintf("\r\n"); for (i=0; g_shell_cmd_list_ast[i].name != 0; i++) { xprintf("%02d.",i); xprintf("%-16s",g_shell_cmd_list_ast[i].name); xprintf("%s\r\n",g_shell_cmd_list_ast[i].helpstr); } }   Shell_func.h #ifndef SHELL_FUNC_H #define SHELL_FUNC_H #include <stdint.h> #ifdef __cplusplus extern "C" { #endif extern const shell_cmd_cfg g_shell_cmd_list_ast[ ]; #ifdef __cplusplus } #endif #endif   测试 周期调用 shell_exec(); 串口终端,输入help可以查看命令 总结 以上移植了标准输入输出接口,移植了shell,可以方便的增加命令,打印输出,进行调试了。

  • 发表了主题帖: 【国民技术高性能MCU N32H487开发板】串口驱动与测试

    前言 本文来测试串口收发,并基于fifo实现串口驱动,提供方便使用的串口读写接口。方便后续调试开发。   FIFO实现参考公众号文章 https://mp.weixin.qq.com/s/MvL9eDesyuxD60fnbl1nag 串口驱动实现参考上述公众号文章其他文章   引脚 使用PA9和PA10,连接到了板载的仿真器 串口初始化 引脚 PA9 AF17 TX PA10 AF18 RX 引脚配置,时钟使能,串口配置,中断配置 RCC_EnableAHB1PeriphClk(RCC_AHB_PERIPHEN_GPIOA,ENABLE); GPIO_InitType GPIO_InitStructure; /* Initialize GPIO_InitStructure */ GPIO_InitStruct(&GPIO_InitStructure); /* Configure USART3 Tx PA9 AF17 as alternate function push-pull */ GPIO_InitStructure.Pin = GPIO_PIN_9; GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP; GPIO_InitStructure.GPIO_Alternate = GPIO_AF17; GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP; GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);   /* Configure USART3 Rx PA10 AF18 as alternate function push-pull */ GPIO_InitStructure.Pin = GPIO_PIN_10; GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP; GPIO_InitStructure.GPIO_Alternate = GPIO_AF18; GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP; GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);   RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_USART3,ENABLE); USART_InitType USART_InitStructure; /* USARTy and USARTz configuration */ USART_StructInit(&USART_InitStructure); USART_InitStructure.BaudRate = baud; USART_InitStructure.WordLength = USART_WL_8B; USART_InitStructure.StopBits = USART_STPB_1; USART_InitStructure.Parity = USART_PE_NO; USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE; USART_InitStructure.OverSampling = USART_16OVER; USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX; /* Configure USART3 */ USART_Init(USART3, &USART_InitStructure); /* Enable the USART3 */ USART_Enable(USART3, ENABLE);   USART_ConfigInt(USART3, USART_INT_RXDNE, ENABLE); NVIC_SetPriority(USART3_IRQn,2); NVIC_EnableIRQ(USART3_IRQn); 中断服务程序 收到数据写入fifo,并清除标志 void USART3_IRQHandler(void) { uint8_t ch; ch = USART_ReceiveData(USART3); USART_ClrFlag(USART3, USART_FLAG_RXDNE); USART_ClrFlag(USART3, USART_FLAG_IDLEF); USART_ClrFlag(USART3, USART_FLAG_OREF); uart_rx_cb(0, &ch, 1); } 发送 查询发送 uint32_t uart_send(int id, uint8_t* buffer, uint32_t len) { if(id == 0){ for(uint32_t i=0;i<len;i++) { while(USART_GetFlagStatus(USART3, USART_FLAG_TXC) == 0); USART_SendData(USART3,buffer); } }else if(id == 1){ } return len; } 测试 Main.c中 #include "uart.h" 收到数据原样返回 int main(void) { uart_init(0,115200); while (1) { uint8_t rx_buffer[64]; uint32_t len = uart_read(0,rx_buffer,sizeof(rx_buffer)); if(len > 0){ uart_send(0,rx_buffer,len); } } } 上位机发送数据,板子原样返回 完整代码 Fifo.c #include <string.h> #include "fifo.h" #define FIFO_PARAM_CHECK 0 /** * in为写入索引 0~(buffer_len-1)。 * out为读出索引 0~(buffer_len-1)。 * in == out时可能是满,也可能是空,可以通过len有效数据长度来确认。 * 写数据in增加,直到追赶到out则满。 * 读数据则out增加,直到追赶到in则空。 * in大于out时则[out,in)区间是有效数据。 * in小于out时则[out,buffer_len)和[0,in)区间是有效数据。 *********************************************************** * 0 buffer_len-1 buffer_len * (1)开始 in和out都是0 * | | * in(0) * out(0) * len = 0 * (2)写入n字节数据 in变为n和out还是0 对应in大于out的情况 * | | * out(0)————————————>in(n) | * len = n * (3)读出m字节数据(m<n) in还是n和out变为m 对应in大于out的情况 * | | * out(m)————>in(n) * len = n-m * (4)继续写入数据,绕回到开头,对应in小于out的情况 * | | * out(m)————————————————————————————————> * ——>in(k) * len = k + buffer_len-m */ uint32_t fifo_in(fifo_st* dev, uint8_t* buffer, uint32_t len) { uint32_t space = 0; /* 用于记录空闲空间大小 */ /* 参数检查 */ #if FIFO_PARAM_CHECK if((dev == 0) || (buffer == 0) || (len == 0)) { return 0; } if(dev->buffer == 0) { return 0; } #endif /* 限制len的最大长度为buffer大小 */ if(len > dev->buffer_len) { len = dev->buffer_len; } /* 计算空闲空间大小 * 正常dev->len不应该大于dev->buffer_len */ if(dev->buffer_len >= dev->len) { space = dev->buffer_len - dev->len; } else { /* 这里不应该出现, 出现则是异常 */ dev->len = 0; space = dev->buffer_len; } /* 计算待写入大小, 如果len大于剩余空间则只写入剩余空间大小 */ len = (len >= space) ? space : len; if(len == 0) { return 0; /* 这里有可能无剩余空间,直接返回 */ } /* 计算len的长度是否需要有绕回,需要分次写入 */ space = dev->buffer_len - dev->in; /* 当前写入位置in到缓存末尾剩余可写入空间 */ if(space >= len) { /* 当前写入位置in到缓存末尾足够一次写入 */ memcpy(dev->buffer+dev->in,buffer,len); } else { /* 当前写入位置in到缓存末尾不够,还需要绕回到前面写 */ memcpy(dev->buffer+dev->in,buffer,space); /* 先写入tail部分 */ memcpy(dev->buffer,buffer+space,len-space); /* 再写入绕回头部分 */ } /* 更新写入索引和有效数据长度 */ dev->in += len; if(dev->in >= dev->buffer_len) { dev->in -= dev->buffer_len; /* 判断加减法 替代 dev->in %= dev->buffer->len */ } dev->len += len; /* dev->len最大dev->buffer->len,无需%= dev->buffer->len */ return len; } uint32_t fifo_out(fifo_st* dev, uint8_t* buffer, uint32_t len) { uint32_t space = 0; /* 参数检查 */ #if FIFO_PARAM_CHECK if((dev == 0) || (buffer == 0) || (len == 0)) { return 0; } if(dev->buffer == 0) { return 0; } #endif /* 判断是否有数据 */ if(dev->len == 0) { return 0; } /* 可读出数据量取需要的和有的之间的小值 */ len = (dev->len) > len ? len : dev->len; /* 计算len的长度是否需要有绕回,需要分次读出 */ space = dev->buffer_len - dev->out; /* 当前读出位置out到缓存末尾剩余可读出空间 */ if(space >= len) { /* 当前读出位置out到缓存末尾足够一次读出 */ memcpy(buffer,dev->buffer+dev->out,len); } else { /* 当前读出位置out到缓存末尾不够,还需要绕回到前面读 */ memcpy(buffer,dev->buffer+dev->out,space); /* 先读出tail部分 */ memcpy(buffer+space,dev->buffer,len-space); /* 再读出绕回头部分 */ } /* 更新读出索引和有效数据长度 */ dev->out += len; if(dev->out >= dev->buffer_len) { dev->out -= dev->buffer_len; /* 判断加减法 替代 dev->out %= dev->buffer->len */ } dev->len -= len; /* 这里dev->len 不可能小于len,不会溢出 */ return len; } uint32_t fifo_getlen(fifo_st* dev) { #if FIFO_PARAM_CHECK if(dev == 0) { return 0; } #endif return dev->len; } void fifo_clean(fifo_st* dev) { #if FIFO_PARAM_CHECK if(dev == 0) { return 0; } #endif dev->len = 0; dev->in = 0; dev->out = 0; } uint32_t fifo_getfree(fifo_st* dev) { if(dev == 0) { return 0; } return dev->buffer_len - dev->len; }   Fifo.h #ifndef FIFO_H #define FIFO_H #ifdef __cplusplus extern "C" { #endif #include <stdint.h> /** * \struct fifo_st * FIFO缓冲区结构. */ typedef struct { uint32_t in; /**< 写入索引 */ uint32_t out; /**< 读出索引 */ uint32_t len; /**< 有效数据长度 */ uint32_t buffer_len; /**< 有效长度 */ uint8_t* buffer; /**< 缓存,用户分配 */ } fifo_st; /** * \fn fifo_in * 往fifo里写数据 * \param[in] dev \ref fifo_st * \param[in] buffer 待写入的数据 * \param[in] len 待写入的长度 * \retval 返回实际写入的数据量 */ uint32_t fifo_in(fifo_st* dev, uint8_t* buffer, uint32_t len); /** * \fn fifo_out * 从fifo读出数据 * \param[in] dev \ref fifo_st * \param[in] buffer 存读出的数据 * \param[in] len 需要读出的数据长度 * \retval 返回实际读出的数据量 */ uint32_t fifo_out(fifo_st* dev, uint8_t* buffer, uint32_t len); uint32_t fifo_getlen(fifo_st* dev); void fifo_clean(fifo_st* dev); uint32_t fifo_getfree(fifo_st* dev); #ifdef __cplusplus } #endif #endif   Uart.c #include "uart.h" #include "fifo.h" #include "n32h47x_48x.h" #include "n32h47x_48x_rcc.h" #include "n32h47x_48x_gpio.h" #include "n32h47x_48x_exti.h" #include "n32h47x_48x_usart.h" #include "n32h47x_48x_dma.h" #define CriticalAlloc() #define EnterCritical() __disable_irq() #define ExitCritical() __enable_irq() uint8_t s_uart_rx0_buffer[1029]; uint8_t s_uart_rx1_buffer[16]; static fifo_st s_uart_fifo_dev[2]= { { .in = 0, .len = 0, .out = 0, .buffer = s_uart_rx0_buffer, .buffer_len = sizeof(s_uart_rx0_buffer), }, { .in = 0, .len = 0, .out = 0, .buffer = s_uart_rx1_buffer, .buffer_len = sizeof(s_uart_rx1_buffer), } }; void uart_rx_cb(int id, uint8_t* buff, uint32_t len) { fifo_in(&(s_uart_fifo_dev[id]), buff, len); } void USART3_IRQHandler(void) { uint8_t ch; ch = USART_ReceiveData(USART3); USART_ClrFlag(USART3, USART_FLAG_RXDNE); USART_ClrFlag(USART3, USART_FLAG_IDLEF); USART_ClrFlag(USART3, USART_FLAG_OREF); uart_rx_cb(0, &ch, 1); } void uart_init(int id, uint32_t baud) { if(id == 0){ RCC_EnableAHB1PeriphClk(RCC_AHB_PERIPHEN_GPIOA,ENABLE); GPIO_InitType GPIO_InitStructure; /* Initialize GPIO_InitStructure */ GPIO_InitStruct(&GPIO_InitStructure); /* Configure USART3 Tx PA9 AF17 as alternate function push-pull */ GPIO_InitStructure.Pin = GPIO_PIN_9; GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP; GPIO_InitStructure.GPIO_Alternate = GPIO_AF17; GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP; GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure); /* Configure USART3 Rx PA10 AF18 as alternate function push-pull */ GPIO_InitStructure.Pin = GPIO_PIN_10; GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP; GPIO_InitStructure.GPIO_Alternate = GPIO_AF18; GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP; GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure); RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_USART3,ENABLE); USART_InitType USART_InitStructure; /* USARTy and USARTz configuration */ USART_StructInit(&USART_InitStructure); USART_InitStructure.BaudRate = baud; USART_InitStructure.WordLength = USART_WL_8B; USART_InitStructure.StopBits = USART_STPB_1; USART_InitStructure.Parity = USART_PE_NO; USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE; USART_InitStructure.OverSampling = USART_16OVER; USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX; /* Configure USART3 */ USART_Init(USART3, &USART_InitStructure); /* Enable the USART3 */ USART_Enable(USART3, ENABLE); USART_ConfigInt(USART3, USART_INT_RXDNE, ENABLE); NVIC_SetPriority(USART3_IRQn,2); NVIC_EnableIRQ(USART3_IRQn); }else if(id == 1){ } } uint32_t uart_send(int id, uint8_t* buffer, uint32_t len) { if(id == 0){ for(uint32_t i=0;i<len;i++) { while(USART_GetFlagStatus(USART3, USART_FLAG_TXC) == 0); USART_SendData(USART3,buffer[i]); } }else if(id == 1){ } return len; } uint32_t uart_read(int id, uint8_t* buffer, uint32_t len) { uint32_t rlen; CriticalAlloc(); EnterCritical(); rlen = fifo_out(&(s_uart_fifo_dev[id]), buffer, len); ExitCritical(); return rlen; }   Uart.h #ifndef UART_H #define UART_H #ifdef __cplusplus extern "C" { #endif #include <stdint.h> void uart_init(int id, uint32_t baud); uint32_t uart_send(int id, uint8_t* buffer, uint32_t len); uint32_t uart_read(int id, uint8_t* buffer, uint32_t len); #ifdef __cplusplus } #endif #endif   总结 以上实现了串口收发驱动,并进行了测试,提供了串口读写接口,方便后面使用。

  • 发表了主题帖: 【国民技术高性能MCU N32H487开发板】系统跑240MHz并输出MCO时钟测试

    前言 本文分享下系统使用HSE跑最大240MHz,并输出MCO时钟验证时钟正确性。 配置使用HSE system_n32h47x_48x.c中 使用HSE PLL #ifndef SYSCLK_SRC #define SYSCLK_SRC SYSCLK_USE_HSE_PLL #endif HSE频率要和 n32h47x_48x.h中对应 #if !defined HSE_VALUE #define HSE_VALUE (8000000U) /* Value of the External oscillator in Hz */ #endif /* HSE_VALUE */ 原理图如下 J6 J9断开 默认系统跑240MHz #ifndef SYSCLK_FREQ #if defined (N32H473) || defined (N32H474) #define SYSCLK_FREQ 200000000 #elif defined (N32H475) || defined (N32H482) || defined (N32H487) #define SYSCLK_FREQ 240000000 #else #error wrong macro definition #endif FLASH等待时间 如下自动根据系统频率设置FLASH等待时间,这里代码自动根据频率修改,无需手动去修改,更严谨,避免用户不知道或者忘记修改导致问题。 /* Flash wait state 0: HCLK <= 40M 1: HCLK <= 80M 2: HCLK <= 120M 3: HCLK <= 160M 4: HCLK <= 200M 5: HCLK <= 240M */ tmpregister = FLASH->AC; tmpregister &= (uint32_t)((uint32_t)~FLASH_AC_LATENCY); tmpregister |= (uint32_t)((SYSCLK_FREQ - 1) / 40000000); FLASH->AC = tmpregister; 时钟输出 引脚 输出最大频率50MHz 测试 使用PLL分频 240MHz分频6得到40MHz,测试看到时钟是正确的。 void mco_init(void) { GPIO_InitType GPIO_InitStructure; /* Initialize GPIO_InitStructure */ GPIO_InitStruct(&GPIO_InitStructure); /* Configure MCO1 PA7 alternate function AF13 push-pull */ GPIO_InitStructure.Pin = GPIO_PIN_7; GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP; GPIO_InitStructure.GPIO_Alternate = GPIO_AF13; GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP; GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);   RCC_ConfigMcoClkPre(RCC_MCO_PLLCLK_DIV6); RCC_ConfigMco1(RCC_MCO_PLL_PRES);   } 实际直接输出系统时钟240MHz也是可以的,只是受限于引脚输出能力,幅值会无法达到摆幅。 RCC_ConfigMco1(RCC_MCO_SYSCLK); 总结 系统时钟可以跑240Mhz,时钟准确,这在MCU中是比较高的了。驱动库完善可以很方便的实现功能。库函数的注释也非常详细,参数注释详细,直接看h文件即可。 相比其他厂家同类型的库,这里在配置系统时钟后自动修改flash等待时间,相比其他库需要手动修改更严谨,避免用户忘记修改导致问题,这也体现厂家开发的细节值得点赞。

  • 2025-03-30
  • 发表了主题帖: 【国民技术高性能MCU N32H487开发板】开发环境搭建

    前言 本文分享N32H48x的开发环境搭建。 官网下载资料 下载需要先注册登录 https://www.nationstech.com/support/dow/?typesof=1508下搜索N32H48 下载SDK https://www.nationstech.com/support/dow/?typesof=1507下搜索N32H48 下载文档 下载开发板资料 https://bbs.eeworld.com.cn/elecplay/content/54b161d1 开发环境搭建 解压N32H48x_SDK.zip 双击 N32H48x_SDK\6-Software Development Kit\Nations.N32H48x_DFP.1.0.0.pack安装MDK的支持包。 如果提示错误,则右键点击pack文件,选择属性 打开方式选择为D:\Keil_v5\UV4\PackUnzip.exe 此时就可以直接双击安装。(我这里是MDK5.40) 安装位于 D:\Keil_v5\Packs\Nationstech\N32H48x_DFP\1.0.0 打开N32H48x_SDK\6-Software Development Kit\Nations.N32H47x_48x_Library.1.0.0\projects\n32h47x_48x_EVAL\examples\USART\Printf\MDK-ARM下的Printf.uvprojx 选择芯片型号 设置编译器 设置宏 修改选择编译的汇编文件 编译 设置仿真器 识别到芯片 添加下载算法 点击进入debug运行 看到串口打印如下,注意跳线连接 串口参数115200-8-n-1 总结 文档资料全面,比较规范,下载方便,在国内厂家中是非常难得的了。资料的搜索过滤批量下载也非常好用。 官网下载中心的文档最好按照芯片系列过滤划分,现在是所有的都是在一起的有点乱。 注意pack如果安装失败,需要选择关联程序PackUnzip.exe 建议mini USB换成type-c,至少也要换成micro usb了,mini usb线真的很少用了。

  • 发表了主题帖: 【米尔-STM32MP257开发板试用体验】开箱与板载资源介绍视频

     

  • 2025-03-25
  • 回复了主题帖: 测评入围名单: 国民技术高性能MCU N32H487开发板

    个人信息无误,确认可以完成测评分享计划

  • 2025-03-14
  • 回复了主题帖: 测评入围名单: 米尔-STM32MP257开发板

    个人信息无误,确认可以完成评测计划

  • 2025-03-09
  • 回复了主题帖: 【EV1W0505B-Y-00A评测】隔离DC/DC选型?-看看MIE1W0505B

    秦天qintian0303 发表于 2025-3-9 09:35 这个隔离高压有人测试吗?   这个不知道怎么测试,非专业人士,也没有设备。 不知道用打火机的打火器试试不知道可不可以

  • 回复了主题帖: 【EV1W0505B-Y-00A评测】隔离DC/DC选型?-看看MIE1W0505B

    lemonboard 发表于 2025-3-9 10:19 隔离高压没有办法测试吧! 难度 有点大吧! 这个不知道怎么测试,非专业人士,也没有设备。 不知道用打火机的打火器试试不知道可不可以

  • 回复了主题帖: 【EV1W0505B-Y-00A评测】隔离DC/DC选型?-看看MIE1W0505B

    PowerAnts 发表于 2025-3-9 10:19 十多年前我就预言,小功率转换器以后完全傻瓜化的,不管是什么应用,都是输入两个脚,输出两个脚。这一天应 ... 是的,集成度会越来越高,关注应用即可。

统计信息

已有591人来访过

  • 芯积分:1092
  • 好友:1
  • 主题:302
  • 回复:223

留言

你需要登录后才可以留言 登录 | 注册


lugl4313820 2022-9-27
您帖的代码的注释都是乱码,注意一下编码格式,下次发帖时注意一下,谢谢。
查看全部