Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
Loading items

Target

Select target project
  • astro/rust-card10
  • rnestler/rust-card10
  • dbrgn/rust-card10
  • toon/rust-card10
  • mwall/rust-card10
  • puzzlewolf/rust-card10
  • rnd/rust-card10
  • lilpep/rust-card10
  • rafael/rust-card10
  • squeed/rust-card10
  • arist/rust-card10
11 results
Select Git revision
Loading items
Show changes
Showing
with 1484 additions and 172 deletions
use crate::Display;
use card10_sys::*;
use core::mem::{transmute, uninitialized}; use core::mem::{transmute, uninitialized};
use core::ops::{Index, IndexMut}; use core::ops::{Index, IndexMut};
use crate::bindings::*;
use crate::Display; use embedded_graphics::pixelcolor::{PixelColor, Rgb565};
use embedded_graphics::prelude::Pixel;
use embedded_graphics::Drawing;
mod font; mod font;
pub use font::*; pub use font::*;
...@@ -9,18 +13,15 @@ mod text; ...@@ -9,18 +13,15 @@ mod text;
pub use text::TextRenderer; pub use text::TextRenderer;
pub struct FrameBuffer<'d> { pub struct FrameBuffer<'d> {
_display: &'d Display, _display: &'d mut Display,
buffer: disp_framebuffer, buffer: disp_framebuffer,
} }
impl<'d> FrameBuffer<'d> { impl<'d> FrameBuffer<'d> {
pub fn uninitialized(display: &'d Display) -> Self { pub fn uninitialized(display: &'d mut Display) -> Self {
FrameBuffer { FrameBuffer {
_display: display, _display: display,
buffer: unsafe { buffer: unsafe { uninitialized() },
uninitialized()
},
} }
} }
...@@ -33,18 +34,26 @@ impl<'d> FrameBuffer<'d> { ...@@ -33,18 +34,26 @@ impl<'d> FrameBuffer<'d> {
pub fn clear(&mut self, color: RawColor) { pub fn clear(&mut self, color: RawColor) {
for y in 0..Display::H { for y in 0..Display::H {
for x in 0..Display::W { for x in 0..Display::W {
let bytes: &mut RawColor = unsafe { let bytes: &mut RawColor =
transmute(&mut self.buffer.fb[y as usize][x as usize]) unsafe { transmute(&mut self.buffer.fb[y as usize][x as usize]) };
};
*bytes = color; *bytes = color;
} }
} }
} }
pub fn text<'a, 'f>(&'a mut self, x: isize, y: isize, font: &'f Font, color: RawColor) -> TextRenderer<'a, 'd, 'f> { pub fn text<'a, 'f>(
&'a mut self,
x: isize,
y: isize,
font: &'f Font,
color: RawColor,
) -> TextRenderer<'a, 'd, 'f> {
TextRenderer { TextRenderer {
framebuffer: self, framebuffer: self,
x, y, font, color, x,
y,
font,
color,
} }
} }
} }
...@@ -52,24 +61,40 @@ impl<'d> FrameBuffer<'d> { ...@@ -52,24 +61,40 @@ impl<'d> FrameBuffer<'d> {
impl<'d> Index<(u16, u16)> for FrameBuffer<'d> { impl<'d> Index<(u16, u16)> for FrameBuffer<'d> {
type Output = RawColor; type Output = RawColor;
fn index(&self, (x, y): (u16, u16)) -> &Self::Output { fn index(&self, (x, y): (u16, u16)) -> &Self::Output {
let x = usize::from(Display::W - 1 - x); let x = usize::from(Display::W as u16 - 1 - x);
let y = usize::from(Display::H - 1 - y); let y = usize::from(Display::H as u16 - 1 - y);
unsafe { unsafe { transmute(&self.buffer.fb[y][x]) }
transmute(&self.buffer.fb[y][x])
}
} }
} }
impl<'d> IndexMut<(u16, u16)> for FrameBuffer<'d> { impl<'d> IndexMut<(u16, u16)> for FrameBuffer<'d> {
fn index_mut(&mut self, (x, y): (u16, u16)) -> &mut Self::Output { fn index_mut(&mut self, (x, y): (u16, u16)) -> &mut Self::Output {
let x = usize::from(Display::W - 1 - x); let x = usize::from(Display::W as u16 - 1 - x);
let y = usize::from(Display::H - 1 - y); let y = usize::from(Display::H as u16 - 1 - y);
unsafe { unsafe { transmute(&mut self.buffer.fb[y][x]) }
transmute(&mut self.buffer.fb[y][x]) }
}
/// `embedded-graphics` support
impl<'d, C: PixelColor + Into<RawColor>> Drawing<C> for FrameBuffer<'d> {
fn draw<T>(&mut self, item: T)
where
T: IntoIterator<Item = Pixel<C>>,
{
for Pixel(coord, color) in item {
let x = coord[0] as u16;
let y = coord[1] as u16;
if x >= Display::W as u16 || y >= Display::H as u16 {
continue;
}
// Swap bytes
self[(x, y)] = color.into();
} }
} }
} }
/// RGB565 with swapped bytes
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
#[repr(C)] #[repr(C)]
pub struct RawColor([u8; 2]); pub struct RawColor([u8; 2]);
...@@ -99,9 +124,40 @@ impl RawColor { ...@@ -99,9 +124,40 @@ impl RawColor {
Self::rgb8(0xff, 0xff, 0) Self::rgb8(0xff, 0xff, 0)
} }
/// Construct from 0..255-triple
pub fn rgb8(r8: u8, g8: u8, b8: u8) -> Self { pub fn rgb8(r8: u8, g8: u8, b8: u8) -> Self {
let b1 = (r8 & 0xF8) | (g8 >> 5); let b1 = (r8 & 0xF8) | (g8 >> 5);
let b2 = ((g8 & 0xFA) << 3) | (b8 >> 3); let b2 = ((g8 & 0xFA) << 3) | (b8 >> 3);
RawColor([b1, b2]) RawColor([b1, b2])
} }
pub fn r8(&self) -> u8 {
self.0[0] & 0xF8
}
pub fn g8(&self) -> u8 {
((self.0[0] & 0x7) << 5) |
((self.0[0] & 0xE) >> 3)
}
pub fn b8(&self) -> u8 {
(self.0[1] & 0x1F) << 3
}
}
impl PixelColor for RawColor {}
/// Most similar format, just byte-swapped
impl From<Rgb565> for RawColor {
fn from(rgb: Rgb565) -> Self {
let c = rgb.0;
RawColor([(c >> 8) as u8, c as u8])
}
}
/// Dummy implementation required for impl Drawable
impl From<u8> for RawColor {
fn from(b: u8) -> Self {
RawColor([0, b])
}
} }
use super::{Font, FrameBuffer, RawColor};
use crate::Display;
use core::fmt::Write; use core::fmt::Write;
use super::{FrameBuffer, Font, RawColor};
use crate::{Display};
pub struct TextRenderer<'a, 'd, 'f> { pub struct TextRenderer<'a, 'd, 'f> {
pub framebuffer: &'a mut FrameBuffer<'d>, pub framebuffer: &'a mut FrameBuffer<'d>,
...@@ -24,10 +24,10 @@ impl<'a, 'd, 'f> Write for TextRenderer<'a, 'd, 'f> { ...@@ -24,10 +24,10 @@ impl<'a, 'd, 'f> Write for TextRenderer<'a, 'd, 'f> {
Some(glyph) => { Some(glyph) => {
for y in 0..self.font.h { for y in 0..self.font.h {
let y1 = (self.y + y as isize) as u16; let y1 = (self.y + y as isize) as u16;
if y1 < Display::H { if y1 < Display::H as u16 {
for x in 0..self.font.w { for x in 0..self.font.w {
let x1 = (self.x + x as isize) as u16; let x1 = (self.x + x as isize) as u16;
if x1 < Display::W { if x1 < Display::W as u16 {
if glyph.get_pixel(x as usize, y as usize) { if glyph.get_pixel(x as usize, y as usize) {
self.framebuffer[(x1, y1)] = self.color; self.framebuffer[(x1, y1)] = self.color;
} }
......
use core::str::from_utf8_unchecked; //! File System support (unfinished)
use core::mem::uninitialized; use core::mem::uninitialized;
use super::bindings::*; use core::str::from_utf8_unchecked;
use card10_sys::*;
type Result<T> = core::result::Result<T, Error>; type Result<T> = core::result::Result<T, Error>;
...@@ -28,9 +31,7 @@ impl From<i32> for Error { ...@@ -28,9 +31,7 @@ impl From<i32> for Error {
pub fn read_dir(path: &str) -> Result<ReadDir> { pub fn read_dir(path: &str) -> Result<ReadDir> {
let pathbuf = crate::str_to_cstr(path); let pathbuf = crate::str_to_cstr(path);
Error::check(|| unsafe { Error::check(|| unsafe { epic_file_opendir(pathbuf.as_ptr()) }).map(|fd| ReadDir { fd })
epic_file_opendir(pathbuf.as_ptr())
}).map(|fd| ReadDir { fd })
} }
pub struct ReadDir { pub struct ReadDir {
...@@ -68,7 +69,7 @@ pub struct epic_stat { ...@@ -68,7 +69,7 @@ pub struct epic_stat {
/// not u32 as generated by bindgen /// not u32 as generated by bindgen
pub type_: epic_stat_type, pub type_: epic_stat_type,
pub size: u32, pub size: u32,
pub name: [super::ctypes::c_char; 256usize], pub name: [ctypes::c_char; 256usize],
pub _reserved: [u8; 12usize], pub _reserved: [u8; 12usize],
} }
...@@ -97,20 +98,15 @@ impl DirStat { ...@@ -97,20 +98,15 @@ impl DirStat {
} }
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
let len = self.entry.name.iter().position(|b| *b == 0) let len = self.entry.name.iter().position(|b| *b == 0).unwrap_or(0);
.unwrap_or(0); unsafe { from_utf8_unchecked(&self.entry.name[0..len]) }
unsafe {
from_utf8_unchecked(&self.entry.name[0..len])
}
} }
} }
pub fn rename(from: &str, to: &str) -> Result<()> { pub fn rename(from: &str, to: &str) -> Result<()> {
let frombuf = crate::str_to_cstr(from); let frombuf = crate::str_to_cstr(from);
let tobuf = crate::str_to_cstr(to); let tobuf = crate::str_to_cstr(to);
Error::check(|| unsafe { Error::check(|| unsafe { epic_file_rename(frombuf.as_ptr(), tobuf.as_ptr()) }).map(|_| ())
epic_file_rename(frombuf.as_ptr(), tobuf.as_ptr())
}).map(|_| ())
} }
pub struct File { pub struct File {
...@@ -121,21 +117,22 @@ impl File { ...@@ -121,21 +117,22 @@ impl File {
pub fn open(path: &str) -> Result<File> { pub fn open(path: &str) -> Result<File> {
let pathbuf = crate::str_to_cstr(path); let pathbuf = crate::str_to_cstr(path);
let modebuf = b"r\0"; let modebuf = b"r\0";
Error::check(|| unsafe { Error::check(|| unsafe { epic_file_open(pathbuf.as_ptr(), modebuf.as_ptr()) })
epic_file_open(pathbuf.as_ptr(), modebuf.as_ptr()) .map(|fd| File { fd })
}).map(|fd| File { fd })
} }
pub fn read<'a>(&mut self, buf: &'a mut [u8]) -> Result<&'a [u8]> { pub fn read<'a>(&mut self, buf: &'a mut [u8]) -> Result<&'a [u8]> {
let bytes = Error::check(|| unsafe { let bytes =
epic_file_read(self.fd, buf.as_ptr() as *mut _, buf.len()) Error::check(|| unsafe { epic_file_read(self.fd, buf.as_ptr() as *mut _, buf.len()) })?
})? as usize; as usize;
Ok(&buf[0..bytes]) Ok(&buf[0..bytes])
} }
} }
impl Drop for File { impl Drop for File {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { epic_file_close(self.fd); } unsafe {
epic_file_close(self.fd);
}
} }
} }
//! Lights
use card10_sys::*;
#[derive(Clone, Copy)]
pub enum LEDColor {
RGB(u8, u8, u8),
HSV(f32, f32, f32),
}
/// Update all RGB LEDs
///
/// `f` must supply a `LEDColor` for `0..=10`.
pub fn update_rgb_leds<F>(f: F)
where
F: Fn(i32) -> LEDColor,
{
for index in 0..=10 {
let color = f(index);
match color {
LEDColor::RGB(r, g, b) => unsafe {
epic_leds_prep(index, r, g, b);
}
LEDColor::HSV(h, s, v) => unsafe {
epic_leds_prep_hsv(index, h, s, v);
}
}
unsafe {
epic_leds_update();
}
}
}
/// Set powersave mode for the RGB leds
///
/// Setting powersave mode disables the LEDs, saving
/// ~15 mA
pub fn set_rgb_leds_powersave(v: bool) {
unsafe { epic_leds_set_powersave(v); }
}
#[repr(i32)]
pub enum Rocket {
Blue = 0,
Yellow = 1,
Green = 2,
}
/// Set one of the rocket LEDs to the desired brightness.
///
/// Brightness should be 0 - 31; larger values will be clamped.
pub fn set_rocket(r: Rocket, brightness: u8) {
let v = if brightness > 31{31} else {brightness}; // clamp
unsafe { epic_leds_set_rocket(r as i32, v) }
}
//! [Repository](https://git.card10.badge.events.ccc.de/astro/rust-card10)
#![no_std]
mod os;
pub use os::*;
mod display;
pub use display::{Color, Display, FillStyle, Font, LineStyle};
mod buttons;
pub mod framebuffer;
pub use buttons::Buttons;
pub mod uart;
pub const UART: uart::Uart = uart::Uart;
mod light_sensor;
pub use light_sensor::LightSensor;
mod rtc;
pub mod trng;
pub mod vibra;
pub use rtc::{MilliSeconds, Seconds, Time};
mod fmt_buffer;
pub use fmt_buffer::{str_to_cstr, FmtBuffer};
mod bme680;
pub use bme680::BME680;
mod max86150;
pub use max86150::MAX86150;
mod bhi160;
pub use bhi160::{
Accelerometer, Error as BHI160Error, Gyroscope, Orientation, Sensor as BHI160,
SensorData as BHI160Data,
};
pub mod fs;
mod leds;
pub use leds::*;
/// Type check the user-supplied entry function.
#[macro_export]
macro_rules! main {
($path:path) => {
#[export_name = "main"]
pub unsafe fn __main() {
// type check the given path
let f: fn() = $path;
f()
}
};
}
use super::bindings::*; use card10_sys::*;
pub struct LightSensor; /// Light sensor
pub struct LightSensor {
// Prevent creation of this struct by all but this module.
_private: (),
}
impl LightSensor { impl LightSensor {
/// Start sensing light
pub fn start() -> Self { pub fn start() -> Self {
if unsafe { epic_light_sensor_run() } != 0 { if unsafe { epic_light_sensor_run() } != 0 {
panic!("Cannot start light sensor"); panic!("Cannot start light sensor");
} }
LightSensor LightSensor { _private: () }
} }
/// Obtain current light sensor reading
pub fn get(&self) -> Option<u16> { pub fn get(&self) -> Option<u16> {
let mut result = 0; let mut result = 0;
if unsafe { epic_light_sensor_get(&mut result) } == 0 { if unsafe { epic_light_sensor_get(&mut result) } == 0 {
...@@ -22,6 +28,8 @@ impl LightSensor { ...@@ -22,6 +28,8 @@ impl LightSensor {
impl Drop for LightSensor { impl Drop for LightSensor {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { epic_light_sensor_stop(); } unsafe {
epic_light_sensor_stop();
}
} }
} }
// ECG and PPG sensor
pub struct MAX86150 {
stream_id: i32,
}
use core::{mem::size_of, mem::MaybeUninit};
use card10_sys::*;
// TODO: redefine in common sensor
use crate::bhi160::Error;
const DATA_MAX: usize = 128;
impl MAX86150 {
pub fn start() -> Result<Self, Error> {
let mut cfg = max86150_sensor_config {
sample_buffer_len: DATA_MAX,
ppg_sample_rate: 200,
};
let stream_id =
unsafe { epic_max86150_enable_sensor(&mut cfg, size_of::<max86150_sensor_config>()) };
if stream_id < 0 {
let error = match -stream_id {
errno::EBUSY => Error::DriverBusy,
_ => Error::Unknown(stream_id),
};
return Err(error);
}
Ok(MAX86150 { stream_id })
}
pub fn read(&self) -> Result<MAX86150SensorData, Error> {
let mut buffer = MaybeUninit::<[max86150_sensor_data; DATA_MAX]>::zeroed();
let buffer_pointer = buffer.as_mut_ptr() as *mut _;
let packet_count = unsafe {
epic_stream_read(
self.stream_id,
buffer_pointer,
size_of::<max86150_sensor_data>() * DATA_MAX,
)
};
if packet_count < 0 {
let error = match -packet_count {
errno::ENODEV => Error::SensorUnavailable,
errno::EBADF => Error::SensorDescriptorUnknown,
errno::EINVAL => Error::InvalidSampleCount,
errno::EBUSY => Error::CouldNotAcquireLock,
_ => Error::Unknown(packet_count),
};
return Err(error);
}
Ok(MAX86150SensorData {
buf: unsafe { buffer.assume_init() },
n: packet_count as usize,
})
}
}
pub struct MAX86150SensorData {
buf: [max86150_sensor_data; DATA_MAX],
n: usize,
}
impl MAX86150SensorData {
pub const fn is_empty(&self) -> bool {
self.n == 0
}
pub const fn len(&self) -> usize {
self.n
}
}
impl<'a> IntoIterator for &'a MAX86150SensorData {
type Item = MAX86150SensorDataItem;
type IntoIter = MAX86150SensorDataIterator<'a>;
fn into_iter(self) -> Self::IntoIter {
MAX86150SensorDataIterator { data: self, pos: 0 }
}
}
pub struct MAX86150SensorDataIterator<'a> {
data: &'a MAX86150SensorData,
pos: usize,
}
#[derive(Debug, Clone)]
pub struct MAX86150SensorDataItem {
pub red_raw: u32,
pub ir_raw: u32,
pub ecg_raw: i32,
}
impl MAX86150SensorDataItem {
pub fn get_red(&self) -> u32 {
self.red_raw
}
}
impl<'a> Iterator for MAX86150SensorDataIterator<'a> {
type Item = MAX86150SensorDataItem;
fn next(&mut self) -> Option<Self::Item> {
while self.pos < self.data.n {
let vec = &self.data.buf[self.pos];
let item = MAX86150SensorDataItem {
red_raw: vec.red,
ir_raw: vec.ir,
ecg_raw: vec.ecg,
};
self.pos += 1;
return Some(item);
}
None
}
}
impl Drop for MAX86150 {
fn drop(&mut self) {
unsafe {
epic_max86150_disable_sensor();
}
}
}
use super::bindings::*; use card10_sys::*;
/// Execute Python script or ELF file
pub fn exec(path: &str) -> ! { pub fn exec(path: &str) -> ! {
let mut pathbuf = super::str_to_cstr(path); let mut pathbuf = super::str_to_cstr(path);
unsafe { unsafe {
...@@ -8,16 +9,18 @@ pub fn exec(path: &str) -> ! { ...@@ -8,16 +9,18 @@ pub fn exec(path: &str) -> ! {
unreachable!() unreachable!()
} }
/// Exit current l0dable
pub fn exit(ret: i32) -> ! { pub fn exit(ret: i32) -> ! {
unsafe { unsafe {
epic_exit(ret); epic_exit(ret);
} }
unreachable!() loop {}
} }
/// Cause a reboot
pub fn system_reset() -> ! { pub fn system_reset() -> ! {
unsafe { unsafe {
epic_system_reset(); epic_system_reset();
} }
unreachable!() loop {}
} }
//! Real-time clock functionality
use card10_sys::*;
use core::ops::Sub; use core::ops::Sub;
use super::bindings::*;
/// Implemented for `Seconds` and `Milliseconds`
pub trait Time { pub trait Time {
/// Get current time
fn time() -> Self; fn time() -> Self;
/// Set the time (TODO)
fn set_time(&self); fn set_time(&self);
} }
...@@ -20,8 +25,8 @@ impl Time for Seconds { ...@@ -20,8 +25,8 @@ impl Time for Seconds {
let s = unsafe { epic_rtc_get_seconds() }; let s = unsafe { epic_rtc_get_seconds() };
Seconds(s) Seconds(s)
} }
/// TODO
fn set_time(&self) { fn set_time(&self) {
// TODO
} }
} }
...@@ -46,8 +51,8 @@ impl Time for MilliSeconds { ...@@ -46,8 +51,8 @@ impl Time for MilliSeconds {
let ms = unsafe { epic_rtc_get_milliseconds() }; let ms = unsafe { epic_rtc_get_milliseconds() };
MilliSeconds(ms) MilliSeconds(ms)
} }
/// TODO
fn set_time(&self) { fn set_time(&self) {
// TODO
} }
} }
......
use super::bindings::*; //! True Random Number Generator
use card10_sys::*;
/// Read bytes from the True Random Number Generated
pub fn read(dest: &mut [u8]) -> bool { pub fn read(dest: &mut [u8]) -> bool {
unsafe { epic_trng_read(dest.as_mut_ptr(), dest.len()) != 0 } unsafe { epic_trng_read(dest.as_mut_ptr(), dest.len()) != 0 }
} }
use core::fmt::Write; use core::fmt::Write;
use super::bindings::*;
use card10_sys::*;
/// USB UART, 115200 baud
///
/// Supports use of `write!(Uart, "{}", ...);` Use `println!(...);`
/// for convenience.
pub struct Uart; pub struct Uart;
impl Write for Uart { impl Write for Uart {
fn write_str(&mut self, s: &str) -> core::fmt::Result { fn write_str(&mut self, s: &str) -> core::fmt::Result {
unsafe { unsafe {
epic_uart_write_str(s.as_ptr(), s.len() as isize); epic_uart_write_str(s.as_ptr(), s.len());
} }
Ok(()) Ok(())
} }
...@@ -25,6 +30,5 @@ macro_rules! println { ...@@ -25,6 +30,5 @@ macro_rules! println {
#[doc(hidden)] #[doc(hidden)]
pub fn _print(args: core::fmt::Arguments) { pub fn _print(args: core::fmt::Arguments) {
use core::fmt::Write; crate::UART.write_fmt(args).ok();
crate::UART.write_fmt(args);
} }
//! Vibration motor
use card10_sys::*;
/// Set vibration motor to off/on
pub fn set(status: bool) {
unsafe {
epic_vibra_set(status.into());
}
}
/// Vibrate for a duration
pub fn vibrate(millis: i32) {
unsafe {
epic_vibra_vibrate(millis);
}
}
[package]
name = "card10-sys"
version = "1.10.0"
authors = [
"Astro <astro@spaceboyz.net>",
"Kloenk <me@kloenk.de>",
"Bruno Kirschner <bruno.kirschner@online.de>",
"Puzzlewolf <camp@nora.pink>",
"Raphael Nestler <raphael.nestler@gmail.com>",
"Danilo Bargen <mail@dbrgn.ch>",
"toon <toon@c3d2.de>",
"Sergey Pepyakin <sergei@parity.io>",
]
license = "MIT/Apache-2.0"
edition = "2018"
description = "Unsafe C bindings for card10 l0dables"
repository = "https://git.card10.badge.events.ccc.de/astro/rust-card10"
homepage = "https://git.card10.badge.events.ccc.de/astro/rust-card10"
documentation = "https://docs.rs/card10-sys"
categories = ["external-ffi-bindings", "no-std"]
keywords = [
"CCC",
"CCCamp2019",
"CCCamp19",
"card10",
"l0dable",
]
exclude = [
"target",
"firmware/lib/micropython",
"firmware/lib/ff13",
"firmware/lib/sdk/Documentation",
"firmware/lib/sdk/Applications",
"firmware/lib/sdk/Libraries/BTLE",
"firmware/lib/sdk/Libraries/FreeRTOS",
"firmware/lib/sdk/Libraries/FreeRTOS-Plus",
"firmware/lib/sdk/Libraries/SDHC",
"firmware/lib/sdk/Libraries/MAXUSB",
"firmware/openocd",
"firmware/Documentation",
"firmware/hw-tests",
"firmware/preload",
"firmware/pycardium",
"firmware/bootloader",
"firmware/tools",
"firmware/docker",
]
[dependencies]
r0 = "^0.2"
[build-dependencies]
bindgen = "^0.52"
cc = "^1.0"
use std::{env, error::Error, fs, path::PathBuf};
fn main() -> Result<(), Box<dyn Error>> {
let out = env::var_os("OUT_DIR")
.map(|path| PathBuf::from(path))
.ok_or("OUT_DIR definition missing")?;
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=vendor/l0dable.ld");
println!("cargo:rerun-if-changed=vendor/client.c");
println!("cargo:rerun-if-changed=vendor/wrapper.h");
println!("cargo:rustc-link-search={}", out.display());
// Linker script
fs::copy("vendor/crt.s", out.join("crt.s"))?;
fs::copy("vendor/l0dable.ld", out.join("l0dable.ld"))?;
// Link against C code
cc::Build::new()
.target("thumbv7em-none-eabi")
.compiler("arm-none-eabi-gcc")
.opt_level_str("s")
.debug(true)
.define("TARGET", "MAX32665")
.define("TARGET_UC", "MAX32665")
.define("TARGET_LC", "max32665")
.define("TARGET_REV", "0x4131")
.define("BOARD", "card10")
.flag("-fPIE")
.flag("-pie")
.include("firmware/epicardium")
.include("firmware/lib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665/Include")
.include("firmware/lib/sdk/Libraries/CMSIS/Include")
.include("firmware/lib/sdk/Libraries/MAX32665PeriphDriver/Include")
.file("firmware/lib/sdk/Libraries/MAX32665PeriphDriver/Source/sema.c")
.file("firmware/lib/sdk/Libraries/MAX32665PeriphDriver/Source/mxc_assert.c")
.file("firmware/l0dables/lib/hardware.c")
.file("firmware/epicardium/api/caller.c")
.file("firmware/lib/gfx/Fonts/font12.c")
.file("firmware/lib/gfx/Fonts/font16.c")
.file("firmware/lib/gfx/Fonts/font20.c")
.file("firmware/lib/gfx/Fonts/font24.c")
.file("firmware/lib/gfx/Fonts/font8.c")
.file("vendor/client.c")
.compile("card10");
// Generate bindings to C code
let bindings = bindgen::Builder::default()
.use_core()
.clang_arg("-Isrc")
.clang_arg("-Ifirmware/epicardium")
.clang_arg("-Ifirmware/lib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665/Include")
.clang_arg("-Ifirmware/lib/sdk/Libraries/CMSIS/Include")
.clang_arg("-Ifirmware/lib/sdk/Libraries/MAX32665PeriphDriver/Include")
.header("vendor/wrapper.h")
.ctypes_prefix("ctypes")
.opaque_type("epic_stat")
.generate()
.map_err(|_| "Couldn't generate bindings")?;
bindings.write_to_file(out.join("bindings.rs"))?;
Ok(())
}
firmware @ da4bc11f
Subproject commit da4bc11fbdded3588a97b1f905da4866a30f520c
//! This gets linked with the client C code for the card10 EPIC API.
#![no_std] #![no_std]
#![feature(global_asm)] #![feature(global_asm)]
#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
#![allow(non_snake_case)]
#![feature(core_intrinsics)]
#![feature(panic_info_message)]
use core::fmt::Write;
use core::intrinsics;
use core::panic::PanicInfo;
pub struct Uart;
use panic_abort as _; impl Write for Uart {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
unsafe {
epic_uart_write_str(s.as_ptr(), s.len());
}
Ok(())
}
}
global_asm!(include_str!("crt.s")); #[panic_handler]
fn panic(info: &PanicInfo) -> ! {
write!(Uart, "panicked").ok();
/// Type check the user-supplied entry function. if let Some(message) = info.message() {
#[macro_export] write!(Uart, " at '{}'", message).ok();
macro_rules! main { }
($path:path) => {
#[export_name = "main"]
pub unsafe fn __main() {
// type check the given path
let f: fn() = $path;
f() if let Some(location) = info.location() {
write!(
Uart,
", {}:{}:{}",
location.file(),
location.line(),
location.column()
)
.ok();
} }
}; writeln!(Uart, "\r").ok();
unsafe { intrinsics::abort() }
} }
global_asm!(include_str!(concat!(env!("OUT_DIR"), "/crt.s")));
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
/// Initialization for l0dables
#[link_section = ".text.boot"] #[link_section = ".text.boot"]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn Reset_Handler() -> ! { pub unsafe extern "C" fn Reset_Handler() -> ! {
extern "C" { extern "C" {
fn SystemInit(); fn SystemInit();
// Boundaries of the .bss section, provided by the linker script // Boundaries of the .bss section, provided by the linker script
static mut __bss_start: u64; static mut __bss_start: u32;
static mut __bss_end: u64; static mut __bss_end: u32;
} }
// Zeroes the .bss section // Zeroes the .bss section
...@@ -38,12 +68,12 @@ pub unsafe extern "C" fn Reset_Handler() -> ! { ...@@ -38,12 +68,12 @@ pub unsafe extern "C" fn Reset_Handler() -> ! {
} }
main(); main();
exit(0);
epic_exit(0);
unreachable!()
} }
pub mod ctypes { pub mod ctypes {
#![allow(non_camel_case_types)]
pub type c_short = i16; pub type c_short = i16;
pub type c_ushort = u16; pub type c_ushort = u16;
pub type c_int = i32; pub type c_int = i32;
...@@ -59,7 +89,6 @@ pub mod ctypes { ...@@ -59,7 +89,6 @@ pub mod ctypes {
} }
pub mod errno { pub mod errno {
#![allow(non_snake_case)]
use crate::ctypes::c_int; use crate::ctypes::c_int;
pub const EPERM: c_int = 1; // Operation not permitted pub const EPERM: c_int = 1; // Operation not permitted
...@@ -101,37 +130,3 @@ pub mod errno { ...@@ -101,37 +130,3 @@ pub mod errno {
pub const ETIMEDOUT: c_int = 110; //Connection timed out pub const ETIMEDOUT: c_int = 110; //Connection timed out
pub const EINPROGRESS: c_int = 115; //Operation now in progress pub const EINPROGRESS: c_int = 115; //Operation now in progress
} }
pub mod bindings {
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
}
mod os;
pub use os::*;
mod display;
pub use display::{Display, Color, LineStyle, FillStyle};
pub mod framebuffer;
mod buttons;
pub use buttons::Buttons;
pub mod uart;
pub const UART: uart::Uart = uart::Uart;
mod light_sensor;
pub use light_sensor::LightSensor;
pub mod vibra;
pub mod trng;
mod rtc;
pub use rtc::{Seconds, MilliSeconds, Time};
mod fmt_buffer;
pub use fmt_buffer::{FmtBuffer, str_to_cstr};
mod bme680;
pub use bme680::BME680;
mod bhi160;
pub use bhi160::{
Accelerometer, Error as BHI160Error, Gyroscope, Orientation, Sensor as BHI160,
SensorData as BHI160Data,
};
pub mod fs;
File moved
File moved
This diff is collapsed.