static BOOL32 check_format_mark(void) { // This function reads a flash page from (bank #0, block #0) in order to check whether the SSD is formatted or not. #ifdef __GNUC__ extern UINT32 size_of_firmware_image; UINT32 firmware_image_pages = (((UINT32) (&size_of_firmware_image)) + BYTES_PER_FW_PAGE - 1) / BYTES_PER_FW_PAGE; #else extern UINT32 Image$$ER_CODE$$RO$$Length; extern UINT32 Image$$ER_RW$$RW$$Length; UINT32 firmware_image_bytes = ((UINT32) &Image$$ER_CODE$$RO$$Length) + ((UINT32) &Image$$ER_RW$$RW$$Length); UINT32 firmware_image_pages = (firmware_image_bytes + BYTES_PER_FW_PAGE - 1) / BYTES_PER_FW_PAGE; #endif UINT32 format_mark_page_offset = FW_PAGE_OFFSET + firmware_image_pages; UINT32 temp; flash_clear_irq(); // clear any flash interrupt flags that might have been set SETREG(FCP_CMD, FC_COL_ROW_READ_OUT); SETREG(FCP_BANK, REAL_BANK(0)); SETREG(FCP_OPTION, FO_E); SETREG(FCP_DMA_ADDR, FTL_BUF_ADDR); // flash -> DRAM SETREG(FCP_DMA_CNT, BYTES_PER_SECTOR); SETREG(FCP_COL, 0); SETREG(FCP_ROW_L(0), format_mark_page_offset); SETREG(FCP_ROW_H(0), format_mark_page_offset); // At this point, we do not have to check Waiting Room status before issuing a command, // because scan list loading has been completed just before this function is called. SETREG(FCP_ISSUE, NULL); // wait for the FC_COL_ROW_READ_OUT command to be accepted by bank #0 while ((GETREG(WR_STAT) & 0x00000001) != 0); // wait until bank #0 finishes the read operation while (BSP_FSM(0) != BANK_IDLE); // Now that the read operation is complete, we can check interrupt flags. temp = BSP_INTR(0) & FIRQ_ALL_FF; // clear interrupt flags CLR_BSP_INTR(0, 0xFF); if (temp != 0) { return FALSE; // the page contains all-0xFF (the format mark does not exist.) } else { return TRUE; // the page contains something other than 0xFF (it must be the format mark) } }
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); } } } }
static void write_format_mark(void) { // This function writes a format mark to a page at (bank #0, block #0). #ifdef __GNUC__ extern UINT32 size_of_firmware_image; UINT32 firmware_image_pages = (((UINT32) (&size_of_firmware_image)) + BYTES_PER_FW_PAGE - 1) / BYTES_PER_FW_PAGE; #else extern UINT32 Image$$ER_CODE$$RO$$Length; extern UINT32 Image$$ER_RW$$RW$$Length; UINT32 firmware_image_bytes = ((UINT32) &Image$$ER_CODE$$RO$$Length) + ((UINT32) &Image$$ER_RW$$RW$$Length); UINT32 firmware_image_pages = (firmware_image_bytes + BYTES_PER_FW_PAGE - 1) / BYTES_PER_FW_PAGE; #endif UINT32 format_mark_page_offset = FW_PAGE_OFFSET + firmware_image_pages; mem_set_dram(FTL_BUF_ADDR, 0, BYTES_PER_SECTOR); SETREG(FCP_CMD, FC_COL_ROW_IN_PROG); SETREG(FCP_BANK, REAL_BANK(0)); SETREG(FCP_OPTION, FO_E | FO_B_W_DRDY); SETREG(FCP_DMA_ADDR, FTL_BUF_ADDR); // DRAM -> flash SETREG(FCP_DMA_CNT, BYTES_PER_SECTOR); SETREG(FCP_COL, 0); SETREG(FCP_ROW_L(0), format_mark_page_offset); SETREG(FCP_ROW_H(0), format_mark_page_offset); // At this point, we do not have to check Waiting Room status before issuing a command, // because we have waited for all the banks to become idle before returning from format(). SETREG(FCP_ISSUE, NULL); // wait for the FC_COL_ROW_IN_PROG command to be accepted by bank #0 while ((GETREG(WR_STAT) & 0x00000001) != 0); // wait until bank #0 finishes the write operation while (BSP_FSM(0) != BANK_IDLE); }
static void build_bad_blk_list(void) { UINT32 bank, num_entries, result, vblk_offset; scan_list_t* scan_list = (scan_list_t*) TEMP_BUF_ADDR; mem_set_dram(BAD_BLK_BMP_ADDR, NULL, BAD_BLK_BMP_BYTES); disable_irq(); flash_clear_irq(); for (bank = 0; bank < NUM_BANKS; bank++) { SETREG(FCP_CMD, FC_COL_ROW_READ_OUT); SETREG(FCP_BANK, REAL_BANK(bank)); SETREG(FCP_OPTION, FO_E); SETREG(FCP_DMA_ADDR, (UINT32) scan_list); SETREG(FCP_DMA_CNT, SCAN_LIST_SIZE); SETREG(FCP_COL, 0); SETREG(FCP_ROW_L(bank), SCAN_LIST_PAGE_OFFSET); SETREG(FCP_ROW_H(bank), SCAN_LIST_PAGE_OFFSET); SETREG(FCP_ISSUE, NULL); while ((GETREG(WR_STAT) & 0x00000001) != 0); while (BSP_FSM(bank) != BANK_IDLE); num_entries = NULL; result = OK; if (BSP_INTR(bank) & FIRQ_DATA_CORRUPT) { result = FAIL; } else { UINT32 i; num_entries = read_dram_16(&(scan_list->num_entries)); if (num_entries > SCAN_LIST_ITEMS) { result = FAIL; } else { for (i = 0; i < num_entries; i++) { UINT16 entry = read_dram_16(scan_list->list + i); UINT16 pblk_offset = entry & 0x7FFF; if (pblk_offset == 0 || pblk_offset >= PBLKS_PER_BANK) { #if OPTION_REDUCED_CAPACITY == FALSE result = FAIL; #endif } else { write_dram_16(scan_list->list + i, pblk_offset); } } } } if (result == FAIL) { num_entries = 0; // We cannot trust this scan list. Perhaps a software bug. } else { write_dram_16(&(scan_list->num_entries), 0); } g_bad_blk_count[bank] = 0; for (vblk_offset = 1; vblk_offset < VBLKS_PER_BANK; vblk_offset++) { BOOL32 bad = FALSE; #if OPTION_2_PLANE { UINT32 pblk_offset; pblk_offset = vblk_offset * NUM_PLANES; // fix bug@jasmine v.1.1.0 if (mem_search_equ_dram(scan_list, sizeof(UINT16), num_entries + 1, pblk_offset) < num_entries + 1) { bad = TRUE; } pblk_offset = vblk_offset * NUM_PLANES + 1; // fix bug@jasmine v.1.1.0 if (mem_search_equ_dram(scan_list, sizeof(UINT16), num_entries + 1, pblk_offset) < num_entries + 1) { bad = TRUE; } } #else { // fix bug@jasmine v.1.1.0 if (mem_search_equ_dram(scan_list, sizeof(UINT16), num_entries + 1, vblk_offset) < num_entries + 1) { bad = TRUE; } } #endif if (bad) { g_bad_blk_count[bank]++; set_bit_dram(BAD_BLK_BMP_ADDR + bank*(VBLKS_PER_BANK/8 + 1), vblk_offset); } } } }
void NANDController::outputLogicBankFSM(int bank) { uint32_t r_data = 0; uint32_t *index = &(curIdx[bank]); signal_t signals; uint8_t w_data_l; uint8_t w_data_h; //Default outputs tmp_flash_sout[bank] = 34; //CEn = disable tmp_flash_dout[bank] = 0; switch(getRegister(BSP_FSM(bank))) { case BS_IDLE: //do nothing. break; //////////////////////////////Read Status////////////////////////////// case BS_RS_CMD: signals.CLE = ENABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = DISABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = FCMD_READ_STATE; break; case BS_RS_DATA: r_data = flash_din_SSlave[bank]; printf( "Read data: 0x%x\n", r_data); break; //////////////////////////////Read////////////////////////////// case BS_READ_CMD_1: signals.CLE = ENABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = DISABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = FCMD_READ_1; break; case BS_READ_COL_1: //two column addresses are zero. case BS_READ_COL_2: signals.CLE = DISABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = ENABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = 0; //fix break; case BS_READ_ROW_1: signals.CLE = DISABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = ENABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = getRegister(BSP_ROW_L(bank)); break; case BS_READ_ROW_2: signals.CLE = DISABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = ENABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = getRegister(BSP_ROW_H(bank)); break; case BS_READ_CMD_2: signals.CLE = ENABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = DISABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = FCMD_READ_2; break; case BS_READ_WAIT: signals.CLE = DISABLE; signals.CEn = ENABLEn; signals.WEn = DISABLEn; signals.ALE = DISABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); break; case BS_READ_DATA: //1024 iteration: using curReadIdx signals.CLE = DISABLE; signals.CEn = ENABLEn; signals.WEn = DISABLEn; signals.ALE = DISABLE; signals.REn = ENABLEn; signals.WPn = DISABLEn; //fix if(flash_inputSignal_active[bank]) { //read data r_data = flash_din_SSlave[bank]; //16bit i/o buffers[bank][(*index)] = (uint8_t)(r_data & 0x00FF); buffers[bank][(*index)+1] = (uint8_t)((r_data & 0xFF00) >> 8); //if(p_enableDbgMsg) printf( "[Bank#%d] Read data: 0x%X, index: %d\n", bank, r_data, *index); (*index) += 2; } else { flash_inputSignal_active[bank] = true; } tmp_flash_sout[bank] = encodingSignals(signals); //printf( "[Drive to bank#%d] sout(%d)", bank, encoded_signal); break; case BS_READ_DMA: if(runDMA(bank, 1)) { dma_done[bank] = true; } break; case BS_READ_INC_BM: bm_read_inc = 1; break; //////////////////////////////Write////////////////////////////// case BS_WRITE_DMA: if(runDMA(bank, 0)) { dma_done[bank] = true; } break; case BS_WRITE_CMD_1: signals.CLE = ENABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = DISABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = FCMD_WRITE_1; break; case BS_WRITE_COL_1: case BS_WRITE_COL_2: signals.CLE = DISABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = ENABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = getRegister(BSP_COL(bank)); //fix break; case BS_WRITE_ROW_1: signals.CLE = DISABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = ENABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = getRegister(BSP_ROW_L(bank)); break; case BS_WRITE_ROW_2: signals.CLE = DISABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = ENABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = getRegister(BSP_ROW_H(bank)); break; case BS_WRITE_DATA: //1024 iteration: using curWriteIdx signals.CLE = DISABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = DISABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix w_data_l = buffers[bank][(*index)]; //need implement w_data_h = (buffers[bank][(*index)+1]); //if(p_enableDbgMsg) printf( "[Bank#%d] Write data: 0x%X, index: %d\n", bank, ((w_data_h << 8)|w_data_l), *index); (*index)+=2; tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = ((w_data_h << 8)|w_data_l); break; case BS_WRITE_CMD_2: signals.CLE = ENABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = DISABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = FCMD_WRITE_2; break; case BS_WRITE_WAIT: signals.CLE = DISABLE; signals.CEn = ENABLEn; signals.WEn = DISABLEn; signals.ALE = DISABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); break; case BS_WRITE_INC_BM: bm_write_inc = 1; break; //////////////////////////////Copy-Back////////////////////////////// case BS_CB_CMD_1: signals.CLE = ENABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = DISABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = FCMD_CP_1; break; case BS_CB_COL_1: case BS_CB_COL_2: signals.CLE = DISABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = ENABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = getRegister(BSP_COL(bank)); break; case BS_CB_ROW_1: signals.CLE = DISABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = ENABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = getRegister(BSP_ROW_L(bank)); break; case BS_CB_ROW_2: signals.CLE = DISABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = ENABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = getRegister(BSP_ROW_H(bank)); break; case BS_CB_CMD_2: signals.CLE = ENABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = DISABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = FCMD_CP_2; break; case BS_CB_WAIT_1: signals.CLE = DISABLE; signals.CEn = ENABLEn; signals.WEn = DISABLEn; signals.ALE = DISABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); break; case BS_CB_CMD_3: signals.CLE = ENABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = DISABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = FCMD_CP_3; break; case BS_CB_COL_3: case BS_CB_COL_4: signals.CLE = DISABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = ENABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = getRegister(BSP_DST_COL(bank)); break; case BS_CB_ROW_3: signals.CLE = DISABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = ENABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = getRegister(BSP_DST_ROW_L(bank)); break; case BS_CB_ROW_4: signals.CLE = DISABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = ENABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = getRegister(BSP_DST_ROW_H(bank)); break; case BS_CB_CMD_4: signals.CLE = ENABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = DISABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = FCMD_CP_4; break; case BS_CB_WAIT_2: signals.CLE = DISABLE; signals.CEn = ENABLEn; signals.WEn = DISABLEn; signals.ALE = DISABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); break; //////////////////////////////Erase////////////////////////////// case BS_ERASE_CMD_1: signals.CLE = ENABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = DISABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = FCMD_ERASE_1; break; case BS_ERASE_ROW_1: signals.CLE = DISABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = ENABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = getRegister(BSP_ROW_L(bank)); break; case BS_ERASE_ROW_2: signals.CLE = DISABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = ENABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = getRegister(BSP_ROW_H(bank)); break; case BS_ERASE_CMD_2: signals.CLE = ENABLE; signals.CEn = ENABLEn; signals.WEn = ENABLEn; signals.ALE = DISABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); tmp_flash_dout[bank] = FCMD_ERASE_2; break; case BS_ERASE_WAIT: signals.CLE = DISABLE; signals.CEn = ENABLEn; signals.WEn = DISABLEn; signals.ALE = DISABLE; signals.REn = DISABLEn; signals.WPn = DISABLEn; //fix tmp_flash_sout[bank] = encodingSignals(signals); break; //////////////////////////////Error////////////////////////////// default: ; }
void NANDController::communicate() { /************************************************************************************** * Read Signals **************************************************************************************/ for(int i=0; i<NUM_BANKS; i++) { RBn[i] = flash_RBn_SSlave[i]; } /* When all banks are idle, set MON_CHABANKIDLE. */ bool allIdle = true; for(int i=0; ( i<NUM_BANKS ) && allIdle; i++) { allIdle = getRegister(BSP_FSM(i)) == BS_IDLE; } if(allIdle && getRegister(WR_STAT) == WR_STAT_IDLE) { setRegister(MON_CHABANKIDLE, 0); } /************************************************************************************** * If Issue flag is on, Execute command **************************************************************************************/ if(getRegister(FCP_ISSUE) == ISSUE_ENABLE) { printf( "Command ISSUED\n"); if(getRegister(WR_STAT) == WR_STAT_BUSY) { printf( "Waiting Room is Busy, ignore this command\n"); } else { getCommandInfo(); //The Banks FSM is already running. if(getRegister(BSP_FSM(curFCPCommand.bank)) != BS_IDLE) { printf( "%d Bank is busy, put this command into WR\n", curFCPCommand.bank); //Active Wating Room. setRegister(WR_BANK, curFCPCommand.bank); setRegister(WR_STAT, WR_STAT_BUSY); } else { issueCommandToBank(curFCPCommand.bank); bIssued[curFCPCommand.bank] = true; } //set some banks are non-idle. setRegister(MON_CHABANKIDLE, 1); } //Clear ISSUE register setRegister(FCP_ISSUE, ISSUE_DISABLE); } /************************************************************************************** * The bank that has next command in WR will be IDLE state, Issue the command. **************************************************************************************/ int wrBank = getRegister(WR_BANK); if( getRegister(WR_STAT) == WR_STAT_BUSY && NextStateOfBanks[wrBank] == BS_IDLE) { printf( "%d Bank become IDLE, issue CMD to %d Bank from WR\n", wrBank, wrBank); issueCommandToBank(wrBank); bIssued[wrBank] = true; setRegister(WR_STAT, WR_STAT_IDLE); } /************************************************************************************** * Banks FSM **************************************************************************************/ for(int i=0; i<NUM_BANKS; i++) { if(bIssued[i]) { runCommand(i); bIssued[i] = false; } combinationalLogicBankFSM(i); } /************************************************************************************** * Send Drive **************************************************************************************/ // Send(drive) all the signals set in previous update() //ahb_m0_mpms->sendDrive(); // Send(drive) all the signals set in previous update() //ahb_m1_mpms->sendDrive(); // Send(drive) all the signals set in previous update() //ahb_s0_spss->sendDrive(); }
void NANDController::combinationalLogicBankFSM(int bank) { /***************************************************************************** * Get pointers that indicating specific bank. *****************************************************************************/ uint8_t *pStateFSMBanks = ((uint8_t*)m_regs)+BSP_FSM(bank); uint8_t *nextState = &(NextStateOfBanks[bank]); uint32_t *index = &(curIdx[bank]); /***************************************************************************** * Move to Next state *****************************************************************************/ *pStateFSMBanks = *nextState; /***************************************************************************** * Define Next state *****************************************************************************/ switch(*pStateFSMBanks) { case BS_IDLE: break; //////////////////////////////Read Status////////////////////////////// case BS_RS_CMD: printf( "[Bank#%d] State: BS_RS_CMD\n", bank); *nextState = (uint8_t)BS_RS_DATA; break; case BS_RS_DATA: printf( "[Bank#%d] State: BS_RS_DATA\n", bank); *nextState = (uint8_t)BS_IDLE; //finish break; //////////////////////////////Read////////////////////////////// case BS_READ_CMD_1: printf( "[Bank#%d] State: BS_READ_CMD_1\n", bank); *nextState = (uint8_t)BS_READ_COL_1; break; case BS_READ_COL_1: printf( "[Bank#%d] State: BS_READ_COL_1\n", bank); *nextState = (uint8_t)BS_READ_COL_2; break; case BS_READ_COL_2: printf( "[Bank#%d] State: BS_READ_COL_2\n", bank); *nextState = (uint8_t)BS_READ_ROW_1; break; case BS_READ_ROW_1: printf( "[Bank#%d] State: BS_READ_ROW_1\n", bank); *nextState = (uint8_t)BS_READ_ROW_2; break; case BS_READ_ROW_2: printf( "[Bank#%d] State: BS_READ_ROW_2\n", bank); *nextState = (uint8_t)BS_READ_CMD_2; break; case BS_READ_CMD_2: printf( "[Bank#%d] State: BS_READ_CMD_2\n", bank); *nextState = (uint8_t)BS_READ_WAIT; flash_inputSignal_active[bank] = false; printf( "[Bank#%d] Move to BS_READ_WAIT\n", bank); break; case BS_READ_WAIT: if(flash_inputSignal_active[bank]) { //printf( "[Bank#%d] BS_READ_WAIT Active \n", bank); if(RBn[bank] == READY) { printf( "[Bank#%d] READY! BS_READ_WAIT \n", bank); *nextState = *pStateFSMBanks = (uint8_t)BS_READ_DATA; *index = 0; flash_inputSignal_active[bank] = false; } } else { //printf( "[Bank#%d] BS_READ_WAIT No Active \n", bank); flash_inputSignal_active[bank] = true; } break; case BS_READ_DATA: //1024 iteration: using curReadIdx if(*index == 0) { printf( "[Bank#%d] State: BS_READ_DATA\n", bank); } if(*index >= BYTE_PER_PAGE-4) { if(getRegister(BSP_DMA_ADDR(bank)) != 0) { dma_done[bank] = false; *nextState = (uint8_t)BS_READ_DMA; //dma } else { *nextState = (uint8_t)BS_IDLE; //finish } } break; case BS_READ_DMA: if(dma_done[bank]) //Write read data into external memory. { dma_running_bank = DMA_IDLE; if(getRegister(BSP_OPTION(bank)) & FO_B_SATA_R) { printf( "[Bank#%d] Move to BS_READ_INC_BM\n", bank); *pStateFSMBanks = (uint8_t)BS_READ_INC_BM; *nextState = (uint8_t)BS_IDLE; //Move to state for BufferManasger } else { *nextState = *pStateFSMBanks = (uint8_t)BS_IDLE; //finish } } break; case BS_READ_INC_BM: *nextState = (uint8_t)BS_IDLE; break; //////////////////////////////Write////////////////////////////// case BS_WRITE_DMA: if(dma_done[bank]) { //Read data that will be wrote into nand flash from external memory. dma_running_bank = DMA_IDLE; printf( "[Bank#%d] Move to BS_WRITE_CMD_1\n", bank); *pStateFSMBanks = (uint8_t)BS_WRITE_CMD_1; *nextState = (uint8_t)BS_WRITE_COL_1; } break; case BS_WRITE_CMD_1: printf( "[Bank#%d] State: BS_WRITE_CMD_1\n", bank); *nextState = (uint8_t)BS_WRITE_COL_1; break; case BS_WRITE_COL_1: printf( "[Bank#%d] State: BS_WRITE_COL_1\n", bank); *nextState = (uint8_t)BS_WRITE_COL_2; break; case BS_WRITE_COL_2: printf( "[Bank#%d] State: BS_WRITE_COL_2\n", bank); *nextState = (uint8_t)BS_WRITE_ROW_1; break; case BS_WRITE_ROW_1: printf( "[Bank#%d] State: BS_WRITE_ROW_1\n", bank); *nextState = (uint8_t)BS_WRITE_ROW_2; break; case BS_WRITE_ROW_2: printf( "[Bank#%d] State: BS_WRITE_ROW_2\n", bank); *nextState = (uint8_t)BS_WRITE_DATA; *index = 0; break; case BS_WRITE_DATA: //1024 iteration: using curWriteIdx if(*index == 0) { printf( "[Bank#%d] State: BS_WRITE_DATA, writeIdx: %d\n", bank, *index); } if(*index >= BYTE_PER_PAGE-2) { *nextState = (uint8_t)BS_WRITE_CMD_2; } break; case BS_WRITE_CMD_2: printf( "[Bank#%d] State: BS_WRITE_CMD_2\n", bank); *nextState = (uint8_t)BS_WRITE_WAIT; flash_inputSignal_active[bank] = false; printf( "[Bank#%d] Move to BS_WRITE_WAIT\n", bank); break; case BS_WRITE_WAIT: if(flash_inputSignal_active[bank]) { if(RBn[bank] == READY) { if(getRegister(BSP_OPTION(bank)) & FO_B_SATA_W) { printf( "[Bank#%d] Move to BS_WRITE_INC_BM\n", bank); *pStateFSMBanks = (uint8_t)BS_WRITE_INC_BM; //Move to the state for Buffer manager *nextState = (uint8_t)BS_RS_CMD; } else { //*pStateFSMBanks = (uint8_t)BS_RS_CMD; //finish //*nextState = (uint8_t)BS_RS_DATA; *nextState = (uint8_t)BS_RS_CMD; } flash_inputSignal_active[bank] = false; } } else { flash_inputSignal_active[bank] = true; } break; case BS_WRITE_INC_BM: *nextState = (uint8_t)BS_RS_CMD; break; //////////////////////////////Copy-Back////////////////////////////// case BS_CB_CMD_1: printf( "[Bank#%d] State: BS_CB_CMD_1\n", bank); *nextState = (uint8_t)BS_CB_COL_1; break; case BS_CB_COL_1: printf( "[Bank#%d] State: BS_CB_COL_1\n", bank); *nextState = (uint8_t)BS_CB_COL_2; break; case BS_CB_COL_2: printf( "[Bank#%d] State: BS_CB_COL_2\n", bank); *nextState = (uint8_t)BS_CB_ROW_1; break; case BS_CB_ROW_1: printf( "[Bank#%d] State: BS_CB_ROW_1\n", bank); *nextState = (uint8_t)BS_CB_ROW_2; break; case BS_CB_ROW_2: printf( "[Bank#%d] State: BS_CB_ROW_2\n", bank); *nextState = (uint8_t)BS_CB_CMD_2; break; case BS_CB_CMD_2: printf( "[Bank#%d] State: BS_CB_CMD_2\n", bank); *nextState = (uint8_t)BS_CB_WAIT_1; flash_inputSignal_active[bank] = false; printf( "[Bank#%d] Move to BS_CB_WAIT_1\n", bank); break; case BS_CB_WAIT_1: if(flash_inputSignal_active[bank]) { if(RBn[bank] == READY) { *pStateFSMBanks = (uint8_t)BS_CB_CMD_3; *nextState = (uint8_t)BS_CB_COL_3; flash_inputSignal_active[bank] = false; } } else { flash_inputSignal_active[bank] = true; } break; case BS_CB_CMD_3: printf( "[Bank#%d] State: BS_CB_CMD_3\n", bank); *nextState = (uint8_t)BS_CB_COL_3; break; case BS_CB_COL_3: printf( "[Bank#%d] State: BS_CB_COL_3\n", bank); *nextState = (uint8_t)BS_CB_COL_4; break; case BS_CB_COL_4: printf( "[Bank#%d] State: BS_CB_COL_4\n", bank); *nextState = (uint8_t)BS_CB_ROW_3; break; case BS_CB_ROW_3: printf( "[Bank#%d] State: BS_CB_ROW_3\n", bank); *nextState = (uint8_t)BS_CB_ROW_4; break; case BS_CB_ROW_4: printf( "[Bank#%d] State: BS_CB_ROW_4\n", bank); *nextState = (uint8_t)BS_CB_CMD_4; break; case BS_CB_CMD_4: printf( "[Bank#%d] State: BS_CB_CMD_4\n", bank); *nextState = (uint8_t)BS_CB_WAIT_2; flash_inputSignal_active[bank] = false; printf( "[Bank#%d] Move to BS_CB_WAIT_2\n", bank); break; case BS_CB_WAIT_2: if(flash_inputSignal_active[bank]) { if(RBn[bank] == READY) { //*pStateFSMBanks = (uint8_t)BS_RS_CMD; //finish //*nextState = (uint8_t)BS_RS_DATA; *nextState = (uint8_t)BS_RS_CMD; flash_inputSignal_active[bank] = false; } } else { flash_inputSignal_active[bank] = true; } break; //////////////////////////////Erase////////////////////////////// case BS_ERASE_CMD_1: printf( "[Bank#%d] State: BS_ERASE_CMD_1\n", bank); *nextState = (uint8_t)BS_ERASE_ROW_1; break; case BS_ERASE_ROW_1: printf( "[Bank#%d] State: BS_ERASE_ROW_1\n", bank); *nextState = (uint8_t)BS_ERASE_ROW_2; break; case BS_ERASE_ROW_2: printf( "[Bank#%d] State: BS_ERASE_ROW_2\n", bank); *nextState = (uint8_t)BS_ERASE_CMD_2; break; case BS_ERASE_CMD_2: printf( "[Bank#%d] State: BS_ERASE_CMD_2\n", bank); *nextState = (uint8_t)BS_ERASE_WAIT; flash_inputSignal_active[bank] = false; printf( "[Bank#%d] Move to BS_ERASE_WAIT\n", bank); break; case BS_ERASE_WAIT: if(flash_inputSignal_active[bank]) { if(RBn[bank] == READY) { //*pStateFSMBanks = (uint8_t)BS_RS_CMD; //finish //*nextState = (uint8_t)BS_RS_DATA; *nextState = (uint8_t)BS_RS_CMD; flash_inputSignal_active[bank] = false; } } else { flash_inputSignal_active[bank] = true; } break; //////////////////////////////Error////////////////////////////// default: *nextState = (uint8_t)BS_IDLE; } }