реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> STM32F0: заморочка с UART
k000858
сообщение Mar 18 2016, 05:12
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



Сколько переюзал юартов на разных линейках STM32 впервые столкнулся с такой заморочкой: принимаю простым поллингом байты по UART. Если следующий байт пришел раньше чем я забрал предыдущий, UART перестает работать - в регистре предпоследний пришедший байт, при всех последующих пришедших байтах соответствующий RXNE флаг не взводится.

Говоря простым языком, если принимать байты медленнее, чем они приходят, UART становится глухим.

STM32F030x08

Быть может кто нибудь встречался с таким?
Может у F0 линейки какой то особенный UART?
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Mar 18 2016, 06:07
Сообщение #2


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



Он ещё и у F7 и у F3 особенный...
Появившийся флаг overflow или frame error тоже надо снимать. Даже если прерывания по нему не разрешены.
У F4 есть такой эффект (у него другой блок), но там связь между этими флагами не описана в документации. И не каждый раз возникает.
Где-то тут я уже жаловался на найденную аномалию поведения.

Код
...
#elif CPUSTYLE_STM32F30X || CPUSTYLE_STM32F0XX || CPUSTYLE_STM32L0XX || CPUSTYLE_STM32F7XX

    void USART1_IRQHandler(void)
    {
        const uint_fast32_t isr = USART1->ISR;

        if (isr & USART_ISR_RXNE)
            cat_parsechar(USART1->RDR);
        if (isr & USART_ISR_ORE)
        {
            USART1->ICR = USART_ICR_ORECF;
            cat_rxoverflow();
        }
        if (isr & USART_ISR_FE)
            USART1->ICR = USART_ICR_FECF;
        if (isr & USART_ISR_TXE)
            cat_sendchar();
    }
#endif


И для случия поллинга:

Код
...
#elif CPUSTYLE_STM32F30X || CPUSTYLE_STM32F0XX || CPUSTYLE_STM32L0XX || CPUSTYLE_STM32F7XX
    const uint_fast32_t isr = USART1->ISR;
    if (isr & USART_ISR_ORE)
        USART1->ICR = USART_ICR_ORECF;
    if (isr & USART_ISR_FE)
        USART1->ICR = USART_ICR_FECF;
    if ((isr & USART_ISR_RXNE) == 0)
        return 0;
    * cp = USART1->RDR;

#endif


Оффтопик:

Вот люди с аномалией в F4 возились...

https://my.st.com/public/STe2ecommunities/m...rrentviews=1896

А вот моё:

Продолжаю разбираться.
Получи все-таки ситуацию (Не на единичных байтах).
В статусном регистре (после входа в обработчик) нет установленного бита готовности данных приёмника, но есть бит ошибки ORE. Но это после нескольких килобайт… Перед этим пара правильных срабатываний (и данные и флаг ORE) проходит.

Вот так выглядит выдача:

$$$$ rxc=61847, ovf=1008, sr=00000008, SR=000000D8, CR1=000020AC, CR2=00000000
$$$$ rxc=351, ovf=1004, sr=00000008, SR=000000D8, CR1=000020AC, CR2=00000000

А вот код:
Код
            void USART1_IRQHandler(void)
            {
                        static unsigned long ovf = 0;
                        static unsigned long rxc = 0;
                        const unsigned long sr = USART1->SR;
                        uint_fast8_t f = 0;

                        if (sr & USART_SR_RXNE)
                        {
                                   (void) USART1->DR;
                                   f=1;
                                   ++ rxc;
                        }
                        if (sr & USART_SR_ORE)
                                   ++ ovf;
                        if (sr & USART_SR_TXE)
                        {
                                   USART1->DR = 0x01;
                                   f=1;
                        }

                        if (f == 0)
                        {
                                   static int cnt = 1000;
                                   if (-- cnt == 0)
                                   {
                                               char buff [128];

                                               local_delay_ms(100);    // чтобы успело ещё множество байт прилететь - скорость 115200
                                               local_snprintf_P(
                                                           buff, sizeof buff / sizeof buff [0],
                                                           PSTR("\n$$$$ rxc=%lu, ovf=%lu, sr=%08lX, SR=%08lX, CR1=%08lX, CR2=%08lX\n"),
                                                           rxc,
                                                           ovf,
                                                           sr,
                                                           USART1->SR,
                                                           USART1->CR1,
                                                           USART1->CR2
                                                           );

                                               hdbg_puts_impl(buff);
                                               for (;;)
                                                          ;
                                   }
                        }
            }
Функция hdbg_puts_impl просто выводит в тот же порт строчку "посмертного дампа", пользуясь программным опросом готовности.

Сообщение отредактировал Genadi Zawidowski - Mar 18 2016, 06:13
Go to the top of the page
 
+Quote Post
k000858
сообщение Mar 18 2016, 06:20
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



то есть надо в ожидании флага RXNE так же считывать флаг ошибки и фрейма, иначе, если он возведен - следующий байт не придет пока мы его не сбросим (прочитав его). так?

Сообщение отредактировал k000858 - Mar 18 2016, 06:20
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Mar 18 2016, 06:22
Сообщение #4


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



Ну упрощённо говоря так. Кроме того, в F0 эти два флага надо явным образом сбросить через ICR
Go to the top of the page
 
+Quote Post
k000858
сообщение Mar 18 2016, 07:31
Сообщение #5


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



Цитата(Genadi Zawidowski @ Mar 18 2016, 10:22) *
Ну упрощённо говоря так. Кроме того, в F0 эти два флага надо явным образом сбросить через ICR

Спасибо за информацию. Разрешилась моя заморочка.

HAL/SPL минус бал за отсутствие обработки такой ситуации.

отругал STшников https:/my.st.com/cf00cd8e

Если кто то столкнется с таким эффектом (аномалией, багом или особенностью - называйте как хотите) при использовании HAL, решение простое: перед вызовом блокирующей функции приема байта(ов)
Код
HAL_UART_Receive(&UartHandle, &byte, 1, 1000)
, вызывать макрос
Код
__HAL_UART_CLEAR_OREFLAG(&UartHandle);
для сброса флага overrun'а.
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Mar 18 2016, 08:16
Сообщение #6


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



В F4 есть аномалия (и в STM32F429 и в STM32F446). В F7 поведение документировано (а кубом/hal не пользуюсь).
Go to the top of the page
 
+Quote Post
k000858
сообщение Mar 18 2016, 08:45
Сообщение #7


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



Цитата(Genadi Zawidowski @ Mar 18 2016, 12:16) *
В F4 есть аномалия (и в STM32F429 и в STM32F446). В F7 поведение документировано (а кубом/hal не пользуюсь).

Еще раз благодарю за решение. Так бы долго еще просидел.
Go to the top of the page
 
+Quote Post
картошка
сообщение Apr 8 2016, 11:30
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 65
Регистрация: 28-12-05
Из: Odessa
Пользователь №: 12 673



Минус в огород Хала/Hal . На STM32F2xx - те же грабли. Только при испытаниях HAL на электрические помехи на линии UART обнаружилось некорректная обработка условий LOW NOISE, STOP BIT. В общем долго рассказывать не надо удалили весь мусор, а его там 100 %.

Что делает ХАЛ , что можно было не делать или сделать лучше:

1. Включает лишние прерывания по ошибкам (LN , FE) и "индусы" запутались с обработкой этих битов. В итоге - не выходит с прерываний вообще.
2. Включает лишний код по обработке четности, когда не заказывали вообще.
3. И что незачем читать постоянно регистр SR , так как он влияет на аппаратный механизм сброса большинства условий.
4. "Индусы" не понимают что значит сократить код.

Цитата
HAL_UART_Receive(&UartHandle, &byte, 1, 1000), вызывать макрос
Код
__HAL_UART_CLEAR_OREFLAG(&UartHandle); для сброса флага overrun'а.


Это помогает лишь в некоторых случаях.

Смысла чинить ХАЛ - НЕТ !!!

Сообщение отредактировал картошка - Apr 8 2016, 11:31
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 05:46
Рейтинг@Mail.ru


Страница сгенерированна за 0.01418 секунд с 7
ELECTRONIX ©2004-2016