Contiki 3.x
flash.c
1 /* Author: Simon Aittamaa */
2 
3 #include <stddef.h>
4 #include <stdint.h>
5 #include <string.h>
6 
7 #include "K60.h"
8 
9 #include "flash.h"
10 
11 #include "udelay.h"
12 
13 /* TODO(henrik) Clean up */
14 
15 /* ************************************************************************** */
16 /* #define FLASH_DEBUG */
17 #ifdef FLASH_DEBUG
18 #include <stdio.h>
19 #define DEBUG(...) printf(__VA_ARGS__)
20 #else
21 #define DEBUG(...) (void)(0);
22 #endif
23 
24 /* ************************************************************************** */
25 
26 /** \todo move FLASH_CTAS to spi abstraction consolidation file. */
27 #define FLASH_CTAS 0
28 
29 /* Spi functions */
30 typedef enum spi_transfer_flag {
31  SPI_TRANSFER_DONE = 0,
32  SPI_TRANSFER_CONT = 1
33 } spi_transfer_flag_t;
34 
35 typedef enum spi_transfer_sync {
36  SPI_TRANSFER_ASYNC = 0,
37  SPI_TRANSFER_BLOCKING = 1
38 } spi_transfer_sync_t;
39 
40 void
41 spi_init(void)
42 {
43  SIM->SCGC5 |= SIM_SCGC5_PORTD_MASK;
44  PORTD->PCR[5] = PORT_PCR_MUX(2); /* SPI0_PCS2 */
45  PORTD->PCR[2] = PORT_PCR_MUX(2); /* SPI0_MOSI */
46  PORTD->PCR[1] = PORT_PCR_MUX(2); /* SPI0_SCLK */
47  PORTD->PCR[3] = PORT_PCR_MUX(2); /* SPI0_MISO */
48 
49  /* Enable clock gate for SPI0 module */
50  SIM->SCGC6 |= SIM_SCGC6_SPI0_MASK;
51 
52  /* Configure SPI0 */
53  /* Master mode */
54  /* all peripheral chip select signals are active low */
55  /* Disable TX,RX FIFO */
56  SPI0->MCR = SPI_MCR_MSTR_MASK | SPI_MCR_PCSIS(0x1F) | SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK; /* 0x803F3000; */
57  /* 8 bit frame size */
58  /* Set up different delays and clock scalers */
59  /* TODO: These need tuning */
60  /* FIXME: Coordinate SPI0 parameters between different peripheral drivers */
61  /* IMPORTANT: Clock polarity is active low! */
62  SPI0->CTAR[FLASH_CTAS] = SPI_CTAR_FMSZ(7) | SPI_CTAR_CSSCK(2) | SPI_CTAR_ASC(2) | SPI_CTAR_DT(2) | SPI_CTAR_BR(4); /*0x38002224; *//* TODO: Should be able to speed up */
63 }
64 /**
65  * Perform a one byte transfer over SPI.
66  *
67  * \param ctas The CTAS register to use for timing information (0 or 1)
68  * \param cs The chip select pins to assert. Bitmask, not PCS number.
69  * \param cont Whether to keep asserting the chip select pin after the current transfer ends.
70  * \param data The data to write to the slave.
71  * \param blocking If set to SPI_TRANSFER_BLOCKING, wait until all bits have been transferred before returning.
72  * \return The byte received from the slave during the same transfer.
73  *
74  * \note There is no need for separate read and write functions, since SPI transfers work like a shift register (one bit out, one bit in.)
75  *
76  * \todo Make SPI abstraction standalone.
77  */
78 static uint8_t
79 spi_transfer(const uint8_t ctas, const uint32_t cs,
80  const spi_transfer_flag_t cont, const uint32_t data,
81  const spi_transfer_sync_t blocking)
82 {
83  uint32_t spi_pushr;
84 
85  spi_pushr = SPI_PUSHR_TXDATA(data);
86  spi_pushr |= SPI_PUSHR_CTAS(ctas);
87  spi_pushr |= SPI_PUSHR_PCS(cs);
88  if(cont == SPI_TRANSFER_CONT) {
89  spi_pushr |= SPI_PUSHR_CONT_MASK;
90  }
91 
92  /* Clear transfer complete flag */
93  SPI0->SR |= SPI_SR_TCF_MASK;
94 
95  /* Shift a frame out/in */
96  SPI0->PUSHR = spi_pushr;
97 
98  if(blocking) {
99  /* Wait for transfer complete */
100  while(!(SPI0->SR & SPI_SR_TCF_MASK));
101  }
102 
103  /* Pop the buffer */
104  return SPI0->POPR;
105 }
106 /* ************************************************************************** */
107 typedef enum flash_cmd {
108  FLASH_CMD_WREN = 0x06,
109  FLASH_CMD_WRDI = 0x04,
110  FLASH_CMD_RDID = 0x9f,
111  FLASH_CMD_RDSR = 0x05,
112  FLASH_CMD_WRSR = 0x01,
113  FLASH_CMD_EN4B = 0xb7,
114  FLASH_CMD_EX4B = 0xe9,
115  FLASH_CMD_READ = 0x03,
116  FLASH_CMD_FAST_READ = 0x0b,
117  FLASH_CMD_RDSFDP = 0x5a,
118  FLASH_CMD_2READ = 0xbb,
119  FLASH_CMD_DREAD = 0x3b,
120  FLASH_CMD_4READ = 0xeb,
121  FLASH_CMD_QREAD = 0x6b,
122  FLASH_CMD_4PP = 0x38,
123  FLASH_CMD_SE = 0xd8,
124  /* FLASH_CMD_BE = 0xd8, */
125  FLASH_CMD_BE32K = 0x52,
126  FLASH_CMD_CE = 0xc7,
127  FLASH_CMD_PP = 0x02,
128  FLASH_CMD_CP = 0xad,
129  FLASH_CMD_DP = 0xb9,
130  FLASH_CMD_RDP = 0xab,
131  FLASH_CMD_RES = 0xab,
132  FLASH_CMD_REMS = 0x90,
133  FLASH_CMD_REMS2 = 0xef,
134  FLASH_CMD_REMS4 = 0xdf,
135  FLASH_CMD_ENSO = 0xb1,
136  FLASH_CMD_EXSO = 0xc1,
137  FLASH_CMD_RDSCUR = 0x2b,
138  FLASH_CMD_WRSCUR = 0x2f,
139  FLASH_CMD_ESRY = 0x70,
140  FLASH_CMD_DSRY = 0x80,
141  FLASH_CMD_CLSR = 0x30,
142  FLASH_CMD_HPM = 0xa3,
143  FLASH_CMD_WPSEL = 0x68,
144  FLASH_CMD_SBLK = 0x36,
145  FLASH_CMD_SBULK = 0x39,
146  FLASH_CMD_RDBLOCK = 0x3c,
147  FLASH_CMD_GBLK = 0x7e,
148  FLASH_CMD_GBULK = 0x98
149 } flash_cmd_t;
150 
151 typedef enum flash_status {
152  FLASH_STATUS_WIP = 1 << 0,
153  FLASH_STATUS_WEL = 1 << 1,
154  FLASH_STATUS_SRWD = 1 << 7
155 } flash_status_t;
156 
157 typedef enum flash_security {
158  FLASH_SECURITY_CP = 1 << 4,
159  FLASH_SECURITY_P_FAIL = 1 << 5,
160  FLASH_SECURITY_E_FAIL = 1 << 6
161 } flash_security_t;
162 
163 /* ************************************************************************** */
164 
165 static const int FLASH_PAGE_WRITE_SIZE = 32;
166 
167 /* ************************************************************************** */
168 
169 static struct {
170  uint32_t active;
171  flash_id_t id;
172  uint32_t addr;
173  const uint8_t *data;
174  uint32_t size;
175 } scheduled_write;
176 
177 /* ************************************************************************** */
178 
179 static void cmd_wrdi(const flash_id_t);
180 static void cmd_wren(const flash_id_t);
181 /* static void cmd_clsr(const flash_id_t); */
182 static uint32_t cmd_rdscur(const flash_id_t);
183 static void cmd_wrsr(const flash_id_t, const uint32_t);
184 static uint32_t cmd_rdsr(const flash_id_t);
185 static uint32_t cmd_rdid(const flash_id_t);
186 static uint32_t cmd_pp(const flash_id_t, const flash_addr_t, const uint8_t *, const uint32_t);
187 static void cmd_se(const flash_id_t, const uint32_t);
188 /* static void cmd_be(const flash_id_t, const uint32_t); */
189 static void cmd_ce(const flash_id_t);
190 
191 /* ************************************************************************** */
192 
193 static void
194 spi_write_addr(const flash_id_t id, const spi_transfer_flag_t flag, const flash_addr_t addr)
195 {
196  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_CONT, (addr >> 16) & 0xff, SPI_TRANSFER_BLOCKING);
197  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_CONT, (addr >> 8) & 0xff, SPI_TRANSFER_BLOCKING);
198  spi_transfer(FLASH_CTAS, id, flag, addr & 0xff, SPI_TRANSFER_BLOCKING);
199 }
200 /* ************************************************************************** */
201 
202 /** Read ID */
203 static uint32_t
204 cmd_rdid(const flash_id_t id)
205 {
206  uint32_t result;
207 
208  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_CONT, FLASH_CMD_RDID, SPI_TRANSFER_BLOCKING);
209  result = spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_CONT, 0, SPI_TRANSFER_BLOCKING);
210  result <<= 8;
211  result |= spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_CONT, 0, SPI_TRANSFER_BLOCKING);
212  result <<= 8;
213  result |= spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_DONE, 0, SPI_TRANSFER_BLOCKING);
214 
215  return result;
216 }
217 /* ************************************************************************** */
218 
219 /** Read status register */
220 static uint32_t
221 cmd_rdsr(const flash_id_t id)
222 {
223  uint32_t result;
224 
225  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_CONT, FLASH_CMD_RDSR, SPI_TRANSFER_BLOCKING);
226  result = spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_DONE, 0, SPI_TRANSFER_BLOCKING);
227 
228  return result;
229 }
230 /* ************************************************************************** */
231 
232 static void cmd_wrsr(const flash_id_t id, const uint32_t status) __attribute__((unused));
233 
234 /** Write status register */
235 static void
236 cmd_wrsr(const flash_id_t id, const uint32_t status)
237 {
238  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_CONT, FLASH_CMD_WRSR, SPI_TRANSFER_BLOCKING);
239  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_DONE, status, SPI_TRANSFER_BLOCKING);
240 }
241 /* ************************************************************************** */
242 
243 static uint32_t
244 cmd_rdscur(const flash_id_t id)
245 {
246  uint32_t result;
247 
248  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_CONT, FLASH_CMD_RDSCUR, SPI_TRANSFER_BLOCKING);
249  result = spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_DONE, 0, SPI_TRANSFER_BLOCKING);
250 
251  return result;
252 }
253 /* ************************************************************************** */
254 
255 /*
256  static void cmd_clsr(const flash_id_t id)
257  {
258  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_DONE, FLASH_CMD_CLSR, SPI_TRANSFER_BLOCKING);
259  }
260  */
261 
262 /* ************************************************************************** */
263 
264 static void
265 cmd_wren(const flash_id_t id)
266 {
267  while(!(cmd_rdsr(id) & FLASH_STATUS_WEL)) {
268  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_DONE, FLASH_CMD_WREN, SPI_TRANSFER_BLOCKING);
269  }
270 }
271 /* ************************************************************************** */
272 
273 static void
274 cmd_wrdi(const flash_id_t id)
275 {
276  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_DONE, FLASH_CMD_WRDI, SPI_TRANSFER_BLOCKING);
277 }
278 /* ************************************************************************** */
279 
280 static uint32_t
281 cmd_pp(const flash_id_t id, const flash_addr_t addr, const uint8_t *data, const uint32_t size)
282 {
283  uint32_t i;
284 
285  if(size == 0) {
286  return E_FLASH_OK;
287  }
288 
289  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_CONT, FLASH_CMD_PP, SPI_TRANSFER_BLOCKING);
290 
291  spi_write_addr(id, SPI_TRANSFER_CONT, addr);
292 
293  for(i = 0; i < size - 1; ++i) {
294  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_CONT, *(data++), SPI_TRANSFER_BLOCKING);
295  }
296  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_DONE, *data, SPI_TRANSFER_BLOCKING);
297 
298 /*
299  if (cmd_rdscur(id) & FLASH_SECURITY_P_FAIL) {
300  return E_FLASH_WRITE_FAILED;
301  }
302  */
303 
304  return E_FLASH_OK;
305 }
306 /* ************************************************************************** */
307 
308 static uint32_t
309 cmd_ppi(const flash_id_t id, const flash_addr_t addr, const uint8_t *data, const uint32_t size)
310 {
311  uint32_t i;
312 
313  if(size == 0) {
314  return E_FLASH_OK;
315  }
316 
317  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_CONT, FLASH_CMD_PP, SPI_TRANSFER_BLOCKING);
318 
319  spi_write_addr(id, SPI_TRANSFER_CONT, addr);
320 
321  for(i = 0; i < size - 1; ++i) {
322  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_CONT, ~(*(data++)), SPI_TRANSFER_BLOCKING);
323  }
324  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_DONE, ~(*data), SPI_TRANSFER_BLOCKING);
325 
326 /* if (cmd_rdscur(id) & FLASH_SECURITY_P_FAIL) { */
327 /* return E_FLASH_WRITE_FAILED; */
328 /* } */
329 
330  return E_FLASH_OK;
331 }
332 /* ************************************************************************** */
333 
334 static uint32_t cmd_cp(const flash_id_t id, const flash_addr_t addr, const uint8_t *data, const uint32_t size) __attribute__((unused));
335 static uint32_t
336 cmd_cp(const flash_id_t id, const flash_addr_t addr, const uint8_t *data, uint32_t size)
337 {
338  if(size == 0) {
339  return 0;
340  }
341 
342  if(cmd_rdscur(id) & FLASH_SECURITY_CP) {
343  DEBUG("Flash already in continous programming mode.\n");
344  return 1;
345  }
346 
347  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_CONT, FLASH_CMD_CP, SPI_TRANSFER_BLOCKING);
348 
349  spi_write_addr(id, SPI_TRANSFER_CONT, addr);
350 
351  while(size > 2) {
352  size -= 2;
353 
354  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_CONT, *(data++), SPI_TRANSFER_BLOCKING);
355  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_CONT, *(data++), SPI_TRANSFER_BLOCKING);
356 
357  if(!(cmd_rdscur(id) & FLASH_SECURITY_CP)) {
358  DEBUG("Flash unexcpectedly left continous programming mode.\n");
359  return 1;
360  }
361 
362  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_CONT, FLASH_CMD_CP, SPI_TRANSFER_BLOCKING);
363  }
364 
365  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_CONT, *(data++), SPI_TRANSFER_BLOCKING);
366  if(size == 2) {
367  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_DONE, *(data++), SPI_TRANSFER_BLOCKING);
368  } else {
369  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_DONE, 0xff, SPI_TRANSFER_BLOCKING);
370  }
371 
372  cmd_wrdi(id);
373 
374  return 0;
375 }
376 /* ************************************************************************** */
377 
378 static void
379 cmd_se(const flash_id_t id, const uint32_t sector)
380 {
381  uint32_t addr = sector * FLASH_SECTOR_SIZE;
382 
383  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_CONT, FLASH_CMD_SE, SPI_TRANSFER_BLOCKING);
384  spi_write_addr(id, SPI_TRANSFER_DONE, addr);
385 }
386 /* ************************************************************************** */
387 
388 static void
389 cmd_ce(const flash_id_t id)
390 {
391  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_DONE, FLASH_CMD_CE, SPI_TRANSFER_BLOCKING);
392 }
393 /* ************************************************************************** */
394 
395 static void
396 cmd_dp(const flash_id_t id)
397 {
398  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_DONE, FLASH_CMD_DP, SPI_TRANSFER_BLOCKING);
399 }
400 /* ************************************************************************** */
401 
402 static void
403 cmd_rdp(const flash_id_t id)
404 {
405  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_DONE, FLASH_CMD_RDP, SPI_TRANSFER_BLOCKING);
406 }
407 /* ************************************************************************** */
408 
409 static void
410 cmd_read(const flash_id_t id, const flash_addr_t addr, uint8_t *dest, const uint32_t size)
411 {
412  uint32_t i;
413 
414  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_CONT, FLASH_CMD_READ, SPI_TRANSFER_BLOCKING);
415 
416  spi_write_addr(id, SPI_TRANSFER_CONT, addr);
417 
418  for(i = 0; i < size - 1; ++i) {
419  *(dest++) = spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_CONT, 0, SPI_TRANSFER_BLOCKING);
420  }
421  *dest = spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_DONE, 0, SPI_TRANSFER_BLOCKING);
422 }
423 /* ************************************************************************** */
424 
425 static void
426 cmd_readi(const flash_id_t id, const flash_addr_t addr, uint8_t *dest, const uint32_t size)
427 {
428  uint32_t i;
429 
430  spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_CONT, FLASH_CMD_READ, SPI_TRANSFER_BLOCKING);
431 
432  spi_write_addr(id, SPI_TRANSFER_CONT, addr);
433 
434  for(i = 0; i < size - 1; ++i) {
435  *(dest++) = ~spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_CONT, 0, SPI_TRANSFER_BLOCKING);
436  }
437  *dest = ~spi_transfer(FLASH_CTAS, id, SPI_TRANSFER_DONE, 0, SPI_TRANSFER_BLOCKING);
438 }
439 /* ************************************************************************** */
440 
441 static void
442 flash_busy_wait(const flash_id_t id)
443 {
444  while(cmd_rdsr(id) & FLASH_STATUS_WIP) {
445  /* XXX: Attempt to fix slow erase times on some chips by not flooding the device with status requests */
446  udelay(1000);
447  }
448 }
449 /* ************************************************************************** */
450 
451 static void
452 flash_write_prepare(const flash_id_t id)
453 {
454  flash_busy_wait(id);
455  /* cmd_clsr(id); */
456  cmd_wren(id);
457 }
458 /* ************************************************************************** */
459 
460 flash_error_t
461 flash_init(void)
462 {
463  uint32_t status;
464  uint32_t jedec_id;
465  int i;
466 
467  SIM->SCGC5 |= SIM_SCGC5_PORTD_MASK;
468 
469  spi_init();
470  {
471  /* Wait a while for memories to start */
472  /* TODO(henrik) Change this to more exact times. */
473  for(i = 0; i < 200; ++i) {
474  udelay(1000);
475  }
476  }
477  for(i = FLASH_ID0; i <= FLASH_ID0; ++i) {
478  status = cmd_rdsr(i);
479  if(status) {
480  DEBUG("Error: Status of flash 0 is non-zero (0x%02x).\n", status);
481  return E_FLASH_INVALID_STATUS;
482  }
483  jedec_id = cmd_rdid(i);
484  if(jedec_id != 0x202015) {
485  DEBUG("Flash0: Invalid JEDEC-ID: 0x%08x\n", jedec_id);
486  return E_FLASH_UNKNOWN;
487  }
488  }
489 
490  return E_FLASH_OK;
491 }
492 /* ************************************************************************** */
493 
494 flash_error_t
495 flash_erase_chip(const flash_id_t id, const flash_flags_t flags)
496 {
497  DEBUG("Starting chip erase...");
498 
499  if((flags & FLASH_WAIT) == 0) {
500  if(cmd_rdsr(id) & FLASH_STATUS_WIP) {
501  return E_FLASH_BUSY;
502  }
503  }
504 
505  flash_write_prepare(id);
506 
507  cmd_ce(id);
508 
509  if(flags & FLASH_FINISH) {
510  flash_busy_wait(id);
511 /* if (cmd_rdscur(id) & FLASH_SECURITY_E_FAIL) { */
512 /* DEBUG("failed!\n"); */
513 /* } */
514  cmd_wrdi(id);
515  }
516 
517  DEBUG("done.\n");
518 
519  return E_FLASH_OK;
520 }
521 /* ************************************************************************** */
522 
523 flash_error_t
524 flash_erase_sector(const flash_id_t id, const uint32_t sector, const flash_flags_t flags)
525 {
526  if((flags & FLASH_WAIT) == 0) {
527  if(cmd_rdsr(id) & FLASH_STATUS_WIP) {
528  return E_FLASH_BUSY;
529  }
530  }
531 
532  DEBUG("Starting sector erase...");
533 
534  flash_write_prepare(id);
535 
536  cmd_se(id, sector);
537 
538  if(flags & FLASH_FINISH) {
539  flash_busy_wait(id);
540 /* if (cmd_rdscur(id) & FLASH_SECURITY_E_FAIL) { */
541 /* DEBUG("failed! (0x%02x)\n"); */
542 /* return E_FLASH_ERASE_FAILED; */
543 /* } */
544  cmd_wrdi(id);
545  }
546 
547  DEBUG("done.\n");
548 
549  return E_FLASH_OK;
550 }
551 /* ************************************************************************** */
552 
553 flash_error_t
554 flash_write_queue(const flash_id_t id, const flash_addr_t addr, const uint8_t *data, const uint32_t size, const flash_flags_t flags)
555 {
556  if(scheduled_write.active) {
557  DEBUG("We already have a scheduled write.\n");
558  return E_FLASH_QUEUE_FULL;
559  }
560 
561  if(size == 0) {
562  return E_FLASH_OK;
563  }
564 
565  scheduled_write.active = 1;
566  scheduled_write.id = id;
567  scheduled_write.addr = addr;
568  scheduled_write.data = data;
569  scheduled_write.size = size;
570 
571  return E_FLASH_OK;
572 }
573 /* ************************************************************************** */
574 
575 flash_error_t
576 flash_write_process(const flash_flags_t flags)
577 {
578  uint32_t count;
579 
580  if(scheduled_write.active == 0) {
581  return E_FLASH_OK;
582  }
583 
584  if(flags & FLASH_WAIT) {
585  if(cmd_rdsr(scheduled_write.id) & FLASH_STATUS_WIP) {
586  return E_FLASH_BUSY;
587  }
588  }
589 
590  flash_write_prepare(scheduled_write.id);
591 
592  /* NOTE: FLASH_PAGE_WRITE_SIZE controls how much we write each time... */
593  if(FLASH_PAGE_WRITE_SIZE >= FLASH_PAGE_SIZE) {
594  DEBUG("Sanity-check failed! We are trying to write too large chunks!\n");
595  }
596  count = FLASH_PAGE_WRITE_SIZE - (scheduled_write.addr % FLASH_PAGE_WRITE_SIZE);
597  if(scheduled_write.size < count) {
598  count = scheduled_write.size;
599  }
600 
601  if(cmd_pp(scheduled_write.id, scheduled_write.addr, scheduled_write.data, count) != E_FLASH_OK) {
602  DEBUG("flash_write_process(): Page-programming failed.\n");
603  return E_FLASH_WRITE_FAILED;
604  }
605 
606  scheduled_write.size -= count;
607  scheduled_write.addr += count;
608  scheduled_write.data += count;
609 
610  if(flags & FLASH_FINISH) {
611  flash_busy_wait(scheduled_write.id);
612  if(cmd_rdscur(scheduled_write.id) & FLASH_SECURITY_P_FAIL) {
613  DEBUG("flash_write_process(): Page-programming failed.\n");
614  return E_FLASH_WRITE_FAILED;
615  }
616  }
617 
618  if(scheduled_write.size == 0) {
619  scheduled_write.active = 0;
620  scheduled_write.id = 0;
621  scheduled_write.addr = 0;
622  scheduled_write.data = 0;
623  return E_FLASH_OK;
624  }
625 
626  return E_FLASH_BUSY;
627 }
628 /* ************************************************************************** */
629 
630 flash_error_t
631 flash_write(const flash_id_t id, const flash_addr_t addr, const uint8_t *data, const uint32_t size, const flash_flags_t flags)
632 {
633  uint32_t count;
634  uint32_t offset = 0;
635 
636  DEBUG("Starting flash write operation...");
637 
638  if((flags & FLASH_WAIT) == 0) {
639  if(cmd_rdsr(id) & FLASH_STATUS_WIP) {
640  return E_FLASH_BUSY;
641  }
642  }
643 
644  if(size == 0) {
645  return E_FLASH_OK;
646  }
647 
648  count = FLASH_PAGE_SIZE - (addr % FLASH_PAGE_SIZE);
649  if(size > count) {
650  flash_write_prepare(id);
651  if(cmd_pp(id, addr + offset, data + offset, count)) {
652  DEBUG("failed!\n");
653  return E_FLASH_WRITE_FAILED;
654  }
655 
656  offset += count;
657  }
658 
659  while(offset < size) {
660  count = size - offset;
661  if(count > FLASH_PAGE_SIZE) {
662  count = FLASH_PAGE_SIZE;
663  }
664 
665  flash_write_prepare(id);
666  if(cmd_pp(id, addr + offset, data + offset, count)) {
667  DEBUG("failed!\n");
668  return E_FLASH_WRITE_FAILED;
669  }
670 
671  offset += count;
672  }
673 
674  if(flags & FLASH_FINISH) {
675  flash_busy_wait(id);
676  }
677 
678  DEBUG("done.\n");
679 
680  return E_FLASH_OK;
681 }
682 /* ************************************************************************** */
683 
684 flash_error_t
685 flash_writei(const flash_id_t id, const flash_addr_t addr, const uint8_t *data, const uint32_t size, const flash_flags_t flags)
686 {
687  uint32_t count;
688  uint32_t offset = 0;
689 
690  DEBUG("Starting flash write operation...");
691 
692  if((flags & FLASH_WAIT) == 0) {
693  if(cmd_rdsr(id) & FLASH_STATUS_WIP) {
694  return E_FLASH_BUSY;
695  }
696  }
697 
698  if(size == 0) {
699  return E_FLASH_OK;
700  }
701 
702  count = FLASH_PAGE_SIZE - (addr % FLASH_PAGE_SIZE);
703  if(size > count) {
704  flash_write_prepare(id);
705  if(cmd_ppi(id, addr + offset, data + offset, count)) {
706  DEBUG("failed!\n");
707  return E_FLASH_WRITE_FAILED;
708  }
709 
710  offset += count;
711  }
712 
713  while(offset < size) {
714  count = size - offset;
715  if(count > FLASH_PAGE_SIZE) {
716  count = FLASH_PAGE_SIZE;
717  }
718 
719  flash_write_prepare(id);
720  if(cmd_ppi(id, addr + offset, data + offset, count)) {
721  DEBUG("failed!\n");
722  return E_FLASH_WRITE_FAILED;
723  }
724 
725  offset += count;
726  }
727 
728  if(flags & FLASH_FINISH) {
729  flash_busy_wait(id);
730  }
731 
732  DEBUG("done.\n");
733 
734  return E_FLASH_OK;
735 }
736 /* ************************************************************************** */
737 
738 flash_error_t
739 flash_read(const flash_id_t id, const flash_addr_t addr, uint8_t *dest, const uint32_t size, const flash_flags_t flags)
740 {
741  if(flags & FLASH_WAIT) {
742  flash_busy_wait(id);
743  } else {
744  if(cmd_rdsr(id) & FLASH_STATUS_WIP) {
745  return E_FLASH_BUSY;
746  }
747  }
748 
749  if(size == 0) {
750  return E_FLASH_OK;
751  }
752 
753  DEBUG("Starting flash read operation...");
754  cmd_read(id, addr, dest, size);
755  DEBUG("done.\n");
756 
757  return E_FLASH_OK;
758 }
759 /* ************************************************************************** */
760 
761 flash_error_t
762 flash_readi(const flash_id_t id, const flash_addr_t addr, uint8_t *dest, const uint32_t size, const flash_flags_t flags)
763 {
764  if(flags & FLASH_WAIT) {
765  flash_busy_wait(id);
766  } else {
767  if(cmd_rdsr(id) & FLASH_STATUS_WIP) {
768  return E_FLASH_BUSY;
769  }
770  }
771 
772  if(size == 0) {
773  return E_FLASH_OK;
774  }
775 
776  DEBUG("Starting flash read operation...");
777  cmd_readi(id, addr, dest, size);
778  DEBUG("done.\n");
779 
780  return E_FLASH_OK;
781 }
782 /* ************************************************************************** */
783 
784 flash_error_t
785 flash_status(const flash_id_t id)
786 {
787  if(cmd_rdsr(id) & FLASH_STATUS_WIP) {
788  return E_FLASH_BUSY;
789  } else if(scheduled_write.active) {
790  return E_FLASH_BUSY;
791  }
792 
793  return E_FLASH_OK;
794 }
795 /* ************************************************************************** */
796 
797 flash_error_t
798 flash_sleep(const flash_id_t id, const flash_flags_t flags)
799 {
800  cmd_dp(id);
801  return E_FLASH_OK;
802 }
803 /* ************************************************************************** */
804 
805 flash_error_t
806 flash_wakeup(const flash_id_t id, const flash_flags_t flags)
807 {
808  cmd_rdp(id);
809  return E_FLASH_OK;
810 }
811 /* ************************************************************************** */
812 
813 flash_error_t
814 flash_dump(const flash_id_t id, void (*dump)(const uint8_t))
815 {
816  flash_addr_t offset = 0;
817  uint8_t buf[FLASH_PAGE_SIZE];
818 
819  while(offset < FLASH_SIZE) {
820  int i;
821  flash_error_t err;
822 
823  err = flash_read(id, offset, buf, sizeof(buf), FLASH_BLOCKING);
824  if(err != E_FLASH_OK) {
825  DEBUG("Reading from flash failed while dumping (0x%02x).\r\n", err);
826  return E_FLASH_WRITE_FAILED;
827  }
828 
829  for(i = 0; i < sizeof(buf); i++) {
830  if(dump) {
831  dump(buf[i]);
832  }
833  }
834 
835  offset += sizeof(buf);
836  }
837 
838  return E_FLASH_OK;
839 }
Provide udelay routine for MK60DZ10.
Flash device driver header file for the Mulle platform.
void __attribute__((interrupt))
This ISR handles most of the business interacting with the 1-wire bus.
Definition: onewire.c:174
#define SIM
Peripheral SIM base pointer.
Definition: MK60D10.h:7650
#define SPI0
Peripheral SPI0 base pointer.
Definition: MK60D10.h:7984
void udelay(uint16_t us)
Microsecond busy wait.
Definition: udelay.c:26
K60 hardware register header wrapper.
void flash_write(unsigned short *ptr, unsigned short word)
Write a 16-bit word to flash ROM.
Definition: flash.c:98
#define PORTD
Peripheral PORTD base pointer.
Definition: MK60D10.h:6427
void spi_init(void)
Initialize the SPI bus.
Definition: spi.c:48