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);
}
Example #3
0
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);
}
Example #4
0
// 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);
			}
		}
    }
}