19 #define DEBUG(...) printf(__VA_ARGS__)
21 #define DEBUG(...) (void)(0);
30 typedef enum spi_transfer_flag {
31 SPI_TRANSFER_DONE = 0,
33 } spi_transfer_flag_t;
35 typedef enum spi_transfer_sync {
36 SPI_TRANSFER_ASYNC = 0,
37 SPI_TRANSFER_BLOCKING = 1
38 } spi_transfer_sync_t;
43 SIM->SCGC5 |= SIM_SCGC5_PORTD_MASK;
44 PORTD->PCR[5] = PORT_PCR_MUX(2);
45 PORTD->PCR[2] = PORT_PCR_MUX(2);
46 PORTD->PCR[1] = PORT_PCR_MUX(2);
47 PORTD->PCR[3] = PORT_PCR_MUX(2);
50 SIM->SCGC6 |= SIM_SCGC6_SPI0_MASK;
56 SPI0->MCR = SPI_MCR_MSTR_MASK | SPI_MCR_PCSIS(0x1F) | SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK;
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);
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)
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;
93 SPI0->SR |= SPI_SR_TCF_MASK;
96 SPI0->PUSHR = spi_pushr;
100 while(!(
SPI0->SR & SPI_SR_TCF_MASK));
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,
125 FLASH_CMD_BE32K = 0x52,
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
151 typedef enum flash_status {
152 FLASH_STATUS_WIP = 1 << 0,
153 FLASH_STATUS_WEL = 1 << 1,
154 FLASH_STATUS_SRWD = 1 << 7
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
165 static const int FLASH_PAGE_WRITE_SIZE = 32;
179 static void cmd_wrdi(
const flash_id_t);
180 static void cmd_wren(
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);
189 static void cmd_ce(
const flash_id_t);
194 spi_write_addr(
const flash_id_t
id,
const spi_transfer_flag_t flag,
const flash_addr_t addr)
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);
204 cmd_rdid(
const flash_id_t
id)
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);
211 result |= spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_CONT, 0, SPI_TRANSFER_BLOCKING);
213 result |= spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_DONE, 0, SPI_TRANSFER_BLOCKING);
221 cmd_rdsr(
const flash_id_t
id)
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);
232 static void cmd_wrsr(
const flash_id_t
id,
const uint32_t status)
__attribute__((unused));
236 cmd_wrsr(
const flash_id_t
id,
const uint32_t status)
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);
244 cmd_rdscur(
const flash_id_t
id)
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);
265 cmd_wren(
const flash_id_t
id)
267 while(!(cmd_rdsr(
id) & FLASH_STATUS_WEL)) {
268 spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_DONE, FLASH_CMD_WREN, SPI_TRANSFER_BLOCKING);
274 cmd_wrdi(
const flash_id_t
id)
276 spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_DONE, FLASH_CMD_WRDI, SPI_TRANSFER_BLOCKING);
281 cmd_pp(
const flash_id_t
id,
const flash_addr_t addr,
const uint8_t *data,
const uint32_t size)
289 spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_CONT, FLASH_CMD_PP, SPI_TRANSFER_BLOCKING);
291 spi_write_addr(
id, SPI_TRANSFER_CONT, addr);
293 for(i = 0; i < size - 1; ++i) {
294 spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_CONT, *(data++), SPI_TRANSFER_BLOCKING);
296 spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_DONE, *data, SPI_TRANSFER_BLOCKING);
309 cmd_ppi(
const flash_id_t
id,
const flash_addr_t addr,
const uint8_t *data,
const uint32_t size)
317 spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_CONT, FLASH_CMD_PP, SPI_TRANSFER_BLOCKING);
319 spi_write_addr(
id, SPI_TRANSFER_CONT, addr);
321 for(i = 0; i < size - 1; ++i) {
322 spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_CONT, ~(*(data++)), SPI_TRANSFER_BLOCKING);
324 spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_DONE, ~(*data), SPI_TRANSFER_BLOCKING);
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));
336 cmd_cp(
const flash_id_t
id,
const flash_addr_t addr,
const uint8_t *data, uint32_t size)
342 if(cmd_rdscur(
id) & FLASH_SECURITY_CP) {
343 DEBUG(
"Flash already in continous programming mode.\n");
347 spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_CONT, FLASH_CMD_CP, SPI_TRANSFER_BLOCKING);
349 spi_write_addr(
id, SPI_TRANSFER_CONT, addr);
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);
357 if(!(cmd_rdscur(
id) & FLASH_SECURITY_CP)) {
358 DEBUG(
"Flash unexcpectedly left continous programming mode.\n");
362 spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_CONT, FLASH_CMD_CP, SPI_TRANSFER_BLOCKING);
365 spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_CONT, *(data++), SPI_TRANSFER_BLOCKING);
367 spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_DONE, *(data++), SPI_TRANSFER_BLOCKING);
369 spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_DONE, 0xff, SPI_TRANSFER_BLOCKING);
379 cmd_se(
const flash_id_t
id,
const uint32_t sector)
381 uint32_t addr = sector * FLASH_SECTOR_SIZE;
383 spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_CONT, FLASH_CMD_SE, SPI_TRANSFER_BLOCKING);
384 spi_write_addr(
id, SPI_TRANSFER_DONE, addr);
389 cmd_ce(
const flash_id_t
id)
391 spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_DONE, FLASH_CMD_CE, SPI_TRANSFER_BLOCKING);
396 cmd_dp(
const flash_id_t
id)
398 spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_DONE, FLASH_CMD_DP, SPI_TRANSFER_BLOCKING);
403 cmd_rdp(
const flash_id_t
id)
405 spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_DONE, FLASH_CMD_RDP, SPI_TRANSFER_BLOCKING);
410 cmd_read(
const flash_id_t
id,
const flash_addr_t addr, uint8_t *dest,
const uint32_t size)
414 spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_CONT, FLASH_CMD_READ, SPI_TRANSFER_BLOCKING);
416 spi_write_addr(
id, SPI_TRANSFER_CONT, addr);
418 for(i = 0; i < size - 1; ++i) {
419 *(dest++) = spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_CONT, 0, SPI_TRANSFER_BLOCKING);
421 *dest = spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_DONE, 0, SPI_TRANSFER_BLOCKING);
426 cmd_readi(
const flash_id_t
id,
const flash_addr_t addr, uint8_t *dest,
const uint32_t size)
430 spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_CONT, FLASH_CMD_READ, SPI_TRANSFER_BLOCKING);
432 spi_write_addr(
id, SPI_TRANSFER_CONT, addr);
434 for(i = 0; i < size - 1; ++i) {
435 *(dest++) = ~spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_CONT, 0, SPI_TRANSFER_BLOCKING);
437 *dest = ~spi_transfer(FLASH_CTAS,
id, SPI_TRANSFER_DONE, 0, SPI_TRANSFER_BLOCKING);
442 flash_busy_wait(
const flash_id_t
id)
444 while(cmd_rdsr(
id) & FLASH_STATUS_WIP) {
452 flash_write_prepare(
const flash_id_t
id)
467 SIM->SCGC5 |= SIM_SCGC5_PORTD_MASK;
473 for(i = 0; i < 200; ++i) {
477 for(i = FLASH_ID0; i <= FLASH_ID0; ++i) {
478 status = cmd_rdsr(i);
480 DEBUG(
"Error: Status of flash 0 is non-zero (0x%02x).\n", status);
481 return E_FLASH_INVALID_STATUS;
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;
495 flash_erase_chip(
const flash_id_t
id,
const flash_flags_t flags)
497 DEBUG(
"Starting chip erase...");
499 if((flags & FLASH_WAIT) == 0) {
500 if(cmd_rdsr(
id) & FLASH_STATUS_WIP) {
505 flash_write_prepare(
id);
509 if(flags & FLASH_FINISH) {
524 flash_erase_sector(
const flash_id_t
id,
const uint32_t sector,
const flash_flags_t flags)
526 if((flags & FLASH_WAIT) == 0) {
527 if(cmd_rdsr(
id) & FLASH_STATUS_WIP) {
532 DEBUG(
"Starting sector erase...");
534 flash_write_prepare(
id);
538 if(flags & FLASH_FINISH) {
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)
556 if(scheduled_write.active) {
557 DEBUG(
"We already have a scheduled write.\n");
558 return E_FLASH_QUEUE_FULL;
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;
576 flash_write_process(
const flash_flags_t flags)
580 if(scheduled_write.active == 0) {
584 if(flags & FLASH_WAIT) {
585 if(cmd_rdsr(scheduled_write.id) & FLASH_STATUS_WIP) {
590 flash_write_prepare(scheduled_write.id);
593 if(FLASH_PAGE_WRITE_SIZE >= FLASH_PAGE_SIZE) {
594 DEBUG(
"Sanity-check failed! We are trying to write too large chunks!\n");
596 count = FLASH_PAGE_WRITE_SIZE - (scheduled_write.addr % FLASH_PAGE_WRITE_SIZE);
597 if(scheduled_write.size < count) {
598 count = scheduled_write.size;
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;
606 scheduled_write.size -= count;
607 scheduled_write.addr += count;
608 scheduled_write.data += count;
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;
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;
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)
636 DEBUG(
"Starting flash write operation...");
638 if((flags & FLASH_WAIT) == 0) {
639 if(cmd_rdsr(
id) & FLASH_STATUS_WIP) {
648 count = FLASH_PAGE_SIZE - (addr % FLASH_PAGE_SIZE);
650 flash_write_prepare(
id);
651 if(cmd_pp(
id, addr + offset, data + offset, count)) {
653 return E_FLASH_WRITE_FAILED;
659 while(offset < size) {
660 count = size - offset;
661 if(count > FLASH_PAGE_SIZE) {
662 count = FLASH_PAGE_SIZE;
665 flash_write_prepare(
id);
666 if(cmd_pp(
id, addr + offset, data + offset, count)) {
668 return E_FLASH_WRITE_FAILED;
674 if(flags & FLASH_FINISH) {
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)
690 DEBUG(
"Starting flash write operation...");
692 if((flags & FLASH_WAIT) == 0) {
693 if(cmd_rdsr(
id) & FLASH_STATUS_WIP) {
702 count = FLASH_PAGE_SIZE - (addr % FLASH_PAGE_SIZE);
704 flash_write_prepare(
id);
705 if(cmd_ppi(
id, addr + offset, data + offset, count)) {
707 return E_FLASH_WRITE_FAILED;
713 while(offset < size) {
714 count = size - offset;
715 if(count > FLASH_PAGE_SIZE) {
716 count = FLASH_PAGE_SIZE;
719 flash_write_prepare(
id);
720 if(cmd_ppi(
id, addr + offset, data + offset, count)) {
722 return E_FLASH_WRITE_FAILED;
728 if(flags & FLASH_FINISH) {
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)
741 if(flags & FLASH_WAIT) {
744 if(cmd_rdsr(
id) & FLASH_STATUS_WIP) {
753 DEBUG(
"Starting flash read operation...");
754 cmd_read(
id, addr, dest, size);
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)
764 if(flags & FLASH_WAIT) {
767 if(cmd_rdsr(
id) & FLASH_STATUS_WIP) {
776 DEBUG(
"Starting flash read operation...");
777 cmd_readi(
id, addr, dest, size);
785 flash_status(
const flash_id_t
id)
787 if(cmd_rdsr(
id) & FLASH_STATUS_WIP) {
789 }
else if(scheduled_write.active) {
798 flash_sleep(
const flash_id_t
id,
const flash_flags_t flags)
806 flash_wakeup(
const flash_id_t
id,
const flash_flags_t flags)
814 flash_dump(
const flash_id_t
id,
void (*dump)(
const uint8_t))
816 flash_addr_t offset = 0;
817 uint8_t buf[FLASH_PAGE_SIZE];
819 while(offset < FLASH_SIZE) {
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;
829 for(i = 0; i <
sizeof(buf); i++) {
835 offset +=
sizeof(buf);
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.
#define SIM
Peripheral SIM base pointer.
#define SPI0
Peripheral SPI0 base pointer.
void udelay(uint16_t us)
Microsecond busy wait.
K60 hardware register header wrapper.
void flash_write(unsigned short *ptr, unsigned short word)
Write a 16-bit word to flash ROM.
#define PORTD
Peripheral PORTD base pointer.
void spi_init(void)
Initialize the SPI bus.