10 Replies Latest reply on Mar 22, 2020 11:47 PM by adominator

    BCM2835 and SPI Transfers

    ceeej

      I'm using a Pi3 to control a PLL (ADF4351) which requires an initial load of 6 32 bit config words to be sent via SPI, MSB first.

       

      I've succesfully used BCM2835 to handle SPI before with a MCP23S17 so I know the library works and is installed correctly.

       

      But, the 32 bit word thing, perhaps I'm missing something (likely) but I can't work out how to transfer more than 16 bits in one go, I can of course 'twiddle' the data to  make it work with bcm2835_spi_write but that feels unnecessarily awkward and not a little inelegant so, is it possible to do a 32 bit transfer using BCM2835 elegantly or do I need to start bit shifting and masking?

       

       

      Any advice (except use another language) welcome and thanks in advance,

       

      Clint

        • Re: BCM2835 and SPI Transfers
          Roger Wolff

          You hint at that you're using a library called BCM2835 in "a language". BCM2835 is hte name of a chip, the CPU on the raspberry pi one.

           

          Now, IF BCM2835 is the name of a library for SPI on BCM2835 and similar chips, then I expect that you can transmit a number of bytes (any number) by passing an array of bytes. For 32 bits, you'd need an array with 4 bytes.

           

          In theory, sending 4 bytes that you have as a 32 bit integer rewquires no conversion: The hardware doesn't know the difference between 4 bytes and a 32bit integer. On the other hand "your language" may.

          2 of 2 people found this helpful
            • Re: BCM2835 and SPI Transfers
              ceeej

              Apologies, yes BCM2835 is an eponymously named library to control the low level peripherals of the chip.

               

              I think I've seen it mentioned here and assumed (I really should know better) which is why I wasn't more explicit.

               

              It's from https://www.airspayce.com/mikem/bcm2835/index.html

               

              You can pass it an array of bytes to send, there's an example of exactly that on the website which works but only 8 bits at a time before it deasserts CE, another of its functions allows 16 bit shorts to be sent but it still (correctly) deasserts CE after 16 bits.

               

              The ADF4351 needs to see all 32 bits of data before CE is deasserted as it latches them into the relevant registers on deassertion so sending it a short and deasserting CE produces 'odd' results.

               

              Using one of the other functions in the library allows me to send 16 bits at a time before CE deasserts so my code, at the moment, is shifting and masking 32 bit values from a 6 member 'int' array into a 12 member 'short' array, sending those 12 shorts and controlling CE instead of letting the library control it.

               

              I'm sure there's a more elegant way to do the bit manipulation but for now my main concern is that there may be a simpler, more obvious way to get 32bits out of the Pi without having to do the bit shuffling and 'manual' control of CE .

               

              To answer Michael, SPI0 but the functions appear to be the same for 'AUX' SPI (which I assume is SPI1, see above about knowing better)

                • Re: BCM2835 and SPI Transfers
                  Roger Wolff

                  The SPI protocol allows for sending a number of bits before de-asserting CE. Commonly that number is a multiple of 8, but it doesn't have to be that way.

                   

                  For example, SD cards (in the simplest form) use an SPI protocol where you need to transfer 512 bytes at a time. That is 4096 bits. (There is probably a command prefixed to that, so there will be a few more than that.)

                   

                  Anyway, If your library de-asserts CE after each byte, then that is an unwanted restriction of the library you are using. That might be "correctly" because it is documetned that way, but it is not "correct" in that it allows you to talk to "normal" SPI devices. You have the following options:

                   

                  * Read the manual of your library to figure out how you can prevent this unusual and often unwanted behaviour.

                  * Dive into the library and fix it to prevent this unusual behaviour.

                  * Use a different library.

                  * Wire your device to a different CS pin than the one that the library uses. Now program that pin low to enable your chip, send four bytes (which causes another output on the chip to go up and down 4 times.... So what?) and then program the pin high again.

                   

                  As far as I can see you need tow be able to write 24 bits without deasserting the CS line to make an MCP23S17 work. So I you might want to investigate how that's done.

                  3 of 3 people found this helpful
                  • Re: BCM2835 and SPI Transfers
                    michaelkellett

                    OK,

                     

                    First thing - the library is not very good (tempted to say junk but that might be a bit hasty). The hardware is way better than that.

                    (Actually library does seem to offer necessary functions but it has one hell of an attitude as expressed in the link you provided. I'm almost temped to contact the author directly just to wind him up  - who does he think he is  (Duchess of Sussex ?))

                    De-asserting CS after each word is niether standard or even normal practice - are you sure there isn't a way of sending a group of words (8 or 16 bit) in a single cs defined frame ?

                     

                    bcm2835_spi_transfern and

                    bcm2835_spi_transfernb

                     

                    look like likely candidates.

                     

                     

                     

                    MK

                    2 of 2 people found this helpful
                • Re: BCM2835 and SPI Transfers
                  michaelkellett

                  You need to provide more information:

                  SPI0 is different from SPI1 and 2 - which are you using ?

                   

                  Which language and which library are you using ?

                   

                  Have you read the Broadcom peripheral data sheet for the BCM2835?

                   

                  SPI0 supports  LOSSI which is not very common.

                   

                  SPI1 and 2 support 32 bit transfers in hardware.

                   

                  (Just saw Roger's post - sorry about duplication.)

                   

                  MK

                  2 of 2 people found this helpful
                  • Re: BCM2835 and SPI Transfers
                    adominator

                    Well, I wish I could've gotten here earlier, but I stumbled upon this post while searching the web trying to find an answer for basically the same issue but this was while I was rewriting aspects of the BCM2835 to serve other purposes. What I found, but haven't implemented yet, is that you can modify the DLEN Register to the number of bytes you wish to send, and this can be done using Direct Memory Access(DMA) setup by the bcm2835 library through this function call: bcm2835_peri_write(bcm2835_spi0 + BCM2835_SPI0_DLEN/4, numOfBytes);

                     

                    BCM2835_SPI0_DLEN is divided by 4 since the addresses used are for 4 byte words so the address of the register needs to be divided by 4 in order to correct for DMA.

                     

                    If you want to look into this more, look at page 156 of the BCM2835 ARM Peripherals.

                    1 of 1 people found this helpful