将自动变量的指针传递给 DMA 函数

Passing pointer of automatic variable to DMA function

问题专门针对使用 DMA 的 STM32 微控制器。

考虑以下几点:

while(true){
    randomStuff();
    uint16_t distance;
    getDistance(&distance);
    HAL_UART_Transmit_DMA((uint8_t*)&distance, 2);
    doOtherStuff();
}

现在通常在使用单线程时这会很好,因为执行遵循线性流程并且在被调用函数完成之前距离不会超出范围。然而,这是对不阻塞并允许继续执行的 DMA 外设的特殊调用,因此超出了 "distance" 变量的范围。

在这个 DMA 函数中,我可以看到指针被复制了:

huart->pTxBuffPtr = pData;

之后,它调用 TDR 应该是目标地址的地方:

HAL_DMA_Start_IT(huart->hdmatx, (uint32_t)huart->pTxBuffPtr, (uint32_t)&huart->Instance->TDR, Size);

我不清楚指针的使用何时结束以及我的作用域何时结束。这样做安全吗?

我想避免使用动态分配,因为它是一个嵌入式系统,如果您过度使用动态分配,它很容易变得支离破碎并崩溃。

函数

HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

获取指针 pData 并立即复制到

huart->pTxBuffPtr = pData;

但该值并未实际使用或发送,因为在几行之后您会发现:

tmp = (uint32_t*)&pData;

然后:

HAL_DMA_Start_IT(huart->hdmatx, *(uint32_t*)tmp, (uint32_t)&huart->Instance->DR, Size);

所以当 &pData 被复制到 tmp 时使用你的指针,然后一直在 DMA 调用中一直使用直到DMA 配置为:

hdma->Instance->M0AR = SrcAddress;

因此这是不安全的,因为从那里你知道的下一件事是 TX 中断从 DMA 完成。所以最后当你 return 来自

HAL_UART_Transmit_DMA

并分支到

doOtherStuff();

您可能还在使用教鞭。如前所述,将其声明为静态是一种解决方案,因为如果您使用 &distance.

再次调用 DMA 传输,内部状态机将防止出现问题