4 Replies Latest reply on Jan 14, 2015 8:22 AM by KurtE

    Multiple objects/threads/Interrupts - Using SPI at the same time


      I am playing around with my little App that uses my Adafruit 2.8" TFT shield as adisplay console. I will launch this app when I power up my Edison that is mounted on a robot, that will display things like Battery voltage.  In addition I have touch buttons, that when I press one, it launches my Phoenix code base, when I press a different one it does a "Shutdown Now" command.


      I ran into issue where the stuff I am trying to output to the TFT display was getting corrupted and other stuff stops working. So have simple app that keeps adding a line every two seconds and it is working. May refine a little the displaying, but...


      Then figured out what that issue is. I created a secondary thread to wait on the pipe and when it receives data it then writes it to the display (SPI). Meanwhile the main thread is looking for user input from the touch screen (SPI), and the two spi communications collide.


      Trying to decide which way I want to fix it.

      a) Set up my own mutex or semaphore or like object which each of these threads explicitly sets/clears when doing these operations. Probably the quickest way to fix it. Although this may require me to do stuff in several different places.


      b) Have my 2ndary thread put the messages into a queue that the primary thread, looks at from time to time and then it does the write to the main screen. sort of defeats the secondary thread.


      c) See about adding the SPI begin/end transaction work that is going into the more recent Arduino IDEs and I know that is done for the Teensy. Internally it probably does the same as a)...   There are several threads about this up on the Teensy forums, with lots of pros and cons about the solution, but the main idea is that several libraries have been updated like the Adafruit ILI9341 library, STMPE610 library SDCARD... where updated, that many of the APIs have built into them, Calls like begin Transaction/end transaction.  These calls try to make sure you don't end up with multiple partial conversations at same time.  Especially when some of these may run at different speeds...


      The good news is at least I think I know what this issue is.  Now trying to decide what I should do for now with my Edison code.




        • 1. Re: Multiple objects/threads/Interrupts - Using SPI at the same time

          Hi KurtE


          According to what I understand of your post, if you are using a single SPI for 2 threads in my opinion the best way would be to use semaphore process, due to the way the SPI work. As far as I understand you have to read data before trying to send data again, so cleaning the bus at the end of a process would work. If this is not the case, could you specify what you have connect besides the TFT screen and the board, and which processes are on which bus?



          • 2. Re: Multiple objects/threads/Interrupts - Using SPI at the same time

            Yes as far as my current issue with SPI, I am updating my version of the ILI9341 and the STMPE 610 driver to have each time they wish to set the appropriate CS pin (10 for the ILI9341 and 8 for the STMPE), I grab a common mutex, such that hopefully only one of them be active at any one time.


            This will hopefully fix it for this case.


            However was wondering if some approach will be taken both in the Arduino IDE (spi library) as well as maybe MRAA. 


            Obviously it would be great if the Kernel did it for us.  On a limited side it can as the spidev library does normally try to set/clear the CS pin.  But there is only one CS pin that it works with (I believe hardware supports 2).  So that part would not work.  Also the current implementation of spidev is not working sufficiently as it appears like it will always set/clear for each call, regardless if you want it to or not.  I believe there is a flag as part of the IOCTL that is supposed to let you specify this.  Without this control somethings won't work.  Example reading back from the ILI9341, works to continue to give you data as long as you keep the CS asserted.


            Maybe SPIDEV could be enhanced to make this part work.  Also maybe it could be updated somehow to also allow GPIO pins to be used as CS pins within the driver.  Not sure, just a thought.


            Note: even with my possible changes it still won't address potential issues with also using device drivers on the same SPI bus, and not sure if/when intel supports DMA, how that would influence this.


            Hope that makes sense.


            • 3. Re: Multiple objects/threads/Interrupts - Using SPI at the same time

              Hi KurtE,


              Have you already tried the semaphore method in your project yet? Did it help on the SPI communication?



              • 4. Re: Multiple objects/threads/Interrupts - Using SPI at the same time

                Thanks, it is helping to keep some stuff straight.


                Luckily most of this code I started off playing with on the Teensy 3.1, where Paul of PJRC worked with others on the Arduino Developers list and implemented a transaction model, which was integrated into the current Teensy releases.  It has also been integrated into Arduino Beta 1.5.8.  I am also pretty sure that Paul was able to get this transaction stuff pulled back into the official Adafruit libraries up on github as well.


                These libraries had stubs in them to call the begin/end transaction, where I simply put in simple calls to pthread_mutex...   Currently this code is only in my Eclipse workspace code project:



                This still does not solve everything.  Example: I display a button on the screen in one thread, but want to display text in listbox in another.  All of their graphic primitives get a complete valid SPI output, but: for example the one thread may set the text point and before it outputs it's text, other thread draws some of the button text there.... So still may need higher level mutex to say I am doing stuff now...


                I hope to have this Repository have enough stuff in it, such that I can simply git it on another machine, tell Eclipse to make it my current workspace and build.  But I did not want all of the unnecessary stuff like caches so currently I exclude the .metadata  and so workspace does not work... Will relax this soon and see.  But that is a different thread.