Принима данные из UDP, разбираю FIFO буфер UDP и заполняю собственный стек типа FIFO для SSC. SSC по прерыванию забирает из моего стека данные и отправляет их со скоростью 100 кбит\с. Дополнительный стек необходим, чтобы сильно не тормозить работу компьютера по USB, чтобы не происходила потеря данных.
CODE
unsigned int que[16]; // Стек типа FIFO для передаваемых по SSC данных
unsigned int head = 0; //начальный индекс
unsigned int tail = 0; //конечный индекс
//Обработчик прерывания SSC
__ramfunc void SscHandler()
{
AT91C_BASE_SSC->SSC_THR = que[head]; //отправляем на передачу слово из стека для SSC
head = (head+1)&0xf; //инкрементируем начальный индекс стека
//если начальный индекс обнулился, значит стек пуст и готов для повторного заполнения
if(head == 0) { AT91C_BASE_SSC->SSC_CR = AT91C_SSC_TXDIS ;
AT91C_BASE_SSC->SSC_IDR = 0xfff; jj=0;}
unsigned int dummy = AT91C_BASE_SSC->SSC_SR;
}
void main()
{
while(1)
{
//если FIFO UDP пуст
if(length == 0)
{
// проверка флага прерывания от EP2
if((AT91C_BASE_UDP->UDP_ISR) & AT91C_UDP_EPINT2)
{
if(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] & pCDC.currentRcvBank)
length = regUDP->UDP_CSR[AT91C_EP_OUT]>>16;
}
}
//если в FIFO UDP присутствуют данные, то заполняем
if(length != 0)
{
if(jj==0) //если стек для SSC не заполнен, то продолжаем его заполнять
{
unsigned int byte[4];
byte[0] = regUDP->UDP_FDR[AT91C_EP_OUT];
byte[1] = regUDP->UDP_FDR[AT91C_EP_OUT];
byte[2] = regUDP->UDP_FDR[AT91C_EP_OUT];
byte[3] = regUDP->UDP_FDR[AT91C_EP_OUT];
unsigned int dat_buf = (byte[3]<<24)|(byte[2]<<16)|(byte[1]<<8)|byte[0];
//формируем 32-битное слово для передачи по SSC
que[tail] = dat_buf;
tail = (tail+1)&0xf;
//инкрементируем конечный индекс и накладываем маску (размер стека 16 слов)
if(tail == 0) jj = 1;
//если конечный индекс обнулился, значит стек полон и необходимо прекратить запись в него, пока он не освободится
else {AT91C_BASE_SSC->SSC_CR = AT91C_SSC_TXEN; AT91C_BASE_SSC->SSC_IER = AT91C_SSC_TXRDY;}
//иначе разрешаем передачу по SSC
length = length-4; //уменьшаем значение остатка в FIFO UDP
}//if(jj == 0)
if(length == 0)
{
Udp_ep_clr_flag(regUDP,AT91C_EP_OUT, pCDC.currentRcvBank);
if(pCDC.currentRcvBank == AT91C_UDP_RX_DATA_BK0)pCDC.currentRcvBank = AT91C_UDP_RX_DATA_BK1;
else pCDC.currentRcvBank = AT91C_UDP_RX_DATA_BK0;
AT91C_BASE_UDP->UDP_ICR = 0xFFFFFFFF;
}
}//if(length != 0)
}//while(1)
}//main
Таким образом, в случае заполнения стека que[], данные из FIFO UDP не считываются пока SSC не опустошит свой стек que[].
Если убрать из обработчика SSC останов передатчика (AT91C_BASE_SSC->SSC_CR = AT91C_SSC_TXDIS ; AT91C_BASE_SSC->SSC_IDR = 0xfff;) то прошивка не повисает. Но тогда данные, передаваемые по SSC будут уже не те. Не понятно где может повиснуть прошивка, так как останов и повторный запуск SSC работает, проблемы возникли, когда я ввел стек.
Сообщение отредактировал rezident - Apr 30 2010, 21:11
Причина редактирования: Редактирование оформления цитаты исходника.