Ошибка переполнения приёмника (overrun)
Приёмник UART складывает принятые символы в маленький буфер. Если программа не успевает его освобождать, следующий символ приходит некуда — это ошибка переполнения, и как минимум один байт пропадает.
Обновлено Редакция GAW
Ошибка переполнения (overrun error) — ситуация, когда UART принял новый символ, а положить его некуда: предыдущие ещё не прочитаны программой. Приёмник выставляет флаг, и как минимум один символ теряется.
Флаги у разных UART
| UART | Регистр и флаг | Сколько символов помещается до переполнения |
|---|---|---|
| STM32F1 | USART_SR, ORE | регистр данных + сдвиговый регистр |
| AVR (ATmega328P) | UCSR0A, DOR0 | буфер из двух символов + сдвиговый регистр |
| UART 16550 | LSR, OE | FIFO 16 символов + сдвиговый регистр |
У ATmega328P флаг DOR0 взводится, когда буфер из двух символов полон, в сдвиговом регистре ждёт третий, а на линии уже начался следующий старт-бит. У STM32F1 по RM0008 символ в регистре данных сохраняется, а всё, что пришло в сдвиговый регистр во время переполнения, пропадает. UART 16550 в режиме FIFO сообщает о переполнении только тогда, когда заполнен весь FIFO.
Сколько времени у программы
Если нет FIFO и DMA, каждый символ надо забрать до прихода следующего. При 115 200 бит/с и формате 8N1 символ приходит каждые 10 / 115 200 ≈ 86,8 мкс (наш расчёт). Обработчик другого прерывания, который работает дольше, или долгий запрет прерываний — и байт потерян. На странице UART в STM32 показано, как сбрасывать флаг и принимать данные через DMA.
Как предотвратить
- Принимать по прерыванию в кольцевой буфер, а разбирать данные в основном цикле.
- Использовать DMA или UART с FIFO.
- Включить аппаратное управление потоком: приёмник снимает RTS, и передатчик останавливается. TI отмечает, что переполнения исключены, если обе стороны — TL16C550C с включённым автоматическим RTS/CTS и RTS каждой соединён с CTS другой.
Не путать с флагом переполнения V процессора — он относится к знаковой арифметике, см. флаг переполнения, — и с ошибкой кадра, когда символ принят, но на месте стоп-бита ноль.
Частые вопросы
Какой байт теряется при переполнении UART?
Зависит от микросхемы. У STM32F1 символ в регистре данных сохраняется, а всё, что приходит в сдвиговый регистр, пока флаг ORE стоит, пропадает. У ATmega328P в буфере остаются два символа, а теряется тот, что ждал в сдвиговом регистре. Флаг в любом случае означает, что потерян хотя бы один символ.
Почему при переполнении STM32 может зависнуть в прерывании?
Флаг ORE тоже вызывает прерывание приёма. Если обработчик проверяет только RXNE и не сбрасывает ORE последовательностью «прочитать USART_SR, затем USART_DR», флаг остаётся, прерывание повторяется бесконечно, а основной код не выполняется.
Как избавиться от ошибок переполнения?
Забирать байты быстрее, чем они приходят: принимать по прерыванию в кольцевой буфер или через DMA, не держать прерывания запрещёнными долго, взять UART с FIFO. Если приёмник всё равно может отстать, нужна аппаратная остановка передатчика — управление потоком RTS/CTS.
Источники
- STMicroelectronics. RM0008 Reference manual: STM32F101xx–STM32F107xx (Rev 21, February 2021) — разд. 27.3.3: переполнение — символ принят, когда RXNE ещё не сброшен; бит ORE; содержимое RDR не теряется, сдвиговый регистр перезаписывается, принятое во время переполнения теряется; прерывание при RXNEIE или EIE и DMAR; ORE сбрасывается чтением SR, затем DR; ORE = 1 означает потерю хотя бы одного символа
- Microchip. ATmega48A/PA/88A/PA/168A/PA/328/P Data Sheet (DS40002061B, 2020) — разд. 20.7.4: флаг DORn — потеря данных из-за заполненного буфера приёма (два символа), когда в сдвиговом регистре ждёт новый символ и обнаружен новый старт-бит; сбрасывается, когда принятый кадр успешно перенесён в буфер
- Texas Instruments. TL16C550C Asynchronous Communications Element with Autoflow Control (SLLS177I), 2021 — LSR, флаг OE: символ в RBR перезаписан следующим до чтения; в режиме FIFO переполнение — только когда FIFO полон и следующий символ полностью принят в сдвиговый регистр; переполнения исключаются, если обе стороны — TL16C550C с autoflow и RTS одной соединён с CTS другой
Нашли ошибку?