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

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管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版