1- //! Basic driver for the MT25QL128ABA. Demonstrates how a flash driver can be
2- //! written using the QSPI driver in the HAL .
1+ //! Basic driver for the MT25QL128ABA. Demonstrates how the QSPI HAL
2+ //! driver can be used to create a driver for a QSPI flash memory chip .
33
4+ use as_slice:: AsSlice ;
5+ use core:: ops:: Deref ;
6+ use core:: pin:: Pin ;
47use stm32f7xx_hal:: {
5- dma:: { Handle , Stream7 } ,
8+ dma:: { Handle , Stream7 , TransferResources } ,
69 gpio:: { GpioExt , Speed } ,
710 pac:: { DMA2 , GPIOB , GPIOD , GPIOE , QUADSPI , RCC } ,
8- qspi:: { Qspi , QspiTransaction , QspiWidth } ,
11+ qspi:: { Qspi , QspiTransaction , QspiWidth , RxTx } ,
912 state,
1013} ;
1114
@@ -19,8 +22,8 @@ const ID_MANF: u8 = 0x20;
1922const ID_MEMT : u8 = 0xBA ;
2023const ID_MEMC : u8 = 0x18 ;
2124const MAX_ADDR : u32 = 0x00FF_FFFF ;
22- const SUBSECTOR_SIZE : u32 = 4096 ;
23- const PAGE_SIZE : u32 = 256 ;
25+ pub const SUBSECTOR_SIZE : u32 = 4096 ;
26+ pub const PAGE_SIZE : u32 = 256 ;
2427
2528pub struct Mt25q {
2629 driver : Qspi ,
@@ -86,22 +89,29 @@ impl Mt25q {
8689 } ;
8790
8891 let mut id = [ 0 , 0 , 0 ] ;
89- self . driver . polling_read ( & mut id, transaction) . unwrap ( ) ;
92+ self . driver . read ( & mut id, transaction) . unwrap ( ) ;
9093
9194 if id[ 0 ] != ID_MANF || id[ 1 ] != ID_MEMT || id[ 2 ] != ID_MEMC {
9295 panic ! ( "Error: Device ID mismatch!" ) ;
9396 }
9497 }
9598
9699 /// Blocking DMA read.
97- pub fn read_dma (
100+ ///
101+ /// NOTE: This function could be easily modified for non-blocking by returning
102+ /// the handle to the ongoing DMA `Transfer`.
103+ pub fn read_dma < B > (
98104 & mut self ,
99- dst : & [ u8 ] ,
105+ dst : Pin < B > ,
100106 src : u32 ,
101107 len : usize ,
102108 dma : & Handle < DMA2 , state:: Enabled > ,
103109 stream : Stream7 < DMA2 > ,
104- ) -> Stream7 < DMA2 > {
110+ ) -> TransferResources < RxTx < QUADSPI > , B >
111+ where
112+ B : Deref + ' static ,
113+ B :: Target : AsSlice < Element = u8 > ,
114+ {
105115 assert ! ( len > 0 ) ;
106116 assert ! ( src + ( len as u32 ) <= MAX_ADDR ) ;
107117
@@ -115,61 +125,63 @@ impl Mt25q {
115125 data_len : Some ( len) ,
116126 } ;
117127
118- self . driver . dma_read ( dst, transaction, dma, stream) . unwrap ( )
128+ // Start the DMA read
129+ let rx_transfer = self . driver . read_all ( dst, transaction, dma, stream) . unwrap ( ) ;
130+
131+ // Wait for DMA read to finish
132+ rx_transfer. wait ( & dma) . unwrap ( )
119133 }
120134
121- /// Blocking DMA write.
122- pub fn write_dma (
135+ /// Blocking DMA page write.
136+ ///
137+ /// NOTE: This function could be easily modified for non-blocking by returning
138+ /// the handle to the ongoing DMA `Transfer`. However for this flash chip it
139+ /// would not be very useful, since writes are limited by page size. The only
140+ /// way to acheive non-blocking writes would be to use interrupts to reload DMA
141+ /// for each page.
142+ pub fn write_page_dma < B > (
123143 & mut self ,
124144 dst : u32 ,
125- src : & [ u8 ] ,
145+ src : Pin < B > ,
126146 len : usize ,
127147 dma : & Handle < DMA2 , state:: Enabled > ,
128148 stream : Stream7 < DMA2 > ,
129- ) -> Stream7 < DMA2 > {
149+ ) -> TransferResources < RxTx < QUADSPI > , B >
150+ where
151+ B : Deref + ' static ,
152+ B :: Target : AsSlice < Element = u8 > ,
153+ {
130154 assert ! ( len > 0 ) ;
131155 assert ! ( dst + ( len as u32 ) <= MAX_ADDR ) ;
132156
133- let mut outer_idx: usize = 0 ;
134- let mut curr_addr: u32 = dst;
135- let mut curr_len: usize = len;
136- let mut curr_stream = stream;
137-
138157 // Constraints for writes: (1) Must be <= 256 bytes, (2) must not cross a page boundry
139- while curr_len > 0 {
140- self . write_enable ( ) ;
158+ assert ! ( len as u32 <= PAGE_SIZE ) ;
159+ assert ! ( dst % PAGE_SIZE == 0 ) ;
141160
142- let start_page = curr_addr - ( curr_addr % PAGE_SIZE ) ;
143- let end_page = start_page + PAGE_SIZE ;
144- let size: usize = if curr_addr + ( curr_len as u32 ) > end_page {
145- ( end_page - curr_addr) as usize
146- } else {
147- curr_len
148- } ;
161+ self . write_enable ( ) ;
149162
150- let transaction = QspiTransaction {
151- iwidth : QspiWidth :: SING ,
152- awidth : QspiWidth :: SING ,
153- dwidth : QspiWidth :: QUAD ,
154- instruction : CMD_MEM_PROGRAM ,
155- address : Some ( curr_addr & MAX_ADDR ) ,
156- dummy : 0 ,
157- data_len : Some ( size ) ,
158- } ;
163+ let transaction = QspiTransaction {
164+ iwidth : QspiWidth :: SING ,
165+ awidth : QspiWidth :: SING ,
166+ dwidth : QspiWidth :: QUAD ,
167+ instruction : CMD_MEM_PROGRAM ,
168+ address : Some ( dst & MAX_ADDR ) ,
169+ dummy : 0 ,
170+ data_len : Some ( len ) ,
171+ } ;
159172
160- let buf = unsafe { core:: slice:: from_raw_parts ( & src[ outer_idx] as * const u8 , size) } ;
161- curr_stream = self
162- . driver
163- . dma_write ( buf, transaction, dma, curr_stream)
164- . unwrap ( ) ;
165- self . poll_status ( ) ;
173+ // Start the DMA write
174+ let tx_transfer = self
175+ . driver
176+ . write_all ( src, transaction, dma, stream)
177+ . unwrap ( ) ;
166178
167- outer_idx += size ;
168- curr_addr += size as u32 ;
169- curr_len -= size ;
170- }
179+ // Wait for DMA write to finish
180+ let resources = tx_transfer . wait ( & dma ) . unwrap ( ) ;
181+
182+ self . poll_status ( ) ;
171183
172- curr_stream
184+ resources
173185 }
174186
175187 /// Blocking polling read.
@@ -187,7 +199,7 @@ impl Mt25q {
187199 data_len : Some ( len) ,
188200 } ;
189201
190- self . driver . polling_read ( dst, transaction) . unwrap ( ) ;
202+ self . driver . read ( dst, transaction) . unwrap ( ) ;
191203 }
192204
193205 /// Blocking polling write.
@@ -222,7 +234,7 @@ impl Mt25q {
222234 } ;
223235
224236 let buf = unsafe { core:: slice:: from_raw_parts ( & src[ outer_idx] as * const u8 , size) } ;
225- self . driver . polling_write ( buf, transaction) . unwrap ( ) ;
237+ self . driver . write ( buf, transaction) . unwrap ( ) ;
226238 self . poll_status ( ) ;
227239
228240 outer_idx += size;
@@ -257,7 +269,7 @@ impl Mt25q {
257269 } ;
258270
259271 let mut dummy = [ 0 ] ;
260- self . driver . polling_read ( & mut dummy, transaction) . unwrap ( ) ;
272+ self . driver . read ( & mut dummy, transaction) . unwrap ( ) ;
261273
262274 num_erased_bytes += SUBSECTOR_SIZE ;
263275 addr += SUBSECTOR_SIZE ;
@@ -282,9 +294,7 @@ impl Mt25q {
282294
283295 let mut status = [ 0 ] ;
284296 while status[ 0 ] & 0x80 == 0 {
285- self . driver
286- . polling_read ( & mut status, transaction. clone ( ) )
287- . unwrap ( ) ;
297+ self . driver . read ( & mut status, transaction. clone ( ) ) . unwrap ( ) ;
288298 }
289299 }
290300
@@ -301,6 +311,6 @@ impl Mt25q {
301311 } ;
302312
303313 let mut dummy = [ 0 ] ;
304- self . driver . polling_read ( & mut dummy, transaction) . unwrap ( )
314+ self . driver . read ( & mut dummy, transaction) . unwrap ( )
305315 }
306316}
0 commit comments