diff --git a/src/platforms/rp2040/src/lib/gpiodriver.c b/src/platforms/rp2040/src/lib/gpiodriver.c index 2462a12a1..9bd059c16 100644 --- a/src/platforms/rp2040/src/lib/gpiodriver.c +++ b/src/platforms/rp2040/src/lib/gpiodriver.c @@ -30,6 +30,10 @@ #include "rp2040_sys.h" #include "trace.h" +#define INVALID_MODE_ATOM globalcontext_make_atom(ctx->global, ATOM_STR("\xC", "invalid_mode")) +#define INVALID_LEVEL_ATOM globalcontext_make_atom(ctx->global, ATOM_STR("\xD", "invalid_level")) +#define INVALID_PIN_ATOM globalcontext_make_atom(ctx->global, ATOM_STR("\xB", "invalid_pin")) + static const struct Nif *gpio_nif_get_nif(const char *nifname); static const AtomStringIntPair pin_mode_table[] = { @@ -105,7 +109,11 @@ static term nif_gpio_set_pin_mode(Context *ctx, int argc, term argv[]) int gpio_num = term_to_int(argv[0]); int mode = interop_atom_term_select_int(pin_mode_table, argv[1], ctx->global); if (UNLIKELY(mode < 0)) { - return ERROR_ATOM; + BEGIN_WITH_STACK_HEAP(TUPLE_SIZE(2), heap); + term ret = term_alloc_tuple(2, &heap); + term_put_tuple_element(ret, 0, ERROR_ATOM); + term_put_tuple_element(ret, 1, INVALID_MODE_ATOM); + return ret; } gpio_set_dir(gpio_num, mode); return OK_ATOM; @@ -133,12 +141,20 @@ static term nif_gpio_digital_write(Context *ctx, int argc, term argv[]) if (term_is_integer(level_term)) { level = term_to_int32(level_term); if (UNLIKELY((level != 0) && (level != 1))) { - return ERROR_ATOM; + BEGIN_WITH_STACK_HEAP(TUPLE_SIZE(2), heap); + term ret = term_alloc_tuple(2, &heap); + term_put_tuple_element(ret, 0, ERROR_ATOM); + term_put_tuple_element(ret, 1, INVALID_LEVEL_ATOM); + return ret; } } else { level = interop_atom_term_select_int(pin_level_table, level_term, ctx->global); if (UNLIKELY(level < 0)) { - return ERROR_ATOM; + BEGIN_WITH_STACK_HEAP(TUPLE_SIZE(2), heap); + term ret = term_alloc_tuple(2, &heap); + term_put_tuple_element(ret, 0, ERROR_ATOM); + term_put_tuple_element(ret, 1, INVALID_LEVEL_ATOM); + return ret; } } @@ -150,12 +166,20 @@ static term nif_gpio_digital_write(Context *ctx, int argc, term argv[]) } else if (term_is_atom(gpio_pin)) { gpio_num = interop_atom_term_select_int(wl_pin_table, gpio_pin, ctx->global); if (UNLIKELY((gpio_num == -1) || (gpio_num > 1))) { - return ERROR_ATOM; + BEGIN_WITH_STACK_HEAP(TUPLE_SIZE(2), heap); + term ret = term_alloc_tuple(2, &heap); + term_put_tuple_element(ret, 0, ERROR_ATOM); + term_put_tuple_element(ret, 1, INVALID_PIN_ATOM); + return ret; } cyw43_arch_gpio_put(gpio_num, level); #endif } else { - return ERROR_ATOM; + BEGIN_WITH_STACK_HEAP(TUPLE_SIZE(2), heap); + term ret = term_alloc_tuple(2, &heap); + term_put_tuple_element(ret, 0, ERROR_ATOM) + term_put_tuple_element(ret, 1, INVALID_PIN_ATOM); + return ret; } return OK_ATOM; @@ -176,12 +200,20 @@ static term nif_gpio_digital_read(Context *ctx, int argc, term argv[]) } else if (term_is_atom(gpio_pin)) { gpio_num = interop_atom_term_select_int(wl_pin_table, gpio_pin, ctx->global); if (UNLIKELY((gpio_num != 2))) { - return ERROR_ATOM; + BEGIN_WITH_STACK_HEAP(TUPLE_SIZE(2), heap); + term ret = term_alloc_tuple(2, &heap); + term_put_tuple_element(ret, 0, ERROR_ATOM); + term_put_tuple_element(ret, 1, INVALID_PIN_ATOM); + return ret; } level = cyw43_arch_gpio_get(gpio_num); #endif } else { - return ERROR_ATOM; + BEGIN_WITH_STACK_HEAP(TUPLE_SIZE(2), heap); + term ret = term_alloc_tuple(2, &heap); + term_put_tuple_element(ret, 0, ERROR_ATOM) + term_put_tuple_element(ret, 1, INVALID_PIN_ATOM); + return ret; } return level ? globalcontext_make_atom(ctx->global, ATOM_STR("\x4", "high")) : globalcontext_make_atom(ctx->global, ATOM_STR("\x3", "low"));