1use core::cell::Cell;
48use core::cmp;
49use kernel::hil;
50use kernel::utilities::cells::{MapCell, OptionalCell, TakeCell};
51use kernel::utilities::leasable_buffer::SubSliceMut;
52use kernel::ErrorCode;
53
54pub const BUF_LEN: usize = 512;
55
56const SPI_SPEED: u32 = 4000000;
57
58#[allow(dead_code)]
59enum Opcodes {
60 WriteEnable = 0x06,
61 WriteDisable = 0x04,
62 ReadStatusRegister = 0x05,
63 WriteStatusRegister = 0x01,
64 ReadMemory = 0x03,
65 WriteMemory = 0x02,
66}
67
68#[derive(Clone, Copy, PartialEq)]
69enum State {
70 Idle,
71
72 ReadStatus,
74
75 WriteEnable,
77 WriteMemory,
78
79 ReadMemory,
81}
82
83pub trait FM25CLCustom {
84 fn read_status(&self) -> Result<(), ErrorCode>;
85}
86
87pub trait FM25CLClient {
88 fn status(&self, status: u8);
89 fn read(&self, data: &'static mut [u8], len: usize);
90 fn done(&self, buffer: &'static mut [u8]);
91}
92
93pub struct FM25CL<'a, S: hil::spi::SpiMasterDevice<'a>> {
94 spi: &'a S,
95 state: Cell<State>,
96 txbuffer: MapCell<SubSliceMut<'static, u8>>,
97 rxbuffer: MapCell<SubSliceMut<'static, u8>>,
98 client: OptionalCell<&'a dyn hil::nonvolatile_storage::NonvolatileStorageClient>,
99 client_custom: OptionalCell<&'a dyn FM25CLClient>,
100 client_buffer: TakeCell<'static, [u8]>, client_write_address: Cell<u16>,
102 client_write_len: Cell<u16>,
103}
104
105impl<'a, S: hil::spi::SpiMasterDevice<'a>> FM25CL<'a, S> {
106 pub fn new(
107 spi: &'a S,
108 txbuffer: &'static mut [u8],
109 rxbuffer: &'static mut [u8],
110 ) -> FM25CL<'a, S> {
111 FM25CL {
113 spi,
114 state: Cell::new(State::Idle),
115 txbuffer: MapCell::new(txbuffer.into()),
116 rxbuffer: MapCell::new(rxbuffer.into()),
117 client: OptionalCell::empty(),
118 client_custom: OptionalCell::empty(),
119 client_buffer: TakeCell::empty(),
120 client_write_address: Cell::new(0),
121 client_write_len: Cell::new(0),
122 }
123 }
124
125 pub fn set_client<C: FM25CLClient>(&self, client: &'a C) {
126 self.client_custom.set(client);
127 }
128
129 fn configure_spi(&self) -> Result<(), ErrorCode> {
131 self.spi.configure(
132 hil::spi::ClockPolarity::IdleLow,
133 hil::spi::ClockPhase::SampleLeading,
134 SPI_SPEED,
135 )
136 }
137
138 pub fn write(
139 &self,
140 address: u16,
141 buffer: &'static mut [u8],
142 len: u16,
143 ) -> Result<(), ErrorCode> {
144 self.configure_spi()?;
145
146 self.txbuffer
147 .take()
148 .map_or(Err(ErrorCode::RESERVE), move |mut txbuffer| {
149 let write_len = cmp::min(txbuffer.len(), len as usize);
150
151 self.client_buffer.replace(buffer);
153 self.client_write_address.set(address);
155 self.client_write_len.set(write_len as u16);
156
157 self.state.set(State::WriteEnable);
158 txbuffer[0] = Opcodes::WriteEnable as u8;
159 txbuffer.slice(..1);
160 let res = self.spi.read_write_bytes(txbuffer, None);
161
162 match res {
163 Ok(()) => Ok(()),
164 Err((err, txbuffer, _)) => {
165 self.txbuffer.replace(txbuffer);
166 Err(err)
167 }
168 }
169 })
170 }
171
172 pub fn read(&self, address: u16, buffer: &'static mut [u8], len: u16) -> Result<(), ErrorCode> {
173 self.configure_spi()?;
174
175 self.txbuffer
176 .take()
177 .map_or(Err(ErrorCode::RESERVE), |mut txbuffer| {
178 self.rxbuffer
179 .take()
180 .map_or(Err(ErrorCode::RESERVE), move |mut rxbuffer| {
181 txbuffer[0] = Opcodes::ReadMemory as u8;
182 txbuffer[1] = ((address >> 8) & 0xFF) as u8;
183 txbuffer[2] = (address & 0xFF) as u8;
184
185 self.client_buffer.replace(buffer);
187
188 rxbuffer.reset();
189 let read_len = cmp::min(rxbuffer.len(), 3 + len as usize);
190 rxbuffer.slice(..read_len);
191
192 self.state.set(State::ReadMemory);
193 let res = self.spi.read_write_bytes(txbuffer, Some(rxbuffer));
194 match res {
195 Ok(()) => Ok(()),
196 Err((err, txbuffer, rxbuffer)) => {
197 self.txbuffer.replace(txbuffer);
198 self.rxbuffer.replace(rxbuffer.unwrap());
199 Err(err)
200 }
201 }
202 })
203 })
204 }
205}
206
207impl<'a, S: hil::spi::SpiMasterDevice<'a>> hil::spi::SpiMasterClient for FM25CL<'a, S> {
208 fn read_write_done(
209 &self,
210 mut write_buffer: SubSliceMut<'static, u8>,
211 read_buffer: Option<SubSliceMut<'static, u8>>,
212 _status: Result<usize, ErrorCode>,
213 ) {
214 write_buffer.reset();
215 match self.state.get() {
216 State::ReadStatus => {
217 self.state.set(State::Idle);
218
219 self.txbuffer.replace(write_buffer);
221
222 read_buffer.map(|read_buffer| {
223 let status = read_buffer[1];
224
225 self.rxbuffer.replace(read_buffer);
227
228 self.client_custom.map(|client| client.status(status));
229 });
230 }
231 State::WriteEnable => {
232 self.state.set(State::WriteMemory);
233
234 self.client_buffer.map(move |buffer| {
235 write_buffer[0] = Opcodes::WriteMemory as u8;
236 write_buffer[1] = ((self.client_write_address.get() >> 8) & 0xFF) as u8;
237 write_buffer[2] = (self.client_write_address.get() & 0xFF) as u8;
238
239 let write_len =
240 cmp::min(write_buffer.len(), self.client_write_len.get() as usize);
241
242 write_buffer[3..(write_len + 3)].copy_from_slice(&buffer[..write_len]);
243 write_buffer.slice(..write_len + 3);
244
245 let _ = self.spi.read_write_bytes(write_buffer, read_buffer);
246 });
247 }
248 State::WriteMemory => {
249 self.state.set(State::Idle);
250
251 let write_len = cmp::min(write_buffer.len(), self.client_write_len.get() as usize);
252
253 self.txbuffer.replace(write_buffer);
255 read_buffer.map(|read_buffer| {
256 self.rxbuffer.replace(read_buffer);
257 });
258
259 self.client_buffer.take().map(move |buffer| {
261 self.client
262 .map(move |client| client.write_done(buffer, write_len));
263 });
264 }
265 State::ReadMemory => {
266 self.state.set(State::Idle);
267
268 self.txbuffer.replace(write_buffer);
270
271 read_buffer.map(|read_buffer| {
272 self.client_buffer.take().map(move |buffer| {
273 let read_len = buffer.len();
274
275 buffer[..(read_len - 3)]
276 .copy_from_slice(&read_buffer[3..((read_len - 3) + 3)]);
277
278 self.rxbuffer.replace(read_buffer);
279
280 self.client
281 .map(move |client| client.read_done(buffer, read_len - 3));
282 });
283 });
284 }
285 _ => {}
286 }
287 }
288}
289
290impl<'a, S: hil::spi::SpiMasterDevice<'a>> FM25CLCustom for FM25CL<'a, S> {
292 fn read_status(&self) -> Result<(), ErrorCode> {
293 self.configure_spi()?;
294
295 self.txbuffer
296 .take()
297 .map_or(Err(ErrorCode::RESERVE), |mut txbuffer| {
298 self.rxbuffer
299 .take()
300 .map_or(Err(ErrorCode::RESERVE), move |mut rxbuffer| {
301 txbuffer[0] = Opcodes::ReadStatusRegister as u8;
302
303 rxbuffer.reset();
307 rxbuffer.slice(..4);
308 let _ = self.spi.read_write_bytes(txbuffer, Some(rxbuffer));
309 self.state.set(State::ReadStatus);
310 Ok(())
311 })
312 })
313 }
314}
315
316impl<'a, S: hil::spi::SpiMasterDevice<'a>> hil::nonvolatile_storage::NonvolatileStorage<'a>
319 for FM25CL<'a, S>
320{
321 fn set_client(&self, client: &'a dyn hil::nonvolatile_storage::NonvolatileStorageClient) {
322 self.client.set(client);
323 }
324
325 fn read(
326 &self,
327 buffer: &'static mut [u8],
328 address: usize,
329 length: usize,
330 ) -> Result<(), ErrorCode> {
331 self.read(address as u16, buffer, length as u16)
332 }
333
334 fn write(
335 &self,
336 buffer: &'static mut [u8],
337 address: usize,
338 length: usize,
339 ) -> Result<(), ErrorCode> {
340 self.write(address as u16, buffer, length as u16)
341 }
342}