你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

F439的HASH模块DMA传输计算问题

[复制链接]
kokoro 提问时间:2019-5-16 08:37 /
本帖最后由 kokoromi 于 2019-5-16 08:38 编辑

项目中需要使用439的的HASH模块计算文件的MD5值,使用的DMA方式,为了提高CPU效率,让其他任务在DMA传输数据、硬件计算MD5期间可以得到运行,DMA的数据来自FMC外扩的SDRAM。


现在的问题是,经过多次调试发现,启动DMA传输后 CPU貌似没运行代码,而是等DMA传输和计算都完成了之后才运行后面的代码,我使用时间戳功能测量了函数 HAL_HASH_MD5_Start_DMA 的运行时间,得到的时间就是DMA传入数据和MD5计算的时间,也就是说,这个函数里面启动了DMA传输后 程序就停了,等整个MD5都计算完了才从这个函数中出来,很是费解,我看了下总线矩阵,也没冲突的地方啊,为什么会出现这个情况...有人知道吗?

下面的是HAL的程序,我在里面加入了测量时间功能,86-89行是我指出的有问题的地方
  1. HAL_StatusTypeDef HASH_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
  2. {
  3.   uint32_t inputaddr;
  4.   uint32_t inputSize;
  5.   HAL_StatusTypeDef status ;
  6.   HAL_HASH_StateTypeDef State_tmp = hhash->State;

  7. #if defined (HASH_CR_MDMAT)
  8.   /* Make sure the input buffer size (in bytes) is a multiple of 4 when MDMAT bit is set
  9.      (case of multi-buffer HASH processing) */
  10.   assert_param(IS_HASH_DMA_MULTIBUFFER_SIZE(Size));
  11. #endif /* MDMA defined*/
  12.    /* If State is ready or suspended, start or resume polling-based HASH processing */
  13. if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
  14.   {
  15.     /* Check input parameters */
  16.     if ( (pInBuffer == NULL ) || (Size == 0U) ||
  17.     /* Check phase coherency. Phase must be
  18.        either READY (fresh start)
  19.        or PROCESS (multi-buffer HASH management) */
  20.        ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HASH_PROCESSING(hhash)))))
  21.     {
  22.       hhash->State = HAL_HASH_STATE_READY;
  23.       return  HAL_ERROR;
  24.     }


  25.     /* Process Locked */
  26.     __HAL_LOCK(hhash);

  27.     /* If not a resumption case */
  28.     if (hhash->State == HAL_HASH_STATE_READY)
  29.     {
  30.       /* Change the HASH state */
  31.       hhash->State = HAL_HASH_STATE_BUSY;

  32.       /* Check if initialization phase has already been performed.
  33.          If Phase is already set to HAL_HASH_PHASE_PROCESS, this means the
  34.          API is processing a new input data message in case of multi-buffer HASH
  35.          computation. */
  36.       if(hhash->Phase == HAL_HASH_PHASE_READY)
  37.       {
  38.         /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
  39.         MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_CR_INIT);

  40.         /* Set the phase */
  41.         hhash->Phase = HAL_HASH_PHASE_PROCESS;
  42.       }

  43.       /* Configure the Number of valid bits in last word of the message */
  44.       __HAL_HASH_SET_NBVALIDBITS(Size);

  45.       inputaddr = (uint32_t)pInBuffer;     /* DMA transfer start address   */
  46.       inputSize = Size;                    /* DMA transfer size (in bytes) */

  47.       /* In case of suspension request, save the starting parameters */
  48.       hhash->pHashInBuffPtr =  pInBuffer;  /* DMA transfer start address   */
  49.       hhash->HashInCount = Size;           /* DMA transfer size (in bytes) */

  50.     }
  51.     /* If resumption case */
  52.     else
  53.     {
  54.       /* Change the HASH state */
  55.       hhash->State = HAL_HASH_STATE_BUSY;

  56.       /* Resumption case, inputaddr and inputSize are not set to the API input parameters
  57.          but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
  58.          processing was suspended */
  59.       inputaddr = (uint32_t)hhash->pHashInBuffPtr;  /* DMA transfer start address   */
  60.       inputSize = hhash->HashInCount;               /* DMA transfer size (in bytes) */

  61.     }

  62.     /* Set the HASH DMA transfert complete callback */
  63.     hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
  64.     /* Set the DMA error callback */
  65.     hhash->hdmain->XferErrorCallback = HASH_DMAError;

  66.     /* Store number of words already pushed to manage proper DMA processing suspension */
  67.     hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();

  68.     /* Enable the DMA In DMA Stream */
  69.     status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (((inputSize %4U)!=0U) ? ((inputSize+(4U-(inputSize %4U)))/4U):(inputSize/4U)));

  70. sts = OS_TS_GET(); //获取时间戳;
  71.     /* Enable DMA requests */
  72.     SET_BIT(HASH->CR, HASH_CR_DMAE); //就是这一句,执行完这一句按理说程序应该继续往下执行,但是实际上经过时间戳的测量,执行完这句耗费了约 4ms,这个时间正好是DMA传输数据+MD5的计算时间。
  73. ets = OS_TS_GET() - sts; //计算耗费的时间

  74.     /* Process Unlock */
  75.     __HAL_UNLOCK(hhash);

  76.     /* Return function status */
  77.     if (status != HAL_OK)
  78.     {
  79.       /* Update HASH state machine to error */
  80.       hhash->State = HAL_HASH_STATE_ERROR;      
  81.     }
  82.     else
  83.     {
  84.       /* Change HASH state */
  85.       hhash->State = HAL_HASH_STATE_READY;
  86.     }

  87.     return status;
  88.   }
  89.   else
  90.   {
  91.     return HAL_BUSY;
  92.   }
  93. }
复制代码



收藏 评论3 发布时间:2019-5-16 08:37

举报

3个回答
kokoro 回答时间:2019-5-19 08:39:56
我昨天又试了 AES加密模块,发现也存在同样的问题,不由得猜测,是不是挂在AHB2总线上的外设都存在DMA传输导致CPU挂起的情况啊。没人有过这俩模块吗?
edmundlee 回答时间:2019-5-19 18:16:25
建议你用IO翻转来代替OS_TS_GET()测量时间。
M0~M4 的DMA我都用过, 没发现过有你说的问题

评分

参与人数 1蝴蝶豆 +2 收起 理由
STMCU + 2

查看全部评分

kokoro 回答时间:2019-5-20 12:22:44
edmundlee 发表于 2019-5-19 18:16
建议你用IO翻转来代替OS_TS_GET()测量时间。
M0~M4 的DMA我都用过, 没发现过有你说的问题 ...

我其他外设的DMA用着都没问题,就AHB2总线上的加密和哈西处理器由这个问题。

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版