Skip to content

Commit

Permalink
Enter bootloader by double tapping reset button (#6)
Browse files Browse the repository at this point in the history
* implement bootloader double tap reset

* move timeout config from env var to keyboard macro

* add compiletime check for value timeout == 0

* implement review suggestions

* wrap MaybeUninit in UnsafeCell

* move bootloader double tap reset check to end
  • Loading branch information
zUnixorn committed Mar 22, 2024
1 parent 7128881 commit a5b5ff2
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 1 deletion.
18 changes: 18 additions & 0 deletions rumcake-macros/src/keyboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub(crate) struct KeyboardSettings {
split_central: Option<SplitCentralSettings>,
via: Option<Override<ViaSettings>>,
vial: Option<Override<ViaSettings>>,
bootloader_double_tap_reset: Option<Override<u64>>,
}

#[derive(Debug, FromMeta, Default)]
Expand Down Expand Up @@ -671,6 +672,23 @@ pub(crate) fn keyboard_main(
}
}

if let Some(arg) = keyboard.bootloader_double_tap_reset {
let timeout = arg.unwrap_or(200);

if timeout == 0 {
initialization.extend(quote! {
compile_error!("The timeout for double tapping the reset button should be > 0");
})
}

spawning.extend(quote! {
unsafe {
::rumcake::hw::check_double_tap_bootloader(#timeout).await;
}
});
}


let final_traits = traits.values();

quote! {
Expand Down
3 changes: 2 additions & 1 deletion rumcake/src/hw/mcu/rp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use embassy_rp::config::Config;
use embassy_rp::flash::Async;
use embassy_rp::flash::Flash as HALFlash;
use embassy_rp::peripherals::{FLASH, USB};
use embassy_rp::rom_data::reset_to_usb_boot;
use embassy_rp::usb::Driver;
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;

Expand All @@ -25,7 +26,7 @@ pub type RawMutex = ThreadModeRawMutex;

/// A function that allows you to jump to the bootloader, usually for re-flashing the firmware.
pub fn jump_to_bootloader() {
// TODO
reset_to_usb_boot(0, 0);
}

/// Initialize the MCU's internal clocks.
Expand Down
25 changes: 25 additions & 0 deletions rumcake/src/hw/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,15 @@ compile_error!("Please enable only one chip feature flag.");
#[cfg_attr(feature = "rp", path = "mcu/rp.rs")]
pub mod mcu;

use core::ptr::read_volatile;
use core::ptr::write_volatile;
use core::mem::MaybeUninit;
use core::cell::UnsafeCell;
use crate::hw::mcu::jump_to_bootloader;
use crate::State;
use embassy_futures::select;
use embassy_sync::signal::Signal;
use embassy_time::Timer;

use mcu::RawMutex;

Expand Down Expand Up @@ -123,6 +129,25 @@ pub async fn output_switcher() {
}
}

const BOOTLOADER_MAGIC: u32 = 0xDEADBEEF;

#[link_section = ".uninit.FLAG"]
static mut FLAG: UnsafeCell<MaybeUninit<u32>> = UnsafeCell::new(MaybeUninit::uninit());

pub async unsafe fn check_double_tap_bootloader(timeout: u64) {
if read_volatile(FLAG.get().cast::<u32>()) == BOOTLOADER_MAGIC {
write_volatile(FLAG.get().cast(), 0);

jump_to_bootloader();
}

write_volatile(FLAG.get().cast(), BOOTLOADER_MAGIC);

Timer::after_millis(timeout).await;

write_volatile(FLAG.get().cast(), 0);
}

extern "C" {
/// This static value will have an address equal to the `__config_start` address in your
/// `memory.x` file. You must set this, along with [`__config_end`], if you're using on-chip
Expand Down

0 comments on commit a5b5ff2

Please sign in to comment.