Jump to content

    

DMA UART выравнивание адреса по u16

Recommended Posts

Nosaer

Доброго времени суток.

UART работает в 9 битном режиме. Девятый бит мне как таковое не интересен, поэтому я его всегда отбрасываю и собираю данные в 8 битный буфер.

При запуске DMA на прием данных:

uint8_t Data[BUFFER_SIZE] = {0};
HAL_UART_Receive_DMA(BKI_UART, &Data[Index], BUFFER_SIZE);

В тех случаях когда Index нечетное значение, получаю HAL_ERROR

HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  /* In case of 9bits/No Parity transfer, pData buffer provided as input parameter
       should be aligned on a u16 frontier, as data copy from RDR will be
       handled by DMA from a u16 frontier. */
    if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
    {
      if ((((uint32_t)pData) & 1U) != 0U)
      {
        return  HAL_ERROR;
      }
    }

Собственно вопрос, можно ли как то это обойти?

Share this post


Link to post
Share on other sites

Arlleex

1. Какой МК? Откуда такая повальная привычка у многих не писать эту информацию..?
2. Почему в HAL_UART_Receive_DMA() передаете BUFFER_SIZE? Переполнение не возможно?
3. Ну Вам же прямо в функции комментарий дается - вроде, даже понятно почему так делать нельзя. Или нет?

Цитата

Собственно вопрос, можно ли как то это обойти?

С UART RDR в 9-битном режиме нужно оперировать в 16-битном доступе на чтение. Либо используйте 8-битный формат.

Share this post


Link to post
Share on other sites

Nosaer

1) STM32G071

2) Размер буфера взят с большим запасом. В прерывании по простою вычисляю сколько данных пришло.

3) Я понимаю, что нельзя и почему. Но надеялся, что есть какого то рода обходные пути, чтоб как можно меньше исправлять уже в существующей программе. 

 

Как вариант нашел это: https://blog.ghmit.com.au/2019/09/stm32-9-bit-uart-halerror.html

Но пока разбираюсь и не совсем понимаю как это реализовать. 

Share this post


Link to post
Share on other sites

Nosaer

Arlleex, большое спасибо.

 //   if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
 //   {
 //     if ((((uint32_t)pData) & 1U) != 0U)
 //     {
 //       return  HAL_ERROR;
 //     }
 //   }

Решило всю проблему, МК и в самом деле автоматически подстраивается

Share this post


Link to post
Share on other sites

Arlleex

Я не это имел в виду... Я говорил о том, что DMA нужно настроить так, чтобы он читал из RDR UART-а 16-битными полусловами, затем обрезал старший байт, а младший помещал в указанный буфер памяти с инкрементом в 1 байт. Тогда Ваш ненужный 1 бит автоматически не попадал бы в приемный буфер. А что сейчас там в этом HAL_UART... мне не ведомо, и возможно, DMA работает криво, на самом деле лишь изображая "правильное" поведение.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.