-
-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Haobo Gu <[email protected]>
- Loading branch information
Showing
9 changed files
with
323 additions
and
3 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
[target.'cfg(all(target_arch = "arm", target_os = "none"))'] | ||
# uncomment ONE of these three option to make `cargo run` start a GDB session | ||
# which option to pick depends on your system | ||
runner = "probe-rs run --chip STM32F411CEUx" | ||
# runner = "gdb-multiarch -q -x openocd.gdb" | ||
# runner = "gdb -q -x openocd.gdb" | ||
|
||
rustflags = [ | ||
# Previously, the linker arguments --nmagic and -Tlink.x were set here. | ||
# They are now set by build.rs instead. The linker argument can still | ||
# only be set here, if a custom linker is needed. | ||
|
||
# By default, the LLD linker is used, which is shipped with the Rust | ||
# toolchain. If you run into problems with LLD, you can switch to the | ||
# GNU linker by uncommenting this line: | ||
# "-C", "linker=arm-none-eabi-ld", | ||
|
||
# If you need to link to pre-compiled C libraries provided by a C toolchain | ||
# use GCC as the linker by uncommenting the three lines below: | ||
# "-C", "linker=arm-none-eabi-gcc", | ||
# "-C", "link-arg=-Wl,-Tlink.x", | ||
# "-C", "link-arg=-nostartfiles", | ||
] | ||
|
||
[build] | ||
# Pick ONE of these default compilation targets | ||
# target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+ | ||
# target = "thumbv7m-none-eabi" # Cortex-M3 | ||
# target = "thumbv7em-none-eabi" # Cortex-M4 and Cortex-M7 (no FPU) | ||
target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) | ||
# target = "thumbv8m.base-none-eabi" # Cortex-M23 | ||
# target = "thumbv8m.main-none-eabi" # Cortex-M33 (no FPU) | ||
# target = "thumbv8m.main-none-eabihf" # Cortex-M33 (with FPU) | ||
|
||
[env] | ||
DEFMT_LOG = "info" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
cargo-features = ["per-package-target"] | ||
|
||
[package] | ||
name = "rmk-stm32f4" | ||
version = "0.1.0" | ||
authors = ["Haobo Gu <[email protected]>"] | ||
description = "Keyboard firmware written in Rust" | ||
homepage = "https://github.com/haobogu/rmk" | ||
repository = "https://github.com/haobogu/rmk" | ||
readme = "../../README.md" | ||
edition = "2021" | ||
license = "MIT OR Apache-2.0" | ||
|
||
forced-target = "thumbv7em-none-eabihf" | ||
|
||
[dependencies] | ||
rmk = { version = "0.1.0", path = "../../rmk", features = [ | ||
"eeprom", | ||
"col2row", | ||
] } | ||
cortex-m = { version = "0.7.7", features = ['critical-section-single-core'] } | ||
cortex-m-rt = "0.7.3" | ||
embassy-time = { version = "0.3", git = "https://github.com/embassy-rs/embassy", features = [ | ||
# "tick-hz-1_000_000", | ||
"tick-hz-32_768", | ||
"defmt", | ||
] } | ||
embassy-stm32 = { version = "0.1.0", git = "https://github.com/embassy-rs/embassy", features = [ | ||
"stm32f411ce", | ||
"defmt", | ||
"time-driver-any", | ||
"exti", | ||
"time", | ||
] } | ||
embassy-executor = { version = "0.5.0", git = "https://github.com/embassy-rs/embassy", features = [ | ||
"defmt", | ||
"arch-cortex-m", | ||
"executor-thread", | ||
"executor-interrupt", | ||
"integrated-timers", | ||
] } | ||
embassy-futures = { version = "0.1.0", git = "https://github.com/embassy-rs/embassy" } | ||
rtt-target = "0.5.0" | ||
log = "0.4.19" | ||
packed_struct = { version = "0.10.1", default-features = false } | ||
embedded-storage = { version = "0.3" } | ||
static_cell = { version = "2" } | ||
|
||
# defmt deps | ||
defmt = "0.3.5" | ||
defmt-rtt = "0.4.0" | ||
panic-probe = {version = "0.3", features = ["print-defmt"] } | ||
|
||
[[bin]] | ||
name = "rmk-stm32f4" | ||
test = false | ||
bench = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
//! This build script copies the `memory.x` file from the crate root into | ||
//! a directory where the linker can always find it at build time. | ||
//! For many projects this is optional, as the linker always searches the | ||
//! project root directory -- wherever `Cargo.toml` is. However, if you | ||
//! are using a workspace or have a more complicated build setup, this | ||
//! build script becomes required. Additionally, by requesting that | ||
//! Cargo re-run the build script whenever `memory.x` is changed, | ||
//! updating `memory.x` ensures a rebuild of the application with the | ||
//! new memory settings. | ||
//! | ||
//! The build script also sets the linker flags to tell it which link script to use. | ||
use std::env; | ||
use std::fs::File; | ||
use std::io::Write; | ||
use std::path::PathBuf; | ||
|
||
fn main() { | ||
// Put `memory.x` in our output directory and ensure it's | ||
// on the linker search path. | ||
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); | ||
File::create(out.join("memory.x")) | ||
.unwrap() | ||
.write_all(include_bytes!("memory.x")) | ||
.unwrap(); | ||
println!("cargo:rustc-link-search={}", out.display()); | ||
|
||
// By default, Cargo will re-run a build script whenever | ||
// any file in the project changes. By specifying `memory.x` | ||
// here, we ensure the build script is only re-run when | ||
// `memory.x` is changed. | ||
println!("cargo:rerun-if-changed=memory.x"); | ||
|
||
// Specify linker arguments. | ||
|
||
// `--nmagic` is required if memory section addresses are not aligned to 0x10000, | ||
// for example the FLASH and RAM sections in your `memory.x`. | ||
// See https://github.com/rust-embedded/cortex-m-quickstart/pull/95 | ||
println!("cargo:rustc-link-arg=--nmagic"); | ||
|
||
// Set the linker script to the one provided by cortex-m-rt. | ||
println!("cargo:rustc-link-arg=-Tlink.x"); | ||
|
||
// Set the extra linker script from defmt | ||
println!("cargo:rustc-link-arg=-Tdefmt.x"); | ||
|
||
println!("cargo:rustc-linker=flip-link"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
MEMORY | ||
{ | ||
/* NOTE K = KiBi = 1024 bytes */ | ||
FLASH : ORIGIN = 0x08000000, LENGTH = 128K | ||
RAM : ORIGIN = 0x20000000, LENGTH = 128K | ||
} | ||
|
||
/* This is where the call stack will be allocated. */ | ||
/* The stack is of the full descending type. */ | ||
/* NOTE Do NOT modify `_stack_start` unless you know what you are doing */ | ||
_stack_start = ORIGIN(RAM) + LENGTH(RAM); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
use rmk::action::KeyAction; | ||
use rmk::{a, k, layer, mo}; | ||
pub(crate) const COL: usize = 3; | ||
pub(crate) const ROW: usize = 4; | ||
pub(crate) const NUM_LAYER: usize = 2; | ||
|
||
#[rustfmt::skip] | ||
pub static KEYMAP: [[[KeyAction; COL]; ROW]; NUM_LAYER] = [ | ||
layer!([ | ||
[k!(AudioVolUp), k!(B), k!(AudioVolDown)], | ||
[k!(Kp4), k!(LShift), k!(Kp6)], | ||
[mo!(1), k!(Kp2), k!(Kp3)], | ||
[mo!(1), a!(No), k!(Kp0)] | ||
]), | ||
layer!([ | ||
[k!(Kp7), k!(Kp8), k!(Kp9)], | ||
[k!(Kp4), k!(LCtrl), k!(Kp6)], | ||
[mo!(1), k!(Kp2), k!(Kp3)], | ||
[mo!(1), a!(No), k!(Kp0)] | ||
]), | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// DEPRECIATED | ||
macro_rules! _config_matrix_pins { | ||
(input: [$($in_port:ident.$in_pin:ident), *], output: [$($out_port:ident.$out_pin:ident), +]) => { | ||
{ | ||
$( | ||
let $in_pin = $in_port.$in_pin.into_pull_down_input().erase(); | ||
)* | ||
$( | ||
let mut $out_pin = $out_port.$out_pin.into_push_pull_output().erase(); | ||
)+ | ||
$( | ||
$out_pin.set_low(); | ||
)+ | ||
let output_pins = [$($out_pin), +]; | ||
let input_pins = [$($in_pin), +]; | ||
(input_pins, output_pins) | ||
} | ||
}; | ||
} | ||
|
||
macro_rules! config_matrix_pins_stm32 { | ||
(peripherals: $p:ident, input: [$($in_pin:ident), *], output: [$($out_pin:ident), +]) => { | ||
{ | ||
let mut output_pins = [$(Output::new($p.$out_pin, embassy_stm32::gpio::Level::Low, embassy_stm32::gpio::Speed::VeryHigh).degrade()), +]; | ||
let input_pins = [$(Input::new($p.$in_pin, embassy_stm32::gpio::Pull::Down).degrade()), +]; | ||
output_pins.iter_mut().for_each(|p| { | ||
p.set_low(); | ||
}); | ||
(input_pins, output_pins) | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
#![no_main] | ||
#![no_std] | ||
#![feature(type_alias_impl_trait)] | ||
#![allow(dead_code)] | ||
|
||
#[macro_use] | ||
mod macros; | ||
mod keymap; | ||
|
||
use core::{cell::RefCell, sync::atomic::AtomicBool}; | ||
use defmt::*; | ||
use defmt_rtt as _; | ||
use embassy_executor::Spawner; | ||
use embassy_futures::join::join; | ||
use embassy_stm32::{ | ||
bind_interrupts, | ||
flash::{Blocking, Flash}, | ||
gpio::{AnyPin, Input, Output}, | ||
peripherals::USB_OTG_FS, | ||
usb_otg::{Driver, InterruptHandler}, | ||
Config, | ||
}; | ||
use embassy_time::Timer; | ||
use panic_probe as _; | ||
use rmk::{eeprom::EepromStorageConfig, initialize_keyboard_and_usb_device, keymap::KeyMap}; | ||
use static_cell::StaticCell; | ||
|
||
use crate::keymap::{COL, NUM_LAYER, ROW}; | ||
|
||
bind_interrupts!(struct Irqs { | ||
OTG_FS => InterruptHandler<USB_OTG_FS>; | ||
}); | ||
|
||
static SUSPENDED: AtomicBool = AtomicBool::new(false); | ||
const FLASH_SECTOR_7_ADDR: u32 = 0x60000; | ||
const EEPROM_SIZE: usize = 128; | ||
|
||
#[embassy_executor::main] | ||
async fn main(_spawner: Spawner) { | ||
info!("start!"); | ||
// RCC config | ||
let config = Config::default(); | ||
|
||
// Initialize peripherals | ||
let p = embassy_stm32::init(config); | ||
|
||
// Usb config | ||
static EP_OUT_BUFFER: StaticCell<[u8; 1024]> = StaticCell::new(); | ||
let mut usb_config = embassy_stm32::usb_otg::Config::default(); | ||
usb_config.vbus_detection = false; | ||
let driver = Driver::new_fs( | ||
p.USB_OTG_FS, | ||
Irqs, | ||
p.PA12, | ||
p.PA11, | ||
&mut EP_OUT_BUFFER.init([0; 1024])[..], | ||
usb_config, | ||
); | ||
|
||
// Pin config | ||
let (input_pins, output_pins) = config_matrix_pins_stm32!(peripherals: p, input: [PD9, PD8, PB13, PB12], output: [PE13, PE14, PE15]); | ||
|
||
// Keymap + eeprom config | ||
static MY_KEYMAP: StaticCell< | ||
RefCell<KeyMap<Flash<'_, Blocking>, EEPROM_SIZE, ROW, COL, NUM_LAYER>>, | ||
> = StaticCell::new(); | ||
let eeprom_storage_config = EepromStorageConfig { | ||
start_addr: FLASH_SECTOR_7_ADDR, | ||
storage_size: 0x20000, // uses last sector, 128KB for eeprom | ||
page_size: 8, | ||
}; | ||
// Use internal flash to emulate eeprom | ||
let f = Flash::new_blocking(p.FLASH); | ||
let keymap = MY_KEYMAP.init(RefCell::new(KeyMap::new( | ||
crate::keymap::KEYMAP, | ||
Some(f), | ||
eeprom_storage_config, | ||
None, | ||
))); | ||
|
||
// Initialize all utilities: keyboard, usb and keymap | ||
let (mut keyboard, mut usb_device, vial) = initialize_keyboard_and_usb_device::< | ||
Driver<'_, USB_OTG_FS>, | ||
Input<'_, AnyPin>, | ||
Output<'_, AnyPin>, | ||
Flash<'_, Blocking>, | ||
EEPROM_SIZE, | ||
ROW, | ||
COL, | ||
NUM_LAYER, | ||
>(driver, input_pins, output_pins, keymap); | ||
|
||
let usb_fut = usb_device.device.run(); | ||
let keyboard_fut = async { | ||
loop { | ||
let _ = keyboard.keyboard_task().await; | ||
keyboard.send_report(&mut usb_device.keyboard_hid).await; | ||
keyboard.send_media_report(&mut usb_device.other_hid).await; | ||
} | ||
}; | ||
|
||
let via_fut = async { | ||
loop { | ||
vial.process_via_report(&mut usb_device.via_hid).await; | ||
Timer::after_millis(1).await; | ||
} | ||
}; | ||
join(usb_fut, join(keyboard_fut, via_fut)).await; | ||
} |