Reading SPI data under interrupt fails

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
KrDe_284951
Level 4
Level 4
10 replies posted 10 questions asked 5 replies posted

Hi

I have an accelerometer generating interrupts on a processor pin on a regular base. I use an SPI interface to communicate between a PSoC3 and the accelero. The routine to read the data from the accelero, using the function adxl362_ReadXYZ(),  works fine under main(). But when the same function is placed in the interrupt vector, it just generates zero a output.  When verifying the behaviour of the accelerometer output data with an ascilloscoop (on Miso, Mosi, SCLK and CS lines) , no differences in the signals can ben detected. Why is the configured SPI component behaving this way? Any ideas?  (by the way there are no other SPI devices are on the SPI bus)

My code looks like:

CY_ISR(adxl_int)

{

  static uint8 _mark = 0;

  ADXL_Sync_ClearInterrupt();

  ADC_DelSig_1_StartConvert();

adxl362_ReadXYZ();                         // comment this line when reading the data from main()

  _adxl_data_ready = 1;

}

void adxl362_ReadXYZ(void)

{

  char msg[64];

  uint8 ch;

  int16 value;

  L2C hl;

  ADXL_ena_Write(0);               // Assert CS

  mySPI_ClearRxBuffer();

    /* Send "Byte Write to Memory " instruction */

    mySPI_WriteTxData(ADXL362_CMD_READ);

  mySPI_WaitTxDone();

    mySPI_WriteTxData(ADXL362_REG_XDATA_L);

  mySPI_WaitTxDone();

  // Erase all data in the Rx buffer

  mySPI_ClearRxBuffer();

    mySPI_WriteTxData(0); // Dummy write

  mySPI_WaitTxDone();

    mySPI_WriteTxData(0); // Dummy write

  mySPI_WaitTxDone();

  hl.c[1] = mySPI_ReadRxData();

  hl.c[0] = mySPI_ReadRxData();

// axis = hl.i[0] & 0xC000;

  value = ((int16)(hl.i[0] << 4)) >> 4;

// sprintf(msg,"\n[%d] x:%d ", _fifo_count, value);

// sendMsg(DEBUG, msg);

  _fifo[0][_fifo_count] = value;

    mySPI_WriteTxData(0); // Dummy write

  mySPI_WaitTxDone();

    mySPI_WriteTxData(0); // Dummy write

  mySPI_WaitTxDone();

  hl.c[1] = mySPI_ReadRxData();

  hl.c[0] = mySPI_ReadRxData();

// axis = hl.i[0] & 0xC000;

  value = ((int16)(hl.i[0] << 4)) >> 4;

//  sprintf(msg,"y:%d ", value);

//  sendMsg(DEBUG, msg);

  _fifo[1][_fifo_count] = value;

    mySPI_WriteTxData(0); // Dummy write

  mySPI_WaitTxDone();

    mySPI_WriteTxData(0); // Dummy write

  mySPI_WaitTxDone();

  hl.c[1] = mySPI_ReadRxData();

  hl.c[0] = mySPI_ReadRxData();

// axis = hl.i[0] & 0xC000;

  value = ((int16)(hl.i[0] << 4)) >> 4;

// sprintf(msg,"z:%d ", value);

// sendMsg(DEBUG, msg);

  _fifo[2][_fifo_count] = value;

    ADXL_ena_Write(1);

  _fifo_count++;

  if (_fifo_count >= MAX_FIFO_SIZE + FIFO_HEADROOM)

  _fifo_count = MAX_FIFO_SIZE + FIFO_HEADROOM -1;

}

0 Likes
1 Solution
KrDe_284951
Level 4
Level 4
10 replies posted 10 questions asked 5 replies posted

Thanks for your efforts.

@Bob: Totally agree on your remarks, but in this application it's the only way, using a PSoC' to synchronize samples from the accelero and an analog input in combination with the data handling routines in non real time part..

The reason for the malfunctioning of the read operation under inteerupt is caused by the loop mySPI_WaitTxDone(); Under interrupt, the SPI status is always marked as "mySPI_STS_SPI_DONE", causing an early termination of the loop and hence the reading of non valid data.

This routine has following code:

void mySPI_WaitTxDone(void)

{

while(!(mySPI_ReadTxStatus() & mySPI_STS_SPI_DONE));

}

Putting some trace in software removed the issue:

void mySPI_WaitTxDone(void)

{

Pin1_Write(1);

while(!(mySPI_ReadTxStatus() & mySPI_STS_SPI_DONE));

Pin1_Write(0);

}

Removing the trace again, thus using the original code again, did not re-insert the problem... Possibly this is a compiler issue??

View solution in original post

0 Likes
4 Replies
Anonymous
Not applicable

Hi,

I don't know how the structure L2C is defined. I suspect the issue in SPI data being stored in hl.c but the "value" uses hl.i.

-Rajiv

0 Likes

Interrupt handlers should be kept small and fast. The pitfall might be to call SPI functions (write)  which could use the interrupt which will not fire because already handled. Try removing the SPI functiond from the handler, the waits() will take too much time.

Bob

0 Likes
KrDe_284951
Level 4
Level 4
10 replies posted 10 questions asked 5 replies posted

Thanks for your efforts.

@Bob: Totally agree on your remarks, but in this application it's the only way, using a PSoC' to synchronize samples from the accelero and an analog input in combination with the data handling routines in non real time part..

The reason for the malfunctioning of the read operation under inteerupt is caused by the loop mySPI_WaitTxDone(); Under interrupt, the SPI status is always marked as "mySPI_STS_SPI_DONE", causing an early termination of the loop and hence the reading of non valid data.

This routine has following code:

void mySPI_WaitTxDone(void)

{

while(!(mySPI_ReadTxStatus() & mySPI_STS_SPI_DONE));

}

Putting some trace in software removed the issue:

void mySPI_WaitTxDone(void)

{

Pin1_Write(1);

while(!(mySPI_ReadTxStatus() & mySPI_STS_SPI_DONE));

Pin1_Write(0);

}

Removing the trace again, thus using the original code again, did not re-insert the problem... Possibly this is a compiler issue??

0 Likes

Try to run this on a PSoC5!!! There are things to observe with PSoC3 and interrupts. Got any compiler warnings?

Get a CY8CKIT-059 and try.<<<<<<<<<<

Bob

0 Likes