[求助]关于STM32F429挂接nandflash的问题

2019-07-20 20:16发布

我用的是stm32f429igt6,挂接了K9F1G08U0D,用同样的驱动,在裸跑读写测试程序时没有问题,但是当我上了RTThread操作系统后,测试程序就不可用了,而且读id也错误,都是返回0


请问这种情况是什么原因?有没有哪位大神用过的帮忙指点一下,多谢!

附驱动及测试程序:
/* nand bank configure */
#define FMC_NAND_BANK  FMC_Bank2_NAND
#define NAND_BANK     ((uint32_t)0x70000000)

#define NAND_LARGE    0 /* k9f1g08 0;  k9f2g08: 1 */

#define ECC_SIZE     4

void nand_cmd(uint8_t cmd)
{
    /* write to CMD area */
    *(volatile uint8_t*)(NAND_BANK | CMD_AREA) = cmd;
}

void nand_addr(uint8_t addr)
{
    /* write to address area */
    *(volatile uint8_t*)(NAND_BANK | ADDR_AREA) = addr;
}

uint8_t nand_read8(void)
{
    /* read 1Byte */
    return (*(volatile uint8_t*)(NAND_BANK | DATA_AREA));
}

void nand_write8(uint8_t data)
{
    /* write 1Byte */
    *(volatile uint8_t*)(NAND_BANK | DATA_AREA) = data;
}

void nand_waitready(void)
{
    while (GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0);
}

static uint8_t nand_readstatus(void)
{
    nand_cmd(NAND_CMD_STATUS);
    return (nand_read8());
}

static uint32_t nand_datacorrect(uint32_t generatedEcc, uint32_t readEcc, uint8_t *data)
{
#define ECC_MASK28    0x0FFFFFFF          /* 28 valid ECC parity bits. */
#define ECC_MASK      0x05555555          /* 14 ECC parity bits.       */

    uint32_t count, bitNum, byteAddr;
    uint32_t mask;
    uint32_t syndrome;
    uint32_t eccP;                            /* 14 even ECC parity bits. */
    uint32_t eccPn;                           /* 14 odd ECC parity bits.  */

    syndrome = (generatedEcc ^ readEcc) & ECC_MASK28;

    if (syndrome == 0)
        return (0);                  /* No errors in data. */

    eccPn = syndrome & ECC_MASK;              /* Get 14 odd parity bits.  */
    eccP  = (syndrome >> 1) & ECC_MASK;       /* Get 14 even parity bits. */

    if ((eccPn ^ eccP) == ECC_MASK)           /* 1-bit correctable error ? */
    {
        bitNum = (eccP & 0x01) |
                 ((eccP >> 1) & 0x02) |
                 ((eccP >> 2) & 0x04);
        byteAddr = ((eccP >> 6) & 0x001) |
                   ((eccP >> 7) & 0x002) |
                   ((eccP >> 8) & 0x004) |
                   ((eccP >> 9) & 0x008) |
                   ((eccP >> 10) & 0x010) |
                   ((eccP >> 11) & 0x020) |
                   ((eccP >> 12) & 0x040) |
                   ((eccP >> 13) & 0x080) |
                   ((eccP >> 14) & 0x100) |
                   ((eccP >> 15) & 0x200) |
                   ((eccP >> 16) & 0x400) ;

        data[ byteAddr ] ^= 1 << bitNum;

        return 0;
    }

    /* Count number of one's in the syndrome. */
    count = 0;
    mask  = 0x00800000;
    while (mask)
    {
        if (syndrome & mask)
            count++;
        mask >>= 1;
    }

    if (count == 1)           /* Error in the ECC itself. */
        return 0;

    return 1;       /* Unable to correct data. */

#undef ECC_MASK
#undef ECC_MASK24
}

static void fsmc_nandflash_init(void)
{
    FMC_NANDInitTypeDef FMC_NANDInitStructure;
    FMC_NAND_PCCARDTimingInitTypeDef p;

    RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FMC, ENABLE);

    p.FMC_SetupTime     = 0x1;
    p.FMC_WaitSetupTime = 0x3;
    p.FMC_HoldSetupTime = 0x2;
    p.FMC_HiZSetupTime  = 0x1;

    FMC_NANDInitStructure.FMC_Bank = FMC_NAND_BANK;
    FMC_NANDInitStructure.FMC_Waitfeature = FMC_Waitfeature_Disable;
    FMC_NANDInitStructure.FMC_MemoryDataWidth = FMC_NAND_MemoryDataWidth_8b;
    FMC_NANDInitStructure.FMC_ECC = FMC_ECC_Disable;/* 先不要开启ECC计算 */
    FMC_NANDInitStructure.FMC_ECCPageSize = FMC_ECCPageSize_2048Bytes;
    FMC_NANDInitStructure.FMC_TCLRSetupTime = 0x00;
    FMC_NANDInitStructure.FMC_TARSetupTime = 0x00;
    FMC_NANDInitStructure.FMC_CommonSpaceTimingStruct = &p;
    FMC_NANDInitStructure.FMC_AttributeSpaceTimingStruct = &p;

    FMC_NANDInit(&FMC_NANDInitStructure);

    /* FMC NAND Bank Cmd Test */
    FMC_NANDCmd(FMC_NAND_BANK, ENABLE);
}



uint32_t nandflash_readpage(uint32_t page,
                                   uint8_t *data, uint32_t data_len,
                                   uint8_t *spare, uint32_t spare_len)
{
    uint32_t index;
    uint32_t gecc, recc;
    uint8_t tmp[8];
    uint32_t result;

    if (data && data_len)
    {
        nand_cmd(NAND_CMD_READ_1);

        nand_addr(0);
        nand_addr(0);
        nand_addr(page);
        nand_addr(page >> 8);
#if NAND_LARGE
        nand_addr(page >> 16);
#endif
        nand_cmd(NAND_CMD_READ_TRUE);
        nand_waitready();
        FMC_NANDECCCmd(FMC_NAND_BANK,ENABLE);
        for (index = 0; index < data_len; index ++)
        {
            data[index] = nand_read8();
        }
        gecc = FMC_GetECC(FMC_NAND_BANK);
        FMC_NANDECCCmd(FMC_NAND_BANK,DISABLE);

        if (data_len == 2048)
        {
            for (index = 0; index < ECC_SIZE; index ++)
                tmp[index] = nand_read8();
            if (spare && spare_len)
            {
                for (index = 0; index < spare_len-ECC_SIZE; index ++)
                    spare[ECC_SIZE + index] = nand_read8();

                spare_len = 0;

                memcpy(spare, tmp , ECC_SIZE);
            }

            recc   = (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0];

            if (nand_datacorrect(gecc, recc, data) != 0)
                result = 0;
            else
                result = 0;

            goto _exit;
        }

        result = 0;
    }

    if (spare && spare_len)
    {
        nand_cmd(NAND_CMD_READ_1);

        nand_addr(0);
        nand_addr(8);
        nand_addr(page);
        nand_addr(page >> 8);
#if NAND_LARGE
        nand_addr(page >> 16);
#endif

        nand_cmd(NAND_CMD_READ_TRUE);
        nand_waitready();

        for (index = 0; index < spare_len; index ++)
        {
            spare[index] = nand_read8();
        }

        result = 0;
    }
_exit:

    return (result);
}

uint32_t nandflash_writepage(uint32_t page,
                                    const uint8_t *data, uint32_t data_len,
                                    const uint8_t *spare, uint32_t spare_len)
{
    uint32_t index;
    uint32_t result;
    uint32_t gecc;

    if (data && data_len)
    {
        nand_cmd(NAND_CMD_PAGEPROGRAM);

        nand_addr(0);
        nand_addr(0);
        nand_addr(page);
        nand_addr(page >> 8);
#if NAND_LARGE
        nand_addr(page >> 16);
#endif

        FMC_NANDECCCmd(FMC_NAND_BANK,ENABLE);
        for (index = 0; index < data_len; index ++)
        {
            nand_write8(data[index]);
        }
        gecc = FMC_GetECC(FMC_NAND_BANK);
        FMC_NANDECCCmd(FMC_NAND_BANK,DISABLE);

        NAND_DEBUG("<wecc %X>",gecc);
        if (data_len == 2048)
        {
            nand_write8((uint8_t)gecc);
            nand_write8((uint8_t)(gecc >> 8));
            nand_write8((uint8_t)(gecc >> 16));
            nand_write8((uint8_t)(gecc >> 24));
        }

        nand_cmd(NAND_CMD_PAGEPROGRAM_TRUE);
        nand_waitready();

        if ((nand_readstatus() & 0x01) == 1)
        {
            result = 0;
            goto _exit;
        }
        else
        {
            result = 0;
        }
    }

    if (spare && spare_len)
    {
        nand_cmd(NAND_CMD_PAGEPROGRAM);

        nand_addr(ECC_SIZE);
        nand_addr(0x08);
        nand_addr(page);
        nand_addr(page >> 8);
#if NAND_LARGE
        nand_addr(page >> 16);
#endif
        for (index = 0; index < spare_len-ECC_SIZE; index ++)
        {
            nand_write8(spare[ECC_SIZE+index]);
        }

        nand_cmd(NAND_CMD_PAGEPROGRAM_TRUE);
        nand_waitready();

        if ((nand_readstatus() & 0x01) == 1)
            result = 0;
        else
            result = 0;
    }

_exit:

    return (result);
}

uint32_t nandflash_eraseblock(uint32_t block)
{
    uint32_t page;
    uint32_t result;

    result = 0;
    page = block * 64;

    nand_cmd(NAND_CMD_ERASE0);

    nand_addr(page);
    nand_addr(page >> 8);
#if NAND_LARGE
    nand_addr(page >> 16);
#endif

    nand_cmd(NAND_CMD_ERASE1);

    nand_waitready();

    if ((nand_readstatus() & 0x01) == 1)
        result = 0;

    return (result);
}

static uint32_t nandflash_pagecopy( uint32_t src_page, uint32_t dst_page)
{
    uint32_t result;


    nand_cmd(NAND_CMD_RDCOPYBACK);

    nand_addr(0);
    nand_addr(0);
    nand_addr(src_page);
    nand_addr(src_page >> 8);
#if NAND_LARGE
    nand_addr(src_page >> 16);
#endif


    nand_cmd(NAND_CMD_RDCOPYBACK_TRUE);

    nand_waitready();

    nand_cmd(NAND_CMD_COPYBACKPGM);

    nand_addr(0);
    nand_addr(0);
    nand_addr(dst_page);
    nand_addr(dst_page >> 8);
#if NAND_LARGE
    nand_addr(dst_page >> 16);
#endif

    nand_cmd(NAND_CMD_COPYBACKPGM_TRUE);

    nand_waitready();
    if ((nand_readstatus() & 0x01) == 0x01)
        result = 0;

    return (result);
}




uint8_t TxBuffer[NAND_PAGE_SIZE];
uint8_t RxBuffer[NAND_PAGE_SIZE];
uint8_t TxSpare[64];
uint8_t RxSpare[64];

void nread(int page)
{
    int index;

    memset(RxBuffer, 0, NAND_PAGE_SIZE);
    memset(RxSpare, 0, 64);

    nandflash_readpage(page,RxBuffer, NAND_PAGE_SIZE,RxSpare,64);

    printf("data: ");
    for (index = 0; index < NAND_PAGE_SIZE; index ++)
    {
        printf("%02X,",RxBuffer[index]);
        if ((index+1) % 16 == 0)
            printf(" ");
    }

    printf(" spare: ");
    for (index = 0; index < 64; index ++)
    {
        printf("[%02X]", RxSpare[index]);
        if ((index+1) % 16 == 0)
        printf(" ");
    }
    printf(" ");
}

void nerase(int block)
{
    nandflash_eraseblock(block);
}

void nwrite(int page)
{
    memset(TxBuffer, 0xAA, NAND_PAGE_SIZE);
    memset(TxSpare, 0x55, 64);
#if 0
    {
        int i;
        for (i = 0; i < 2048; i ++)
            TxBuffer[i] = i/5 - i;
    }
#endif
    nandflash_writepage(page,TxBuffer,NAND_PAGE_SIZE, TxSpare, 64);
}

void fmc_gpio_init(void)
{
    /* 定义GPIO初始化结构体 */
    GPIO_InitTypeDef GPIO_InitStructure;
    /*
    ****************************************************************************
    * PD14 --> D0      | PD4  --> NAND_NOE
    * PD15 --> D1      | PD5  --> NAND_NWE
    * PD0  --> D2      | PG6  --> NAND_INT2
    * PD1  --> D3      | PD7  --> NAND_NCE2
    * PE7  --> D4      | PD11 --> NAND_CLE
    * PE8  --> D5      | PD12 --> NAND_ALE
    * PE9  --> D6      |
    * PE10 --> D7      |
    ****************************************************************************
    */
    /* 使能GPIO时钟 */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOG, ENABLE);
    /* Enable FMC clock */
    RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FMC, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

    /* 设置GPIO mode、speed、otype、pupd */
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;

    GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource4, GPIO_AF_FMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_FMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource7, GPIO_AF_FMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource11, GPIO_AF_FMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_FMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_FMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_FMC);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4
        | GPIO_Pin_5 | GPIO_Pin_7 | GPIO_Pin_11 | GPIO_Pin_12
        | GPIO_Pin_14 | GPIO_Pin_15;
    GPIO_Init(GPIOD, &GPIO_InitStructure);


    GPIO_PinAFConfig(GPIOE, GPIO_PinSource7, GPIO_AF_FMC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource8, GPIO_AF_FMC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource9, GPIO_AF_FMC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource10, GPIO_AF_FMC);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 |GPIO_Pin_8 |GPIO_Pin_9 |GPIO_Pin_10;
    GPIO_Init(GPIOE, &GPIO_InitStructure);

#if 1
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_Init(GPIOG, &GPIO_InitStructure);   
#else
    GPIO_PinAFConfig(GPIOG, GPIO_PinSource6, GPIO_AF_FMC);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_Init(GPIOG, &GPIO_InitStructure);
#endif
}

void nandTest(void)
{
    unsigned int i;
    nerase(0);
    for(i=0;i<655360;i++);
    nwrite(3);
    for(i=0;i<655360;i++);
    nread(3);
    for(i=0;i<655360;i++);
}

void FMC_NAND_Init(void)
{
    fmc_gpio_init();
    fsmc_nandflash_init();
}

static struct nand_id nand_table[] =
{
    {{0xEC, 0xF1, 0x80, 0x15}, "K9F1G08U0A"},
    {{0xEC, 0xF1, 0x00, 0x95}, "K9F1G08U0B"},
    {{0xEC, 0xAA, 0x00, 0x15}, "K9F2G08R0A"},
    {{0xEC, 0xF1, 0x00, 0x15}, "K9F1G08U0D"},
    {{0xAD, 0xF1, 0x80, 0x1D}, "HY27UF081G2A"},

    {{0x0, 0x0, 0x0, 0x0}, "end"},
};
static struct stm32_nand _device;

int nandflash_readid(void)
{
    int i;

    nand_cmd(NAND_CMD_READID);
    nand_addr(0);

    _device.id[0] = nand_read8();
    _device.id[1] = nand_read8();
    _device.id[2] = nand_read8();
    _device.id[3] = nand_read8();
    //_device.id[4] = nand_read8();
    //printf("ID[%X,%X,%X,%X,%X] ",_device.id[0], _device.id[1], _device.id[2], _device.id[3], _device.id[4]);
    printf("ID[%X,%X,%X,%X] ",_device.id[0], _device.id[1], _device.id[2], _device.id[3]);
    for (i=0; nand_table[i].id[0] != 0; i++)
    {
        if((_device.id[0] == nand_table[i].id[0])
            && (_device.id[1] == nand_table[i].id[1]))
            return (0);
    }
    printf("NAND device unsupported! ");

    return (1);
}

int main(void)
{
    int ret = 0;

    /* 初始化串口 */
    Debug_USART_Config();

    printf(" STM32F429 NANDFLASH 读写测试例程 ");

    /*初始化NANDFlash模块*/
    FMC_NAND_Init();


    delay_Nms(1000); //1s
     ret = nandflash_readid();
    printf("ret=%d. ", ret);

   nandTest();



    while(1)
    {
        //printf("FMC Nand Test. ");
        nandTest();
        //ret = nandflash_readid();
        //printf("ret=%d. ", ret);
        Dog();
        delay_Nms(500);
    }

}



0条回答

一周热门 更多>