Skip to content

Instantly share code, notes, and snippets.

@ciniml
Created June 11, 2019 21:52
Show Gist options
  • Save ciniml/f93d49cb0330d01b78ee417ce4668642 to your computer and use it in GitHub Desktop.
Save ciniml/f93d49cb0330d01b78ee417ce4668642 to your computer and use it in GitHub Desktop.
M5Stack Rust Example
#![no_std]
#![feature(lang_items, alloc_error_handler, alloc)]
use core::panic::PanicInfo;
use core::alloc::{GlobalAlloc, Layout};
use core::fmt;
use core::fmt::Write;
use core::convert::From;
use core::ptr;
use core::mem;
use core::str;
use rand::prelude::*;
mod m5stack;
use m5stack::m5display;
use freertos_rs::*;
extern crate alloc;
use alloc::rc::Rc;
use alloc::sync::Arc;
use alloc::vec::Vec;
use idf::*;
extern "C" {
fn malloc(size: usize) -> *mut u8;
fn free(ptr: *mut u8);
fn write(file: isize, buffer: *const u8, count: usize) -> usize;
fn lcd_print(buffer: *const u8, count: usize) -> usize;
#[no_mangle]
static esp_wifi_init_config_default: wifi_init_config_t;
}
struct LibcAllocator;
unsafe impl GlobalAlloc for LibcAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
if layout.align() > 8 {
panic!("Unsupported alignment")
}
malloc(layout.size())
}
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
free(ptr)
}
}
struct Stdout;
impl fmt::Write for Stdout {
fn write_str(&mut self, s: &str) -> fmt::Result {
unsafe {
let buffer = s.as_bytes();
if write(0, buffer.as_ptr(), buffer.len()) > 0 {
Ok(())
} else {
Err(()).map_err(|_| fmt::Error)
}
}
}
}
struct Lcd;
impl fmt::Write for Lcd {
fn write_str(&mut self, s: &str) -> fmt::Result {
unsafe {
let buffer = s.as_bytes();
lcd_print(buffer.as_ptr(), buffer.len());
Ok(())
}
}
}
fn stdout() -> Stdout {
Stdout
}
fn print_str(s: &str) -> Result<(), ()> {
stdout().write_str(s).map_err(drop)
}
fn print_fmt(args: fmt::Arguments) -> Result<(), ()> {
stdout().write_fmt(args).map_err(drop)
}
fn lcd() -> Lcd {
Lcd
}
fn print_lcd(args: fmt::Arguments) -> Result<(), ()> {
lcd().write_fmt(args).map_err(drop)
}
#[global_allocator]
static A: LibcAllocator = LibcAllocator;
trait AsResult<T, E> {
fn as_result(&self) -> Result<T, E>;
}
impl AsResult<(), esp_err_t> for esp_err_t {
fn as_result(&self) -> Result<(), esp_err_t> {
if *self == 0 {
Ok(())
}
else {
Err(*self)
}
}
}
unsafe extern "C" fn event_handler(ctx: *mut std::os::raw::c_void, event: *mut system_event_t) -> esp_err_t {
match (*event).event_id {
system_event_id_t_SYSTEM_EVENT_STA_START => {
esp_wifi_connect();
}
system_event_id_t_SYSTEM_EVENT_STA_GOT_IP => {
print_str("Got IP\n");
let mut addrCStr = ip4addr_ntoa(&((*event).event_info.got_ip.as_ref().ip_info.ip));
let mut addr = Vec::new();
while *addrCStr != 0 {
addr.push(*addrCStr as u8);
addrCStr = addrCStr.offset(1);
}
if let Ok(s) = str::from_utf8(addr.as_ref()) {
print_str(s);
}
}
system_event_id_t_SYSTEM_EVENT_STA_DISCONNECTED => {
print_str("Disconnected\n");
}
_ => {
;
}
}
0
}
#[no_mangle]
pub extern fn rust_main() {
print_str("Hello from Rust!\n");
print_fmt(format_args!("Hello formatted from {}\n", "Rust"));
print_lcd(format_args!("Print from {}\n", "Rust"));
let queue = Arc::new( Queue::<(i32, i32, i32, i32, u32)>::new(32).unwrap() );
let queueDrawTask = queue.clone();
let _drawTask = Task::new().name("line task").stack_size(4096).core(1).start(move || {
loop {
if let Ok((x0, y0, x1, y1, color)) = queueDrawTask.receive(Duration::infinite()) {
m5display.drawLine(x0, y0, x1, y1, color);
}
unsafe {
esp_task_wdt_reset();
}
}
}).unwrap();
let mainTask = Task::current().unwrap();
let queueRequestTask = queue.clone();
let _requestTask = Task::new().name("rand task").stack_size(4096).core(0).start(move || {
let seed:[u8; 16] = [7; 16];
let mut rng = SmallRng::from_seed(seed);
for i in 0..100000 {
let x0:i32 = rng.gen_range(0, 320);
let y0:i32 = rng.gen_range(0, 240);
let x1:i32 = rng.gen_range(0, 320);
let y1:i32 = rng.gen_range(0, 240);
let color:u32 = rng.gen_range(0, 0x10000);
queueRequestTask.send((x0, y0, x1, y1, color), Duration::infinite());
unsafe {
esp_task_wdt_reset();
}
}
mainTask.notify(TaskNotification::SetBits(0x01));
}).unwrap();
unsafe {
nvs_flash_init();
tcpip_adapter_init();
esp_event_loop_init(Some(event_handler), ptr::null_mut());
let wifiInitConfig = esp_wifi_init_config_default;
let mut wifiConfig = mem::zeroed::<wifi_config_t>();
let ssid = "ssid\0";
let password = "passphrase\0";
wifiConfig.sta.as_mut().ssid[..ssid.len()].clone_from_slice(ssid.as_bytes());
wifiConfig.sta.as_mut().password[..password.len()].clone_from_slice(password.as_bytes());
let result = esp_wifi_init(&wifiInitConfig).as_result()
.and_then(|_| esp_wifi_set_mode(wifi_mode_t_WIFI_MODE_STA).as_result())
.and_then(|_| esp_wifi_set_config(esp_interface_t_ESP_IF_WIFI_STA, &mut wifiConfig).as_result())
.and_then(|_| esp_wifi_start().as_result());
if let Err(code) = result {
print_fmt(format_args!("Failed to initialize Wi-Fi - {}\n", code));
}
}
let mainTask = Task::current().unwrap();
mainTask.wait_for_notification(0x01, 0x01, Duration::infinite());
}
#[lang = "panic_impl"]
#[no_mangle]
pub extern fn rust_begin_panic(_info: &PanicInfo) -> ! {
loop {}
}
#[alloc_error_handler]
fn on_oom(_layout: Layout) -> ! {
loop {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment