OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3329|回复: 4

使用DMA传输时,CPU停止运行了...

[复制链接]

68

主题

165

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
388
金钱
388
注册时间
2017-3-2
在线时间
156 小时
发表于 2019-5-11 14:53:09 | 显示全部楼层 |阅读模式
1金钱
本帖最后由 kokoromi 于 2019-5-14 12:27 编辑

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

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

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

57

主题

1680

帖子

3

精华

资深版主

Rank: 8Rank: 8

积分
4306
金钱
4306
注册时间
2018-6-30
在线时间
808 小时
发表于 2019-5-11 18:01:48 | 显示全部楼层
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2019-5-13 02:42:23 | 显示全部楼层
帮顶
回复

使用道具 举报

37

主题

596

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1574
金钱
1574
注册时间
2017-7-17
在线时间
308 小时
发表于 2019-5-13 08:41:23 | 显示全部楼层
那你可以看看HAL_HASH_MD5_Start_DMA这个函数里是不是有while的等待结构存在。
回复

使用道具 举报

68

主题

165

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
388
金钱
388
注册时间
2017-3-2
在线时间
156 小时
 楼主| 发表于 2019-5-13 09:12:56 | 显示全部楼层
本帖最后由 kokoromi 于 2019-5-13 09:17 编辑
candylife9 发表于 2019-5-13 08:41
那你可以看看HAL_HASH_MD5_Start_DMA这个函数里是不是有while的等待结构存在。

没有啊,DMA这个功能不是第一次用了,其他模块的都用过,启动了DMA后CPU都可以继续执行程序,但是这个HASH模块不知道怎么回事,我用uCOS的时间戳函数测量了时间,下面的是HAL的程序,我在里面加入了测量时间功能:
[mw_shl_code=c,true]HAL_StatusTypeDef HASH_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
{
  uint32_t inputaddr;
  uint32_t inputSize;
  HAL_StatusTypeDef status ;
  HAL_HASH_StateTypeDef State_tmp = hhash->State;

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


    /* Process Locked */
    __HAL_LOCK(hhash);

    /* If not a resumption case */
    if (hhash->State == HAL_HASH_STATE_READY)
    {
      /* Change the HASH state */
      hhash->State = HAL_HASH_STATE_BUSY;

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

        /* Set the phase */
        hhash->hase = HAL_HASH_PHASE_PROCESS;
      }

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

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

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

    }
    /* If resumption case */
    else
    {
      /* Change the HASH state */
      hhash->State = HAL_HASH_STATE_BUSY;

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

    }

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

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

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

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

    /* Process Unlock */
    __HAL_UNLOCK(hhash);

    /* Return function status */
    if (status != HAL_OK)
    {
      /* Update HASH state machine to error */
      hhash->State = HAL_HASH_STATE_ERROR;      
    }
    else
    {
      /* Change HASH state */
      hhash->State = HAL_HASH_STATE_READY;
    }

    return status;
  }
  else
  {
    return HAL_BUSY;
  }
}[/mw_shl_code]


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-11 13:24

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表