Hi folks,
Im working withe the SPI-A on the F28027 to communicate between two of these devices. I though I had everything set up correctly, and still cant see any issue but as soon as the master F28027 starts sending data (8-bit ASCII) to the slave F28027, the slave traps the SPIRXINTA in the ISR_ILLEGAL isr.
PIECTRL.PIEVECT shows that it is the SPIRXINTA vector (0x0D91) that is being fetched when this happens, even though I have assigned my own ISR to this vector that should handle the SPI Rx. Am at a bit of a loss as to what is wrong to cause this :\
Thanks for any help figuring it out!
Below is my current code. With it when the master wishes to communicate with the slave it does so in a synchronous manner by calling spiMasterComm() which simply pushes the bytes sequentially into the TX buffer, blocking while the transmission takes place (i.e. while SPISTS.BUFFULL_FLAG is true). If the master knows a response is required from the slave it waits for a service request signal (external interrupt) then begins to feed dummy data into the TX buffer and remove the received data from the RX buffer.
the slave side operates a little more asynchronously, using interrupts, when data is received the spiSlaveRx_isr() *should* be vectored and remove the byte from the RX buffer push it to a queue, before acknowledging the interrupt and returning. If transmitting a response to the master, the slave simply calls spiSlaveTx() which pops a char off of a queue, asserts the GPIO to raise the master's external interrupt service request signal and puts the data in the TX buffer. spiSlaveTx_isr then only needs to acknowledge the TX interrupt.
static void interrupt spiSlaveRx_isr (void) {
/* Receives data on a slave unit from a master unit. */
uint16_t err = 0;
char buf[2] = {0}; /* pushIBuff requires a string input */
/* Read the data from the SPI receive buffer and push the lower byte to the SCPI input buffer */
buf[0] = (char) SpiaRegs.SPIRXBUF;
if (GpioDataRegs.GPADAT.bit.GPIO6) {/* Check SRQ is not asserted as otherwise the received data is just dummy data */
err = pushIBuff(buf); /* Push the char to the iBuff. */
if (err) /* Ensure the push completed OK. */
pushError(err);
}
PieCtrlRegs.PIEACK.bit.ACK6 = 1;/* Acknowledge the interrupt in PIE */
}
int16_t spiSlaveTx (void) {
/* Starts transmitting data-byte from a slave unit to a master unit. */
uint16_t err;
char buf = 0;
while (SpiaRegs.SPISTS.bit.BUFFULL_FLAG) {} /* Wait for the transmit buffer to be ready. */
msgs.flag.brq = true; /* Set brq message. */
err = popOQueue(&buf); /* Pop a byte from the output queue. */
if (err) { /* Check the pop occurred correctly. */
pushError(err);
return 1;
}
assertSRQ(); /* Make sure SRQ is asserted. */
buf = SpiaRegs.SPIRXBUF;/* Read any dummy data from receive buffer to clear interrupt flag. */
/* Move the byte to the transmit buffer (left justified). */
SpiaRegs.SPITXBUF = buf << 8;
return 0;
}
static void interrupt spiSlaveTx_isr (void) {
/* SPI transmission interrupt, indicating the SPI is ready for more data. */
PieCtrlRegs.PIEACK.bit.ACK6 = 1; /* Acknowledge the interrupt in PIE. */
}
int16_t spiInit(spiMode mode, uint32_t baud, spiLpbk loopback, transPol cPol, spiCPha cPha, uint16_t to) {
float spiBrr = (float)baud;
uint16_t temp = 7; /* Init the config control reg (SPICCR) value. Reset on, 8-bit char length. */
temp |= ((uint16_t) cPol) << 6; /* Add the clock polarity setting to the SPICCR value. */
temp |= ((uint16_t) loopback) << 4;/* Add the loop-back setting to the SPICCR value. */
SpiaRegs.SPICCR.all = temp; /* Save the SPICCR value to the register. */
temp = 0x02; /* Init the operation control reg (SPICTL) value. Enable TALK. */
if (mode == spiSlave) /* Enable the interrupts if this is the slave. */
temp |= 1;
temp |= ((uint16_t) cPha) << 3; /* Add the clock phase setting to the SPICTL value. */
temp |= ((uint16_t) mode) << 2; /* Add the mode setting to the SPICTL value. */
SpiaRegs.SPICTL.all = temp; /* Save the SPICTL value to the register. */
/* Use the requested baud rate and LSPCLK frequency to calculate the
* SPI bit rate control value.
* Baud rate = (LSPCLK / [SPIBRR + 1]).
*/
spiBrr = (LOSPCLK_FREQ_SET / spiBrr) - 1;
if ((spiBrr < 4) || (spiBrr > 127)) /* Ensure SPIBRR value is within bounds */
return VALUE_OOB;
SpiaRegs.SPIBRR = (uint16_t) spiBrr;/* Save the |SPIBRR| value to the register. */
SpiaRegs.SPIPRI.all = 0x00; /* Set free-run and 4-wire mode. */
if (mode == spiSlave) {
releaseSRQ(); /* Make sure outgoing SRQ output is LOW. */
PieVectTable.SPIRXINTA = &spiSlaveRx_isr; /* Set ISR for SPI receive interrupt. */
PieVectTable.SPITXINTA = &spiSlaveTx_isr; /* Set ISR for SPI transmit interrupt. */
PieCtrlRegs.PIECTRL.bit.ENPIE = 1; /* Ensure the PIE block is enabled. */
PieCtrlRegs.PIEIER6.bit.INTx1 = 1; /* Enable PIE group 6, INT 1, SPIRXINTA. */
PieCtrlRegs.PIEIER6.bit.INTx2 = 1; /* Enable PIE group 6, INT 2, SPITXINTA. */
IER |= M_INT6; /* Enable group 6 in IER */
}
rxTimeout = to; /* Save the receive timeout setting. */
resetVirtualTimer(&vTimer0); /* Setup the timer for the SRQ assertion timeout. */
setVirtualTimerThld(&vTimer0, rxTimeout);
SpiaRegs.SPICCR.bit.SPISWRESET = 1; /* Relinquish SPI from reset. */
return 0;
}
int16_t spiMasterComm (uint16_t * length, char * txMessage, char * rxMessage) {
if ((!*txMessage || !*length) && !rxMessage) /* Check parameters are valid. */
return 1; /* Parameters incorrect. */
uint16_t i = 0, dump;
char buf = 0;
if (*txMessage && *length) { /* Check if a transmission is required. */
/* Count the number of bytes sent so we know when the full message has been sent. */
for (i = 0; i < *length; i++) {
while (SpiaRegs.SPISTS.bit.BUFFULL_FLAG) {} /* Wait until the transmit buffer is ready. */
/* Move the next byte to be transmitted into the transmit buffer (left justified). */
SpiaRegs.SPITXBUF = ((uint16_t) (*txMessage++)) << 8;
}
i = 0; /* Clear the counter. */
}
if (*rxMessage) { /* Check if a receive is required. */
/* Set so the ISR doesn't regard the SRQ as a report of an error on the slave. */
expectingSRQ = true;
startVirtualTimer(&vTimer0); /* Start the timer for the receive timeout. */
/* Wait for the SRQ assertion to be reported by the ISR. */
while (!isSRQ) {}
ackSRQ(); /* Acknowledge the SRQ. */
/* Receive the expected data while the destination remains valid. */
while (*rxMessage) {
/* Transmit dummy data to run the clock for receive data from the slave. */
SpiaRegs.SPITXBUF = 0;
while (!SpiaRegs.SPISTS.bit.INT_FLAG) {} /* Wait for a data byte to be received. */
buf = (char) SpiaRegs.SPIRXBUF;
if ((buf != UNIT_SEP) && (buf != NL_MSG_TERM) && (buf != END_MSG_TERM)) {
*rxMessage++ = buf;
i++;
} else {
*rxMessage++ = 0; /* Replace any <PMUT>s or <PMT>s with string termination. */
}
}
*length = i;
}
dump = dump; /* Prevent unused variable warning. */
return 0;
}