flash.c
来自「FreeScale imx21开发板Nand flash烧写程序」· C语言 代码 · 共 1,195 行 · 第 1/3 页
C
1,195 行
// ***************************************************************************
//
// Filename: flash.c
//
// Created: Louis Lai (6/20/2003)
//
// Modified: $Author: $ $Date: $
//
// ***************************************************************************
// ***************************************************************************
// pragmas
// ***************************************************************************
// ***************************************************************************
// includes
// ***************************************************************************
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "tht_memory_map_defines.h"
#include "common.h"
//add by fcding
#include "mx_nand2k.h"
#include "flash_report.h"
//add by fcding
/*****************************************************************************
* <Macros>
*****************************************************************************/
#define CCM_RCSR (0x10027000+0x814)
#define CCM_PDR0 (0x10027000+0x18)
//#define NFC_BASE_ADDR (0xD8000000)
#define NFC_MAB0_BASE (NFC_BASE_ADDR+0x000) /* main area buffer0 */
#define NFC_MAB1_BASE (NFC_BASE_ADDR+0x200) /* main area buffer1 */
#define NFC_MAB2_BASE (NFC_BASE_ADDR+0x400) /* main area buffer2 */
#define NFC_MAB3_BASE (NFC_BASE_ADDR+0x600) /* main area buffer3 */
#define NFC_SAB0_BASE (NFC_BASE_ADDR+0x800) /* spare area buffer0 */
#define NFC_SAB1_BASE (NFC_BASE_ADDR+0x810) /* spare area buffer1 */
#define NFC_SAB2_BASE (NFC_BASE_ADDR+0x820) /* spare area buffer2 */
#define NFC_SAB3_BASE (NFC_BASE_ADDR+0x830) /* spare area buffer3 */
#define NFC_REG_BASE (NFC_BASE_ADDR+0xE00) /* nfc register area */
#define NFC_BUFSIZE (NFC_REG_BASE+0x00)
#define NFC_BLK_ADD_LOCK (NFC_REG_BASE+0x02)
#define NFC_RAM_BUF_ADDR (NFC_REG_BASE+0x04)
#define NFC_NAND_FLASH_ADDR (NFC_REG_BASE+0x06)
#define NFC_NAND_FLASH_CMD (NFC_REG_BASE+0x08)
#define NFC_CONFIGURATION (NFC_REG_BASE+0x0A)
#define NFC_ECC_STAT_RES (NFC_REG_BASE+0x0C)
#define NFC_ECC_RSLT_MA (NFC_REG_BASE+0x0E)
#define NFC_ECC_RSLT_SA (NFC_REG_BASE+0x10)
#define NFC_NF_WR_PROT (NFC_REG_BASE+0x12)
#define NFC_ULOCK_START_BLK (NFC_REG_BASE+0x14)
#define NFC_ULOCK_END_BLK (NFC_REG_BASE+0x16)
#define NFC_NF_WR_PROT_STAT (NFC_REG_BASE+0x18)
#define NFC_NF_CONFIG1 (NFC_REG_BASE+0x1A)
#define NFC_NF_CONFIG2 (NFC_REG_BASE+0x1C)
/*******************************************************************************/
#define NAND_CMD_READ (0x00)
#define NAND_CMD_READ1 (0x01)
#define NAND_CMD_READ2 (0x50)
#define NAND_CMD_READ_CONFIRM (0x30)
#define NAND_CMD_PAGE_PROG (0x80)
#define NAND_CMD_PAGE_PROG_CONFIRM (0x10)
#define NAND_CMD_ERASE (0x60)
#define NAND_CMD_ERASE_CONFIRM (0xD0)
#define NAND_CMD_READID (0x90)
#define NAND_CMD_RESET (0xFFFF)
#define NAND_CMD_READ_STATUS (0x70)
#define NAND_STATUS_READY (0x40)
#define NAND_STATUS_NOT_PROTECT (0x80)
#define NAND_STATUS_PROG_ERROR (0x01)
#define NF_FMS_2KB (0x20)
#define NF_16BIT (0x10)
#define PCDR0_NFCDIV_MASK (0x0000F000)
#define PCDR0_NFCDIV_10 (0x9)
#define NFC_BUSY (!( *(volatile u16 *)NFC_NF_CONFIG2 & 0x8000 ))
/*****************************************************************************
* <global Variables>
*****************************************************************************/
nand_t nand_type[] = {
// manuf device io badblock row num num
// id id width marker addr of of
// offset cycle block page
{ 0xEC, 0xDC, 8, 0, 3, 4096, 64, "NAND K9F4G08U0M" }, // K9F4G08U0M
{ 0xEC, 0xAA, 8, 0, 3, 2048, 64, "NAND K9K2G08R0A" } // K9K2G08R0A
};
nand_t *gNAND;
//#define DEBUG
#ifndef TRUE
#define TRUE (1 == 1)
#endif
#ifndef FALSE
#define FALSE (1 == 2)
#endif
// ***************************************************************************
// macros
// ***************************************************************************
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) > (b) ? (a) : (b))
// ***************************************************************************
// definitions
// ***************************************************************************
#define FLASH_DQ7_2X16 ((1 << (7 + 16)) | (1 << 7))
#define FLASH_DQ5_2X16 ((1 << (5 + 16)) | (1 << 5))
#define TACC 55 // Asyn. Access Time
#define TIACC 87 // Syn. Access Time#define HCLK 66 // EIM CLK
#define FCLK 54 // Flash Burst CLK
#define HCLK 66
#define MX21_MEM_ADDR_CS0 0xC8000000
#define MX21_MEM_ADDR_CS1 0xCC000000
#define MX21_MEM_ADDR_CS2 0xD0000000
#define MX21_MEM_ADDR_CS3 0xD1000000
#define MX21_MEM_ADDR_CS4 0xD2000000
#define MX21_MEM_ADDR_CS5 0xD3000000
//change by fcding
U8 nand_init(void)
{
U8 man_id;
U8 dev_id;
U16 i;
U8 is_found =0;
*(volatile U32 *)CCM_RCSR &= ~NF_16BIT; /* Set to 8-bit NAND */
*(volatile U32 *)CCM_RCSR |= NF_FMS_2KB; /* Set to 2K Page Size */
*(volatile U32 *)CCM_PDR0 &= ~PCDR0_NFCDIV_MASK;
*(volatile U32 *)CCM_PDR0 |= (PCDR0_NFCDIV_10 << 12); /* set NFC_PODF = 10 */
*(volatile U16 *)NFC_RAM_BUF_ADDR = 0; /* select Buffer 0 */
*(volatile U16 *)NFC_ULOCK_START_BLK = 0x0000;
*(volatile U16 *)NFC_ULOCK_END_BLK = 0x0FFF;
*(volatile U16 *)NFC_NF_WR_PROT = 0x0004;
*(volatile U16 *)NFC_CONFIGURATION = 0x0002; /* unlock the internal RAM buffer */
*(volatile U16 *)NFC_NF_CONFIG2 = 0x8000; /* clear all operation */
//*(volatile U16 *)NFC_NF_CONFIG1 = 0x0018; /* enable ECC and disable spare only, disable interrupt*/
*(volatile U16 *)NFC_NF_CONFIG1 = 0x0008;
*(volatile U16 *)NFC_ECC_STAT_RES =0x0000;
/*
nand_read_id(&man_id, &dev_id);
gNAND = nand_type;
i = sizeof(nand_type) / sizeof(nand_t);
while(i--) {
if( nand_type[i].man_id == man_id && nand_type[i].dev_id == dev_id ){
gNAND = nand_type + i;
if( gNAND->io_width == 16 )
*(volatile u32 *)CCM_RCSR |= NF_16BIT;
is_found = 1;
dbg("Find specific NAND type!\n");
break;
}
}
if(is_found)
return NAND_ERROR_NO;
else
return NAND_ERROR_INIT;
*/
}
U8 nfc_wait(void)
{
while(NFC_BUSY); /* Wait for Basic Operation Complete */
return 0;
}
void nfc_command_input(U16 command)
{
*(volatile U16 *)NFC_NAND_FLASH_CMD = command;
*(volatile U16 *)NFC_NF_CONFIG2 = 0x0001;
nfc_wait();
}
U8 nand_read_status(void)
{
*(volatile U16 *)NFC_RAM_BUF_ADDR = 0;
nfc_command_input(NAND_CMD_READ_STATUS);
*(volatile U16 *)NFC_NF_CONFIG2 = 0x0020; // FDO -> Read Status
nfc_wait();
return (U8)((*(volatile U32 *)(NFC_MAB0_BASE)) & 0xFF) ;
}
void nfc_address_input(U16 address)
{
*(volatile U16 *)NFC_NAND_FLASH_ADDR = address;
*(volatile U16 *)NFC_NF_CONFIG2 = 0x0002;
nfc_wait();
}
void nfc_address_cycle(U32 Address, U8 NumOfCycle)
{
U8 i;
for(i=0; i<NumOfCycle; i++)
nfc_address_input( (U16)( (Address>>(i*8))&0xFF ) );
}
void nfc_flash_data_output(void)
{
*(volatile U16 *)NFC_NF_CONFIG2 = 0x0008;
nfc_wait();
}
U8 nfc_ecc_uncorrectable_error(void)
{
return ( *(volatile U16 *)NFC_ECC_STAT_RES & 0xA ) ? 1 : 0;
}
U8 nand_erase_block(u32 BlockNum)
{
U32 row;
row = (BlockNum*NAND_NUM_OF_PAGES);
nfc_command_input(NAND_CMD_ERASE);
nfc_address_cycle(row, NAND_NUM_OF_ROW_ADDR_CYCLES);
nfc_command_input(NAND_CMD_ERASE_CONFIRM);
if( nand_read_status() & NAND_STATUS_PROG_ERROR ) {
return NAND_ERROR_ERASE;
}
else
return NAND_ERROR_NO;
}
void nfc_flash_data_input(void)
{
*(volatile U16 *)NFC_NF_CONFIG2 = 0x0004;
nfc_wait();
}
U8 nand_mark_bad_block(U32 BlockNum)
{
U8 i;
U32 col = 0, row;
row = (BlockNum*NAND_NUM_OF_PAGES);
for(i=0; i<64; i+=2)
*(volatile U16 *)(NFC_SAB0_BASE+i) = 0;
*(volatile U16 *)NFC_RAM_BUF_ADDR = 0;
nfc_command_input(NAND_CMD_PAGE_PROG);
nfc_address_cycle(col, 2);
nfc_address_cycle(row, NAND_NUM_OF_ROW_ADDR_CYCLES);
nfc_flash_data_input();
*(volatile U16 *)NFC_RAM_BUF_ADDR = 1;
nfc_flash_data_input();
*(volatile U16 *)NFC_RAM_BUF_ADDR = 2;
nfc_flash_data_input();
*(volatile U16 *)NFC_RAM_BUF_ADDR = 3;
nfc_flash_data_input();
nfc_command_input(NAND_CMD_PAGE_PROG_CONFIRM);
while (!(nand_read_status() & NAND_STATUS_READY));
if (nand_read_status() & NAND_STATUS_PROG_ERROR)
{
return 1;
}
return 0;
}
U8 nand_block_is_good(U32 BlockNum)
{
U16 flag;
U32 col = 0, row;
/* check first page */
row = (BlockNum*NAND_NUM_OF_PAGES);
*(volatile U16 *)NFC_RAM_BUF_ADDR = 0;
nfc_command_input(NAND_CMD_READ);
nfc_address_cycle(col, 2);
nfc_address_cycle(row, NAND_NUM_OF_ROW_ADDR_CYCLES);
/* command READ CONFIRM */
nfc_command_input(NAND_CMD_READ_CONFIRM);
nfc_flash_data_output();
*(volatile U16 *)NFC_RAM_BUF_ADDR = 1;
nfc_flash_data_output();
*(volatile U16 *)NFC_RAM_BUF_ADDR = 2;
nfc_flash_data_output();
*(volatile U16 *)NFC_RAM_BUF_ADDR = 3;
nfc_flash_data_output();
if(nfc_ecc_uncorrectable_error()) {
return 0;
}
flag = *(volatile u16 *)(NFC_SAB0_BASE + 4);
if ((flag & 0xFF00) != 0xFF00) {
return 0;
}
/* check second page */
row = (BlockNum*NAND_NUM_OF_PAGES) + 1;
*(volatile U16 *)NFC_RAM_BUF_ADDR = 0;
nfc_command_input(NAND_CMD_READ);
nfc_address_cycle(col, 2);
nfc_address_cycle(row, NAND_NUM_OF_ROW_ADDR_CYCLES);
/* command READ CONFIRM */
nfc_command_input(NAND_CMD_READ_CONFIRM);
nfc_flash_data_output();
*(volatile U16 *)NFC_RAM_BUF_ADDR = 1;
nfc_flash_data_output();
*(volatile U16 *)NFC_RAM_BUF_ADDR = 2;
nfc_flash_data_output();
*(volatile U16 *)NFC_RAM_BUF_ADDR = 3;
nfc_flash_data_output();
if(nfc_ecc_uncorrectable_error()) {
return 0;
}
flag = *(volatile U16 *)(NFC_SAB0_BASE + 4);
return ((flag & 0xFF00) == 0xFF00);
}
void nand_wait(void)
{
while(!(NAND_STATUS_READY & nand_read_status()));
}
void nfc_memcpy(U32 SourceAddress, U32 TargetAddress, U32 ByteSize)
{
U32 i;
for(i=0; i<ByteSize; i+=4) {
*(volatile u32 *)(TargetAddress+i) = *(volatile u32 *)(SourceAddress+i);
}
}
U8 nand_read_page(U32 BlockNum, U32 PageNum, U32 TargetAddress, U32 ByteSize)
{
*(volatile U16 *)NFC_RAM_BUF_ADDR = 0;
nfc_command_input(NAND_CMD_READ);
nfc_address_cycle(0, 2);
nfc_address_cycle(BlockNum*NAND_NUM_OF_PAGES+PageNum, NAND_NUM_OF_ROW_ADDR_CYCLES);
nfc_command_input(NAND_CMD_READ_CONFIRM);
nfc_flash_data_output();
*(volatile u16 *)NFC_RAM_BUF_ADDR = 1;
nfc_flash_data_output();
*(volatile u16 *)NFC_RAM_BUF_ADDR = 2;
nfc_flash_data_output();
*(volatile u16 *)NFC_RAM_BUF_ADDR = 3;
nfc_flash_data_output();
if(nfc_ecc_uncorrectable_error())
return NAND_ERROR_ECC;
nfc_memcpy(NFC_MAB0_BASE, TargetAddress, ByteSize);
return NAND_ERROR_NO;
}
U8 nand_read(U32 FlashAddress, U32 TargetAddress, U32 ByteSize)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?