原始 MMIO

大多数微控制器通过内存映射 IO 访问外围设备。现在试着开启 micro:bit 上的 LED 指示灯:

  1. #![no_main]
  2. #![no_std]
  3. extern crate panic_halt as _;
  4. mod interrupts;
  5. use core::mem::size_of;
  6. use cortex_m_rt::entry;
  7. /// GPIO port 0 peripheral address
  8. const GPIO_P0: usize = 0x5000_0000;
  9. // GPIO peripheral offsets
  10. const PIN_CNF: usize = 0x700;
  11. const OUTSET: usize = 0x508;
  12. const OUTCLR: usize = 0x50c;
  13. // PIN_CNF fields
  14. const DIR_OUTPUT: u32 = 0x1;
  15. const INPUT_DISCONNECT: u32 = 0x1 << 1;
  16. const PULL_DISABLED: u32 = 0x0 << 2;
  17. const DRIVE_S0S1: u32 = 0x0 << 8;
  18. const SENSE_DISABLED: u32 = 0x0 << 16;
  19. #[entry]
  20. fn main() -> ! {
  21. // Configure GPIO 0 pins 21 and 28 as push-pull outputs.
  22. let pin_cnf_21 = (GPIO_P0 + PIN_CNF + 21 * size_of::<u32>()) as *mut u32;
  23. let pin_cnf_28 = (GPIO_P0 + PIN_CNF + 28 * size_of::<u32>()) as *mut u32;
  24. // SAFETY: The pointers are to valid peripheral control registers, and no
  25. // aliases exist.
  26. unsafe {
  27. pin_cnf_21.write_volatile(
  28. DIR_OUTPUT
  29. | INPUT_DISCONNECT
  30. | PULL_DISABLED
  31. | DRIVE_S0S1
  32. | SENSE_DISABLED,
  33. );
  34. pin_cnf_28.write_volatile(
  35. DIR_OUTPUT
  36. | INPUT_DISCONNECT
  37. | PULL_DISABLED
  38. | DRIVE_S0S1
  39. | SENSE_DISABLED,
  40. );
  41. }
  42. // Set pin 28 low and pin 21 high to turn the LED on.
  43. let gpio0_outset = (GPIO_P0 + OUTSET) as *mut u32;
  44. let gpio0_outclr = (GPIO_P0 + OUTCLR) as *mut u32;
  45. // SAFETY: The pointers are to valid peripheral control registers, and no
  46. // aliases exist.
  47. unsafe {
  48. gpio0_outclr.write_volatile(1 << 28);
  49. gpio0_outset.write_volatile(1 << 21);
  50. }
  51. loop {}
  52. }
  • 将 GPIO 0 的引脚 21 连接到 LED 矩阵的第一列,将引脚 28 连接到第一行。

使用以下命令运行该示例:

  1. cargo embed --bin mmio