Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 28 additions & 52 deletions libtock-sync/peripherals/gpio_async.c
Original file line number Diff line number Diff line change
@@ -1,92 +1,68 @@
#include "gpio_async.h"

struct gpio_async_data {
bool fired;
bool value;
returncode_t ret;
};

static struct gpio_async_data result = { .fired = false };
#include "syscalls/gpio_async_syscalls.h"

static void gpio_async_callback_command(returncode_t ret, bool value) {
result.fired = true;
result.value = value;
result.ret = ret;
}

static returncode_t gpio_async_op(uint32_t port, uint8_t pin, returncode_t (*op)(uint32_t, uint8_t,
libtock_gpio_async_callback_command)) {
returncode_t err;
result.fired = false;
static returncode_t gpio_async_command(uint32_t port, uint8_t pin, returncode_t (*command_fn)(uint32_t, uint8_t)) {
returncode_t ret;

err = op(port, pin, gpio_async_callback_command);
if (err != RETURNCODE_SUCCESS) return err;
ret = command_fn(port, pin);
if (ret != RETURNCODE_SUCCESS) return ret;

// Wait for the callback.
yield_for(&result.fired);
return result.ret;
ret = libtocksync_gpio_async_yield_wait_for_generic_command();
return ret;
}

returncode_t libtocksync_gpio_async_make_output(uint32_t port, uint8_t pin) {
return gpio_async_op(port, pin, libtock_gpio_async_make_output);
return gpio_async_command(port, pin, libtock_gpio_async_command_make_output);
}

returncode_t libtocksync_gpio_async_set(uint32_t port, uint8_t pin) {
return gpio_async_op(port, pin, libtock_gpio_async_set);
return gpio_async_command(port, pin, libtock_gpio_async_command_set);
}

returncode_t libtocksync_gpio_async_clear(uint32_t port, uint8_t pin) {
return gpio_async_op(port, pin, libtock_gpio_async_clear);
return gpio_async_command(port, pin, libtock_gpio_async_command_clear);
}

returncode_t libtocksync_gpio_async_toggle(uint32_t port, uint8_t pin) {
return gpio_async_op(port, pin, libtock_gpio_async_toggle);
return gpio_async_command(port, pin, libtock_gpio_async_command_toggle);
}

returncode_t libtocksync_gpio_async_make_input(uint32_t port, uint8_t pin, libtock_gpio_input_mode_t pin_config) {
returncode_t err;
result.fired = false;
returncode_t ret;

err = libtock_gpio_async_make_input(port, pin, pin_config, gpio_async_callback_command);
if (err != RETURNCODE_SUCCESS) return err;
ret = libtock_gpio_async_command_make_input(port, pin, pin_config);
if (ret != RETURNCODE_SUCCESS) return ret;

// Wait for the callback.
yield_for(&result.fired);
return result.ret;
ret = libtocksync_gpio_async_yield_wait_for_generic_command();
return ret;
}

returncode_t libtocksync_gpio_async_read(uint32_t port, uint8_t pin, bool* value) {
returncode_t err;
result.fired = false;

err = libtock_gpio_async_read(port, pin, gpio_async_callback_command);
if (err != RETURNCODE_SUCCESS) return err;
returncode_t ret;

// Wait for the callback.
yield_for(&result.fired);
if (result.ret != RETURNCODE_SUCCESS) return result.ret;
ret = libtock_gpio_async_command_read(port, pin);
if (ret != RETURNCODE_SUCCESS) return ret;

*value = result.value;
return RETURNCODE_SUCCESS;
ret = libtocksync_gpio_async_yield_wait_for_read(value);
return ret;
}

returncode_t libtocksync_gpio_async_enable_interrupt(uint32_t port, uint8_t pin,
libtock_gpio_interrupt_mode_t irq_config) {
returncode_t err;
result.fired = false;
returncode_t ret;

err = libtock_gpio_async_enable_interrupt(port, pin, irq_config, gpio_async_callback_command);
if (err != RETURNCODE_SUCCESS) return err;
ret = libtock_gpio_async_command_enable_interrupt(port, pin, irq_config);
if (ret != RETURNCODE_SUCCESS) return ret;

// Wait for the callback.
yield_for(&result.fired);
return result.ret;
ret = libtocksync_gpio_async_yield_wait_for_generic_command();
return ret;
}

returncode_t libtocksync_gpio_async_disable_interrupt(uint32_t port, uint8_t pin) {
return gpio_async_op(port, pin, libtock_gpio_async_disable_interrupt);
return gpio_async_command(port, pin, libtock_gpio_async_command_disable_interrupt);
}

returncode_t libtocksync_gpio_async_disable_sync(uint32_t port, uint8_t pin) {
return gpio_async_op(port, pin, libtock_gpio_async_disable);
return gpio_async_command(port, pin, libtock_gpio_async_command_disable);
}
21 changes: 21 additions & 0 deletions libtock-sync/peripherals/syscalls/gpio_async_syscalls.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include "gpio_async_syscalls.h"

returncode_t libtocksync_gpio_async_yield_wait_for_generic_command(void) {
yield_waitfor_return_t ret;
ret = yield_wait_for(DRIVER_NUM_GPIO_ASYNC, 0);

return (returncode_t) ret.data0;
}

returncode_t libtocksync_gpio_async_yield_wait_for_read(bool* value) {
yield_waitfor_return_t ywf;
returncode_t ret;

ywf = yield_wait_for(DRIVER_NUM_GPIO_ASYNC, 0);

ret = (returncode_t) ywf.data0;
if (ret != RETURNCODE_SUCCESS) return ret;

*value = (bool) ywf.data1;
return ret;
}
20 changes: 20 additions & 0 deletions libtock-sync/peripherals/syscalls/gpio_async_syscalls.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once

#include <libtock/peripherals/syscalls/gpio_async_syscalls.h>
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
#include <libtock/peripherals/syscalls/gpio_async_syscalls.h>

So we don't leak libtock in libtock-sync.

Copy link
Member Author

Choose a reason for hiding this comment

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

It's there to avoid duplicating the DRIVER_NUM_GPIO_ASYNC, presumably for the same reason you have the same include here ( https://github.com/tock/libtock-c/pull/553/files#diff-28af97b25b50c3d619c7a3ba099e6a2ff6ebcf972c1fc84800fa932c3c1159d7R3 ) and elsewhere in #553.

#include <libtock/tock.h>

#ifdef __cplusplus
extern "C" {
#endif

// Wait for a GPIO-Async operation with no values to finish.
//
// In lieu of redundant `wait_for_[set|clear|...]`, generic_command can be used
// for any operation that only reports success or failure, expecting no values.
returncode_t libtocksync_gpio_async_yield_wait_for_generic_command(void);

returncode_t libtocksync_gpio_async_yield_wait_for_read(bool* value);

#ifdef __cplusplus
}
#endif