Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Вопрос по USART в SAM7X
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Terminator
Пытаюсь сделать приём пакетов с использованием PDC(DMA).
Проблемы с прерыванием "Receiver timeout'. Срабатывает после приёма одного или двух байт.
Специально выставил таймаут на максимум, при скорости 115200 должно получится немного больше 0.5сек и всё равно больше двух байт не принимает.
help.gif

Инициализация
Код
    // Usart Configure
    AT91F_US_Configure (uart->usart, configCPU_CLOCK_HZ, mode, 115200, 0);

    uart->usart->US_RTOR = USART_BITS_TIMEOUT;

    // Enable usart
    uart->usart->US_CR = AT91C_US_RXEN | AT91C_US_TXEN;

    // open Usart interrupt
    AT91F_AIC_ConfigureIt (
            AT91C_BASE_AIC,
            d_id,
            interrupt_level,
            AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,
            USART0_ISR);

    AT91F_AIC_EnableIt (AT91C_BASE_AIC, d_id);
    
    AT91PS_PDC pPDC = ((AT91PS_PDC) &(uart->usart->US_RPR));
    AT91F_PDC_DisableRx(pPDC);
    AT91F_PDC_SetNextRx(pPDC, (char *) 0, 0);
    AT91F_PDC_SetRx(pPDC, (char *) 0, 0);

    AT91F_PDC_SetNextRx(pPDC, (char*)0, 0);
    AT91F_PDC_SetRx(pPDC, (char*)uart->rxbuf, PACKET_MAX_SIZE);
    AT91F_PDC_EnableRx(pPDC);
    
    // перезапускаем таймер таймаута
    uart->usart->US_CR = AT91C_US_STTTO;        

    // разрешаем прерывания по приёму
    uart->usart->US_IER = AT91C_US_ENDRX +
        AT91C_US_OVRE +
        AT91C_US_FRAME +
        AT91C_US_TIMEOUT;
a3r3
Нормально у него тайм-аут работает. Что записывается в US_RTOR (число)?
Terminator
65000
Timofey
Цитата(Terminator @ Jul 4 2007, 09:28) *
А чему равно PACKET_MAX_SIZE? Неплохо бы увидеть еще функцию обработки прерывания.
Terminator
PACKET_MAX_SIZE = 530

Эта функция вызывается из обработчика прерываний
Код
#define USART_RECV_INT     (AT91C_US_ENDRX +    \
                        AT91C_US_OVRE +        \
                        AT91C_US_FRAME +     \
                                                AT91C_US_TIMEOUT)

#define USART_SEND_INT     (AT91C_US_ENDTX)

// обработчик прерывания USART
static portBASE_TYPE usart_isr(tUART *uart)
{
    // смотрим что случилось
    int stat = uart->usart->US_CSR;
    int imr = uart->usart->US_IMR;
    stat &= imr;
    // сбрасываем флаги
    uart->usart->US_CR = AT91C_US_RSTSTA;

    // записываем состояние    
    uart->stat = stat;
    
    portBASE_TYPE xSwitchRequired = pdFALSE;

    if (stat & USART_SEND_INT)
    {
        // закончилась передача
        // запрещаем прерывание на  передачу
        uart->usart->US_IDR = USART_SEND_INT;
        // сигналим задаче
        xSwitchRequired = xSemaphoreGiveFromISR( uart->txsem, xSwitchRequired );
    }
        

    if (stat & USART_RECV_INT)
    {
        // событие по приёму
        // запрещаем прерывания по приёму
        uart->usart->US_IDR = USART_RECV_INT;
        // сигналим задаче
        xSwitchRequired = xSemaphoreGiveFromISR( uart->rxsem, xSwitchRequired );
    }

    /* Clear the interrupt. */
    AT91C_BASE_AIC->AIC_EOICR = 0;
    
    return xSwitchRequired;
}


В задаче обслуживающей приём пакетов, сразу после получания семафора, смотрю stat и регистры PDC.
В stat отмечено, что был timeout, а в регистрах PDC, что получено 2 байта. Что я забыл или неправильно сделал?
Terminator
Заработало когда на передающем конце(комп) сделал 2 стоп бита 07.gif
Я чтото пропустил в доке? cranky.gif
a3r3
М.б. четность забыли выключить при конфигурировании USART? 0 - это even parity.
Terminator
Цитата(a3r3 @ Jul 5 2007, 18:48) *
М.б. четность забыли выключить при конфигурировании USART? 0 - это even parity.

Перепроверил ещё раз. Явно указал AT91C_US_PAR_NONE.
Timofey
Цитата(a3r3 @ Jul 5 2007, 17:48) *
М.б. четность забыли выключить при конфигурировании USART? 0 - это even parity.
Смотрите что вы передаете в функции AT91F_US_Configure ( ) Чему у вас равна mode. Если функцию размотать, то видно что именно эта переменная настраивает порт. Может быть из-за неё вы пишите в регистр US_MR в биты 12 и 13 числа 1 и 0 соответственно?

Terminator
Ошибка найдена.
mode передаётся в функцию в виде
AT91C_US_USMODE_NORMAL | AT91C_US_PAR_NONE
Код
    mode &= AT91C_US_USMODE | AT91C_US_PAR;

Нехватало "| AT91C_US_PAR"
Код
    mode |= (
        AT91C_US_CLKS_CLOCK +
        AT91C_US_CHRL_8_BITS +
        //AT91C_US_NBSTOP_2_BIT +
        AT91C_US_CHMODE_NORMAL);


Посыпаю голову пеплом ...
Два дня потерял sad.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.