-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #104 from GaloisInc/89-gpio-linux
Add Linux GPIO support to MPS This updates MPS with the ability to send actuator outputs to a Linux GPIO device. For example, building with `make GPIO=Enabled` and running with `MPS_GPIO_DEVICE=/dev/gpiochip1 ./mps` will cause MPS to output the current actuator state on GPIO lines 0 and 1 of `/dev/gpiochip1`. (It also displays the actuator state in the human-readable UART output as usual.) This PR also updates the MPS test scripts to check the GPIO behavior in addition to the UART output. The CI is updated to run the VM tests in this mode, so the new GPIO support is tested in CI. However, this only applies to MPS test cases that explicitly check the actuator state, which at the moment is only `scenarios/normal_5a` (`normal_6` also checks the actuator state, but only the first few cases are run when `QUICK=1`, and these don't trigger any actuators).
- Loading branch information
Showing
23 changed files
with
674 additions
and
80 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
// GPIO implementation for Linux, using libgpiod | ||
|
||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <gpiod.h> | ||
#include "common.h" | ||
// Include `platform.h` for `ASSERT` | ||
#include "platform.h" | ||
|
||
#define NUM_LINES NDEV | ||
|
||
// BEGIN code copied from libgpiod `examples/toggle_multiple_line_values.c` | ||
|
||
static struct gpiod_line_request * | ||
request_output_lines(const char *chip_path, const unsigned int *offsets, | ||
enum gpiod_line_value *values, unsigned int num_lines, | ||
const char *consumer) | ||
{ | ||
struct gpiod_request_config *rconfig = NULL; | ||
struct gpiod_line_request *request = NULL; | ||
struct gpiod_line_settings *settings; | ||
struct gpiod_line_config *lconfig; | ||
struct gpiod_chip *chip; | ||
unsigned int i; | ||
int ret; | ||
|
||
chip = gpiod_chip_open(chip_path); | ||
if (!chip) | ||
return NULL; | ||
|
||
settings = gpiod_line_settings_new(); | ||
if (!settings) | ||
goto close_chip; | ||
|
||
gpiod_line_settings_set_direction(settings, | ||
GPIOD_LINE_DIRECTION_OUTPUT); | ||
|
||
lconfig = gpiod_line_config_new(); | ||
if (!lconfig) | ||
goto free_settings; | ||
|
||
for (i = 0; i < num_lines; i++) { | ||
ret = gpiod_line_config_add_line_settings(lconfig, &offsets[i], | ||
1, settings); | ||
if (ret) | ||
goto free_line_config; | ||
} | ||
gpiod_line_config_set_output_values(lconfig, values, num_lines); | ||
|
||
if (consumer) { | ||
rconfig = gpiod_request_config_new(); | ||
if (!rconfig) | ||
goto free_line_config; | ||
|
||
gpiod_request_config_set_consumer(rconfig, consumer); | ||
} | ||
|
||
request = gpiod_chip_request_lines(chip, rconfig, lconfig); | ||
|
||
gpiod_request_config_free(rconfig); | ||
|
||
free_line_config: | ||
gpiod_line_config_free(lconfig); | ||
|
||
free_settings: | ||
gpiod_line_settings_free(settings); | ||
|
||
close_chip: | ||
gpiod_chip_close(chip); | ||
|
||
return request; | ||
} | ||
|
||
// END code copied from libgpiod `examples/toggle_multiple_line_values.c` | ||
|
||
static int request_inited = 0; | ||
static struct gpiod_line_request* request = NULL; | ||
|
||
// Hardcoded device and lines for use in OpenSUT VMs. | ||
static const unsigned int line_offsets[NUM_LINES] = {0, 1}; | ||
|
||
static void init_request() { | ||
if (!request_inited) { | ||
request_inited = 1; | ||
const char* chip_path = getenv("MPS_GPIO_DEVICE"); | ||
if (chip_path == NULL) { | ||
// No device is configured. Leave `request` as `NULL`, so no GPIO output | ||
// will be performed. | ||
return; | ||
} | ||
|
||
enum gpiod_line_value values[NUM_LINES] = { GPIOD_LINE_VALUE_INACTIVE, | ||
GPIOD_LINE_VALUE_INACTIVE }; | ||
request = request_output_lines(chip_path, line_offsets, values, NUM_LINES, "mps"); | ||
if (request == NULL) { | ||
fprintf(stderr, "warning: failed to open GPIO device %s\n", chip_path); | ||
} | ||
} | ||
} | ||
|
||
void gpio_set_value(int index, int value) { | ||
enum gpiod_line_value gpiod_value; | ||
if (value == 0) { | ||
gpiod_value = GPIOD_LINE_VALUE_INACTIVE; | ||
} else { | ||
gpiod_value = GPIOD_LINE_VALUE_ACTIVE; | ||
} | ||
unsigned int gpiod_offset = line_offsets[index]; | ||
|
||
init_request(); | ||
if (request != NULL) { | ||
gpiod_line_request_set_value(request, gpiod_offset, gpiod_value); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#ifndef GPIO_LINUX_H_ | ||
#define GPIO_LINUX_H_ | ||
|
||
// Set the value of GPIO output `index` to `value`. This will open the GPIO | ||
// device the first time it's called. | ||
void gpio_set_value(int index, int value); | ||
|
||
#endif // GPIO_LINUX_H_ |
Oops, something went wrong.