• In recent project I used Espruino itself to run test regression. Espruino pins drive devices under test with analog and digital signals: voltages, low and high pulses, low and high states, etc.

    After reset, all free ports / pins are input - very high impedance and the pin output latch registers are set to low. This makes the read of a connected test candidate pin on input mode with a very weak pull-up to deliver high value. Espruino has though this specialty that makes lazy programming easy: On reset, pin mode is not just set straight to "input" mode, but to "auto" mode. In mode, the pin will adjust to the automatically applied operation: on pin.read() the pin switches to input mode behavior, and on pin.write() the pin switches to output mode behavior. The pin input/output control register are set automatically. No need for the application to configure the pin when plain input and plain output are sufficient.

    For a test setup, assume the Espruino pin A0 is the test pin (test driver) for the tested pin x2 of Espruino itself or of a device connected to and controlled by Espruino. A0 is initially in input mode - no pull-up or pull-down - and the tested x2 pin is in input (very weak) pull-up mode. A read by the x1 pin will deliver a High / true.

    When the tested pin x1 is NOT under watch / is NOT on interrupt, changing the testing pin A0 from input to output H in order to keep continuously High / true on texted pin x1 is not a challenge, since the switching falls between two test reads. The code for switching looks like this:

    A0.mode("output"); // switching test pin to output mode
    A0.set();          // set A0 High to keep x1 input on High
    

    When the tested pin x1 is under watch / is on interrupt, the watch / event fire because there is a very brief period between switching to output mode and asserting High where the still set to Low pin latch / output register pulls the test pin A0 AND the tested pin x1 low.

    The hope that using Espruino's unique "auto" pin mode feature could help got quickly dashed: applying a pin.set() H 'immediately' after a reset shows the same issue: the reset latch / output register is briefly exposed when the pin switches automatically from input to output - in fact is connecting the pin with the output register just before setting it to high... :(

    // reset, A0.mode("auto") or A0.mode() followed by A0.read();
    A0.set(); // switch from "input" "auto" to output and H
    

    Therefore, the following sequence has to be use to keep the A0 test pin AND x1 tested pin 'seamlessly' high:

    A0.mode("input"); // or "input_pullup" - lets A0 and x1 pin stay on High
    A0.set(); // latches / sets output reg to H, but w/ no effect on pin A0 (yet)
    A0.mode("output"); // exposes output reg's H (w/ 'going with the flow')
    

    In other words, to put a pin on input, then re/set the pin's latch /output register as desired and finally put the pin in output mode prevents exposing an undesired previous value and possible generation of a watch / interrupt spike.

  • Thanks - actually that's something that might be easy enough to fix: https://github.com/espruino/Espruino/blob/master/src/jspin.c#L218

    However how big is the spike you're noticing when using Espruno's .set on its own? It should be really very small - significantly less than a microsecond?

  • The spike is long enough for a hardware device watching, such as a MCP23017 Portexpander pin, to trigger interrupt operation. Did not (self) test on a watched Espruino-Wifi pin.

  • It should be fixed in latest builds now

  • Excellent!

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Spike free switching of pin mode from input to output

Posted by Avatar for allObjects @allObjects

Actions