void NANDController::runCommand(int bank) { switch(getRegister(BSP_CMD(bank))) { // write operations case FC_COL_ROW_IN_PROG: //column address - row address - [DRAM or SRAM -> flash] - program command - wait - check result if(getRegister(BSP_DMA_ADDR(bank)) != 0) { dma_done[bank] = false; NextStateOfBanks[bank] = BS_WRITE_DMA; } else { NextStateOfBanks[bank] = BS_WRITE_CMD_1; } break; // read operations case FC_COL_ROW_READ_OUT: //column address - row address - read command - wait - [flash -> DRAM or SRAM] NextStateOfBanks[bank] = BS_READ_CMD_1; break; // copyback operations case FC_COPYBACK: //see descriptions below NextStateOfBanks[bank] = BS_CB_CMD_1; break; // erase case FC_ERASE: //row address - erase command - wait - check result NextStateOfBanks[bank] = BS_ERASE_CMD_1; break; // unused case FC_COL_ROW_IN: //column address - row address - [DRAM or SRAM -> flash] case FC_IN: //[DRAM or SRAM -> flash] case FC_IN_PROG: //[DRAM or SRAM -> flash] - program command - wait - check result case FC_PROG: //program command - wait - check result case FC_COL_ROW_READ: //column address - row address - read command - wait case FC_OUT: //[flash -> DRAM or SRAM] case FC_COL_OUT: //column address change - [flash -> DRAM or SRAM] case FC_MODIFY_COPYBACK: case FC_WAIT: //wait (used after FC_GENERIC when the command involves flash busy signal) case FC_GENERIC: //generic command (FCP_COL = command code) case FC_GENERIC_ADDR: //generic address (FCP_ROW_L and FCP_ROW_H = address, FCP_DMA_CNT = cycle count) case FC_READ_ID: //read_ID command - [flash -> SRAM] (FCP_OPTION = 0, FCP_DMA_ADDR = SRAM address, FCP_DMA_CNT = 16, FCP_COL = 0) printf( "Unused Command 0x%X\n", curFCPCommand.cmd); break; default: printf( "Invalid Command 0x%X\n", curFCPCommand.cmd); break; } }
inline void NANDController::issueCommandToBank(int bank) { setRegister(BSP_CMD(bank), curFCPCommand.cmd); setRegister(BSP_OPTION(bank), curFCPCommand.option); setRegister(BSP_DMA_ADDR(bank), curFCPCommand.dma_addr); setRegister(BSP_DMA_CNT(bank), curFCPCommand.dma_cnt); setRegister(BSP_COL(bank), curFCPCommand.col); setRegister(BSP_ROW_L(bank), curFCPCommand.row[curFCPCommand.bank][0]); setRegister(BSP_ROW_H(bank), curFCPCommand.row[curFCPCommand.bank][1]); setRegister(BSP_DST_COL(bank), curFCPCommand.dst_col); setRegister(BSP_DST_ROW_L(bank), curFCPCommand.dst_row[0]); setRegister(BSP_DST_ROW_H(bank), curFCPCommand.dst_row[1]); setRegister(BSP_CMD_ID(bank), curFCPCommand.cmd_id); }
void ftl_isr(void) { // interrupt service routine for flash interrupts UINT32 bank; UINT32 bsp_intr_flag; for (bank = 0; bank < NUM_BANKS; bank++) { while (BSP_FSM(bank) != BANK_IDLE); bsp_intr_flag = BSP_INTR(bank); if (bsp_intr_flag == 0) { continue; } UINT32 fc = GETREG(BSP_CMD(bank)); CLR_BSP_INTR(bank, bsp_intr_flag); if (bsp_intr_flag & FIRQ_DATA_CORRUPT) { g_read_fail_count++; } if (bsp_intr_flag & (FIRQ_BADBLK_H | FIRQ_BADBLK_L)) { if (fc == FC_COL_ROW_IN_PROG || fc == FC_IN_PROG || fc == FC_PROG) { g_program_fail_count++; } else { ASSERT(fc == FC_ERASE); g_erase_fail_count++; } } } // clear the flash interrupt flag at the interrupt controller SETREG(APB_INT_STS, INTR_FLASH); }
// BSP interrupt service routine void ftl_isr(void) { UINT32 bank; UINT32 bsp_intr_flag; uart_print("BSP interrupt occured..."); // interrupt pending clear (ICU) SETREG(APB_INT_STS, INTR_FLASH); for (bank = 0; bank < NUM_BANKS; bank++) { while (BSP_FSM(bank) != BANK_IDLE); // get interrupt flag from BSP bsp_intr_flag = BSP_INTR(bank); if (bsp_intr_flag == 0) { continue; } UINT32 fc = GETREG(BSP_CMD(bank)); // BSP clear CLR_BSP_INTR(bank, bsp_intr_flag); // interrupt handling if (bsp_intr_flag & FIRQ_DATA_CORRUPT) { uart_printf("BSP interrupt at bank: 0x%x", bank); uart_print("FIRQ_DATA_CORRUPT occured..."); } if (bsp_intr_flag & (FIRQ_BADBLK_H | FIRQ_BADBLK_L)) { uart_printf("BSP interrupt at bank: 0x%x", bank); if (fc == FC_COL_ROW_IN_PROG || fc == FC_IN_PROG || fc == FC_PROG) { uart_print("find runtime bad block when block program..."); } else { uart_printf("find runtime bad block when block erase...vblock #: %d", GETREG(BSP_ROW_H(bank)) / PAGES_PER_BLK); ASSERT(fc == FC_ERASE); } } } }