| 
									
										
										
										
											2018-03-02 13:41:35 +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 | 
					
						
							|  |  |  |  |  *****************************************************************************/ | 
					
						
							| 
									
										
										
										
											2018-03-02 14:53:40 +07:00
										 |  |  |  | #include "../board.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-02 13:41:35 +07:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | #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<EFBFBD>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
 |