4 Replies Latest reply on Jul 16, 2018 2:07 AM by bob.marlowe

    Reading SPI data under interrupt fails

    user_148813134

      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;

       

      }

        • 1. Re: Reading SPI data under interrupt fails
          rajiv.vasanth.badiger

          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

          • 2. Re: Reading SPI data under interrupt fails
            bob.marlowe

            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

            • 3. Re: Reading SPI data under interrupt fails
              user_148813134

              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??

              • 4. Re: Reading SPI data under interrupt fails
                bob.marlowe

                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