Skip to content

Commit

Permalink
Merge pull request #1234 from pguyot/w29/gpio-init-esp32
Browse files Browse the repository at this point in the history
Implement `gpio:init/1` on esp32

Some GPIO pins require initialization as gpio pins to work, for example GPIO 4
on ESP32C3. This is achieved by calling esp-idf `gpio_config`. Implement this
within `gpio:init/1` which is used on rp2040.

These changes are made under both the "Apache 2.0" and the "GNU Lesser General
Public License 2.1 or later" license terms (dual license).

SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
  • Loading branch information
bettio committed Jul 26, 2024
2 parents 3b6f36c + 855460c commit 1f06efc
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 1 deletion.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [0.6.4] - Unreleased

### Added

- Implement `gpio:init/1` on esp32 to initialize pins for GPIO usage, which some pins
require depending on default function and bootloader code

## [0.6.3] - 20-07-2024

### Added
Expand Down
2 changes: 1 addition & 1 deletion libs/eavmlib/src/gpio.erl
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ remove_int(GPIO, Pin) ->
%% @param Pin number to initialize
%% @returns ok
%% @doc Initialize a pin to be used as GPIO.
%% Currently only implemented (and required) for RP2040 (Pico).
%% This is required on RP2040 and for some pins on ESP32.
%% @end
%%-----------------------------------------------------------------------------
-spec init(Pin :: pin()) -> ok.
Expand Down
48 changes: 48 additions & 0 deletions src/platforms/esp32/components/avm_builtins/gpio_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -644,10 +644,43 @@ REGISTER_PORT_DRIVER(gpio, gpio_driver_init, NULL, gpio_driver_create_port)

#ifdef CONFIG_AVM_ENABLE_GPIO_NIFS

static term nif_gpio_init(Context *ctx, int argc, term argv[])
{
UNUSED(argc);

gpio_num_t gpio_num;
if (LIKELY(term_is_integer(argv[0]))) {
avm_int_t pin_int = term_to_int32(argv[0]);
if (UNLIKELY((pin_int < 0) || (pin_int >= GPIO_NUM_MAX))) {
RAISE_ERROR(BADARG_ATOM);
}
gpio_num = (gpio_num_t) pin_int;
} else {
RAISE_ERROR(BADARG_ATOM);
}

gpio_config_t config = {};
config.pin_bit_mask = 1 << gpio_num;
config.mode = GPIO_MODE_DISABLE;
config.pull_up_en = GPIO_PULLUP_DISABLE;
config.pull_down_en = GPIO_PULLDOWN_DISABLE;
config.intr_type = GPIO_INTR_DISABLE;

esp_err_t result = gpio_config(&config);

if (UNLIKELY(result != ESP_OK)) {
RAISE_ERROR(BADARG_ATOM);
}

return OK_ATOM;
}

/* TODO: in the case of {error, Return} we should RAISE_ERROR(Reason) */

static term nif_gpio_set_pin_mode(Context *ctx, int argc, term argv[])
{
UNUSED(argc);

return gpio_set_pin_mode(ctx, argv[0], argv[1]);
}

Expand Down Expand Up @@ -706,6 +739,12 @@ static term nif_gpio_digital_read(Context *ctx, int argc, term argv[])
return gpio_digital_read(argv[0]);
}

static const struct Nif gpio_init_nif =
{
.base.type = NIFFunctionType,
.nif_ptr = nif_gpio_init
};

static const struct Nif gpio_set_pin_mode_nif =
{
.base.type = NIFFunctionType,
Expand Down Expand Up @@ -757,6 +796,15 @@ static const struct Nif gpio_digital_read_nif = {

const struct Nif *gpio_nif_get_nif(const char *nifname)
{
if (strcmp("gpio:init/1", nifname) == 0) {
TRACE("Resolved platform nif %s ...\n", nifname);
return &gpio_init_nif;
}
if (strcmp("Elixir.GPIO:init/1", nifname) == 0) {
TRACE("Resolved platform nif %s ...\n", nifname);
return &gpio_init_nif;
}

if (strcmp("gpio:set_pin_mode/2", nifname) == 0) {
TRACE("Resolved platform nif %s ...\n", nifname);
return &gpio_set_pin_mode_nif;
Expand Down

0 comments on commit 1f06efc

Please sign in to comment.