This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

SPI issue: long time for RXINTFLG to be set

Other Parts Discussed in Thread: HALCOGEN

I am using Halcogen and SPI1 in interrupt mode to communicate with an IMU (MPU6000). I am performing a SendData() several times and then performing a SendAndGet(). However, it seems to take the RXINTFLG a long time to be set. This results in my read actually reading the previous Rx data.

To explain, here is a segment of the HALCogen Tx buffer empty interrupt handler, where a dummy read is performed:

                 spiREG1->DAT1 = ((uint32)DataFormat << 24U) |
                                 ((uint32)ChipSelect << 16U) |
                                 (WDelay)           |
                                 (Chip_Select_Hold) |
                                 (uint32)Tx_Data;

                 /*SAFETYMCUSW 567 S MR:17.1,17.4 <APPROVED> "Pointer increment needed" */
                 g_spiPacket_t[0U].txdata_ptr++;
                 /* Dummy Receive read if no RX Interrupt enabled */
                 if(((spiREG1->INT0 & 0x0000FFFFU)& 0x0100U) == 0U)
                 {
                     if((spiREG1->FLG & 0x00000100U) == 0x00000100U)
                     {
                         SpiBuf = spiREG1->BUF;
                     }
                 }

The problem is that the Rx data comes too late and the RXINTFLG is set too late, and therefore this dummy read never occurs. Therefore, the next time I perform a Write and I enter this interrupt handler, instead of performing a dummy read of the current Rx data, I perform a read of the previous data (which has arrived by this time).

The final result of all this is that when I finally call SendAndGetData(), I go to the Rx interrupt before I get to the Tx interrupt because the RXINTFLG is still set from the Rx data of the last Write (because it was never read using the dummy read!).

The best way I see to take care of this is to clear any RXINTFLG before performing a SendAndGetData(). However, once again, it takes some time for the flag to be set, so I need to wait for the RXINTFLG to before I can clear it:

	spiSendData(spiREG1, &imu_dataconfig, 2, txData);

	while(SpiTxStatus(spiREG1) != SPI_COMPLETED);

	// Wait for RXINTFLG to be set
	while((spiREG1->FLG & 0x00000100U) != 0x00000100U);

	// Clear the RXINTFLG
	if((spiREG1->FLG & 0x00000100U) == 0x00000100U){
		// Read the buffer to clear the flag
		uint32_t spiBuf = spiREG1->BUF;
		// In case there was data in RXBUF, clear the flag again
		spiREG1->FLG = 0x00000100U;
	}

	txData[0] = (0xF5);
	txData[1] = 0;
	spiSendAndGetData(spiREG1, &imu_dataconfig, 2, txData, rxData);

This is fine with me. I would just like to know if there is any reason why it takes the Rx data and the RXINTFLG so long to be set? It seems to affect the functionality of the HALCogen code.

  • The TX interrupt flag is set when the transmit data is shifted out of the SPIDAT0/DAT1 register (start of transmission). The RX interrupt flag is set when the SPIBuf register is full (end of transmission).

    Thanks and regards,

    Zhaohong
  • So is the dummy read in the HALCogen code basically useless since the RXINTFLG is set too late?

  • I guess that the purpose of the dummy read in TX ISR is to clear previously received data.

    Since SPI operation is synchronous, my personal preference is to only use RX ISR. If you want to send a lock of data. CPU needs to write the first data to transmit. And then, you can send the rest of the data in RX ISR. You will need to maintain a counter to check the number of data remaining. In the Last RX ISR, you just need to do a dummy read and do not need to send any data.

    Thanks and regards,

    Zhaohong