STM32F4之FPU效能的充分發揮 設定要點

2021-08-09 01:17:57 字數 2903 閱讀 7704

浮點運算一直是定點cpu的難題,比如乙個簡單的1.1+1.1,定點cpu必須要按照ieee-754標準的演算法來完成運算,對於8位微控制器來說已經完全是噩夢,對32為微控制器來說也不會有多大改善。雖然將浮點數進行q化處理能充分發揮32位微控制器的運算效能,但是精度受到限制而不會太高。對於有fpu(浮點運算單元)的微控制器或者cpu來說,浮點加法只是幾條指令的事情。

現在又fpu或者硬體浮點運算能力的主要有高階dsp(比如ti f28335/c6000/dm6xx/omap等),通用cpu(x87數學協處理器)和高階的arm+dsp處理器等。

stm32-f4屬於cortex-m4f構架,這和m0、m3的最大不同就是多了乙個f-float,即支援浮點指令集,因此在處理數**算時能比m0/m3高出數十倍甚至上百倍的效能,但是要充分發揮fpu的數學效能,還需要一些小小的設定:

1.編譯控制選項:雖然stm32f4xx韌體庫的例程之system_stm32f4***.c檔案中新增了對應的**,但給使用者評估使用的stm32f4-discovery例程中卻沒有,因此mdk4.23編寫浮點運算程式時,雖然編譯器正確產生了v指令來進行浮點運算,但是因為system_stm32f4***.c檔案沒有啟用fpu,因此cpu執行時只認為是遇到非法指令而跳轉到hardfault_handler()中斷中原地踏步。因此要保證這個錯誤不發生,必須要在system_init()函式裡面新增如下**:

#if (__fpu_present == 1) && (__fpu_used == 1)

scb->cpacr |= ((3ul << 10*2)|(3ul << 11*2)); 

#endif

因為這個選項是有條件編譯控制的,因此需要在工程選項(project->options for target "***x")中的c/c++選項卡的define中加入如下的語句:__fpu_present=1,__fpu_used =1。這樣編譯時就加入了啟動fpu的**,cpu也就能正確高效的使用fpu進行簡單的加減乘除了。

但這還遠遠不夠。對於複雜運算,比如三角函式,開方等運算,如果程式設計時還是使用math.h標頭檔案,那是沒法提公升效率的:因為math.h標頭檔案是針對所有arm處理器的,其運算函式都是基於定點cpu和標準演算法(ieee-754),並沒有預見使用fpu的情況,需要很多指令和複雜的過程才能完成運算,也就增加了運算時間。因此要充分發揮m4f的浮點功能,就需要使用韌體庫自帶的arm_math.h,這個檔案根據編譯控制項(__fpu_used == 1)來決定是使用那一種函式方法:如果沒有使用fpu,那就呼叫keil的標準math.h標頭檔案中定義的函式;如果使用了fpu,那就是用韌體庫自帶的優化函式來解決問題。

在arm_math的開頭部分是有這些編譯控制資訊:

#ifndef _arm_math_h

#define _arm_math_h

#define __cmsis_generic 

#if defined (arm_math_cm4)

#include "core_cm4.h"

#elif defined (arm_math_cm3)

#include "core_cm3.h"

#elif defined (arm_math_cm0)

#include "core_cm0.h"

#else

#include "armcm4.h"

#warning "define either arm_math_cm4 or arm_math_cm3...by default building on arm_math_cm4....."

#endif

#undef  __cmsis_generic 

#include "string.h"

#include "math.h"

就是說如果不使用cmsis的,就會呼叫keil自帶的標準庫函式。否則就用cmsis的定義。這裡因為是用的stm32f4,所以應該要arm_math_cm4控制,即加入core_cm4.h,否則就用使用armcm4.h——但在編譯時keil會提示找不到這檔案。因此需要在工程選項之c/c++選項卡的define中繼續加入語句arm_math_cm4。

加入上述編譯控制項之後,高階數學函式的使用基本沒問題了,比如正余弦三角函式的計算。但需要注意,如果你直接使用sin()、cos()、sqrt()這樣的函式,那結果還算呼叫keil的math.h,你可以在debug時看對應的**,其彙編指令為bl.w __hardfp_***。因此這時要完成三角函式的計算就要使用arm_sin_f32()或者arm_cos_f32(),用法不變,這兩個函式的原型分別在arm_sin_f32.c和arm_cos_f32.c中。通過對256點三角函式表的查詢和插值演算法得到任意角度的精確函式值,這就比「原裝」的sin()、cos()快多了。

當然有些例外的是開發函式sqrt(),在arm_math.h中是這麼定義的:

static __inline arm_status  arm_sqrt_f32(float32_t in, float32_t *pout)

else

} 即開方用的函式是arm_sqrt_f32(),其中首先判斷被開發的書是否大於0,只有大於0的才能進行運算,否則輸出結果為0並返回「錯誤」標誌。如果大於0,並且實用了fpu和__cc_arm控制項,那呼叫__sqrtf()來完成編譯,否則呼叫sqrtf()——這個sqrtf()是能在keil的math.h中找到的,即呼叫子函式來完成運算,而__sqrtf()呢?新出現的,相信大家都能猜到是什麼玩意兒:對,就是vsqrt指令!因此要把這點效能也要發揮出來,就需要工程選項之c/c++選項卡的define中繼續加入語句__cc_arm才行。大家可以比較一下是否加入__cc_arm編譯後會彙編**的差別巨大差別。

當然,對於arm_sqrt_f32()函式還是有些麻煩,如果你確認被開方的書是大於等於0的,那就直接使用__sqrtf()函式完成運算,即一條簡單的vsqrt指令。

stm32f4韌體庫還提供了其他很有用的數學函式,都位於dsp_lib資料夾,請大家慢慢探索,discovery!

STM32F4之FPU效能的充分發揮 設定要點

浮點運算一直是定點cpu的難題,比如乙個簡單的1.1 1.1,定點cpu必須要按照ieee 754標準的演算法來完成運算,對於8位微控制器來說已經完全是噩夢,對32為微控制器來說也不會有多大改善。雖然將浮點數進行q化處理能充分發揮32位微控制器的運算效能,但是精度受到限制而不會太高。對於有fpu 浮...

KEIL中STM32F4系列使能FPU

操作步驟 1 在keil使能fpu,參考下圖 2 在keil新增fpu的巨集定義 3 一些配置巨集說明 target fpu vfp fpu的條件編譯配置巨集 開和關 配置該巨集,則開 arm math matrix check 庫函式引數檢查配置巨集 開和關 arm math rounding 庫...

STM32F4外設配置速查 FPU與DSP部分

詳細內容參考cortex m4核心程式設計手冊 stm32f4xx及更高配置stm32微控制器才有fpu支援 stm32f4帶有32位單精度硬體fpu,支援浮點指令集,整個fpu單元能被使能和關閉 使用協處理器控制暫存器 scb cpacr 中的cp11和cp10啟用 關閉fpu 晶元復位後,cp1...