1 2 Previous Next 22 Replies Latest reply on Jan 28, 2015 10:13 AM by xblades

    Question about Write/Read SPI functions for Edison (Mraa)

    danny7yoo

      Hi,

       

      I am currently working with VC0706 SPI camera module and Edison arduino board.

      For Camera-to-Edison connection, I am using pins 10-13 on the Arduino breakout board.

       

      1) First questions is: Do I need to somehow manually set pins10-13 to SPI pins instead of default digital I/O on the arduino? (If so how can I do that?)

      2) I was wondering if anyone has confirmed that the SPI functions in Mraa Intel iot-devkit library works properly.

      I've tried to send some commands to my camera via both mraa_spi_write_buf() and mraa_spi_transfer_buf() but I don't think the commands are being sent properly to my VC0706 Camera. Also, wirte/transfer functions are supposed to return Data received on the MISO line but I am skeptical as to if it actually returns the 'output' from my camera. (Because I receive 0x00 + 0x00 + 0x00 + 0x00 + 0x00 but according to the camera datasheet, return value should begin with 0x76)

       

      Example of the command:

      Command function :System reset

      Command format :0x56+Serial number+0x26+0x00

      Return format :0x76+Serial number+0x26+0x00+0x00 (But I would receive 0x00 + 0x00 + 0x00 + 0x00 + 0x00)

       

      My code:

      #include "mraa.h"

      #include <unistd.h>

      #include <stdint.h>

       

      int

      main(int argc, char **argv) {

          mraa_init();

          mraa_spi_context spi;

          spi = mraa_spi_init(0);

          unsigned int response = 0;

          printf("Hello, SPI initialised\n");

       

          //mraa_spi_mode_t MRAA_SPI_MODE0;

          //mraa_spi_mode (spi, MRAA_SPI_MODE0);

         // printf("Set to SPI mode:0\n");

       

          int freq = 12000000; // set SPI frequency to 12 MHz

          mraa_spi_frequency (spi, freq);

          printf("SPI clock frequency set to %iHz\n", freq);

       

          uint8_t data[] = {0x56, 0x00, 0x26, 0x00};

          uint8_t *recv;

          recv = mraa_spi_write_buf(spi, data, 4);

          printf("Writing System_Reset 0x%X + 0x%X + 0x%X + 0x%X\n", data[0], data[1], data[2], data[3]);

          usleep(100000);

          if (recv == NULL)

              printf("Errors encountered when writing to camera\n");

        else

              printf("RECEIVED 0x%X + 0x%X + 0x%X + 0x%X + 0x%X\n",recv[0], recv[1], recv[2], recv[3], recv[4]);

          usleep(100000);

       

       

          uint8_t *rxbuf;

          mraa_spi_transfer_buf (spi, data, rxbuf, 4);

          printf("Transfering System_Reset 0x%X + 0x%X + 0x%X + 0x%X\n", data[0], data[1], data[2], data[3]);

          usleep(100000);

          if (rxbuf == NULL)

              printf("Errors encountered when transfering to camera\n");

          else

              printf("RECEIVED 0x%X + 0x%X + 0x%X + 0x%X + 0x%X\n",rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3], rxbuf[4]);

          usleep(100000);

      }

       

      Thanks,

      -Danny

        • 1. Re: Question about Write/Read SPI functions for Edison (Mraa)
          CMata_Intel

          Hi danny7yoo

           

          Are you using the pins as :

               MOSI: pin 11

               MISO: pin 12

               SCK: pin 13

          What are you using in pin 10, "chip select" pin?

          You are using this example as template so you should't have problems. Are you using a logic analyzer? If you do, are you writing as you should? Take a look at MISO signal and verify that you are writing what you want.

           

          Regards;

          CMata

          • 2. Re: Question about Write/Read SPI functions for Edison (Mraa)
            danny7yoo

            Hi CMata,

             

            Thanks for the reply. I do not have access to a logic analyzer as university is closed for the holiday.

            One question regarding MISO. I thought the Edison is sending commands to the SPI device through MOSI and then receiving it back through MISO line? So shouldn't I be checking MOSI line to see if I'm sending the correct signal?

             

            Thanks,

            Danny

            • 3. Re: Question about Write/Read SPI functions for Edison (Mraa)
              CMata_Intel

              Yes, sorry for that, you should check MOSI signal

              • 4. Re: Question about Write/Read SPI functions for Edison (Mraa)
                danny7yoo

                Writing System_Reset 0x56 + 0x0 + 0x26 + 0x0

                RECEIVED 0x0 + 0x0 + 0x0 + 0x0 + 0x0

                Transfering System_Reset 0x56 + 0x0 + 0x26 + 0x0

                RECEIVED 0x85 + 0xC0 + 0x74 + 0x2A + 0x8B

                 


                I am getting this result which is no where close to what I am supposed to receive (0x76+0x00r+0x26+0x00+0x00 )

                I am curious as to the difference between mraa_spi_write_buf, mraa_spi_transfer_buf

                • 5. Re: Question about Write/Read SPI functions for Edison (Mraa)
                  danny7yoo

                  Hi CMata,

                   

                  for pin10, I've connected it to SPI_SS pin from the VC0706 camera module.

                  I'm new to SPI but I know that SS needs to be set low in order to activate the slave(camera)? Is is done automatically on the Edison side?

                   

                  -Danny

                  • 6. Re: Question about Write/Read SPI functions for Edison (Mraa)
                    KurtE

                    I will chime in a bit here as I have SPI working using MRAA (and Arduino) for use with the Adafruit TFT displays that use the ILI9341 display.

                     

                    Some thoughts that come to mind, that I have run into and the like:

                     

                    First the easy thing.  The difference between write_buf and transfer_buf.  (I added transfer_buf). write_buf calls transfer_buf.  The difference is that write_buf calls malloc to allocate the read buffer, that is returned and as such your user application is responsible to free this buffer.  Whereas transfer_buf, you pass in the buffer that you wish to use and if it is some fixed buffer you avoid having a lot of mallocs/frees going on  Also if you are really only doing a write and don't need the return results, you can pass in NULL, and the kernel does not have to take the time to copy the data back to your buffer.

                     

                    Also MRAA does initialize the SCLK, MISO, MOSI and CS to be in SPI mode when the spi_init is called.

                     

                    Currently with user mode spi (through SPIDEV), the fastest speed that it appears to support is 6.5mhz.  In addition for whatever reason there is a pretty big gap of time between bytes sent, so so lucky to maybe get about 3mhz. Hopefully this will change as the specs say that SPI can support up to 25mhz?

                     

                    CS pin - By default MRAA now initializes the CS pin (Arduino pin 10) to be in SPI mode. This may be good or bad.  The issue is, that there does not appear to be any control of it from the user side (SPIDEV).  There are flags that are parts of the IOCTL control, that is supposed to allow you to choose if the CS pin should stay asserted or not between calls.   Right now I believe that the CS goes low for each byte and then back high.  It may have changed to do this by the wordsize mentioned in the IOCTL.  Not sure.

                     

                    This did not work for me in the ILI9341 driver, especially for read operations.  As for example if you are in a read operation to get the state of several pixels, the chip will continue to output bytes of data to you as long as the CS stays asserted.  So my code currently manually controls the CS pin.   I do this by initializing the CS pin to gpio after the spi init call completes.  This does all of the stuff needed to switch that pin back to GPIO mode (mode0) instead of being in SPI mode (mode1).   Note: in my case I have a second GPIO pin that is used by the chip to know if the bytes are to be used as data or to be used as commands....

                     

                    good luck

                    • 7. Re: Question about Write/Read SPI functions for Edison (Mraa)
                      danny7yoo

                      Thanks Kurt for the detailed response.

                       

                      I have a better understanding of SPI now. However, if transfer_buf and write_buf are essentially the same except the read buffer(memory), I don't understand why I would get a different reading.

                       

                      e.g.

                      Writing System_Reset 0x56 + 0x0 + 0x26 + 0x0

                      RECEIVED 0x0 + 0x0 + 0x0 + 0x0 + 0x0

                      Transfering System_Reset 0x56 + 0x0 + 0x26 + 0x0

                      RECEIVED 0x85 + 0xC0 + 0x74 + 0x2A + 0x8B

                       

                      I am not sure if I am even sending the intended command to MOSI properly, so i'll have to wait until Monday to get access to a logic analyzer at school.


                      Regarding CS pin(10), do you have a sample code as an example to show me how to get the CS pin to GPIO instead of SPI after initialization?

                       

                      -Danny

                      • 8. Re: Question about Write/Read SPI functions for Edison (Mraa)
                        KurtE

                        In your above program I am surprised that the Transfer is working and not faulting... That is: if you look at the code:

                          uint8_t *rxbuf;
                            mraa_spi_transfer_buf (spi, data, rxbuf, 4);
                            printf("Transfering System_Reset 0x%X + 0x%X + 0x%X + 0x%X\n", data[0], data[1], data[2], data[3]);
                            usleep(100000);
                            if (rxbuf == NULL)
                                printf("Errors encountered when transfering to camera\n");
                            else
                                printf("RECEIVED 0x%X + 0x%X + 0x%X + 0x%X + 0x%X\n",rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3], rxbuf[4]);
                        

                        You see that you are passing rxbuf, to transfer which is simply a pointer so hopefully initialized to something valid or could easily fault, if 0, it would be passing NULL pointer and no data would be

                        returned.

                        in this case you should probably do uint8_t rxbuf[5];

                        to have an actual buffer available to read and write data to.

                         

                        Forgot to look to see if on your write buffer case, if you free the memory back up or not.  Not a main issue for short run test apps, but if part of a program that does lots of stuff can cause crashes at different times.

                         

                        As for examples: I have the actual ILI9341 driver using it that is part of my Raspberry Pi project.  This is a version of the code that builds directly under linux.

                        It is up on github.com under kurte/Raspberry_Pi.  It is in the ILI9341... directory.  Note: Soon I will be pushing up a similar version of this code as part of my Eclipse Workspace for doing work for my PhantomX Hexapod, also has some test apps and the like.

                         

                        Kurt

                        • 9. Re: Question about Write/Read SPI functions for Edison (Mraa)
                          danny7yoo

                          Hey Kurt,

                           

                          When the mraa_spi_transfer_buf() is called, is the 'data' being sent through the MOSI line and then the return value from MISO is saved in the rxbuf?

                           

                          2015-01-05 17.47.20.jpg

                          I'm a little confused because it looks like the data is being sent through MISO instead.

                           

                          D3 = pin 13 (CLK)

                          D2 = pin 12 (MOSI)

                          D1 = pin 11 (MISO)

                          D0 = pin 10 (Signal select)


                          Transfering System_Reset 0x56 + 0x0 + 0x26 + 0x0   (So this is MISO?)

                          RECEIVED 0x0 + 0x0 + 0x0 + 0x0 + 0x0 (So this is MOSI?)



                          Thanks,

                          Danny


                          • 10. Re: Question about Write/Read SPI functions for Edison (Mraa)
                            KurtE

                            Hi, yes transfer works for me.

                             

                            For example from some of my code to talk to the Adafruit display, I have code that copies lines of data from one part of the display to another part as part of a scroll operation.  something like:

                            
                            
                            
                            
                            for (int y=(_y+CHAR_HEIGHT+1); y < (_y+_h-2); y++) {
                            
                            
                               
                             tft.readRect(_x+1, y, _w-2, 1, awColors);  // try to read one row at a time...
                            
                            
                               
                             tft.writeRect(_x+1, y-CHAR_HEIGHT, _w-2, 1, awColors);  // try to read one row at a time...
                            
                            
                            
                                }
                            
                            
                            

                            Where the tft.readRect is implemented:

                            oid Adafruit_ILI9341::readRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t *pcolors) 
                            {
                                uint16_t c = w * h;
                                spi_begin();
                            
                                setAddr(x, y, x+w-1, y+h-1);
                                writecommand_cont(ILI9341_RAMRD); // read from RAM
                                DCHigh();  // make sure we are in data mode
                            
                                uint8_t txdata[X86_BUFFSIZE * 3];   // how many to read at a time
                                memset(txdata, 0, X86_BUFFSIZE * 3);
                            
                                uint8_t rxdata[X86_BUFFSIZE * 3];   // how many to read at a time
                                   rxdata [0]= spiread();            // Read a DUMMY byte of GRAM
                            
                            
                                while (c){
                                    uint16_t cRead = min (c, X86_BUFFSIZE);
                                    mraa_spi_transfer_buf(SPI, txdata, rxdata, cRead * 3);
                                    for (uint16_t i=0; i < cRead*3; i+=3) {
                                        *pcolors++ = color565(rxdata[i], rxdata[i+1], rxdata[i+2]);
                                    }
                                    c -= cRead;
                                }
                               CSHigh();
                               spi_end();
                            }
                            

                            This code could probably be cleaned up some, but shows how I am reading data back from the display.  I init the TX buffer to be all zeros to send.  Wish I could pass NULL pointer for TX buffer in spidev, when I don't care about send, but that faults...

                            • 11. Re: Question about Write/Read SPI functions for Edison (Mraa)
                              CMata_Intel

                              Hi danny7yoo

                               

                              Do you have any updates in this? Are you still having questions about this?

                               

                              Regards;

                              CMata

                              • 12. Re: Question about Write/Read SPI functions for Edison (Mraa)
                                danny7yoo

                                Hi CMata,

                                 

                                Sorry for the delayed reply.

                                I gave up on SPI camera for my project. I am looking to use a USB camera instead, using the UVC interface.

                                I gave up on SPI not because of the Edison but due to such poor documentation of SPI camera in general. The datasheet is so incomplete and poorly written for most SPI cameras out there.

                                 

                                Regards,

                                Danny

                                • 13. Re: Question about Write/Read SPI functions for Edison (Mraa)
                                  xblades

                                  Hi Kurt,

                                  i wanted to use CS0 and CS1 as separate Chip-selects as you seem to do.

                                  In my case, i initialized the CS as GPIO after spi_init, but it seems,that CS1 is connected to SPI.

                                  How can i switch back to GPIO mode (sample code ?) ?

                                  I can use CS0 as separate Chip-select, but not CS1. I guess CS0 is never switched to SPI-mode, CS1 always.

                                   

                                  Regards,

                                  Stefan Verse

                                  • 14. Re: Question about Write/Read SPI functions for Edison (Mraa)
                                    KurtE

                                    I am not sure how you have things set up.  I only created one SPI object and use it for both logical devices.  So I never did anything to let system know about CS1...  So I simply manually set the IO state of which CS (likewise DC) pin to what I need before and after calls to SPI.transfer.   So again I am not sure how you currently have yours set up.

                                     

                                    Kurt

                                    1 2 Previous Next