e310x.rs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. //! Peripheral definitions for the E310x chip.
  2. //! This is a simple example of how to use the `riscv-peripheral` crate to generate
  3. //! peripheral definitions for a target.
  4. use riscv_pac::{HartIdNumber, InterruptNumber, PriorityNumber};
  5. #[repr(u16)]
  6. #[derive(Clone, Copy, Debug, Eq, PartialEq)]
  7. pub enum HartId {
  8. H0 = 0,
  9. }
  10. unsafe impl HartIdNumber for HartId {
  11. const MAX_HART_ID_NUMBER: u16 = 0;
  12. #[inline]
  13. fn number(self) -> u16 {
  14. self as _
  15. }
  16. #[inline]
  17. fn from_number(number: u16) -> Result<Self, u16> {
  18. if number > Self::MAX_HART_ID_NUMBER {
  19. Err(number)
  20. } else {
  21. // SAFETY: valid context number
  22. Ok(unsafe { core::mem::transmute(number) })
  23. }
  24. }
  25. }
  26. #[derive(Copy, Clone, Debug, PartialEq, Eq)]
  27. #[repr(u16)]
  28. pub enum Interrupt {
  29. WATCHDOG = 1,
  30. RTC = 2,
  31. UART0 = 3,
  32. UART1 = 4,
  33. QSPI0 = 5,
  34. QSPI1 = 6,
  35. QSPI2 = 7,
  36. GPIO0 = 8,
  37. GPIO1 = 9,
  38. GPIO2 = 10,
  39. GPIO3 = 11,
  40. GPIO4 = 12,
  41. GPIO5 = 13,
  42. GPIO6 = 14,
  43. GPIO7 = 15,
  44. GPIO8 = 16,
  45. GPIO9 = 17,
  46. GPIO10 = 18,
  47. GPIO11 = 19,
  48. GPIO12 = 20,
  49. GPIO13 = 21,
  50. GPIO14 = 22,
  51. GPIO15 = 23,
  52. GPIO16 = 24,
  53. GPIO17 = 25,
  54. GPIO18 = 26,
  55. GPIO19 = 27,
  56. GPIO20 = 28,
  57. GPIO21 = 29,
  58. GPIO22 = 30,
  59. GPIO23 = 31,
  60. GPIO24 = 32,
  61. GPIO25 = 33,
  62. GPIO26 = 34,
  63. GPIO27 = 35,
  64. GPIO28 = 36,
  65. GPIO29 = 37,
  66. GPIO30 = 38,
  67. GPIO31 = 39,
  68. PWM0CMP0 = 40,
  69. PWM0CMP1 = 41,
  70. PWM0CMP2 = 42,
  71. PWM0CMP3 = 43,
  72. PWM1CMP0 = 44,
  73. PWM1CMP1 = 45,
  74. PWM1CMP2 = 46,
  75. PWM1CMP3 = 47,
  76. PWM2CMP0 = 48,
  77. PWM2CMP1 = 49,
  78. PWM2CMP2 = 50,
  79. PWM2CMP3 = 51,
  80. I2C0 = 52,
  81. }
  82. unsafe impl InterruptNumber for Interrupt {
  83. const MAX_INTERRUPT_NUMBER: u16 = 52;
  84. #[inline]
  85. fn number(self) -> u16 {
  86. self as _
  87. }
  88. #[inline]
  89. fn from_number(number: u16) -> Result<Self, u16> {
  90. if number == 0 || number > Self::MAX_INTERRUPT_NUMBER {
  91. Err(number)
  92. } else {
  93. // SAFETY: valid interrupt number
  94. Ok(unsafe { core::mem::transmute(number) })
  95. }
  96. }
  97. }
  98. #[derive(Copy, Clone, Debug, PartialEq, Eq)]
  99. #[repr(u8)]
  100. pub enum Priority {
  101. P0 = 0,
  102. P1 = 1,
  103. P2 = 2,
  104. P3 = 3,
  105. P4 = 4,
  106. P5 = 5,
  107. P6 = 6,
  108. P7 = 7,
  109. }
  110. unsafe impl PriorityNumber for Priority {
  111. const MAX_PRIORITY_NUMBER: u8 = 7;
  112. #[inline]
  113. fn number(self) -> u8 {
  114. self as _
  115. }
  116. #[inline]
  117. fn from_number(number: u8) -> Result<Self, u8> {
  118. if number > Self::MAX_PRIORITY_NUMBER {
  119. Err(number)
  120. } else {
  121. // SAFETY: valid priority number
  122. Ok(unsafe { core::mem::transmute(number) })
  123. }
  124. }
  125. }
  126. #[cfg(feature = "aclint-hal-async")]
  127. riscv_peripheral::clint_codegen!(
  128. base 0x0200_0000,
  129. freq 32_768,
  130. async_delay,
  131. mtimecmps [mtimecmp0=(HartId::H0,"`H0`")],
  132. msips [msip0=(HartId::H0,"`H0`")],
  133. );
  134. #[cfg(not(feature = "aclint-hal-async"))]
  135. riscv_peripheral::clint_codegen!(
  136. base 0x0200_0000,
  137. freq 32_768,
  138. mtimecmps [mtimecmp0=(HartId::H0,"`H0`")],
  139. msips [msip0=(HartId::H0,"`H0`")],
  140. );
  141. riscv_peripheral::plic_codegen!(
  142. base 0x0C00_0000,
  143. ctxs [ctx0=(HartId::H0,"`H0`")],
  144. );
  145. #[cfg(feature = "aclint-hal-async")]
  146. /// extern functions needed by the `riscv-peripheral` crate for the `async` feature.
  147. ///
  148. /// # Note
  149. ///
  150. /// The functionality in this module is just to illustrate how to enable the `async` feature
  151. /// The timer queue used here, while functional, is unsound and should not be used in production.
  152. /// In this case, you should protect the timer queue with a mutex or critical section.
  153. /// For a more robust implementation, use proper timer queues such as the ones provided by `embassy-time`
  154. mod async_no_mangle {
  155. use super::CLINT;
  156. use heapless::binary_heap::{BinaryHeap, Min};
  157. use riscv_peripheral::{aclint::mtimer::MTIMER, hal_async::aclint::Timer};
  158. const N_TIMERS: usize = 16;
  159. static mut TIMER_QUEUE: BinaryHeap<Timer, Min, N_TIMERS> = BinaryHeap::new();
  160. #[no_mangle]
  161. fn _riscv_peripheral_aclint_mtimer() -> MTIMER {
  162. CLINT::mtimer()
  163. }
  164. #[no_mangle]
  165. fn _riscv_peripheral_aclint_push_timer(t: Timer) -> Result<(), Timer> {
  166. unsafe { TIMER_QUEUE.push(t) }
  167. }
  168. #[no_mangle]
  169. fn _riscv_peripheral_aclint_wake_timers(current_tick: u64) -> Option<u64> {
  170. let mut next_expires = None;
  171. while let Some(t) = unsafe { TIMER_QUEUE.peek() } {
  172. if t.expires() > current_tick {
  173. next_expires = Some(t.expires());
  174. break;
  175. }
  176. let t = unsafe { TIMER_QUEUE.pop() }.unwrap();
  177. t.waker().wake_by_ref();
  178. }
  179. next_expires
  180. }
  181. }
  182. fn main() {}