Vlad_G 8 19 июня Опубликовано 19 июня · Жалоба МК - 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. По возможности. Видимо пропустил какую-то функцию, которая взводит процесс на начало. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ruslan1 17 19 июня Опубликовано 19 июня · Жалоба 1 час назад, Vlad_G сказал: На приём всё работает как нормуль, претензий нет. А вот на передачу.... - один раз срабатывает (самый первый раз, после сброса МК), а далее затыкается. Вот это самое "затыкается" хорошо бы расшифровать. Данные не доходят до буфера DMA, или DMA не запускается, или еще дальше по цепи... Если один раз срабатывает- это значит что-то в инициализации DMA, или в самом USART что-то происходит- посмотрите флаги ошибок. Конечно, все это дебаггером и пошагово внутрь функций, насколько возможно. P.S. А зачем себя так истязать? Если "на регистрах" уже все работало... 🙂 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 51 19 июня Опубликовано 19 июня · Жалоба 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vlad_G 8 19 июня Опубликовано 19 июня · Жалоба 3 часа назад, Ruslan1 сказал: P.S. А зачем себя так истязать? Новые веяния, с новым начальством. С другой стороны, сложность проектов растёт. Кто прав, как знать... 3 часа назад, Ruslan1 сказал: хорошо бы расшифровать Сейчас этим и занимаюсь в свободное время. Отладчик CubeIDE не работает (вот тоже напасть) - ошибка GDB сервера. Посмотрю позжее. Пользую STMStudio, тоже не фонтан, но что-то можно. А так при первом вызове конструкции: HAL_UART_Transmit_DMA(&huart1, UART1_Tx, 12); - работает, данные передаются. При втором и последующих вызовах ничего не происходит, передачи нет. При этом приём от ПК идёт нормально, подпрограмма прерывания по приёму отрабатывает своё. Может перед вызовом этой функции надо ещё какие действия предпринять и (или) после вызова тоже? А может я вообще всё неправильно понял и выбрал не ту функцию? Ещё такой вопрос. Есть ли мануал по HAL, типа - Code Examples? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
firstvald 22 19 июня Опубликовано 19 июня · Жалоба есть Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vlad_G 8 21 июня Опубликовано 21 июня · Жалоба Продолжаю тему. Анализ регистров в отладчике показал, что при начальной инициализации устанавливаются биты: 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 ничего такого. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sidy 1 21 июня Опубликовано 21 июня · Жалоба 4 hours ago, Vlad_G said: Наведите на мысль Выкинуть HAL. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 59 21 июня Опубликовано 21 июня · Жалоба 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. И заодно разберитесь, что эти ваши биты делают и почему они сбрасываются. Тем более, вы говорили, что на регистрах у вас все работает. Наверняка у вас проблема в другом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vlad_G 8 21 июня Опубликовано 21 июня · Жалоба 54 минуты назад, sidy сказал: Выкинуть HAL. Не по существу. Причина - см. выше. 18 минут назад, dimka76 сказал: также присутствуют Это уже лучше. Ещё понять бы где они там находятся, среди всего этого вложенного во вложенное, на вложенное.... С регистрами проще - сам поставил, сам сбросил - на смсис они сами по себе не гуляют. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vlad_G 8 21 июня Опубликовано 21 июня (изменено) · Жалоба 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... Изменено 21 июня пользователем Vlad_G Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 59 21 июня Опубликовано 21 июня · Жалоба 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); 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vlad_G 8 21 июня Опубликовано 21 июня (изменено) · Жалоба 5 часов назад, dimka76 сказал: Непосредственно перед выходом из функции SET_BIT(huart->Instance->CR3, USART_CR3_DMAT); Да, в теле функции есть установка бита, но отладчик и реальность показывают, что этот бит сброшен. И сбросился от где-то по дороге во время или после вызова функции HAL_UART_Transmit_DMA(). Код, который я привёл в последнем посте он как раз находится в глубине функции HAL_UART_Transmit_DMA(), в глубинах не первого уровня. Ну да, как на форумах пишут, что HAL - это всего лишь красивая обёртка для смсис. Лютый ад... Но в любом случае спасибо вам! Буду дальше пытаться понять всё это. Изменено 21 июня пользователем Vlad_G Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 231 22 июня Опубликовано 22 июня · Жалоба 11 часов назад, Vlad_G сказал: Но в любом случае спасибо вам! Буду дальше пытаться понять всё это. Зачем все эти мучения??? Вы же (как говорите) умеете самостоятельно работать с периферией. Без Калов. Так и работайте. Кал - он для тех, кто самостоятельно не умеет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться