Skip to content

machine.Pin: Implement Pin.toggle() for three ports. - #16607

Merged
dpgeorge merged 4 commits into
micropython:masterfrom
robert-hh:esp32_pin_toggle
Feb 28, 2025
Merged

dpgeorge merged 4 commits into
micropython:masterfrom
robert-hh:esp32_pin_toggle

Conversation

@robert-hh

@robert-hh robert-hh commented Jan 18, 2025 •

Copy link
Copy Markdown
Contributor

Summary

The ESP32, ESP8266 and CC3200 ports did not provide the method Pin.toggle(). This PR adds it.

Testing

Tested with:

  • ESP32
  • ESP32C3
  • ESP32C6
  • ESP32S2
  • ESP32S3
  • ESP8266
  • WiPY 1 (CC3200)

@mattytrentini mattytrentini left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (we should check toggle exists for all other ports too...)

@robert-hh

Copy link
Copy Markdown
Contributor Author

grep -r QSTR_toggle * at the current master returns:

mimxrt/machine_pin.c:    { MP_ROM_QSTR(MP_QSTR_toggle),  MP_ROM_PTR(&machine_pin_toggle_obj) },
mimxrt/machine_led.c:    {MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&led_obj_toggle_obj)},
nrf/modules/board/led.c:    { MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&led_obj_toggle_obj) },
pic16bit/modpybled.c:    { MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&pyb_led_toggle_obj) },
renesas-ra/led.c:    { MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&led_obj_toggle_obj) },
rp2/machine_pin.c:    { MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&machine_pin_toggle_obj) },
samd/machine_pin.c:    { MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&machine_pin_toggle_obj) },
stm32/led.c:    { MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&led_obj_toggle_obj) },

So ports with a machine module missing Pin.toggle() are:

  • esp32 (done with this PR)
  • esp8266
  • cc3200
  • zephyr

I can try to implement it for ESP8266 and CC3200, even it it may be waste of time for the latter. I have no hardware with Zephyr loaded, and I never dealt with Zephyr. And it depends a lot from the way, the functions gpio_pin_get_raw() and gpio_pin_set_raw() are implemented and the pins are initialized for the respective hardware. So even if a Pin.toggle() was implemented using these two functions, it may not work.

@robert-hh

Copy link
Copy Markdown
Contributor Author

Pin.toggle() is added for ESP8266 and CC3200 as well.

@robert-hh robert-hh changed the title esp32/machine_pin.c: Implement Pin.toggle(). machine.Pin: Implement Pin.toggle() for three ports. Jan 19, 2025
@mattytrentini

Copy link
Copy Markdown
Contributor

Fantastic work @robert-hh!

@Josverl

Josverl commented Jan 22, 2025

Copy link
Copy Markdown
Contributor

Then perhaps it's good to update the docs on this as well

Availability: mimxrt, samd, rp2 ports.

@robert-hh

Copy link
Copy Markdown
Contributor Author

That's right

@dpgeorge

Copy link
Copy Markdown
Member

Note that the stm32 port does not have Pin.toggle() (only LED.toggle()).

But in general it's not easy to implement this function. To make it work correctly you must be able to read the current output state of the pin, not the input state.

For the three ports that you implemented toggle() for, does it work correctly and invert the state of the output pin regardless of the voltage level on the pin?

@robert-hh

robert-hh commented Feb 25, 2025 •

Copy link
Copy Markdown
Contributor Author

When the Pin was set to OUT mode, the state of the Pin was inverted properly independent of the initial state. When set to OPEN_DRAIN mode, the ESP32 works fine. The ESP8266 toggles once from the initial value of 0 to 1, the CC3200 does not support OPEN_DRAIN. All if the Pin could change it's level and was not hard wired to GND or Vcc. But then it would anyhow not toggle.

I did not check in detail whether the level is read back from the pad or the driver. I would assume it is reading the pad value, since the function used for the Pin input value is used.
Obviously Pin.toggle() can be implemented by storing the set level of the Pin at the object, making it independent of whether the level is read back from the pad or the driver.

Edit: Checking the implementation for mimxrt and samd: there the output driver itself supports toggling, which is used by the code. I have to check whether is is supported by the ESP32 hardware. The API does not seem to support it. But it can be done by reading back the output register. Same for ESP8266,

@dpgeorge

Copy link
Copy Markdown
Member

Checking the implementation for mimxrt and samd: there the output driver itself supports toggling, which is used by the code.

OK, thanks for checking. I think we should only implement Pin.toggle() for ports that can do it properly like this.

I have to check whether is is supported by the ESP32 hardware.

Please do. And if we need to do raw register access to read back the current state, I think that's what we should do.

@robert-hh

Copy link
Copy Markdown
Contributor Author

Please do. And if we need to do raw register access to read back the current state, I think that's what we should do.

Done. ESP32 and ESP8266 use the output register value, while the CC3200 port already stored the actual set output value at the pin object. So that could be used.

@robert-hh
robert-hh force-pushed the esp32_pin_toggle branch 2 times, most recently from da04166 to a4cdfbf Compare February 25, 2025 16:06
Comment thread docs/library/machine.Pin.rst Outdated
Comment thread ports/esp32/mphalport.h Outdated
Comment thread ports/esp32/mphalport.h Outdated
Comment thread ports/esp8266/esp_mphal.h Outdated
Comment thread ports/esp8266/esp_mphal.h Outdated
@robert-hh

Copy link
Copy Markdown
Contributor Author

All suggested comments implemented & tested. For ESP32 I tested the ESP32_GENERIC and ESP32_GENERIC_C3 board to cover all changed code.

Comment thread ports/esp32/mphalport.h Outdated
The actual output pin value is taken from the OUT register, not from the
pad.

Tested with:
- ESP32   low and high Pin numbers
- ESP32C3 low Pin numbers
- ESP32C6 low Pin numbers
- ESP32S2 low and high Pin numbers
- ESP32S3 low and high Pin numbers

Signed-off-by: robert-hh <[email protected]>
Tested with a generic ESP8266 device.  The actual output value is taken
from the output register, not by reading the pad level.

Signed-off-by: robert-hh <[email protected]>
Tested with a WiPy 1 board.

Signed-off-by: robert-hh <[email protected]>
@dpgeorge
dpgeorge merged commit 48925fd into micropython:master Feb 28, 2025
@robert-hh

Copy link
Copy Markdown
Contributor Author

Thank you.

@robert-hh
robert-hh deleted the esp32_pin_toggle branch February 28, 2025 11:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants