From dd88e567e6868bac5dacf6222be9663c0801ee9f Mon Sep 17 00:00:00 2001 From: Knox Lively Date: Thu, 10 Apr 2025 16:15:23 -0600 Subject: [PATCH 1/6] Added GPIO API --- docs/reference/container-api/gpio.md | 442 +++++++++++++++++++++++++++ 1 file changed, 442 insertions(+) create mode 100644 docs/reference/container-api/gpio.md diff --git a/docs/reference/container-api/gpio.md b/docs/reference/container-api/gpio.md new file mode 100644 index 0000000..b8ec343 --- /dev/null +++ b/docs/reference/container-api/gpio.md @@ -0,0 +1,442 @@ +--- +title: GPIO +layout: default +parent: Container APIs +has_toc: false +--- + +# GPIO +{: .no_toc } + +The GPIO API provides access to General Purpose Input/Output pins on Ocre containers. It enables applications to configure pins, read input states, set output states, and register callbacks for pin state changes. + +--- + +## Table of Contents +{: .no_toc } + +Navigate this comprehensive API reference using the links below. + +
+ + Click to expand + + {: .text-delta } +1. TOC +{:toc} +
+ +--- + +## Header File + +```c +#include "ocre_gpio.h" +``` + +--- + +## Types + +### GPIO Pin State + +An enumeration defining the possible states of a GPIO pin. + +```c +typedef enum { + OCRE_GPIO_PIN_RESET = 0, ///< Pin is low (0) + OCRE_GPIO_PIN_SET = 1 ///< Pin is high (1) +} ocre_gpio_pin_state_t; +``` + +### GPIO Direction + +An enumeration defining the direction of a GPIO pin. + +```c +typedef enum { + OCRE_GPIO_DIR_INPUT = 0, ///< Pin configured as input + OCRE_GPIO_DIR_OUTPUT = 1 ///< Pin configured as output +} ocre_gpio_direction_t; +``` + +### GPIO Configuration + +A structure for configuring a GPIO pin. + +```c +typedef struct { + int pin; /**< GPIO pin number (logical) */ + ocre_gpio_direction_t direction; /**< Pin direction */ +} ocre_gpio_config_t; +``` + +### GPIO Callback Function + +A function that will be called when a GPIO pin's state changes. + +```c +typedef void (*ocre_gpio_callback_t)(int pin, ocre_gpio_pin_state_t state); +``` + +### Execution Environment + +All GPIO functions have an internal `wasm_exec_env_t` parameter that is used by the Ocre runtime. This parameter is NOT needed when calling these functions from within a container. Container applications should omit this parameter. + +--- + +## Methods + +### GPIO Initialization + +Initializes the GPIO subsystem. This function must be called before using any other GPIO functions. + +```c +int ocre_gpio_init(void); +``` + +**Returns**: + +| Value | Description | +| ------ | ----------- | +| `0` | on success | +| negative value | on error | + +### Configure GPIO Pin + +Configures a GPIO pin for either input or output. + +```c +int ocre_gpio_configure(const ocre_gpio_config_t *config); +``` + +**Parameters**: + +| Name | Type | Description | +| ------ | ------ | ----------- | +| `config` | *const ocre_gpio_config_t* * | Pointer to a GPIO configuration structure | + +**Returns**: + +| Value | Description | +| ------ | ----------- | +| `0` | on success | +| negative value | on error | + +### Set GPIO Pin + +Sets the state of a GPIO output pin. + +```c +int ocre_gpio_pin_set(int pin, ocre_gpio_pin_state_t state); +``` + +**Parameters**: + +| Name | Type | Description | +| ------ | ------ | ----------- | +| `pin` | *int* | GPIO pin number | +| `state` | *ocre_gpio_pin_state_t* | State to set the pin to (`OCRE_GPIO_PIN_SET` or `OCRE_GPIO_PIN_RESET`) | + +**Returns**: + +| Value | Description | +| ------ | ----------- | +| `0` | on success | +| negative value | on error | + +### Get GPIO Pin State + +Reads the current state of a GPIO pin. + +```c +ocre_gpio_pin_state_t ocre_gpio_pin_get(int pin); +``` + +**Parameters**: + +| Name | Type | Description | +| ------ | ------ | ----------- | +| `pin` | *int* | GPIO pin number | + +**Returns**: + +| Value | Description | +| ------ | ----------- | +| `OCRE_GPIO_PIN_SET` | if the pin is high | +| `OCRE_GPIO_PIN_RESET` | if the pin is low | +| negative value | on error | + +### Toggle GPIO Pin + +Toggles the state of a GPIO output pin. + +```c +int ocre_gpio_pin_toggle(int pin); +``` + +**Parameters**: + +| Name | Type | Description | +| ------ | ------ | ----------- | +| `pin` | *int* | GPIO pin number | + +**Returns**: + +| Value | Description | +| ------ | ----------- | +| `0` | on success | +| negative value | on error | + +### Register GPIO Callback + +Registers a callback function to be called when a GPIO input pin changes state. + +```c +int ocre_gpio_register_callback(int pin, ocre_gpio_callback_t callback); +``` + +**Parameters**: + +| Name | Type | Description | +| ------ | ------ | ----------- | +| `pin` | *int* | GPIO pin number | +| `callback` | *ocre_gpio_callback_t* | Function to call when the pin state changes | + +**Returns**: + +| Value | Description | +| ------ | ----------- | +| `0` | on success | +| negative value | on error | + +### Unregister GPIO Callback + +Removes a previously registered callback for a GPIO pin. + +```c +int ocre_gpio_unregister_callback(int pin); +``` + +**Parameters**: + +| Name | Type | Description | +| ------ | ------ | ----------- | +| `pin` | *int* | GPIO pin number | + +**Returns**: + +| Value | Description | +| ------ | ----------- | +| `0` | on success | +| negative value | on error | + +### Get Pin ID + +Calculates a pin ID from port and pin numbers. + +```c +int get_pin_id(int port, int pin); +``` + +**Parameters**: + +| Name | Type | Description | +| ------ | ------ | ----------- | +| `port` | *int* | GPIO port number | +| `pin` | *int* | Pin number within the port | + +**Returns**: + +| Value | Description | +| ------ | ----------- | +| positive value (pin ID) | on success | +| `-1` | on error | + +--- + +## Error Handling + +Most GPIO functions return status codes: + +| Value | Description | +| ------ | ----------- | +| `0` | Operation completed successfully | +| `ENODEV` | GPIO system not initialized | +| `EINVAL` | Invalid parameter | +| `ENOMEM` | Memory allocation failed | +| other negative values | Other errors from underlying system | + +--- + +## Examples + +### Basic GPIO Output + +```c +#include +#include "ocre_gpio.h" + +#define LED_PIN 5 // Example pin number (adjust for your hardware) + +int main() { + // Initialize GPIO subsystem + if (ocre_gpio_init() != 0) { + printf("Failed to initialize GPIO\n"); + return -1; + } + + // Configure the pin as output + ocre_gpio_config_t config; + config.pin = LED_PIN; + config.direction = OCRE_GPIO_DIR_OUTPUT; + + if (ocre_gpio_configure(&config) != 0) { + printf("Failed to configure GPIO pin\n"); + return -1; + } + + // Blink LED 5 times + for (int i = 0; i < 5; i++) { + // Turn LED on + ocre_gpio_pin_set(LED_PIN, OCRE_GPIO_PIN_SET); + printf("LED on\n"); + + // Delay (implementation-specific) + for (volatile int j = 0; j < 1000000; j++); + + // Turn LED off + ocre_gpio_pin_set(LED_PIN, OCRE_GPIO_PIN_RESET); + printf("LED off\n"); + + // Delay (implementation-specific) + for (volatile int j = 0; j < 1000000; j++); + } + + return 0; +} +``` + +### GPIO Input with Callback + +```c +#include +#include +#include "ocre_gpio.h" + +#define BUTTON_PIN 7 // Example pin number (adjust for your hardware) + +// Flag to signal application to exit +volatile bool running = true; + +// Callback function for button press +void button_callback(int pin, ocre_gpio_pin_state_t state) { + printf("Button event on pin %d: state = %d\n", pin, state); + + // If button is pressed, exit the application + if (state == OCRE_GPIO_PIN_SET) { + printf("Button pressed, exiting...\n"); + running = false; + } +} + +int main() { + // Initialize GPIO subsystem + if (ocre_gpio_init() != 0) { + printf("Failed to initialize GPIO\n"); + return -1; + } + + // Configure the pin as input + ocre_gpio_config_t config; + config.pin = BUTTON_PIN; + config.direction = OCRE_GPIO_DIR_INPUT; + + if (ocre_gpio_configure(&config) != 0) { + printf("Failed to configure GPIO pin\n"); + return -1; + } + + // Register callback for button presses + if (ocre_gpio_register_callback(BUTTON_PIN, button_callback) != 0) { + printf("Failed to register GPIO callback\n"); + return -1; + } + + printf("Waiting for button press...\n"); + + // Main application loop + while (running) { + // Application logic here + + // Simple delay + for (volatile int j = 0; j < 100000; j++); + } + + // Clean up + ocre_gpio_unregister_callback(BUTTON_PIN); + + return 0; +} +``` + +### Using Port and Pin Mapping + +```c +#include +#include "ocre_gpio.h" + +#define GPIO_PORT_A 0 +#define GPIO_PIN_5 5 + +int main() { + // Initialize GPIO subsystem + if (ocre_gpio_init() != 0) { + printf("Failed to initialize GPIO\n"); + return -1; + } + + // Calculate pin ID from port and pin + int pin_id = get_pin_id(GPIO_PORT_A, GPIO_PIN_5); + if (pin_id < 0) { + printf("Invalid port or pin\n"); + return -1; + } + + // Configure the pin as output + ocre_gpio_config_t config; + config.pin = pin_id; + config.direction = OCRE_GPIO_DIR_OUTPUT; + + if (ocre_gpio_configure(&config) != 0) { + printf("Failed to configure GPIO pin\n"); + return -1; + } + + // Toggle the pin 10 times + for (int i = 0; i < 10; i++) { + ocre_gpio_pin_toggle(pin_id); + printf("Pin toggled\n"); + + // Delay (implementation-specific) + for (volatile int j = 0; j < 500000; j++); + } + + return 0; +} +``` + +--- + +## Reference + +| Function | Description | Parameters | Return Value | Error Codes | +|----------|-------------|------------|--------------|--------------| +| [`ocre_gpio_init`](#gpio-initialization) | Initializes GPIO subsystem | None | `0` on success, negative on error | `ENODEV` | +| [`ocre_gpio_configure`](#configure-gpio-pin) | Configures a GPIO pin | `config`: Pointer to GPIO configuration | `0` on success, negative on error | `ENODEV`, `EINVAL` | +| [`ocre_gpio_pin_set`](#set-gpio-pin) | Sets a GPIO pin state | `pin`: GPIO pin number
`state`: Pin state to set | `0` on success, negative on error | `ENODEV`, `EINVAL` | +| [`ocre_gpio_pin_get`](#get-gpio-pin-state) | Gets a GPIO pin state | `pin`: GPIO pin number | `OCRE_GPIO_PIN_SET`/`OCRE_GPIO_PIN_RESET` or negative error code | `ENODEV`, `EINVAL` | +| [`ocre_gpio_pin_toggle`](#toggle-gpio-pin) | Toggles a GPIO pin state | `pin`: GPIO pin number | `0` on success, negative on error | `ENODEV`, `EINVAL` | +| [`ocre_gpio_register_callback`](#register-gpio-callback) | Registers callback for GPIO changes | `pin`: GPIO pin number
`callback`: Callback function | `0` on success, negative on error | `ENODEV`, `EINVAL` | +| [`ocre_gpio_unregister_callback`](#unregister-gpio-callback) | Removes GPIO callback | `pin`: GPIO pin number | `0` on success, negative on error | `ENODEV`, `EINVAL` | +| [`get_pin_id`](#get-pin-id) | Calculates pin ID from port and pin | `port`: GPIO port number
`pin`: Pin number within port | Pin ID or `-1` on invalid Pin | N/A | \ No newline at end of file From 97c70194b419ae48994d5da301c56b434d9c9d41 Mon Sep 17 00:00:00 2001 From: Knox Lively Date: Thu, 10 Apr 2025 16:15:35 -0600 Subject: [PATCH 2/6] Updated bundle --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 1c0a624..7453833 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -98,4 +98,4 @@ DEPENDENCIES logger BUNDLED WITH - 2.5.9 + 2.6.7 From e8aea8c34d3361fc094fe2bc260a8a47ff27fcd1 Mon Sep 17 00:00:00 2001 From: Knox Lively Date: Thu, 10 Apr 2025 16:15:57 -0600 Subject: [PATCH 3/6] Refereshed sensors and timers parameter table with a "type" --- docs/reference/container-api/sensors.md | 79 ++++++++++++------------- docs/reference/container-api/timers.md | 61 ++++++++++--------- 2 files changed, 69 insertions(+), 71 deletions(-) diff --git a/docs/reference/container-api/sensors.md b/docs/reference/container-api/sensors.md index d4e750b..54e9fd0 100644 --- a/docs/reference/container-api/sensors.md +++ b/docs/reference/container-api/sensors.md @@ -145,14 +145,14 @@ int ocre_sensors_init(int unused); **Parameters**: -| Value | Description | -| ------ | -----------| -| `unused` | Reserved parameter (not used) | +| Name | Type | Description | +| ------ | ------ | ----------- | +| `unused` | *int* | Reserved parameter (not used) | **Returns**: | Value | Description | -| ------ | -----------| +| ------ | ----------- | | `0` | on success | | negative value | on error | @@ -167,15 +167,15 @@ ocre_sensors_status_t ocre_sensors_discover_sensors(ocre_sensor_t *sensors, int **Parameters**: -| Value | Description | -| ------ | -----------| -| `sensors` | Pointer to the sensor list to store the discovered info about available sensors | -| `sensors_count` | Pointer to variable to store the number of discovered sensors | +| Name | Type | Description | +| ------ | ------ | ----------- | +| `sensors` | *ocre_sensor_t** | Pointer to the sensor list to store the discovered info about available sensors | +| `sensors_count` | *int** | Pointer to variable to store the number of discovered sensors | **Returns**: | Value | Description | -| ------ | -----------| +| ------ | ----------- | | `SENSOR_API_STATUS_OK` | on success | | other status code | on error | @@ -189,14 +189,14 @@ ocre_sensors_status_t ocre_sensors_open(ocre_sensor_handle_t *sensor_handle); **Parameters**: -| Value | Description | -| ------ | -----------| -| `sensor_handle` | Pointer to the sensor handle to open | +| Name | Type | Description | +| ------ | ------ | ----------- | +| `sensor_handle` | *ocre_sensor_handle_t** | Pointer to the sensor handle to open | **Returns**: | Value | Description | -| ------ | -----------| +| ------ | ----------- | | `SENSOR_API_STATUS_OK` | on success | | `SENSOR_API_STATUS_ERROR` | on error | @@ -211,14 +211,14 @@ ocre_sensors_sample_t sensor_read_sample(ocre_sensor_handle_t *sensor_handle); **Parameters**: -| Value | Description | -| ------ | -----------| -| `sensor_handle` | Pointer to the sensor handle to read from | +| Name | Type | Description | +| ------ | ------ | ----------- | +| `sensor_handle` | *ocre_sensor_handle_t** | Pointer to the sensor handle to read from | **Returns**: | Value | Description | -| ------ | -----------| +| ------ | ----------- | | `ocre_sensors_sample_t` | A structure containing the sensor data sample | @@ -232,20 +232,19 @@ ocre_sensor_value_t sensor_get_channel(ocre_sensors_sample_t sample, sensor_chan **Parameters**: -| Value | Description | -| ------ | -----------| -| `sample` | The sensor sample containing raw data | -| `channel` | The specific channel to retrieve data for (e.g., `SENSOR_CHANNEL_TEMPERATURE`) | +| Name | Type | Description | +| ------ | ------ | ----------- | +| `sample` | *ocre_sensors_sample_t* | The sensor sample containing raw data | +| `channel` | *sensor_channel_t* | The specific channel to retrieve data for (e.g., `SENSOR_CHANNEL_TEMPERATURE`) | **Returns**: | Value | Description | -| ------ | -----------| +| ------ | ----------- | | `ocre_sensor_value_t` | The value from the requested channel | -:::note +{: .note } If the channel is invalid or unavailable, the function may return an error code or placeholder value. -::: ### Set Sensor Trigger @@ -259,18 +258,18 @@ ocre_sensors_status_t ocre_sensors_set_trigger(ocre_sensor_handle_t sensor_handl **Parameters**: -| Value | Description | -| ------ | -----------| -| `sensor_handle` | Handle of the sensor | -| `channel` | Channel to set the trigger on | -| `trigger_type` | Type of trigger (e.g., data ready, threshold) | -| `callback` | Function to be called when trigger occurs | -| `subscription_id` | Pointer to store the subscription ID | +| Name | Type | Description | +| ------ | ------ | ----------- | +| `sensor_handle` | *ocre_sensor_handle_t* | Handle of the sensor | +| `channel` | *sensor_channel_t* | Channel to set the trigger on | +| `trigger_type` | *enum sensor_trigger_type* | Type of trigger (e.g., data ready, threshold) | +| `callback` | *ocre_sensor_trigger_cb* | Function to be called when trigger occurs | +| `subscription_id` | *int** | Pointer to store the subscription ID | **Returns**: | Value | Description | -| ------ | -----------| +| ------ | ----------- | | `SENSOR_API_STATUS_OK` | on success | | other status code | on error | @@ -285,16 +284,16 @@ ocre_sensors_status_t ocre_sensors_clear_trigger(ocre_sensor_handle_t sensor_han **Parameters**: -| Value | Description | -| ------ | -----------| -| `sensor_handle` | Handle of the sensor | -| `channel` | The specific channel (e.g., `SENSOR_CHANNEL_TEMPERATURE`) from which the trigger should be removed | -| `subscription_id` | ID of the subscription to remove | +| Name | Type | Description | +| ------ | ------ | ----------- | +| `sensor_handle` | *ocre_sensor_handle_t* | Handle of the sensor | +| `channel` | *sensor_channel_t* | The specific channel (e.g., `SENSOR_CHANNEL_TEMPERATURE`) from which the trigger should be removed | +| `subscription_id` | *int* | ID of the subscription to remove | **Returns**: | Value | Description | -| ------ | -----------| +| ------ | ----------- | | `SENSOR_API_STATUS_OK` | on success | | other status code | on error | @@ -310,7 +309,7 @@ ocre_sensors_status_t ocre_sensors_cleanup(); **Returns**: | Value | Description | -| ------ | -----------| +| ------ | ----------- | | `SENSOR_API_STATUS_OK` | on success | | other status code | on error | @@ -321,7 +320,7 @@ ocre_sensors_status_t ocre_sensors_cleanup(); Most functions return status codes from the `ocre_sensors_status_t` enumeration. Check the return value to determine if an operation succeeded or failed. | Value | Description | -| ------ | -----------| +| ------ | ----------- | | `SENSOR_API_STATUS_OK` | Operation completed successfully | | `SENSOR_API_STATUS_ERROR` | General failure | | `SENSOR_API_STATUS_UNINITIALIZED` | API not initialized | diff --git a/docs/reference/container-api/timers.md b/docs/reference/container-api/timers.md index 9ac6508..eb31977 100644 --- a/docs/reference/container-api/timers.md +++ b/docs/reference/container-api/timers.md @@ -79,21 +79,21 @@ int ocre_timer_create(int id); **Parameters**: -| Value | Description | -| ------ | -----------| -| `id` | Timer identifier (must be between `1` and `MAX_TIMERS`) | +| Name | Type | Description | +| ------ | ------ | ----------- | +| `id` | *int* | Timer identifier (must be between `1` and `MAX_TIMERS`) | **Returns**: | Value | Description | -| ------ | -----------| +| ------ | ----------- | | `0` | on success | | `-1` | on error with errno set | **Errors**: | Value | Description | -| ------ | -----------| +| ------ | ----------- | | `EINVAL` | Invalid timer ID or timer system not initialized | | `EEXIST` | Timer ID already in use | @@ -107,23 +107,23 @@ int ocre_timer_start(ocre_timer_t id, int interval, int is_periodic); **Parameters**: -| Value | Description | -| ------ | -----------| -| `id` | Timer identifier | -| `interval` | Timer interval in milliseconds | -| `is_periodic`| `1` for periodic timer, `0` for one-shot +| Name | Type | Description | +| ------ | ------ | ----------- | +| `id` | *ocre_timer_t* | Timer identifier | +| `interval` | *int* | Timer interval in milliseconds | +| `is_periodic` | *int* | `1` for periodic timer, `0` for one-shot | **Returns**: | Value | Description | -| ------ | -----------| +| ------ | ----------- | | `0` | on success | | `-1` | on error with errno set | **Errors**: | Value | Description | -| ------ | -----------| +| ------ | ----------- | | `EINVAL` | Invalid timer ID, timer not found, or invalid interval | ### Stop Timer @@ -136,21 +136,21 @@ int ocre_timer_stop(ocre_timer_t id); **Parameters**: -| Value | Description | -| ------ | -----------| -| `id` | Timer identifier | +| Name | Type | Description | +| ------ | ------ | ----------- | +| `id` | *ocre_timer_t* | Timer identifier | **Returns**: | Value | Description | -| ------ | -----------| +| ------ | ----------- | | `0` | on success | | `-1` | on error with errno set | **Errors**: | Value | Description | -| ------ | -----------| +| ------ | ----------- | | `EINVAL` | Invalid timer ID, timer not found, or invalid interval | ### Get Remaining Time @@ -163,21 +163,21 @@ int ocre_timer_get_remaining(ocre_timer_t id); **Parameters**: -| Value | Description | -| ------ | -----------| -| `id` | Timer identifier | +| Name | Type | Description | +| ------ | ------ | ----------- | +| `id` | *ocre_timer_t* | Timer identifier | **Returns**: | Value | Description | -| ------ | -----------| -| `>= 0` | Remaining time in milliseconds| +| ------ | ----------- | +| `>= 0` | Remaining time in milliseconds | | `-1` | Error occurred (check errno) | **Errors**: | Value | Description | -| ------ | -----------| +| ------ | ----------- | | `EINVAL` | Invalid timer ID, timer not found, or invalid interval | ### Delete Timer @@ -190,21 +190,21 @@ int ocre_timer_delete(ocre_timer_t id); **Parameters**: -| Value | Description | -| ------ | -----------| -| `id` | Timer identifier | +| Name | Type | Description | +| ------ | ------ | ----------- | +| `id` | *ocre_timer_t* | Timer identifier | **Returns**: | Value | Description | -| ------ | -----------| +| ------ | ----------- | | `0` | on success | | `-1` | on error with errno set | **Errors**: | Value | Description | -| ------ | -----------| +| ------ | ----------- | | `EINVAL` | Invalid timer ID, timer not found, or invalid interval | @@ -216,9 +216,8 @@ Sets the WASM dispatcher function for timer callbacks. This function is used int void ocre_timer_set_dispatcher(void); ``` -:::info +{: .note } This function is handled automatically by the Ocre runtime and is included here for completeness. Container applications should not call this function directly. -::: --- ## Error Handling @@ -228,7 +227,7 @@ All functions, except `ocre_timer_set_module_inst` and `ocre_timer_set_dispatche **Errors:** | Value | Description | -| ------ | -----------| +| ------ | ----------- | | `EINVAL` | Invalid timer ID or timer system not initialized | | `EEXIST` | Timer ID already in use | From b9db53af461b705a4999829c1f6583affa421339 Mon Sep 17 00:00:00 2001 From: Knox Lively Date: Thu, 24 Apr 2025 19:32:48 -0600 Subject: [PATCH 4/6] Updated the expected output after flashing the Ocre runtime --- docs/quickstart/firmware/hardware.md | 7 ++++++- docs/quickstart/firmware/simulated.md | 7 ++++++- docs/quickstart/firmware/success.png | Bin 119350 -> 0 bytes 3 files changed, 12 insertions(+), 2 deletions(-) delete mode 100644 docs/quickstart/firmware/success.png diff --git a/docs/quickstart/firmware/hardware.md b/docs/quickstart/firmware/hardware.md index 7176895..f415f59 100644 --- a/docs/quickstart/firmware/hardware.md +++ b/docs/quickstart/firmware/hardware.md @@ -88,7 +88,12 @@ To flash the Ocre Runtime to your device follow these steps: ``` 3. After flashing, restart/reset your board to run the application. If successful, you should see the following output on your console: -![](../success.png) + ```sh + ocre:~$ + + Ocre runtime started + Hello world from Ocre. + ``` --- diff --git a/docs/quickstart/firmware/simulated.md b/docs/quickstart/firmware/simulated.md index 7a05466..6ab1689 100644 --- a/docs/quickstart/firmware/simulated.md +++ b/docs/quickstart/firmware/simulated.md @@ -94,7 +94,12 @@ To run the application, simply run the following command: If successful, you should see the following output: -![](../success.png) + ```sh + ocre:~$ + + Ocre runtime started + Hello world from Ocre. + ``` --- diff --git a/docs/quickstart/firmware/success.png b/docs/quickstart/firmware/success.png deleted file mode 100644 index 37792807214fa0bc4bb3507ca45a1df627acddbe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 119350 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%0D6E-lrJ==l6y{36qC^B zcD?||5b`A%tK-BNuY3VkARETxJ^=t0DfJqoj16Si7psx9 zub6ka_>O0-{Ko~J+W76OyRBQf7}xZB-*|Gj-CQ14lw`^m{3 z3V9n;CO*Ht`8_>lqlD(v)dpV|KJ=X#0Yg;(XeJqFXJ=#-Sm9&z9piC)CG)F6*OyoE zo8Px{7FWV0;y$i?5IHrK7A7AY`PNAIj@{7r|&azBT zM5I!&5PS;sqMTy`w`AVO#LUiu-09EpTtccPl*&~uaY`NMeaE9qVl!`2*_m%FjDi+NjY=kYB3hlCA z9Q*zsAFKfJZRLf|nx$M<>-%qRxl$&(k+4PoE3{wvhk{FEG!7`=B#t~YFtXRy9*!Gj zkUanu>h8pRyMn&bNFT9QLsruq`UK0?vVQs*GKY)RY}X^c@*_&dNeOxpYt+x)Vf9zq z7g;_34RPTpG;D>Q;72@b7fa;S7&;dk1U^R|H9c|!Ixt!A)kpr}M(rSdEBv&Iy{6li ziO-_NYnVRYmUFHcXvj+dOs_Vh&WPq}&1gyS@c4m$j&>5dGcY?5J+WYWqTvoLs~ zhva=V4GO}lN_=;q?MZ<-Fk4gy?AWp22Pz=mf^)}8`}G@uVf}IssFgA-8{_XEF=bAp zCv{-v4oM*p)k4E-#kG*}-icUTN?KalD5deVscG&B7PY|w3FwW#eSKnndt)0qyCVhv z)MLk4zqATT*zEBj2>tN_d@aGLlRtSNxpRDQYw50K3yY0$$g>-zh*!F2GyctU-Zfx6-CwGBC0uayd6y(0c%=@hd^y1t`hgw$>b z6F8!P%7HH)KRvbb-N;I({{H6XX0kkR#Czs=qty{#!McwmG*i{`X9g1Vo*15Xe;{H{ ze8Fa)4vFiAhCf?QG6?wKgn}Nn#OEeSdCGi*-JcjQ=_c*F7ZDLbp#Y|tS%5vRa4`#Y}q3i)qf$-#cHHmIQw2Ff{&l_Lg(@)IP^xybw7PQAj+;CoN$Ef zPH>iyo+Gd7_*|F+p?a!EFWRRv`u7(0y`Mo1uX`@{AZLObFO0c)b3FS( z6m?CQlam^GyCcD=K9(o+63pFMq33rf_!gq9|Lp)|UEdtpM?beY+808?D z{ob@hJtYXGH`o3JX2iCHPY)s^V>6K_JbisVoA~*sD{Zo4HCk|_Gu3M3gQzkqvIvxB zu;k_R#A?9kG!6B7lcM6TUAlI`-qK^BSYG+ZdE^cN(O1->m4 zx$$0TXsG$&N1*Z5cMz8*6Q=&T!ss9V_9uz{PPwE5(hP&l&5wQrjjrFMLwOo9bWVx2 z52t{?b7yeyg~0y5+Qx)=O}|@uW;aJcqc~~(PGB>`vfkU95FdJge)D@1)csevI&jhn z>g}x`ez%W)=g!NQ5Pp?UB3vqZ_-n??mwXQUr=@>&bIaLco4J=919U~f?jZfD%F3!y z=TH5|pYFN)OEZBuI~><&pbY7{5>vh@s`PZea4uQI&$fr;I3kvqmF2W|tET3zPi;>yP>p^ZJY0?F((PPG{L<7x&r~_GSCU6n33<>}|8Vly%&-?OFTr zF^kkJ>#S^K=5O1!UB7%AP|k}i#Jt$zxi4tZC%6XxF;X<8Rz-} z)NA>H|0&si++FhZy&h>9m-IT-`=Z;6=UbGQl$PlxggbZOMl-Sq2DJD{r6cj0+1bm~ zZ;e3p=ZYHZR38kOnI!4;k=tK%vIcw&;0@fUf}qw^ z<}7y<8KE;g_10K^$EWP#eoFO+CounSQKYmACOp(gtEc-bi~D4?POL*;xU#^^wlj2% z=iB2I6K@bkc|lqP2Qn6g18{;rPIu@bBal`yU?gu4I6a6GZX4WW)=pqJbZ<~2lxU~) z`WXtQ7Dz2E^`LGtbHb=NL4`VS`)Nbr_W#^5FV9`P{GXc%(nHhjc9*yXsn?{pn8n;? z@u?`BFvV06dMsxm9Q_KGH z%4Li4oeigJ%+zjG_*@JM!nAwp0@Em7N3ju)I=1ud!5R|y!=V+aEta4XOatxu)?mwEM#!S<-&yUMMW;wH7ebAVq>>$GeQqNO2>z*hiqdr-tJec1gtEcJiufwQ->sbsJO3UxYe;RM5#Yi72`D^&>T}%lO9M z4plls-~BCe*X#YlfBb4u73p#9Ao|4Df6z_&pDVrUKkf>Lzs2S5Ia2!StJe=qJFjbh ze;JSP2RHswdp0Nd>sR}#=+OW5)naGVKxi%h7qUq5s=I&r=f?%_siUHDf7X(D*`}#K zErF2rQY67DvrKnzbhN80EzKd~t6wk@`p-A3BJ1#=)KF9Eey>Hx$p@Rf1J`&?Ct8)m4hq5^k(3i5cda zvpAruz&fj$?x427P1Q-k?MQFgM6Ss}ij$u2XmZ5u!0FoZ$u1(_P&{d#M#8qgi1a8q zB^Hur5+E5X(U6>@N~!x(mi?;zpP$$xa;}=Dhv!AJEVErY7d|dlx+y595;=VqIN9mP zI}zxD^i64H=&k}h#JdfI>&=JTY*>;y#SJiObR!d{jcpjjN z*I=a#=FCvC8ruf@h)aHwl{LzFApj7l!Qz1S7coxvoL7@(8pd)kgZCq4wm;9f=;G3S zfzMh@e|kfeG?$rWWH9y0cT66$ebC;$R4nqZ>QCE@v80{n58LcoqaZaseOxv6taATc zvwZE@W5)y{GHh&-{Z&Lfh(PDQ+*XJi)huN=(+dl5VVGojdZFiNh zGjWRINx$CmYG*eDX0nt9tA?Ns)fePfA#RGFxiPzC`#PQJkH*HN!3S|3@NOc>-1;xu z@0_R*j=Hx5Rcj**WO1UIe0;A@%RodhtVxIKi-@=XxGSHI%~aQX{U8ilVb|Y3_)guS z$gil*JgtDGhFi?Nr##!snJ6|^-M)Rx>YeKcXBu%MNs=A07aW2RO%+L~m=4$L3(^|& zK?`~J?nRoJwOmy9ao6E;^%(24ip(ER;lzIR8j5}lV9ZFCzI5lG0^Dc@Dbv%N%vPz~ z^PVLxS;A*!yja?4LCN;Seq2?1){}|l-x3TcSR@8k%PHcxb?44SDFp|PWv3@xX*sNj zv{}B+|J8g&l>cY3h#?kO)JSh;jmc=eOALUJJwsUZT`8KH!)UobKg&zWum8S2y!Q~@ znr+|0ijjwovDuU^K`oq&Kn&?~&T#pGydJUMp7tgdc} zm>NLKJu|Sz#jh(PbM%R`5$V(Q5Y^Znii3WA8JYKrJ-oeXaDRrbQ6#gP8Q7Syp@s9h z)DqPpalo%H;Pb6WJkEfUe4}TYH?PQsNn2FT5cM*gyi99=4dp*&?{O<|qOe*{Myp6L zq=v`JYUOSGv1@Rm7?n4e6l?_dYLo>@I2#Fx zUu9^^uuYDR#qPajD}Q~5GEF_+bnf_s$2^yEfBiGnu+dD{DT-O?&WSo_59)UfQ-fa3 z=k%>@E@vcS++7=sPZ`gNy&E0T^p0G`h_#$@pDUAIKnreK8J^JpJ<2B85O6T@i(*w;}OpmzqWLC7eDWX*rxIIrVn5 zO|kKbdJr$~9CKjEx$t^@9EIm!mS>e&;veH^WH8$iqN+=a*H#D^e7sXJLY93?ZK<5B z7o#r&Zo8V)RDcp6`(Ql$ph$n=6y>$%C5Ne}njS(mXyooba96Q#- zP)J}1o_f#lMn)(mv}gb)tZW`>N{{zqR!Sb?TQXGy2wl9=xye9bq-n#G&|+}#o;#PC zstEpzbMN2XRYZB$r^Zw<8kKE!@AhHise0X9Gm5TZM}dl%d%&sh(`!XJpN}26n8`KM zWxg$GLRPw>MO@M8{jS{`oQ8+$;BOFc%eX|&=vajAwn0MR&=`sery`}pu?RkqW7HRG znDxgRd^P*l4}ULNwvmU{JuMyiRFm!B-nL@Ha-G4N4aR*KAVk5&uA}Br6Zuw3id%=0 z*BG5FHx_-m(V6e+>P_4ymzBHIiR6qA8h#Qfqehy3U#BL;eXlI$;HZJ>g9^e6f;mIc z&cXd5nVGui_E!HYN(_o5f)I`6+&F6d4#mXJoN{V{_RhrlTxAq@ZeXp)Qtq=5>~s_b zC8d+lfXz9(i@(y+z8vlA8un9XY;0zx5t`FmEg$0iNx@K*6x@G1G%qhR)BgZXAm|6! zvavz`ojNsfQ-l#|vMg8uwWGfy@jh^}wNKUO1GjwKc%cCNXV@-XSYVX}t zKWdbP(-qsATen)$sW@DXA-A?x2?a+gvlvZ{%CN1l<+9tDvqUIjL^~6AmXSnRs4xZG z`-jo$zg3&C9y~B!UOJlT9~hzkOJk&?6SztI`qoU(F|~Skd!MgatNHNZc!6aNf5K0| zWQKl(l_#cHgM4FfXqg;(BuSAPI0MfOUyLL}qrybtmSApxEbnZl&j(JM*0i-9 zK78wzV$8$wmv5Kr-E=^SKL<0HPG)QTuu=xLJSNk>{~dgcYtb$)i2<7v_lj??J%V6o z7aKVh=cH^*JjHLd#7*5WQ(erREXN1#G7vfVGRdyfC<>Opw|2!5L*bnb z{RbX!XYwOV?(UO3btF#2vb6>x?UcpRN3<0aJw?|RmHCD=640#G2!LuDi`WDP(T_FK z9$gxw%NNOvg)$U6b*bFFv|)DBeL_S-4o>`5O8i>NC~?Q<+3tZK;xjBgN zL4oC?!n@}VH00h&sX45MXRed>Hu->@*TFy%Q8+s^#N@#hmNK|Q7DrjY9#3gnVKPqQ zKR?Et-W1ijOx01?_U9bT-teE*Gj^sb+B|J&dy+kWU5saPjey&!{tWJ^$2*y!sc&zq zIPzeL5{&071ir)u<;0w<>wI}?vWF^E1&=JONdC7w6vT7kdi`stP`_%7g+e=HvXsw= zAd97NB@B{(5UlE8Dq`btfo%4Q}|=ZEq-P^Jwq#1Ud`cB|u+#oR|o_worL$JpKF zy*$;AtcMNk={SBu+t)?^t!O3E!K>B-w|088ZP~K=YMI8zfD*S%ud1%zc_z>K-6Zcp z?Ht>C@V=n{+=RCSYZMWfBMGw8ZAjRdRw8c-`a?oi6;AkT20`@jrBWOg+tYEm>mtPo z({)jiGpZ4Ut_W&0;9p;2*G=+VKnY#rQL#d+rU%1tCG`4O*2p;e%yvrZwaHRAd{34u z7Pq&zb)0aL*ZSTZFM6|tKwLGQj(6{fM3A(op%GdPBGOLx!qFNWuVt{-)A-G);4pbP zGQJTn9*!Gp7tSz!NCReO2@}FIZ*NbD3tbI`Fe1=)rWU_^2?Y?}yVo$1FC^rXaRsF1 zdM(_&&V%d~UYLl+1i&23i9aTlPnOLz!0WcQS%p_ah~`pE)hd1_;M-+YpqP3qWgLsp zqnLF!m9=xtklKb9RN+3~7{%oV@ox4=z_`o_YiqcpcfNdjGRCpLDzV!GuOHA;5?M?o z6|k7q#?Wnq^NS4m$I`sKXX~B%-n{AWFG)&!x#N*WhMDo(G`{(tTT4&NKaQ$J0q2f(9_Ul+6vtuE-9g+Q&JTW!<_Nod%a!6;*cfzS}uGU&i4 z_|nxp^cCX--6 zs@g;$QvWRmZy>n?MJrckA*6r&lur{}ry zr2t~wHs6M7ltP}P1GO4VOPFn}@7Fk(;bS;Z$FK2gj^7zFKeSpU&KxnQrPu(y(69*b zz$yPnSBt$3qh-@|e2?fRrlbuDBAObm6`Usy3Un*`0oXtTOqQV!2z7wJ65x4PqWs%x zI2kmjPIbbkU@vIkpZT_fzA;uFgqLLk;QfJmDq|n#kvRYZa4*sRK1YIWf7&4P^us8h zm(0OmbBX#paU5K{<-*u_p>m#@%586${lvqoNi$p(vxV>hE5$plX_5>C#i?M0ju-lU z_!`8pAm88i?m4IKE$yC!XF8YsWHI^DTDwBV%LK?>fctbjsUF&8fKV(}KMovuKdO4} zA71%u`tcR00{|x~A07i4kfCvy(z3D_d!MRVB84pgZzC;C6y`0w)3O4U5Eezi6r}Dx zRV|<};cFw?vejVb)7A50Cy%0+ALa}Rc6)1+0=u3&oUR$kNX5vQo*=mMTpuZ(WG#+5 zk-wG3LEsI>d4G$Zo5;?d7pz&=6UIPN6k3ay-rh#W1>y(V^Z=4t?MY6(nDox|lbp?MgT2wLrJI5!s-rp;jZX(2#iR$=YJ!H+Tid3Dae?h0aA-M5ia1Us((kT9_TuM_Uze>A&!m#)Z$XA%*N)uH{1A+ z7H_EO({n{Z6Hj>U3dNg@(YZ3?BD^PIvJGkt3UW>qSBSzG=?|7dzKu4G$>}WFpfSTO z${!&0DH^gSgE#TH?2sbB;RwTlwO}J*n^PrtDN}>wfD&XVOj_53f*R`_=yRAr5gd7BD+mhOLW8gw$ zWN`jbtR_H_WSltFu&`dEO~kM%;1?U^fx4y6J80i93u%A830`e|`Lek9@v~=MMBmmO zF%^EN6#J47HHOroa=wAzqi#h9`&ha)Uu-U09>wem^ z=ci^xUTv)#HcB+U$kz%y>7m8U21&~?>;?%K3`u6Cz$>G;x!KvN7^N&?PznMV5XsZnS1el1s2Kz5= z2ni>z|Az_xxaA9$Vsio^;uZRH#uxN)?LIW32bn`At| zxk`t5`1qK16AYiX}(uCxhaH2(l8;1 zIHmHYa!wn#s|)!cL2)ikH#TN|2x}2O5Trp-L$&!of=GdB4+X8t4mTLa?RAy zC$2fZItC5j2|pFg&Gp*6rcjVEX}a=x>gL^XF+G><%{OZC0aE)f zvI-?=O5L`^R{1@j?ha_Y(;!)2^VB6)lXLhb8h_Gj*pCyx)X-d-075aX>s#tc~|%;XPv% z2d@3uS0$JN<5)6*8$-A(Ei;)+#q~bJhOt?>c;vUnZ+5#y`ZTlT)9|_`o~+xc@Kge1 zFk`=a)zyL8RHLjs3l0uLO)?QQ=401K#%q8;L9Uc?x9z(_CO3Qnbz#_Y;L;=}YFk?Y zcd69?Ci<}CF7ZmMe=jI21Dy)OzpkmSu8--fOa;$dytJ zv_1FGcqaMtwr4JalD`4YH1JU-iaBMhkXBEndI)GX+p+`z%lWL(&a*bLZc7kA@Vk!9 z_Vr2yUHnf?dtks9Sf@UBm7OkAbfX2NI(SjzVwgdQdO;^H&fNDDRx<}3=N=)K(yXHv z#`!1%Qq_NCCJ606YtZ^?y<3X$pyy+Ag)h)&MTIsqgNUL2=A5}C(2TXayUH&)EWE|r ze0896@6E47+<3P$*G98;KinWRW;{fRF>eqT-QCl696(f2+e~(N{u1=ts6HtMt*zE|wNPl2?&cwX=iVJuMt=lo&T-f|C=K0t09s{*a ztpFqn4>H%8$u_<|+GwN>`V=h1zf-Q5T=!BUBBs9RB|x3croWa(v&=^SK*mk*G0GRk z3J%Q5Qn_e0eMj`@mxgFAH@<#}TNQ}(-R9fP>@BtkONf?pT@UtXgLDQUSI3UNcmZf# zUMUilqyd3`{V-zC(FrA~)5b+l-~NWB2yecn0@lfy4S2jzI6qg96wHnrkar3vd+%-| zO6HhZPXP~aDGO|NatrRc48rmlb^@p;L%W9laIg@kNgG4I{f0xOs+tVc?cOBdRlE#r zxsSE{R*JyXiQ19J=SEfcCma>Y5q*_Rgqn1+0t-WryiYY~n6-fcj&xq2W)TY5-EH4> z(J4kR|1(XSdsn|~WO!k|Jgfop(i5O)K}7c$!9Ya(B20O`RlhKI>(VnzhikZT^_Sme z8v|!z@slk~?l0!))IENpH})&oz~CNQ?ski!z`g0GsgXSZV!BIHfmaVbxf`dt7OV|F z+WcJhX$GB=>~5R!Ax}P7Bl2{1@n1XUx`J)DIS%p+>Y z0gM3v`rUbVXj(6dGxc3xeLuX%0WG*&bKM#~2u=u<;Seb$y|xE z!tR~Wy>9Ur*Z6s_CAhB;x$N1tg56lj3u{2}gC)c$b&P_t)R6l28A~asEF7 zeE1o^t8ePBt1SJ_M6MLYe13sxEsEa)b}T>8G;!tUQdacu$@(yN;2-G5=YxA(R$gx9 z^Q?TK?^!+D(g54NoUgwT^aTbF10%B16-h8{t2n_h+3dRawrnz9#&iQw;X!>Wh%`Y444+E8QT!xZa`r$U1q}{)ZU%eYlHPROiv^Oj~`#nF7^bZcnRa%O<;ouJQ>JB}{VOWE&g#e#qJ!;@EAirteD6;Ogy5@`Pob0;0Qx zWa9F47v}nv-*ZVgMBf@auZWEWyn^qkW+no|POy%P5!=vOTj4kM?CA}_SD!7YMgoXz zO`5%Bji`ORlVjsqe+2%uzX@F-=LiDHazK@GrUpS8^SqS#;?=9CKf*7aEJ#c&&qQ|0 zkAN6Gem!KXFr0}J<#^7&^#i$cEv>x423I2TP;c_y5@SLrPYiHkfX}{*$8gQw#Zx71 zt#|pXt_P>7$-7$sW^iT$_>Mp+^Etl7MR<_W+6Hb&7OL}E69=V~*VYpBgZsZXy7U?Z z(#iT?eRb?uFvsqfU(R+s`bB%&7L98^*ONig9Y#rv3X3NE%*|-2oGeTr`kn1)zIRI{ z-p$cC2HB5HJF(Bbc6`dg$;p!}pf0oemzZA|SVZsRSL1Q_M(?+fP@Llr9$RBgbm7Qm z?{clO%GoI*w_UZSTv$fU*sp4mKGCfQ|Ih;mP9qaY71yp+QA>fGTcc*Fn6Do4?tbyj z=Fzsh)XbK~`y|_yvrfMLJ{a#-l0Rn*x4OxdX`sa zgZ*Nnb~fysxX3XCAedC9S(<;~2lz*S#R5DqNg^pP2bFtUtu;+&$MRLy zudDH+y}8AqkfRF4LxBV)>7VS?F6`vj zZ-x>o2Vb9ac6J{Ss|uWb40}~|=H^7BP05hR$by2Li9;s~onAJ>AN5w=ym?QD17ebo zbrIp#Cv-PQ^n~&~&TWE5efQnN&~yD`oo;9}V1P{9z{fitHP;8P1M`dN(6;~m)si>6 z(h|(9_UdV&kqfh_#l?m8Scu!FaWDxe8Qvjt6O$=ne#;&)Vc)^X8L6NGpV{GP zxwnC*ySu-C|0@TVg}wj*uki8ZC6eG7MyZ3{X<<72?2Td_ZK>E;(Lr2jp zf>)p2>*%5mZD00vUIl$z;XPJex#r*S_(z##WF%Osx2#1r&0q?bLk_%n;lk^`V|@6+ z`9{?(ZD3V+L%pAZM4d*B?JeF84(23pLl{gZGs>zy_}jZU$KtC2OoAoBH!>2yUc9ZC zUD3&)iJff0Kj?giS~LX+mdj=%0rU?|0h{{WEk{+};W? zz6t=Z`1KYO&#Q-?MS9s@w}@J|b31f{s+OVz(NtqRH<)u_7}X3Z!mla}?D2YX94j*R3?Txo9QvB^~sza+Zck9KQsx>Zz9mgKJ{F5 z%^A3Nzu~KF@W)=0A{8M>(rzc~(*>Y0WAplyQMrCl=D<+eugTj%d)#_+9v#pTwspRC z^~%bsp`X$xn9xBMqr{bDj$SM;hYtQ>VK%(503E#JX%G0dGU}_#KxPhz!fhK?qmMtu@W(U%gAb zYrTK3x}`ZB+2UO;ySXW$n*7bb=F*Ll^c5b%URc%#_`@r`spbBvs#=(OUpoMX&CM|p zS|NM88vyUPG^DWe{Xd^|mQq1)P)&d=;w)FMxov*wwG-L&+NEaTip3vybPV@83W{L4 ziw;tfw;CJcVm3iTX2&adr2}>G=7Bu`=ijjzfPMiCk`fI_kcTFK!ADL^u){K1fLjr9 z=Et;#Xg{oPTXyy1{EC1p7b~Av9vY@lYHI;P1z=ShtVaXj1?O2xlw`o#qajK-EERF) z%6>a07H->0;lY-4Jx`vbc7mFy@87fe_#%I%W%enGs#Q}HP}4&bfd&OMFxmPZzUW*% z^G2o6Zf#AG|LBLlK0BC~IVmnK%Lul3V0epO`SsQgU#==-5FP#ICKBb#72E1^Cqp|mIYZ~F5eM9 z!!|RWa@oObR-c=$gJTt7xb!ZV%V%FWYJ(L)BwK()1VHE3@yQAvj8<~8kT(I;LLLnZ z0xH;=sLXO!e(C;2a^)-*lLR>wHCsJ=-$Jsk=Fua2Ty=+6*Yi$b+F*SEAzZ5FyFRkF z+!dYxxqPmOLZKMcMgd11>IJ*z>qEbX-V;eEp-6nQ3gqYgW!+c6k!r<>N& z7~nnhRz(vzUXYrT4dkiti~jC=w?G?bCyYb9v6^6){rlCy`A_-O=VycS!6GVwR)_9t z@m4B;OJMHZe9wlWy1(fBFK<%J!uv(WEK;$PeXcs$(p1S?_Hu5t{jw6bAdf3DG9ta$ zvaaq1;rlxNlFaqkvHm|h$jZy{z=LhJh+Yq&7dtIpY4NtUJ`unGBAx#2=Pro59KfC- z@hJNtS24M^zpL_UcOfpW-n*rQNbkDsc0P3Mv5rk#e<5wUPQup$4(+a8!8#`lv)ehDGhKL65#B(r7_Xe<@RHb5uAZY^^m9 zKC!_*w!Ur=`29Aa2xL|Ots~H@e6o$`+cO*&*VmV>XANrl3pgya*>HV5h2mylZL>1M zWKS)NL_Ruy5srVxb=G;FC}976!%}<$Sgob408qn)omEwk!?!1|EF1l6zsD=XGQ{Ak zk6jNyuECj~xxnCE8@l-wKrW*O!h+%ZM>Z{YUo2N+(0_3~OSbOk(<4x&mFW1t=>mHm zei=kQrEmS0Z3N}EZC1`j+$r6(tW)z=i`NTh-qY0)B3Y)>J8=2~@LFEU?H@YyrTqaaYD} z=6x|K+jK#igV9gxU69aHEPtqy2o6h3TIiL>T$wPaSW#0DR%P_CU6(;UvC8zg4OuH_ zTB5>-x!d}gv3mPC{yatRpdfIX&*~46%W4T|9Pd$?++4kDMDq}*8tsO+noB+il#QCYWt0un0=v(-tB~IR9#x`>y-z?I1IsnC$ z;paNMS!P+2fg&lvQZYF~^JZ^^vg%ws%IJ$7eV7I$*Tt(OfTU6xlu*HtQ1~4gT*MTe z(Do{w*PG2W)#;(6AcATrW%7#ahy}C0S_DE~krp~Th~rrhjHghTvB~J8(_EY0S>x`K z0di1&P!Oe!-oD%PH`PjC(ey!mB6alPW&i86yy^m+Qe^H?>gSBWr{oR&#NZg`_Yk~V zX>nEK4J8$Aj6u3_m%wjrNrQ|yC8kqYin+3J8-%j#X;3S<0PCSo+v+mNsW5P-KD0wj z<4zowB*oOwyZ!zi#78p4S85cY#TChZt@{O(43d7p_v!B~pNw*Mr$t6;b4PZi6`fy< zDLOBnDmot%E$SC?sVRA@F`eAaIh@YE(!m{_9aM=Mc{L*HkVb$l#GgtupMm zU$lN`BMV0G(|}JB#4+fqGP2DT8f_bHL|U7j0*`5#w*d_bfdU_4ek7s4*T#+R~r<|W8 zyC3Xc{I)bDW}42mK`?dDd3yEC7e=%*9a*Ic8I@B--`+*n8-{YX4CHtn?@!Tm@atoR zXfvEX66tsD$rYWXhA=Ouj|88snmFE%G6~8p%WvRvaa?Yi-4waRm_(3w_eB+QpCJZ9y{7!6 zk(K&>t02*fgwk7XdCHi)xy}V0g5P3}WWK7#FO>Dkh(eT0O;o1>6l5Oo|zTmw;Xdx>#<;8fpWPfr<*;TAw+^$m6n z3W###A2M1#VG?;=o-i>gmlknknWn-zCcdJf?xSUHaC9hPN7wJAZwifHbGv&nuut7p z5=oFg2GUC>=Z%e#iPQ63qFRuP4Vg-;(tfH>lQ^Scq%!WDe#L+!-icpvLMetL4ho)!*!JaM7?Y1Y5$c&|?=vy)TFQn0kfy zfS*-{2MiDCA2ifI2t9wm*!0i=(}PBO2M(AXI1uoa_Rznb5QOmd_l^ADPf)*@7RE9^$+s79(p Date: Thu, 24 Apr 2025 19:33:45 -0600 Subject: [PATCH 5/6] Added the ocre_runtime api, as well as re-organized the API structure in the references section. --- .../{ => apis}/container-api/gpio.md | 2 +- docs/reference/apis/container-api/index.md | 23 + .../{ => apis}/container-api/sensors.md | 2 +- .../{ => apis}/container-api/timers.md | 2 +- docs/reference/apis/index.md | 27 + docs/reference/apis/runtime-api/index.md | 667 ++++++++++++++++++ docs/reference/container-api/index.md | 26 - 7 files changed, 720 insertions(+), 29 deletions(-) rename docs/reference/{ => apis}/container-api/gpio.md (99%) create mode 100644 docs/reference/apis/container-api/index.md rename docs/reference/{ => apis}/container-api/sensors.md (99%) rename docs/reference/{ => apis}/container-api/timers.md (99%) create mode 100644 docs/reference/apis/index.md create mode 100644 docs/reference/apis/runtime-api/index.md delete mode 100644 docs/reference/container-api/index.md diff --git a/docs/reference/container-api/gpio.md b/docs/reference/apis/container-api/gpio.md similarity index 99% rename from docs/reference/container-api/gpio.md rename to docs/reference/apis/container-api/gpio.md index b8ec343..2b30d64 100644 --- a/docs/reference/container-api/gpio.md +++ b/docs/reference/apis/container-api/gpio.md @@ -1,7 +1,7 @@ --- title: GPIO layout: default -parent: Container APIs +parent: Container has_toc: false --- diff --git a/docs/reference/apis/container-api/index.md b/docs/reference/apis/container-api/index.md new file mode 100644 index 0000000..2a60f0f --- /dev/null +++ b/docs/reference/apis/container-api/index.md @@ -0,0 +1,23 @@ +--- +title: Container +layout: default +parent: APIs +has_toc: false +--- +# Container APIs + +Container APIs provide direct interfaces for containers to efficiently interact with underlying system resources and capabilities. Designed with simplicity, security, and consistency in mind, these APIs follow well-defined patterns to facilitate ease of use and seamless integration. + +--- + +## Available APIs + +Below are the core APIs available for Ocre containers. Each API includes detailed documentation with usage examples, error handling patterns, and best practices. + +### System Interaction + +| API | Description | +|-----|-------------| +| **[GPIO](gpio)** | Control digital pins for input/output operations with hardware peripherals and external components | +| **[Sensors](sensors)** | Interface with hardware sensors for environmental and motion data | +| **[Timers](timers)** | Create and manage timed events with millisecond precision | \ No newline at end of file diff --git a/docs/reference/container-api/sensors.md b/docs/reference/apis/container-api/sensors.md similarity index 99% rename from docs/reference/container-api/sensors.md rename to docs/reference/apis/container-api/sensors.md index 54e9fd0..144ea21 100644 --- a/docs/reference/container-api/sensors.md +++ b/docs/reference/apis/container-api/sensors.md @@ -1,7 +1,7 @@ --- title: Sensors layout: default -parent: Container APIs +parent: Container --- # Sensors diff --git a/docs/reference/container-api/timers.md b/docs/reference/apis/container-api/timers.md similarity index 99% rename from docs/reference/container-api/timers.md rename to docs/reference/apis/container-api/timers.md index eb31977..6a5b3b3 100644 --- a/docs/reference/container-api/timers.md +++ b/docs/reference/apis/container-api/timers.md @@ -1,7 +1,7 @@ --- title: Timers layout: default -parent: Container APIs +parent: Container --- # Timers diff --git a/docs/reference/apis/index.md b/docs/reference/apis/index.md new file mode 100644 index 0000000..109e77c --- /dev/null +++ b/docs/reference/apis/index.md @@ -0,0 +1,27 @@ +--- +title: APIs +layout: default +parent: Reference +has_toc: false +--- + +# APIs + +This page provides an overview of the Application Programming Interfaces (APIs) available in the Ocre platform. These APIs allow developers to interact with various features of the Ocre runtime and create containerized applications. + +--- + +## Overview + +Ocre provides *two* primary categories of APIs: + +1. **[Container APIs:](../apis/container-api)** APIs that are accessible from within containers and allow applications to interact with hardware, timers, and other system resources. These are designed for application developers building solutions that will run within Ocre containers. + +2. **[Runtime API:](../apis/runtime-api)** The API for managing the Ocre runtime environment itself, including container lifecycle operations. The Runtime API is intended for system implementors and integrators looking to incorporate the Ocre runtime into their own solutions. + + +--- + +## Next Steps + +Check out some of the the [Sample Applications](../../samples) for practical examples using these APIs \ No newline at end of file diff --git a/docs/reference/apis/runtime-api/index.md b/docs/reference/apis/runtime-api/index.md new file mode 100644 index 0000000..5af432a --- /dev/null +++ b/docs/reference/apis/runtime-api/index.md @@ -0,0 +1,667 @@ +--- +title: Runtime +layout: default +parent: APIs +has_toc: false +--- + +# Runtime API +{: .no_toc } + +The Ocre Runtime API enables full container lifecycle management and can be integrated into various environments including real-time operating systems ([Zephyr](https://zephyrproject.org/), [FreeRTOS](https://www.freertos.org/)), Linux-based platforms (including [Yocto](https://www.yoctoproject.org/)), or custom firmware implementations. With these interfaces, platform developers can initialize the runtime, deploy containers, monitor their execution, and control their operation throughout the system lifecycle. + +--- + +## Table of Contents +{: .no_toc } + +Navigate this comprehensive API reference using the links below. + +
+ + Click to expand + + {: .text-delta } +1. TOC +{:toc} +
+ +--- + +## Header File + +```c +#include "ocre_container_runtime.h" +``` + +--- + +## Types + +### Runtime Status + +An enumeration defining the possible states of the container runtime. + +```c +typedef enum { + RUNTIME_STATUS_UNKNOWN, ///< Status is unknown. + RUNTIME_STATUS_INITIALIZED, ///< Runtime has been initialized. + RUNTIME_STATUS_DESTROYED, ///< Runtime has been destroyed. + RUNTIME_STATUS_ERROR ///< An error occurred with the runtime. +} ocre_container_runtime_status_t; +``` + +### Container Status + +An enumeration defining the possible states of a container. + +```c +typedef enum { + CONTAINER_STATUS_UNKNOWN, ///< Status is unknown. + CONTAINER_STATUS_CREATED, ///< Container has been created. + CONTAINER_STATUS_RUNNING, ///< Container is currently running. + CONTAINER_STATUS_STOPPED, ///< Container has been stopped. + CONTAINER_STATUS_DESTROYED, ///< Container has been destroyed. + CONTAINER_STATUS_UNRESPONSIVE, ///< Container is unresponsive (used with health checks). + CONTAINER_STATUS_ERROR, ///< An error occurred with the container. +} ocre_container_status_t; +``` + +### Container Permissions + +An enumeration defining the permission types for containers. + +```c +typedef enum { + OCRE_CONTAINER_PERM_READ_ONLY, ///< Container has read-only permissions. + OCRE_CONTAINER_PERM_READ_WRITE, ///< Container has read and write permissions. + OCRE_CONTAINER_PERM_EXECUTE ///< Container has execute permissions. +} ocre_container_permissions_t; +``` + +{: .note } +Not currently used. + +### Runtime Arguments + +A structure containing the runtime arguments for a container runtime. + +```c +typedef struct ocre_runtime_arguments_t { + uint32_t size; ///< Size of the buffer. + char *buffer; ///< Pointer to the buffer containing the WASM module. + char error_buf[128]; ///< Buffer to store error messages. + wasm_module_t module; ///< Handle to the loaded WASM module. + wasm_module_inst_t module_inst; ///< Handle to the instantiated WASM module. + wasm_function_inst_t func; ///< Handle to the function to be executed within the WASM module. + wasm_exec_env_t exec_env; ///< Execution environment for the WASM function. + uint32_t stack_size; ///< Stack size for the WASM module. + uint32_t heap_size; ///< Heap size for the WASM module. +} ocre_runtime_arguments_t; +``` + +### Container Data + +A structure representing the data associated with a container. All fields must be initialized to avoid undefined behavior. + +```c +typedef struct ocre_container_data_t { + char name[16]; ///< Name of the module (must be unique per installed instance). + char sha256[70]; ///< SHA-256 hash of the WASM file, used to construct the file path (e.g., /lfs/ocre/images/.bin). + uint32_t stack_size; ///< Stack size for the WASM module. + uint32_t heap_size; ///< Heap size for the WASM module. + ocre_healthcheck WDT; ///< Watchdog timer for container health checking (set to NULL if unused). + int watchdog_interval;///< Watchdog interval in milliseconds (set to 0 if unused). + int timers; ///< Number of timers allocated for the container (set to 0 if unused). +} ocre_container_data_t; +``` + +### Container Init Arguments + +A structure with initialization arguments for the container runtime. + +```c +typedef struct ocre_container_runtime_init_arguments_t { + uint32_t default_stack_size; ///< Default stack size for WASM modules. + uint32_t default_heap_size; ///< Default heap size for WASM modules. + int maximum_containers; ///< Maximum number of containers allowed (must not exceed MAX_CONTAINERS). + NativeSymbol *ocre_api_functions; ///< Pointer to an array of host functions for WASM modules (set to NULL for defaults). +} ocre_container_init_arguments_t; +``` + +### Container + +A structure representing a container in the runtime. + +```c +typedef struct ocre_container_t { + ocre_runtime_arguments_t ocre_runtime_arguments; ///< Runtime arguments for the container. + ocre_container_status_t container_runtime_status; ///< Current status of the container. + ocre_container_data_t ocre_container_data; ///< Container-specific data. +} ocre_container_t; +``` + +### Container Runtime Context + +An opaque structure used internally by the runtime. Do not modify directly. + +```c +typedef struct ocre_cs_ctx { + ocre_container_t containers[MAX_CONTAINERS]; + int current_container_id; + int download_count; +} ocre_cs_ctx; +``` + +### Container Runtime Callback + +A function prototype for container runtime callbacks, invoked when a container operation completes (e.g., creation, running). + +```c +typedef void (*ocre_container_runtime_cb)(void); +``` + +--- + +## Methods + +### Runtime Initialization + +Initializes the container runtime environment. Blocks until the runtime is initialized or an error occurs. + +```c +ocre_container_runtime_status_t ocre_container_runtime_init(ocre_cs_ctx *ctx, ocre_container_init_arguments_t *args); +``` + +**Parameters**: + +| Name | Type | Description | +| ------ | ------ | ----------- | +| `ctx` | *ocre_cs_ctx* * | Pointer to the container runtime context structure | +| `args` | *ocre_container_init_arguments_t* * | Pointer to the runtime arguments structure, with initialized fields | + +**Returns**: + +| Value | Description | +| ------ | ----------- | +| `RUNTIME_STATUS_INITIALIZED` | Runtime successfully initialized | +| `RUNTIME_STATUS_ERROR` | Failed to initialize runtime | + +### Runtime Destruction + +Destroys the container runtime environment. Blocks until the runtime is destroyed. + +```c +ocre_container_status_t ocre_container_runtime_destroy(void); +``` + +**Returns**: + +| Value | Description | +| ------ | ----------- | +| `RUNTIME_STATUS_DESTROYED` | Runtime successfully destroyed | + +### Create Container + +Creates a new container within the runtime, loading the WASM module specified by `container_data.sha256`. + +```c +ocre_container_status_t ocre_container_runtime_create_container(ocre_cs_ctx *ctx, + struct ocre_container_data_t *container_data, + int *container_id, ocre_container_runtime_cb callback); +``` + +**Parameters**: + +| Name | Type | Description | +| ------ | ------ | ----------- | +| `ctx` | *ocre_cs_ctx* * | Pointer to the container runtime context structure | +| `container_data` | *ocre_container_data_t* * | Pointer to the container data structure, with all fields initialized | +| `container_id` | *int* * | Pointer to receive the assigned container `ID` | +| `callback` | *ocre_container_runtime_cb* | Optional callback function invoked when the container is created (set to `NULL` if unused) | + +**Returns**: + +| Value | Description | +| ------ | ----------- | +| `CONTAINER_STATUS_CREATED` | Container successfully created | +| `CONTAINER_STATUS_ERROR` | Failed to create container (e.g., no available slots, invalid WASM module) | + +### Run Container + +Executes a specific container. + +```c +ocre_container_status_t ocre_container_runtime_run_container(ocre_cs_ctx *ctx, int container_id, + ocre_container_runtime_cb callback); +``` + +**Parameters**: + +| Name | Type | Description | +| ------ | ------ | ----------- | +| `ctx` | *ocre_cs_ctx* * | Pointer to the container runtime context structure | +| `container_id` | *int* | The container `ID` to run | +| `callback` | *ocre_container_runtime_cb* | Optional callback function invoked when the container starts (set to `NULL` if unused) | + +**Returns**: + +| Value | Description | +| ------ | ----------- | +| `CONTAINER_STATUS_RUNNING` | Container successfully started | +| `CONTAINER_STATUS_ERROR` | Failed to run container (e.g., invalid container `ID`) | + +### Get Container Status + +Retrieves the current status of a specific container. + +```c +ocre_container_status_t ocre_container_runtime_get_container_status(ocre_cs_ctx *ctx, int container_id); +``` + +**Parameters**: + +| Name | Type | Description | +| ------ | ------ | ----------- | +| `ctx` | *ocre_cs_ctx* * | Pointer to the container runtime context structure | +| `container_id` | *int* | The container `ID` to check | + +**Returns**: + +| Value | Description | +| ------ | ----------- | +| The current status of the specified container | Success | +| `CONTAINER_STATUS_ERROR` | Invalid container `ID` | + +### Stop Container + +Stops a running container. + +```c +ocre_container_status_t ocre_container_runtime_stop_container(ocre_cs_ctx *ctx, int container_id, + ocre_container_runtime_cb callback); +``` + +**Parameters**: + +| Name | Type | Description | +| ------ | ------ | ----------- | +| `ctx` | *ocre_cs_ctx* * | Pointer to the container runtime context structure | +| `container_id` | *int* | The container `ID` to stop | +| `callback` | *ocre_container_runtime_cb* | Optional callback function invoked when the container stops (set to `NULL` if unused) | + +**Returns**: + +| Value | Description | +| ------ | ----------- | +| `CONTAINER_STATUS_STOPPED` | Container successfully stopped | +| `CONTAINER_STATUS_ERROR` | Failed to stop container | + +### Destroy Container + +Destroys and unloads a container from the runtime. + +```c +ocre_container_status_t ocre_container_runtime_destroy_container(ocre_cs_ctx *ctx, int container_id, + ocre_container_runtime_cb callback); +``` + +**Parameters**: + +| Name | Type | Description | +| ------ | ------ | ----------- | +| `ctx` | *ocre_cs_ctx* * | Pointer to the container runtime context structure | +| `container_id` | *int* | The container `ID` to destroy | +| `callback` | *ocre_container_runtime_cb* | Optional callback function invoked when the container is destroyed (set to `NULL` if unused) | + +**Returns**: + +| Value | Description | +| ------ | ----------- | +| `CONTAINER_STATUS_DESTROYED` | Container successfully destroyed | +| `CONTAINER_STATUS_ERROR` | Failed to destroy container | + +### Restart Container + +Restarts a running container. + +```c +ocre_container_status_t ocre_container_runtime_restart_container(ocre_cs_ctx *ctx, int container_id, + ocre_container_runtime_cb callback); +``` + +**Parameters**: + +| Name | Type | Description | +| ------ | ------ | ----------- | +| `ctx` | *ocre_cs_ctx* * | Pointer to the container runtime context structure | +| `container_id` | *int* | The container `ID` to restart | +| `callback` | *ocre_container_runtime_cb* | Optional callback function invoked when the container restarts (set to `NULL` if unused) | + +**Returns**: + +| Value | Description | +| ------ | ----------- | +| Current status of the container | Success (typically `CONTAINER_STATUS_RUNNING`) | +| `CONTAINER_STATUS_ERROR` | Failed to restart container | + +--- + +## Error Handling + +The Runtime API functions return status codes that indicate the success or failure of operations. These codes, defined in `ocre_container_runtime_status_t` and `ocre_container_status_t`, allow developers to monitor the state of the runtime and containers. The following table summarizes the key status codes and their meanings: + +| Value | Description | +|----------|-------------| +| `RUNTIME_STATUS_INITIALIZED` | Runtime was successfully initialized | +| `RUNTIME_STATUS_ERROR` | An error occurred in the runtime (e.g., initialization failure) | +| `RUNTIME_STATUS_DESTROYED` | Runtime was successfully destroyed | +| `CONTAINER_STATUS_CREATED` | Container was successfully created | +| `CONTAINER_STATUS_RUNNING` | Container is running | +| `CONTAINER_STATUS_STOPPED` | Container was successfully stopped | +| `CONTAINER_STATUS_DESTROYED` | Container was successfully destroyed | +| `CONTAINER_STATUS_ERROR` | Invalid container `ID`, invalid WASM module, or other error | + +To handle these status codes effectively, check the return value of each API call and take appropriate action based on the result. For example, when querying a container's status, use a switch statement to interpret the status and respond accordingly: + +```c +// Check the container status +ocre_container_status_t status = ocre_container_runtime_get_container_status(&ctx, container_id); +switch (status) { + case CONTAINER_STATUS_RUNNING: + printf("Container is running\n"); + break; + case CONTAINER_STATUS_STOPPED: + printf("Container is stopped\n"); + break; + case CONTAINER_STATUS_ERROR: + printf("Container is in an error state\n"); + break; + default: + printf("Container is in state: %d\n", status); + break; +} +``` + +--- + +## Examples + +### Initializing the Runtime + +This example demonstrates initializing the Ocre runtime with specified stack and heap sizes. + +```c +#include +#include + +int main() { + ocre_cs_ctx ctx; + ocre_container_init_arguments_t args = {0}; // Zero-initialize to avoid undefined behavior + + // Set up initialization arguments + args.default_stack_size = 8192; // 8 KB stack size + args.default_heap_size = 16384; // 16 KB heap size + args.maximum_containers = 5; // Allow up to 5 containers + args.ocre_api_functions = NULL; // Use default WebAssembly host functions + + // Initialize the Ocre runtime + ocre_container_runtime_status_t ret = ocre_container_runtime_init(&ctx, &args); + + if (ret == RUNTIME_STATUS_INITIALIZED) { + printf("Ocre runtime initialized successfully\n"); + // Continue with container creation and operation... + } else { + printf("Failed to initialize runtime: %d\n", ret); + return -1; + } + + // Clean up + ocre_container_runtime_destroy(); + return 0; +} +``` + +### Creating and Running a Container + +This example creates a container from a (minimal valid) WebAssembly module, runs it, and performs cleanup. It includes error handling and proper initialization. + +```c +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(ocre_example, LOG_LEVEL_INF); + +int create_sample_container(char *file_name) { + struct fs_file_t f; + char file_path[64]; + int res; + + snprintf(file_path, sizeof(file_path), "/lfs/ocre/images/%s.bin", file_name); + + fs_file_t_init(&f); + res = fs_open(&f, file_path, FS_O_CREATE | FS_O_RDWR); + if (res < 0) { + LOG_ERR("Failed to open file %s: %d", file_path, res); + return res; + } + + // Minimal valid WASM module (no-op, 45 bytes) + unsigned char wasm_binary[] = { + 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, // WASM header + 0x01, 0x04, 0x01, 0x60, 0x00, 0x00, // Type section: () -> () + 0x03, 0x02, 0x01, 0x00, // Function section: one function + 0x07, 0x07, 0x01, 0x03, 0x72, 0x75, 0x6E, 0x00, 0x00, // Export "run" + 0x0A, 0x04, 0x01, 0x02, 0x00, 0x0B // Code section: empty function + }; + + res = fs_write(&f, wasm_binary, sizeof(wasm_binary)); + if (res != sizeof(wasm_binary)) { + LOG_ERR("Failed to write WASM binary: %d", res); + fs_close(&f); + return -EIO; + } + + res = fs_close(&f); + if (res < 0) { + LOG_ERR("Failed to close file %s: %d", file_path, res); + return res; + } + + return 0; +} + +int main(int argc, char *argv[]) { + ocre_cs_ctx ctx; + ocre_container_init_arguments_t args = {0}; + char *container_filename = "hello"; + int ret; + + // Initialize storage + ret = ocre_app_storage_init(); + if (ret < 0) { + LOG_ERR("Failed to initialize storage: %d", ret); + return ret; + } + + // Create WASM container image + ret = create_sample_container(container_filename); + if (ret < 0) { + LOG_ERR("Failed to create container image"); + return ret; + } + + // Initialize runtime + args.default_stack_size = 8192; + args.default_heap_size = 16384; + args.maximum_containers = 5; + args.ocre_api_functions = NULL; + + ocre_container_runtime_status_t status = ocre_container_runtime_init(&ctx, &args); + if (status != RUNTIME_STATUS_INITIALIZED) { + LOG_ERR("Ocre runtime failed to start: %d", status); + return -1; + } + + // Create container + ocre_container_data_t container_data = {0}; + int container_id; + ocre_container_runtime_cb callback = NULL; + + container_data.heap_size = 16384; + container_data.stack_size = 8192; + snprintf(container_data.name, sizeof(container_data.name), "Hello World"); + // Note: In production, compute SHA-256 hash of the WASM file + snprintf(container_data.sha256, sizeof(container_data.sha256), "%s", container_filename); + container_data.timers = 0; + container_data.watchdog_interval = 0; + container_data.WDT = NULL; + + status = ocre_container_runtime_create_container(&ctx, &container_data, &container_id, callback); + if (status != CONTAINER_STATUS_CREATED) { + LOG_ERR("Failed to create container: %d", status); + ocre_container_runtime_destroy(); + return -1; + } + + // Run container + status = ocre_container_runtime_run_container(&ctx, container_id, callback); + if (status != CONTAINER_STATUS_RUNNING) { + LOG_ERR("Failed to run container: %d", status); + ocre_container_runtime_destroy_container(&ctx, container_id, NULL); + ocre_container_runtime_destroy(); + return -1; + } + + // Monitor for 10 seconds + for (int i = 0; i < 10; i++) { + status = ocre_container_runtime_get_container_status(&ctx, container_id); + LOG_INF("Container status: %d", status); + if (status == CONTAINER_STATUS_ERROR) { + break; + } + k_msleep(1000); + } + + // Clean up + status = ocre_container_runtime_stop_container(&ctx, container_id, NULL); + if (status != CONTAINER_STATUS_STOPPED) { + LOG_ERR("Failed to stop container: %d", status); + } + + status = ocre_container_runtime_destroy_container(&ctx, container_id, NULL); + if (status != CONTAINER_STATUS_DESTROYED) { + LOG_ERR("Failed to destroy container: %d", status); + } + + ocre_container_runtime_destroy(); + return 0; +} +``` + +### Container Lifecycle Management + +This example demonstrates the full container lifecycle, including creation, running, stopping, and destruction. + +```c +#include +#include +#include + +LOG_MODULE_REGISTER(ocre_lifecycle, LOG_LEVEL_INF); + +int main() { + ocre_cs_ctx ctx; + ocre_container_init_arguments_t args = {0}; + + // Initialize runtime + args.default_stack_size = 8192; + args.default_heap_size = 16384; + args.maximum_containers = 5; + args.ocre_api_functions = NULL; + + ocre_container_runtime_status_t ret = ocre_container_runtime_init(&ctx, &args); + if (ret != RUNTIME_STATUS_INITIALIZED) { + LOG_ERR("Failed to initialize runtime: %d", ret); + return -1; + } + + // Create container + ocre_container_data_t container_data = {0}; + int container_id; + container_data.heap_size = 16384; + container_data.stack_size = 8192; + snprintf(container_data.name, sizeof(container_data.name), "Sample"); + snprintf(container_data.sha256, sizeof(container_data.sha256), "sample"); + container_data.timers = 0; + container_data.watchdog_interval = 0; + container_data.WDT = NULL; + + ocre_container_status_t status = ocre_container_runtime_create_container( + &ctx, &container_data, &container_id, NULL); + if (status != CONTAINER_STATUS_CREATED) { + LOG_ERR("Failed to create container: %d", status); + ocre_container_runtime_destroy(); + return -1; + } + + // Run container + status = ocre_container_runtime_run_container(&ctx, container_id, NULL); + if (status != CONTAINER_STATUS_RUNNING) { + LOG_ERR("Failed to run container: %d", status); + ocre_container_runtime_destroy_container(&ctx, container_id, NULL); + ocre_container_runtime_destroy(); + return -1; + } + + // Wait and check status + k_msleep(5000); + status = ocre_container_runtime_get_container_status(&ctx, container_id); + LOG_INF("Container status after 5 seconds: %d", status); + + // Stop container + status = ocre_container_runtime_stop_container(&ctx, container_id, NULL); + if (status != CONTAINER_STATUS_STOPPED) { + LOG_ERR("Failed to stop container: %d", status); + } + + // Destroy container + status = ocre_container_runtime_destroy_container(&ctx, container_id, NULL); + if (status != CONTAINER_STATUS_DESTROYED) { + LOG_ERR("Failed to destroy container: %d", status); + } + + // Shutdown runtime + ocre_container_runtime_destroy(); + return 0; +} +``` + +--- + +## Reference + +| Function | Description | Parameters | Return Value | Error Codes | +|----------|-------------|------------|--------------|--------------| +| [`ocre_container_runtime_init`](#runtime-initialization) | Initializes the runtime | `ctx`: Runtime context
`args`: Init arguments | Runtime status | `RUNTIME_STATUS_ERROR` | +| [`ocre_container_runtime_destroy`](#runtime-destruction) | Destroys the runtime | None | Runtime status | None | +| [`ocre_container_runtime_create_container`](#create-container) | Creates a container | `ctx`: Runtime context
`container_data`: Container config
`container_id`: Receives `ID`
`callback`: Optional callback | Container status | `CONTAINER_STATUS_ERROR` | +| [`ocre_container_runtime_run_container`](#run-container) | Runs a container | `ctx`: Runtime context
`container_id`: Container `ID`
`callback`: Optional callback | Container status | `CONTAINER_STATUS_ERROR` | +| [`ocre_container_runtime_get_container_status`](#get-container-status) | Gets container status | `ctx`: Runtime context
`container_id`: Container `ID` | Container status | `CONTAINER_STATUS_ERROR` | +| [`ocre_container_runtime_stop_container`](#stop-container) | Stops a container | `ctx`: Runtime context
`container_id`: Container `ID`
`callback`: Optional callback | Container status | `CONTAINER_STATUS_ERROR` | +| [`ocre_container_runtime_destroy_container`](#destroy-container) | Destroys a container | `ctx`: Runtime context
`container_id`: Container `ID`
`callback`: Optional callback | Container status | `CONTAINER_STATUS_ERROR` | +| [`ocre_container_runtime_restart_container`](#restart-container) | Restarts a container | `ctx`: Runtime context
`container_id`: Container `ID`
`callback`: Optional callback | Container status | `CONTAINER_STATUS_ERROR` | + +--- + +## Notes + +- **WASM Module Requirements**: The WebAssembly module specified by `container_data.sha256` must be a valid, complete binary stored in the filesystem (e.g., `/lfs/ocre/images/.bin`). Invalid or truncated modules will cause `CONTAINER_STATUS_ERROR`. +- **SHA-256 Usage**: The sha256 field in `ocre_container_data_t` must contain the SHA-256 hash of the WASM file as a **hexadecimal string**. Using a filename instead of a hash is not recommended and may cause file loading errors unless explicitly supported by the runtime. +- **Host Functions**: The `ocre_api_functions` field in `ocre_container_init_arguments_t` allows defining custom WebAssembly host functions. Set to `NULL` to use default functions provided by the runtime. +- **Error Handling**: Always check return values of API calls, as shown in the examples, to handle errors gracefully and prevent resource leaks. +- **Resource Cleanup**: Ensure proper cleanup by calling `ocre_container_runtime_stop_container`, `ocre_container_runtime_destroy_container`, and `ocre_container_runtime_destroy` when operations are complete. \ No newline at end of file diff --git a/docs/reference/container-api/index.md b/docs/reference/container-api/index.md deleted file mode 100644 index cc16516..0000000 --- a/docs/reference/container-api/index.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Container APIs -layout: default -parent: Reference -has_toc: false ---- - -# Container APIs - - Container APIs provide direct interfaces for containers to efficiently interact with underlying system resources and capabilities. Designed with simplicity, security, and consistency in mind, these APIs follow well-defined patterns to facilitate ease of use and seamless integration. - -These APIs serve as the foundation for container interactions, enabling capabilities such as: - -- **Hardware Resource Access:** Interface with sensors to collect environmental or motion data. -- **Timers:** Create and manage timed events with precise millisecond accuracy. -- **WebAssembly Integration:** Ensure smooth execution within a WebAssembly-based environment, abstracting the complexity from container applications. - ---- - -## Available APIs - -Below are the core APIs available for Ocre containers. They are categorized for your convenience, with detailed documentation for each, including usage examples, error handling patterns, and best practices. - -### System Interaction -- [Sensors](sensors): Interface with hardware sensors for environmental and motion data -- [Timers](timers): Create and manage timed events with millisecond precision \ No newline at end of file From 2cca8b5f93c64f10f1f6c7acae301f486c309ba5 Mon Sep 17 00:00:00 2001 From: Knox Lively Date: Thu, 24 Apr 2025 19:40:02 -0600 Subject: [PATCH 6/6] Minor formatting tweaks --- docs/reference/apis/container-api/sensors.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/reference/apis/container-api/sensors.md b/docs/reference/apis/container-api/sensors.md index 144ea21..6316476 100644 --- a/docs/reference/apis/container-api/sensors.md +++ b/docs/reference/apis/container-api/sensors.md @@ -58,7 +58,7 @@ typedef struct ocre_sensor_handle_t { } ocre_sensor_handle_t; ``` -The sensor handle contains a unique ID, device name, and a reference to the underlying device structure. It is used to reference a specific sensor in all operations. +The sensor handle contains a unique `ID`, device name, and a reference to the underlying device structure. It is used to reference a specific sensor in all operations. ### Sensor Instance @@ -169,8 +169,8 @@ ocre_sensors_status_t ocre_sensors_discover_sensors(ocre_sensor_t *sensors, int | Name | Type | Description | | ------ | ------ | ----------- | -| `sensors` | *ocre_sensor_t** | Pointer to the sensor list to store the discovered info about available sensors | -| `sensors_count` | *int** | Pointer to variable to store the number of discovered sensors | +| `sensors` | *ocre_sensor_t* * | Pointer to the sensor list to store the discovered info about available sensors | +| `sensors_count` | *int* * | Pointer to variable to store the number of discovered sensors | **Returns**: @@ -191,7 +191,7 @@ ocre_sensors_status_t ocre_sensors_open(ocre_sensor_handle_t *sensor_handle); | Name | Type | Description | | ------ | ------ | ----------- | -| `sensor_handle` | *ocre_sensor_handle_t** | Pointer to the sensor handle to open | +| `sensor_handle` | *ocre_sensor_handle_t* * | Pointer to the sensor handle to open | **Returns**: @@ -213,7 +213,7 @@ ocre_sensors_sample_t sensor_read_sample(ocre_sensor_handle_t *sensor_handle); | Name | Type | Description | | ------ | ------ | ----------- | -| `sensor_handle` | *ocre_sensor_handle_t** | Pointer to the sensor handle to read from | +| `sensor_handle` | *ocre_sensor_handle_t* * | Pointer to the sensor handle to read from | **Returns**: @@ -264,7 +264,7 @@ ocre_sensors_status_t ocre_sensors_set_trigger(ocre_sensor_handle_t sensor_handl | `channel` | *sensor_channel_t* | Channel to set the trigger on | | `trigger_type` | *enum sensor_trigger_type* | Type of trigger (e.g., data ready, threshold) | | `callback` | *ocre_sensor_trigger_cb* | Function to be called when trigger occurs | -| `subscription_id` | *int** | Pointer to store the subscription ID | +| `subscription_id` | *int* * | Pointer to store the subscription `ID` | **Returns**: @@ -288,7 +288,7 @@ ocre_sensors_status_t ocre_sensors_clear_trigger(ocre_sensor_handle_t sensor_han | ------ | ------ | ----------- | | `sensor_handle` | *ocre_sensor_handle_t* | Handle of the sensor | | `channel` | *sensor_channel_t* | The specific channel (e.g., `SENSOR_CHANNEL_TEMPERATURE`) from which the trigger should be removed | -| `subscription_id` | *int* | ID of the subscription to remove | +| `subscription_id` | *int* | `ID` of the subscription to remove | **Returns**: @@ -463,6 +463,6 @@ int main() { | [`ocre_sensors_open`](#open-sensor) | Opens sensor | `sensor_handle`: Sensor to open | Status code | `SENSOR_API_STATUS_OK`,
`SENSOR_API_STATUS_ERROR` | | [`sensor_read_sample`](#read-sensor-sample) | Reads sensor data | `sensor_handle`: Sensor to read from | `ocre_sensors_sample_t` structure | N/A | | [`sensor_get_channel`](#get-sensor-channel) | Gets channel data | `sample`: Sensor sample
`channel`: Channel to retrieve | `ocre_sensor_value_t` structure | N/A | -| [`ocre_sensors_set_trigger`](#set-sensor-trigger) | Sets sensor trigger | `sensor_handle`: Target sensor
`channel`: Target channel
`trigger_type`: Trigger type
`callback`: Callback function
`subscription_id`: ID output | Status code | `SENSOR_API_STATUS_OK`,
`SENSOR_API_STATUS_ERROR` | +| [`ocre_sensors_set_trigger`](#set-sensor-trigger) | Sets sensor trigger | `sensor_handle`: Target sensor
`channel`: Target channel
`trigger_type`: Trigger type
`callback`: Callback function
`subscription_id`: `ID` output | Status code | `SENSOR_API_STATUS_OK`,
`SENSOR_API_STATUS_ERROR` | | [`ocre_sensors_clear_trigger`](#clear-sensor-trigger) | Removes sensor trigger | `sensor_handle`: Target sensor
`channel`: Target channel
`subscription_id`: Subscription to remove | Status code | `SENSOR_API_STATUS_OK`,
`SENSOR_API_STATUS_ERROR` | | [`ocre_sensors_cleanup`](#clean-up-sensor-environment) | Cleans up resources | None | Status code | `SENSOR_API_STATUS_OK`,
`SENSOR_API_STATUS_ERROR` | \ No newline at end of file