Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: LPC236x, scmRTOS. Как обработать переполнение UART?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
meister
Обработчик прерывания (ниже), если не доставать данные из rx очереди вылетает на

Код
assert(0 == (iir & util::bit<hw::UART::UxIIR_int_status>::value) && "At least one interrupt is pending.");


а должен в
Код
assert(0 && "UART RX FIFO overflow");
или
Код
assert(0 == (lsr & util::bit<hw::UART::UxLSR_RX_OE>::value));


Что я делаю не по мануалу?

Код
OS_INTERRUPT void interrupts::irq_uart2_handler(void)
{
    OS::TISRW ISRW;
    interrupt_leds();
    
    unsigned const iir = U2IIR;
    
    assert(0 == (iir & util::bit<hw::UART::UxIIR_int_status>::value) && "At least one interrupt is pending.");
    
    switch (iir & hw::UART::UxIIR_IRQ_mask)
    {
    default: PANIC("unknown UART interrupt", UART2_FAULT);
    case hw::UART::UxIIR_RLS_bit:
        {
            basic_uart_t::rx_channel_item_t item;
            
            {
                byte const lsr = U2LSR;
                
                if (lsr & util::bit<hw::UART::UxLSR_RX_OE>::value)
                {
                    assert(0 && "UART RX FIFO overflow");
                    item.value = '?';
                }
                else
                {
                    assert(lsr & util::bit<hw::UART::UxLSR_RX_RDR>::value);
                    item.value = U2RBR;
                }
                
                item.lsr = lsr & hw::UART::UxLSR_RX_error_mask;
            }
            
            if (uarts::uart2.rx_.get_free_size() > 0)
            {
                uarts::uart2.rx_.push(item);
            }
            else
            {
                assert(0 && "UART RX queue overflow");
                hw::LEDs::red(config::led_long_flash);
                uarts::uart2.overflow_ = true;
            }
        }
        break;
        
    case hw::UART::UxIIR_RDA_bit:
    case hw::UART::UxIIR_CTI_bit:
        while (uarts::uart2.rx_.get_free_size() > 0)
        {
            byte lsr = U2LSR;
            
            assert(0 == (lsr & util::bit<hw::UART::UxLSR_RX_OE>::value));
            
            if (lsr & util::bit<hw::UART::UxLSR_RX_RDR>::value)
            {
                basic_uart_t::rx_channel_item_t item;
                
                item.lsr = 0;
                item.value = U2RBR;
                
                uarts::uart2.rx_.push(item);
            }
            else
            {
                break;
            }
        }
        break;
        
    case hw::UART::UxIIR_THRE_bit:
        for (unsigned n = util::min_val<unsigned>(hw::UART::tx_batch_max_length, uarts::uart2.tx_.get_count()); n > 0; --n)
        {
            byte b;
            uarts::uart2.tx_.pop(b);
            U2THR = b;
        }
        break;
    }
}
HARMHARM
Возможно, дело в том, что в регистре IIR могут быть установлены несколько бит одновременно.
Один из битов вы обработали (сняли флаг), по выходу из прерывания сразу следует второе.
У меня сделано так (подсмотрел):

Код
    iirMask = Reg.IIR_FCR & 0x07;
    while ( iirMask != 1 )
    {
       if()....
       else if()....
       else if()....
       iirMask = Reg.IIR_FCR & 0x07;
    }
meister
Цитата(HARMHARM @ Nov 25 2008, 14:10) *
Возможно, дело в том, что в регистре IIR могут быть установлены несколько бит одновременно.


Я убрал все обращения к UxLSR вне прерывания Receive Line Status (RLS) - теперь работает как надо.
meister
Переполнения я обработал. А как обрабатывать ошибки? В мануале по Framing error написано следующее:

Цитата
When the stop bit of a received character is a logic 0, a framing error occurs. An UnLSR read clears UnLSR[3]. The time of the framing error detection is dependent on UnFCR0. Upon detection of a framing error, the Rx will attempt to resynchronize to the data and assume that the bad stop bit is actually an early start bit. However, it cannot be assumed that the next received byte will be correct even if there is no Framing Error.

Цитата
Note: A framing error is associated with the character at the top of the UARTn RBR FIFO.


Код
    case hw::UART::UxIIR_RLS_bit:
        {
            byte const lsr = U0LSR; // <1>
            
            if (uarts::uart0.rx_.get_free_size() > 0)
            {
                basic_uart_t::rx_channel_item_t item;
                item.value = '?';
                item.lsr = lsr & hw::UART::UxLSR_RX_error_mask;
                uarts::uart0.rx_.push(item);
            }
            else
            {
                uarts::uart0.rx_overflow_ = true;
            }
        }
        break;


В строчке <1> переменная lsr иногда равна 0xE8 - данных в RX FIFO нет, Framing error - есть. Не соответствует Note из мануала.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.