Skip to content
Snippets Groups Projects
Commit fd7d8044 authored by Astro's avatar Astro :gear:
Browse files

Merge branch 'rnd/task/card10-sys'

Fixes MR !13
parents 7f040415 be4030fa
No related branches found
No related tags found
1 merge request!13Introduce card10-sys.
Pipeline #3771 passed
Showing
with 210 additions and 88 deletions
[submodule "c"]
path = c
[submodule "card10-sys/firmware"]
path = card10-sys/firmware
url = https://git.card10.badge.events.ccc.de/card10/firmware.git
......@@ -80,6 +80,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "card10-l0dable"
version = "0.1.1"
dependencies = [
"card10-sys 0.1.0",
]
[[package]]
name = "card10-sys"
version = "0.1.0"
dependencies = [
"bindgen 0.51.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
......
[workspace]
members = [
"l0dable",
"card10-sys",
"card10-l0dable",
"example",
"rkanoid",
]
default-members = [
"example",
"rkanoid",
......
......@@ -51,7 +51,7 @@ https://firmware.card10.badge.events.ccc.de/how-to-build.html this
should work as following:
```shell
cd c/
cd card10-sys/firmware
./bootstrap -Djailbreak_card10=true
ninja -C build/
```
......@@ -61,10 +61,63 @@ And then copy `build/pycardium/pycardium_epicardium.bin` as
## Build and run Rust loadables
### Setup
If you want to come up with your own rust based loadable crate a few
preparations are required:
- Setup the new crate repository.
- Add `card10-l0dable = "^0.1"` as a dependency to your new crate.
- Change the configuration of the default cargo release profile inside your
`Cargo.toml` file:
```
[profile.release]
opt-level = "s"
panic = "abort"
```
- Create (or update) the `thumbv7em-none-eabi` target configuration at
`$PROJECT/.cargo/config` with the following rustflags:
```
[target.thumbv7em-none-eabi]
rustflags = [
"-C", "linker=arm-none-eabi-gcc",
"-C", "link-args=-Tl0dable.ld -n -pie -fPIC",
"-C", "relocation-model=pic",
]
[build]
target = "thumbv7em-none-eabi"
```
- Ensure that your crate is marked as a `non_std` project and make
`card10-l0dable` aware of your custom main function. This should require
the following update to your `main.rs` file.
```main.rs
#![no_std]
#![no_main]
use card10_l0dable::main;
main!(main);
fn main() {}
```
### Compilation
To compile the project use the nightly toolchain and define the proper target.
```shell
cargo +nightly build --release --target thumbv7em-none-eabi
```
### Transfer to card10
Then copy the resulting executable from the target directory
`target/thumbv7em-none-eabi/release/example` into the
`apps` directory of your badge.
......@@ -76,7 +129,7 @@ extension (e.g `example` must be renamed as `example.elf`).
| Crate | Description |
| ---- | --- |
| l0dable | Helper crate for building l0dables |
| card10-l0dable | Helper crate for building l0dables |
| example | l0dable example |
| rkanoid | Arkanoid clone |
......@@ -85,14 +138,14 @@ extension (e.g `example` must be renamed as `example.elf`).
### How to update the firmware bindings
1) Update the `c/` submodule to the latest firmware state.
1) Update the `card10-sys/firmware` submodule to the latest firmware state.
2) Rebuild the firmware as described above.
3) Run the following script from the project root directory
```shell
python c/epicardium/api/genapi.py -H c/epicardium/epicardium.h -c l0dable/src/client.c -s l0dable/src/server.c
python card10-sys/firmware/epicardium/api/genapi.py -H card10-sys/firmware/epicardium/epicardium.h -c card10-sys/vendor/client.c -s card10-sys/vendor/server.c
```
4) Rebuild your app :)
......
......@@ -14,20 +14,8 @@ keywords = [
"l0dable",
]
categories = ["no-std"]
description = """
make l0dables for the Card10 (CCCamp 2019) badge
"""
include = [
"**/*.rs",
"Cargo.toml",
"l0dable.ld",
"../c/",
]
description = "make l0dables for the Card10 (CCCamp 2019) badge"
[dependencies]
r0 = "0.2"
panic-abort = "0.3"
card10-sys = { path = "../card10-sys", version = "^0.1" }
[build-dependencies]
cc = "1.0"
bindgen = "0.51"
File moved
File moved
......@@ -4,7 +4,7 @@ use core::{
mem::MaybeUninit,
};
use crate::{bindings::*, errno};
use card10_sys::*;
pub trait SensorType {
/// sensor_type in C, sensor_id in Python
......
use card10_sys::*;
use core::mem::uninitialized;
use super::bindings::*;
pub struct BME680;
pub type SensorData = bme680_sensor_data;
......@@ -24,6 +24,8 @@ impl BME680 {
impl Drop for BME680 {
fn drop(&mut self) {
unsafe { epic_bme680_deinit(); }
unsafe {
epic_bme680_deinit();
}
}
}
use super::bindings::*;
use card10_sys::*;
pub struct Buttons {
state: u32,
......@@ -6,12 +6,11 @@ pub struct Buttons {
impl Buttons {
pub fn read() -> Self {
let mask =
epic_button_BUTTON_LEFT_BOTTOM |
epic_button_BUTTON_RIGHT_BOTTOM |
epic_button_BUTTON_LEFT_TOP |
epic_button_BUTTON_RIGHT_TOP |
epic_button_BUTTON_RESET;
let mask = epic_button_BUTTON_LEFT_BOTTOM
| epic_button_BUTTON_RIGHT_BOTTOM
| epic_button_BUTTON_LEFT_TOP
| epic_button_BUTTON_RIGHT_TOP
| epic_button_BUTTON_RESET;
let state = unsafe { epic_buttons_read(mask as u8) }.into();
Buttons { state }
}
......
use super::bindings::*;
use super::framebuffer::FrameBuffer;
use card10_sys::*;
#[derive(Debug, Clone, Copy)]
#[repr(C)]
......@@ -32,9 +32,7 @@ impl Color {
pub fn rgb8(r8: u8, g8: u8, b8: u8) -> Self {
let c =
((u16::from(r8) & 0xF8) << 8) |
((u16::from(g8) & 0xFA) << 3) |
(u16::from(b8) & 0xF8);
((u16::from(r8) & 0xF8) << 8) | ((u16::from(g8) & 0xFA) << 3) | (u16::from(b8) & 0xF8);
Color(c)
}
......@@ -84,16 +82,22 @@ impl Display {
pub const FONT_H: u16 = 20;
pub fn open() -> Self {
unsafe { epic_disp_open(); }
unsafe {
epic_disp_open();
}
Display
}
pub fn update(&self) {
unsafe { epic_disp_update(); }
unsafe {
epic_disp_update();
}
}
pub fn clear(&self, color: Color) {
unsafe { epic_disp_clear(color.0); }
unsafe {
epic_disp_clear(color.0);
}
}
/// s must be 0-terminated
......@@ -109,19 +113,45 @@ impl Display {
}
}
pub fn line(&self, x1: u16, y1: u16, x2: u16, y2: u16, color: Color, linestyle: LineStyle, pixelsize: u16) {
pub fn line(
&self,
x1: u16,
y1: u16,
x2: u16,
y2: u16,
color: Color,
linestyle: LineStyle,
pixelsize: u16,
) {
unsafe {
epic_disp_line(x1, y1, x2, y2, color.0, linestyle as u32, pixelsize);
}
}
pub fn rect(&self, x1: u16, y1: u16, x2: u16, y2: u16, color: Color, fillstyle: FillStyle, pixelsize: u16) {
pub fn rect(
&self,
x1: u16,
y1: u16,
x2: u16,
y2: u16,
color: Color,
fillstyle: FillStyle,
pixelsize: u16,
) {
unsafe {
epic_disp_rect(x1, y1, x2, y2, color.0, fillstyle as u32, pixelsize);
}
}
pub fn circ(&self, x: u16, y: u16, rad: u16, color: Color, fillstyle: FillStyle, pixelsize: u16) {
pub fn circ(
&self,
x: u16,
y: u16,
rad: u16,
color: Color,
fillstyle: FillStyle,
pixelsize: u16,
) {
unsafe {
epic_disp_circ(x, y, rad, color.0, fillstyle as u32, pixelsize);
}
......@@ -134,6 +164,8 @@ impl Display {
impl Drop for Display {
fn drop(&mut self) {
unsafe { epic_disp_close(); }
unsafe {
epic_disp_close();
}
}
}
File moved
use crate::Display;
use card10_sys::*;
use core::mem::{transmute, uninitialized};
use core::ops::{Index, IndexMut};
use crate::bindings::*;
use crate::Display;
mod font;
pub use font::*;
......@@ -13,14 +13,11 @@ pub struct FrameBuffer<'d> {
buffer: disp_framebuffer,
}
impl<'d> FrameBuffer<'d> {
pub fn uninitialized(display: &'d Display) -> Self {
FrameBuffer {
_display: display,
buffer: unsafe {
uninitialized()
},
buffer: unsafe { uninitialized() },
}
}
......@@ -33,18 +30,26 @@ impl<'d> FrameBuffer<'d> {
pub fn clear(&mut self, color: RawColor) {
for y in 0..Display::H {
for x in 0..Display::W {
let bytes: &mut RawColor = unsafe {
transmute(&mut self.buffer.fb[y as usize][x as usize])
};
let bytes: &mut RawColor =
unsafe { transmute(&mut self.buffer.fb[y as usize][x as usize]) };
*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 {
framebuffer: self,
x, y, font, color,
x,
y,
font,
color,
}
}
}
......@@ -54,9 +59,7 @@ impl<'d> Index<(u16, u16)> for FrameBuffer<'d> {
fn index(&self, (x, y): (u16, u16)) -> &Self::Output {
let x = usize::from(Display::W - 1 - x);
let y = usize::from(Display::H - 1 - y);
unsafe {
transmute(&self.buffer.fb[y][x])
}
unsafe { transmute(&self.buffer.fb[y][x]) }
}
}
......@@ -64,9 +67,7 @@ impl<'d> IndexMut<(u16, u16)> for FrameBuffer<'d> {
fn index_mut(&mut self, (x, y): (u16, u16)) -> &mut Self::Output {
let x = usize::from(Display::W - 1 - x);
let y = usize::from(Display::H - 1 - y);
unsafe {
transmute(&mut self.buffer.fb[y][x])
}
unsafe { transmute(&mut self.buffer.fb[y][x]) }
}
}
......
use core::str::from_utf8_unchecked;
use core::mem::uninitialized;
use super::bindings::*;
use core::str::from_utf8_unchecked;
use card10_sys::*;
type Result<T> = core::result::Result<T, Error>;
......@@ -28,9 +29,7 @@ impl From<i32> for Error {
pub fn read_dir(path: &str) -> Result<ReadDir> {
let pathbuf = crate::str_to_cstr(path);
Error::check(|| unsafe {
epic_file_opendir(pathbuf.as_ptr())
}).map(|fd| ReadDir { fd })
Error::check(|| unsafe { epic_file_opendir(pathbuf.as_ptr()) }).map(|fd| ReadDir { fd })
}
pub struct ReadDir {
......@@ -68,7 +67,7 @@ pub struct epic_stat {
/// not u32 as generated by bindgen
pub type_: epic_stat_type,
pub size: u32,
pub name: [super::ctypes::c_char; 256usize],
pub name: [ctypes::c_char; 256usize],
pub _reserved: [u8; 12usize],
}
......@@ -97,20 +96,15 @@ impl DirStat {
}
pub fn name(&self) -> &str {
let len = self.entry.name.iter().position(|b| *b == 0)
.unwrap_or(0);
unsafe {
from_utf8_unchecked(&self.entry.name[0..len])
}
let len = self.entry.name.iter().position(|b| *b == 0).unwrap_or(0);
unsafe { from_utf8_unchecked(&self.entry.name[0..len]) }
}
}
pub fn rename(from: &str, to: &str) -> Result<()> {
let frombuf = crate::str_to_cstr(from);
let tobuf = crate::str_to_cstr(to);
Error::check(|| unsafe {
epic_file_rename(frombuf.as_ptr(), tobuf.as_ptr())
}).map(|_| ())
Error::check(|| unsafe { epic_file_rename(frombuf.as_ptr(), tobuf.as_ptr()) }).map(|_| ())
}
pub struct File {
......@@ -121,21 +115,22 @@ impl File {
pub fn open(path: &str) -> Result<File> {
let pathbuf = crate::str_to_cstr(path);
let modebuf = b"r\0";
Error::check(|| unsafe {
epic_file_open(pathbuf.as_ptr(), modebuf.as_ptr())
}).map(|fd| File { fd })
Error::check(|| unsafe { epic_file_open(pathbuf.as_ptr(), modebuf.as_ptr()) })
.map(|fd| File { fd })
}
pub fn read<'a>(&mut self, buf: &'a mut [u8]) -> Result<&'a [u8]> {
let bytes = Error::check(|| unsafe {
epic_file_read(self.fd, buf.as_ptr() as *mut _, buf.len())
})? as usize;
let bytes =
Error::check(|| unsafe { epic_file_read(self.fd, buf.as_ptr() as *mut _, buf.len()) })?
as usize;
Ok(&buf[0..bytes])
}
}
impl Drop for File {
fn drop(&mut self) {
unsafe { epic_file_close(self.fd); }
unsafe {
epic_file_close(self.fd);
}
}
}
#![no_std]
mod os;
pub use os::*;
mod display;
pub use display::{Color, Display, FillStyle, 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 bhi160;
pub use bhi160::{
Accelerometer, Error as BHI160Error, Gyroscope, Orientation, Sensor as BHI160,
SensorData as BHI160Data,
};
pub mod fs;
/// 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 {
// Prevent creation of this struct by all but this module.
......@@ -25,6 +25,8 @@ impl LightSensor {
impl Drop for LightSensor {
fn drop(&mut self) {
unsafe { epic_light_sensor_stop(); }
unsafe {
epic_light_sensor_stop();
}
}
}
use super::bindings::*;
use card10_sys::*;
pub fn exec(path: &str) -> ! {
let mut pathbuf = super::str_to_cstr(path);
......
use card10_sys::*;
use core::ops::Sub;
use super::bindings::*;
pub trait Time {
fn time() -> Self;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment