Skip to content

Commit

Permalink
Merge pull request #447 from UncleGrumpy/stm32_gpio
Browse files Browse the repository at this point in the history
Update stm32 gpio driver

Restores functionality to the stm32 gpio driver by updating mailbox message
parsing to match updates to the the erlang and elixir drivers. Modifies the
`pin() type` in both versions of the gpio driver to accommodate tuples used in
the stm32 port.

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 May 23, 2023
2 parents d35a000 + a52f1be commit a557047
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 9 deletions.
5 changes: 4 additions & 1 deletion libs/eavmlib/src/gpio.erl
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
%%
%% This module provides functions for interacting with micro-controller GPIO
%% (General Purpose Input and Output) pins.
%%
%% Note: `-type pin()' used in this driver refers to a pin number on Espressif
%% chips, or a tuple {GPIO_GROUP, PIN} for stm32 chips.
%% @end
%%-----------------------------------------------------------------------------
-module(gpio).
Expand All @@ -62,7 +65,7 @@
]).

-type gpio() :: pid().
-type pin() :: non_neg_integer().
-type pin() :: non_neg_integer() | {atom(), non_neg_integer()}.
-type direction() :: input | output | output_od.
-type pull() :: up | down | up_down | floating.
-type low_level() :: low | 0.
Expand Down
4 changes: 3 additions & 1 deletion libs/exavmlib/lib/GPIO.ex
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ defmodule GPIO do
Valid GPIO pin number.
The actual number of pins that are broken out vary by board and module.
For espressif chips this a the pin number marked on the board or data sheet.
For stm32 chips this is a tuple {GPIO_GROUP, PIN_NUMBER}.
"""
@type gpio_pin() :: non_neg_integer()
@type gpio_pin() :: non_neg_integer() | {atom(), non_neg_integer()}

@typedoc """
Event type describing the voltage that will trigger an interrupt.
Expand Down
33 changes: 26 additions & 7 deletions src/platforms/stm32/src/lib/gpiodriver.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#include <mailbox.h>
#include <term.h>

// Uncomment to enable trace
//#define ENABLE_TRACE 1
#include <trace.h>

#include "platform_defaultatoms.h"
Expand All @@ -36,6 +38,15 @@ static uint32_t port_atom_to_gpio_port(Context *ctx, term port_atom);
static uint16_t gpio_port_to_rcc_port(uint32_t gpio_port);
static char gpio_port_to_name(uint32_t gpio_port);

static term create_pair(Context *ctx, term term1, term term2)
{
term ret = term_alloc_tuple(2, ctx);
term_put_tuple_element(ret, 0, term1);
term_put_tuple_element(ret, 1, term2);

return ret;
}

void gpiodriver_init(Context *ctx)
{
ctx->native_handler = consume_gpio_mailbox;
Expand All @@ -49,17 +60,18 @@ static void consume_gpio_mailbox(Context *ctx)
Message *message = mailbox_dequeue(ctx);
term msg = message->message;
term pid = term_get_tuple_element(msg, 0);
term cmd = term_get_tuple_element(msg, 1);
term req = term_get_tuple_element(msg, 2);
term cmd = term_get_tuple_element(req, 0);

int local_process_id = term_to_local_process_id(pid);
Context *target = globalcontext_get_process(ctx->global, local_process_id);

if (cmd == SET_LEVEL_ATOM) {
term gpio_tuple = term_get_tuple_element(msg, 2);
term gpio_tuple = term_get_tuple_element(req, 1);
term gpio_port_atom = term_get_tuple_element(gpio_tuple, 0);
uint32_t gpio_port = port_atom_to_gpio_port(ctx, gpio_port_atom);
int32_t gpio_pin_num = term_to_int32(term_get_tuple_element(gpio_tuple, 1));
int32_t level = term_to_int32(term_get_tuple_element(msg, 3));
int32_t level = term_to_int32(term_get_tuple_element(req, 2));

if (level != 0) {
gpio_set(gpio_port, 1 << gpio_pin_num);
Expand All @@ -70,11 +82,11 @@ static void consume_gpio_mailbox(Context *ctx)
ret = OK_ATOM;

} else if (cmd == SET_DIRECTION_ATOM) {
term gpio_tuple = term_get_tuple_element(msg, 2);
term gpio_tuple = term_get_tuple_element(req, 1);
term gpio_port_atom = term_get_tuple_element(gpio_tuple, 0);
uint32_t gpio_port = port_atom_to_gpio_port(ctx, gpio_port_atom);
int32_t gpio_pin_num = term_to_int32(term_get_tuple_element(gpio_tuple, 1));
term direction = term_get_tuple_element(msg, 3);
term direction = term_get_tuple_element(req, 2);

uint16_t rcc_port = gpio_port_to_rcc_port(gpio_port);
// Set direction implicitly enables the port of the GPIO
Expand All @@ -100,9 +112,16 @@ static void consume_gpio_mailbox(Context *ctx)
ret = ERROR_ATOM;
}

free(message);
term ret_msg;
if (UNLIKELY(memory_ensure_free(ctx, 3) != MEMORY_GC_OK)) {
ret_msg = OUT_OF_MEMORY_ATOM;
} else {
term ref = term_get_tuple_element(msg, 1);
ret_msg = create_pair(ctx, ref, ret);
}

mailbox_send(target, ret);
mailbox_send(target, ret_msg);
mailbox_destroy_message(message);
}

static uint32_t port_atom_to_gpio_port(Context *ctx, term port_atom)
Expand Down

0 comments on commit a557047

Please sign in to comment.