После нескольких секунд/минут нормальной работы 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);
}
}
}
{
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);
}
}
}
Нажмите для просмотра прикрепленного файла