Multiple registers

We can use a struct to represent the memory layout of the UART’s registers.

  1. #[repr(C, align(4))]
  2. struct Registers {
  3.     dr: u16,
  4.     _reserved0: [u8; 2],
  5.     rsr: ReceiveStatus,
  6.     _reserved1: [u8; 19],
  7.     fr: Flags,
  8.     _reserved2: [u8; 6],
  9.     ilpr: u8,
  10.     _reserved3: [u8; 3],
  11.     ibrd: u16,
  12.     _reserved4: [u8; 2],
  13.     fbrd: u8,
  14.     _reserved5: [u8; 3],
  15.     lcr_h: u8,
  16.     _reserved6: [u8; 3],
  17.     cr: u16,
  18.     _reserved7: [u8; 3],
  19.     ifls: u8,
  20.     _reserved8: [u8; 3],
  21.     imsc: u16,
  22.     _reserved9: [u8; 2],
  23.     ris: u16,
  24.     _reserved10: [u8; 2],
  25.     mis: u16,
  26.     _reserved11: [u8; 2],
  27.     icr: u16,
  28.     _reserved12: [u8; 2],
  29.     dmacr: u8,
  30.     _reserved13: [u8; 3],
  31. }
  • #[repr(C)] tells the compiler to lay the struct fields out in order, following the same rules as C. This is necessary for our struct to have a predictable layout, as default Rust representation allows the compiler to (among other things) reorder fields however it sees fit.