【STM32H7的DSP教程】第7章 ARM DSP源碼和庫移植方法(IAR8)


完整版教程下載地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=94547

第7章   ARM DSP源碼和庫移植方法(IAR8)

本期教程主要講解ARM官方DSP源碼和庫的移植以及一些相關知識的介紹。

7.1 初學者重要提示

7.2 DSP庫的下載和說明

7.3 DSP庫版本的區別

7.4 DSP庫的幾個重要的預定義宏含義

7.5 DSP庫在IAR上的移植(源碼移植方式)

7.6 DSP庫在IAR上的移植(庫移植方式)

7.7 升級到最新版DSP庫方法

7.8 簡易DSP庫函數驗證

7.9 總結

 

 

7.1   初學者重要提示

  1.   IAR請使用8.30及其以上版本,CMSIS請使用5.6.0及其以上版本。
  2.   IAR的工程創建,下載和調試方法,在V7用戶手冊有詳細說明:http://www.armbbs.cn/forum.php?mod=viewthread&tid=93255

7.2   DSP庫的下載和說明

下面詳細的給大家講解一下官方DSP庫的移植。

7.2.1  DSP庫的下載

DSP庫是包含在CMSIS軟件包(Cortex Microcontroller Software Interface Standard)里面,所以下載DSP庫也就是下載CMSIS軟件包。這里提供三個可以下載的地方:

  •   方式一:STM32CubeH7軟件包里面。

每個版本的Cube軟件包都會攜帶CMSIS文件夾,只是版本比較老,不推薦。即使是最新的CubeH7

軟件包,包含的CMSIS軟件包版本也有點低。

  •   方式二:MDK安裝目錄(下面是5.6.0版本的路徑)。

大家安裝了新版MDK后,CMSIS軟件包會存在於路徑:ARM\PACK\ARM\CMSIS\5.6.0\CMSIS。

如果有更新的版本,推薦大家使用最新版本,MDK的軟包下載地址:http://www.keil.com/dd2/Pack/

 

  •  方式三:GitHub。

通過GitHub獲取也比較方便,地址:https://github.com/ARM-software/CMSIS_5 。點擊右上角就可以下載CMSIS軟件包了。

 

當然,也可以在ARM官網下載,只是這兩年ARM官網升級得非常頻繁,通過檢索功能找資料非常麻煩。所以不推薦大家到ARM官網下載資料了。

7.2.2  DSP庫的說明

這里我們以CMSIS V5.6.0為標准進行移植。打開固件庫里面的CMSIS文件,可以看到如下幾個文件:

 

其中DSP文件夾是我們需要的:

 

Examples文件夾中的文件如下,主要是提供了一些例子:

 

Include文件夾里面是DSP庫的頭文件:

 

Lib文件夾里面是MDK(ARM),IAR和CGG版庫文件:

Projects文件夾里面的文件如下,提供了三個版本的工程模板,每個模板里面都是把所有源碼文件添加了進來:

 

Source文件夾中的文件如下,這個是DSP的源碼文件:

 

7.3   DSP庫版本的區別

IAR版本的DSP庫如下:

 

  •   iar_cortexM7ls_math.a

Cortex-M7內核,l表示小端格式,s表示帶FPU單元,Single Precision單精度浮點。iar_cortexM7lf_math.a

Cortex-M7內核,l表示小端格式,f表示帶FPU單元, Double Precision雙精度浮點。

  •   iar_cortexM7l_math.a

Cortex-M7內核,l表示小端格式。

  •   iar_cortexM7bs_math.a

Cortex-M7內核,b表示大端格式,s表示帶FPU單元,Single Precision單精度浮點。

  •   iar_cortexM7bf_math.a

Cortex-M7內核,b表示大端格式,f表示帶FPU單元, Double Precision雙精度浮點。

  •   iar_cortexM7b_math.a

Cortex-M7內核,b表示大端格式。

 

STM32H7是M7內核,雙精度浮點,一般使用小端格式,所以我們選擇庫iar_cortexM7lf_math.a

7.4   DSP庫的幾個重要的預定義宏含義

根據用戶的使用要求,這幾個預定義宏可以添加到IAR的預定義選項中:

 

這里將這幾個預定義宏做個介紹:

  •   ARM_MATH_BIG_ENDIAN:

大端格式。

  •   ARM_MATH_MATRIX_CHECK:

檢測矩陣的輸入輸出大小

  •  ARM_MATH_NEON:
  • ARM_MATH_NEON_EXPERIMENTAL:

這兩個暫時用不到,因為M0,M3,M4和M7內核不支持NEON指令,需要等待升級到ARMv8.1-M架構。

  •   ARM_MATH_ROUNDING:

主要用在浮點數轉Q32,Q15和Q7時,類似四舍五入的處理上,其它函數沒用到。

 

  •   ARM_MATH_LOOPUNROLL:

用於4個為一組的的小批量處理上,加快執行速度。

通過下面的求絕對值函數,可以方便的看出區別:

void arm_abs_f32(
  const float32_t * pSrc,
        float32_t * pDst,
        uint32_t blockSize)
{
        uint32_t blkCnt;                               /* Loop counter */

#if defined(ARM_MATH_NEON)
    float32x4_t vec1;
    float32x4_t res;

    /* Compute 4 outputs at a time */
    blkCnt = blockSize >> 2U;

    while (blkCnt > 0U)
    {
        /* C = |A| */

            /* Calculate absolute values and then store the results in the destination buffer. */
        vec1 = vld1q_f32(pSrc);
        res = vabsq_f32(vec1);
        vst1q_f32(pDst, res);

        /* Increment pointers */
        pSrc += 4;
        pDst += 4;
        
        /* Decrement the loop counter */
        blkCnt--;
    }

    /* Tail */
    blkCnt = blockSize & 0x3;

#else
#if defined (ARM_MATH_LOOPUNROLL)

  /* Loop unrolling: Compute 4 outputs at a time */
  blkCnt = blockSize >> 2U;

  while (blkCnt > 0U)
  {
    /* C = |A| */

    /* Calculate absolute and store result in destination buffer. */
    *pDst++ = fabsf(*pSrc++);

    *pDst++ = fabsf(*pSrc++);

    *pDst++ = fabsf(*pSrc++);

    *pDst++ = fabsf(*pSrc++);

    /* Decrement loop counter */
    blkCnt--;
  }

  /* Loop unrolling: Compute remaining outputs */
  blkCnt = blockSize % 0x4U;

#else

  /* Initialize blkCnt with number of samples */
  blkCnt = blockSize;

#endif /* #if defined (ARM_MATH_LOOPUNROLL) */
#endif /* #if defined(ARM_MATH_NEON) */

  while (blkCnt > 0U)
  {
    /* C = |A| */

    /* Calculate absolute and store result in destination buffer. */
    *pDst++ = fabsf(*pSrc++);

    /* Decrement loop counter */
    blkCnt--;
  }

}

 

7.5   DSP庫在IAR上的移植(源碼移植方式)

下面我們講解下如何在IAR上面移植DSP庫源碼,DSP庫的移植相對比較容易。

7.5.1  第一步:建立IAR工程並添加DSP庫

為了方便起見,我們這里不再專門建立一個MDK工程了,直接以V7開發板中的例子:V7-001_跑馬燈例程為模板進行添加即可。打開這個實例並在左側添加分組CMSIS/DSP:

 

我們這里不需要添加每個C文件源碼,僅需添加包含這些C文件的匯總文件,比如BasicMathFunctions.c文件里面包含的C文件就是:

#include "arm_abs_f32.c"
#include "arm_abs_q15.c"
#include "arm_abs_q31.c"
#include "arm_abs_q7.c"
#include "arm_add_f32.c"
#include "arm_add_q15.c"
#include "arm_add_q31.c"
#include "arm_add_q7.c"
#include "arm_dot_prod_f32.c"
#include "arm_dot_prod_q15.c"
#include "arm_dot_prod_q31.c"
#include "arm_dot_prod_q7.c"
#include "arm_mult_f32.c"
#include "arm_mult_q15.c"
#include "arm_mult_q31.c"
#include "arm_mult_q7.c"
#include "arm_negate_f32.c"
#include "arm_negate_q15.c"
#include "arm_negate_q31.c"
#include "arm_negate_q7.c"
#include "arm_offset_f32.c"
#include "arm_offset_q15.c"
#include "arm_offset_q31.c"
#include "arm_offset_q7.c"
#include "arm_scale_f32.c"
#include "arm_scale_q15.c"
#include "arm_scale_q31.c"
#include "arm_scale_q7.c"
#include "arm_shift_q15.c"
#include "arm_shift_q31.c"
#include "arm_shift_q7.c"
#include "arm_sub_f32.c"
#include "arm_sub_q15.c"
#include "arm_sub_q31.c"
#include "arm_sub_q7.c"

 

這樣一來,IAR編譯后會自動關聯,查看源碼非方便:

 

7.5.2  第二步:添加頭文件路徑

添加DSP所需的頭文件路徑,這個頭文件路徑是已經在模板工程中添加好的,這里只是跟大家強調一下:

 

這里要注意一點,為什么直接添加路徑Libraries\CMSIS\Include里面的頭文件即可,而沒有添加Libraries\CMSIS\DSP\Include,這是因為路徑Libraries\CMSIS\Include里面已經包含了DSP庫的頭文件。

7.5.3  第三步:添加宏定義

我們這里僅使能一個宏定義ARM_MATH_LOOPUNROLL:

 

7.5.4  第四步:開啟FPU

需要客戶通過MDK開啟FPU,由於STM32H7支持雙精度浮點,這里要開啟Double Precision。

 

7.5.5  第五步:添加頭文件arm_math.h

用到DSP庫函數的文件得添加#include "arm_math.h"就可以調用DSP庫的API了。至此就完成了DSP庫的移植。

7.6   DSP庫在IAR上的移植(庫移植方式)

移植方法與本章7.5小節的相同,僅第1步不同,將源碼的添加修改為庫添加:

 

7.7   升級到最新版DSP庫方法

由於CMSIS軟件包是實時更新的,這里提供一種升級的簡單辦法,按照本章7.1小節的說明下載到最新版CMSIS軟件包,然后直接覆蓋DSP工程里面的CMSIS文件夾即可。

7.8   簡易DSP庫函數驗證

這里我們主要運行arm_abs_f32,arm_abs_q31,arm_abs_q15這三個函數,以此來驗證我們移植的DSP庫是否正確。

配套例子:

本章配套了如下兩個例子:

  •   V7-200_DSP程序模板(源碼方式)
  •   V7-201_DSP程序模板(庫方式)

實驗目的:

1. 學習官方DSP庫的移植

實驗內容:

1. 按下按鍵K1, 串口打印函數arm_abs_f32的輸出結果

2. 按下按鍵K2, 串口打印函數arm_abs_q31的輸出結果

3. 按下按鍵K3, 串口打印函數arm_abs_q15的輸出結果

實驗現象:

       通過串口上位機軟件SecureCRT看打印信息現象如下(分別按幾次K1,K2,K3)。如果編譯的是MDK的AC6工程,特別要注意本章7.7小節所說的問題。

 

程序設計:

程序的設計也比較簡單,通過按下不同的按鍵從而打印不同的DSP庫函數執行結果,主程序如下:

#include "bsp.h"            /* 底層硬件驅動 */
#include "arm_math.h"



/* 定義例程名和例程發布日期 */
#define EXAMPLE_NAME    "V7-ARM的DSP移植模板(源碼方式)"
#define EXAMPLE_DATE    "2019-07-31"
#define DEMO_VER        "1.0"

static void PrintfLogo(void);
static void PrintfHelp(void);

/*
*********************************************************************************************************
*    函 數 名: main
*    功能說明: c程序入口
*    形    參: 無
*    返 回 值: 錯誤代碼(無需處理)
*********************************************************************************************************
*/
int main(void)
{
    uint8_t ucKeyCode;        /* 按鍵代碼 */
    float32_t pSrc;
    float32_t pDst;
    q31_t pSrc1;
    q31_t pDst1;
    q15_t pSrc2;
    q15_t pDst2;

    
    bsp_Init();        /* 硬件初始化 */
    
    PrintfLogo();    /* 打印例程名稱和版本等信息 */
    PrintfHelp();    /* 打印操作提示 */

    bsp_StartAutoTimer(0, 100);    /* 啟動1個100ms的自動重裝的定時器 */
    
    /* 主程序大循環 */
    while (1)
    {
        /* CPU空閑時執行的函數,在 bsp.c */
        bsp_Idle();        
        
        /* 判斷定時器超時時間 */
        if (bsp_CheckTimer(0))    
        {
            /* 每隔100ms 進來一次 */
            /* 翻轉LED2的狀態 */
            bsp_LedToggle(2);    
        }

        /* 處理按鍵事件 */
        ucKeyCode = bsp_GetKey();
        if (ucKeyCode > 0)
        {
            /* 有鍵按下 */
            switch (ucKeyCode)
            {
                case KEY_DOWN_K1:               /* K1鍵按下 */
                    pSrc -= 1.23f;
                    arm_abs_f32(&pSrc, &pDst, 1);
                    printf("pDst = %f\r\n", pDst);
                    break;
                    
                case KEY_DOWN_K2:              /* K2鍵按下 */
                    pSrc1 -= 1;
                    arm_abs_q31(&pSrc1, &pDst1, 1);
                    printf("pDst1 = %d\r\n", pDst1);
                    break;

                case KEY_DOWN_K3:              /* K3鍵按下 */
                    pSrc2 -= 1;
                    arm_abs_q15(&pSrc2, &pDst2, 1);
                    printf("pDst2 = %d\r\n", pDst2);
                    break;
                
                default:
                    break;
            }
        }
    }
}

 

7.9   總結

本期教程主要跟大家介紹了官方DSP庫的移植,相對來說移植也比較簡單,建議初學的同學按照這個步驟移植一遍。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM