dma.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. #![allow(dead_code)]
  2. use core::marker::PhantomData;
  3. use core::ops;
  4. use rcc::AHB;
  5. #[derive(Debug)]
  6. pub enum Error {
  7. Overrun,
  8. #[doc(hidden)]
  9. _Extensible,
  10. }
  11. pub enum Event {
  12. HalfTransfer,
  13. TransferComplete,
  14. }
  15. #[derive(Clone, Copy, PartialEq)]
  16. pub enum Half {
  17. First,
  18. Second,
  19. }
  20. pub struct CircBuffer<BUFFER, CHANNEL>
  21. where
  22. BUFFER: 'static,
  23. {
  24. buffer: &'static mut [BUFFER; 2],
  25. channel: CHANNEL,
  26. readable_half: Half,
  27. }
  28. impl<BUFFER, CHANNEL> CircBuffer<BUFFER, CHANNEL> {
  29. pub(crate) fn new(buf: &'static mut [BUFFER; 2], chan: CHANNEL) -> Self {
  30. CircBuffer {
  31. buffer: buf,
  32. channel: chan,
  33. readable_half: Half::Second,
  34. }
  35. }
  36. }
  37. pub trait Static<B> {
  38. fn borrow(&self) -> &B;
  39. }
  40. impl<B> Static<B> for &'static B {
  41. fn borrow(&self) -> &B {
  42. *self
  43. }
  44. }
  45. impl<B> Static<B> for &'static mut B {
  46. fn borrow(&self) -> &B {
  47. *self
  48. }
  49. }
  50. pub trait DmaExt {
  51. type Channels;
  52. fn split(self, ahb: &mut AHB) -> Self::Channels;
  53. }
  54. pub struct Transfer<MODE, BUFFER, CHANNEL, PAYLOAD> {
  55. _mode: PhantomData<MODE>,
  56. buffer: BUFFER,
  57. channel: CHANNEL,
  58. payload: PAYLOAD,
  59. }
  60. impl<BUFFER, CHANNEL, PAYLOAD> Transfer<R, BUFFER, CHANNEL, PAYLOAD> {
  61. pub(crate) fn r(buffer: BUFFER, channel: CHANNEL, payload: PAYLOAD) -> Self {
  62. Transfer {
  63. _mode: PhantomData,
  64. buffer,
  65. channel,
  66. payload,
  67. }
  68. }
  69. }
  70. impl<BUFFER, CHANNEL, PAYLOAD> Transfer<W, BUFFER, CHANNEL, PAYLOAD> {
  71. pub(crate) fn w(buffer: BUFFER, channel: CHANNEL, payload: PAYLOAD) -> Self {
  72. Transfer {
  73. _mode: PhantomData,
  74. buffer,
  75. channel,
  76. payload,
  77. }
  78. }
  79. }
  80. impl<BUFFER, CHANNEL, PAYLOAD> ops::Deref for Transfer<R, BUFFER, CHANNEL, PAYLOAD> {
  81. type Target = BUFFER;
  82. fn deref(&self) -> &BUFFER {
  83. &self.buffer
  84. }
  85. }
  86. /// Read transfer
  87. pub struct R;
  88. /// Write transfer
  89. pub struct W;
  90. macro_rules! dma {
  91. ($($DMAX:ident: ($dmaX:ident, $dmaXen:ident, $dmaXrst:ident, {
  92. $($CX:ident: (
  93. $ccrX:ident,
  94. $CCRX:ident,
  95. $cndtrX:ident,
  96. $CNDTRX:ident,
  97. $cparX:ident,
  98. $CPARX:ident,
  99. $cmarX:ident,
  100. $CMARX:ident,
  101. $htifX:ident,
  102. $tcifX:ident,
  103. $chtifX:ident,
  104. $ctcifX:ident,
  105. $cgifX:ident
  106. ),)+
  107. }),)+) => {
  108. $(
  109. pub mod $dmaX {
  110. use core::sync::atomic::{self, Ordering};
  111. use stm32::{$DMAX, dma1};
  112. use dma::{CircBuffer, DmaExt, Error, Event, Half, Transfer, W};
  113. use rcc::AHB;
  114. pub struct Channels((), $(pub $CX),+);
  115. $(
  116. pub struct $CX { _0: () }
  117. impl $CX {
  118. pub fn listen(&mut self, event: Event) {
  119. match event {
  120. Event::HalfTransfer => self.ccr().modify(|_, w| w.htie().set_bit()),
  121. Event::TransferComplete => {
  122. self.ccr().modify(|_, w| w.tcie().set_bit())
  123. }
  124. }
  125. }
  126. pub fn unlisten(&mut self, event: Event) {
  127. match event {
  128. Event::HalfTransfer => {
  129. self.ccr().modify(|_, w| w.htie().clear_bit())
  130. },
  131. Event::TransferComplete => {
  132. self.ccr().modify(|_, w| w.tcie().clear_bit())
  133. }
  134. }
  135. }
  136. pub(crate) fn isr(&self) -> dma1::isr::R {
  137. // NOTE(unsafe) atomic read with no side effects
  138. unsafe { (*$DMAX::ptr()).isr.read() }
  139. }
  140. pub(crate) fn ifcr(&self) -> &dma1::IFCR {
  141. unsafe { &(*$DMAX::ptr()).ifcr }
  142. }
  143. pub(crate) fn ccr(&mut self) -> &dma1::$CCRX {
  144. unsafe { &(*$DMAX::ptr()).$ccrX }
  145. }
  146. pub(crate) fn cndtr(&mut self) -> &dma1::$CNDTRX {
  147. unsafe { &(*$DMAX::ptr()).$cndtrX }
  148. }
  149. pub(crate) fn cpar(&mut self) -> &dma1::$CPARX {
  150. unsafe { &(*$DMAX::ptr()).$cparX }
  151. }
  152. pub(crate) fn cmar(&mut self) -> &dma1::$CMARX {
  153. unsafe { &(*$DMAX::ptr()).$cmarX }
  154. }
  155. pub(crate) fn get_cndtr(&self) -> u32 {
  156. // NOTE(unsafe) atomic read with no side effects
  157. unsafe { (*$DMAX::ptr()).$cndtrX.read().bits() }
  158. }
  159. }
  160. impl<B> CircBuffer<B, $CX> {
  161. /// Peeks into the readable half of the buffer
  162. pub fn peek<R, F>(&mut self, f: F) -> Result<R, Error>
  163. where
  164. F: FnOnce(&B, Half) -> R,
  165. {
  166. let half_being_read = self.readable_half()?;
  167. let buf = match half_being_read {
  168. Half::First => &self.buffer[0],
  169. Half::Second => &self.buffer[1],
  170. };
  171. // XXX does this need a compiler barrier?
  172. let ret = f(buf, half_being_read);
  173. let isr = self.channel.isr();
  174. let first_half_is_done = isr.$htifX().bit_is_set();
  175. let second_half_is_done = isr.$tcifX().bit_is_set();
  176. if (half_being_read == Half::First && second_half_is_done) ||
  177. (half_being_read == Half::Second && first_half_is_done) {
  178. Err(Error::Overrun)
  179. } else {
  180. Ok(ret)
  181. }
  182. }
  183. /// Returns the `Half` of the buffer that can be read
  184. pub fn readable_half(&mut self) -> Result<Half, Error> {
  185. let isr = self.channel.isr();
  186. let first_half_is_done = isr.$htifX().bit_is_set();
  187. let second_half_is_done = isr.$tcifX().bit_is_set();
  188. if first_half_is_done && second_half_is_done {
  189. return Err(Error::Overrun);
  190. }
  191. let last_read_half = self.readable_half;
  192. Ok(match last_read_half {
  193. Half::First => {
  194. if second_half_is_done {
  195. self.channel.ifcr().write(|w| w.$ctcifX().set_bit());
  196. self.readable_half = Half::Second;
  197. Half::Second
  198. } else {
  199. last_read_half
  200. }
  201. }
  202. Half::Second => {
  203. if first_half_is_done {
  204. self.channel.ifcr().write(|w| w.$chtifX().set_bit());
  205. self.readable_half = Half::First;
  206. Half::First
  207. } else {
  208. last_read_half
  209. }
  210. }
  211. })
  212. }
  213. }
  214. impl<BUFFER, PAYLOAD, MODE> Transfer<MODE, BUFFER, $CX, PAYLOAD> {
  215. pub fn is_done(&self) -> bool {
  216. self.channel.isr().$tcifX().bit_is_set()
  217. }
  218. pub fn wait(mut self) -> (BUFFER, $CX, PAYLOAD) {
  219. // XXX should we check for transfer errors here?
  220. // The manual says "A DMA transfer error can be generated by reading
  221. // from or writing to a reserved address space". I think it's impossible
  222. // to get to that state with our type safe API and *safe* Rust.
  223. while !self.is_done() {}
  224. self.channel.ifcr().write(|w| w.$cgifX().set_bit());
  225. self.channel.ccr().modify(|_, w| w.en().clear_bit());
  226. // TODO can we weaken this compiler barrier?
  227. // NOTE(compiler_fence) operations on `buffer` should not be reordered
  228. // before the previous statement, which marks the DMA transfer as done
  229. atomic::compiler_fence(Ordering::SeqCst);
  230. (self.buffer, self.channel, self.payload)
  231. }
  232. }
  233. impl<BUFFER, PAYLOAD> Transfer<W, &'static mut BUFFER, $CX, PAYLOAD> {
  234. pub fn peek<T>(&self) -> &[T]
  235. where
  236. BUFFER: AsRef<[T]>,
  237. {
  238. let pending = self.channel.get_cndtr() as usize;
  239. let slice = self.buffer.as_ref();
  240. let capacity = slice.len();
  241. &slice[..(capacity - pending)]
  242. }
  243. }
  244. )+
  245. impl DmaExt for $DMAX {
  246. type Channels = Channels;
  247. fn split(self, ahb: &mut AHB) -> Channels {
  248. ahb.enr().modify(|_, w| w.$dmaXen().set_bit());
  249. // reset the DMA control registers (stops all on-going transfers)
  250. $(
  251. self.$ccrX.reset();
  252. )+
  253. Channels((), $($CX { _0: () }),+)
  254. }
  255. }
  256. }
  257. )+
  258. }
  259. }
  260. dma! {
  261. DMA1: (dma1, dma1en, dma1rst, {
  262. C1: (
  263. ccr1, CCR1,
  264. cndtr1, CNDTR1,
  265. cpar1, CPAR1,
  266. cmar1, CMAR1,
  267. htif1, tcif1,
  268. chtif1, ctcif1, cgif1
  269. ),
  270. C2: (
  271. ccr2, CCR2,
  272. cndtr2, CNDTR2,
  273. cpar2, CPAR2,
  274. cmar2, CMAR2,
  275. htif2, tcif2,
  276. chtif2, ctcif2, cgif2
  277. ),
  278. C3: (
  279. ccr3, CCR3,
  280. cndtr3, CNDTR3,
  281. cpar3, CPAR3,
  282. cmar3, CMAR3,
  283. htif3, tcif3,
  284. chtif3, ctcif3, cgif3
  285. ),
  286. C4: (
  287. ccr4, CCR4,
  288. cndtr4, CNDTR4,
  289. cpar4, CPAR4,
  290. cmar4, CMAR4,
  291. htif4, tcif4,
  292. chtif4, ctcif4, cgif4
  293. ),
  294. C5: (
  295. ccr5, CCR5,
  296. cndtr5, CNDTR5,
  297. cpar5, CPAR5,
  298. cmar5, CMAR5,
  299. htif5, tcif5,
  300. chtif5, ctcif5, cgif5
  301. ),
  302. C6: (
  303. ccr6, CCR6,
  304. cndtr6, CNDTR6,
  305. cpar6, CPAR6,
  306. cmar6, CMAR6,
  307. htif6, tcif6,
  308. chtif6, ctcif6, cgif6
  309. ),
  310. C7: (
  311. ccr7, CCR7,
  312. cndtr7, CNDTR7,
  313. cpar7, CPAR7,
  314. cmar7, CMAR7,
  315. htif7, tcif7,
  316. chtif7, ctcif7, cgif7
  317. ),
  318. }),
  319. DMA2: (dma2, dma2en, dma2rst, {
  320. C1: (
  321. ccr1, CCR1,
  322. cndtr1, CNDTR1,
  323. cpar1, CPAR1,
  324. cmar1, CMAR1,
  325. htif1, tcif1,
  326. chtif1, ctcif1, cgif1
  327. ),
  328. C2: (
  329. ccr2, CCR2,
  330. cndtr2, CNDTR2,
  331. cpar2, CPAR2,
  332. cmar2, CMAR2,
  333. htif2, tcif2,
  334. chtif2, ctcif2, cgif2
  335. ),
  336. C3: (
  337. ccr3, CCR3,
  338. cndtr3, CNDTR3,
  339. cpar3, CPAR3,
  340. cmar3, CMAR3,
  341. htif3, tcif3,
  342. chtif3, ctcif3, cgif3
  343. ),
  344. C4: (
  345. ccr4, CCR4,
  346. cndtr4, CNDTR4,
  347. cpar4, CPAR4,
  348. cmar4, CMAR4,
  349. htif4, tcif4,
  350. chtif4, ctcif4, cgif4
  351. ),
  352. C5: (
  353. ccr5, CCR5,
  354. cndtr5, CNDTR5,
  355. cpar5, CPAR5,
  356. cmar5, CMAR5,
  357. htif5, tcif5,
  358. chtif5, ctcif5, cgif5
  359. ),
  360. }),
  361. }
  362. pub trait DmaChannel {
  363. type Dma;
  364. }