3 Replies Latest reply on Aug 10, 2020 11:58 AM by coldfront

    SPI return result issue

    coldfront

      Hello Everyone,

      I hope someone can help and answer a few questions I have in-regards to SPI protocol and the MDK. Currently I have 2 x MDK, 2 x PiHats, and a few perf boards. I have tried on multiple MDKs, a PiHat, and a perf board with all the same results. I am trying to interface over SPI with a HopeRF RFM95 Sub-Ghz LoRa module (https://www.hoperf.com/modules/lora/RFM95.html). Currently I have it wired up with the table below.

      The issue I am having is the return results from SPI_SEND(), judging from the block comment it returns the value of what should be stored in the registry.

      /****************************************************************************

      * Name: SPI_SEND

      *

      * Description:

      *   Exchange one word on SPI. Required.

      *

      * Input Parameters:

      *   dev - Device-specific state data

      *   wd  - The word to send.  the size of the data is determined by the

      *         number of bits selected for the SPI interface.

      *

      * Returned Value:

      *   Received value

      *

      ****************************************************************************/

       

      #define SPI_SEND(d,wd) ((d)->ops->send(d,(uint16_t)wd))

       

      My issue is the return results when my readu8 and writeu8 functions are called is 0x00. I have tracked down where the spi_send() function is called for the stm32 cortex board and copied the spivdbg line changing the function to dbg() to receive output to the ramlog of nsh console.

      static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)

      {

        FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev;

        uint32_t regval;

        uint16_t ret;

        DEBUGASSERT(priv && priv->spibase);

        spi_writeword(priv, wd);

        ret = spi_readword(priv);

        /* Check and clear any error flags (Reading from the SR clears the error flags) */

        regval = spi_getreg(priv, STM32_SPI_SR_OFFSET);

        spivdbg("Sent: %04x Return: %04x Status: %02x\n", wd, ret, regval);

        dbg("Sent: %04x Return: %04x Status: %02x\n", wd, ret, regval);

        UNUSED(regval);

        return ret;

      }

       

      The return results in the spi_send function are correct but when they are passed to the SPI_SEND() macro they seem to just produce 0x00. I have provided my rfm95_readu8() function below.

      uint8_t rfm95_readu8(FAR struct rfm95_dev_s *dev, uint8_t regaddr) {

          uint8_t regval;

        rfm95_lock(dev->spi);

          rfm95_select(dev);

        SPI_SEND(dev->spi, regaddr);

        regval = SPI_SEND(dev->spi, 0);

          rfm95_deselect(dev);

          rfm95_unlock(dev->spi);

        dbg("regAddr=0x%04x, regVal=0x%04x\n", regaddr, regval);

          return regval;

      }

       

      From my understand with SPI and to access the registry values is first we send over the registry address, and we call SPI_SEND again to pull the results of such address. Bellow is a screenshot of the nsh /dev/ramlog

       

       

      As we can see where spi_send it returns the correct Sent and Return values. But when the return value for uint8_t regval = SPI_SEND(); the result for the regval is 0x00. I have also attached the lines up to my saleae pro 16 analyzer.

       

      It would seem judging from the data table on the right the bytes being sent over are correct and the return results should be correct. This makes me believe my code is wrong some how inside my function where I am not getting the correct return value. The HopeRF RFM95 is an MSB, and full-duplex CPOL = 0 and CPHA = 0. This is coming from the datasheet, which I have set when configuring the spi device.

       

      If anyone has any insight on what my issue is please let me know thanks.

       

      Message was edited by: David Mydlarz

        • Re: SPI return result issue
          wolfgangfriedrich

          Hello David,

          Just a guess from looking through the code:

          SPI_SEND() is looking for the 16 bit value for the 2nd parameter, thus clocking out 16 bit.

          In your rfm95_readu8 function, the return variable regval defined as uint8_t regval;    

          is only 8 bit wide, so you might be losing the other 8 bit of the chip response containing the response you are looking for.

           

          - W.

          (Sorry for the light grey font colour, I copied text from your code example and cannot change colours.)

            • Re: SPI return result issue
              coldfront

              Hello Wolfgang Friedrich,

               

              Thanks for replying. Shortly after posting this and looking over the code again I had noticed it was returning a uint16, I changed my variable to uint16 and the value had returned in full. I have never worked with SPI before and most of the libraries I have looked over in-regards to the rfm95w read/write registry it would seem they all have a return type of uint8. I have set my spi_config for 8 bits which I would assume would be its 8 bits in length for all the data being returned over SPI. Would this be a correct assumption?

               

              void rfm95_configspi(FAR struct spi_dev_s *spi) {

                SPI_SETMODE(spi, SPIDEV_MODE0);

                SPI_SETBITS(spi, 8);

                SPI_SETFREQUENCY(spi, 1000000);

                dbg("... Done!\n");

              }

               

               

              I will connect the module to my raspberrypi, and logic analyzer later and see what data is being set when it is initialized to correspond it with the output I am receiving. Just to make sure there isn't any other issue even thought I do think I am setting up the SPI device and it does seem to be sending the correct bytes over when i send over 0x80 for setting the rf mode of the module. I semi based my code off of the spi example over at https://github.com/micro-ROS/NuttX/issues/29. I do believe they run a newer version of nuttx I don't think this would be an issue though because most of the base code I looked over is all the same. The newer Apache nuttx did change over the spi_send from uint16_t to uint32_t which isn't an issue here, just the return value if anything I would believe it should be 0x80. I will look over the datasheet of the rfm95w later to make sure what the correct byte value should be when reading from the module later.
              *update*
              Also to add to the point MSB (most significant bit) from what I have been reading it is the left or highest bit. Would this mean nuttx/spi should be clearing all the other bits and only selecting the most significant bit?
              Thanks,
              David
              • Re: SPI return result issue
                coldfront

                Hello again,

                 

                I was looking over Porting the PaPiRus HAT to the MDK, it would seem they use SPI protocol on the MDK. Looking at comment #7.

                 

                * Stm32_spi.c: 1444: RPi’s epd_spi utility code did not clear the LSBFIRST bit.  The MDK doesn’t support configuration of those clear bits, so we had no choice but to edit the MDK’s SPI code to NOT clear that bit.

                 

                Even thought they are speaking about LSBFIRST which i beleive would apply for least significant bit. I am surprised this code had even executed looking over their "nuttx/nuttx/configs/hdk/muc/epd/defconfig" file they have # CONFIG_SPI_OWNBUS is not set. Which judging from the stm32_spi.c code the lines they changed would only be executed if it was set to Yes/True. I have setup vscode for debugging and now I am able to breakpoint across my code...

                Hopefully my questions are not that stupid... I am pretty new to working with Nuttx/MCU/SPI most of my programming is in higher level languages. I don't know if this would be the same kind of issue he is having where the LSB are not being cleared out at the end if that is what even it applies to.

                 

                Thanks,

                David