2013-11-05 13:02:15 +07:00
|
|
|
|
/*****************************************************************************
|
|
|
|
|
*
|
|
|
|
|
* 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
|
|
|
|
|
*****************************************************************************/
|
2013-12-11 12:13:22 +07:00
|
|
|
|
#include "../../board.h"
|
|
|
|
|
|
|
|
|
|
#if BOARD == BOARD_EA4357
|
2013-11-05 13:02:15 +07:00
|
|
|
|
|
|
|
|
|
#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
|
2013-12-11 12:13:22 +07:00
|
|
|
|
* page - page with<EFBFBD>n block to read from
|
2013-11-05 13:02:15 +07:00
|
|
|
|
* 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);
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-11 12:13:22 +07:00
|
|
|
|
#endif
|