nodemcu / nodemcu-firmware

Lua based interactive firmware for ESP8266, ESP8285 and ESP32
https://nodemcu.readthedocs.io
MIT License
7.66k stars 3.12k forks source link

Improving GPIO toggling speed #177

Closed raz123 closed 9 years ago

raz123 commented 9 years ago

I have ran a few test to see how fast one could toggle the GPIO line in LUA and here are my results:

nodemcu (CPU @ 80 Mhz): ~10 Khz nodemcu (CPU @ 160 Mhz): ~20 Khz nodelua (CPU @ 80 Mhz): ~44 Khz

Is there a good reason for which nodemcu is 4x slower than its counterpart? Do you think it would be possible to improve the performance of the GPIO handling in nodemcu?

dvv commented 9 years ago

code?

raz123 commented 9 years ago

The code to toggle the GPIO line was simply:

gpio.mode(2, gpio.OUTPUT)

for i = 1,10 do

gpio.write(2, 1)
gpio.write(2, 0)

end

nodemcu's gpio code to write to a pin is the following:

static int lgpio_write( lua_State* L )
{
  unsigned level;
  unsigned pin;

  pin = luaL_checkinteger( L, 1 );
  MOD_CHECK_ID( gpio, pin );
  level = luaL_checkinteger( L, 2 );
  if ( level!=HIGH && level!=LOW )
    return luaL_error( L, "wrong arg type" );
  platform_gpio_write(pin, level);
  return 0;  
}

nodelua's gpio code to write to a pin is the following:

static int ICACHE_FLASH_ATTR lnode_gpio_write (lua_State *L)
{
    int pin = luaL_checkinteger(L, 1);
    int val = luaL_checkinteger(L, 2);
    if (check_pin(pin))
    {
        GPIO_OUTPUT_SET(GPIO_ID_PIN(pin), val);
    }
    else
    {
        return luaL_error(L, "invalid pin");
    }
    return 0;
}

After reviewing both codes, I feel like there is definitely space for a speed-optimized gpio module, which could have hardcoded/fixed pin values. Nodemcu's poor GPIO performance might also have to do with other interrupts firing, which I have not yet reviewed.

dvv commented 9 years ago

I squeezed circa 60kHz of it. The clue is the same that I keep telling here: always do local-ize global variables:

do
  local mode, write, OUTPUT = gpio.mode, gpio.write, gpio.OUTPUT
  mode(2, OUTPUT)
  for i = 1,10 do
    write(2, 1)
    write(2, 0)
  end
end

Mind to retry and post the results of this code? TIA

raz123 commented 9 years ago

dvv, woah, that is quite interesting! Here are my results, using your code:

~52 kHz on the nodelua 20150120 firmware (gpio pin = 4) ~51 kHz on the nodemcu 20150127 firmware (gpio pin = 4) ~63 kHz on the jrahlf 20150127 fork (gpio pin = 2)

Thanks for the tip!

dvv commented 9 years ago

yw

raz123 commented 9 years ago

Just landed on this document that discusses optimizing Lua code. Will leave it here for those who happen to stumble on this thread: http://www.lua.org/gems/sample.pdf

dvv commented 9 years ago

Yup. Though this one imo should be linked to the main project's page ) Lua's very simple yet has some known surprises everyone should know.

urmilparikh commented 9 years ago

Very helpful tip, @dvv, Thanks!

TerryE commented 9 years ago

It's in my unofficial FAQ, but note that these are nearly all optimisation for time rather than space. You typically need the latter on the esp8266.

@raz123, if you don't mind, I'll close this issue because this issue isn't one that we'll try to address by firmware changes. It's more to do with coding techniques that can be discussed on one off the applications developer forums.