STM32/STM8技术论坛
直播中

硬汉Eric2013

9年用户 1035经验值
擅长:嵌入式技术
私信 关注
[经验]

【安富莱——DSP教程】第8章 BasicMathFunctions的使用(一)

第8章  BasicMathFunctions的使用(一)
    本期教程开始学习ARM官方的DSP库,这里我们先从基本数学函数开始。本期教程主要讲绝对值,加法,点乘和乘法四种运算。
    8.1 绝对值(VectorAbsolute Value)
    8.2 求和(VectorAddition)
    8.3 点乘(VectorDot Product)
    8.4 乘法(VectorMultiplication)

回帖(5)

硬汉Eric2013

2015-6-4 14:21:12
8.1  绝对值(Vector Absolute Value)
    这部分函数主要用于求绝对值,公式描述如下:
      pDst[n] = abs(pSrc[n]),   0 <= n < blockSize.
    特别注意,这部分函数支持目标指针和源指针指向相同的缓冲区。

8.1.1  arm_abs_f32
    这个函数用于求32位浮点数的绝对值,源代码分析如下:
  1. /**      
  2. * @brief Floating-point vector absolute value.                                                    (1)
  3. * @param[in]       *pSrc points to the input buffer      
  4. * @param[out]      *pDst points to the output buffer      
  5. * @param[in]       blockSize number of samples in each vector      
  6. * [url=home.php?mod=space&uid=1141835]@Return[/url] none.      
  7. */

  8. void arm_abs_f32(                                                                                  (2)
  9.   float32_t * pSrc,
  10.   float32_t * pDst,
  11.   uint32_t blockSize)
  12. {
  13.   uint32_t blkCnt;                               /* loop counter */

  14. #ifndef ARM_MATH_CM0_FAMILY                                                                        (3)

  15.   /* Run the below code for Cortex-M4 and Cortex-M3 */
  16.   float32_t in1, in2, in3, in4;                  /* temporary variables */

  17.   /*loop Unrolling */
  18.   blkCnt = blockSize >> 2u;                                                                        (4)

  19.   /* First part of the processing with loop unrolling.  Compute 4 outputs at a time.   
  20.    ** a second loop below computes the remaining 1 to 3 samples. */
  21.   while(blkCnt > 0u)
  22.   {
  23.     /* C = |A| */
  24.     /* Calculate absolute and then store the results in the destination buffer. */
  25.     /* read sample from source */
  26.     in1 = *pSrc;
  27.     in2 = *(pSrc + 1);
  28.     in3 = *(pSrc + 2);

  29.     /* find absolute value */
  30.     in1 = fabsf(in1);                                                                             (5)

  31.     /* read sample from source */
  32.     in4 = *(pSrc + 3);

  33.     /* find absolute value */
  34.     in2 = fabsf(in2);

  35.     /* read sample from source */
  36.     *pDst = in1;

  37.     /* find absolute value */
  38.     in3 = fabsf(in3);

  39.     /* find absolute value */
  40.     in4 = fabsf(in4);

  41.     /* store result to destination */
  42.     *(pDst + 1) = in2;

  43.     /* store result to destination */
  44.     *(pDst + 2) = in3;

  45.     /* store result to destination */
  46.     *(pDst + 3) = in4;


  47.     /* Update source pointer to process next sampels */                                            (6)
  48.     pSrc += 4u;

  49.     /* Update destination pointer to process next sampels */
  50.     pDst += 4u;

  51.     /* Decrement the loop counter */
  52.     blkCnt--;
  53.   }

  54.   /* If the blockSize is not a multiple of 4, compute any remaining output samples here.   
  55.    ** No loop unrolling is used. */
  56.   blkCnt = blockSize % 0x4u;

  57. #else                                                                                             (7)

  58.   /* Run the below code for Cortex-M0 */

  59.   /* Initialize blkCnt with number of samples */
  60.   blkCnt = blockSize;

  61. #endif /*   #ifndef ARM_MATH_CM0_FAMILY   */

  62.   while(blkCnt > 0u)                                                                              (8)
  63.   {
  64.     /* C = |A| */
  65.     /* Calculate absolute and then store the results in the destination buffer. */
  66.     *pDst++ = fabsf(*pSrc++);

  67.     /* Decrement the loop counter */
  68.     blkCnt--;
  69.   }
  70. }
1.     在这里简单的跟大家介绍一下DSP库中函数的通用格式,后面就不再赘述了。
    (1)    基本所有的函数都是可重入的。
    (2)    大部分函数都支持一组数的计算,比如这个函数arm_abs_f32就可以计算一组数的绝对值。所以如果只是就几个数的绝对值,用这个库函数就没有什么优势了。
    (3)    库函数基本是CM0,CM3和CM4都支持的(最新的DSP库已经添加CM7的支持)。
    (4)    每组数据基本上都是以4个数为一个单位进行计算,不够四个再单独计算。
    (5)    大部分函数都是配有f32,Q31,Q15和Q7四种格式。
2.     函数参数,支持输入一个数组进行计算绝对值。
3.     这部分代码是用于CM3和CM4内核。
4.     左移两位从而实现每4个数据为一组进行计算。
5.     fabsf:这个函数不是用Cortex-M4F支持的DSP指令实现的,而是用C语言实现的,这个函数是被MDK封装起来的。
6.     切换到下一组数据。
7.     这部分代码用于CM0.
8.     用于不够4个数据的计算或者CM0内核。

8.1.2  arm_abs_q31
    这个函数用于求32位定点数的绝对值,源代码分析如下:
  1. /**   
  2. * @brief Q31 vector absolute value.   
  3. * @param[in]       *pSrc points to the input buffer   
  4. * @param[out]      *pDst points to the output buffer   
  5. * @param[in]       blockSize number of samples in each vector   
  6. * @return none.   
  7. *   
  8. * Scaling and Overflow Behavior:                                                              (1)
  9. * par   
  10. * The function uses saturating arithmetic.   
  11. * The Q31 value -1 (0x80000000) will be saturated to the maximum allowable positive value 0x7FFFFFFF.   
  12. */

  13. void arm_abs_q31(
  14.   q31_t * pSrc,
  15.   q31_t * pDst,
  16.   uint32_t blockSize)
  17. {
  18.   uint32_t blkCnt;                               /* loop counter */
  19.   q31_t in;                                      /* Input value */

  20. #ifndef ARM_MATH_CM0_FAMILY

  21.   /* Run the below code for Cortex-M4 and Cortex-M3 */
  22.   q31_t in1, in2, in3, in4;

  23.   /*loop Unrolling */
  24.   blkCnt = blockSize >> 2u;

  25.   /* First part of the processing with loop unrolling.  Compute 4 outputs at a time.   
  26.    ** a second loop below computes the remaining 1 to 3 samples. */
  27.   while(blkCnt > 0u)
  28.   {
  29.     /* C = |A| */
  30.     /* Calculate absolute of input (if -1 then saturated to 0x7fffffff) and then store the results in the destination buffer. */
  31.     in1 = *pSrc++;
  32.     in2 = *pSrc++;
  33.     in3 = *pSrc++;
  34.     in4 = *pSrc++;

  35.     *pDst++ = (in1 > 0) ? in1 : (q31_t)__QSUB(0, in1);                                              (2)
  36.     *pDst++ = (in2 > 0) ? in2 : (q31_t)__QSUB(0, in2);
  37.     *pDst++ = (in3 > 0) ? in3 : (q31_t)__QSUB(0, in3);
  38.     *pDst++ = (in4 > 0) ? in4 : (q31_t)__QSUB(0, in4);

  39.     /* Decrement the loop counter */
  40.     blkCnt--;
  41.   }

  42.   /* If the blockSize is not a multiple of 4, compute any remaining output samples here.   
  43.    ** No loop unrolling is used. */
  44.   blkCnt = blockSize % 0x4u;

  45. #else

  46.   /* Run the below code for Cortex-M0 */

  47.   /* Initialize blkCnt with number of samples */
  48.   blkCnt = blockSize;

  49. #endif /*   #ifndef ARM_MATH_CM0_FAMILY   */

  50.   while(blkCnt > 0u)
  51.   {
  52.     /* C = |A| */
  53.     /* Calculate absolute value of the input (if -1 then saturated to 0x7fffffff) and then store the results in the destination buffer. */
  54.     in = *pSrc++;
  55.     *pDst++ = (in > 0) ? in : ((in == INT32_MIN) ? INT32_MAX : -in);

  56.     /* Decrement the loop counter */
  57.     blkCnt--;
  58.   }

  59. }
1.    这个函数使用了饱和运算,其实不光这个函数,后面很多函数都是使用了饱和运算的,关于什么是饱和运算,大家看Cortex-M3权威指南中文版的4.3.6 小节:汇编语言:饱和运算即可。
    对于Q31格式的数据,饱和运算会使得数据0x80000000变成0x7fffffff(这个数比较特殊,算是特殊处理,记住即可)。
2.    这里重点说一下函数__QSUB,其实这个函数算是Cortex-M4/M3的一个指令,用于实现饱和减法。
    比如函数:__QSUB(0,in1) 的作用就是实现0 – in1并返回结果。这里__QSUB实现的是32位数的饱和减法。还有__QSUB16和__QSUB8实现的是16位和8位数的减法。

8.1.3  arm_abs_q15
    这个函数用于求15位定点数的绝对值,源代码分析如下:
  1. /**   
  2. * @brief Q15 vector absolute value.   
  3. * @param[in]       *pSrc points to the input buffer   
  4. * @param[out]      *pDst points to the output buffer   
  5. * @param[in]       blockSize number of samples in each vector   
  6. * @return none.   
  7. *   
  8. * Scaling and Overflow Behavior:   
  9. * par   
  10. * The function uses saturating arithmetic.   
  11. * The Q15 value -1 (0x8000) will be saturated to the maximum allowable positive value 0x7FFF.       (1)
  12. */

  13. void arm_abs_q15(
  14.   q15_t * pSrc,
  15.   q15_t * pDst,
  16.   uint32_t blockSize)
  17. {
  18.   uint32_t blkCnt;                               /* loop counter */

  19. #ifndef ARM_MATH_CM0_FAMILY
  20.   __SIMD32_TYPE *simd;                                                                               (2)

  21. /* Run the below code for Cortex-M4 and Cortex-M3 */

  22.   q15_t in1;                                     /* Input value1 */
  23.   q15_t in2;                                     /* Input value2 */


  24.   /*loop Unrolling */
  25.   blkCnt = blockSize >> 2u;

  26.   /* First part of the processing with loop unrolling.  Compute 4 outputs at a time.   
  27.    ** a second loop below computes the remaining 1 to 3 samples. */
  28.   simd = __SIMD32_CONST(pDst);                                                                       (3)
  29.   while(blkCnt > 0u)
  30.   {
  31.     /* C = |A| */
  32.     /* Read two inputs */
  33.     in1 = *pSrc++;
  34.     in2 = *pSrc++;


  35.     /* Store the Absolute result in the destination buffer by packing the two values, in a single cycle */
  36. #ifndef  ARM_MATH_BIG_ENDIAN
  37.     *simd++ =
  38.       __PKHBT(((in1 > 0) ? in1 : (q15_t)__QSUB16(0, in1)),                                           (4)
  39.               ((in2 > 0) ? in2 : (q15_t)__QSUB16(0, in2)), 16);

  40. #else


  41.     *simd++ =
  42.       __PKHBT(((in2 > 0) ? in2 : (q15_t)__QSUB16(0, in2)),
  43.               ((in1 > 0) ? in1 : (q15_t)__QSUB16(0, in1)), 16);

  44. #endif /* #ifndef  ARM_MATH_BIG_ENDIAN    */

  45.     in1 = *pSrc++;
  46.     in2 = *pSrc++;


  47. #ifndef  ARM_MATH_BIG_ENDIAN

  48.     *simd++ =
  49.       __PKHBT(((in1 > 0) ? in1 : (q15_t)__QSUB16(0, in1)),
  50.               ((in2 > 0) ? in2 : (q15_t)__QSUB16(0, in2)), 16);

  51. #else


  52.     *simd++ =
  53.       __PKHBT(((in2 > 0) ? in2 : (q15_t)__QSUB16(0, in2)),
  54.               ((in1 > 0) ? in1 : (q15_t)__QSUB16(0, in1)), 16);

  55. #endif /* #ifndef  ARM_MATH_BIG_ENDIAN    */

  56.     /* Decrement the loop counter */
  57.     blkCnt--;
  58.   }
  59.   pDst = (q15_t *)simd;
  60.    
  61.   /* If the blockSize is not a multiple of 4, compute any remaining output samples here.   
  62.    ** No loop unrolling is used. */
  63.   blkCnt = blockSize % 0x4u;

  64.   while(blkCnt > 0u)
  65.   {
  66.     /* C = |A| */
  67.     /* Read the input */
  68.     in1 = *pSrc++;

  69.     /* Calculate absolute value of input and then store the result in the destination buffer. */
  70.     *pDst++ = (in1 > 0) ? in1 : (q15_t)__QSUB16(0, in1);

  71.     /* Decrement the loop counter */
  72.     blkCnt--;
  73.   }

  74. #else

  75.   /* Run the below code for Cortex-M0 */

  76.   q15_t in;                                      /* Temporary input variable */

  77.   /* Initialize blkCnt with number of samples */
  78.   blkCnt = blockSize;

  79.   while(blkCnt > 0u)
  80.   {
  81.     /* C = |A| */
  82.     /* Read the input */
  83.     in = *pSrc++;

  84.     /* Calculate absolute value of input and then store the result in the destination buffer. */
  85.     *pDst++ = (in > 0) ? in : ((in == (q15_t) 0x8000) ? 0x7fff : -in);

  86.     /* Decrement the loop counter */
  87.     blkCnt--;
  88.   }

  89. #endif /* #ifndef ARM_MATH_CM0_FAMILY */

  90. }
1.    对于Q15格式的数据,饱和运算会使得数据0x8000变成0x7fff。
2.    __SIMD32_TYPE的定义在文件arm_math.h中,具体定义如下:
      #define __SIMD32_TYPE int32_t __packed
    SIMD就是咱们上期教程所将的单指令多数据流。简单的理解就是__SIMD32_TYPE就是定义了一个int32_t类型的数据,__packed的含义就是实现字节的对齐功能,方便两个16位数据的都存入到这个数据类型中。
3.    函数__SIMD32_CONST的定义如下:
      #define __SIMD32_CONST(addr) ((__SIMD32_TYPE *)(addr))
4.    函数__PKHBT的定义在文件core_cm4_simd.h,定义如下:
      #define __PKHBT(ARG1,ARG2,ARG3)  ( ((((uint32_t)(ARG1)) ) &0x0000FFFFUL) |  
                                                                 ((((uint32_t)(ARG2)) <<(ARG3)) & 0xFFFF0000UL) )
           这个宏定义的作用就是将将两个16位的数据合并成32位数据。但是有一点要特别说明__PKHBT也是CM4内核支持的SIMD指令,上面的宏定义的C函数会被MDK自动识别并调用相应的PKHBT指令。
            __QSUB16用于实现16位数据的饱和减法。

8.1.4  arm_abs_q7
    这个函数用于求8位定点数的绝对值,源代码分析如下:
  1. /**      
  2. * @brief Q7 vector absolute value.      
  3. * @param[in]       *pSrc points to the input buffer      
  4. * @param[out]      *pDst points to the output buffer      
  5. * @param[in]       blockSize number of samples in each vector      
  6. * @return none.      
  7. *   
  8. * par Conditions for optimum performance   
  9. *  Input and output buffers should be aligned by 32-bit   
  10. *   
  11. *      
  12. * Scaling and Overflow Behavior:                                                             (1)
  13. * par      
  14. * The function uses saturating arithmetic.      
  15. * The Q7 value -1 (0x80) will be saturated to the maximum allowable positive value 0x7F.      
  16. */

  17. void arm_abs_q7(
  18.   q7_t * pSrc,
  19.   q7_t * pDst,
  20.   uint32_t blockSize)
  21. {
  22.   uint32_t blkCnt;                               /* loop counter */
  23.   q7_t in;                                       /* Input value1 */

  24. #ifndef ARM_MATH_CM0_FAMILY

  25.   /* Run the below code for Cortex-M4 and Cortex-M3 */
  26.   q31_t in1, in2, in3, in4;                      /* temporary input variables */
  27.   q31_t out1, out2, out3, out4;                  /* temporary output variables */

  28.   /*loop Unrolling */
  29.   blkCnt = blockSize >> 2u;

  30.   /* First part of the processing with loop unrolling.  Compute 4 outputs at a time.   
  31.    ** a second loop below computes the remaining 1 to 3 samples. */
  32.   while(blkCnt > 0u)
  33.   {
  34.     /* C = |A| */
  35.     /* Read inputs */
  36.     in1 = (q31_t) * pSrc;
  37.     in2 = (q31_t) * (pSrc + 1);
  38.     in3 = (q31_t) * (pSrc + 2);

  39.     /* find absolute value */
  40.     out1 = (in1 > 0) ? in1 : (q31_t)__QSUB8(0, in1);                                                  (2)

  41.     /* read input */
  42.     in4 = (q31_t) * (pSrc + 3);

  43.     /* find absolute value */
  44.     out2 = (in2 > 0) ? in2 : (q31_t)__QSUB8(0, in2);

  45.     /* store result to destination */
  46.     *pDst = (q7_t) out1;

  47.     /* find absolute value */
  48.     out3 = (in3 > 0) ? in3 : (q31_t)__QSUB8(0, in3);

  49.     /* find absolute value */
  50.     out4 = (in4 > 0) ? in4 : (q31_t)__QSUB8(0, in4);

  51.     /* store result to destination */
  52.     *(pDst + 1) = (q7_t) out2;

  53.     /* store result to destination */
  54.     *(pDst + 2) = (q7_t) out3;

  55.     /* store result to destination */
  56.     *(pDst + 3) = (q7_t) out4;

  57.     /* update pointers to process next samples */
  58.     pSrc += 4u;
  59.     pDst += 4u;

  60.     /* Decrement the loop counter */
  61.     blkCnt--;
  62.   }

  63.   /* If the blockSize is not a multiple of 4, compute any remaining output samples here.   
  64.    ** No loop unrolling is used. */
  65.   blkCnt = blockSize % 0x4u;
  66. #else

  67.   /* Run the below code for Cortex-M0 */
  68.   blkCnt = blockSize;

  69. #endif //      #define ARM_MATH_CM0_FAMILY

  70.   while(blkCnt > 0u)
  71.   {
  72.     /* C = |A| */
  73.     /* Read the input */
  74.     in = *pSrc++;

  75.     /* Store the Absolute result in the destination buffer */
  76.     *pDst++ = (in > 0) ? in : ((in == (q7_t) 0x80) ? 0x7f : -in);

  77.     /* Decrement the loop counter */
  78.     blkCnt--;
  79.   }
  80. }
1.    由于饱和运算,0x80求绝对值将变成数据0x7F。
2.    __QSUB8用以实现8位数的饱和减法运算。

8.1.5  实例讲解
实验目的:
    1. 四种数据类型数据绝对值求解
实验内容:
    1. 按下按键K1, 串口打印输出结果
实验现象:
           通过窗口上位机软件SecureCRT(V5光盘里面有此软件)查看打印信息现象如下:
8.1.png

程序设计:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: DSP_ABS
  4. *    功能说明: 求绝对值
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void DSP_ABS(void)
  10. {
  11.      static float32_t pSrc;
  12.     static float32_t pDst;
  13.    
  14.      static q31_t pSrc1;
  15.      static q31_t pDst1;
  16.    
  17.      static q15_t pSrc2;
  18.      static q15_t pDst2;
  19.    
  20.      static q7_t pSrc3 = 127; /* 为了说明问题,在这里设置初始值为127,然后查看0x80是否饱和为0x7F */
  21.      static q7_t pDst3;
  22.    
  23.    
  24.      pSrc -= 1.23f;
  25.      arm_abs_f32(&pSrc, &pDst, 1);                                                                    (1)
  26.      printf("arm_abs_f32 = %frn", pDst);

  27.      pSrc1 -= 1;
  28.      arm_abs_q31(&pSrc1, &pDst1, 1);                                                                  (2)
  29.      printf("arm_abs_q31 = %drn", pDst1);

  30.      pSrc2 -= 1;
  31.      arm_abs_q15(&pSrc2, &pDst2, 1);                                                                  (3)
  32.      printf("arm_abs_q15 = %drn", pDst2);

  33.      pSrc3 += 1;
  34.      printf("pSrc3 = %drn", pSrc3);
  35.      arm_abs_q7(&pSrc3, &pDst3, 1);                                                                   (4)
  36.      printf("arm_abs_q7 = %drn", pDst3);
  37.      printf("***********************************rn");
  38. }
(1)到(4)实现相应格式下绝对值的求解。这里只求了一个数,大家可以尝试求解一个数组的绝对值。

举报

硬汉Eric2013

2015-6-4 14:25:52
8.2  求和(Vector Addition)
    这部分函数主要用于求和,公式描述如下:
      pDst[n] = pSrcA[n] + pSrcB[n],   0 <= n < blockSize.

8.2.1  arm_add_f32
     这个函数用于求32位浮点数的和,源代码分析如下:
  1. /**      
  2. * @brief Floating-point vector addition.      
  3. * @param[in]       *pSrcA points to the first input vector      
  4. * @param[in]       *pSrcB points to the second input vector      
  5. * @param[out]      *pDst points to the output vector      
  6. * @param[in]       blockSize number of samples in each vector      
  7. * @return none.      
  8. */

  9. void arm_add_f32(
  10.   float32_t * pSrcA,
  11.   float32_t * pSrcB,
  12.   float32_t * pDst,
  13.   uint32_t blockSize)
  14. {
  15.   uint32_t blkCnt;                               /* loop counter */

  16. #ifndef ARM_MATH_CM0_FAMILY

  17. /* Run the below code for Cortex-M4 and Cortex-M3 */
  18.   float32_t inA1, inA2, inA3, inA4;              /* temporary input variabels */
  19.   float32_t inB1, inB2, inB3, inB4;              /* temporary input variables */

  20.   /*loop Unrolling */
  21.   blkCnt = blockSize >> 2u;

  22.   /* First part of the processing with loop unrolling.  Compute 4 outputs at a time.      
  23.    ** a second loop below computes the remaining 1 to 3 samples. */
  24.   while(blkCnt > 0u)
  25.   {
  26.     /* C = A + B */
  27.     /* Add and then store the results in the destination buffer. */

  28.     /* read four inputs from sourceA and four inputs from sourceB */
  29.     inA1 = *pSrcA;
  30.     inB1 = *pSrcB;
  31.     inA2 = *(pSrcA + 1);
  32.     inB2 = *(pSrcB + 1);
  33.     inA3 = *(pSrcA + 2);
  34.     inB3 = *(pSrcB + 2);
  35.     inA4 = *(pSrcA + 3);
  36.     inB4 = *(pSrcB + 3);

  37.     /* C = A + B */                                                                                  (1)
  38.     /* add and store result to destination */
  39.     *pDst = inA1 + inB1;
  40.     *(pDst + 1) = inA2 + inB2;
  41.     *(pDst + 2) = inA3 + inB3;
  42.     *(pDst + 3) = inA4 + inB4;

  43.     /* update pointers to process next samples */
  44.     pSrcA += 4u;
  45.     pSrcB += 4u;
  46.     pDst += 4u;


  47.     /* Decrement the loop counter */
  48.     blkCnt--;
  49.   }

  50.   /* If the blockSize is not a multiple of 4, compute any remaining output samples here.      
  51.    ** No loop unrolling is used. */
  52.   blkCnt = blockSize % 0x4u;

  53. #else

  54.   /* Run the below code for Cortex-M0 */

  55.   /* Initialize blkCnt with number of samples */
  56.   blkCnt = blockSize;

  57. #endif /* #ifndef ARM_MATH_CM0_FAMILY */

  58.   while(blkCnt > 0u)
  59.   {
  60.     /* C = A + B */
  61.     /* Add and then store the results in the destination buffer. */
  62.     *pDst++ = (*pSrcA++) + (*pSrcB++);

  63.     /* Decrement the loop counter */
  64.     blkCnt--;
  65.   }
  66. }
1.    这部分的代码比较简单,只是求解两个数的和。

8.2.2  arm_add_q31
    这个函数用于求32位定点数的和,源代码分析如下:
  1. /**   
  2. * @brief Q31 vector addition.   
  3. * @param[in]       *pSrcA points to the first input vector   
  4. * @param[in]       *pSrcB points to the second input vector   
  5. * @param[out]      *pDst points to the output vector   
  6. * @param[in]       blockSize number of samples in each vector   
  7. * @return none.   
  8. *   
  9. * Scaling and Overflow Behavior:                                                             (1)
  10. * par   
  11. * The function uses saturating arithmetic.   
  12. * Results outside of the allowable Q31 range[0x80000000 0x7FFFFFFF] will be saturated.   
  13. */

  14. void arm_add_q31(
  15.   q31_t * pSrcA,
  16.   q31_t * pSrcB,
  17.   q31_t * pDst,
  18.   uint32_t blockSize)
  19. {
  20.   uint32_t blkCnt;                               /* loop counter */

  21. #ifndef ARM_MATH_CM0_FAMILY

  22. /* Run the below code for Cortex-M4 and Cortex-M3 */
  23.   q31_t inA1, inA2, inA3, inA4;
  24.   q31_t inB1, inB2, inB3, inB4;

  25.   /*loop Unrolling */
  26.   blkCnt = blockSize >> 2u;

  27.   /* First part of the processing with loop unrolling.  Compute 4 outputs at a time.   
  28.    ** a second loop below computes the remaining 1 to 3 samples. */
  29.   while(blkCnt > 0u)
  30.   {
  31.     /* C = A + B */
  32.     /* Add and then store the results in the destination buffer. */
  33.     inA1 = *pSrcA++;
  34.     inA2 = *pSrcA++;
  35.     inB1 = *pSrcB++;
  36.     inB2 = *pSrcB++;

  37.     inA3 = *pSrcA++;
  38.     inA4 = *pSrcA++;
  39.     inB3 = *pSrcB++;
  40.     inB4 = *pSrcB++;

  41.     *pDst++ = __QADD(inA1, inB1);                                                                   (2)
  42.     *pDst++ = __QADD(inA2, inB2);
  43.     *pDst++ = __QADD(inA3, inB3);
  44.     *pDst++ = __QADD(inA4, inB4);

  45.     /* Decrement the loop counter */
  46.     blkCnt--;
  47.   }

  48.   /* If the blockSize is not a multiple of 4, compute any remaining output samples here.   
  49.    ** No loop unrolling is used. */
  50.   blkCnt = blockSize % 0x4u;

  51.   while(blkCnt > 0u)
  52.   {
  53.     /* C = A + B */
  54.     /* Add and then store the results in the destination buffer. */
  55.     *pDst++ = __QADD(*pSrcA++, *pSrcB++);

  56.     /* Decrement the loop counter */
  57.     blkCnt--;
  58.   }

  59. #else

  60.   /* Run the below code for Cortex-M0 */



  61.   /* Initialize blkCnt with number of samples */
  62.   blkCnt = blockSize;

  63.   while(blkCnt > 0u)
  64.   {
  65.     /* C = A + B */
  66.     /* Add and then store the results in the destination buffer. */
  67.     *pDst++ = (q31_t) clip_q63_to_q31((q63_t) * pSrcA++ + *pSrcB++);                                  (3)

  68.     /* Decrement the loop counter */
  69.     blkCnt--;
  70.   }

  71. #endif /* #ifndef ARM_MATH_CM0_FAMILY */

  72. }
1.     这个函数也是饱和运算,输出结果的范围[0x800000000x7FFFFFFF],超出这个结果将产生饱和结果。
2.     __QADD实现32位数的加法。
3.     函数clip_q63_to_q31的定义在文件arm_math.h里面
      static __INLINE q31_t clip_q63_to_q31(
      q63_t x)
      {
          return ((q31_t) (x >> 32) != ((q31_t)x >> 31)) ?
            ((0x7FFFFFFF ^ ((q31_t) (x >>63)))) : (q31_t) x;
          }
    这个函数的作用是实现饱和结果。

8.2.3  arm_add_q15
    这个函数用于求16位定点数的和,源代码分析如下:
  1. /**   
  2. * @brief Q15 vector addition.   
  3. * @param[in]       *pSrcA points to the first input vector   
  4. * @param[in]       *pSrcB points to the second input vector   
  5. * @param[out]      *pDst points to the output vector   
  6. * @param[in]       blockSize number of samples in each vector   
  7. * @return none.   
  8. *   
  9. * Scaling and Overflow Behavior:                                                               (1)
  10. * par   
  11. * The function uses saturating arithmetic.   
  12. * Results outside of the allowable Q15 range [0x8000 0x7FFF] will be saturated.   
  13. */

  14. void arm_add_q15(
  15.   q15_t * pSrcA,
  16.   q15_t * pSrcB,
  17.   q15_t * pDst,
  18.   uint32_t blockSize)
  19. {
  20.   uint32_t blkCnt;                               /* loop counter */

  21. #ifndef ARM_MATH_CM0_FAMILY

  22. /* Run the below code for Cortex-M4 and Cortex-M3 */
  23.   q31_t inA1, inA2, inB1, inB2;

  24.   /*loop Unrolling */
  25.   blkCnt = blockSize >> 2u;

  26.   /* First part of the processing with loop unrolling.  Compute 4 outputs at a time.   
  27.    ** a second loop below computes the remaining 1 to 3 samples. */
  28.   while(blkCnt > 0u)
  29.   {
  30.     /* C = A + B */                                                                                    (2)
  31.     /* Add and then store the results in the destination buffer. */
  32.     inA1 = *__SIMD32(pSrcA)++;
  33.     inA2 = *__SIMD32(pSrcA)++;
  34.     inB1 = *__SIMD32(pSrcB)++;
  35.     inB2 = *__SIMD32(pSrcB)++;

  36.     *__SIMD32(pDst)++ = __QADD16(inA1, inB1);
  37.     *__SIMD32(pDst)++ = __QADD16(inA2, inB2);

  38.     /* Decrement the loop counter */
  39.     blkCnt--;
  40.   }

  41.   /* If the blockSize is not a multiple of 4, compute any remaining output samples here.   
  42.    ** No loop unrolling is used. */
  43.   blkCnt = blockSize % 0x4u;

  44.   while(blkCnt > 0u)
  45.   {
  46.     /* C = A + B */
  47.     /* Add and then store the results in the destination buffer. */
  48.     *pDst++ = (q15_t) __QADD16(*pSrcA++, *pSrcB++);

  49.     /* Decrement the loop counter */
  50.     blkCnt--;
  51.   }

  52. #else

  53.   /* Run the below code for Cortex-M0 */



  54.   /* Initialize blkCnt with number of samples */
  55.   blkCnt = blockSize;

  56.   while(blkCnt > 0u)
  57.   {
  58.     /* C = A + B */
  59.     /* Add and then store the results in the destination buffer. */
  60.     *pDst++ = (q15_t) __SSAT(((q31_t) * pSrcA++ + *pSrcB++), 16);                                      (3)

  61.     /* Decrement the loop counter */
  62.     blkCnt--;
  63.   }

  64. #endif /* #ifndef ARM_MATH_CM0_FAMILY */


  65. }
1.     这个函数也是饱和运算,输出结果的范围[0x80000x7FFF],超出这个结果将产生饱和结果。
2.     函数inA1 = *__SIMD32(pSrcA)++仅需要一条SIMD指令即可完成将两个16位数存到32位的变量inA1中。
3.     __SSAT也是SIMD指令,这里是将结果饱和到16位精度。

8.2.4  arm_add_q7
    这个函数用于求8位定点数的绝对值,源代码分析如下:
  1. /**   
  2. * @brief Q7 vector addition.   
  3. * @param[in]       *pSrcA points to the first input vector   
  4. * @param[in]       *pSrcB points to the second input vector   
  5. * @param[out]      *pDst points to the output vector   
  6. * @param[in]       blockSize number of samples in each vector   
  7. * @return none.   
  8. *   
  9. * Scaling and Overflow Behavior:                                                              (1)
  10. * par   
  11. * The function uses saturating arithmetic.   
  12. * Results outside of the allowable Q7 range [0x80 0x7F] will be saturated.   
  13. */

  14. void arm_add_q7(
  15.   q7_t * pSrcA,
  16.   q7_t * pSrcB,
  17.   q7_t * pDst,
  18.   uint32_t blockSize)
  19. {
  20.   uint32_t blkCnt;                               /* loop counter */

  21. #ifndef ARM_MATH_CM0_FAMILY

  22. /* Run the below code for Cortex-M4 and Cortex-M3 */


  23.   /*loop Unrolling */
  24.   blkCnt = blockSize >> 2u;

  25.   /* First part of the processing with loop unrolling.  Compute 4 outputs at a time.   
  26.    ** a second loop below computes the remaining 1 to 3 samples. */
  27.   while(blkCnt > 0u)
  28.   {
  29.     /* C = A + B */
  30.     /* Add and then store the results in the destination buffer. */                                 (2)
  31.     *__SIMD32(pDst)++ = __QADD8(*__SIMD32(pSrcA)++, *__SIMD32(pSrcB)++);

  32.     /* Decrement the loop counter */
  33.     blkCnt--;
  34.   }

  35.   /* If the blockSize is not a multiple of 4, compute any remaining output samples here.   
  36.    ** No loop unrolling is used. */
  37.   blkCnt = blockSize % 0x4u;

  38.   while(blkCnt > 0u)
  39.   {
  40.     /* C = A + B */
  41.     /* Add and then store the results in the destination buffer. */
  42.     *pDst++ = (q7_t) __SSAT(*pSrcA++ + *pSrcB++, 8);

  43.     /* Decrement the loop counter */
  44.     blkCnt--;
  45.   }

  46. #else

  47.   /* Run the below code for Cortex-M0 */



  48.   /* Initialize blkCnt with number of samples */
  49.   blkCnt = blockSize;

  50.   while(blkCnt > 0u)
  51.   {
  52.     /* C = A + B */
  53.     /* Add and then store the results in the destination buffer. */
  54.     *pDst++ = (q7_t) __SSAT((q15_t) * pSrcA++ + *pSrcB++, 8);

  55.     /* Decrement the loop counter */
  56.     blkCnt--;
  57.   }

  58. #endif /* #ifndef ARM_MATH_CM0_FAMILY */


  59. }
1. 这个函数也是饱和运算,输出结果的范围[0x800x7F],超出这个结果将产生饱和。
2. 这里通过SIMD指令实现4组8位数的加法。

8.2.5  实例讲解
实验目的:
    1. 四种类似数据的求和
实验内容:
    1. 按下按键K2, 串口打印输出结果
实验现象:
           通过窗口上位机软件SecureCRT(V5光盘里面有此软件)查看打印信息现象如下:
8.2.png

程序设计:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: DSP_ABS
  4. *    功能说明: 加法
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void DSP_Add(void)
  10. {
  11.      static float32_t   pSrcA;
  12.      static float32_t   pSrcB;
  13.      static float32_t   pDst;
  14.    
  15.      static q31_t  pSrcA1;
  16.      static q31_t  pSrcB1;
  17.      static q31_t  pDst1;

  18.      static q15_t  pSrcA2;
  19.      static q15_t  pSrcB2;
  20.      static q15_t  pDst2;

  21.      static q7_t  pSrcA3;
  22.      static q7_t  pSrcB3;
  23.      static q7_t  pDst3;

  24.    
  25.      pSrcA--;
  26.      arm_add_f32(&pSrcA, &pSrcB, &pDst, 1);
  27.      printf("arm_add_f32 = %frn", pDst);

  28.      pSrcA1--;
  29.      arm_add_q31(&pSrcA1, &pSrcB1, &pDst1, 1);
  30.      printf("arm_add_q31 = %drn", pDst1);

  31.      pSrcA2--;
  32.      arm_add_q15(&pSrcA2, &pSrcB2, &pDst2, 1);
  33.      printf("arm_add_q15 = %drn", pDst2);

  34.      pSrcA3--;
  35.      arm_add_q7(&pSrcA3, &pSrcB3, &pDst3, 1);
  36.      printf("arm_add_q7 = %drn", pDst3);
  37.      printf("***********************************rn");
  38. }

举报

硬汉Eric2013

2015-6-4 14:32:38
8.3  点乘(Vector Dot Product)
    这部分函数主要用于点乘,公式描述如下:
      sum =pSrcA[0]*pSrcB[0] + pSrcA[1]*pSrcB[1] + ... +pSrcA[blockSize-1]*pSrcB[blockSize-1]

8.3.1  arm_dot_prod_f32
    这个函数用于求32位浮点数的点乘,源代码分析如下:
  1. /**
  2. * @defgroup dot_prod Vector Dot Product
  3. *
  4. * Computes the dot product of two vectors.
  5. * The vectors are multiplied element-by-element and then summed.
  6. *
  7. *

  8. *     sum = pSrcA[0]*pSrcB[0] + pSrcA[1]*pSrcB[1] + ... + pSrcA[blockSize-1]*pSrcB[blockSize-1]
  9. *
  10.    
  11. *
  12. * There are separate functions for floating-point, Q7, Q15, and Q31 data types.   
  13. */

  14. /**   
  15. * @addtogroup dot_prod   
  16. * @{   
  17. */

  18. /**   
  19. * @brief Dot product of floating-point vectors.   
  20. * @param[in]       *pSrcA points to the first input vector   
  21. * @param[in]       *pSrcB points to the second input vector   
  22. * @param[in]       blockSize number of samples in each vector   
  23. * @param[out]      *result output result returned here   
  24. * @return none.   
  25. */


  26. void arm_dot_prod_f32(
  27.   float32_t * pSrcA,
  28.   float32_t * pSrcB,
  29.   uint32_t blockSize,
  30.   float32_t * result)
  31. {
  32.   float32_t sum = 0.0f;                          /* Temporary result storage */                      (1)
  33.   uint32_t blkCnt;                               /* loop counter */


  34. #ifndef ARM_MATH_CM0_FAMILY

  35. /* Run the below code for Cortex-M4 and Cortex-M3 */
  36.   /*loop Unrolling */
  37.   blkCnt = blockSize >> 2u;

  38.   /* First part of the processing with loop unrolling.  Compute 4 outputs at a time.   
  39.    ** a second loop below computes the remaining 1 to 3 samples. */
  40.   while(blkCnt > 0u)
  41.   {
  42.     /* C = A[0]* B[0] + A[1]* B[1] + A[2]* B[2] + .....+ A[blockSize-1]* B[blockSize-1] */
  43.     /* Calculate dot product and then store the result in a temporary buffer */
  44.     sum += (*pSrcA++) * (*pSrcB++);                                                                  (2)
  45.     sum += (*pSrcA++) * (*pSrcB++);
  46.     sum += (*pSrcA++) * (*pSrcB++);
  47.     sum += (*pSrcA++) * (*pSrcB++);

  48.     /* Decrement the loop counter */
  49.     blkCnt--;
  50.   }

  51.   /* If the blockSize is not a multiple of 4, compute any remaining output samples here.   
  52.    ** No loop unrolling is used. */
  53.   blkCnt = blockSize % 0x4u;

  54. #else

  55.   /* Run the below code for Cortex-M0 */

  56.   /* Initialize blkCnt with number of samples */
  57.   blkCnt = blockSize;

  58. #endif /* #ifndef ARM_MATH_CM0_FAMILY */


  59.   while(blkCnt > 0u)
  60.   {
  61.     /* C = A[0]* B[0] + A[1]* B[1] + A[2]* B[2] + .....+ A[blockSize-1]* B[blockSize-1] */
  62.     /* Calculate dot product and then store the result in a temporary buffer. */
  63.     sum += (*pSrcA++) * (*pSrcB++);

  64.     /* Decrement the loop counter */
  65.     blkCnt--;
  66.   }
  67.   /* Store the result back in the destination buffer */
  68.   *result = sum;
  69. }
1.     由于CM4上带的FPU是单精度的,所以初始化float32_t类型的浮点数时需要在数据的末尾加上f。
2.     类似函数sum += (*pSrcA++) * (*pSrcB++)最终会通过浮点的MAC(乘累加)实现,从而加快执行时间。

8.3.2  arm_dot_prod_q31
    这个函数用于求32位定点数的点乘,源代码分析如下:
  1. /**   
  2. * @brief Dot product of Q31 vectors.   
  3. * @param[in]       *pSrcA points to the first input vector   
  4. * @param[in]       *pSrcB points to the second input vector   
  5. * @param[in]       blockSize number of samples in each vector   
  6. * @param[out]      *result output result returned here   
  7. * @return none.   
  8. *   
  9. * Scaling and Overflow Behavior:                                                              (1)
  10. * par   
  11. * The intermediate multiplications are in 1.31 x 1.31 = 2.62 format and these   
  12. * are truncated to 2.48 format by discarding the lower 14 bits.   
  13. * The 2.48 result is then added without saturation to a 64-bit accumulator in 16.48 format.   
  14. * There are 15 guard bits in the accumulator and there is no risk of overflow as long as   
  15. * the length of the vectors is less than 2^16 elements.   
  16. * The return result is in 16.48 format.   
  17. */

  18. void arm_dot_prod_q31(
  19.   q31_t * pSrcA,
  20.   q31_t * pSrcB,
  21.   uint32_t blockSize,
  22.   q63_t * result)
  23. {
  24.   q63_t sum = 0;                                 /* Temporary result storage */
  25.   uint32_t blkCnt;                               /* loop counter */


  26. #ifndef ARM_MATH_CM0_FAMILY

  27. /* Run the below code for Cortex-M4 and Cortex-M3 */
  28.   q31_t inA1, inA2, inA3, inA4;
  29.   q31_t inB1, inB2, inB3, inB4;

  30.   /*loop Unrolling */
  31.   blkCnt = blockSize >> 2u;

  32.   /* First part of the processing with loop unrolling.  Compute 4 outputs at a time.   
  33.    ** a second loop below computes the remaining 1 to 3 samples. */
  34.   while(blkCnt > 0u)
  35.   {
  36.     /* C = A[0]* B[0] + A[1]* B[1] + A[2]* B[2] + .....+ A[blockSize-1]* B[blockSize-1] */
  37.     /* Calculate dot product and then store the result in a temporary buffer. */
  38.     inA1 = *pSrcA++;
  39.     inA2 = *pSrcA++;
  40.     inA3 = *pSrcA++;
  41.     inA4 = *pSrcA++;
  42.     inB1 = *pSrcB++;
  43.     inB2 = *pSrcB++;
  44.     inB3 = *pSrcB++;
  45.     inB4 = *pSrcB++;

  46.     sum += ((q63_t) inA1 * inB1) >> 14u;                                                               (2)
  47.     sum += ((q63_t) inA2 * inB2) >> 14u;
  48.     sum += ((q63_t) inA3 * inB3) >> 14u;
  49.     sum += ((q63_t) inA4 * inB4) >> 14u;

  50.     /* Decrement the loop counter */
  51.     blkCnt--;
  52.   }

  53.   /* If the blockSize is not a multiple of 4, compute any remaining output samples here.   
  54.    ** No loop unrolling is used. */
  55.   blkCnt = blockSize % 0x4u;

  56. #else

  57.   /* Run the below code for Cortex-M0 */

  58.   /* Initialize blkCnt with number of samples */
  59.   blkCnt = blockSize;

  60. #endif /* #ifndef ARM_MATH_CM0_FAMILY */


  61.   while(blkCnt > 0u)
  62.   {
  63.     /* C = A[0]* B[0] + A[1]* B[1] + A[2]* B[2] + .....+ A[blockSize-1]* B[blockSize-1] */
  64.     /* Calculate dot product and then store the result in a temporary buffer. */
  65.     sum += ((q63_t) * pSrcA++ * *pSrcB++) >> 14u;

  66.     /* Decrement the loop counter */
  67.     blkCnt--;
  68.   }

  69.   /* Store the result in the destination buffer in 16.48 format */
  70.   *result = sum;
  71. }
1.     两个Q31格式的32位数相乘,那么输出结果的格式是1.31*1.31 = 2.62。实际应用中基本不需要这么高的精度,这个函数将低14位的数据截取掉,反应在函数中就是两个数的乘积左移14位,也就是定点数的小数点也左移14位,那么最终的结果的格式是16.48。所以只要乘累加的个数小于2^16就没有输出结果溢出的危险(不知道这里为什么不是2^14,留作以后解决)。
2.     将获取的结果左移14位。

8.3.3  arm_dot_prod_q15
    这个函数用于求16位定点数的点乘,源代码分析如下:
  1. /**   
  2. * @brief Dot product of Q15 vectors.   
  3. * @param[in]       *pSrcA points to the first input vector   
  4. * @param[in]       *pSrcB points to the second input vector   
  5. * @param[in]       blockSize number of samples in each vector   
  6. * @param[out]      *result output result returned here   
  7. * @return none.   
  8. *   
  9. * Scaling and Overflow Behavior:                                                             (1)
  10. * par   
  11. * The intermediate multiplications are in 1.15 x 1.15 = 2.30 format and these   
  12. * results are added to a 64-bit accumulator in 34.30 format.   
  13. * Nonsaturating additions are used and given that there are 33 guard bits in the accumulator   
  14. * there is no risk of overflow.   
  15. * The return result is in 34.30 format.   
  16. */

  17. void arm_dot_prod_q15(
  18.   q15_t * pSrcA,
  19.   q15_t * pSrcB,
  20.   uint32_t blockSize,
  21.   q63_t * result)
  22. {
  23.   q63_t sum = 0;                                 /* Temporary result storage */
  24.   uint32_t blkCnt;                               /* loop counter */

  25. #ifndef ARM_MATH_CM0_FAMILY

  26. /* Run the below code for Cortex-M4 and Cortex-M3 */


  27.   /*loop Unrolling */
  28.   blkCnt = blockSize >> 2u;

  29.   /* First part of the processing with loop unrolling.  Compute 4 outputs at a time.   
  30.    ** a second loop below computes the remaining 1 to 3 samples. */
  31.   while(blkCnt > 0u)
  32.   {
  33.     /* C = A[0]* B[0] + A[1]* B[1] + A[2]* B[2] + .....+ A[blockSize-1]* B[blockSize-1] */           (2)
  34.     /* Calculate dot product and then store the result in a temporary buffer. */
  35.     sum = __SMLALD(*__SIMD32(pSrcA)++, *__SIMD32(pSrcB)++, sum);
  36.     sum = __SMLALD(*__SIMD32(pSrcA)++, *__SIMD32(pSrcB)++, sum);

  37.     /* Decrement the loop counter */
  38.     blkCnt--;
  39.   }

  40.   /* If the blockSize is not a multiple of 4, compute any remaining output samples here.   
  41.    ** No loop unrolling is used. */
  42.   blkCnt = blockSize % 0x4u;

  43.   while(blkCnt > 0u)
  44.   {
  45.     /* C = A[0]* B[0] + A[1]* B[1] + A[2]* B[2] + .....+ A[blockSize-1]* B[blockSize-1] */
  46.     /* Calculate dot product and then store the results in a temporary buffer. */
  47.     sum = __SMLALD(*pSrcA++, *pSrcB++, sum);

  48.     /* Decrement the loop counter */
  49.     blkCnt--;
  50.   }


  51. #else

  52.   /* Run the below code for Cortex-M0 */

  53.   /* Initialize blkCnt with number of samples */
  54.   blkCnt = blockSize;

  55.   while(blkCnt > 0u)
  56.   {
  57.     /* C = A[0]* B[0] + A[1]* B[1] + A[2]* B[2] + .....+ A[blockSize-1]* B[blockSize-1] */
  58.     /* Calculate dot product and then store the results in a temporary buffer. */
  59.     sum += (q63_t) ((q31_t) * pSrcA++ * *pSrcB++);

  60.     /* Decrement the loop counter */
  61.     blkCnt--;
  62.   }

  63. #endif /* #ifndef ARM_MATH_CM0_FAMILY */

  64.   /* Store the result in the destination buffer in 34.30 format */
  65.   *result = sum;

  66. }
1. 两个Q15格式的数据相乘,那么输出结果的格式是1.15*1.15 = 2.30,这个函数将输出结果赋值给了64位变量,那么输出结果就是34.30格式。所以基本没有溢出的危险。
2. __SMLALD也是SIMD指令,实现两个16位数相乘,并把结果累加给64位变量。

8.3.4  arm_dot_prod_q7
    这个函数用于求8位定点数的点乘,源代码分析如下:
  1. /**   
  2. * @brief Dot product of Q7 vectors.   
  3. * @param[in]       *pSrcA points to the first input vector   
  4. * @param[in]       *pSrcB points to the second input vector   
  5. * @param[in]       blockSize number of samples in each vector   
  6. * @param[out]      *result output result returned here   
  7. * @return none.   
  8. *   
  9. * Scaling and Overflow Behavior:                                                              (1)
  10. * par   
  11. * The intermediate multiplications are in 1.7 x 1.7 = 2.14 format and these   
  12. * results are added to an accumulator in 18.14 format.   
  13. * Nonsaturating additions are used and there is no danger of wrap around as long as   
  14. * the vectors are less than 2^18 elements long.   
  15. * The return result is in 18.14 format.   
  16. */

  17. void arm_dot_prod_q7(
  18.   q7_t * pSrcA,
  19.   q7_t * pSrcB,
  20.   uint32_t blockSize,
  21.   q31_t * result)
  22. {
  23.   uint32_t blkCnt;                               /* loop counter */

  24.   q31_t sum = 0;                                 /* Temporary variables to store output */

  25. #ifndef ARM_MATH_CM0_FAMILY

  26. /* Run the below code for Cortex-M4 and Cortex-M3 */

  27.   q31_t input1, input2;                          /* Temporary variables to store input */
  28.   q31_t inA1, inA2, inB1, inB2;                  /* Temporary variables to store input */



  29.   /*loop Unrolling */
  30.   blkCnt = blockSize >> 2u;

  31.   /* First part of the processing with loop unrolling.  Compute 4 outputs at a time.   
  32.    ** a second loop below computes the remaining 1 to 3 samples. */
  33.   while(blkCnt > 0u)
  34.   {
  35.     /* read 4 samples at a time from sourceA */                                                       (2)
  36.     input1 = *__SIMD32(pSrcA)++;
  37.     /* read 4 samples at a time from sourceB */
  38.     input2 = *__SIMD32(pSrcB)++;

  39.     /* extract two q7_t samples to q15_t samples */
  40.     inA1 = __SXTB16(__ROR(input1, 8));                                                                (3)
  41.     /* extract reminaing two samples */
  42.     inA2 = __SXTB16(input1);
  43.     /* extract two q7_t samples to q15_t samples */
  44.     inB1 = __SXTB16(__ROR(input2, 8));
  45.     /* extract reminaing two samples */
  46.     inB2 = __SXTB16(input2);

  47.     /* multiply and accumulate two samples at a time */
  48.     sum = __SMLAD(inA1, inB1, sum);                                                                   (4)
  49.     sum = __SMLAD(inA2, inB2, sum);

  50.     /* Decrement the loop counter */
  51.     blkCnt--;
  52.   }

  53.   /* If the blockSize is not a multiple of 4, compute any remaining output samples here.   
  54.    ** No loop unrolling is used. */
  55.   blkCnt = blockSize % 0x4u;

  56.   while(blkCnt > 0u)
  57.   {
  58.     /* C = A[0]* B[0] + A[1]* B[1] + A[2]* B[2] + .....+ A[blockSize-1]* B[blockSize-1] */
  59.     /* Dot product and then store the results in a temporary buffer. */
  60.     sum = __SMLAD(*pSrcA++, *pSrcB++, sum);

  61.     /* Decrement the loop counter */
  62.     blkCnt--;
  63.   }

  64. #else

  65.   /* Run the below code for Cortex-M0 */



  66.   /* Initialize blkCnt with number of samples */
  67.   blkCnt = blockSize;

  68.   while(blkCnt > 0u)
  69.   {
  70.     /* C = A[0]* B[0] + A[1]* B[1] + A[2]* B[2] + .....+ A[blockSize-1]* B[blockSize-1] */
  71.     /* Dot product and then store the results in a temporary buffer. */
  72.     sum += (q31_t) ((q15_t) * pSrcA++ * *pSrcB++);

  73.     /* Decrement the loop counter */
  74.     blkCnt--;
  75.   }

  76. #endif /* #ifndef ARM_MATH_CM0_FAMILY */


  77.   /* Store the result in the destination buffer in 18.14 format */
  78.   *result = sum;
  79. }
1.     两个Q8格式的数据相乘,那么输出结果就是1.7*1.7 = 2.14格式。这里将最终结果赋值给了32位的变量,那么最终的格式就是18.14。如果乘累加的个数小于2^18那么就不会有溢出的危险(感觉这里应该是2^16)。
2.     一次读取4个8位的数据。
3.     __SXTB16也是SIMD指令,用于将两个8位的有符号数扩展成16位。__ROR用于实现数据的循环右移。
4.     __SMLAD也是SIMD指令,用于实现如下功能:
      sum = __SMLAD(x, y, z)
       sum = z + ((short)(x>>16) * (short)(y>>16))+ ((short)x * (short)y)

8.3.5  实例讲解
实验目的:
    1. 四种类型数据的点乘。
实验内容:
    1. 按下按键K3, 串口打印输出结果
实验现象:
           通过窗口上位机软件SecureCRT(V5光盘里面有此软件)查看打印信息现象如下:
8.3.png

程序设计:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: DSP_DotProduct
  4. *    功能说明: 乘积
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void DSP_DotProduct(void)
  10. {
  11.      static float32_t   pSrcA[5] = {1.0f,1.0f,1.0f,1.0f,1.0f};
  12.      static float32_t   pSrcB[5] = {1.0f,1.0f,1.0f,1.0f,1.0f};
  13.      static float32_t   result;
  14.    
  15.      static q31_t  pSrcA1[5] = {0x7ffffff0,1,1,1,1};
  16.      static q31_t  pSrcB1[5] = {1,1,1,1,1};
  17.      static q63_t   result1;  

  18.      static q15_t  pSrcA2[5] = {1,1,1,1,1};
  19.      static q15_t  pSrcB2[5] = {1,1,1,1,1};
  20.      static q63_t  result2;  

  21.      static q7_t  pSrcA3[5] = {1,1,1,1,1};
  22.      static q7_t  pSrcB3[5] = {1,1,1,1,1};
  23.      static q31_t result3;

  24.    
  25.      pSrcA[0] -= 1.1f;
  26.      arm_dot_prod_f32(pSrcA, pSrcB, 5, &result);
  27.      printf("arm_dot_prod_f32 = %frn", result);
  28.    
  29.      pSrcA1[0] -= 0xffff;
  30.      arm_dot_prod_q31(pSrcA1, pSrcB1, 5, &result1);
  31.      printf("arm_dot_prod_q31 = %lldrn", result1);

  32.      pSrcA2[0] -= 1;
  33.      arm_dot_prod_q15(pSrcA2, pSrcB2, 5, &result2);
  34.      printf("arm_dot_prod_q15 = %lldrn", result2);

  35.      pSrcA3[0] -= 1;
  36.      arm_dot_prod_q7(pSrcA3, pSrcB3, 5, &result3);
  37.      printf("arm_dot_prod_q7 = %drn", result3);
  38.      printf("***********************************rn");
  39. }

举报

硬汉Eric2013

2015-6-4 14:36:49
8.4  乘法(Vector Multiplication)
    这部分函数主要用于乘法,公式描述如下:
      pDst[n]= pSrcA[n] * pSrcB[n],   0 <= n
8.4.1  arm_mult_f32
    这个函数用于求32位浮点数的乘法,源代码分析如下:
  1. /**      
  2. * @brief Floating-point vector multiplication.      
  3. * @param[in]       *pSrcA points to the first input vector      
  4. * @param[in]       *pSrcB points to the second input vector      
  5. * @param[out]      *pDst points to the output vector      
  6. * @param[in]       blockSize number of samples in each vector      
  7. * @return none.      
  8. */

  9. void arm_mult_f32(
  10.   float32_t * pSrcA,
  11.   float32_t * pSrcB,
  12.   float32_t * pDst,
  13.   uint32_t blockSize)
  14. {
  15.   uint32_t blkCnt;                               /* loop counters */
  16. #ifndef ARM_MATH_CM0_FAMILY

  17.   /* Run the below code for Cortex-M4 and Cortex-M3 */
  18.   float32_t inA1, inA2, inA3, inA4;              /* temporary input variables */
  19.   float32_t inB1, inB2, inB3, inB4;              /* temporary input variables */
  20.   float32_t out1, out2, out3, out4;              /* temporary output variables */

  21.   /* loop Unrolling */
  22.   blkCnt = blockSize >> 2u;

  23.   /* First part of the processing with loop unrolling.  Compute 4 outputs at a time.      
  24.    ** a second loop below computes the remaining 1 to 3 samples. */
  25.   while(blkCnt > 0u)
  26.   {
  27.     /* C = A * B */
  28.     /* Multiply the inputs and store the results in output buffer */                                 (1)
  29.     /* read sample from sourceA */
  30.     inA1 = *pSrcA;
  31.     /* read sample from sourceB */
  32.     inB1 = *pSrcB;
  33.     /* read sample from sourceA */
  34.     inA2 = *(pSrcA + 1);
  35.     /* read sample from sourceB */
  36.     inB2 = *(pSrcB + 1);

  37.     /* out = sourceA * sourceB */
  38.     out1 = inA1 * inB1;

  39.     /* read sample from sourceA */
  40.     inA3 = *(pSrcA + 2);
  41.     /* read sample from sourceB */
  42.     inB3 = *(pSrcB + 2);

  43.     /* out = sourceA * sourceB */
  44.     out2 = inA2 * inB2;

  45.     /* read sample from sourceA */
  46.     inA4 = *(pSrcA + 3);

  47.     /* store result to destination buffer */
  48.     *pDst = out1;

  49.     /* read sample from sourceB */
  50.     inB4 = *(pSrcB + 3);

  51.     /* out = sourceA * sourceB */
  52.     out3 = inA3 * inB3;

  53.     /* store result to destination buffer */
  54.     *(pDst + 1) = out2;

  55.     /* out = sourceA * sourceB */
  56.     out4 = inA4 * inB4;
  57.     /* store result to destination buffer */
  58.     *(pDst + 2) = out3;
  59.     /* store result to destination buffer */
  60.     *(pDst + 3) = out4;


  61.     /* update pointers to process next samples */
  62.     pSrcA += 4u;
  63.     pSrcB += 4u;
  64.     pDst += 4u;

  65.     /* Decrement the blockSize loop counter */
  66.     blkCnt--;
  67.   }

  68.   /* If the blockSize is not a multiple of 4, compute any remaining output samples here.      
  69.    ** No loop unrolling is used. */
  70.   blkCnt = blockSize % 0x4u;

  71. #else

  72.   /* Run the below code for Cortex-M0 */

  73.   /* Initialize blkCnt with number of samples */
  74.   blkCnt = blockSize;

  75. #endif /* #ifndef ARM_MATH_CM0_FAMILY */

  76.   while(blkCnt > 0u)
  77.   {
  78.     /* C = A * B */
  79.     /* Multiply the inputs and store the results in output buffer */
  80.     *pDst++ = (*pSrcA++) * (*pSrcB++);

  81.     /* Decrement the blockSize loop counter */
  82.     blkCnt--;
  83.   }
  84. }
1.     浮点的32位乘法比较简单,这里依然是以4次的计算为一组。

8.4.2  arm_mult_q31
    这个函数用于求32位定点数的乘法,源代码分析如下:
  1. /**   
  2. * @brief Q31 vector multiplication.   
  3. * @param[in]       *pSrcA points to the first input vector   
  4. * @param[in]       *pSrcB points to the second input vector   
  5. * @param[out]      *pDst points to the output vector   
  6. * @param[in]       blockSize number of samples in each vector   
  7. * @return none.   
  8. *   
  9. * Scaling and Overflow Behavior:                                                             (1)
  10. * par   
  11. * The function uses saturating arithmetic.   
  12. * Results outside of the allowable Q31 range[0x80000000 0x7FFFFFFF] will be saturated.   
  13. */

  14. void arm_mult_q31(
  15.   q31_t * pSrcA,
  16.   q31_t * pSrcB,
  17.   q31_t * pDst,
  18.   uint32_t blockSize)
  19. {
  20.   uint32_t blkCnt;                               /* loop counters */

  21. #ifndef ARM_MATH_CM0_FAMILY

  22. /* Run the below code for Cortex-M4 and Cortex-M3 */
  23.   q31_t inA1, inA2, inA3, inA4;                  /* temporary input variables */
  24.   q31_t inB1, inB2, inB3, inB4;                  /* temporary input variables */
  25.   q31_t out1, out2, out3, out4;                  /* temporary output variables */

  26.   /* loop Unrolling */
  27.   blkCnt = blockSize >> 2u;

  28.   /* First part of the processing with loop unrolling.  Compute 4 outputs at a time.   
  29.    ** a second loop below computes the remaining 1 to 3 samples. */
  30.   while(blkCnt > 0u)
  31.   {
  32.     /* C = A * B */
  33.     /* Multiply the inputs and then store the results in the destination buffer. */
  34.     inA1 = *pSrcA++;
  35.     inA2 = *pSrcA++;
  36.     inA3 = *pSrcA++;
  37.     inA4 = *pSrcA++;
  38.     inB1 = *pSrcB++;
  39.     inB2 = *pSrcB++;
  40.     inB3 = *pSrcB++;
  41.     inB4 = *pSrcB++;

  42.     out1 = ((q63_t) inA1 * inB1) >> 32;                                                              (2)
  43.     out2 = ((q63_t) inA2 * inB2) >> 32;
  44.     out3 = ((q63_t) inA3 * inB3) >> 32;
  45.     out4 = ((q63_t) inA4 * inB4) >> 32;

  46.     out1 = __SSAT(out1, 31);                                                                         (3)
  47.     out2 = __SSAT(out2, 31);
  48.     out3 = __SSAT(out3, 31);
  49.     out4 = __SSAT(out4, 31);

  50.     *pDst++ = out1 << 1u;                                                                            (4)
  51.     *pDst++ = out2 << 1u;
  52.     *pDst++ = out3 << 1u;
  53.     *pDst++ = out4 << 1u;

  54.     /* Decrement the blockSize loop counter */
  55.     blkCnt--;
  56.   }

  57.   /* If the blockSize is not a multiple of 4, compute any remaining output samples here.   
  58.    ** No loop unrolling is used. */
  59.   blkCnt = blockSize % 0x4u;

  60. #else

  61.   /* Run the below code for Cortex-M0 */

  62.   /* Initialize blkCnt with number of samples */
  63.   blkCnt = blockSize;

  64. #endif /* #ifndef ARM_MATH_CM0_FAMILY */

  65.   while(blkCnt > 0u)
  66.   {
  67.     /* C = A * B */
  68.     /* Multiply the inputs and then store the results in the destination buffer. */
  69.     *pDst++ =
  70.       (q31_t) clip_q63_to_q31(((q63_t) (*pSrcA++) * (*pSrcB++)) >> 31);

  71.     /* Decrement the blockSize loop counter */
  72.     blkCnt--;
  73.   }
  74. }
1.     这个函数使用了饱和算法。
    所得结果是Q31格式,范围Q31range[0x80000000 0x7FFFFFFF]。
2.     所得乘积左移32位。
3.     实现31位精度的饱和运算。
4.     右移一位,保证所得结果是Q31格式。

8.4.3  arm_mult_q15
    这个函数用于求16位定点数的乘法,源代码分析如下:
  1. /**   
  2. * @brief           Q15 vector multiplication   
  3. * @param[in]       *pSrcA points to the first input vector   
  4. * @param[in]       *pSrcB points to the second input vector   
  5. * @param[out]      *pDst points to the output vector   
  6. * @param[in]       blockSize number of samples in each vector   
  7. * @return none.   
  8. *   
  9. * Scaling and Overflow Behavior:                                                              (1)
  10. * par   
  11. * The function uses saturating arithmetic.   
  12. * Results outside of the allowable Q15 range [0x8000 0x7FFF] will be saturated.   
  13. */

  14. void arm_mult_q15(
  15.   q15_t * pSrcA,
  16.   q15_t * pSrcB,
  17.   q15_t * pDst,
  18.   uint32_t blockSize)
  19. {
  20.   uint32_t blkCnt;                               /* loop counters */

  21. #ifndef ARM_MATH_CM0_FAMILY

  22. /* Run the below code for Cortex-M4 and Cortex-M3 */
  23.   q31_t inA1, inA2, inB1, inB2;                  /* temporary input variables */
  24.   q15_t out1, out2, out3, out4;                  /* temporary output variables */
  25.   q31_t mul1, mul2, mul3, mul4;                  /* temporary variables */

  26.   /* loop Unrolling */
  27.   blkCnt = blockSize >> 2u;

  28.   /* First part of the processing with loop unrolling.  Compute 4 outputs at a time.      
  29.    ** a second loop below computes the remaining 1 to 3 samples. */
  30.   while(blkCnt > 0u)
  31.   {
  32.     /* read two samples at a time from sourceA */
  33.     inA1 = *__SIMD32(pSrcA)++;                                                                     (2)
  34.     /* read two samples at a time from sourceB */
  35.     inB1 = *__SIMD32(pSrcB)++;
  36.     /* read two samples at a time from sourceA */
  37.     inA2 = *__SIMD32(pSrcA)++;
  38.     /* read two samples at a time from sourceB */
  39.     inB2 = *__SIMD32(pSrcB)++;

  40.     /* multiply mul = sourceA * sourceB */
  41.     mul1 = (q31_t) ((q15_t) (inA1 >> 16) * (q15_t) (inB1 >> 16));                                  (3)
  42.     mul2 = (q31_t) ((q15_t) inA1 * (q15_t) inB1);
  43.     mul3 = (q31_t) ((q15_t) (inA2 >> 16) * (q15_t) (inB2 >> 16));
  44.     mul4 = (q31_t) ((q15_t) inA2 * (q15_t) inB2);

  45.     /* saturate result to 16 bit */
  46.     out1 = (q15_t) __SSAT(mul1 >> 15, 16);                                                         (4)
  47.     out2 = (q15_t) __SSAT(mul2 >> 15, 16);
  48.     out3 = (q15_t) __SSAT(mul3 >> 15, 16);
  49.     out4 = (q15_t) __SSAT(mul4 >> 15, 16);

  50.     /* store the result */
  51. #ifndef ARM_MATH_BIG_ENDIAN

  52.     *__SIMD32(pDst)++ = __PKHBT(out2, out1, 16);                                                   (5)
  53.     *__SIMD32(pDst)++ = __PKHBT(out4, out3, 16);

  54. #else

  55.     *__SIMD32(pDst)++ = __PKHBT(out2, out1, 16);
  56.     *__SIMD32(pDst)++ = __PKHBT(out4, out3, 16);

  57. #endif //      #ifndef ARM_MATH_BIG_ENDIAN

  58.     /* Decrement the blockSize loop counter */
  59.     blkCnt--;
  60.   }

  61.   /* If the blockSize is not a multiple of 4, compute any remaining output samples here.   
  62.    ** No loop unrolling is used. */
  63.   blkCnt = blockSize % 0x4u;

  64. #else

  65.   /* Run the below code for Cortex-M0 */

  66.   /* Initialize blkCnt with number of samples */
  67.   blkCnt = blockSize;

  68. #endif /* #ifndef ARM_MATH_CM0_FAMILY */


  69.   while(blkCnt > 0u)
  70.   {
  71.     /* C = A * B */
  72.     /* Multiply the inputs and store the result in the destination buffer */
  73.     *pDst++ = (q15_t) __SSAT((((q31_t) (*pSrcA++) * (*pSrcB++)) >> 15), 16);

  74.     /* Decrement the blockSize loop counter */
  75.     blkCnt--;
  76.   }
  77. }
1.     这个函数使用了饱和算法。
    所得结果是Q15格式,范围[0x8000  0x7FFF]。
2.     一次读取两个Q15格式的数据。
3.     将四组数的乘积保存到Q31格式的变量mul1,mul2,mul3,mul4。
4.     丢弃32位数据的低15位,并把最终结果饱和到16位精度。
5.     通过SIMD指令__PKHBT将两个Q15格式的数据保存的结果数组中,从而一个指令周期就能完成两个数据的存储。

8.4.4  arm_mult_q7
    这个函数用于求8位定点数的乘法,源代码分析如下:
  1. /**   
  2. * @brief           Q7 vector multiplication   
  3. * @param[in]       *pSrcA points to the first input vector   
  4. * @param[in]       *pSrcB points to the second input vector   
  5. * @param[out]      *pDst points to the output vector   
  6. * @param[in]       blockSize number of samples in each vector   
  7. * @return none.   
  8. *   
  9. * Scaling and Overflow Behavior:                                                             (1)
  10. * par   
  11. * The function uses saturating arithmetic.   
  12. * Results outside of the allowable Q7 range [0x80 0x7F] will be saturated.   
  13. */

  14. void arm_mult_q7(
  15.   q7_t * pSrcA,
  16.   q7_t * pSrcB,
  17.   q7_t * pDst,
  18.   uint32_t blockSize)
  19. {
  20.   uint32_t blkCnt;                               /* loop counters */

  21. #ifndef ARM_MATH_CM0_FAMILY

  22. /* Run the below code for Cortex-M4 and Cortex-M3 */
  23.   q7_t out1, out2, out3, out4;                   /* Temporary variables to store the product */

  24.   /* loop Unrolling */
  25.   blkCnt = blockSize >> 2u;

  26.   /* First part of the processing with loop unrolling.  Compute 4 outputs at a time.   
  27.    ** a second loop below computes the remaining 1 to 3 samples. */
  28.   while(blkCnt > 0u)
  29.   {
  30.     /* C = A * B */
  31.     /* Multiply the inputs and store the results in temporary variables */                          (2)
  32.     out1 = (q7_t) __SSAT((((q15_t) (*pSrcA++) * (*pSrcB++)) >> 7), 8);
  33.     out2 = (q7_t) __SSAT((((q15_t) (*pSrcA++) * (*pSrcB++)) >> 7), 8);
  34.     out3 = (q7_t) __SSAT((((q15_t) (*pSrcA++) * (*pSrcB++)) >> 7), 8);
  35.     out4 = (q7_t) __SSAT((((q15_t) (*pSrcA++) * (*pSrcB++)) >> 7), 8);

  36.     /* Store the results of 4 inputs in the destination buffer in single cycle by packing */
  37.     *__SIMD32(pDst)++ = __PACKq7(out1, out2, out3, out4);                                          (3)

  38.     /* Decrement the blockSize loop counter */
  39.     blkCnt--;
  40.   }

  41.   /* If the blockSize is not a multiple of 4, compute any remaining output samples here.   
  42.    ** No loop unrolling is used. */
  43.   blkCnt = blockSize % 0x4u;

  44. #else

  45.   /* Run the below code for Cortex-M0 */

  46.   /* Initialize blkCnt with number of samples */
  47.   blkCnt = blockSize;

  48. #endif /* #ifndef ARM_MATH_CM0_FAMILY */


  49.   while(blkCnt > 0u)
  50.   {
  51.     /* C = A * B */
  52.     /* Multiply the inputs and store the result in the destination buffer */
  53.     *pDst++ = (q7_t) __SSAT((((q15_t) (*pSrcA++) * (*pSrcB++)) >> 7), 8);

  54.     /* Decrement the blockSize loop counter */
  55.     blkCnt--;
  56.   }
  57. }
1.     这个函数使用了饱和算法。
    所得结果是Q7格式,范围 [0x80 0x7F]。
2.     将两个Q7格式的数据乘积左移7位,也就是丢掉低7位的数据,并将所得结果饱和到8位精度。
3.     __PACKq7函数可以在一个时钟周期就能完成相应操作。

8.4.5  实例讲解
实验目的:
    1. 四种类型数据的乘法。
实验内容:
    1. 按下摇杆的UP键, 串口打印输出结果
实验现象:
           通过窗口上位机软件SecureCRT(V5光盘里面有此软件)查看打印信息现象如下:
8.4.png

程序设计:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: DSP_Multiplication
  4. *    功能说明: 乘法
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void DSP_Multiplication(void)
  10. {
  11.      static float32_t   pSrcA[5] = {1.0f,1.0f,1.0f,1.0f,1.0f};
  12.      static float32_t   pSrcB[5] = {1.0f,1.0f,1.0f,1.0f,1.0f};
  13.      static float32_t   pDst[5];
  14.    
  15.      static q31_t  pSrcA1[5] = {1,1,1,1,1};
  16.      static q31_t  pSrcB1[5] = {1,1,1,1,1};
  17.      static q31_t  pDst1[5];  

  18.      static q15_t  pSrcA2[5] = {1,1,1,1,1};
  19.      static q15_t  pSrcB2[5] = {1,1,1,1,1};
  20.      static q15_t  pDst2[5];  

  21.      static q7_t  pSrcA3[5] = {0x70,1,1,1,1};
  22.      static q7_t  pSrcB3[5] = {0x7f,1,1,1,1};
  23.      static q7_t pDst3[5];

  24.    
  25.      pSrcA[0] += 1.1f;
  26.      arm_mult_f32(pSrcA, pSrcB, pDst, 5);
  27.      printf("arm_mult_f32 = %frn", pDst[0]);
  28.    
  29.      pSrcA1[0] += 1;
  30.      arm_mult_q31(pSrcA1, pSrcB1, pDst1, 5);
  31.      printf("arm_mult_q31 = %drn", pDst1[0]);

  32.      pSrcA2[0] += 1;
  33.      arm_mult_q15(pSrcA2, pSrcB2, pDst2, 5);
  34.      printf("arm_mult_q15 = %drn", pDst2[0]);

  35.      pSrcA3[0] += 1;
  36.      arm_mult_q7(pSrcA3, pSrcB3, pDst3, 5);
  37.      printf("arm_mult_q7 = %drn", pDst3[0]);
  38.      printf("***********************************rn");
  39. }

硬汉Eric2013

2015-6-4 14:37:43
8.5  总结
    本期教程就跟大家讲这么多,还是那句话,可以自己写些代码调用本期教程中讲的这几个函数,如果可以的话,可以自己尝试直接调用这些DSP指令。

举报

更多回帖

×
20
完善资料,
赚取积分