macros.rs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /// Macro to create interfaces to CLINT peripherals in PACs.
  2. /// The resulting struct will be named `CLINT`, and will provide safe access to the CLINT registers.
  3. ///
  4. /// This macro expects 2 different argument types:
  5. ///
  6. /// - Base address (**MANDATORY**): base address of the CLINT peripheral of the target.
  7. /// - Per-HART mtimecmp registers (**OPTIONAL**): a list of `mtimecmp` registers for easing access to per-HART mtimecmp regs.
  8. ///
  9. /// Check the examples below for more details about the usage and syntax of this macro.
  10. ///
  11. /// # Example
  12. ///
  13. /// ## Base address only
  14. ///
  15. /// ```
  16. /// use riscv_peripheral::clint_codegen;
  17. ///
  18. /// clint_codegen!(base 0x0200_0000,); // do not forget the ending comma!
  19. ///
  20. /// let mswi = CLINT::mswi(); // MSWI peripheral
  21. /// let mtimer = CLINT::mtimer(); // MTIMER peripheral
  22. /// ```
  23. ///
  24. /// ## Base address and per-HART mtimecmp registers
  25. ///
  26. /// ```
  27. /// use riscv_peripheral::clint_codegen;
  28. ///
  29. /// /// HART IDs for the target CLINT peripheral
  30. /// #[derive(Clone, Copy, Debug, Eq, PartialEq)]
  31. /// #[repr(u16)]
  32. /// pub enum HartId { H0 = 0, H1 = 1, H2 = 2 }
  33. ///
  34. /// // Implement `HartIdNumber` for `HartId`
  35. /// unsafe impl riscv_peripheral::aclint::HartIdNumber for HartId {
  36. /// const MAX_HART_ID_NUMBER: u16 = 2;
  37. /// fn number(self) -> u16 { self as _ }
  38. /// fn from_number(number: u16) -> Result<Self, u16> {
  39. /// if number > Self::MAX_HART_ID_NUMBER {
  40. /// Err(number)
  41. /// } else {
  42. /// // SAFETY: valid context number
  43. /// Ok(unsafe { core::mem::transmute(number) })
  44. /// }
  45. /// }
  46. /// }
  47. ///
  48. /// clint_codegen!(
  49. /// base 0x0200_0000,
  50. /// mtimecmps [mtimecmp0 = HartId::H0, mtimecmp1 = HartId::H1, mtimecmp2 = HartId::H2], // do not forget the ending comma!
  51. /// );
  52. ///
  53. /// let mswi = CLINT::mswi(); // MSWI peripheral
  54. /// let mtimer = CLINT::mtimer(); // MTIMER peripheral
  55. ///
  56. /// let mtimecmp0 = CLINT::mtimecmp0(); // mtimecmp register for HART 0
  57. /// let mtimecmp1 = CLINT::mtimecmp1(); // mtimecmp register for HART 1
  58. /// let mtimecmp2 = CLINT::mtimecmp2(); // mtimecmp register for HART 2
  59. /// ```
  60. #[macro_export]
  61. macro_rules! clint_codegen {
  62. () => {
  63. #[allow(unused_imports)]
  64. use CLINT as _; // assert that the CLINT struct is defined
  65. };
  66. (base $addr:literal, $($tail:tt)*) => {
  67. /// CLINT peripheral
  68. #[derive(Clone, Copy, Debug, Eq, PartialEq)]
  69. pub struct CLINT;
  70. unsafe impl $crate::aclint::Clint for CLINT {
  71. const BASE: usize = $addr;
  72. }
  73. impl CLINT {
  74. /// Returns the `MSWI` peripheral.
  75. #[inline]
  76. pub const fn mswi() -> $crate::aclint::mswi::MSWI {
  77. $crate::aclint::CLINT::<CLINT>::mswi()
  78. }
  79. /// Returns the `MTIMER` peripheral.
  80. #[inline]
  81. pub const fn mtimer() -> $crate::aclint::mtimer::MTIMER {
  82. $crate::aclint::CLINT::<CLINT>::mtimer()
  83. }
  84. }
  85. $crate::clint_codegen!($($tail)*);
  86. };
  87. (mtimecmps [$($fn:ident = $hart:expr),+], $($tail:tt)*) => {
  88. impl CLINT {
  89. $(
  90. #[inline]
  91. pub fn $fn() -> $crate::aclint::mtimer::MTIMECMP {
  92. Self::mtimer().mtimecmp($hart)
  93. }
  94. )*
  95. }
  96. $crate::clint_codegen!($($tail)*);
  97. };
  98. }
  99. #[macro_export]
  100. macro_rules! plic_codegen {
  101. () => {
  102. #[allow(unused_imports)]
  103. use PLIC as _; // assert that the PLIC struct is defined
  104. };
  105. (base $addr:literal, $($tail:tt)*) => {
  106. /// PLIC peripheral
  107. #[derive(Clone, Copy, Debug, Eq, PartialEq)]
  108. pub struct PLIC;
  109. unsafe impl $crate::plic::Plic for PLIC {
  110. const BASE: usize = $addr;
  111. }
  112. impl PLIC {
  113. /// Enables machine external interrupts to allow the PLIC to trigger interrupts.
  114. ///
  115. /// # Safety
  116. ///
  117. /// Enabling the `PLIC` may break mask-based critical sections.
  118. #[inline]
  119. pub unsafe fn enable() {
  120. $crate::plic::PLIC::<PLIC>::enable();
  121. }
  122. /// Disables machine external interrupts to prevent the PLIC from triggering interrupts.
  123. #[inline]
  124. pub fn disable() {
  125. $crate::plic::PLIC::<PLIC>::disable();
  126. }
  127. /// Returns the priorities register of the PLIC.
  128. #[inline]
  129. pub fn priorities() -> $crate::plic::priorities::PRIORITIES {
  130. $crate::plic::PLIC::<PLIC>::priorities()
  131. }
  132. /// Returns the pendings register of the PLIC.
  133. #[inline]
  134. pub fn pendings() -> $crate::plic::pendings::PENDINGS {
  135. $crate::plic::PLIC::<PLIC>::pendings()
  136. }
  137. /// Returns the context proxy of a given PLIC context.
  138. #[inline]
  139. pub fn ctx<C: $crate::plic::ContextNumber>(context: C) -> $crate::plic::CTX<Self> {
  140. $crate::plic::PLIC::<PLIC>::ctx(context)
  141. }
  142. }
  143. $crate::plic_codegen!($($tail)*);
  144. };
  145. (ctxs [$($fn:ident = $ctx:expr),+], $($tail:tt)*) => {
  146. impl PLIC {
  147. $(
  148. #[inline]
  149. pub fn $fn() -> $crate::plic::CTX<Self> {
  150. Self::ctx($ctx)
  151. }
  152. )*
  153. }
  154. $crate::plic_codegen!($($tail)*);
  155. };
  156. }