X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fcpu%2Fcortex-m3%2Fdrv%2Fmt29f_sam3.c;h=6a5087ae5217cb0b15fdaeecc7358d7912c3b4e5;hb=7612c956f3f2bba9b2ba01b8731297fd9c86dd21;hp=bd28a40547e2cfde2e9081037c66f8c89cadc607;hpb=ecbc38a94d767a547fb44ee30faef2bccc20c775;p=bertos.git diff --git a/bertos/cpu/cortex-m3/drv/mt29f_sam3.c b/bertos/cpu/cortex-m3/drv/mt29f_sam3.c index bd28a405..6a5087ae 100644 --- a/bertos/cpu/cortex-m3/drv/mt29f_sam3.c +++ b/bertos/cpu/cortex-m3/drv/mt29f_sam3.c @@ -56,6 +56,8 @@ #include /* memcpy() */ +// Timeout for read/write transfers in ms +#define MT29F_XFER_TMOUT 1000 // NAND flash status codes #define MT29F_STATUS_READY BV(6) @@ -82,13 +84,13 @@ struct Mt29fHardware { - int boh; + uint8_t status; }; /* - * Translate flash memory offset in the five address cycles format - * needed by NAND. + * Translate flash page index plus a byte offset + * in the five address cycles format needed by NAND. * * Cycles in x8 mode as the MT29F2G08AAD * CA = column addr, PA = page addr, BA = block addr @@ -101,15 +103,17 @@ struct Mt29fHardware * Fourth BA15 BA14 BA13 BA12 BA11 BA10 BA9 BA8 * Fifth LOW LOW LOW LOW LOW LOW LOW BA16 */ -static void mt29f_getAddrCycles(size_t offset, uint32_t *cycle0, uint32_t *cycle1234) +static void mt29f_getAddrCycles(block_idx_t page, size_t offset, uint32_t *cycle0, uint32_t *cycle1234) { + uint32_t addr = (page * MT29F_PAGE_SIZE) + offset; + /* * offset nibbles 77776666 55554444 33332222 11110000 * cycle1234 -------7 66665555 ----4444 33332222 * cycle0 11110000 */ - *cycle0 = offset & 0xFF; - *cycle1234 = ((offset >> 8) & 0x00000fff) | ((offset >> 4) & 0x01ff0000); + *cycle0 = addr & 0xff; + *cycle1234 = ((addr >> 8) & 0x00000fff) | ((addr >> 4) & 0x01ff0000); } @@ -123,11 +127,30 @@ INLINE bool mt29f_isCmdDone(void) return SMC_SR & SMC_SR_CMDDONE; } -INLINE uint8_t mt29f_isReadyBusy(void) +INLINE bool mt29f_isReadyBusy(void) { return SMC_SR & SMC_SR_RB_EDGE0; } +/* + * Wait for transfer to complete until timeout. + * If transfer completes return true, false in case of timeout. + */ +INLINE bool mt29f_waitTransferComplete(void) +{ + time_t start = timer_clock(); + + while (!(SMC_SR & SMC_SR_XFRDONE)) + { + cpu_relax(); + if (timer_clock() - start > MT29F_XFER_TMOUT) + return false; + } + + kprintf("xfer ok!!\n"); + return true; +} + /* * Send command to NAND and wait for completion. @@ -160,34 +183,38 @@ static bool mt29f_isOperationComplete(void) } -#if 0 //reset +static void mt29f_reset(void) +{ mt29f_sendCommand( - NFC_CMD_NFCCMD | MT29F_CSID | NFC_CMD_ACYCLE_NONE | - MT29F_CMD_RESET << 2, - 0, /* Dummy address cylce 1,2,3,4.*/ - 0 /* Dummy address cylce 0.*/ -#endif + NFC_CMD_NFCCMD | MT29F_CSID | NFC_CMD_ACYCLE_NONE | + MT29F_CMD_RESET << 2, + 0, 0); + + while (!mt29f_isReadyBusy()); +} + /** - * Erase block at given offset. + * Erase the whole block containing given page. */ -int mt29f_blockErase(Mt29f *fls, size_t blk_offset) +int mt29f_blockErase(Mt29f *fls, block_idx_t page) { uint32_t cycle0; uint32_t cycle1234; - mt29f_getAddrCycles(blk_offset, &cycle0, &cycle1234); + mt29f_getAddrCycles(page, 0, &cycle0, &cycle1234); mt29f_sendCommand( NFC_CMD_NFCCMD | MT29F_CSID | NFC_CMD_ACYCLE_THREE | NFC_CMD_VCMD2 | (MT29F_CMD_ERASE_2 << 10) | (MT29F_CMD_ERASE_1 << 2), - cycle1234, 0); + 0, cycle1234); while (!mt29f_isReadyBusy()); if (!mt29f_isOperationComplete()) { LOG_ERR("mt29f: error erasing block\n"); + fls->hw->status |= MT29F_ERR_ERASE; return -1; } @@ -197,23 +224,94 @@ int mt29f_blockErase(Mt29f *fls, size_t blk_offset) static size_t mt29f_readDirect(struct KBlock *blk, block_idx_t idx, void *buf, size_t offset, size_t size) { + Mt29f *fls = FLASH_CAST(blk); + uint32_t cycle0; + uint32_t cycle1234; + + ASSERT(offset == 0); + ASSERT(size == blk->blk_size); + + kprintf("read direct\n"); + + mt29f_getAddrCycles(idx, 0, &cycle0, &cycle1234); + + mt29f_sendCommand( + NFC_CMD_NFCCMD | NFC_CMD_NFCEN | MT29F_CSID | NFC_CMD_ACYCLE_FIVE | NFC_CMD_VCMD2 | + (MT29F_CMD_READ_2 << 10) | (MT29F_CMD_READ_1 << 2), + cycle0, cycle1234); + + while (!mt29f_isReadyBusy()); + if (!mt29f_waitTransferComplete()) + { + LOG_ERR("mt29f: read timeout\n"); + fls->hw->status |= MT29F_ERR_RD_TMOUT; + return 0; + } + + if (!kblock_buffered(blk) && (buf != (void *)NFC_SRAM_BASE_ADDR)) + memcpy(buf, (void *)NFC_SRAM_BASE_ADDR, size); + + return size; } static size_t mt29f_writeDirect(struct KBlock *blk, block_idx_t idx, const void *_buf, size_t offset, size_t size) { + Mt29f *fls = FLASH_CAST(blk); + uint32_t cycle0; + uint32_t cycle1234; + + ASSERT(offset == 0); + ASSERT(size == blk->blk_size); + + kprintf("write direct\n"); + + if (!kblock_buffered(blk) && (_buf != (void *)NFC_SRAM_BASE_ADDR)) + memcpy((void *)NFC_SRAM_BASE_ADDR, _buf, size); + + mt29f_getAddrCycles(idx, 0, &cycle0, &cycle1234); + + mt29f_sendCommand( + NFC_CMD_NFCCMD | NFC_CMD_NFCWR | NFC_CMD_NFCEN | MT29F_CSID | NFC_CMD_ACYCLE_FIVE | + MT29F_CMD_WRITE_1 << 2, + cycle0, cycle1234); + + if (!mt29f_waitTransferComplete()) + { + LOG_ERR("mt29f: write timeout\n"); + fls->hw->status |= MT29F_ERR_WR_TMOUT; + return 0; + } + + mt29f_sendCommand( + NFC_CMD_NFCCMD | MT29F_CSID | NFC_CMD_ACYCLE_NONE | + MT29F_CMD_WRITE_2 << 2, + 0, 0); + + while (!mt29f_isReadyBusy()); + + if (!mt29f_isOperationComplete()) + { + LOG_ERR("mt29f: error writing page\n"); + fls->hw->status |= MT29F_ERR_WRITE; + return 0; + } + + return size; } static int mt29f_error(struct KBlock *blk) { Mt29f *fls = FLASH_CAST(blk); + return fls->hw->status; } static void mt29f_clearerror(struct KBlock *blk) { Mt29f *fls = FLASH_CAST(blk); + fls->hw->status = 0; } @@ -304,23 +402,36 @@ static void common_init(Mt29f *fls) SMC_MODE0 = SMC_MODE_READ_MODE | SMC_MODE_WRITE_MODE; + + SMC_CFG = SMC_CFG_PAGESIZE_PS2048_64 + | SMC_CFG_EDGECTRL + | SMC_CFG_DTOMUL_X1048576 + | SMC_CFG_DTOCYC(0xF); + + // Disable SMC interrupts, reset and enable NFC controller + SMC_IDR = ~0; + SMC_CTRL = 0; + SMC_CTRL = SMC_CTRL_NFCEN; + + mt29f_reset(); } -void mt29f_hw_init(Mt29f *fls) +void mt29f_init(Mt29f *fls) { common_init(fls); fls->blk.priv.vt = &mt29f_buffered_vt; - fls->blk.priv.flags |= KB_BUFFERED | KB_PARTIAL_WRITE; - fls->blk.priv.buf = (void *)NFC_CMD_BASE_ADDR; + fls->blk.priv.flags |= KB_BUFFERED; + fls->blk.priv.buf = (void *)NFC_SRAM_BASE_ADDR; // Load the first block in the cache - void *start = 0x0; - memcpy(fls->blk.priv.buf, start, fls->blk.blk_size); + //mt29f_readDirect(&fls->blk, 0, (void *)NFC_SRAM_BASE_ADDR, 0, MT29F_PAGE_SIZE); + //debug + memset((void *)NFC_SRAM_BASE_ADDR, 0xbb, MT29F_PAGE_SIZE); } -void mt29f_hw_initUnbuffered(Mt29f *fls) +void mt29f_initUnbuffered(Mt29f *fls) { common_init(fls); fls->blk.priv.vt = &mt29f_unbuffered_vt;