Приветствую!

После нескольких секунд/минут нормальной работы SSP (режим SPI master), перестает вызываться tn_sem_isignal(&semSSP1); из IntHandlerSSP1(), т.к. счетчик принятых байт SSP1_iByteIndex меньше требуемого количества данных - SSP1_iByteCnt.

В свою очередь это вызвано тем, что происходит переполнение RX FIFO (после "зависания" установлен бит RORRIS, см. скриншот).

При этом на линии все нормально, единственное что последний байт проблемной (последней) посылки иногда выходит после небольшого временного промежутка а не мгновенно за предыдущим, в отличии от непрерывного потока байтов до него во всех? предыдущих посылках.

Не могу понять как может переполниться RX FIFO, если до записи в TX FIFO он полностью вычитывается ( while(rSSP1SR & (0x1/*RNE*/ << 2)) .... в IntHandlerSSP1())

CODE
static void InitSSP1(void)
{
rPCONP|= (1<<10);//SSP1 on

//-- Pins
rPINSEL0 |= (0x2<<16) | //-- P0.8 MISO1
(0x2<<18) | //-- P0.9 MOSI1
(0x2<<14); //-- P0.7 SCK1
//
rPCLKSEL1 |= (0x00 << 20); //-- Clock div SSP1 //0x00=div4, 0x01 = div1, 0x02 = div2, 0x03=div8

rSSP1CR0 = (0x7/*DSS*/ << 0) | (0x0/*FRF*/ << 4) | (0x1/*CPOL*/ << 6) | (0x1/*CPHA*/ << 7) | (0x0/*SCR*/ << 8);
//8 bit, no prescaler
rSSP1CR1 = (0x0/*SSE(enable)*/ << 1) | (0x0/*MS*/ << 2);//master

rSSP1CPSR = 12;//divider, 72MHz / 4 / 12 = 1.5;

rSSP1IMSC = 0;//disable interrupts

//--- Interrupts

install_irq(11, //-- IntNumber for SSP1
(unsigned int)int_func_ssp1, //-- Handler
2); //-- Priority

rSSP1CR1|= (0x1/*SSE(enable)*/ << 1);

}


int WriteReadSSP1(unsigned char* iobuf, unsigned char length)
{
int i;

rSSP1IMSC = 0;//disable interrupt

while(rSSP1SR & (0x1/*BSY*/ << 4))//transmit not finished
i=0;//dbg

while(rSSP1SR & (0x1/*RNE*/ << 2)) //receive fifo not empty - clear
i = rSSP1DR;

MCP3903_CS1tmp_CLR();//tmp

SSP1_buf = iobuf;
SSP1_iByteCnt = length;
SSP1_iByteIndex = 0;
SSP1_iByteIndexTx = 0;

if(length < SSP_FIFO_SIZE)
SSP1_iByteIndexTx = length;
else
SSP1_iByteIndexTx = SSP_FIFO_SIZE;

for(i = 0; i < SSP1_iByteIndexTx; i++)
rSSP1DR = SSP1_buf[i];//write first bytes to trigger interrupt

rSSP1IMSC = (0x1/*RTIM*/ << 1) | (0x1/*RXIM*/ << 2);//enable interrupt

tn_sem_acquire(&semSSP1, TN_WAIT_INFINITE);//wait for end of transmit/receive from interrupt

MCP3903_CS1tmp_SET();//tmp

return SSP1_iByteIndex;
}


#pragma inline
void IntHandlerSSP1()
{
unsigned int status;

status = rSSP1MIS; // Int Request Source

if(status & ((0x1/*RTMIS*/ << 1)|(0x1/*RXMIS*/ << 2)) )//rx fifo half-full or unread data in rx fifo
{
//read data
while(rSSP1SR & (0x1/*RNE*/ << 2))//receive fifo not empty
{
SSP1_buf[SSP1_iByteIndex] = rSSP1DR;//read received byte
SSP1_iByteIndex++;
}

if(SSP1_iByteIndex < SSP1_iByteCnt)
{
//write data
while(rSSP1SR & (0x1/*TNF*/ << 1))//transmit fifo not full
{
if(SSP1_iByteIndexTx < SSP1_iByteCnt)
{
rSSP1DR = SSP1_buf[SSP1_iByteIndexTx];//write byte
SSP1_iByteIndexTx++;
}
else
break;
}
}
else
{
rSSP1IMSC = 0;//disable interrupts
tn_sem_isignal(&semSSP1);
}

}
}


Нажмите для просмотра прикрепленного файла