5 Replies Latest reply on Mar 1, 2015 9:16 AM by egorf

    How to use libmraa's memory map GPIO functionality correctly?

    egorf

      I want to use libmraa in my project, which deals with GPIO. For me, GPIO interaction speed is very important and using sysfs to interact with GPIO is not an option.

      This is the example, meant to show how  to use mmap part of libmraa:

      int main(int argc, char **argv)
      {
      //! [Interesting]
          fprintf(stdout, "hello mraa\n Version: %s\n", mraa_get_version());
          mraa_gpio_context gpio;
          gpio = mraa_gpio_init(2);
      
          mraa_gpio_use_mmaped(gpio, 1);
      
          for (;;) {
              mraa_gpio_write(gpio , 1);
              usleep(50000);
              mraa_gpio_write(gpio, 0);
              usleep(50000);
          }
      }
      
      

       

      Now, what is the correct way to read GPIO values using memory mapping? I've looked through the code for Edison but it doesn't have a function for changing GPIO direction.

      It only offers following functions to setup mmap io, unsetup it, write and read. Do i have to change direction of GPIO beforehand?
      Where can I get more info about using this part of the library and Edison's reg map?

        • 1. Re: How to use libmraa's memory map GPIO functionality correctly?
          Intel_Alvarado

          Hi egorf,

           

          The correct way to read GPIO values in memory should be using the read commands found on mraa documentation http://iotdk.intel.com/docs/master/mraa/classmraa_1_1_aio.html . You can use all of the available functions in the mraa library. To change direction you can check http://iotdk.intel.com/docs/master/mraa/classmraa_1_1_gpio.html . If it should be changed beforehand depends on the library itself, in some cases such as SPI it comes already with a predefined direction but other cases such as UART you have to change it manually. Regarding the Edison’s region map we are continuously working on improving documentation, right now there isn’t a specific document with the Edison’s mapping of registers.

           

          Regards

          Sergio

          • 2. Re: How to use libmraa's memory map GPIO functionality correctly?
            arfoll

            Once you use mmap'd IO you stop using the generic sysfs functions defined in src/gpio/gpio.c and move to the 'advance' functions form the platform config file - https://github.com/intel-iot-devkit/mraa/blob/master/src/x86/intel_edison_fab_c.c#L586 Howeve for direction changes there is no way to do that from mmap'd access so this is slower, still we cache the gpios so it should be relatively fast - mraa/intel_edison_fab_c.c at master · intel-iot-devkit/mraa · GitHub.  Anyways once you have you gpio context just call mraa_gpio_dir() and that will change the direction as fast as we know how for your platform (and if you know better we're interested!)

             

            You're right we dont have any mmap'd access to read gpios, I'll look into what we can do for that, honestly we haven't had too much interest that way round, people typically use interupts when they want fast gpio responses rather than poll them. Please do rememeber, this is linux non realtime userspace. So your timings are 'best efforts'

            • 3. Re: How to use libmraa's memory map GPIO functionality correctly?
              egorf

              Thank you for the elaborate answer. I am using mmap'd access to emulate SWD interface, so speed is indeed one of the concerns. I wish I could use GPIOs like I do on Raspberry Pi:

              RPi Low-level peripherals - eLinux.org

              As Intel_Alvarado said, there is no open register map for edison yet, so I don't think I can do much.

              • 4. Re: How to use libmraa's memory map GPIO functionality correctly?
                KurtE

                There are multiple things involved here. 

                 

                If you simply wish for an IO pin to have it's reads or writes down through memory mapped access that is there, both in the MRAA library as well as with Arduino. To set a pin with GPIO into input mode simply call: mraa_gpio_dir with MRAA_GPIO_IN  if use memory mapped is on, it will use it.  The memory map for the IO pins associated with the Edison module have 4 operations (set, clear, read), not sure yet what the 4th is.  I wondered if toggle, but did not work in my test.

                 

                But, if you wish to quickly switch a pin from input to output (or back),  As far as I can tell, there is no memory mapped access to set the direction, so that goes through FS.  I added caching of values to try to speed that up.  There are a few different threads talking about this including: Fast GPIO Arduino board to logical IO pins on Breakout board? and https://communities.intel.com/message/267710?tstart=0#267710

                 

                Now if you are using the Arduino breakout board, it gets even worse as all of the physical IO pins have several parts associated with them.  That is for example to switch Arduino pin 2 from input to output, you have to set several object:

                Set tristate

                Set level shifter direction

                Set PU/PD state

                Set our actual object direction

                clear tristate

                 

                Except for setting the actual edison object state, all of the other objects are done through FS calls, which in turn do I2C communications to stuff on the Arduino board and there are no short cuts that I have found, except cache the state, so for example if PU state is same, don't go through that part of code.

                 

                Hopefully you can find something I missed.

                • 5. Re: How to use libmraa's memory map GPIO functionality correctly?
                  egorf

                  Hello KurtE!

                   

                  After some testing, I came up with the solution you mentioned: I use mraa_gpio_use_mmaped and then just simply use mraa_gpio_dir when it's time to change direction, even though it does not get changed to a new function, it might slow things down, but the speed still seems to be good enough to work with SWD interface.

                   

                  Btw, I am not using an Arduino breakout, so I am feeling a little bit lucky now that you've mentioned the process

                   

                  Thanks everybody!