x893 34 22 августа, 2019 Опубликовано 22 августа, 2019 · Жалоба Например, чтобы каждый не вызывать Receive_IT(... 1) после приема - можно после вызова HAL_UART_IRQ_... уменьшить счетчик и вернуть указатель (если они изменились). А вызывать Receive_IT(... 2) только в начале программы и после ошибки. В общем всё зависит от желания. Но можно конечно под каждый процессор проштудировать RM и колбасить всё ручками. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 60 22 августа, 2019 Опубликовано 22 августа, 2019 · Жалоба 8 minutes ago, x893 said: Но можно конечно под каждый процессор проштудировать RM и колбасить всё ручками Так.. это... как бэ разве куб отменяет смотреть доку?))) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 17 22 августа, 2019 Опубликовано 22 августа, 2019 · Жалоба 1 minute ago, haker_fox said: разве куб отменяет смотреть доку?))) Косвенно - да, поскольку куб значительно снизил "порог вхождения" и в тему хлынул поток "ардуинщиков" Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dimonira 0 22 августа, 2019 Опубликовано 22 августа, 2019 · Жалоба 19 minutes ago, x893 said: Например, чтобы каждый не вызывать Receive_IT(... 1) после приема - можно после вызова HAL_UART_IRQ_... уменьшить счетчик и вернуть указатель (если они изменились). А вызывать Receive_IT(... 2) только в начале программы Счётчик тогда уж увеличивать надо (при приёме он уменьшается). Но это не работает, ибо HAL_UART_RxCpltCallback никогда не вызовется, поскольку его вызов в UART_RxISR_8BIT случается только когда счётчик принятых байтов стал равен 0, а к моменту вызова "чёрное дело" по запрету прерываний и пр. уже случилось. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 34 22 августа, 2019 Опубликовано 22 августа, 2019 · Жалоба 4 minutes ago, Dimonira said: Счётчик тогда уж увеличивать надо (при приёме он уменьшается). Но это не работает, ибо HAL_UART_RxCpltCallback никогда не вызовется, поскольку его вызов в UART_RxISR_8BIT случается только когда счётчик принятых байтов стал равен 0, а к моменту вызова "чёрное дело" по запрету прерываний и пр. уже случилось. Не вызывается, но где лежат данные известно. Можно забрать по указателю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dimonira 0 22 августа, 2019 Опубликовано 22 августа, 2019 · Жалоба 4 minutes ago, x893 said: Не вызывается, но где лежат данные известно. Можно забрать по указателю. Можно конечно, но в каком месте забирать? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 34 22 августа, 2019 Опубликовано 22 августа, 2019 · Жалоба 30 minutes ago, Dimonira said: Можно конечно, но в каком месте забирать? А разве при вызове Receive_IT не передаете указатель ? И он потом сохраняется в husart1 (название поля есть в описании структуры). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dimonira 0 22 августа, 2019 Опубликовано 22 августа, 2019 · Жалоба В итоге я сделал более-менее приемлемо - заменил три стандартные функции UART_RxISR_8BIT, UART_RxISR_16BIT и HAL_UART_Receive_IT на свои. Чтобы не было конфликта, сделал у них имена с суфиксом "_new": UART_RxISR_8BIT_new, UART_RxISR_16BIT_new, HAL_UART_Receive_IT_new. Я воспользовался полем дескриптора huart->RxXferSize, в которое HAL только записывает количество байтов для приёма, но нигде не использует. Сделал, чтобы при вызове HAL_UART_Receive_IT_new аргумент Size мог принимать значение 0, которое "сигнализирует" необходимость непрерывного приёма. Size как раз присваивается полю huart->RxXferSize, а если оно равно 0, то в UART_RxISR_8BIT_new и UART_RxISR_16BIT_new это используется как "сигнал", что приём надо продолжать, указатель в буфере и счётчик не менять, плюс надо вызвать HAL_UART_RxCpltCallback. То есть буфер при вызове HAL_UART_Receive_IT_new при Size = 0 может быть на одно слово (uint8_t или uint16_t). Если Size > 0, то всё будет работать по старому. Далее в main включаю новый заголовок и в дефолтовой задаче один раз делаю вызов HAL_UART_Receive_IT_new с аргументом Size = 0 и всё: void StartDefaultTask(void *argument) { /* init code for LWIP */ MX_LWIP_Init(); /* USER CODE BEGIN 5 */ logprintf("LWIP initialization done...\r\n"); // Запускаем приём UART по прерываниям for(int i = 0; i < NUMBER_OF_UARTS; i++) { if(uarts[i]) HAL_UART_Receive_IT_new(uarts[i], &rx_buf[i], 0); } logprintf("UART reception started...\r\n"); /* Infinite loop */ for(;;) { HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); osDelay(500); } /* USER CODE END 5 */ } Функция обратного вызова остаётся в том же виде (без вызова HAL_UART_Receive_IT): void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { // Находим индекс UART int idx; for(idx = 0; idx < NUMBER_OF_UARTS; idx++) { if(uarts[idx] == huart) break; } // Готовим сообщение с принятым байтом MSG_UART_RX msg; msg.uart = idx; // индекс UART msg.byte = rx_buf[idx]; // принятый байт // Помещаем сообщение в очередь osMessageQueuePut(mid_RxQueue, &msg, 0, 0); } В файле stm32f7xx_it.c всё вернул взад как было (свой MY_UART_IRQHandler не нужен). Теперь всё работает как надо. И код HAL "не пострадал". Моё "дополнение" состоит из двух файлов. Исходник stm32f7xx_hal_uart_new.c: #include "stm32f7xx_hal_uart_new.h" #ifdef HAL_UART_MODULE_ENABLED /** * @brief RX interrrupt handler for 7 or 8 bits data word length . * @param huart UART handle. * @retval None */ static void UART_RxISR_8BIT_new(UART_HandleTypeDef *huart) { uint16_t uhMask = huart->Mask; uint16_t uhdata; /* Check that a Rx process is ongoing */ if (huart->RxState == HAL_UART_STATE_BUSY_RX) { uhdata = (uint16_t) READ_REG(huart->Instance->RDR); *huart->pRxBuffPtr = (uint8_t)(uhdata & (uint8_t)uhMask); if(huart->RxXferSize) { huart->pRxBuffPtr++; huart->RxXferCount--; } if (huart->RxXferCount == 0U) { /* Disable the UART Parity Error Interrupt and RXNE interrupts */ CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */ CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); /* Rx process is completed, restore huart->RxState to Ready */ huart->RxState = HAL_UART_STATE_READY; /* Clear RxISR function pointer */ huart->RxISR = NULL; } if(huart->RxXferCount == 0U || !huart->RxXferSize) { #if (USE_HAL_UART_REGISTER_CALLBACKS == 1) /*Call registered Rx complete callback*/ huart->RxCpltCallback(huart); #else /*Call legacy weak Rx complete callback*/ HAL_UART_RxCpltCallback(huart); #endif /* USE_HAL_UART_REGISTER_CALLBACKS */ } } else { /* Clear RXNE interrupt flag */ __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); } } /** * @brief RX interrrupt handler for 9 bits data word length . * @note Function is called under interruption only, once * interruptions have been enabled by HAL_UART_Receive_IT() * @param huart UART handle. * @retval None */ static void UART_RxISR_16BIT_new(UART_HandleTypeDef *huart) { uint16_t *tmp; uint16_t uhMask = huart->Mask; uint16_t uhdata; /* Check that a Rx process is ongoing */ if (huart->RxState == HAL_UART_STATE_BUSY_RX) { uhdata = (uint16_t) READ_REG(huart->Instance->RDR); tmp = (uint16_t *) huart->pRxBuffPtr ; *tmp = (uint16_t)(uhdata & uhMask); if(huart->RxXferSize) { huart->pRxBuffPtr += 2U; huart->RxXferCount--; } if (huart->RxXferCount == 0U) { /* Disable the UART Parity Error Interrupt and RXNE interrupt*/ CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */ CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); /* Rx process is completed, restore huart->RxState to Ready */ huart->RxState = HAL_UART_STATE_READY; /* Clear RxISR function pointer */ huart->RxISR = NULL; } if(huart->RxXferCount == 0U || !huart->RxXferSize) { #if (USE_HAL_UART_REGISTER_CALLBACKS == 1) /*Call registered Rx complete callback*/ huart->RxCpltCallback(huart); #else /*Call legacy weak Rx complete callback*/ HAL_UART_RxCpltCallback(huart); #endif /* USE_HAL_UART_REGISTER_CALLBACKS */ } } else { /* Clear RXNE interrupt flag */ __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); } } /** * @brief Receive an amount of data in interrupt mode. * @param huart UART handle. * @param pData Pointer to data buffer. If Size=0, then just one word buffer. * @param Size Amount of data to be received. If 0, then continuous reception of one word. * @retval HAL status */ HAL_StatusTypeDef HAL_UART_Receive_IT_new(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) { /* Check that a Rx process is not already ongoing */ if (huart->RxState == HAL_UART_STATE_READY) { if ((pData == NULL)) { return HAL_ERROR; } /* Process Locked */ __HAL_LOCK(huart); huart->pRxBuffPtr = pData; huart->RxXferSize = Size; huart->RxXferCount = !Size ? 1 : Size; huart->RxISR = NULL; /* Computation of UART mask to apply to RDR register */ UART_MASK_COMPUTATION(huart); huart->ErrorCode = HAL_UART_ERROR_NONE; huart->RxState = HAL_UART_STATE_BUSY_RX; /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */ SET_BIT(huart->Instance->CR3, USART_CR3_EIE); /* Set the Rx ISR function pointer according to the data word length */ if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) { huart->RxISR = UART_RxISR_16BIT_new; } else { huart->RxISR = UART_RxISR_8BIT_new; } /* Process Unlocked */ __HAL_UNLOCK(huart); /* Enable the UART Parity Error interrupt and Data Register Not Empty interrupt */ SET_BIT(huart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE); return HAL_OK; } else { return HAL_BUSY; } } #endif /* HAL_UART_MODULE_ENABLED */ И заголовок stm32f7xx_hal_uart_new.h: #ifndef STM32F7xx_HAL_UART_NEW_H #define STM32F7xx_HAL_UART_NEW_H #include "stm32f7xx_hal.h" #ifdef __cplusplus extern "C" { #endif /** * @brief Receive an amount of data in interrupt mode. * @param huart UART handle. * @param pData Pointer to data buffer. If Size=0, then just one word buffer. * @param Size Amount of data to be received. If 0, then continuous reception of one word. * @retval HAL status */ HAL_StatusTypeDef HAL_UART_Receive_IT_new(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); #ifdef __cplusplus } #endif #endif /* STM32F7xx_HAL_UART_NEW_H */ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 29 22 августа, 2019 Опубликовано 22 августа, 2019 · Жалоба Господа, вы это всё серьёзно? Побайтный приём из USART? void USART1_IRQHandler(void) { uint32_t sr = USART1->SR; if(sr & USART_SR_RXNE) { uint8_t data = USART1->DR; if(!(sr & (USART_SR_PE | USART_SR_FE | USART_SR_NE | USART_SR_ORE))) { // в data принятый байт, делай с ним что хошь. } } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dimonira 0 22 августа, 2019 Опубликовано 22 августа, 2019 · Жалоба 11 minutes ago, VladislavS said: Господа, вы это всё серьёзно? Побайтный приём из USART? void USART1_IRQHandler(void) { uint32_t sr = USART1->SR; if(sr & USART_SR_RXNE) { uint8_t data = USART1->DR; if(!(sr & (USART_SR_PE | USART_SR_FE | USART_SR_NE | USART_SR_ORE))) { // в data принятый байт, делай с ним что хошь. } } } Что хошь в FreeRTOS не получится. Вы вообще читали тему с начала? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 60 22 августа, 2019 Опубликовано 22 августа, 2019 · Жалоба 1 hour ago, Dimonira said: Что хошь в FreeRTOS не получится. Так, а причём здесь FreeRTOS? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 34 22 августа, 2019 Опубликовано 22 августа, 2019 · Жалоба Просто мастера программирования ! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mcheb 0 22 августа, 2019 Опубликовано 22 августа, 2019 · Жалоба #include "stm32f7xx_hal_uart_new.h" Положение обязывает Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 17 22 августа, 2019 Опубликовано 22 августа, 2019 · Жалоба (С) "Ежики кололись, но все равно ели кактус..." Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 34 22 августа, 2019 Опубликовано 22 августа, 2019 · Жалоба Некоторые и плитку кафельную молотком режут. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться