diff --git a/src/modules/rust_module_test/CMakeLists.txt b/src/modules/rust_module_test/CMakeLists.txt new file mode 100644 index 000000000000..12b4772f39fa --- /dev/null +++ b/src/modules/rust_module_test/CMakeLists.txt @@ -0,0 +1,40 @@ +# ########################################################################### +# +# Copyright (c) 2024 Technology Innovation Institute. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# ############################################################################ + +px4_add_module( + MODULE modules__rust_module_test + MAIN rust_module_test + LANG Rust + RUST_MOD + rust_mod + ) diff --git a/src/modules/rust_module_test/Kconfig b/src/modules/rust_module_test/Kconfig new file mode 100644 index 000000000000..21c7142888fd --- /dev/null +++ b/src/modules/rust_module_test/Kconfig @@ -0,0 +1,12 @@ +menuconfig MODULES_RUST_MODULE_TEST + bool "rust_module_test" + default n + ---help--- + Enable rust module test + +menuconfig USER_RUST_MODULE_TEST + bool "rust module test in user" + default y + depends on BOARD_PROTECTED && MODULES_RUST_MODULE_TEST + ---help--- + Put rust module test in userspace memory diff --git a/src/modules/rust_module_test/rust_mod/Cargo.lock b/src/modules/rust_module_test/rust_mod/Cargo.lock new file mode 100644 index 000000000000..a667df184ed0 --- /dev/null +++ b/src/modules/rust_module_test/rust_mod/Cargo.lock @@ -0,0 +1,84 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "no-std-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "px4_nuttx" +version = "0.1.0" +dependencies = [ + "embedded-io", + "log", + "no-std-net", + "px4_nuttx_macros", +] + +[[package]] +name = "px4_nuttx_macros" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rust_mod" +version = "0.1.0" +dependencies = [ + "log", + "px4_nuttx", + "px4_nuttx_macros", +] + +[[package]] +name = "syn" +version = "2.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" diff --git a/src/modules/rust_module_test/rust_mod/Cargo.toml b/src/modules/rust_module_test/rust_mod/Cargo.toml new file mode 100644 index 000000000000..cd86edaad7fd --- /dev/null +++ b/src/modules/rust_module_test/rust_mod/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "rust_mod" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["staticlib"] + +[profile.dev] +panic = "abort" + +[profile.release] +panic = "abort" + +[dependencies] +log = "0.4" +px4_nuttx = { path = "../../../lib/rust_px4_nuttx" } +px4_nuttx_macros = { path = "../../../lib/rust_px4_nuttx/px4_nuttx_macros" } diff --git a/src/modules/rust_module_test/rust_mod/src/lib.rs b/src/modules/rust_module_test/rust_mod/src/lib.rs new file mode 100644 index 000000000000..3eaf406b6b3f --- /dev/null +++ b/src/modules/rust_module_test/rust_mod/src/lib.rs @@ -0,0 +1,109 @@ +#![no_std] +#![no_main] + +extern crate px4_nuttx; +extern crate px4_nuttx_macros; + +use px4_nuttx::logger::{log_raw, LogLevel}; +use log::{info, warn}; +use px4_nuttx::px4_module_main; +use px4_nuttx::nuttx::net::UdpSocket; +use px4_nuttx::nuttx::time::{hrt_time, Duration}; +use px4_nuttx::alloc::vec::Vec; +use px4_nuttx::alloc::string::String; + + +#[px4_module_main] +pub fn run(_args: &[&str]) -> Result<(), ()> { + info!("Hello from Rust module test!"); + + let mut count: u32 = 0; + for arg in _args { + info!(" arg[{}]: {}", count, arg); + count += 1; + } + + if _args.len() > 1 { + let mode: u32 = _args[1].parse::().unwrap_or(0); + match mode { + 1 => vector_test(), + 2 => timer_test(), + 3 => udp_send_test(), + 4 => udp_recv_test(), + 5 => generate_panic(), + 6 => test_raw(), + _ => warn!("Invalid test. Use 1-6"), + } + + } else { + vector_test(); + timer_test(); + udp_send_test(); + udp_recv_test() + } + + Ok(()) +} + +fn vector_test() { + // Test vector + info!("TEST: Vector"); + let mut v1: Vec = Vec::new(); + for i in 0..10 { + v1.push(i+3); + } + info!("This is new vector: {:?}", v1); +} + +fn timer_test() { + // Test hrt_timer + info!("TEST: timer"); + info!("System timer: {}", hrt_time()); +} + +fn udp_send_test() { + // Test udp socket send + info!("TEST: UDP socket send"); + let socket = UdpSocket::bind("192.168.200.101:12222").unwrap(); + info!("Created a socket which is bound to address 192.168.200.101:12222"); + socket.send_to(b"Hello from Rust!\n", "192.168.200.100:12223").unwrap(); + info!("Message sent to 192.168.200.100:12223"); +} + +fn udp_recv_test() { + let mut buf: [u8; 128] = [0; 128]; + let timeout = 5; + + // Test udp socket receive + info!("TEST: UDP socket receive"); + let mut socket = UdpSocket::bind("192.168.200.101:12222").unwrap(); + info!("Set read timeout {} secs", timeout); + socket.set_read_timeout(Some(Duration::from_secs(timeout))).unwrap(); + info!("Created a socket which is bound to address 192.168.200.101:12222"); + if let Ok(len) = socket.recv_from(&mut buf) { + info!("Receive {} bytes", len); + if let Ok(data) = core::str::from_utf8(&buf[..len]) { + info!("MSG: {}", data); + } else { + warn!("Can't read message data"); + } + } else { + warn!("Receiving failed!") + } + +} + +fn test_raw() { + let message = String::from("hello from log_raw"); + info!("Test raw print here"); + log_raw( + LogLevel::Panic, + &message, + ); +} + +fn generate_panic() { + info!("This should cause panic"); + let a: Option = None; + let _b = a.unwrap(); +}