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; }