Other Parts Discussed in Thread: MSP430FR5739
I am currently working on an SPI Sniffer for the MSP430FR5739. Specifically, what I want to do is allow the MSP430 intercept SPI transactions coming from the SPI Master, and store those transactions into the FRAM.
The way I would like to do this is by using a circular buffer and a SPI Rx Interrupt Routine. Below is what I have implemented.
#define FRAM_START 0x1800
volatile unsigned char Temp_SPI_Read;
volatile unsigned char byte_count = 0;
volatile unsigned char SPI_Transmit = 0;
volatile unsigned char *FRAM_ptr;
volatile int First = TRUE;
/*************CIRCULAR BUFFER*************/
typedef struct { unsigned char value; } ElemType;
// Circular buffer object //
typedef struct
{
int size; // maximum number of elements
int start; // index of oldest element
int end; // index at which to write new element
ElemType *elems; // vector of elements
} CircularBuffer;
CircularBuffer cb;
ElemType elem = {0};
int testBufferSize = 0x100; // arbitrary size //
void cbInit(CircularBuffer *cb, int size)
{
cb->size = size + 1; // include empty elem //
cb->start = 0;
cb->end = 0;
cb->elems = (ElemType *)calloc(cb->size, sizeof(ElemType));
}
void cbFree(CircularBuffer *cb)
{
free(cb->elems); // OK if null //
}
int cbIsFull(CircularBuffer *cb) {
return (cb->end + 1) % cb->size == cb->start; }
int cbIsEmpty(CircularBuffer *cb) {
return cb->end == cb->start; }
// Write an element, overwriting oldest element if buffer is full. App can
// choose to avoid the overwrite by checking cbIsFull(). //
void cbWrite(CircularBuffer *cb, ElemType *elem) {
cb->elems[cb->end] = *elem;
cb->end = (cb->end + 1) % cb->size;
if (cb->end == cb->start)
cb->start = (cb->start + 1) % cb->size; // full, overwrite //
}
// Read oldest element. App must ensure !cbIsEmpty() first. //
void cbRead(CircularBuffer *cb, ElemType *elem) {
*elem = cb->elems[cb->start];
cb->start = (cb->start + 1) % cb->size;
}
/*
* main.c
*/
int main(void)
{
FRAM_ptr = (unsigned char *)(FRAM_START+SPI_Transmit);
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
/*************CLOCK INITIALIZER*************/
//Writes password to enable CS register access
CSCTL0_H = 0xA5;
//Set max. DCO setting to 24MHz
CSCTL1 |= DCOFSEL0 + DCOFSEL1 + DCORSEL;
// Sets the MCLK source to DCOCLK,
// the SMCLK source to DCOCLK,
// and the ACLK source to VLOCLK
CSCTL2 = SELM0 + SELM1 + SELS0 + SELS1 + SELA0;
// Sets the MCLK clock divider to 0,
// the SMCLK clock divider to 0,
// and the ACLK clock divider to 0,
CSCTL3 &= 0x00;
// Enables conditional module requests for
// MCLK, SMCLK, and ACLK
CSCTL6 |= MCLKREQEN + SMCLKREQEN + ACLKREQEN;
/*************TEMPRETURE SENSOR CONTROL*************/
// Turn off temp sensor
REFCTL0 |= REFTCOFF;
REFCTL0 &= ~REFON;
/*************GPIO INITIALIZER*************/
GPIO_init();
/*************SPI INITIALIZER*************/
UCA0CTLW0 |= UCSWRST; // **Put state machine in reset**
// 4-pin, 8-bit SPI slave
// Clock polarity high, MSB
// 4-Pin SPI, w/ UCxSTE Active Low
UCA0CTLW0 |= UCSYNC + UCMSB + UCMODE1 + UCCKPH;
UCA0CTLW0 |= UCSSEL_2; // ACLK
UCA0BR0 = 0x02; // /2
UCA0BR1 = 0; //
UCA0MCTLW = 0; // No modulation
UCA0CTLW0 &= ~UCSWRST; // **Initialize USCI state machine**
UCA0IE |= UCRXIE;// + UCTXIE; // Enable USCI_A0 RX interrupt
/*************CONFIGURE MPU*************/
MPUCTL0 = MPUPW; // Write PWD to access MPU registers
//Add any changes to the MPU here
MPUCTL0 = MPUPW+MPUENA; // Enable MPU protection
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0, enable interrupts
/*************INITIALIZE BUFFER*************/
cbInit(&cb, testBufferSize);
while (1)
{
if(SPI_Transmit > 2048)
{
cbFree(&cb);
break;
}
/* Remove and print all elements */
while (!cbIsEmpty(&cb)) {
cbRead(&cb, &elem);
FRAM_ptr = (unsigned char *)(FRAM_START+SPI_Transmit);
*FRAM_ptr = elem.value;
SPI_Transmit++;
}
}
}
#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
{
STROBE1_TOGGLE;
elem.value = UCA0RXBUF;
cbWrite(&cb, &elem);
UCA0TXBUF = 0x00;
STROBE1_TOGGLE;
__bic_SR_register_on_exit(CPUOFF);// Wake up to setup next TX
}
I know that the SPI Interrupt is working by looking at the data in the FRAM, and I am also using a Beagle SPI Sniffer to verify that my code works. However, what I am finding out is that the data isn't being correctly written to the FRAM until about 1700 transactions.
I am first wondering if my approach is the best option for this problem. I intially tried without the buffer, and my results were much worse. I've also tried to increase the buffer size, but I did not find any of the SPI transactions written to the EEPROM. Any suggestions would be appreciated.