⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nfc_base.c

📁 freescale atk source code
💻 C
字号:
/*****************************************************************************
** nfc_base.c
**
** Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
**
** This file contains copyrighted material. Use of this file is
** restricted by the provisions of a Freescale Software License
** Agreement, which has either been electronically accepted by
** you or has been expressly executed between the parties.
**
** Description: Explanation for the usage of this file.
**
** Revision History:
** -----------------
*****************************************************************************/
#include "nand_flash.h"
#include "flash_lib.h"
#include "protocol.h"
#include "nfc_base.h"

#if defined(MCU_MX51)
#include "mx51_nfc.h"
#elif defined(MCU_MX35)
#include "mx35_nfc.h"
#elif defined(MCU_MX37)
#include "mx37_nfc.h"
#elif defined(MCU_MX31) || defined(MCU_MX32)
#include "mx3_nfc.h"
#elif defined(MCU_MX27)
#include "mx27_nfc.h"
#endif

#define NAND_MAN_ID                 (nand->man_id)
#define NAND_DEV_ID                 (nand->dev_id)
#define NAND_NUM_OF_ROW_ADDR_CYCLES (nand->row_addr_cycle)
#define NAND_NUM_OF_BLOCKS          (nand->blk_count)
#define NAND_NUM_OF_PAGES           (nand->ppb)
#define NAND_IO_WIDTH               (nand->bus_width)
#define NAND_MAIN_BYTESIZE          (nand->page_size)
#define NAND_SPARE_BYTESIZE         (nand->oob_size)
#define NAND_BADBLOCK_MARKER_OFFSET (nand->bbm_offset)
#define NAND_BLK_SIZE 				(NAND_NUM_OF_PAGES  * NAND_MAIN_BYTESIZE)
#define NAND_SIZE				    (u64)(NAND_NUM_OF_BLOCKS * NAND_BLK_SIZE)
#define NAND_BBI_PAGE_OFFSET		(nand->bbi_page_offset)
#define NAND_SCAN_PG_NUM			(nand->scan_pg_num)

/* extern global nand device 
 * handle,defined in the
 * nand_flash.c file 
 */ 
extern nand_t* nand;

/* indication for bi swap enable 
 * or not, define in the main.c
 * host will send command to 
 * set this flag  
 */ 
extern BI_SWAP_FLAG flag_bi_swap;

/*!
 * Function to do base nfc basic init
 * @param none
 */
void nfc_base_init(void)
{
	nfc_init();
	
	/* FIXME,some nand 
	 * flash need reset first 
	 */
	nfc_command_input(NAND_CMD_RESET);
}

/*!
 * Function to read id
 * @param	[out] tmp 
 */
void nfc_send_read_id(u32* tmp)
{
	send_read_id(tmp);	
}

/*!
 * Function to set fms
 * @param	[in] bus_width
 * @param	[in] page_size
 * @param	[in] oob_size   
 */
void nfc_set_fms(u8 bus_width, u32 page_size,u16 oob_size)
{
	set_fms(bus_width,page_size,oob_size);
}

/*
 * This function does the trick of swapping the 464th byte in the last RAM
 * buffer in the main area with the 0th byte in the spare area. This seems
 * to be the optimal way of addressing the NFC imcompatibility problem with
 * the NAND flash out of factory in terms of BI field.
 * Note: this function only operates on the NFC's internal RAM buffers and
 * for 2K page only.
 */

void nand_bi_main_sp(void)
{
	u16 tmp1, tmp2, new_tmp1;
	tmp1 = BAD_BLK_MARKER_MAIN;
	tmp2 = BAD_BLK_MARKER_SP_0;

	new_tmp1 = (tmp1 & 0xFF00) | (tmp2 >> 8);
	tmp2 = (tmp1 << 8) | (tmp2 & 0xFF);
	BAD_BLK_MARKER_MAIN = new_tmp1;
	BAD_BLK_MARKER_SP_0 = tmp2;
}

/*!
 * Function to copy memory content
 * Parser the command, and then call the corresponding functions.
 * @param	[in] SourceAddress  - source address
 * @param	[in] TargetAddress -Destination address
 * @param	[in] ByteSize	-byte size
 */
void nfc_memcpy(u32 s, u32 d, u32 len)
{
	u32 i;
	for(i = 0; i < len; i += 2)
		*(volatile u16 *)(d + i) = *(volatile u16 *)(s + i);
}

/*!
 * Function to copy spare content
 * @param	[in] nd - nand structure
 * @param	[in] pbuf  - data buf address
 * @param	[in] pspare - spare buf address
 * @param	[in] len - byte size
 * @param	[in] bfrom - direction
 */
void copy_spare(nand_t *nd, char *pbuf, char *pspare,int len, u8 bfrom)
{
	u16 ooblen = nd->oob_size;
	u8  i, count,size;
	
	count = nd->page_size>>9;
	size = (ooblen/count >>1)<<1;
	
	if(!pspare)
		pspare = (char*)NFC_SAB0_BASE;
		
	if(bfrom){
		for(i=0;i<count -1;i++){
			/* source,dest,len */
			nfc_memcpy((u32)(pspare + i *NFC_SAB_LEN),(u32)(pbuf + i*size), size);
			}
	
		nfc_memcpy((u32)(pspare + i *NFC_SAB_LEN),(u32)(pbuf + i*size), len - i *size);
	}
	else{
		for(i=0;i<count -1;i++){
			/* source,dest,len */
			nfc_memcpy((u32)(pbuf+ i * size),(u32)(pspare + i *NFC_SAB_LEN) , size);
			}
	
		nfc_memcpy((u32)(pbuf+ i * size),(u32)(pspare + i *NFC_SAB_LEN), len - i *size);
		}
}

/*!
 * Function to check whether nand block is good
 * @param	[in] BlockNum - block number
 */
u8 nand_block_is_good(u32 block)
{
	u16 flag;
	u32 row;
	u8 i,col_addr_cycle;
	
	/* set row_addr_cycle */
	col_addr_cycle = NAND_MAIN_BYTESIZE > 512 ? 2 : 1;
	
	/* check first page */
	row = (block*NAND_NUM_OF_PAGES);
	
	/* get the offset page */
	row += NAND_BBI_PAGE_OFFSET;
	
	for(i=0;i<NAND_SCAN_PG_NUM;i++){
		/* send read command */
		nfc_command_input(NAND_CMD_READ);
		
		/* address cycle, row & col */
		nfc_address_cycle(0, col_addr_cycle);
		row +=i;
		nfc_address_cycle(row, NAND_NUM_OF_ROW_ADDR_CYCLES);
		
		/* send page read command for large page */
		if (NAND_MAIN_BYTESIZE > 512)
			nfc_command_input(NAND_CMD_READ_CONFIRM);
		
		/* trans data from nand flash to nfc buffer */
		send_read_page();
		
		/* check ecc status */
		if(nfc_ecc_uncorrectable_error(NAND_MAIN_BYTESIZE))
    		return 0;

		/* bi swap */
		if((flag_bi_swap == BI_SWAP_ENABLE) &&
		   	(NAND_MAIN_BYTESIZE > 512)) {
			nand_bi_main_sp();
			flag = BAD_BLK_MARKER_SP_0;
		}
		else {
			flag = *(volatile u16 *)(NFC_SAB0_BASE + 4);
		}
		
		/* check bad or not */
		if ((flag & 0xFF00) != 0xFF00) {
			return 0;
		}
	}
	return 1;
}

/*!
 * Function to  mark bad block
 * @param	[in] BlockNum - block number
 */
s16 nand_mark_bad_block(u32 block)
{
	u8 i,j;
	u32 row;
	u8 col_addr_cycle = 0;
	
	/* set row_addr_cycle */
	col_addr_cycle = NAND_MAIN_BYTESIZE > 512 ? 2 : 1;
	
    /* filled the memory with zero */
    for(j=0;j<NFC_SAB_COUNT;j++){
	    for(i=0; i<NFC_SAB_LEN; i+=2){
		    *(volatile u16 *)(NFC_SAB0_BASE+i+j*NFC_SAB_LEN) = 0;
	    }
    }
    
	/* bi swap*/
	if((flag_bi_swap == BI_SWAP_ENABLE) &&
		(NAND_MAIN_BYTESIZE > 512))
		nand_bi_main_sp();

	/* send prog initial command */
	nfc_command_input(NAND_CMD_PAGE_PROG);
	
	/* address cycle */
	nfc_address_cycle(0, col_addr_cycle);
	row = (block * NAND_NUM_OF_PAGES);
	row += NAND_BBI_PAGE_OFFSET;
	nfc_address_cycle(row, NAND_NUM_OF_ROW_ADDR_CYCLES);

	/* trans data from nfc to nand flash */
	send_prog_page();

	/* send prog confirm command */
	nfc_command_input(NAND_CMD_PAGE_PROG_CONFIRM);

	/* wait prog completely*/
	while (!(nand_read_status() & NAND_STATUS_READY));
	
	/* check prog status */
	if (nand_read_status() & NAND_STATUS_PROG_ERROR)
    		return FLASH_ERROR_PROG;

	return FLASH_ERROR_NO;
}

/*!
 * Function to  erase nand block
 * @param	[in] BlockNum	- block number
 */
s16 nand_erase_block(u32 block)
{
	u32 row;
	
	/* send erase command */
	nfc_command_input(NAND_CMD_ERASE);
	
	/* addr cycle only row addr */
	row = (block*NAND_NUM_OF_PAGES);
	nfc_address_cycle(row, NAND_NUM_OF_ROW_ADDR_CYCLES);
	
	/* send erase confirm command */
	nfc_command_input(NAND_CMD_ERASE_CONFIRM);

	/* check the status */
	if( nand_read_status() & NAND_STATUS_PROG_ERROR )
		return FLASH_ERROR_ERASE;

	return FLASH_ERROR_NO;
}

/*!
 * Function to  read one page
 * @param	[in] BlockNum	- block number
 * @param	[in] PageNum - page number
 * @param	[in] TargetAddress	- destination address
 * @param	[in] ByteSize	- byte size to be read
 */
s16 nand_read_page(u32 block, u32 page, u32 dest, u32 len,u32 offs)
{
	u8 col_addr_cycle = 0;
	
	/* set row_addr_cycle */
	col_addr_cycle = NAND_MAIN_BYTESIZE > 512 ? 2 : 1;
	
	/* send read command */
	nfc_command_input(NAND_CMD_READ);
	
	/* addr cycle: row & col */
	nfc_address_cycle(0, col_addr_cycle);
	nfc_address_cycle(block * NAND_NUM_OF_PAGES + page, NAND_NUM_OF_ROW_ADDR_CYCLES);
	
	/* send read confirm command for large page */
	if (NAND_MAIN_BYTESIZE > 512)
	nfc_command_input(NAND_CMD_READ_CONFIRM);

	/* trans data from nand to nfc buffer*/
	send_read_page();

	/* check ecc status */
	if(nfc_ecc_uncorrectable_error(NAND_MAIN_BYTESIZE))
		return FLASH_ERROR_ECC;

	/* bi swap */
	if((flag_bi_swap == BI_SWAP_ENABLE) &&
		(NAND_MAIN_BYTESIZE > 512))
		nand_bi_main_sp();

	/* trans data from nfc buffer to data buffer*/
	nfc_memcpy(NFC_MAB0_BASE + offs, dest, len);

	return FLASH_ERROR_NO;
}

 /*!
 * Function to  write one page
 * @param	[in] BlockNum	- block number
 * @param	[in] PageNum page number
 * @param	[in] SourceAddress	-source address
 * @param	[in]ByteSize	-byte size to be written
 */
s16 nand_write_page(u32 block, u32 page, u32 src, u32 len,u8 file_format)
{
	u8 col_addr_cycle = 0;
	
	/* set row_addr_cycle */
	col_addr_cycle = NAND_MAIN_BYTESIZE > 512 ? 2 : 1;
	
	/* set nfc spare data */
    set_nfc_spare(file_format);
    
	/* zero buffer in case len < page size */
	if( len < nand->page_size)
		memset((void *)NFC_MAB0_BASE,0xff,nand->page_size);
    /* copy the data */
	nfc_memcpy(src, NFC_MAB0_BASE, len);

	/* bi swap */
	if((flag_bi_swap == BI_SWAP_ENABLE) &&
		(NAND_MAIN_BYTESIZE > 512))
		nand_bi_main_sp();

	/* send prog inital command */
	nfc_command_input(NAND_CMD_PAGE_PROG);
	
	/* addr cycle: row & col */
	nfc_address_cycle(0, col_addr_cycle);
	nfc_address_cycle(block * NAND_NUM_OF_PAGES + page, NAND_NUM_OF_ROW_ADDR_CYCLES);
	
	/* trans data from nfc to nand flash*/
	send_prog_page();

	/* send prog confirm command */
	nfc_command_input(NAND_CMD_PAGE_PROG_CONFIRM);

	/* wait prog completely*/
	nand_wait();

	/* check prog status */
	if(nand_read_status() & NAND_STATUS_PROG_ERROR)
		return FLASH_ERROR_PROG;

	return FLASH_ERROR_NO;
}

 /*!
 * Function to  compare one page
 * @param	[in] BlockNum	- block number
 * @param	[in] PageNum - page number
 * @param	[in] TargetAddress	-destination address
 * @param	[in]	ByteSize	- byte size to be compared
 */
s16 nand_compare_page(u32 block, u32 page, u32 dest, u32 len)
{
	u32 i;
	u32 error = 0;
	u8 col_addr_cycle = 0;
	
	/* set row_addr_cycle */
	col_addr_cycle = NAND_MAIN_BYTESIZE > 512 ? 2 : 1;
	
	/* send page read command */
	nfc_command_input(NAND_CMD_READ);
	
	/* address cycle, row & col */
	nfc_address_cycle(0, col_addr_cycle);
	nfc_address_cycle(block * NAND_NUM_OF_PAGES + page, NAND_NUM_OF_ROW_ADDR_CYCLES);
	
	/* send page read confirm command for large page */
	if (NAND_MAIN_BYTESIZE > 512)
		nfc_command_input(NAND_CMD_READ_CONFIRM);

	/* trans data from nand flash to nfc buffer */
	send_read_page();

	/* check ecc status */
	if(nfc_ecc_uncorrectable_error(NAND_MAIN_BYTESIZE))
		return FLASH_ERROR_ECC;

	/* bi swap */
	if((flag_bi_swap == BI_SWAP_ENABLE) &&
		(NAND_MAIN_BYTESIZE > 512))
		nand_bi_main_sp();

	/* compare data */
	for(i = 0; i < len; i += 2) {
		if((*(volatile u16 *)(NFC_MAB0_BASE+i)) != (*(volatile u16 *)(dest + i))){
      		error++;
  		}
	}
	
	if(error)
		return FLASH_ERROR_VERIFY;

	return FLASH_ERROR_NO;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -