Передача указателя автоматической переменной в функцию DMA - PullRequest
0 голосов
/ 05 февраля 2019

Вопрос конкретно о микроконтроллерах STM32, использующих DMA.

Примите во внимание следующее:

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);

Мне не ясно, в какой момент заканчивается использование моего указателя, а когда заканчивается мой объем.Это безопасно сделать?

Я хочу избегать использования динамического выделения, потому что это встроенная система, которая имеет тенденцию фрагментироваться и зависать при чрезмерном использовании динамического выделения.

1 Ответ

0 голосов
/ 09 февраля 2019

Функция

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.Таким образом, в конце концов, когда вы вернетесь от

HAL_UART_Transmit_DMA

и перейдете к

doOtherStuff();

Возможно, вы все еще используете указатель.Как уже упоминалось, объявление статического является решением, потому что внутренний конечный автомат предотвращает возникновение проблем, если вы снова вызываете передачу DMA с помощью & distance .

...