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

 
 
 
Reply to this topicStart new topic
> Прерывания USART
Daermon
сообщение Nov 16 2007, 06:22
Сообщение #1


Участник
*

Группа: Новичок
Сообщений: 36
Регистрация: 26-10-07
Пользователь №: 31 739



AT91rm9200 AS-9200
IAR4.42


Разрешил прерывания RXBUFF и ENDRX.
На шине тишина, а прерывания эти срабатывают! В чем может быть дело?


//== Обработчик прерываний
static __arm __irq void IRQ1_RS232()
{
unsigned int status;
unsigned int status1;
//----------------------------------
AT91C_BASE_AIC->AIC_IVR = 0 ; /* enter interrupt in protected mode */
DBGU.PrintString("\n\rINTERUPT_USART1\n\r");

status = (AT91C_BASE_US1->US_CSR) ;
status1 = (AT91C_BASE_US1->US_IMR);
status &=status1;
//
//* Disable all interrupts
// AT91C_BASE_US1->US_IDR = (0xFFFFFFFF);

if( status & AT91C_US_TXEMPTY ){DBGU.PrintString("\n\rAT91C_US_TXEMPTY\n\r");}
if( status & AT91C_US_RXBUFF )
{
RxBuffer[count++] = AT91F_US_GetChar(AT91C_BASE_US1);
if(count==5)
{
count=0;
for(int i=0;i<10;i++)
RxBuffer[i]=0;
}
DBGU.PrintString("\n\rAT91C_US_RXBUFF\n\r");
}
if( status & AT91C_US_TXBUFE ){DBGU.PrintString("\n\rAT91C_US_TXBUFE\n\r");}
if( status & AT91C_US_TIMEOUT ){DBGU.PrintString("\n\rAT91C_US_TIMEOUT\n\r");}
if( status & AT91C_US_ENDTX ){DBGU.PrintString("\n\rAT91C_US_ENDTX\n\r");}
if( status & AT91C_US_ENDRX )
{
RxBuffer[count++] = AT91F_US_GetChar(AT91C_BASE_US1);
if(count==5)
{
count=0;
for(int i=0;i<10;i++)
RxBuffer[i]=0;
}
}
if( status & AT91C_US_ITERATION ){;}
if( status & AT91C_US_NACK ){;}
if( status & AT91C_US_RIIC ){;}
if( status & AT91C_US_DSRIC ){;}
if( status & AT91C_US_DCDIC ){;}
if( status & AT91C_US_CTSIC ){;}
AT91C_BASE_US1->US_CR = AT91C_US_RSTSTA;
AT91C_BASE_AIC->AIC_EOICR = 0 ; /* unstack one level */
}

status = (AT91C_BASE_US1->US_CSR) ;
Эта операция не чистит статус рег.
можно опять вызвать
status = (AT91C_BASE_US1->US_CSR) ;
и статус снова будет тем же
Go to the top of the page
 
+Quote Post
VSt&
сообщение Nov 16 2007, 08:53
Сообщение #2


Частый гость
**

Группа: Свой
Сообщений: 101
Регистрация: 3-08-06
Из: Екатеринбург
Пользователь №: 19 275



прерывания срабатывают, потому что счетчики PDC пустые
RXBUFF и ENDRX встают при обнулении RXNCR и RXCTR соответственно

работа с PDC ведется следующим образом:
в регистры RXPTR, TXPTR записываются указатели куда писать и откуда читать
в регистры RXCTR, TXCTR записывается, сколько писать и сколько читать
далее инициализируется трансфер

прерывания ENDRX, ENDTX, RXBUFF, TXBUFE встают при обнулении счетчиков DMA
Go to the top of the page
 
+Quote Post
Daermon
сообщение Nov 16 2007, 10:23
Сообщение #3


Участник
*

Группа: Новичок
Сообщений: 36
Регистрация: 26-10-07
Пользователь №: 31 739



Вроде все заработало...но появилась другая проблема.

В обработчике прерывания вызываю функцию
AT91F_US_ReceiveFrame (AT91C_BASE_US1,RxBuffer, 5, 0,0 );

Если посылаю посылку (0x01 0x02 0x03 0x04 0x05), то приемный буфер заполняется с 0го элемента до 4го:
RxBuffer[0] = 1;
RxBuffer[1] = 2;
RxBuffer[2] = 3;
RxBuffer[3] = 4;
RxBuffer[4] = 5;

если вдруг в результате сбоя или еще чего посылка становится другой, например
(0x01 0x02 0x03 0x04 0x05 0x06) - в этом случае принимаем следующее:
RxBuffer[0] = 6;
RxBuffer[1] = 1; // интересно куда пропала 5 ка???
RxBuffer[2] = 2;
RxBuffer[3] = 3;
RxBuffer[4] = 4;




а потом востанавливается до 5 байт (0x01 0x02 0x03 0x04 0x05), и начинаем принимать:
RxBuffer[0] = 5;
RxBuffer[1] = 1;
RxBuffer[2] = 2;
RxBuffer[3] = 3;
RxBuffer[4] = 4;

Необходимо вернуть прием в след вид
RxBuffer[0] = 1;
RxBuffer[1] = 2;
RxBuffer[2] = 3;
RxBuffer[3] = 4;
RxBuffer[4] = 5;

Что можно сделать?

Преинициализацию PDP делал - непомагает.
//* Disable the RX and TX PDC transfer requests
AT91F_PDC_DisableRx(pPDC);
AT91F_PDC_DisableTx(pPDC);

//* Reset all Counter register Next buffer first
AT91F_PDC_SetNextTx(pPDC, (char *) 0, 0);
AT91F_PDC_SetNextRx(pPDC, (char *) 0, 0);
AT91F_PDC_SetTx(pPDC, (char *) 0, 0);
AT91F_PDC_SetRx(pPDC, (char *) 0, 0);

//* Enable the RX and TX PDC transfer requests
AT91F_PDC_EnableRx(pPDC);
AT91F_PDC_EnableTx(pPDC);

//*----------------------------------------------------------------------------
//* \fn AT91F_US_ReceiveFrame
//* \brief Return 2 if PDC has been initialized with Buffer and Next Buffer, 1 if PDC has been initializaed with Next Buffer, 0 if PDC is busy
//*----------------------------------------------------------------------------
inline unsigned int AT91F_US_ReceiveFrame (
AT91PS_USART pUSART,
char *pBuffer,
unsigned int szBuffer,
char *pNextBuffer,
unsigned int szNextBuffer )
{
return AT91F_PDC_ReceiveFrame(
(AT91PS_PDC) &(pUSART->US_RPR),
pBuffer,
szBuffer,
pNextBuffer,
szNextBuffer);
}
Go to the top of the page
 
+Quote Post
VSt&
сообщение Nov 16 2007, 11:05
Сообщение #4


Частый гость
**

Группа: Свой
Сообщений: 101
Регистрация: 3-08-06
Из: Екатеринбург
Пользователь №: 19 275



мне почему-то кажется, что дело в размерности элементов Вашего RxBuffer и выравнивании, т.к. я не вижу механизмов, сдвигающих массив поиндексно (а у Вас так и происходит, 0х06 встает спереди, сдвигая все на один индекс вверх)
предлагаю попробовать USART c DMA без прерываний, возможно на "пустом" проекте, сделать "ровные" массивы для dma

в момент окончания приема, определяемый обнулением значения счетчика dma, регистр RXPTR указывает на адрес последнего принятого элемента

Сообщение отредактировал VSt& - Nov 16 2007, 11:11
Go to the top of the page
 
+Quote Post
Daermon
сообщение Nov 16 2007, 12:29
Сообщение #5


Участник
*

Группа: Новичок
Сообщений: 36
Регистрация: 26-10-07
Пользователь №: 31 739



Не индексирую массив потому что просто хочу перезаписать старые значения новыми. масив char RxBuffer [250];

я так понимаю что вызовом AT91F_US_ReceiveFrame (AT91C_BASE_US1,RxBuffer,5, 0,0 );
я инизиализирую прием в адрес RxBuffer пяти байт. Но почему то этого не происходит...

может нужно очистить PDC но как это сделать простая перейинициализация не помагает...


А как без прерываний сделать чтение через PDC ?

inline void AT91F_US_ResetRx (
AT91PS_USART pUSART) // \arg pointer to a USART controller
{
//* Reset receiver
pUSART->US_CR = AT91C_US_RSTRX;
//* Re-Enable receiver
pUSART->US_CR = AT91C_US_RXEN;
}


делаю резет перед AT91F_US_ReceiveFrame (AT91C_BASE_US1,RxBuffer,5, 0,0 );

И все работает smile.gif))

Сообщение отредактировал Daermon - Nov 16 2007, 12:09
Go to the top of the page
 
+Quote Post
VSt&
сообщение Nov 16 2007, 17:50
Сообщение #6


Частый гость
**

Группа: Свой
Сообщений: 101
Регистрация: 3-08-06
Из: Екатеринбург
Пользователь №: 19 275



алгоритм работы с последовательной периферией посредством DMA:
1) при инициализации периферии обнуляем все указатели и счетчики PDC, выключаем обмен TXTDIS, RXTDIS
2) в приложении, для того, чтобы принять блок данных, выполняем следующую последовательность действий:
2.1) устанавливаем указатель(и) и счетчик(и) PDC на некоторую заранее определенную область памяти, память должна быть некешируемой
2.2) включаем нужные прерывания - ENDRX, ENDTX, RXBUFF, TXBUFE и др. - в IMR (AIC сконфигурирован заранее)
2.3) разрешаем обмен TXTEN, RXTEN
2.4) занимаемся далее своими делами, ожидая прерывания
3) хендлер прерывания выключает обмен, при необходимости устанавливает новые указатели и счетчики, и снова разрешает обмен - либо играет глобальными флагами( sad.gif )


вроде ничего не напутал
p.s. не увлекайтесь иаровскими макросами - в первый раз лучше написать лично с указанием регистров и битов
Go to the top of the page
 
+Quote Post
Daermon
сообщение Nov 19 2007, 09:47
Сообщение #7


Участник
*

Группа: Новичок
Сообщений: 36
Регистрация: 26-10-07
Пользователь №: 31 739



Спасибо! Разобрался. Все работает.
Go to the top of the page
 
+Quote Post
Daermon
сообщение Nov 20 2007, 10:10
Сообщение #8


Участник
*

Группа: Новичок
Сообщений: 36
Регистрация: 26-10-07
Пользователь №: 31 739



Опа..шаманство какоето. вчера весь день все нормально запускалось. сегодня добавил пару строчек и все заткнулось..удаление этих строк ни к чему хорошему не привело... может в ИАРе глюк какой есть..файлы не не подтягивает или еще что???

Запускаю USART1
void Usart1::Init()
{
for(int i=0;i<100;i++) Usart1::OutBuf[i] = i+100;
PIO_Init();
AIC_Init();

AT91F_US1_CfgPMC();

AT91F_US_Configure (
AT91C_BASE_US1, // \arg pointer to a USART controller
60000000, // \arg peripheral clock - 60 ÌÃö
AT91C_US_USMODE_NORMAL | // normal mode
AT91C_US_CLKS_CLOCK | // clock is MCK
AT91C_US_CHRL_8_BITS | // 8 databits
AT91C_US_PAR_NONE | // no parity
AT91C_US_NBSTOP_1_BIT | // 1 stopbit
AT91C_US_CHMODE_NORMAL // channel mode - normal
// AT91C_US_CHMODE_LOCAL // channel mode - local
, // \arg mode Register to be programmed
9600 , // \arg baudrate to be programmed
0 ); // \arg timeguard to be programmed


AT91F_US_ResetTx(AT91C_BASE_US1);
AT91F_US_ResetRx(AT91C_BASE_US1);

AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_US1,AT91C_AIC_PRIOR_HIGHEST, AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, (void (*)(void))IRQ1_USART);
AT91C_BASE_AIC->AIC_EOICR = 0 ; /* unstack one level */
AT91C_BASE_AIC->AIC_ICCR = ( 1<<AT91C_ID_US1 );
AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_US1);
__enable_interrupt();
AT91F_US_EnableIt(AT91C_BASE_US1,AT91C_US_ENDRX);

}

а в обработчике инициализирую прием через PDC

static __arm __irq void IRQ1_USART()
{
unsigned int status;
unsigned int status1;

AT91C_BASE_AIC->AIC_IVR = 0 ; /* enter interrupt in protected mode */
//* get Usart status register and active interrupt

status = (AT91C_BASE_US1->US_CSR) ;status &= (AT91C_BASE_US1->US_IMR);
status = (AT91C_BASE_US1->US_CSR) ;
status1 = (AT91C_BASE_US1->US_IMR);
status &=status1;

//* Disable all interrupts
AT91C_BASE_US1->US_IDR = (0xFFFFFFFF);
if( status & AT91C_US_ENDTX )
{

}

if(status & AT91C_US_ENDRX )
{

AT91F_US_ResetRx(AT91C_BASE_US1);
AT91F_US_ReceiveFrame (AT91C_BASE_US1,RxBuffer,Rx_Len,RxBuffer+10,Rx_Len );
AT91F_US_EnableIt(AT91C_BASE_US1,AT91C_US_ENDRX); //AT91C_US_RXRDY);

}

AT91C_BASE_US1->US_CR = AT91C_US_RSTSTA;
AT91C_BASE_AIC->AIC_EOICR = 0 ;

}

Все в теории должно пахать...а на практике работало только вчера smile.gif)) Может сегодня магнитные бури???
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Nov 20 2007, 10:53
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Коллега!

Как ты думаешь, когда вырабатывается прерывание ENDRX? Когда заполнится приемный буффер через DMA. Если ты его в Init'e никак не определяешь, то чего же ты хочешь?
Go to the top of the page
 
+Quote Post
Daermon
сообщение Nov 20 2007, 12:09
Сообщение #10


Участник
*

Группа: Новичок
Сообщений: 36
Регистрация: 26-10-07
Пользователь №: 31 739



Очепятка
AT91F_US_ReceiveFrame (AT91C_BASE_US1,RxBuffer, Rx_Len, 0,0 );
Вот что стоит перед разрешением прерывания.

Хотя... практика показывает что и без ЭТОГО работает, так как прерывания начинают сразу генериться как только счетчик PDC становится равным 0.


Я плакаю crying.gif не могу отладить этот код через SAM-ICE...почемуто в прерывания не заходит...вижу что в AIC_IPR регистре выставляется флаг....а в прерывание не заходит.
Если заливаю код через DBGU то отлично все работает...

Из за чего может не работать SAM-ICE???
Прибор исправный. Есть 3 новых штуки - проверял.

А вот вчера и через SAM-ICE все нормально работало.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 20 2007, 12:24
Сообщение #11


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Daermon @ Nov 20 2007, 14:09) *
Я плакаю crying.gif не могу отладить этот код через SAM-ICE...почемуто в прерывания не заходит...вижу что в AIC_IPR регистре выставляется флаг....а в прерывание не заходит.
Если заливаю код через DBGU то отлично все работает...
Закройте окно просмотра AIC. Или отредактируйте .ddf и удалите из этого окна AIC_IVR. Чтение этого регистра, даже отладчиком, говорит процессору, что началась обработка прерывания и все прерывания с этим и более низким приоритетом блокируются. То же и с другой периферией - если чтение какого-то регистра приводит к каким-то действиям, то смотреть этот регистр в отладчике не надо.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Daermon
сообщение Nov 20 2007, 12:36
Сообщение #12


Участник
*

Группа: Новичок
Сообщений: 36
Регистрация: 26-10-07
Пользователь №: 31 739



a14.gif

Вотэто да....
И точно...ни за что бы не додумался

Борщу a14.gif a14.gif a14.gif a14.gif
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 27th July 2025 - 16:14
Рейтинг@Mail.ru


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