Перейти к содержанию
    

Пытаюсь освоить HAL

МК - STM32F407IG, CubeIDE. Задача простая: принимаю по UART от ПК пакет, для конкретики 12 байт, но это не важно, с использованием DMA. По полному приёму срабатывает прерывание, я переписываю из одного буфера во второй и из второго буфера отправляю данные обратно на ПК, опять таки через DMA. Первичные настройки делал в Cube, в смысле автоконфигураторе. Настройка DMA на приём - циклический режим. На передачу - однократный. Надо сделать это исключительно средствами HAL (на регистрах всё работает).

На приём всё работает как нормуль, претензий нет. А вот на передачу.... - один раз срабатывает (самый первый раз, после сброса МК), а далее затыкается. И ни как я это "победють" не могу.

void DMA2_Stream2_IRQHandler(void)
{
  /* USER CODE BEGIN DMA2_Stream2_IRQn 0 */

  /* USER CODE END DMA2_Stream2_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_usart1_rx);
  /* USER CODE BEGIN DMA2_Stream2_IRQn 1 */

  for(uart_count=0; uart_count <12; uart_count++ )
  	{
  		UART1_Tx[uart_count] = UART1_Rx[uart_count];
  	}


  HAL_UART_Transmit_DMA(&huart1, UART1_Tx, 12);

  	count_uart++;
  /* USER CODE END DMA2_Stream2_IRQn 1 */

Stream2 - прерывание по полному приёму. Переменная count_uart - для отладки.

void DMA2_Stream7_IRQHandler(void)
{
  /* USER CODE BEGIN DMA2_Stream7_IRQn 0 */
												
  /* USER CODE END DMA2_Stream7_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_usart1_tx);
  /* USER CODE BEGIN DMA2_Stream7_IRQn 1 */
  test1 = DMA2_Stream7->CR;
  test2 = 0;
  test3 = 0;

//  DMA2_Stream7->CR = 0x50;
//DMA_Tx_flag = 1; 
  DMA_Tx_flag++;

  DMA2->LIFCR |= 0xFFFFFFFF;
  DMA2->HIFCR |= 0xFFFFFFFF;
  /* USER CODE END DMA2_Stream7_IRQn 1 */
}

Stream7 - прерывание по окончанию передачи, основное здесь - поставить флаг: DMA_Tx_flag. На остальное не обращайте внимание, это попытки хоть как-то решить проблему. Хотя эти попытки опять таки через регистры, но надо через HAL. По возможности. Видимо пропустил какую-то функцию, которая взводит процесс на начало.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, Vlad_G сказал:

На приём всё работает как нормуль, претензий нет. А вот на передачу.... - один раз срабатывает (самый первый раз, после сброса МК), а далее затыкается.

Вот это самое "затыкается" хорошо бы расшифровать. Данные не доходят до буфера DMA, или DMA не запускается, или еще дальше по цепи...

Если один раз срабатывает- это значит что-то в инициализации DMA, или в самом USART что-то происходит- посмотрите флаги ошибок.

Конечно, все это дебаггером и пошагово внутрь функций, насколько возможно.

P.S. А зачем себя так истязать? Если "на регистрах" уже все работало... 🙂

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, Vlad_G said:

МК - STM32F407IG, CubeIDE. Задача простая: принимаю по UART от ПК пакет, для конкретики 12 байт, но это не важно, с использованием DMA. По полному приёму срабатывает прерывание, я переписываю из одного буфера во второй и из второго буфера отправляю данные обратно на ПК, опять таки через DMA. Первичные настройки делал в Cube, в смысле автоконфигураторе. Настройка DMA на приём - циклический режим. На передачу - однократный. Надо сделать это исключительно средствами HAL (на регистрах всё работает).

На приём всё работает как нормуль, претензий нет. А вот на передачу.... - один раз срабатывает (самый первый раз, после сброса МК), а далее затыкается. И ни как я это "победють" не могу.

void DMA2_Stream2_IRQHandler(void)
{
  /* USER CODE BEGIN DMA2_Stream2_IRQn 0 */

  /* USER CODE END DMA2_Stream2_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_usart1_rx);
  /* USER CODE BEGIN DMA2_Stream2_IRQn 1 */

  for(uart_count=0; uart_count <12; uart_count++ )
  	{
  		UART1_Tx[uart_count] = UART1_Rx[uart_count];
  	}


  HAL_UART_Transmit_DMA(&huart1, UART1_Tx, 12);

  	count_uart++;
  /* USER CODE END DMA2_Stream2_IRQn 1 */

Stream2 - прерывание по полному приёму. Переменная count_uart - для отладки.

void DMA2_Stream7_IRQHandler(void)
{
  /* USER CODE BEGIN DMA2_Stream7_IRQn 0 */
												
  /* USER CODE END DMA2_Stream7_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_usart1_tx);
  /* USER CODE BEGIN DMA2_Stream7_IRQn 1 */
  test1 = DMA2_Stream7->CR;
  test2 = 0;
  test3 = 0;

//  DMA2_Stream7->CR = 0x50;
//DMA_Tx_flag = 1; 
  DMA_Tx_flag++;

  DMA2->LIFCR |= 0xFFFFFFFF;
  DMA2->HIFCR |= 0xFFFFFFFF;
  /* USER CODE END DMA2_Stream7_IRQn 1 */
}

Stream7 - прерывание по окончанию передачи, основное здесь - поставить флаг: DMA_Tx_flag. На остальное не обращайте внимание, это попытки хоть как-то решить проблему. Хотя эти попытки опять таки через регистры, но надо через HAL. По возможности. Видимо пропустил какую-то функцию, которая взводит процесс на начало.

volatile ... DMA_Tx_flag

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, Ruslan1 сказал:

P.S. А зачем себя так истязать?

Новые веяния, с новым начальством. С другой стороны, сложность проектов растёт. Кто прав, как знать...

3 часа назад, Ruslan1 сказал:

хорошо бы расшифровать

Сейчас этим и занимаюсь в свободное время. Отладчик CubeIDE не работает (вот тоже напасть) - ошибка GDB сервера. Посмотрю позжее. Пользую STMStudio, тоже не фонтан, но что-то можно.

А так при первом вызове конструкции: HAL_UART_Transmit_DMA(&huart1, UART1_Tx, 12); - работает, данные передаются. При втором и последующих вызовах ничего не происходит, передачи нет. При этом приём от ПК идёт нормально, подпрограмма прерывания по приёму отрабатывает своё.  Может перед вызовом этой функции надо ещё какие действия предпринять и (или) после вызова тоже? А может я вообще всё неправильно понял и выбрал не ту функцию?

Ещё такой вопрос. Есть ли мануал по HAL, типа - Code Examples?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Продолжаю тему. Анализ регистров в отладчике показал, что при начальной инициализации устанавливаются биты:

USART_CR3_DMAT в USART2->CR3, DMA_SxCR_TCIE и DMA_SxCR_HTIE в DMA1_Stream6->CR, но после первого вызова функции: HAL_UART_Transmit_DMA() эти биты сбрасываются и последующие вызовы HAL_UART_Transmit_DMA ни к чему не приводят. Модифицировал код:

void DMA1_Stream5_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Stream5_IRQn 0 */

  /* USER CODE END DMA1_Stream5_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_usart2_rx);
  /* USER CODE BEGIN DMA1_Stream5_IRQn 1 */
  	  for(uart_count=0; uart_count <12; uart_count++ )
  	  {
  		  UART1_Tx[uart_count] = UART1_Rx[uart_count];
  	  }

  	  HAL_UART_Transmit_DMA(&huart2, UART1_Tx, 12);

  	  USART2->CR3 |= USART_CR3_DMAT;
  	  DMA1_Stream6->CR |= DMA_SxCR_TCIE | DMA_SxCR_HTIE | DMA_SxCR_EN;

  /* USER CODE END DMA1_Stream5_IRQn 1 */
}

Вот этот код рабочий. Правда поменял USART1 на USART2, но это замена сути не изменила.

Те, приставил костыли - после вызова:  HAL_UART_Transmit_DMA(&huart2, UART1_Tx, 12); надо выполнить:

USART2->CR3 |= USART_CR3_DMAT;
DMA1_Stream6->CR |= DMA_SxCR_TCIE | DMA_SxCR_HTIE | DMA_SxCR_EN; - тогда всё работает.

 

В связи с этим вопрос к тем, кто активно использует HAL. Это нормально, что после вызова функции HAL надо устанавливать отдельные битики вручную? Как по мне, так нарушается, прости Господи, философия HAL. Обвинять индусов, что оне там перекурили не хочу, видимо что-то я так и не понимаю как работать с HAL. Наведите на мысль, может какую функцию HAL надо пользовать до и/или после вызова HAL_UART_Transmit_DMA(), что бы всё работало. Пока не вижу по мануалу на HAL ничего такого.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 6/21/2024 at 10:26 AM, Vlad_G said:

Продолжаю тему.

 

Внутри функции HAL_UART_Transmit_DMA эти строки кода 

USART2->CR3 |= USART_CR3_DMAT;
DMA1_Stream6->CR |= DMA_SxCR_TCIE | DMA_SxCR_HTIE

также присутствуют

Не стесняйтесь заглянуть внутрь HAL. И заодно разберитесь, что эти ваши биты делают и почему они сбрасываются.

Тем более, вы говорили, что на регистрах у вас все работает.

Наверняка у вас проблема в другом.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

54 минуты назад, sidy сказал:

Выкинуть HAL.

Не по существу. Причина - см. выше.

18 минут назад, dimka76 сказал:

также присутствуют

Это уже лучше. Ещё понять бы где они там находятся, среди всего этого вложенного во вложенное, на вложенное....

С регистрами проще - сам поставил, сам сбросил - на смсис они сами по себе не гуляют.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, dimka76 сказал:

Не стесняйтесь заглянуть внутрь HAL. И заодно разберитесь, что эти ваши биты делают и почему они сбрасываются.

Попытался покопаться в нутрях HAL, нашел такое:

if ((hdma->Instance->CR & DMA_SxCR_CIRC) == 0U)
  {
    huart->TxXferCount = 0x00U;

    /* Disable the DMA transfer for transmit request by setting the DMAT bit
       in the UART CR3 register */
    ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);

Те, если циклический режим (мой случай) выключен, то бит DMAT сбрасывается. А что, обратно его надо ставить так: USART2->CR3 |= USART_CR3_DMAT; ? Как-то не коррелирует с концепцией HAL...

Изменено пользователем Vlad_G

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 6/21/2024 at 4:42 PM, Vlad_G said:

Попытался покопаться в нутрях HAL, нашел такое:

Не понятно где вы такое нашли, но вот тело вызываемой вами функции

HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  uint32_t *tmp;
  
  /* Check that a Tx process is not already ongoing */
  if(huart->gState == HAL_UART_STATE_READY)
  {
    if((pData == NULL ) || (Size == 0U))
    {
      return HAL_ERROR;
    }

    /* Process Locked */
    __HAL_LOCK(huart);

    huart->pTxBuffPtr = pData;
    huart->TxXferSize = Size;
    huart->TxXferCount = Size;

    huart->ErrorCode = HAL_UART_ERROR_NONE;
    huart->gState = HAL_UART_STATE_BUSY_TX;

    /* Set the UART DMA transfer complete callback */
    huart->hdmatx->XferCpltCallback = UART_DMATransmitCplt;

    /* Set the UART DMA Half transfer complete callback */
    huart->hdmatx->XferHalfCpltCallback = UART_DMATxHalfCplt;

    /* Set the DMA error callback */
    huart->hdmatx->XferErrorCallback = UART_DMAError;

    /* Set the DMA abort callback */
    huart->hdmatx->XferAbortCallback = NULL;

    /* Enable the UART transmit DMA Stream */
    tmp = (uint32_t*)&pData;
    HAL_DMA_Start_IT(huart->hdmatx, *(uint32_t*)tmp, (uint32_t)&huart->Instance->DR, Size);
    
    /* Clear the TC flag in the SR register by writing 0 to it */
    __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_TC);
    
    /* Process Unlocked */
    __HAL_UNLOCK(huart);
    
    /* Enable the DMA transfer for transmit request by setting the DMAT bit
       in the UART CR3 register */
    SET_BIT(huart->Instance->CR3, USART_CR3_DMAT);
    
    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}

Непосредственно перед выходом из функции

SET_BIT(huart->Instance->CR3, USART_CR3_DMAT);

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 часов назад, dimka76 сказал:

Непосредственно перед выходом из функции

SET_BIT(huart->Instance->CR3, USART_CR3_DMAT);

Да, в теле функции есть установка бита, но отладчик и реальность показывают, что этот бит сброшен. И сбросился от где-то по дороге во время или после вызова функции HAL_UART_Transmit_DMA(). Код, который я привёл в последнем посте он как раз находится в глубине функции HAL_UART_Transmit_DMA(), в глубинах не первого уровня. Ну да, как на форумах пишут, что HAL - это всего лишь красивая обёртка для смсис. Лютый ад...

Но в любом случае спасибо вам! Буду дальше пытаться понять всё это.

Изменено пользователем Vlad_G

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 часов назад, Vlad_G сказал:

Но в любом случае спасибо вам! Буду дальше пытаться понять всё это.

Зачем все эти мучения??? Вы же (как говорите) умеете самостоятельно работать с периферией. Баз Калов. Так и работайте. Кал - он для тех, кто самостоятельно не умеет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...