This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
The following commit(s) were added to refs/heads/master by this push:
new 437c903c4 examples/leds_rust: Add Rust App for blinking the LED
437c903c4 is described below
commit 437c903c47d37d36aa1bd8ca75a078d304fadc99
Author: Rushabh Gala <[email protected]>
AuthorDate: Thu Aug 1 00:27:36 2024 +0530
examples/leds_rust: Add Rust App for blinking the LED
- This PR adds `examples/leds_rust` to call NuttX POSIX APIs like `open()`
and `ioctl()`, so that it blinks an LED
- The `leds_rust` app is also used for testing the GPIO and LED Drivers for
Ox64 BL808 SBC and QEMU RISC-V Emulator in Google Summer of Code
- `leds_rust` be executed locally on Linux / macOS / Windows, by commenting
out the first 2 lines of code
- The code is based on `examples/leds` in C, and `examples/hello_rust` in
Rust
Co-Authored-By: Lup Yuen Lee <[email protected]>
---
examples/leds_rust/Kconfig | 30 ++++++++
examples/leds_rust/Make.defs | 23 +++++++
examples/leds_rust/Makefile | 36 ++++++++++
examples/leds_rust/leds_rust_main.rs | 128 +++++++++++++++++++++++++++++++++++
examples/leds_rust/nuttx.rs | 119 ++++++++++++++++++++++++++++++++
5 files changed, 336 insertions(+)
diff --git a/examples/leds_rust/Kconfig b/examples/leds_rust/Kconfig
new file mode 100644
index 000000000..914693c88
--- /dev/null
+++ b/examples/leds_rust/Kconfig
@@ -0,0 +1,30 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+config EXAMPLES_LEDS_RUST
+ tristate "\"LEDs Rust\" example"
+ default n
+ depends on USERLED
+ ---help---
+ Enable the \"LEDs Rust\" example
+
+if EXAMPLES_LEDS_RUST
+
+config EXAMPLES_LEDS_RUST_PROGNAME
+ string "Program name"
+ default "leds_rust"
+ ---help---
+ This is the name of the program that will be used when the
+ program is installed.
+
+config EXAMPLES_LEDS_RUST_PRIORITY
+ int "LEDs Rust task priority"
+ default 100
+
+config EXAMPLES_LEDS_RUST_STACKSIZE
+ int "LEDs Rust stack size"
+ default DEFAULT_TASK_STACKSIZE
+
+endif
diff --git a/examples/leds_rust/Make.defs b/examples/leds_rust/Make.defs
new file mode 100644
index 000000000..0749823da
--- /dev/null
+++ b/examples/leds_rust/Make.defs
@@ -0,0 +1,23 @@
+############################################################################
+# apps/examples/leds_rust/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership. The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+ifneq ($(CONFIG_EXAMPLES_LEDS_RUST),)
+CONFIGURED_APPS += $(APPDIR)/examples/leds_rust
+endif
diff --git a/examples/leds_rust/Makefile b/examples/leds_rust/Makefile
new file mode 100644
index 000000000..ab3d86e2b
--- /dev/null
+++ b/examples/leds_rust/Makefile
@@ -0,0 +1,36 @@
+############################################################################
+# apps/examples/leds_rust/Makefile
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership. The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+include $(APPDIR)/Make.defs
+
+# Hello, Rust! built-in application info
+
+PROGNAME = $(CONFIG_EXAMPLES_LEDS_RUST_PROGNAME)
+PRIORITY = $(CONFIG_EXAMPLES_LEDS_RUST_PRIORITY)
+STACKSIZE = $(CONFIG_EXAMPLES_LEDS_RUST_STACKSIZE)
+MODULE = $(CONFIG_EXAMPLES_LEDS_RUST)
+
+# Hello, Rust! Example
+
+MAINSRC = leds_rust_main.rs
+
+RUSTFLAGS += -C panic=abort -O
+
+include $(APPDIR)/Application.mk
diff --git a/examples/leds_rust/leds_rust_main.rs
b/examples/leds_rust/leds_rust_main.rs
new file mode 100644
index 000000000..1bd1bca42
--- /dev/null
+++ b/examples/leds_rust/leds_rust_main.rs
@@ -0,0 +1,128 @@
+/****************************************************************************
+ * apps/examples/leds_rust/leds_rust_main.rs
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Attributes
+ ****************************************************************************/
+
+/* Comment out these lines for testing with Rust Standard Library */
+
+#![no_main]
+#![no_std]
+
+/****************************************************************************
+ * Uses
+ ****************************************************************************/
+
+#[cfg(target_os = "none")]
+use core::{
+ panic::PanicInfo,
+ result::Result::{self, Err, Ok},
+};
+
+/****************************************************************************
+ * Modules
+ ****************************************************************************/
+
+mod nuttx;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Panic Handler (needed for [no_std] compilation)
+ ****************************************************************************/
+
+#[cfg(target_os = "none")] /* For NuttX */
+#[panic_handler]
+fn panic(_panic: &PanicInfo<'_>) -> ! {
+ loop {}
+}
+
+/****************************************************************************
+ * rust_main
+ ****************************************************************************/
+
+fn rust_main(_argc: i32, _argv: *const *const u8) -> Result<i32, i32> {
+ /* "Hello, Rust!!" using puts() from libc */
+
+ nuttx::safe_puts("Hello, Rust!!");
+
+ /* Blink LED 1 using ioctl() from NuttX */
+
+ nuttx::safe_puts("Opening /dev/userleds");
+ let fd = nuttx::safe_open("/dev/userleds", nuttx::O_WRONLY)?;
+ nuttx::safe_puts("Set LED 1 to 1");
+
+ nuttx::safe_ioctl(fd, nuttx::ULEDIOC_SETALL, 1)?;
+ nuttx::safe_puts("Sleeping...");
+ unsafe {
+ nuttx::usleep(500_000);
+ }
+
+ nuttx::safe_puts("Set LED 1 to 0");
+ nuttx::safe_ioctl(fd, nuttx::ULEDIOC_SETALL, 0)?;
+ unsafe {
+ nuttx::close(fd);
+ }
+
+ /* Exit with status 0 */
+
+ Ok(0)
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * leds_rust_main
+ ****************************************************************************/
+
+#[no_mangle]
+pub extern "C" fn leds_rust_main(_argc: i32, _argv: *const *const u8) -> i32 {
+ /* Call the program logic in Rust Main */
+
+ let res = rust_main(0, core::ptr::null());
+
+ /* If Rust Main returns an error, print it */
+
+ if let Err(e) = res {
+ unsafe {
+ nuttx::printf(
+ b"ERROR: rust_main() failed with error %d\n\0" as *const u8,
+ e,
+ );
+ }
+ e
+ } else {
+ 0
+ }
+}
+
+/****************************************************************************
+ * main
+ ****************************************************************************/
+
+#[cfg(not(target_os = "none"))] /* For Testing Locally */
+fn main() {
+ leds_rust_main(0, core::ptr::null());
+}
diff --git a/examples/leds_rust/nuttx.rs b/examples/leds_rust/nuttx.rs
new file mode 100644
index 000000000..4b075767b
--- /dev/null
+++ b/examples/leds_rust/nuttx.rs
@@ -0,0 +1,119 @@
+/****************************************************************************
+ * apps/examples/leds_rust/nuttx.rs
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/* NuttX Definitions for Rust Apps */
+
+/****************************************************************************
+ * Uses
+ ****************************************************************************/
+
+use core::result::Result::{self, Err, Ok};
+
+/****************************************************************************
+ * Externs
+ ****************************************************************************/
+
+extern "C" {
+ pub fn printf(format: *const u8, ...) -> i32;
+ pub fn open(path: *const u8, oflag: i32, ...) -> i32;
+ pub fn close(fd: i32) -> i32;
+ pub fn ioctl(fd: i32, request: i32, ...) -> i32;
+ pub fn usleep(usec: u32) -> u32;
+ pub fn puts(s: *const u8) -> i32;
+}
+
+/****************************************************************************
+ * Public Constants
+ ****************************************************************************/
+
+pub const ENAMETOOLONG: i32 = 36;
+pub const O_WRONLY: i32 = 1 << 1;
+pub const PATH_MAX: usize = 256;
+pub const PUTS_MAX: usize = 256;
+pub const ULEDIOC_SETALL: i32 = 0x1d03;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/* Copy the Rust Str to the Byte Buffer and terminate with null */
+
+fn copy_to_buffer(s: &str, buffer: &mut [u8]) -> Result<(), ()> {
+ let byte_str = s.as_bytes();
+ let len = byte_str.len();
+ if len >= buffer.len() {
+ Err(())
+ } else {
+ buffer[..len].copy_from_slice(&byte_str[..len]);
+ buffer[len] = 0;
+ Ok(())
+ }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/* Safe Version of open() */
+
+pub fn safe_open(path: &str, oflag: i32) -> Result<i32, i32> {
+ let mut buffer = [0u8; PATH_MAX];
+ let res = copy_to_buffer(path, &mut buffer);
+ if res.is_err() {
+ unsafe {
+ puts(b"ERROR: safe_open() path size exceeds PATH_MAX\0" as *const
u8);
+ }
+ return Err(-ENAMETOOLONG);
+ }
+
+ let fd = unsafe { open(buffer.as_ptr(), oflag) };
+ if fd < 0 {
+ Err(fd)
+ } else {
+ Ok(fd)
+ }
+}
+
+/* Safe Version of ioctl() */
+
+pub fn safe_ioctl(fd: i32, request: i32, arg: i32) -> Result<i32, i32> {
+ let ret = unsafe { ioctl(fd, request, arg) };
+ if ret < 0 {
+ Err(ret)
+ } else {
+ Ok(ret)
+ }
+}
+
+/* Safe Version of puts() */
+
+pub fn safe_puts(s: &str) {
+ let mut buffer = [0u8; PUTS_MAX];
+ let res = copy_to_buffer(s, &mut buffer);
+ if res.is_err() {
+ unsafe {
+ puts(b"ERROR: safe_puts() string size exceeds PUTS_MAX\0" as
*const u8);
+ }
+ } else {
+ unsafe {
+ puts(buffer.as_ptr());
+ }
+ }
+}