Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Проблема с UART SAM7X256
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Alexey V.
Отладочная плата: AT91SAM7X-EK
Запускаю УАРТ (9600, 8,1, без четности) (прерывание RXRDY), в обработчике прерывания заворачиваю данные.
Запускаю TESTCOM. Первые секунд десять все идет отлично (что отправили, то и получили), затем контроллер подвисает (причем, блок уарта продолжает работать, но раз в секунду теряя 1 символ). Такое ощущение, что где-то что-то переполняется...

код иницииализации уарта:
Код
void InitUart(void)
{
    //отключаем пины USART0
    AT91C_BASE_PIOA->PIO_PDR = PA1 | PA0;


    AT91C_BASE_SYS->AIC_SVR[AT91C_ID_US0] = (INT32U) UartIrqHandler;
    //растановка приоритета прерывания
    AT91C_BASE_SYS->AIC_SMR[AT91C_ID_US0] = 0x63; // SRCTYPE=1, PRIOR=3. USART 0 interrupt positive edge-triggered at prio 3 //0x02;
    //разрешение прерывания по Timer 1
    AT91C_BASE_SYS->AIC_IECR = (1<<AT91C_ID_US0);
    AT91C_BASE_SYS->AIC_ICCR = (1<<AT91C_ID_US0);


    *AT91C_US0_BRGR = 625;
    *AT91C_US0_MR = 0x000808C0; // Normal mode, 1 stop bit, no parity, async mode, 8 bits, MCK.
    *AT91C_US0_IDR = 0xffffffff; // Disable all USART interrupts
    *AT91C_US0_IER = AT91C_US_RXRDY;

    *AT91C_US0_CR = AT91C_US_RXDIS | AT91C_US_TXDIS;
    *AT91C_US0_CR = 0x0000010c; // Reset status bits, reset rx/tx.
    *AT91C_US0_CR = AT91C_US_RXEN | AT91C_US_TXEN;
    *AT91C_PMC_PCER = (1 << AT91C_ID_US0);
}


код обработчика прерывания:
Код
void UartIrqHandler(void)
{
    INT8U Tmp = *AT91C_US0_CSR;
    INT8U Data;

    //AT91C_BASE_AIC->AIC_IVR = 0;
    //AT91C_BASE_AIC->AIC_ICCR  = (1 << AT91C_ID_US0);

    Data = *AT91C_US0_RHR;

    do
    {
        Tmp = *AT91C_US0_CSR;
    } while ((Tmp & 0x02) == 0);

    *AT91C_US0_THR = Data;

    Main.Led1Blink = 1;
    
    AT91C_BASE_AIC->AIC_EOICR = 0;            // Signal end of interrupt
}
aaarrr
По-моему, у Вас прерывание объявлено неправильно.
Alexey V.
Цитата(aaarrr @ Oct 26 2006, 11:53) *
По-моему, у Вас прерывание объявлено неправильно.


Но работает... меня смущает только
Код
AT91C_BASE_SYS->AIC_SMR[AT91C_ID_US0] = 0x63

эту строчку взял из одного примера, но не совсем понял зачем там цифра 6 smile.gif ()
aaarrr
Я имел в виду это: void UartIrqHandler(void) - нет модификаторов, указывающих что это прерывание.

Цитата
Но работает... меня смущает только
Код
AT91C_BASE_SYS->AIC_SMR[AT91C_ID_US0] = 0x63

Вместо 6 можно с тем же успехом написать 2.
А вот работа по фронту, а не по уровню, может привести к пропуску прерываний.
Alexey V.
Цитата(aaarrr @ Oct 26 2006, 12:31) *
Я имел в виду это: void UartIrqHandler(void) - нет модификаторов, указывающих что это прерывание.


переделал так:
Код
__irq __arm void UartIrqHandler(void)

теперь посылаю с компа один символ, а в ответ начинает постоянно приходить этот символ (соответственно все остальное подвисает)
aaarrr
Цитата(Alexey V. @ Oct 26 2006, 14:23) *
теперь посылаю с компа один символ, а в ответ начинает постоянно приходить этот символ (соответственно все остальное подвисает)

Странно, у меня этот код выполняется нормально. А другие прерывания от UART'а точно выключены?
Alexey V.
Цитата(aaarrr @ Oct 26 2006, 14:08) *
Странно, у меня этот код выполняется нормально. А другие прерывания от UART'а точно выключены?

Кроме этих двух функций уарт больше нигде не упоминается (кроме непосредственно вызова InitUart)...
vmp
У тебя AT91C_US0_CSR два раза считывается - первый раз в объявлении tmp, второй раз - в цикле.
SpiritDance
какой компилятор-то вообще? Если ИАР, то сишному обработчику не нужно никаких модификаторов и AIC_EOICR = 0, так как у него собственно обработчик находится в стартапе, а сишные подпрограммы являюится по сути callback- функциями которые он вызывает. Недавно сам напоролся на похожий трабл, только с USB, заработало вот с таким кодом обработчмка IRQ:
Код
IRQ_Handler_Entry:
//           ldr          pc, AT91C_AIC_IVR
;-------------------------
;- Manage Exception Entry
;-------------------------
;- Adjust and save LR_irq in IRQ stack
    sub         lr, lr, #4
    stmfd       sp!, {lr}

;- Save r0 and SPSR (need to be saved for nested interrupt)
    mrs         r14, SPSR
    stmfd       sp!, {r0,r14}

;- Write in the IVR to support Protect Mode
;- No effect in Normal Mode
;- De-assert the NIRQ and clear the source in Protect Mode
    ldr         r14, =AT91C_BASE_AIC
    ldr         r0 , [r14, #+AIC_IVR]
    str         r14, [r14, #+AIC_IVR]

;- Enable Interrupt and Switch in Supervisor Mode
    msr         CPSR_c, #ARM_MODE_SVC

;- Save scratch/used registers and LR in User Stack
    stmfd       sp!, { r1-r3, r12, r14}

;----------------------------------------------
;- Branch to the routine pointed by the AIC_IVR
;----------------------------------------------
    mov         r14, pc
    bx          r0

;----------------------------------------------
;- Manage Exception Exit
;----------------------------------------------
;- Restore scratch/used registers and LR from User Stack
    ldmia       sp!, { r1-r3, r12, r14}

;- Disable Interrupt and switch back in IRQ mode
    msr         CPSR_c, #I_BIT | ARM_MODE_IRQ

;- Mark the End of Interrupt on the AIC
    ldr         r14, =AT91C_BASE_AIC
    str         r14, [r14, #AIC_EOICR]

;- Restore SPSR_irq and r0 from IRQ stack
    ldmia       sp!, {r0,r14}
    msr         SPSR_cxsf, r14

;- Restore adjusted  LR_irq from IRQ stack directly in the PC
    ldmia       sp!, {pc}^

а в чем собственнно был косяк старого кода так и осталось непонятым. sad.gif

и про AT91C_US0_CSR тоже верно замечено
aaarrr
Цитата
и про AT91C_US0_CSR тоже верно замечено

Раз уж пошла такая пьянка, то всю конструкцию:
Код
    INT8U Tmp = *AT91C_US0_CSR;

    do
    {
        Tmp = *AT91C_US0_CSR;
    } while ((Tmp & 0x02) == 0);

следует заменить на:
Код
    while((*AT91C_US0_CSR & 0x02) == 0);

только сути дела это никак не меняет.
EugeneB
Зачем изобретать велосипед. Берешь пример с атмела по обмену USART, там все написано правильно, и на основе этого пишешь свое(только обработчик прерывания в стартапе подправить).

А как у тебя данные передаются? Пинг-понг?
к примеру лучше так
void InitUart(void)
{
....
*AT91C_US0_IER = AT91C_US_RXRDY;
...
}
void UartIrqHandler(void)
{
UINT status;

status = us->US_CSR;
status &= us->US_IMR;

if ( status & AT91C_US_RXRDY )
{
......
*AT91C_US0_IER = AT91C_US_TXRDY;
*AT91C_US0_IDR = AT91C_US_RXRDY;
}
if ( status & AT91C_US_TXRDY )
{
*AT91C_US0_IDR = AT91C_US_TXRDY;
*AT91C_US0_IER = AT91C_US_RXRDY;
......
}
......
}
Alexey V.
Спасибо, буду пробовать
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.