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

 
 
 
Reply to this topicStart new topic
> Проблема с UART SAM7X256, зависает в прерывании
Alexey V.
сообщение Oct 26 2006, 08:37
Сообщение #1


Участник
*

Группа: Новичок
Сообщений: 24
Регистрация: 10-05-06
Из: Russia, Tomsk
Пользователь №: 16 936



Отладочная плата: 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
}
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Oct 26 2006, 08:53
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



По-моему, у Вас прерывание объявлено неправильно.
Go to the top of the page
 
+Quote Post
Alexey V.
сообщение Oct 26 2006, 08:56
Сообщение #3


Участник
*

Группа: Новичок
Сообщений: 24
Регистрация: 10-05-06
Из: Russia, Tomsk
Пользователь №: 16 936



Цитата(aaarrr @ Oct 26 2006, 11:53) *
По-моему, у Вас прерывание объявлено неправильно.


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

эту строчку взял из одного примера, но не совсем понял зачем там цифра 6 smile.gif ()
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Oct 26 2006, 09:31
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Я имел в виду это: void UartIrqHandler(void) - нет модификаторов, указывающих что это прерывание.

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

Вместо 6 можно с тем же успехом написать 2.
А вот работа по фронту, а не по уровню, может привести к пропуску прерываний.
Go to the top of the page
 
+Quote Post
Alexey V.
сообщение Oct 26 2006, 10:23
Сообщение #5


Участник
*

Группа: Новичок
Сообщений: 24
Регистрация: 10-05-06
Из: Russia, Tomsk
Пользователь №: 16 936



Цитата(aaarrr @ Oct 26 2006, 12:31) *
Я имел в виду это: void UartIrqHandler(void) - нет модификаторов, указывающих что это прерывание.


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

теперь посылаю с компа один символ, а в ответ начинает постоянно приходить этот символ (соответственно все остальное подвисает)
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Oct 26 2006, 11:08
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



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

Странно, у меня этот код выполняется нормально. А другие прерывания от UART'а точно выключены?
Go to the top of the page
 
+Quote Post
Alexey V.
сообщение Oct 26 2006, 11:11
Сообщение #7


Участник
*

Группа: Новичок
Сообщений: 24
Регистрация: 10-05-06
Из: Russia, Tomsk
Пользователь №: 16 936



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

Кроме этих двух функций уарт больше нигде не упоминается (кроме непосредственно вызова InitUart)...
Go to the top of the page
 
+Quote Post
vmp
сообщение Oct 26 2006, 13:08
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 426
Регистрация: 20-01-05
Из: Зеленоград
Пользователь №: 2 070



У тебя AT91C_US0_CSR два раза считывается - первый раз в объявлении tmp, второй раз - в цикле.
Go to the top of the page
 
+Quote Post
SpiritDance
сообщение Oct 26 2006, 14:02
Сообщение #9


Дух погибшего транзистора
****

Группа: Свой
Сообщений: 877
Регистрация: 6-09-05
Из: Москва
Пользователь №: 8 288



какой компилятор-то вообще? Если ИАР, то сишному обработчику не нужно никаких модификаторов и 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 тоже верно замечено


--------------------
Yes, there are two paths you can go by But in the long run Theres still time to change the road youre on.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Oct 26 2006, 20:07
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



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

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

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

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

только сути дела это никак не меняет.
Go to the top of the page
 
+Quote Post
EugeneB
сообщение Oct 26 2006, 23:07
Сообщение #11





Группа: Новичок
Сообщений: 7
Регистрация: 6-08-06
Пользователь №: 19 356



Зачем изобретать велосипед. Берешь пример с атмела по обмену 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;
......
}
......
}

Сообщение отредактировал EugeneB - Oct 26 2006, 23:09
Go to the top of the page
 
+Quote Post
Alexey V.
сообщение Oct 27 2006, 02:24
Сообщение #12


Участник
*

Группа: Новичок
Сообщений: 24
Регистрация: 10-05-06
Из: Russia, Tomsk
Пользователь №: 16 936



Спасибо, буду пробовать
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 22nd June 2025 - 07:16
Рейтинг@Mail.ru


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