1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

examples: Add second Rust example (gcoap)

This commit is contained in:
chrysn 2021-08-26 16:23:31 +02:00
parent 49403c7781
commit 6246ab70d1
7 changed files with 245 additions and 0 deletions

BIN
examples/rust-gcoap/Cargo.lock generated Normal file

Binary file not shown.

View File

@ -0,0 +1,16 @@
[package]
name = "rust-gcoap"
version = "0.1.0"
authors = ["Christian Amsüss <chrysn@fsfe.org>"]
edition = "2018"
resolver = "2"
[lib]
crate-type = ["staticlib"]
[dependencies]
riot-wrappers = { version = "^0.7", features = [ "with_coap_message", "with_coap_handler" ] }
coap-message-demos = { git = "https://gitlab.com/chrysn/coap-message-demos/", default-features = false }
coap-handler-implementations = "0.1"
riot-coap-handler-demos = { git = "https://gitlab.com/etonomy/riot-module-examples/", features = [ "vfs" ] }

View File

@ -0,0 +1,39 @@
# name of your application
APPLICATION = rust_gcoap
# If no BOARD is found in the environment, use this default:
BOARD ?= native
# This has to be the absolute path to the RIOT base directory:
RIOTBASE ?= $(CURDIR)/../..
# Basic networking, and gcoap
USEMODULE += gcoap
USEMODULE += netdev_default
USEMODULE += auto_init_gnrc_netif
USEMODULE += gnrc_ipv6_default
USEMODULE += gnrc_icmpv6_echo
USEMODULE += ztimer
USEMODULE += ztimer_usec
USEMODULE += ztimer_msec
USEMODULE += ztimer_sec
USEMODULE += vfs
USEMODULE += constfs
# Comment this out to disable code in RIOT that does safety checking
# which is not needed in a production environment but helps in the
# development process:
DEVELHELP ?= 1
# Change this to 0 show compiler invocation lines by default:
QUIET ?= 1
# The name of crate (as per Cargo.toml package name, but with '-' replaced with '_')
APPLICATION_RUST_MODULE = rust_gcoap
BASELIBS += $(APPLICATION_RUST_MODULE).module
FEATURES_REQUIRED += rust_target
include $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1,8 @@
BOARD_INSUFFICIENT_MEMORY := \
blackpill \
bluepill \
nucleo-f302r8 \
nucleo-f303k8 \
nucleo-f334r8 \
stm32mp157c-dk2 \
#

View File

@ -0,0 +1,53 @@
gcoap used with Rust
====================
This is the advanced Rust example; see ../rust-hello-world/ for the basics.
In extension to the basic example, it shows:
* C code can be mixed with Rust code easily; any C file is built and linked
as in applications without Rust.
While it's technically possible to have header files for that code,
it is easier (and likewise often done in C applications)
to just translate the entry function's signature manually,
as is done with the `do_vfs_init()` function.
* Code of Rust applications can be spread out into modules,
even if it builds on RIOT components.
The CoAP handler built in the main function
combines generic CoAP components (from `coap_message_demos`)
with RIOT specific components (from `riot-coap-handler-demos`).
* Many features of RIOT are exposed to Rust through the riot-wrappers crate,
which provides safe wrappers around RIOT structures.
In this example, the abovementioned CoAP handler is run on the gcoap server,
for which the wrappers provide adaptation to the platform independent handler interface.
Then, ztimer is used to sleep until the network interfaces are expected to be ready.
Finally, the available network interfaces are iterated over
and queried for their IP addresses,
which makes it easier (in absence of an interactive shell) to find which address CoAP requests can be directed at.
How to use
----------
```
$ make all flash term
[...]
main(): This is RIOT! (Version: 2022.01-devel-560-g7f8ed-rust-application)
constfs mounted successfully
CoAP server ready; waiting for interfaces to settle before reporting addresses...
Active interface from PID KernelPID(6) ("gnrc_netdev_tap")
Address fe80:0000:0000:0000:1234:56ff:fe78:90ab
Address 2a02:0b18:c13b:8018:1234:56ff:fe78:90ab
```
Once that is ready, in a parallel shell, run:
```
$ aiocoap-client 'coap://[2a02:0b18:c13b:8018:1234:56ff:fe78:90ab]/.well-known/core'
```

View File

@ -0,0 +1,57 @@
// Copyright (C) 2020 Christian Amsüss
//
// This file is subject to the terms and conditions of the GNU Lesser
// General Public License v2.1. See the file LICENSE in the top level
// directory for more details.
#![no_std]
use riot_wrappers::{riot_main, println};
use riot_wrappers::{gcoap, thread, ztimer, gnrc};
use coap_handler_implementations::{ReportingHandlerBuilder, HandlerBuilder};
riot_main!(main);
fn main() {
extern "C" {
fn do_vfs_init();
}
unsafe { do_vfs_init() };
let handler = coap_message_demos::full_application_tree(None)
.below(&["ps"], riot_coap_handler_demos::ps::ps_tree())
.below(&["vfs"], riot_coap_handler_demos::vfs::vfs("/const"))
.with_wkc()
;
let mut handler = riot_wrappers::coap_handler::GcoapHandler(handler);
let mut listener = gcoap::SingleHandlerListener::new_catch_all(&mut handler);
gcoap::scope(|greg| {
greg.register(&mut listener);
println!("CoAP server ready; waiting for interfaces to settle before reporting addresses...");
let sectimer = ztimer::ZTimer::sec();
sectimer.sleep_ticks(2);
for netif in gnrc::Netif::all() {
println!("Active interface from PID {:?} ({:?})", netif.pid(), netif.pid().get_name().unwrap_or("unnamed"));
match netif.ipv6_addrs() {
Ok(addrs) => {
for a in addrs.addresses() {
println!(" Address {:?}", a);
}
}
_ => {
println!(" Does not support IPv6.");
}
}
}
// Sending main thread to sleep; can't return or the Gcoap handler would need to be
// deregistered (which it can't).
loop { thread::sleep(); }
})
}

72
examples/rust-gcoap/vfs.c Normal file
View File

@ -0,0 +1,72 @@
/*
* Copyright (C) 2018 OTA keys S.A.
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* This file demonstrates how C code can be mixed with Rust code in an
* application in an ad-hoc fashion.
*/
#include <vfs.h>
#include "fs/constfs.h"
#include <stdio.h>
#define HELLO_WORLD_CONTENT "Hello World!\n"
#define HELLO_RIOT_CONTENT "Hello RIOT!\n"
#define LARGE "1234567890---------\n" \
"1234567890---------\n" \
"1234567890---------\n" \
"1234567890---------\n" \
"1234567890---------\n" \
"1234567890---------\n" \
"1234567890---------\n" \
"1234567890---------\n" \
"1234567890---------\n" \
"1234567890---------\n" \
"1234567890---------\n" \
"1234567890---------\n" \
"1234567890---------\n"
static constfs_file_t constfs_files[] = {
{
.path = "/hello-world",
.size = sizeof(HELLO_WORLD_CONTENT),
.data = (const uint8_t *)HELLO_WORLD_CONTENT,
},
{
.path = "/hello-riot",
.size = sizeof(HELLO_RIOT_CONTENT),
.data = (const uint8_t *)HELLO_RIOT_CONTENT,
},
{
.path = "/large",
.size = sizeof(LARGE),
.data = (const uint8_t *)LARGE,
}
};
static constfs_t constfs_desc = {
.nfiles = ARRAY_SIZE(constfs_files),
.files = constfs_files,
};
static vfs_mount_t const_mount = {
.fs = &constfs_file_system,
.mount_point = "/const",
.private_data = &constfs_desc,
};
void do_vfs_init(void) {
int res = vfs_mount(&const_mount);
if (res < 0) {
puts("Error while mounting constfs");
}
else {
puts("constfs mounted successfully");
}
}