понедельник, 25 сентября 2017 г.

STM32 HAL_SPI_TransmitReceive_DMA restart bug

  Захотелось мне перезапустить трансфер SPI прямо в колбэке HAL_SPI_TxRxCpltCallback. Казалось бы, из названия колбэка ясно, что вызывается он, когда и Tx и Rx полностью завершены и нет причин, почему в этом же колбэке нельзя запустить новый трансфер.

  А вот и есть: рукожопость.  Если внутри HAL_SPI_TxRxCpltCallback снова вызвать HAL_SPI_TransmitReceive_DMA, то трансфер никогда не завершится.

  А вот почему? Изначально не понятно, я же хорошо написал код, захендлил все Error code-ы библиотеки и если что-то не так, то я бы увидел в терминале ошибку и код автоматом бы мне вызвал breakpoint. Но всё вроде как ок, ошибок нет!

  Проверил под дебаггером - да,  HAL_SPI_TransmitReceive_DMA во второй раз возвращает HAL_OK! Статусы/регистры все сконфигурены корректно в SPI, стейт BUSY но прерываний нет... о_О

  Но не стоит недооценивать разработчиков HAL библиотеки, они те ещё рукожопы. Вспомнил я как несколько лет назад писал им в саппорт и уведомлял о баге, но конечно же его не починили )

Часть кода функции HAL_SPI_TransmitReceive_DMA:

/* Set the DMA AbortCpltCallback */
hspi->hdmarx->XferAbortCallback = NULL;
/* Enable the Rx DMA Stream/Channel  */
HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->DR, (uint32_t)hspi->pRxBuffPtr, hspi->RxXferCount);
/* Enable Rx DMA Request */
SET_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);


  HAL_DMA_Start_IT возвращает код ошибки, который благополучно игнорируется! И кажется, что всё ОК )) А на самом деле HAL_SPI_TxRxCpltCallback  вызывается из прерывания RX DMA канала, а обработчик TX канала ещё не вызывался к этому моменту (он вызовется после RX канала).  И получается, что в колбэке RX DMA канала я перезапускаю передачу, которая не смогла запустить TX DMA канал  (он ещё не разлочен своим обработчиком прерывания) и потому всё висит.

  Это восхитительно.  Мало того, что TX прерывания ещё не было, но уже вызвался HAL_SPI_TxRxCpltCallback , так ещё и коды ошибок нагло игнорируются, вводя в глубочайшее заблуждение. Вот как так?  Железо у ST отличное, а код - говно...

Комментариев нет:

Отправить комментарий