547 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			547 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*****************************************************************************
 | 
						||
 *
 | 
						||
 *   Copyright(C) 2011, Embedded Artists AB
 | 
						||
 *   All rights reserved.
 | 
						||
 *
 | 
						||
 ******************************************************************************
 | 
						||
 * Software that is described herein is for illustrative purposes only
 | 
						||
 * which provides customers with programming information regarding the
 | 
						||
 * products. This software is supplied "AS IS" without any warranties.
 | 
						||
 * Embedded Artists AB assumes no responsibility or liability for the
 | 
						||
 * use of the software, conveys no license or title under any patent,
 | 
						||
 * copyright, or mask work right to the product. Embedded Artists AB
 | 
						||
 * reserves the right to make changes in the software without
 | 
						||
 * notification. Embedded Artists AB also make no representation or
 | 
						||
 * warranty that such application will be suitable for the specified
 | 
						||
 * use without further testing or modification.
 | 
						||
 *****************************************************************************/
 | 
						||
 | 
						||
 | 
						||
/******************************************************************************
 | 
						||
 * Includes
 | 
						||
 *****************************************************************************/
 | 
						||
#include "../board.h"
 | 
						||
 | 
						||
#if BOARD == BOARD_EA4357
 | 
						||
 | 
						||
#include "lpc_types.h"
 | 
						||
#include "lpc43xx_scu.h"
 | 
						||
#include "lpc43xx_timer.h"
 | 
						||
#include "nand.h"
 | 
						||
 | 
						||
 | 
						||
/******************************************************************************
 | 
						||
 * Defines and typedefs
 | 
						||
 *****************************************************************************/
 | 
						||
 | 
						||
#define K9F1G_CLE   ((volatile uint8_t *)0x1D100000)
 | 
						||
#define K9F1G_ALE   ((volatile uint8_t *)0x1D080000)
 | 
						||
#define K9F1G_DATA  ((volatile uint8_t *)0x1D000000)
 | 
						||
 | 
						||
#define K9FXX_WAIT()
 | 
						||
 | 
						||
#define K9FXX_READ_1            0x00                
 | 
						||
#define K9FXX_READ_2            0x30                
 | 
						||
 | 
						||
#define K9FXX_SET_ADDR_A        0x00                
 | 
						||
#define K9FXX_SET_ADDR_B        0x01                
 | 
						||
#define K9FXX_SET_ADDR_C        0x50                
 | 
						||
#define K9FXX_READ_ID           0x90                
 | 
						||
#define K9FXX_RESET             0xff                
 | 
						||
#define K9FXX_BLOCK_PROGRAM_1   0x80                
 | 
						||
#define K9FXX_BLOCK_PROGRAM_2   0x10                
 | 
						||
#define K9FXX_BLOCK_ERASE_1     0x60                
 | 
						||
#define K9FXX_BLOCK_ERASE_2     0xd0                
 | 
						||
#define K9FXX_READ_STATUS       0x70                
 | 
						||
#define K9FXX_BUSY              (1 << 6)            
 | 
						||
#define K9FXX_OK                (1 << 0)   
 | 
						||
 | 
						||
#define ID_MARKER_CODE (0xEC)
 | 
						||
#define ID_SAMSUNG     (0xF1)
 | 
						||
 | 
						||
#define ID_PAGE_SZ_1KB (0x00)
 | 
						||
#define ID_PAGE_SZ_2KB (0x01)
 | 
						||
#define ID_PAGE_SZ_4KB (0x02)
 | 
						||
#define ID_PAGE_SZ_8KB (0x03)
 | 
						||
 | 
						||
#define ID_BLOCK_SZ_64KB  (0x00)
 | 
						||
#define ID_BLOCK_SZ_128KB (0x01)
 | 
						||
#define ID_BLOCK_SZ_256KB (0x02)
 | 
						||
#define ID_BLOCK_SZ_512KB (0x03)
 | 
						||
 | 
						||
#define ID_PAGE_SZ_1KB (0x00)
 | 
						||
#define ID_PAGE_SZ_2KB (0x01)
 | 
						||
#define ID_PAGE_SZ_4KB (0x02)
 | 
						||
#define ID_PAGE_SZ_8KB (0x03)
 | 
						||
 | 
						||
#define ID_REDUND_SZ_8  (0x00)
 | 
						||
#define ID_REDUND_SZ_16 (0x01)
 | 
						||
 | 
						||
 | 
						||
 | 
						||
/* This macro could be changed to check the ready pin */
 | 
						||
#define WAIT_READY() (TIM_Waitus(25))
 | 
						||
         
 | 
						||
 | 
						||
/******************************************************************************
 | 
						||
 * External global variables
 | 
						||
 *****************************************************************************/
 | 
						||
 | 
						||
/******************************************************************************
 | 
						||
 * Local variables
 | 
						||
 *****************************************************************************/
 | 
						||
 | 
						||
static uint32_t pageSize   = 0;
 | 
						||
static uint32_t blockSize  = 0;
 | 
						||
static uint32_t reduntSize = 0;
 | 
						||
 | 
						||
 | 
						||
/******************************************************************************
 | 
						||
 * Local Functions
 | 
						||
 *****************************************************************************/
 | 
						||
 | 
						||
static void pinConfig(void)
 | 
						||
{
 | 
						||
	/* Set up EMC pin */
 | 
						||
	scu_pinmux(	 2	,	 9	,	MD_PLN_FAST	,	3	);//A0
 | 
						||
	scu_pinmux(	 2	,	10	,	MD_PLN_FAST	,	3	);//A1
 | 
						||
	scu_pinmux(	 2	,	11	,	MD_PLN_FAST	,	3	);//A2
 | 
						||
	scu_pinmux(	 2	,	12	,	MD_PLN_FAST	,	3	);//A3
 | 
						||
	scu_pinmux(	 2	,	13	,	MD_PLN_FAST	,	3	);//A4
 | 
						||
	scu_pinmux(	 1	,	 0	,	MD_PLN_FAST	,	2	);//A5
 | 
						||
	scu_pinmux(	 1	,	 1	,	MD_PLN_FAST	,	2	);//A6
 | 
						||
	scu_pinmux(	 1	,	 2	,	MD_PLN_FAST	,	2	);//A7
 | 
						||
	scu_pinmux(	 2	,	 8	,	MD_PLN_FAST	,	3	);//A8
 | 
						||
	scu_pinmux(	 2	,	 7	,	MD_PLN_FAST	,	3	);//A9
 | 
						||
	scu_pinmux(	 2	,	 6	,	MD_PLN_FAST	,	2	);//A10
 | 
						||
	scu_pinmux(	 2	,	 2	,	MD_PLN_FAST	,	2	);//A11
 | 
						||
	scu_pinmux(	 2	,	 1	,	MD_PLN_FAST	,	2	);//A12
 | 
						||
	scu_pinmux(	 2	,	 0	,	MD_PLN_FAST	,	2	);//A13
 | 
						||
	scu_pinmux(	 6	,	 8	,	MD_PLN_FAST	,	1	);//A14
 | 
						||
	scu_pinmux(	 6	,	 7	,	MD_PLN_FAST	,	1	);//A15
 | 
						||
	scu_pinmux(	13	,	16	,	MD_PLN_FAST	,	2	);//A16
 | 
						||
	scu_pinmux(	13	,	15	,	MD_PLN_FAST	,	2	);//A17
 | 
						||
	scu_pinmux(	14	,	 0	,	MD_PLN_FAST	,	3	);//A18
 | 
						||
	scu_pinmux(	14	,	 1	,	MD_PLN_FAST	,	3	);//A19
 | 
						||
	scu_pinmux(	14	,	 2	,	MD_PLN_FAST	,	3	);//A20
 | 
						||
	scu_pinmux(	14	,	 3	,	MD_PLN_FAST	,	3	);//A21
 | 
						||
	scu_pinmux(	14	,	 4	,	MD_PLN_FAST	,	3	);//A22
 | 
						||
	scu_pinmux(	10	,	 4	,	MD_PLN_FAST	,	3	);//A23
 | 
						||
	
 | 
						||
	scu_pinmux(	 1	,	 7	,	MD_PLN_FAST	,	3	);//D0
 | 
						||
	scu_pinmux(	 1	,	 8	,	MD_PLN_FAST	,	3	);//D1
 | 
						||
	scu_pinmux(	 1	,	 9	,	MD_PLN_FAST	,	3	);//D2
 | 
						||
	scu_pinmux(	 1	,	10	,	MD_PLN_FAST	,	3	);//D3
 | 
						||
	scu_pinmux(	 1	,	11	,	MD_PLN_FAST	,	3	);//D4
 | 
						||
	scu_pinmux(	 1	,	12	,	MD_PLN_FAST	,	3	);//D5
 | 
						||
	scu_pinmux(	 1	,	13	,	MD_PLN_FAST	,	3	);//D6
 | 
						||
	scu_pinmux(	 1	,	14	,	MD_PLN_FAST	,	3	);//D7
 | 
						||
	scu_pinmux(	 5	,	 4	,	MD_PLN_FAST	,	2	);//D8
 | 
						||
	scu_pinmux(	 5	,	 5	,	MD_PLN_FAST	,	2	);//D9
 | 
						||
	scu_pinmux(	 5	,	 6	,	MD_PLN_FAST	,	2	);//D10
 | 
						||
	scu_pinmux(	 5	,	 7	,	MD_PLN_FAST	,	2	);//D11
 | 
						||
	scu_pinmux(	 5	,	 0	,	MD_PLN_FAST	,	2	);//D12
 | 
						||
	scu_pinmux(	 5	,	 1	,	MD_PLN_FAST	,	2	);//D13
 | 
						||
	scu_pinmux(	 5	,	 2	,	MD_PLN_FAST	,	2	);//D14
 | 
						||
	scu_pinmux(	 5	,	 3	,	MD_PLN_FAST	,	2	);//D15
 | 
						||
	scu_pinmux(	13	,	 2	,	MD_PLN_FAST	,	2	);//D16
 | 
						||
	scu_pinmux(	13	,	 3	,	MD_PLN_FAST	,	2	);//D17
 | 
						||
	scu_pinmux(	13	,	 4	,	MD_PLN_FAST	,	2	);//D18
 | 
						||
	scu_pinmux(	13	,	 5	,	MD_PLN_FAST	,	2	);//D19
 | 
						||
	scu_pinmux(	13	,	 6	,	MD_PLN_FAST	,	2	);//D20
 | 
						||
	scu_pinmux(	13	,	 7	,	MD_PLN_FAST	,	2	);//D21
 | 
						||
	scu_pinmux(	13	,	 8	,	MD_PLN_FAST	,	2	);//D22
 | 
						||
	scu_pinmux(	13	,	 9	,	MD_PLN_FAST	,	2	);//D23
 | 
						||
	scu_pinmux(	14	,	 5	,	MD_PLN_FAST	,	3	);//D24
 | 
						||
	scu_pinmux(	14	,	 6	,	MD_PLN_FAST	,	3	);//D25
 | 
						||
	scu_pinmux(	14	,	 7	,	MD_PLN_FAST	,	3	);//D26
 | 
						||
	scu_pinmux(	14	,	 8	,	MD_PLN_FAST	,	3	);//D27
 | 
						||
	scu_pinmux(	14	,	 9	,	MD_PLN_FAST	,	3	);//D28
 | 
						||
	scu_pinmux(	14	,	10	,	MD_PLN_FAST	,	3	);//D29
 | 
						||
	scu_pinmux(	14	,	11	,	MD_PLN_FAST	,	3	);//D30
 | 
						||
	scu_pinmux(	14	,	12	,	MD_PLN_FAST	,	3	);//D31
 | 
						||
		
 | 
						||
	scu_pinmux(	 1	,	 3	,	MD_PLN_FAST	,	3	);//OE
 | 
						||
	scu_pinmux(	 1	,	 6	,	MD_PLN_FAST	,	3	);//WE
 | 
						||
	
 | 
						||
	scu_pinmux(	 1	,	 4	,	MD_PLN_FAST	,	3	);//BLS0
 | 
						||
	scu_pinmux(	 6	,	 6	,	MD_PLN_FAST	,	1	);//BLS1	
 | 
						||
	scu_pinmux(	13	,	13	,	MD_PLN_FAST	,	2	);//BLS2
 | 
						||
	scu_pinmux(	13	,	10	,	MD_PLN_FAST	,	2	);//BLS3
 | 
						||
	
 | 
						||
	scu_pinmux(	 1	,	 5	,	MD_PLN_FAST	,	3	);//CS0	
 | 
						||
	scu_pinmux(	 6	,	 3	,	MD_PLN_FAST	,	3	);//CS1
 | 
						||
	scu_pinmux(	13	,	12	,	MD_PLN_FAST	,	2	);//CS2
 | 
						||
	scu_pinmux(	13	,	11	,	MD_PLN_FAST	,	2	);//CS3
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
static uint32_t nandReadId(void)
 | 
						||
{
 | 
						||
  uint8_t a, b, c, d;
 | 
						||
  volatile uint8_t *pCLE;
 | 
						||
  volatile uint8_t *pALE;
 | 
						||
  volatile uint8_t *pData;
 | 
						||
  
 | 
						||
  pCLE  = K9F1G_CLE;
 | 
						||
  pALE  = K9F1G_ALE;
 | 
						||
  pData = K9F1G_DATA;
 | 
						||
    
 | 
						||
  *pCLE = K9FXX_READ_ID;
 | 
						||
  *pALE = 0;
 | 
						||
    
 | 
						||
  a = *pData;
 | 
						||
  b = *pData;
 | 
						||
  c = *pData;
 | 
						||
  d = *pData;
 | 
						||
  
 | 
						||
    
 | 
						||
  return (a << 24) | (b << 16) | (c << 8) | d;
 | 
						||
}
 | 
						||
 | 
						||
static uint8_t nandStatus(void)
 | 
						||
{
 | 
						||
  uint8_t status = 0;
 | 
						||
  volatile uint8_t *pCLE;
 | 
						||
  volatile uint8_t *pALE;
 | 
						||
  volatile uint8_t *pData;
 | 
						||
  
 | 
						||
  pCLE  = K9F1G_CLE;
 | 
						||
  pALE  = K9F1G_ALE;
 | 
						||
  pData = K9F1G_DATA;
 | 
						||
    
 | 
						||
  *pCLE = K9FXX_READ_STATUS;
 | 
						||
  *pALE = 0;
 | 
						||
    
 | 
						||
  status = *pData;
 | 
						||
      
 | 
						||
  /* remove bits not used */
 | 
						||
  return (status & 0xC1);  
 | 
						||
}
 | 
						||
 | 
						||
static void nandWaitReady(void) 
 | 
						||
{
 | 
						||
  while( !(nandStatus() & (1<<6)) );
 | 
						||
}
 | 
						||
 | 
						||
/******************************************************************************
 | 
						||
 * Public Functions
 | 
						||
 *****************************************************************************/
 | 
						||
 | 
						||
 | 
						||
 | 
						||
/******************************************************************************
 | 
						||
 *
 | 
						||
 * Description:
 | 
						||
 *    Initialize the NAND Flash
 | 
						||
 *
 | 
						||
 * Returns:
 | 
						||
 *    TRUE if initialization successful; otherwise FALSE
 | 
						||
 *
 | 
						||
 *****************************************************************************/
 | 
						||
uint32_t nand_init (void)
 | 
						||
{
 | 
						||
  uint32_t nandId = 0;
 | 
						||
  TIM_TIMERCFG_Type timerCfg;
 | 
						||
 | 
						||
//  LPC_SC->PCONP     |= 0x00000800;
 | 
						||
  LPC_EMC->CONTROL   = 0x00000001;
 | 
						||
  LPC_EMC->CONFIG    = 0x00000000;
 | 
						||
 | 
						||
  pinConfig();
 | 
						||
 | 
						||
  TIM_ConfigStructInit(TIM_TIMER_MODE, &timerCfg);
 | 
						||
  TIM_Init(LPC_TIMER0, TIM_TIMER_MODE, &timerCfg);
 | 
						||
 | 
						||
  LPC_EMC->STATICCONFIG1   = 0x00000080;
 | 
						||
 | 
						||
  LPC_EMC->STATICWAITWEN1  = 0x00000002; 
 | 
						||
  LPC_EMC->STATICWAITOEN1  = 0x00000002; 
 | 
						||
  LPC_EMC->STATICWAITRD1   = 0x00000008; 
 | 
						||
  LPC_EMC->STATICWAITPAG1  = 0x0000001f; 
 | 
						||
  LPC_EMC->STATICWAITWR1   = 0x00000008; 
 | 
						||
  LPC_EMC->STATICWAITTURN1 = 0x0000000f;
 | 
						||
 | 
						||
  nandId = nandReadId();
 | 
						||
 | 
						||
  if ((nandId & 0xffff0000) != 
 | 
						||
    (((uint32_t)(ID_MARKER_CODE) << 24) | ID_SAMSUNG << 16)) {
 | 
						||
    /* unknown NAND chip */
 | 
						||
    return FALSE;
 | 
						||
  }
 | 
						||
 | 
						||
  pageSize   = 1024 * (1 << (nandId & 0x03));  
 | 
						||
  blockSize  = 64*1024 * (1 << ((nandId>>4) & 0x03));
 | 
						||
  reduntSize = 8 * (1 << ((nandId >> 1) & 0x1));
 | 
						||
 | 
						||
                         
 | 
						||
  return TRUE;
 | 
						||
}
 | 
						||
 | 
						||
/******************************************************************************
 | 
						||
 *
 | 
						||
 * Description:
 | 
						||
 *    Get the page size of the NAND flash
 | 
						||
 *
 | 
						||
 * Returns:
 | 
						||
 *    page size in bytes
 | 
						||
 *
 | 
						||
 *****************************************************************************/
 | 
						||
uint32_t nand_getPageSize(void)
 | 
						||
{
 | 
						||
  return pageSize;
 | 
						||
}
 | 
						||
 | 
						||
/******************************************************************************
 | 
						||
 *
 | 
						||
 * Description:
 | 
						||
 *    Get the block size of the NAND flash
 | 
						||
 *
 | 
						||
 * Returns:
 | 
						||
 *    block size in bytes
 | 
						||
 *
 | 
						||
 *****************************************************************************/
 | 
						||
uint32_t nand_getBlockSize(void)
 | 
						||
{
 | 
						||
  return blockSize;
 | 
						||
}
 | 
						||
 | 
						||
/******************************************************************************
 | 
						||
 *
 | 
						||
 * Description:
 | 
						||
 *    Get the redundant (spare) size per page
 | 
						||
 *
 | 
						||
 * Returns:
 | 
						||
 *    redundant/spare size in bytes
 | 
						||
 *
 | 
						||
 *****************************************************************************/
 | 
						||
uint32_t nand_getRedundantSize(void)
 | 
						||
{
 | 
						||
  return reduntSize * (pageSize/512);
 | 
						||
}
 | 
						||
 | 
						||
/******************************************************************************
 | 
						||
 *
 | 
						||
 * Description:
 | 
						||
 *    Check if a block is valid
 | 
						||
 *
 | 
						||
 * Returns:
 | 
						||
 *    TRUE if the block is valid; otherwise FALSE
 | 
						||
 *
 | 
						||
 *****************************************************************************/
 | 
						||
uint32_t nand_isBlockValid(uint32_t block)
 | 
						||
{
 | 
						||
  uint32_t addr = 0;
 | 
						||
  uint32_t page = 0;
 | 
						||
 | 
						||
  volatile uint8_t *pCLE;
 | 
						||
  volatile uint8_t *pALE;
 | 
						||
  volatile uint8_t *pData;
 | 
						||
 | 
						||
  
 | 
						||
  pCLE  = K9F1G_CLE;
 | 
						||
  pALE  = K9F1G_ALE;
 | 
						||
  pData = K9F1G_DATA;
 | 
						||
 | 
						||
  if (block >= NAND_NUM_BLOCKS) {
 | 
						||
    return FALSE;
 | 
						||
  }
 | 
						||
 | 
						||
  addr = block * (blockSize/pageSize);
 | 
						||
 | 
						||
  /* 
 | 
						||
   * Check page 0 and page 1 in each block. If the first byte
 | 
						||
   * in the spare area (of either page 0 or page 1) is != 0xFF 
 | 
						||
   * the block is invalid.
 | 
						||
   */
 | 
						||
 | 
						||
  nandWaitReady();
 | 
						||
 | 
						||
  for (page = 0; page < 2; page++) {
 | 
						||
    addr += page;
 | 
						||
 | 
						||
    *pCLE = K9FXX_READ_1;
 | 
						||
    *pALE = (uint8_t) (pageSize & 0x00FF);
 | 
						||
    *pALE = (uint8_t)((pageSize & 0xFF00) >> 8);
 | 
						||
    *pALE = (uint8_t)((addr & 0x00FF));
 | 
						||
    *pALE = (uint8_t)((addr & 0xFF00) >> 8);
 | 
						||
    *pCLE = K9FXX_READ_2;
 | 
						||
 | 
						||
    WAIT_READY();
 | 
						||
 | 
						||
    if (*pData != 0xFF) {
 | 
						||
      return FALSE;
 | 
						||
    }
 | 
						||
        
 | 
						||
  }
 | 
						||
 | 
						||
  return TRUE;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
/******************************************************************************
 | 
						||
 *
 | 
						||
 * Description:
 | 
						||
 *    Read a page from the NAND memory
 | 
						||
 *
 | 
						||
 * Params:
 | 
						||
 *    block - block number to read from
 | 
						||
 *    page  - page with<74>n block to read from
 | 
						||
 *    pageBuf - data is copied to this buffer. The size must be at least 
 | 
						||
 *              pageSize.
 | 
						||
 *
 | 
						||
 * Returns:
 | 
						||
 *    TRUE if read successful; otherwise FALSE
 | 
						||
 *
 | 
						||
 *****************************************************************************/
 | 
						||
uint32_t nand_readPage(uint32_t block, uint32_t page, uint8_t* pageBuf)
 | 
						||
{
 | 
						||
  uint32_t i = 0;
 | 
						||
  uint32_t addr = 0;
 | 
						||
 | 
						||
  volatile uint8_t *pCLE;
 | 
						||
  volatile uint8_t *pALE;
 | 
						||
  volatile uint8_t *pData;
 | 
						||
 | 
						||
  
 | 
						||
  pCLE  = K9F1G_CLE;
 | 
						||
  pALE  = K9F1G_ALE;
 | 
						||
  pData = K9F1G_DATA;
 | 
						||
 | 
						||
  if (block >= NAND_NUM_BLOCKS) {
 | 
						||
    return FALSE;
 | 
						||
  }
 | 
						||
 | 
						||
  if (page >= blockSize/pageSize) {
 | 
						||
    return FALSE;
 | 
						||
  }
 | 
						||
 | 
						||
  addr = block * (blockSize/pageSize) + page;
 | 
						||
 | 
						||
  /*
 | 
						||
   * Always reading from start of a page address.
 | 
						||
   * This means that the column address is always 0.
 | 
						||
   */
 | 
						||
 | 
						||
  *pCLE = K9FXX_READ_1;
 | 
						||
  *pALE = 0;
 | 
						||
  *pALE = 0;
 | 
						||
  *pALE = (uint8_t)((addr & 0x00FF));
 | 
						||
  *pALE = (uint8_t)((addr & 0xFF00) >> 8);
 | 
						||
  *pCLE = K9FXX_READ_2;
 | 
						||
 | 
						||
  WAIT_READY(); 
 | 
						||
  
 | 
						||
 | 
						||
  for (i = 0; i < pageSize; i++) {
 | 
						||
    *pageBuf++ = *pData;  
 | 
						||
  }
 | 
						||
 | 
						||
 | 
						||
  return TRUE;
 | 
						||
}
 | 
						||
 | 
						||
/******************************************************************************
 | 
						||
 *
 | 
						||
 * Description:
 | 
						||
 *    Write a page of data to the NAND memory
 | 
						||
 *
 | 
						||
 * Params:
 | 
						||
 *    block - block number to write to
 | 
						||
 *    page  - page within block to write to
 | 
						||
 *    pageBuf - data is copied from this buffer. The size must be at least 
 | 
						||
 *              pageSize.
 | 
						||
 *
 | 
						||
 * Returns:
 | 
						||
 *    TRUE if write successful; otherwise FALSE
 | 
						||
 *
 | 
						||
 *****************************************************************************/
 | 
						||
uint32_t nand_writePage(uint32_t block, uint32_t page, uint8_t* pageBuf)
 | 
						||
{
 | 
						||
  uint32_t i = 0;
 | 
						||
  uint32_t addr = 0;
 | 
						||
 | 
						||
  volatile uint8_t *pCLE;
 | 
						||
  volatile uint8_t *pALE;
 | 
						||
  volatile uint8_t *pData;
 | 
						||
 | 
						||
  
 | 
						||
  pCLE  = K9F1G_CLE;
 | 
						||
  pALE  = K9F1G_ALE;
 | 
						||
  pData = K9F1G_DATA;
 | 
						||
 | 
						||
  if (block >= NAND_NUM_BLOCKS) {
 | 
						||
    return FALSE;
 | 
						||
  }
 | 
						||
 | 
						||
  if (page >= blockSize/pageSize) {
 | 
						||
    return FALSE;
 | 
						||
  }
 | 
						||
 | 
						||
  addr = block * (blockSize/pageSize) + page;
 | 
						||
 | 
						||
  /*
 | 
						||
   * Always writing to start of a page address.
 | 
						||
   * This means that the column address is always 0.
 | 
						||
   */ 
 | 
						||
 | 
						||
  *pCLE = K9FXX_BLOCK_PROGRAM_1;
 | 
						||
  *pALE = 0; 
 | 
						||
  *pALE = 0; 
 | 
						||
  *pALE = (uint8_t)((addr & 0x00FF));
 | 
						||
  *pALE = (uint8_t)((addr & 0xFF00) >> 8);
 | 
						||
 | 
						||
 | 
						||
  for (i = 0; i < pageSize; i++) {
 | 
						||
    *pData = *pageBuf++;
 | 
						||
  }
 | 
						||
 | 
						||
  *pCLE = K9FXX_BLOCK_PROGRAM_2;
 | 
						||
 | 
						||
  TIM_Waitus(700);  
 | 
						||
  nandWaitReady();
 | 
						||
  
 | 
						||
  return ((nandStatus() & 0x01) != 0x01); 
 | 
						||
}
 | 
						||
 | 
						||
/******************************************************************************
 | 
						||
 *
 | 
						||
 * Description:
 | 
						||
 *    Erase a block
 | 
						||
 *
 | 
						||
 * Params:
 | 
						||
 *    block - block number to erase
 | 
						||
 *
 | 
						||
 * Returns:
 | 
						||
 *    TRUE if eras successful; otherwise FALSE
 | 
						||
 *
 | 
						||
 *****************************************************************************/
 | 
						||
uint32_t nand_eraseBlock(uint32_t block)
 | 
						||
{
 | 
						||
  uint32_t addr = 0;
 | 
						||
 | 
						||
  volatile uint8_t *pCLE;
 | 
						||
  volatile uint8_t *pALE;
 | 
						||
 | 
						||
  pCLE  = K9F1G_CLE;
 | 
						||
  pALE  = K9F1G_ALE;
 | 
						||
 | 
						||
  if (block >= NAND_NUM_BLOCKS) {
 | 
						||
    return FALSE;
 | 
						||
  }
 | 
						||
    
 | 
						||
  addr = block * (blockSize/pageSize);
 | 
						||
 | 
						||
  *pCLE = K9FXX_BLOCK_ERASE_1;
 | 
						||
  *pALE = (uint8_t)(addr & 0x00FF);
 | 
						||
  *pALE = (uint8_t)((addr & 0xFF00) >> 8);
 | 
						||
  *pCLE = K9FXX_BLOCK_ERASE_2;
 | 
						||
 | 
						||
  TIM_Waitus(700);
 | 
						||
  nandWaitReady();
 | 
						||
 | 
						||
  return ((nandStatus() & 0x01) != 0x01); 
 | 
						||
}
 | 
						||
 | 
						||
#endif
 |