stm32 fsmc nand 硬件ecc 错误 问题

2019-03-23 19:08发布

本人在初始化STM32 --- NAND(K9F1208U0B)的时候,在产生硬件ecc时候 一直错误,非常费解,求各位高人指点······谢谢!代码大略如下:
void FSMC_NAND_INIT(void)
{
      /*-- FSMC Configuration ------------------------------------------------------*/
     p.FSMC_SetupTime = 0x1;
     p.FSMC_WaitSetupTime = 0x3;
     p.FSMC_HoldSetupTime = 0x2;
     p.FSMC_HiZSetupTime = 0x1;
    FSMC_NANDInitStructure.FSMC_Bank = FSMC_Bank3_NAND;
   FSMC_NANDInitStructure.FSMC_Waitfeature = FSMC_Waitfeature_Enable;
   FSMC_NANDInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_8b;
   FSMC_NANDInitStructure.FSMC_ECC = FSMC_ECC_Enable;
   FSMC_NANDInitStructure.FSMC_ECCPageSize = FSMC_ECCPageSize_512Bytes;
   FSMC_NANDInitStructure.FSMC_TCLRSetupTime = 0x00;
   FSMC_NANDInitStructure.FSMC_TARSetupTime = 0x00;
   FSMC_NANDInitStructure.FSMC_CommonSpaceTimingStruct = &p;
   FSMC_NANDInitStructure.FSMC_AttributeSpaceTimingStruct = &p;
    FSMC_NANDInit(&FSMC_NANDInitStructure);
   FSMC_NANDCmd(FSMC_Bank3_NAND, ENABLE);
   FSMC_NANDECCCMD(FSMC_Bank3_NAND,ENABLE);

}
  
volatile u32 mecc,mecc1;
然后在测试程序里是:
void nwrite_t (u16 PAGE)
{
/*  前边是一大堆 定义和初始化的东西*/
     u32   STATUS_WRITE;
    u32  NumPageToWrite = 1;
    u8 *p_write;
     u8  a[512];      
      
     NAND_ADDRESS  write_address;
      write_address.page = PAGE;
      write_address.block = 0;   ////由于测试程序,所以我就只是读写在第一块,所以这2个都赋值0.
      write_address.zone = 0;   /////  
        a[512]  =  {  ////***   该数组是512个随机数字 ,太长了,所以省略了,请见谅 **////////};
       p_write= a ;   //

    FSMC_NAND_INIT();
    FSMC_NANDECCCMD(FSMC_Bank3_NAND,DISABLE);  
    FSMC_NANDECCCMD(FSMC_Bank3_NAND,ENABLE);
     STATUS_WRITE= NAND_WriteSmallPage( p_write, write_address, NumPageToWrite);   ///  返回值为 0x00000140;
     while ( FSMC_GetFlagStatus (FSMC_Bank3_NAND , FSMC_FLAG_FEMPT)  == RESET  );
      mecc = FSMC_GetECC ( FSMC_Bank3_NAND );
      printf("mecc:%x ",mecc);   
     FSMC_NANDECCCMD(FSMC_Bank3_NAND,DISABLE);  
}

void nread_t (u16 page)
{
/*  前边是一大堆 定义和初始化的东西*/
     u32 mecc;
     u32   STATUS_READ;
    u32  NumPageToRead = 1;
    u8 *p_read;
     u8  b[512];   

     NAND_ADDRESS  read_address;
      read_address.page = PAGE;
      read_address.block = 0;   ////由于测试程序,所以我就只是读写在第一块,所以这2个都赋值0.
      read_address.zone = 0;   /////  
       p_read = b ;   //

    FSMC_NAND_INIT();
    FSMC_NANDECCCMD(FSMC_Bank3_NAND,DISABLE);  
    FSMC_NANDECCCMD(FSMC_Bank3_NAND,ENABLE);
     STATUS_READ = NAND_ReadSmallPage( p_read, read_address, NumPageToRead);   ///  返回值为 0x00000140
     while ( FSMC_GetFlagStatus (FSMC_Bank3_NAND , FSMC_FLAG_FEMPT)  == RESET  );///  等待标志位
       mecc1= FSMC_GetECC ( FSMC_Bank3_NAND );  /// 获取ecc
      printf("mecc:%x ",mecc);   
     FSMC_NANDECCCMD(FSMC_Bank3_NAND,DISABLE);  
}
第一块已经成功擦除,读出全为 FF ;然后在第一页写入,再读出,
结果我打印出来的mecc 是32位的数,读与写的mecc结果是一样的。按STM32 pdf的资料应该是 一个24位的数才对,所以该32位数毫无疑问是错误的。是否哪里设置错误,或者漏设置了,所以对此非常费解,卡了好几天都没有搞定。求各位高人指点迷津啊······ 此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
2条回答
libinglibo
2019-03-24 05:03
手册里说:当规定数目的字节已经写入NAND 闪存或从NAND 闪存读出,软件必须读出FSMC_ECCR2/3 寄存器以获得计算的ECC数值。读出ECC数值后,再次计算ECC时需要通过先置ECCEN为’0’ 清除这个寄存器,再在FSMC_PCR2/3 寄存器的ECCEN位写’1’ 重新使能ECC计算。
必须是写入或读取一定的字节数以后立刻进行ECC值读取,因此ECC值的读取应在写入或读取函数里。因大家的源码都是从ST官方源码简化来的,所以废话不多说,值给你看几个关键性的语句,你就明白了。这是写一页的函数,主要看读取ECC值和复位的位置。
/* Page write command and address */
    *(vu8 *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_PAGEPROGRAM;
    *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = 0x00;  
    *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = 0X00;  
    *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS);  
    *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS);   
    /* Calculate the size */
    size = NAND_PAGE_SIZE;
    /* Write data */
    size=2048;
    for(index=0; index < size; index++)
    {
       *(vu8 *)(Bank_NAND_ADDR | DATA_AREA) = pBuffer[index];  
    }
ecclb=FSMC_GetECC(FSMC_Bank2_NAND);
printf(" EccVal2 is 0x%x ", ecclb);
//复位ECC
FSMC_NANDECCCmd(FSMC_Bank2_NAND, DISABLE);
FSMC_NANDECCCmd(FSMC_Bank2_NAND, ENABLE);   
  
    *(vu8 *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_PAGEPROGRAM_TRUE;
    while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );

一周热门 更多>