【STM32-DSP库的使用】基于Keil5 + STM32CubeMX 手动添加、库添加方式

STM32-DSP库的使用

  • 一.CMSIS-DSP
    • [1.1 DSP库简介](#1.1 DSP库简介)
    • [1.2 支持的函数类别](#1.2 支持的函数类别)
    • [1.3 宏定义](#1.3 宏定义)
  • 二、操作
    • [2.1 STM32CubeMX 配置基本工程](#2.1 STM32CubeMX 配置基本工程)
    • [2.2 Lib库的方式实现(推荐)](#2.2 Lib库的方式实现(推荐))
    • [2.3 手动添加DSP文件(可以下载官方最新库,功能齐全)](#2.3 手动添加DSP文件(可以下载官方最新库,功能齐全))
  • 三、MFCC测试DSP加速效果

为验证语音识别MFCC用到快速傅里叶变换FFT,在工程中应用DSP库时对着网上各种教程暴雷难受,希望给大家提供帮助;并且以lib库手动src移植 两种方式分别实现;测试环境Crotex-M4实测有效(相比于Cortex-M3增加了浮点运算单元和数字信号处理(DSP)指令集,适用于需要处理复杂算法的应用);

一.CMSIS-DSP

1.1 DSP库简介

CMSIS简述

通用微控制器软件接口标准 (CMSIS) 简化了微控制器软件开发, 为使用 Cortex-M 和入门级 Cortex-A 处理器的开发人员提供一致且高效的接口。 它促进了代码的重用、可移植性和互操作性, 使开发人员能够专注于应用程序级逻辑,而不是处理低级硬件细节。

CMSIS提供处理器和外围设备、实时操作系统、 和中间件组件,并包括交付机制 (CMSIS-Pack) 用于设备、主板和软件, 并支持组合来自多个供应商的软件组件。 keil.arm.com 上的内容直接从 CMSIS 包中提取。

CMSIS是与各种芯片和软件供应商密切合作定义的,并提供了一种与外设接口的通用方法。 实时操作系统和中间件组件。 它旨在实现来自多个供应商的软件组件的互操作性。
DSP库说明详情见官网

本用户手册介绍了 CMSIS DSP 软件库,这是一套用于基于 Cortex-M 和 Cortex-A 处理器的器件的常见信号处理功能

1.2 支持的函数类别

支持该库分为许多函数,每个函数涵盖一个特定的类别:

  • 基本数学函数
  • 快速数学函数
  • 复杂的数学函数
  • 过滤函数
  • 矩阵函数
  • 转换函数
  • 电机控制功能
  • 统计函数
  • 支持功能
  • 插值函数
  • 支持向量机函数 (SVM)
  • 贝叶斯分类器函数
  • 距离函数
  • 四元数函数

1.3 宏定义

该库通常具有单独的函数,用于对 8 位整数、16 位整数、32 位整数和 32 位浮点值进行操作。预处理器宏,每个库项目都有不同的预处理器宏。

bash 复制代码
ARM_MATH_BIG_ENDIAN:
定义宏ARM_MATH_BIG_ENDIAN,为大端目标构建库。默认情况下,库会为小端目标构建。

ARM_MATH_MATRIX_CHECK:
定义用于检查矩阵的输入和输出大小的宏ARM_MATH_MATRIX_CHECK

ARM_MATH_ROUNDING:
定义用于舍入支持函数的宏ARM_MATH_ROUNDING

ARM_MATH_LOOPUNROLL:
定义宏ARM_MATH_LOOPUNROLL,以便在 DSP 函数中启用手动循环展开

ARM_MATH_NEON:
定义宏ARM_MATH_NEON以启用 DSP 功能的 Neon 版本。默认情况下,当 Neon 可用时,它不会启用,因为性能取决于编译器和目标体系结构。

ARM_MATH_NEON_EXPERIMENTAL:
定义宏ARM_MATH_NEON_EXPERIMENTAL以启用某些 DSP 函数的实验性 Neon 版本。实验性 Neon 版本目前没有比标量版本更好的性能。

ARM_MATH_HELIUM:
它意味着标志 ARM_MATH_MVEF 和 ARM_MATH_MVEI 和 ARM_MATH_MVE_FLOAT16。

ARM_MATH_HELIUM_EXPERIMENTAL:
仅在定义ARM_MATH_MVEF、ARM_MATH_MVEI或ARM_MATH_MVE_FLOAT16时才考虑在内。启用一些矢量版本,这些版本的性能可能比标量差,具体取决于内核/编译器配置。

ARM_MATH_MVEF:
选择 f32 算法的 Helium 版本。它意味着ARM_MATH_FLOAT16和ARM_MATH_MVEI。

ARM_MATH_MVEI:
选择 int 和 fixed point 算法的 Helium 版本。

ARM_MATH_MVE_FLOAT16:
某些算法的 MVE Float16 实现(需要 MVE 扩展)。

DISABLEFLOAT16:
当特定编译器/内核配置不支持 __fp16 时禁用 float16 算法。这仅对标量有效。当矢量体系结构支持 f16 时,无法禁用它。

ARM_MATH_AUTOVECTORIZE:
使用 Helium 或 Neon,禁用带有 C 内部函数的矢量化代码,改用纯 C。然后由编译器完成矢量化。

官方github最新库版本

二、操作

2.1 STM32CubeMX 配置基本工程

工程用的STM32407IGT6实现

简单配置一下时钟和Keil项目,这里略过细节重点在Keil中的配置

2.2 Lib库的方式实现(推荐)

用Keil 自带的 CMSIS-DSP包,一键添加非常方便也不需要添加头文件路径之类的

添加编译宏,可以根据(1.3)实际功能进行配置,点击OK

bash 复制代码
,ARM_MATH_CM4,__CC_ARM,ARM_MATH_MATRIX_CHECK,ARM_MATH_ROUNDING,__TARGET_FPU_VFP,__FPU_PRESENT=1

编译出现如下图,是因为重复宏定义导致的,宏的作用域CMSIS-DSP中获取不到,不添加不行

bash 复制代码
warning:  #47-D: incompatible redefinition of macro "__FPU_PRESENT" 

可以注释掉代码中的一个即可,就不会出现warring了

终于编译过了(期间有一次遇到keil全局宏修改不生效的问题,导致死都编译不过,最后只能在keil的配置表里面修改,正常不会有这个问题)

2.3 手动添加DSP文件(可以下载官方最新库,功能齐全)

添加编译宏,和(2.1)一致

bash 复制代码
,ARM_MATH_CM4,__CC_ARM,ARM_MATH_MATRIX_CHECK,ARM_MATH_ROUNDING,__TARGET_FPU_VFP,__FPU_PRESENT=1

添加DSP src文件

可以根据实际使用的API添加,基本功能添加下图所示三个文件夹所有.C文件

这里要注意的是,别漏了 arm_bitreversal2.S

关于汇编文件编译报错的问题,--cpreproc选项是告诉armasm在汇编代码时先调用armclang来处理该汇编代码,然后再将处理后的代码给armasm来汇编成机器码。

error: A1163E: Unknown opcode defined , expecting opcode or Macro


添加DSP的头文件路径

编译是发现arm_dct4_X相关功能没用到这边就直接在工程中剔除,避免牵连更多的引用到工程中

Undefined symbol arm_cmplx_mult_cmplx_f32 (referred from arm_dct4_f32.o).

最终编译OK

三、MFCC测试DSP加速效果

c 复制代码
		// MFCC
		// do the first mfcc with half old data(256) and half new data(256)
		// then do the second mfcc with all new data(512). 
		// take mfcc buffer
    	float startTime = __HAL_TIM_GetCounter(&htim2)/100.0;
		osMutexAcquire(mfcc_bufHandle, osWaitForever);
		for(int i=0; i<2; i++)
		{
			mfcc_compute(mfcc, &audio_buffer_16bit[i*AUDIO_FRAME_LEN/2], mfcc_features_f);
			
			// quantise them using the same scale as training data (in keras), by 2^n. 
			quantize_data(mfcc_features_f, mfcc_features[mfcc_feat_index], MFCC_COEFFS, 3);
			
			// debug only, to print mfcc data on console
			if(is_print_mfcc)
			{
				for(int i=0; i<MFCC_COEFFS; i++)
					printf("%d ",  mfcc_features[mfcc_feat_index][i]);
				printf("\n");
			}
			
			mfcc_feat_index++;
			if(mfcc_feat_index >= MFCC_LEN)
				mfcc_feat_index = 0;
		}
		osMutexRelease(mfcc_bufHandle);
    printf("mfcc time %0.2f ms\r\n", __HAL_TIM_GetCounter(&htim2)/100.0-startTime);

//不增加DSP库
mfcc time 2.66 ms

//增加DSP库MFCC处理速度提升 56.0%
mfcc time 1.17 ms

相关推荐
青牛科技-Allen6 分钟前
GC3910S:一款高性能双通道直流电机驱动芯片
stm32·单片机·嵌入式硬件·机器人·医疗器械·水泵、
森焱森2 小时前
无人机三轴稳定控制(2)____根据目标俯仰角,实现俯仰稳定化控制,计算出升降舵输出
c语言·单片机·算法·架构·无人机
白鱼不小白2 小时前
stm32 USART串口协议与外设(程序)——江协教程踩坑经验分享
stm32·单片机·嵌入式硬件
S,D3 小时前
MCU引脚的漏电流、灌电流、拉电流区别是什么
驱动开发·stm32·单片机·嵌入式硬件·mcu·物联网·硬件工程
芯岭技术6 小时前
PY32F002A单片机 低成本控制器解决方案,提供多种封装
单片机·嵌入式硬件
youmdt6 小时前
Arduino IDE ESP8266连接0.96寸SSD1306 IIC单色屏显示北京时间
单片机·嵌入式硬件
嘿·嘘6 小时前
第七章 STM32内部FLASH读写
stm32·单片机·嵌入式硬件
Meraki.Zhang6 小时前
【STM32实践篇】:I2C驱动编写
stm32·单片机·iic·驱动·i2c
几个几个n9 小时前
STM32-第二节-GPIO输入(按键,传感器)
单片机·嵌入式硬件
Despacito0o12 小时前
ESP32-s3摄像头驱动开发实战:从零搭建实时图像显示系统
人工智能·驱动开发·嵌入式硬件·音视频·嵌入式实时数据库