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
  • 4-fix-card10-l0dable-on-crates-io
  • 5-implement-client-c-in-plain-rust
  • api
  • build-from-root
  • master
  • no-str_to_cstr
  • card10-alloc-0.1.0
  • card10-alloc-0.1.1
  • card10-l0dable-0.2.0
  • card10-l0dable-0.3.0
  • card10-sys-1.10.0
  • card10-sys-1.9.0
12 results

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
  • add-sensor-plot
  • add-submodule-instruction-to-readme
  • master
3 results
Show changes
Commits on Source (136)
Showing
with 679 additions and 234 deletions
#!/usr/bin/env bash
set -e
cargo build --release
arm-none-eabi-objcopy -O binary target/thumbv7em-none-eabi/release/$2 card10.bin
python c/bootloader/crc_patch.py card10.bin
echo "Copy this file to the device in USB Mass Storage mode:"
ls -l card10.bin
......@@ -29,4 +29,5 @@ firmware:
- apps
- main.py
- menu.py
- card10.cfg
expire_in: 1 week
[submodule "c"]
path = c
[submodule "card10-sys/firmware"]
path = card10-sys/firmware
url = https://git.card10.badge.events.ccc.de/card10/firmware.git
From 93c318a284f7b0f3bce2046e1f631599190eaa10 Mon Sep 17 00:00:00 2001
From: Astro <astro@spaceboyz.net>
Date: Fri, 23 Aug 2019 19:44:45 +0200
Subject: [PATCH] feat(nix): add jailbreak arg
---
default.nix | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/default.nix b/default.nix
index dc9649bc..c49d0ab2 100644
--- a/default.nix
+++ b/default.nix
@@ -1,4 +1,8 @@
-with import <nixpkgs> {};
+{ pkgs ? import <nixpkgs> {},
+ jailbreak ? false,
+}:
+
+with pkgs;
let
py = python36;
@@ -12,6 +16,10 @@ let
sha256 = "15nkx0pa4lskwin84flpk8fsw3jqg6wic6v3s83syjqg76h6my61";
};
};
+ mesonOpt =
+ if jailbreak
+ then "-Djailbreak_card10=true"
+ else "";
in stdenv.mkDerivation rec {
name = "card10";
nativeBuildInputs = [
@@ -39,7 +47,7 @@ in stdenv.mkDerivation rec {
done
# Actually run the build.
- meson --cross-file card10-cross.ini "$build"
+ meson --cross-file card10-cross.ini ${mesonOpt} "$build"
ninja -C "$build" -j $NIX_BUILD_CORES
# Copy ELFs for debugging
--
2.22.0
From baef13b1adb6f7bf01a7dfd7f4f44a5a3e950b1d Mon Sep 17 00:00:00 2001
From: Astro <astro@spaceboyz.net>
Date: Thu, 5 Sep 2019 02:22:45 +0200
Subject: [PATCH] hack(epicardium): reduce init delay from 2s to 0.1s
---
epicardium/main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/epicardium/main.c b/epicardium/main.c
index 51edbe93..7607d39d 100644
--- a/epicardium/main.c
+++ b/epicardium/main.c
@@ -32,7 +32,7 @@ int main(void)
epic_disp_print(10, 20, "Epicardium", 0xfe20, 0x0000);
epic_disp_print(off > 0 ? off : 0, 40, version_buf, 0xfe20, 0x0000);
epic_disp_update();
- mxc_delay(2000000);
+ mxc_delay(100000);
LOG_DEBUG("startup", "Initializing tasks ...");
--
2.22.1
This diff is collapsed.
[workspace]
members = [
"l0dable",
"card10-sys",
"card10-alloc",
"card10-l0dable",
"example",
"rkanoid",
"draw-image",
]
default-members = [
"example",
"rkanoid",
"draw-image",
]
[profile.release]
......@@ -16,3 +21,6 @@ debug = true
opt-level = "s"
lto = true
panic = "abort"
[patch.crates-io]
alloc-cortex-m = { git = 'https://github.com/rust-embedded/alloc-cortex-m' }
# Rust support for the card10 CCCamp19 badge
## Prepare your card10
**Jailbreaking is no longer necessary!**
Starting with firmware v1.9, running ELF binaries requires a
`/card10.cfg` with the following content:
```
execute_elf=true
```
## Prebuilt binaries
By courtesy of this Gitlab's CI system, and NixOS, we build `.elf`
files for you drop into the `apps/` directory of your card10 badge.
Because running ELF binaries requires a jailbroken base firmware
starting with v1.5, we build this one too. It includes this project's
Rust binaries.
For each commit in this repository, we also build complete firmware
images with the required configuration and our example binaries.
https://git.card10.badge.events.ccc.de/astro/rust-card10/-/jobs
......@@ -40,31 +50,65 @@ firmware including the matching libc.
git submodule update --init --recursive
```
## Setup a Rust enabled firmware
## Build and run Rust loadables
To allow rust based apps on card10 you need a firmware which allows
to run custom elf binaries on the core. This requires a custom build
with `-Djailbreak_card10=true` as bootstrapping flag.
### Setup
Assuming that you installed all required dependencies mentioned in
https://firmware.card10.badge.events.ccc.de/how-to-build.html this
should work as following:
If you want to come up with your own rust based loadable crate a few
preparations are required:
```shell
cd c/
./bootstrap -Djailbreak_card10=true
ninja -C build/
- 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"
```
And then copy `build/pycardium/pycardium_epicardium.bin` as
`card10.bin` onto your badge.
- Create (or update) the `thumbv7em-none-eabi` target configuration at
`$PROJECT/.cargo/config` with the following rustflags:
## Build and run Rust loadables
```
[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.
......@@ -74,29 +118,32 @@ extension (e.g `example` must be renamed as `example.elf`).
## Crates
| Crate | Description |
| ---- | --- |
| l0dable | Helper crate for building l0dables |
| example | l0dable example |
| rkanoid | Arkanoid clone |
| Crate | Documentation | Description |
| ---- | --- | --- |
| card10-sys | [docs.rs][card10-sys] | Unsafe C bindings for l0dables |
| card10-alloc | [docs.rs][card10-alloc] | alloc::* support for l0dables |
| card10-l0dable | [docs.rs][card10-l0dable] | High-level crate for building l0dables |
| example | | l0dable example |
| rkanoid | | Arkanoid clone |
| draw-image | | Example of drawing a static image to the display |
[card10-sys]: https://docs.rs/card10-sys/
[card10-alloc]: https://docs.rs/card10-alloc/
[card10-l0dable]: https://docs.rs/card10-l0dable/
## Misc
### 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 :)
## TODO
- [ ] alloc
c @ 45c228ac
Subproject commit 45c228ac4887d2a838dcbb563c45182e579c5e35
[package]
edition = "2018"
name = "card10-l0dable"
name = "card10-alloc"
version = "0.1.1"
authors = ["Astro <astro@spaceboyz.net>", "Kloenk <me@kloenk.de>"]
authors = ["Astro <astro@spaceboyz.net>"]
license = "MIT/Apache-2.0"
edition = "2018"
description = "Dynamic memory allocation 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-alloc"
categories = ["no-std", "memory-management"]
keywords = [
"CCC",
"CCCamp2019",
......@@ -13,21 +19,7 @@ keywords = [
"card10",
"l0dable",
]
categories = ["no-std"]
description = """
make l0dables for the Card10 (CCCamp 2019) badge
"""
include = [
"**/*.rs",
"Cargo.toml",
"l0dable.ld",
"../c/",
]
[dependencies]
r0 = "0.2"
panic-abort = "0.3"
[build-dependencies]
cc = "1.0"
bindgen = "0.51"
alloc-cortex-m = "0.3"
card10-sys = { path = "../card10-sys" }
//! Support for dynamically allocated memory
//!
//! Reproduces l0dable hardware.c's `_sbrk()`
//!
//! Unfortunately, we cannot link `_sbrk()` directly because it
//! references the unwieldy `errno`.
//!
//! ## Example
//!
//! ```rust
//! #![no_std]
//! #![no_main]
//!
//! extern crate alloc;
//! use alloc::vec;
//! use card10_l0dable::*;
//!
//! main!(main);
//! fn main() {
//! // Pass stack headroom
//! card10_alloc::init(128 * 1024);
//! let mut xs = vec![];
//! xs.push(23);
//! }
//! ```
#![no_std]
#![feature(asm)]
#![feature(alloc_error_handler)]
use core::alloc::Layout;
use alloc_cortex_m::CortexMHeap;
use card10_sys as _;
#[global_allocator]
static ALLOCATOR: CortexMHeap = CortexMHeap::empty();
extern "C" {
static mut __heap_start: u32;
}
#[inline(always)]
fn sp() -> usize {
let mut value;
unsafe {
asm!("mov $0, sp" : "=r" (value) ::: "volatile");
}
value
}
/// Call this before using anything from `alloc`.
///
/// Consider the size of your stack-allocated variables for the
/// `stack_headroom` parameter.
///
/// Returns heap size
pub fn init(stack_headroom: usize) -> usize {
let start = unsafe { &__heap_start } as *const _ as usize;
let size = sp() - stack_headroom - start;
unsafe { ALLOCATOR.init(start, size); }
size
}
#[alloc_error_handler]
fn on_oom(_layout: Layout) -> ! {
panic!("OOM")
}
[package]
edition = "2018"
name = "card10-l0dable"
version = "0.3.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"
repository = "https://git.card10.badge.events.ccc.de/astro/rust-card10"
homepage = "https://git.card10.badge.events.ccc.de/astro/rust-card10"
keywords = [
"CCC",
"CCCamp2019",
"CCCamp19",
"card10",
"l0dable",
]
categories = ["no-std"]
description = "make l0dables for the Card10 (CCCamp 2019) badge"
documentation = "https://docs.rs/card10-l0dable"
[dependencies]
card10-sys = { path = "../card10-sys" }
embedded-graphics = "0.5"
File moved
File moved
/// Accelerometer, Gyroscope, Orientation
use core::{
fmt::{self, Display, Write},
marker::PhantomData,
mem::MaybeUninit,
};
use crate::{bindings::*, errno};
use card10_sys::*;
pub trait SensorType {
/// sensor_type in C, sensor_id in Python
......@@ -12,6 +14,7 @@ pub trait SensorType {
fn convert_single(value: i16) -> f32;
}
#[derive(Debug)]
pub struct Accelerometer;
impl SensorType for Accelerometer {
fn sensor_type() -> u32 {
......@@ -22,6 +25,7 @@ impl SensorType for Accelerometer {
}
}
#[derive(Debug)]
pub struct Gyroscope;
impl SensorType for Gyroscope {
fn sensor_type() -> u32 {
......@@ -32,6 +36,7 @@ impl SensorType for Gyroscope {
}
}
#[derive(Debug)]
pub struct Orientation;
impl SensorType for Orientation {
fn sensor_type() -> u32 {
......@@ -50,6 +55,10 @@ pub struct Sensor<S: SensorType> {
}
impl<S: SensorType> Sensor<S> {
/// Use one of:
/// - `BHI160::<Accelerometer>::start()`
/// - `BHI160::<Gyroscope>::start()`
/// - `BHI160::<Orientation>::start()`
fn new(stream_id: i32) -> Self {
Self {
stream_id,
......@@ -118,7 +127,7 @@ pub struct SensorData<S> {
}
impl<'a, S: SensorType> IntoIterator for &'a SensorData<S> {
type Item = SensorDataItem;
type Item = SensorDataItem<S>;
type IntoIter = SensorDataIter<'a, S>;
fn into_iter(self) -> Self::IntoIter {
......@@ -132,25 +141,26 @@ pub struct SensorDataIter<'a, S> {
}
impl<'a, S: SensorType> Iterator for SensorDataIter<'a, S> {
type Item = SensorDataItem;
type Item = SensorDataItem<S>;
fn next(&mut self) -> Option<Self::Item> {
while self.pos < self.data.n {
self.pos += 1;
let vec = &self.data.buf[self.pos];
if vec.data_type != DATA_TYPE_VECTOR {
writeln!(crate::UART, "Sensor: skip type {}\r", vec.data_type).ok();
continue;
}
let item = SensorDataItem {
x: S::convert_single(vec.x),
y: S::convert_single(vec.y),
z: S::convert_single(vec.z),
let item = SensorDataItem::<S> {
x_raw: vec.x,
y_raw: vec.y,
z_raw: vec.z,
status: vec.status,
_kind: PhantomData,
};
self.pos += 1;
return Some(item);
}
......@@ -159,11 +169,26 @@ impl<'a, S: SensorType> Iterator for SensorDataIter<'a, S> {
}
#[derive(Debug, Clone)]
pub struct SensorDataItem {
x: f32,
y: f32,
z: f32,
status: u8,
pub struct SensorDataItem<S: SensorType> {
pub x_raw: i16,
pub y_raw: i16,
pub z_raw: i16,
pub status: u8,
_kind: PhantomData<S>,
}
impl<S: SensorType> SensorDataItem<S> {
pub fn get_x(&self) -> f32 {
S::convert_single(self.x_raw)
}
pub fn get_y(&self) -> f32 {
S::convert_single(self.y_raw)
}
pub fn get_z(&self) -> f32 {
S::convert_single(self.z_raw)
}
}
#[repr(C)]
......
/// Enviromental sensor
use card10_sys::*;
use core::mem::uninitialized;
use super::bindings::*;
pub struct BME680;
pub type SensorData = bme680_sensor_data;
......@@ -7,7 +9,7 @@ pub type SensorData = bme680_sensor_data;
impl BME680 {
pub fn start() -> Self {
if unsafe { epic_bme680_init() } != 0 {
panic!("Cannot start light sensor");
panic!("Cannot start BME680 sensor");
}
BME680
}
......@@ -24,6 +26,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::*;
/// Button inputs
pub struct Buttons {
state: u32,
}
impl Buttons {
/// Read the current button state
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)
}
......@@ -51,7 +49,7 @@ impl Color {
}
pub fn g8(&self) -> u8 {
self.r() << 2
self.g() << 2
}
pub fn b(&self) -> u8 {
......@@ -59,7 +57,7 @@ impl Color {
}
pub fn b8(&self) -> u8 {
self.r() << 3
self.b() << 3
}
}
......@@ -77,63 +75,167 @@ pub enum FillStyle {
pub struct Display;
#[repr(u8)]
pub enum Font {
Font8 = disp_font_name_DISP_FONT8 as u8,
Font12 = disp_font_name_DISP_FONT12 as u8,
Font16 = disp_font_name_DISP_FONT16 as u8,
Font20 = disp_font_name_DISP_FONT20 as u8,
Font24 = disp_font_name_DISP_FONT24 as u8,
}
/// Immediate mode routines
impl Display {
pub const W: u16 = 160;
pub const H: u16 = 80;
pub const FONT_W: u16 = 14;
pub const FONT_H: u16 = 20;
pub const W: i16 = 160;
pub const H: i16 = 80;
pub const FONT_W: i16 = 14;
pub const FONT_H: i16 = 20;
/// Open the display, return an instance
pub fn open() -> Self {
unsafe { epic_disp_open(); }
unsafe {
epic_disp_open();
}
Display
}
/// Write Epicardium's framebuffer to the display
pub fn update(&self) {
unsafe { epic_disp_update(); }
unsafe {
epic_disp_update();
}
}
/// Clear everything with a solid `color`
pub fn clear(&self, color: Color) {
unsafe { epic_disp_clear(color.0); }
unsafe {
epic_disp_clear(color.0);
}
}
/// Print text
///
/// s must be 0-terminated
pub fn print(&self, x: u16, y: u16, s: &[u8], fg: Color, bg: Color) {
pub fn print(&self, x: i16, y: i16, s: &[u8], fg: Color, bg: Color) {
unsafe {
epic_disp_print(x, y, s.as_ptr(), fg.0, bg.0);
}
}
pub fn pixel(&self, x: u16, y: u16, color: Color) {
/// Print text with a selected font
///
/// s must be 0-terminated
pub fn print_adv(&self, font: Font, x: i16, y: i16, s: &[u8], fg: Color, bg: Color) {
unsafe {
epic_disp_print_adv(font as u8, x, y, s.as_ptr(), fg.0, bg.0);
}
}
/// Set a pixel
pub fn pixel(&self, x: i16, y: i16, color: Color) {
unsafe {
epic_disp_pixel(x, y, color.0);
}
}
pub fn line(&self, x1: u16, y1: u16, x2: u16, y2: u16, color: Color, linestyle: LineStyle, pixelsize: u16) {
/// Draw a line
pub fn line(
&self,
x1: i16,
y1: i16,
x2: i16,
y2: i16,
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: i16,
y1: i16,
x2: i16,
y2: i16,
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) {
/// Draw a circle
pub fn circ(
&self,
x: i16,
y: i16,
rad: u16,
color: Color,
fillstyle: FillStyle,
pixelsize: u16,
) {
unsafe {
epic_disp_circ(x, y, rad, color.0, fillstyle as u32, pixelsize);
}
}
pub fn framebuffer<'d>(&'d self) -> FrameBuffer<'d> {
/// Obtain a handle for a framebuffer.
///
/// Don't use `display.send()` but `framebuffer.send()` as long as
/// it is in use.
pub fn framebuffer<'d>(&'d mut self) -> FrameBuffer<'d> {
FrameBuffer::uninitialized(self)
}
}
impl Drop for Display {
fn drop(&mut self) {
unsafe { epic_disp_close(); }
}
unsafe {
epic_disp_close();
}
}
}
/// Convenience text display
///
/// Requires `card10_alloc::init()` and `extern crate alloc;`
#[macro_export]
macro_rules! display {
($disp: expr, $x: expr, $y: expr, $fg: expr, $bg: expr,
$fmt: expr) => ({
use alloc::format;
let s = format!(concat!($fmt, "\0"));
$disp.print($x, $y, s.as_bytes(), $fg, $bg);
});
($disp: expr, $x: expr, $y: expr, $fg: expr, $bg: expr,
$fmt: expr, $($arg: tt)*) => ({
use alloc::format;
let s = format!(concat!($fmt, "\0"), $($arg)*);
$disp.print($x, $y, s.as_bytes(), $fg, $bg);
});
}
/// Convenience text display with selected font
///
/// Requires `card10_alloc::init()` and `extern crate alloc;`
#[macro_export]
macro_rules! display_adv {
($disp: expr, $font: tt, $x: expr, $y: expr, $fg: expr, $bg: expr,
$fmt: expr) => ({
use alloc::format;
use card10_l0dable::Font;
let s = format!(concat!($fmt, "\0"));
$disp.print_adv(Font::$font, $x, $y, s.as_bytes(), $fg, $bg);
});
($disp: expr, $font: tt, $x: expr, $y: expr, $fg: expr, $bg: expr,
$fmt: expr, $($arg: tt)*) => ({
use alloc::format;
let s = format!(concat!($fmt, "\0"), $($arg)*);
$disp.print_adv(Font::$font, $x, $y, s.as_bytes(), $fg, $bg);
});
}
......@@ -37,7 +37,7 @@ impl<'a> fmt::Write for FmtBuffer<'a> {
}
}
/// 256 bytes ought to be enough for any string
/// 255 bytes ought to be enough for any C string
pub fn str_to_cstr(s: &str) -> [u8; 256] {
let mut buf: [u8; 256] = unsafe { uninitialized() };
let mut fmt = FmtBuffer::new(buf.as_mut());
......