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 <9960133+lupyuen@users.noreply.github.com>
This commit is contained in:
parent
b4999fa916
commit
437c903c47
30
examples/leds_rust/Kconfig
Normal file
30
examples/leds_rust/Kconfig
Normal file
@ -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
|
23
examples/leds_rust/Make.defs
Normal file
23
examples/leds_rust/Make.defs
Normal file
@ -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
|
36
examples/leds_rust/Makefile
Normal file
36
examples/leds_rust/Makefile
Normal file
@ -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
|
128
examples/leds_rust/leds_rust_main.rs
Normal file
128
examples/leds_rust/leds_rust_main.rs
Normal file
@ -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());
|
||||
}
|
119
examples/leds_rust/nuttx.rs
Normal file
119
examples/leds_rust/nuttx.rs
Normal file
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user