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.
Hello,
I have my project mostly working with the TMS320F280039C and just a couple issues are holding me back from going to testing with this microcontroller. I am using the MCU to control an AC motor and have the motor spinning. The way my project is structured I have a 250us ADC interrupt that fires and does my motor control. This interrupt then fires off a user interrupt that runs for 100us (note that the added 100us must be less than 250us total). During the 250us interrupt I use SPI FIFO interrupts to read my resolver twice. This is working well, but I seem to be getting some bad data back causing noise in my speed feedback and an audible noise in my motor sometimes since I am firing current at the incorrect spot.
Below Conv1Debug3 shows a count of bad data on the SPI link - as can be seen in 1.5s I missed 14 transfers from my resolver and you can also notice the accompanying glitches in speed:
I wonder if this is a nested interrupt issue?
I am starting a SPI transfer like this - note that I had to add EINT to allow 2 SPI interrupts during my ADC ISR.
// Start sequence of SPI Master read/write register operations to Resolver chip - Blocking void SpiMaster_StartTransfer(GE_Primary_Container_t *pContainer, uint32_t command) { pContainer->mpSpiMaster->mDataRecv = 0; // Reset Rx and Tx Buffers SPIMaster_ResetBuffers(pContainer); // Set TxData buffer pContainer->mpSpiMaster->mTxData[0] = (command >> 24) & 0xFFU; pContainer->mpSpiMaster->mTxData[1] = (command >> 16) & 0xFFU; pContainer->mpSpiMaster->mTxData[2] = (command >> 8) & 0xFFU; pContainer->mpSpiMaster->mTxData[3] = (command & 0xFFU); pContainer->mpSpiMaster->mIsTransferCompleted = false; // Reset / Setup SPI SPIMaster_SetupResetSPI(pContainer); // Reset / Setup FIFO SPI_disableFIFO(REPC_RES_DSPI_MASTER_BASEADDR); SPI_clearInterruptStatus(REPC_RES_DSPI_MASTER_BASEADDR, SPI_INT_TXFF); SPI_clearInterruptStatus(REPC_RES_DSPI_MASTER_BASEADDR, SPI_INT_RXFF); SPI_enableFIFO(REPC_RES_DSPI_MASTER_BASEADDR); SPI_setFIFOInterruptLevel(REPC_RES_DSPI_MASTER_BASEADDR, SPI_FIFO_TXEMPTY, SPI_FIFO_RX4); // Enable RxFIFO Interrupt SPI_enableInterrupt(REPC_RES_DSPI_MASTER_BASEADDR, SPI_INT_RXFF); // Enable SPI SPI_enableModule(REPC_RES_DSPI_MASTER_BASEADDR); // Clear INTM so that we can trigger another interrupt inside of fast thread EINT; // Enable interrupts Interrupt_enable(INT_SPIB_TX); Interrupt_enable(INT_SPIB_RX); // Fill FIFO and send data - no interrupt required here int i = 0; for (i = 0; i < REPC_RES_MASTER_TRANSFER_SIZE; i++) { SPI_writeDataNonBlocking(REPC_RES_DSPI_MASTER_BASEADDR, ((pContainer->mpSpiMaster->mTxData[i] & 0x00FF) << 8)); } }
This is how I have the SPI initialized:
// Setup / Reset SPI void SPIMaster_SetupResetSPI(GE_Primary_Container_t *pContainer) { // Must put SPI into reset before configuring it SPI_disableModule(REPC_RES_DSPI_MASTER_BASEADDR); // SPI configuration. Use a 12.5MHz SPICLK and 32-bit word size, 25MHz LSPCLK // Rising edge SPI SPI_setConfig(REPC_RES_DSPI_MASTER_BASEADDR, REPC_RES_DSPI_MASTER_CLK_SRC, SPI_PROT_POL0PHA0, SPI_MODE_MASTER, REPC_RES_TRANSFER_BAUDRATE, 8U); SPI_disableLoopback(REPC_RES_DSPI_MASTER_BASEADDR); SPI_setEmulationMode(REPC_RES_DSPI_MASTER_BASEADDR, SPI_EMULATION_FREE_RUN); } // Init SPI1 Interface to resolver void SPIMaster_Init(GE_Primary_Container_t *pContainer) { // Register interrupt ISRs Interrupt_register(INT_SPIB_TX, &spiBTxFIFOISR); Interrupt_register(INT_SPIB_RX, &spiBRxFIFOISR); // Setup / Reset SPI SPIMaster_SetupResetSPI(pContainer); // Configuration complete. Enable the module. SPI_enableModule(REPC_RES_DSPI_MASTER_BASEADDR); // Init Master Buffers to 0 SPIMaster_ResetBuffers(pContainer); // Init Control Variables pContainer->mpSpiMaster->mIsTransferCompleted = false; }
Thanks for the help!
This happens also when the card is just sitting on my desk and not in the system.
This is the good data:
This is the bad data:
It looks like the only thing wrong in the bad data is a misplaced / extra 1
I briefly looked into your SPI configuration code, it looks fine. Did you monitor your SPI bus on oscilloscope to see whether any noise is affecting the SPI transaction? Do the error bit always happen on the bit6 or is it random.
Regards,
Manoj
Hey Manoj,
The angle has changed on my resolver (read on the PGA411-Q1 from TI). Now it is this for good data:
I captured 50 bad data points:
It looks like there are multiple configurations of bad data here.
1) bit 6 is random - 410eec63
2) Header 0x41 is repeated - 410e410e / 41410eec
3) Last byte is missed and we get first byte of the next transfer - 410eec41
When I initially got the PGA411-Q1 working with this MCU (I have it working with another MCU vendor) I thought it was weird that the MISO line does not go low between transfers - see below channel 3 on the scope:
It is hard to tell which packets are bad. I will drive a GPIO when I think there is bad data to see if anything looks weird with the packets.
Are you making sure to read the SPIRX data based on SPI RX interrupt? Based on the number 2 failure signature, I feel like you are reading SPIRXBUF in middle of SPI transaction.
2) Header 0x41 is repeated - 410e410e / 41410eec
Do you have any capacitor on MISO pin? Also, why does your SPI bus look sinusoidal?
It is hard to tell which packets are bad. I will drive a GPIO when I think there is bad data to see if anything looks weird with the packets.
Yes, this is a key experiment to identify the problem. Do you have
Regards,
Manoj
Hey Manoj,
I am triggering the interrupt after I receive 4 bytes:
SPI_enableFIFO(REPC_RES_DSPI_MASTER_BASEADDR); SPI_setFIFOInterruptLevel(REPC_RES_DSPI_MASTER_BASEADDR, SPI_FIFO_TXEMPTY, SPI_FIFO_RX4);
Then in the interrupt I just copy the data received:
void spiRxFIFOISRRoutine(GE_Primary_Container_t *pContainer) { // Read 32 bit response from PGA411-Q1 int i = 0; for (i = 0; i < REPC_RES_MASTER_TRANSFER_SIZE; i++) { pContainer->mpSpiMaster->mRxData[i] = (SPI_readDataNonBlocking(REPC_RES_DSPI_MASTER_BASEADDR) & 0x00FF); } pContainer->mpSpiMaster->mIsTransferCompleted = true; // Ack interrupt SPI_clearInterruptStatus(REPC_RES_DSPI_MASTER_BASEADDR, SPI_INT_RXFF); Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP6); }
SPI bus is not sinusoidal - it is because my scope probes are not grounded at the moment. Just ignore the sinusoidal look. It is not sinusoidal. Also there is no capacitor on MISO pin.
I will use the scope / GPIO to try and label what is bad data on the scope to see if it is actually bad or not.
Hey Manoj,
I captured the bad data - it seems that CS is going high for 1us in the middle of the transfer. What could cause this?
This is what good data looks like (majority of transfers):
I'm guessing SPISTE pin is controlled as SPI pin. Correct?
If SPISTE pin is configured as SPI pin, then SPISTE pin will go high after SPI transaction is complete (whether transmit / receive)
Yes, that is correct. But did you not see the scope trace? It goes high in the middle of the 32 bit transfer:
What is the circled area doing? Why would this happen? This is a 32 bit transfer and the CS, MISO, MOSI, CLK all glitches in the middle.
I changed the CS to a GPIO I pull low when I start a transfer and then set back to 1 in the interrupt and the bad data glitch no longer happens
I would like to know why the driver CS glitches high in the middle of the transfer though.
The snapshot you showed here doesn't look like a glitch. It is a proper signal. You may to have check your code to understand the source of the problem.
Which snapshot? The one where I circled the CS going high? How would my code drive the chip select high? That does not look like a normal transfer. I just transferred 32 bits and the CS went high in the middle of the transfer. I am not controlling CS in that case.
I switched CS to a GPIO and that resolves my issue. I can work with this but I'd like to understand why CS goes high when it is set to STE.
Which snapshot? The one where I circled the CS going high? How would my code drive the chip select high? That does not look like a normal transfer. I just transferred 32 bits and the CS went high in the middle of the transfer. I am not controlling CS in that case.
Yes, I was referring to snapshot which you had circled. Based on this snapshot, it does look like SPI transaction was complete. For 32 bit transaction, i believe you are doing two 16 bit transfers. correct? Are you using FIFO?
Hi Manoj,
Here is my init code:
// Setup / Reset SPI void SPIMaster_SetupResetSPI(GE_Secondary_Container_t *pContainer) { // Must put SPI into reset before configuring it SPI_disableModule(REPC_RES_DSPI_MASTER_BASEADDR); // SPI configuration. Use a 12.5MHz SPICLK and 32-bit word size, 25MHz LSPCLK // Rising edge SPI SPI_setConfig(REPC_RES_DSPI_MASTER_BASEADDR, REPC_RES_DSPI_MASTER_CLK_SRC, SPI_PROT_POL0PHA0, SPI_MODE_MASTER, REPC_RES_TRANSFER_BAUDRATE, 8U); SPI_disableLoopback(REPC_RES_DSPI_MASTER_BASEADDR); SPI_setEmulationMode(REPC_RES_DSPI_MASTER_BASEADDR, SPI_EMULATION_FREE_RUN); // Reset / Setup FIFO SPI_disableFIFO(REPC_RES_DSPI_MASTER_BASEADDR); SPI_clearInterruptStatus(REPC_RES_DSPI_MASTER_BASEADDR, SPI_INT_TXFF); SPI_clearInterruptStatus(REPC_RES_DSPI_MASTER_BASEADDR, SPI_INT_RXFF); SPI_enableFIFO(REPC_RES_DSPI_MASTER_BASEADDR); SPI_setFIFOInterruptLevel(REPC_RES_DSPI_MASTER_BASEADDR, SPI_FIFO_TXEMPTY, SPI_FIFO_RX4); // Enable RxFIFO Interrupt SPI_enableInterrupt(REPC_RES_DSPI_MASTER_BASEADDR, SPI_INT_RXFF); // Enable interrupts Interrupt_enable(INT_SPIB_TX); Interrupt_enable(INT_SPIB_RX); } // Init SPI1 Interface to resolver void SPIMaster_Init(GE_Secondary_Container_t *pContainer) { // Register interrupt ISRs Interrupt_register(INT_SPIB_TX, &spiBTxFIFOISR); Interrupt_register(INT_SPIB_RX, &spiBRxFIFOISR); // Setup / Reset SPI SPIMaster_SetupResetSPI(pContainer); // Configuration complete. Enable the module. SPI_enableModule(REPC_RES_DSPI_MASTER_BASEADDR); // Init Master Buffers to 0 SPIMaster_ResetBuffers(pContainer); // Init Control Variables pContainer->mpSpiMaster->mIsTransferCompleted = false; }
Here is how I initiate a transfer:
// Start sequence of SPI Master read/write register operations to Resolver chip - Blocking void SpiMaster_StartTransfer(GE_Secondary_Container_t *pContainer, uint32_t command) { pContainer->mpSpiMaster->mDataRecv = 0; // Reset Rx and Tx Buffers SPIMaster_ResetBuffers(pContainer); // Set TxData buffer pContainer->mpSpiMaster->mTxData[0] = (command >> 24) & 0xFFU; pContainer->mpSpiMaster->mTxData[1] = (command >> 16) & 0xFFU; pContainer->mpSpiMaster->mTxData[2] = (command >> 8) & 0xFFU; pContainer->mpSpiMaster->mTxData[3] = (command & 0xFFU); pContainer->mpSpiMaster->mIsTransferCompleted = false; // Clear INTM so that we can trigger another interrupt inside of fast thread EINT; GPIO_writePin(GPIO27_SPIBCS, 0); // Fill FIFO and send data - no interrupt required here int i = 0; for (i = 0; i < REPC_RES_MASTER_TRANSFER_SIZE; i++) { SPI_writeDataNonBlocking(REPC_RES_DSPI_MASTER_BASEADDR, ((pContainer->mpSpiMaster->mTxData[i] & 0x00FF) << 8)); } }
After receiving 4 bytes the RX FIFO interrupt occurs:
void spiRxFIFOISRRoutine(GE_Secondary_Container_t *pContainer) { // Read 32 bit response from PGA411-Q1 int i = 0; for (i = 0; i < REPC_RES_MASTER_TRANSFER_SIZE; i++) { pContainer->mpSpiMaster->mRxData[i] = (SPI_readDataNonBlocking(REPC_RES_DSPI_MASTER_BASEADDR) & 0x00FF); } pContainer->mpSpiMaster->mIsTransferCompleted = true; GPIO_writePin(GPIO27_SPIBCS, 1); // Ack interrupt SPI_clearInterruptStatus(REPC_RES_DSPI_MASTER_BASEADDR, SPI_INT_RXFF); Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP6); }
Notice I am controlling CS manually now. That fixes my issue with bad data. When I use CS as SPIB_STE and let the driver control it that is when the "glitches" happen.
// GPIO27 -> SPIB CS (PGA411 SPI) //GPIO_setPinConfig(GPIO_27_SPIB_STE); GPIO_setPinConfig(GPIO_27_GPIO27); GPIO_setDirectionMode(GPIO27_SPIBCS, GPIO_DIR_MODE_OUT); GPIO_setPadConfig(GPIO27_SPIBCS, GPIO_PIN_TYPE_PULLUP); GPIO_setQualificationMode(GPIO27_SPIBCS, GPIO_QUAL_ASYNC); GPIO_writePin(GPIO27_SPIBCS, 1);
You already have only 1 byte stored in pContainer->mpSpiMaster->mTxData . So, you need to use the below command. right?
SPI_writeDataNonBlocking(REPC_RES_DSPI_MASTER_BASEADDR, (pContainer->mpSpiMaster->mTxData[i]));
I sent 4 bytes with the below code:
// Start sequence of SPI Master read/write register operations to Resolver chip - Blocking void SpiMaster_StartTransfer(GE_Secondary_Container_t *pContainer, uint32_t command) { pContainer->mpSpiMaster->mDataRecv = 0; // Reset Rx and Tx Buffers SPIMaster_ResetBuffers(pContainer); // Set TxData buffer pContainer->mpSpiMaster->mTxData[0] = (command >> 24) & 0xFFU; pContainer->mpSpiMaster->mTxData[1] = (command >> 16) & 0xFFU; pContainer->mpSpiMaster->mTxData[2] = (command >> 8) & 0xFFU; pContainer->mpSpiMaster->mTxData[3] = (command & 0xFFU); pContainer->mpSpiMaster->mIsTransferCompleted = false; // Clear INTM so that we can trigger another interrupt inside of fast thread EINT; GPIO_writePin(GPIO27_SPIBCS, 0); // Fill FIFO and send data - no interrupt required here int i = 0; for (i = 0; i < REPC_RES_MASTER_TRANSFER_SIZE; i++) { SPI_writeDataNonBlocking(REPC_RES_DSPI_MASTER_BASEADDR, ((pContainer->mpSpiMaster->mTxData[i] & 0x00FF) << 8)); } }
REPC_RES_MASTER_TRANSFER_SIZE = 4.
Can you try replacing the code with red code with blue one?
// Fill FIFO and send data - no interrupt required here
int i = 0;
for (i = 0; i < REPC_RES_MASTER_TRANSFER_SIZE; i++)
{
SPI_writeDataNonBlocking(REPC_RES_DSPI_MASTER_BASEADDR, ((pContainer->mpSpiMaster->mTxData[i] & 0x00FF) << 8));
SPI_writeDataNonBlocking(REPC_RES_DSPI_MASTER_BASEADDR, (pContainer->mpSpiMaster->mTxData[i]));
}
Hi Manoj,
I did this, but it sends the wrong data. I want to send 4 8 bit packets and I have the SPI set up to do that:
SPI_setConfig(REPC_RES_DSPI_MASTER_BASEADDR, REPC_RES_DSPI_MASTER_CLK_SRC, SPI_PROT_POL0PHA0, SPI_MODE_MASTER, REPC_RES_TRANSFER_BAUDRATE, 8U);
If I want to send 8 bits I have to put the data in the upper byte of the 16 bit register like this:
SPI_writeDataNonBlocking(REPC_RES_DSPI_MASTER_BASEADDR, ((pContainer->mpSpiMaster->mTxData[i] & 0x00FF) << 8));
If I do this, I send all 0's
SPI_writeDataNonBlocking(REPC_RES_DSPI_MASTER_BASEADDR, txPacket[i]);
In the end, I am ok to use CS as a GPIO since that fixes the issue.