|
|
  |
Проблема с UART SAM7X256, зависает в прерывании |
|
|
|
Oct 26 2006, 08:37
|

Участник

Группа: Новичок
Сообщений: 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 }
|
|
|
|
|
Oct 26 2006, 08:56
|

Участник

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

|
Цитата(aaarrr @ Oct 26 2006, 11:53)  По-моему, у Вас прерывание объявлено неправильно. Но работает... меня смущает только Код AT91C_BASE_SYS->AIC_SMR[AT91C_ID_US0] = 0x63 эту строчку взял из одного примера, но не совсем понял зачем там цифра 6  ()
|
|
|
|
|
Oct 26 2006, 09:31
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Я имел в виду это: void UartIrqHandler(void) - нет модификаторов, указывающих что это прерывание. Цитата Но работает... меня смущает только Код AT91C_BASE_SYS->AIC_SMR[AT91C_ID_US0] = 0x63 Вместо 6 можно с тем же успехом написать 2. А вот работа по фронту, а не по уровню, может привести к пропуску прерываний.
|
|
|
|
|
Oct 26 2006, 10:23
|

Участник

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

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

Участник

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

|
Цитата(aaarrr @ Oct 26 2006, 14:08)  Странно, у меня этот код выполняется нормально. А другие прерывания от UART'а точно выключены? Кроме этих двух функций уарт больше нигде не упоминается (кроме непосредственно вызова InitUart)...
|
|
|
|
|
Oct 26 2006, 14:02
|

Дух погибшего транзистора
   
Группа: Свой
Сообщений: 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}^ а в чем собственнно был косяк старого кода так и осталось непонятым.  и про 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.
|
|
|
|
|
Oct 26 2006, 20:07
|
Гуру
     
Группа: Свой
Сообщений: 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); только сути дела это никак не меняет.
|
|
|
|
|
Oct 26 2006, 23:07
|
Группа: Новичок
Сообщений: 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
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|