2/16/2015

NAND BBM(Bad Block Management)

1. NAND의 Block의 상태 

  • NAND Block의 상태종류 
  1. 1st block : Chip Vendor는 1st Block은 Bad Block이 되지 않게 유지해줌  
  2. Factory-Default bad blocks:  Chip Vendor는 Block 의 1st or 2nd Page의 OOB 정보표시 
  3. Worn-out bad blocks : NAND 를 Erase or Write할 경우 BAD Block이 발생한 경우  
  4. Good blocks : 현재 좋은 상태의 Block 

  • Factory-Default Bad Block
    공장 초기에 제공해주는 Bad Block 정보이며, Chip Vendor 마다
    다를 수 있으므로 Datasheet를 참고 해야한다.

     - Samsung 인경우,
         각 Block의  1st or 2nd page의 6th OOB의 값이 0xFF 아닐 경우, BAD
   
이 정보는 Large page or Small page, bus width 에 따라 달라질 수 있다.
(Chip vendor 정보 반드시 참고)  
아래 link에 macronix를 정보를 소개.
이 정보를 BBI ( Bad block indication ) 라고도 호칭하기도 한다.


  • 1st Block
Chip Vendor마다 다르겠지만, 보통 ECC도 필요가 없으며, Nand 회사에서 보증하는 Block으로
약 1000 write 까지보증한다고 한다, 이부분도 각각의 Datasheet를 참고를 해야겠다.
하지만, 보통 1st Block에서 문제생기는 일은 거의 없기에 구지 자세히 알필요까지는 없을 것 같다.

  • Worn-out bad blocks 
보통 Write 제한이 있기에, 이를 초과 했을 경우, bad block이 발생. or
사용도중 Program or Erase 도중 fail 이나서 STATUS를 읽어서 ERROR 읽어 경우도
Bad block으로 처리한다.

1.2 NAND의 Bad Block 숙지사항 

UBOOT기준으로 설명을 하면, 이전 Version에는 아래의 사이트 처럼 U-Boot 에서
Bad Block을 만들어주는 Command가 존재했지만, 최신 Version으로 가면 없어진다.

NAND처리는 지속적으로 변화고 있으며,  본인의 BSP 를 비롯하여, U-BOOT, Kernel의
MTD관련부분을 어느정도 정확하게 알아야 동작원리를 알아야 겠다.

기본적인 BBT(Bad Block Table) 원리와 BBM(Bad Block Management) 부분을 정확하게
알아야 나중에 에러가 발생을 하여도 문제진단이 빠를 것 같다.

  • U-BOOT의 NAND관련 Command (오래된 Version) 
  http://wiki.openmoko.org/wiki/NAND_bad_blocks



  • U-BOOT의 NAND관련 Command 

  https://www.denx.de/wiki/DULG/UBootCmdGroupNand


1.3 BSP의 NAND의 구성 


  • AM35x-OMAP35x 관련 내용 
TI의 AM35x와 OMAP3관련 NAND 설정 및 이에 관련내용들이며, UBOOT에서 nanecc 라는 ECC설정가능명령도 존재한다.

  http://processors.wiki.ti.com/index.php/AM35x-OMAP35x-PSP_04.02.00.07_UserGuide



  • i.M28과 BBT와 BBI설명 
아래 문서를 읽어보면,  I.MX28 NAND 구성은 재미있는 것 같다.
2K page 64 OOB 구성을 512+16 매번 쪼깨서 사용하며, 이것은 정말 신선하게 느껴졌다.
매번 느끼는 것이지만, Bad block 의 관리와 NAND관리는 MPU와도 밀접한 것 같다.


  Freescale-i.MX28-MCIMX281AVM4B-Learning Centre MCU-Application Notes-Freescale.Application_Notes_5.pdf

  https://www.element14.com/community/docs/DOC-31589/l/freescale-application-note-for-nand-flash-bad-block-management-for-linux-bsp





2. Linux의 NAND BBM(Bad Block Management) 


2.1 Bad Block Table 생성 

Bad Block Table은 2bit 정보로 각 Block을 관리하며, 보통은 BBT은 2개의 Block을 사용을 하며, 하나는 Back-up용으로 생각하면 된다.

MPU-Nand Driver에서  static struct nand_bbt_descr을 선언하여 사용.
기본적 Last 2 Block or 1st Block을 사용하며, 아래와 같은 가지고 사용을 한다.

Nand에서 사용하는 BBT 
 * The table uses 2 bits per block
 * 11b:     block is good
 * 00b:     block is factory marked bad
 * 01b, 10b:    block is marked bad due to wear

Memory에서 사용하는 임시 BBT
 * The memory bad block table uses the following scheme:
 * 00b:     block is good
 * 01b:     block is marked bad due to wear
 * 10b:     block is reserved (to protect the bbt area)
 * 11b:     block is factory marked bad


Bad block table
  http://www.linux-mtd.infradead.org/tech/mtdnand/x144.html

  • BBT의 생성되는 Flowchart
초기에 U-Boot에서 한번 하며, 아래와 같이 공장 초기 값을 이용하여 만든다.
Factory-Default  bad block 정보이용하여  Bad block Table에 만드는 방법
현재 Linux BBT 역시 이와 같은 방식으로 동작하지만, 옵션에 따라 미세하게 다르게 동작.


http://bbs.ednchina.com/FORUM_POST_17_89328_0.HTM
  http://www.macronix.com/Lists/ApplicationNote/Attachments/729/AN0278V1%20-%20BB%20information%20introduction.pdf
  https://www.micron.com/resource-details/8e059ff2-fb4f-4e05-974c-e205226d2318


3. U-BOOT 와 Kernel BBT 분석 

Uboot 와 Kernel은 NAND를 사용시에는 BBT를 사용하며, 이에 관련된 부분을 알아보자. 

  • U-BOOT
U-BOOT NAND Bad Block Table 관련부분

 $ vi ./drivers/mtd/nand/davinci_nand.c

void davinci_nand_init(struct nand_chip *nand)
{
        nand->chip_delay  = 0;
#ifdef CONFIG_SYS_NAND_USE_FLASH_BBT
        nand->bbt_options         |= NAND_BBT_USE_FLASH;
#endif
#ifdef CONFIG_SYS_NAND_NO_SUBPAGE_WRITE
        nand->options     |= NAND_NO_SUBPAGE_WRITE;
#endif
#ifdef CONFIG_SYS_NAND_HW_ECC
        nand->ecc.mode = NAND_ECC_HW;
        nand->ecc.size = 512;
        nand->ecc.bytes = 3;
        nand->ecc.strength = 1;
        nand->ecc.calculate = nand_davinci_calculate_ecc;
        nand->ecc.correct  = nand_davinci_correct_data;
        nand->ecc.hwctl  = nand_davinci_enable_hwecc;
#else
        nand->ecc.mode = NAND_ECC_SOFT;
#endif /* CONFIG_SYS_NAND_HW_ECC */
#ifdef CONFIG_SYS_NAND_4BIT_HW_ECC_OOBFIRST
        nand->ecc.mode = NAND_ECC_HW_OOB_FIRST;
        nand->ecc.size = 512;
        nand->ecc.bytes = 10;
        nand->ecc.strength = 4;
        nand->ecc.calculate = nand_davinci_4bit_calculate_ecc;
        nand->ecc.correct = nand_davinci_4bit_correct_data;
        nand->ecc.hwctl = nand_davinci_4bit_enable_hwecc;
        nand->ecc.layout = &nand_davinci_4bit_layout_oobfirst;
#endif

$ vi ./drivers/mtd/nand/nand_bbt.c
nand_default_bbt
    -> 1.bbt_main_descr,bbt_mirror_descr  //NAND_BBT_USE_FLASH 때문에 default BBT옵션설정 
    -> 2.nand_scan_bbt 
           -> check_create
                 -> create_bbt
                      ->  scan_block_full or scan_block_fast

$ vi ./include/linux/mtd/bbm.h  // BBT 관련옵션 확인 


  • bbt_md(bbt_mirror_descr) or bbt_td(bbt_main_descr) 설정분석 
  1. NAND_BBT_LASTBLOCK :  NAND 마지막 Block BBT 존재여부 확인 
  2. NAND_BBT_CREATE      :  NAND BBT가 없다면 생성  
  3. NAND_BBT_WRITE       :  NAND BBT에 WRITE 가능   
  4. NAND_BBT_2BIT          :  각 Bblock 당 정보를 2bit식 할당 
  5. NAND_BBT_VERSION   :   BBT Version 정보 표시  
  6. NAND_BBT_PERCHIP    :   NAND Chip 마다 BBT 생성 


$ vi ./drivers/mtd/nand/nand_bbt.c

/* Generic flash bbt descriptors */
static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };

static struct nand_bbt_descr bbt_main_descr = {
        .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
                | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,

        .offs = 8,  //offset of the pattern in the oob area of the page
        .len = 4,   //length of the pattern
        .veroffs = 12,  //offset of the bbt version counter in the oob are of the page
        .maxblocks = NAND_BBT_SCAN_MAXBLOCKS, //maximum number of blocks to search for a bbt
        .pattern = bbt_pattern      //pattern to identify bad block table or factory marked
};

static struct nand_bbt_descr bbt_mirror_descr = {
        .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
                | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
        .offs = 8,
        .len = 4,
        .veroffs = 12,
        .maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
        .pattern = mirror_pattern
};

static struct nand_bbt_descr bbt_main_no_oob_descr = {
        .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
                | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP
                | NAND_BBT_NO_OOB,
        .len = 4,
        .veroffs = 4,
        .maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
        .pattern = bbt_pattern
};

static struct nand_bbt_descr bbt_mirror_no_oob_descr = {
        .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
                | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP
                | NAND_BBT_NO_OOB,
        .len = 4,
        .veroffs = 4,
        .maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
        .pattern = mirror_pattern
};


  • Kernel Source

  http://lxr.free-electrons.com/source/drivers/mtd/nand/Makefile

  nand-objs := nand_base.o nand_bbt.o nand_timings.o

  http://lxr.free-electrons.com/source/drivers/mtd/nand/nand_bbt.c

  • drivers/mtd/nand/nand_bbt.c

           nand_scan_bbt
Search
-> check_create
                     -> mark_bbt_region
->nand_update_bbt

               * check_create
                        read_abs_bbt
                                   read_bbt


  http://lxr.free-electrons.com/source/drivers/mtd/nand/nand_base.c
  • drivers/mtd/nand/nand_base.c

        /* Fill in remaining MTD driver data */
         mtd->type = nand_is_slc(chip) ? MTD_NANDFLASH : MTD_MLCNANDFLASH;
         mtd->flags = (chip->options & NAND_ROM) ? MTD_CAP_ROM :
                                                 MTD_CAP_NANDFLASH;
         mtd->_erase = nand_erase;
         mtd->_point = NULL;
         mtd->_unpoint = NULL;
         mtd->_read = nand_read;
         mtd->_write = nand_write;
         mtd->_panic_write = panic_nand_write;
         mtd->_read_oob = nand_read_oob;
         mtd->_write_oob = nand_write_oob;
         mtd->_sync = nand_sync;
         mtd->_lock = NULL;
         mtd->_unlock = NULL;
         mtd->_suspend = nand_suspend;
         mtd->_resume = nand_resume;
         mtd->_reboot = nand_shutdown;
         mtd->_block_isreserved = nand_block_isreserved;
         mtd->_block_isbad = nand_block_isbad;
         mtd->_block_markbad = nand_block_markbad;
         mtd->writebufsize = mtd->writesize;


           nand_block_markbad
                -> nand_block_markbad_lowlevel
                         -> nand_markbad_bbt



  http://lxr.free-electrons.com/source/drivers/mtd/mtdcore.c

  • drivers/mtd/mtdcore.c

           mtd_block_isbad
              -> mtd->_block_isbad

           mtd_block_markbad
              -> mtd->_block_markbad


  http://lxr.free-electrons.com/source/drivers/mtd/nand/davinci_nand.c

댓글 2개 :

floor rugs Adelaide :
블로그 관리자가 댓글을 삭제했습니다.
Iftikhar Khan :

https://servicechargesorted.co.uk/blogs/responsibilities-of-a-director-of-a-freehold-management-company