Use Rust
By default, the generated project uses keyboard.toml to configure the RMK keyboard firmware. If you want to customize your firmware using Rust, there are several steps you need to follow to make the generated firmware project compile.
Update memory.x
memory.x is the linker script of a Rust embedded project; it's used to define the memory layout of the microcontroller. The generated project enables the memory-x feature for embassy-stm32, so if you're using STM32, you can just ignore this step.
For other ARM Cortex-M microcontrollers, you only need to update the LENGTH of FLASH and RAM for your microcontroller.
If you're using nRF52840, ensure that you have Adafruit_nRF52_Bootloader flashed to your board. Most nice!nano compatible boards have it already. As long as you can open a USB drive for your board and update the uf2 firmware by dragging and dropping, you're all set.
You can check either your microcontroller's datasheet or an existing Rust project for your microcontroller for the correct values.
If you're using rmk-boot with DFU firmware updates (dfu_rp / dfu_nrf), you don't need to write a memory.x manually. Building rmk-boot generates a rmk-memory.x next to the bootloader binary; rename it to memory.x and place it next to your Cargo.toml. The generated project's build.rs already copies it into the linker's search path. See the embassy-boot flashing guide.
Update main.rs
The generated main.rs needs to be updated as well to use Rust code. You can copy the code from RMK's Rust example, such as https://github.com/rmk-rs/rmk/blob/main/examples/use_rust/rp2040/src/main.rs to src/main.rs to get started.
Next, check src/main.rs and make sure the bound USB interrupt is correct. Different microcontrollers have different USB peripherals, which means the interrupt bindings will also differ. Your best resource is to check Embassy's examples for your chip family to see how to bind the USB interrupt correctly.
For example, if you're using STM32F4, there is a USB serial example there. The code for binding the USB interrupt is at lines 15-17:
Add your own layout
This step only applies when you build with the Vial protocol (the vial feature), like the Rust examples do. RMK supports the Vial app, an open-source cross-platform (Windows/macOS/Linux/web) keyboard configurator. The Vial-like keymap definition needs to be imported into the firmware project.
Fortunately, RMK does most of the heavy lifting for you. All you need to do is create your own keymap definition and convert it to vial.json following Vial's documentation here, and place it at the root of the firmware project, replacing the default one. RMK will handle all the rest for you.
If you opt into Rynk instead of the default Vial protocol, you don't need a vial.json — skip this step.
Add your default keymap
After adding the layout of your keyboard, the default keymap should also be updated. The default keymap is defined in src/keymap.rs. Update the keyboard matrix constants and add a get_default_keymap() function that returns the default keymap of your keyboard.
RMK provides a bunch of useful macros to help you define your keymap. Check out the keymap configuration chapter for more details. You can also check the src/keymap.rs files in the https://github.com/rmk-rs/rmk/blob/main/examples/use_rust examples for reference.
Some KeyActions have no macro; plain KeyActions also work, for example a key that runs macro 0 when tapped and acts as Shift when held: KeyAction::TapHold(Action::TriggerMacro(0), Action::Modifier(ModifierCombination::LSHIFT), u8::MAX) (the last argument indexes the morse profile table; use u8::MAX for the default tap-hold timing)
Define your matrix
Next, you're going to change the I/O pins of the keyboard matrix to make RMK run on your own PCB. Generally, I/O pins are defined in src/main.rs. The Rust examples ship a small helper macro in src/macros.rs to define the matrix; it's part of the example, not of the rmk crate. For example, examples/use_rust/rp2040 defines pins with config_matrix_pins_rp!:
input and output are lists of used pins; change them accordingly.
If your keys are directly connected to the microcontroller pins, use the direct_pins variant of the macro from examples/use_rust/rp2040_direct_pin instead:
So far so good, you've done all necessary modifications of your firmware project. You can also check TODOs listed in the generated README.md file. Happy coding!