⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 samsung_nand.c

📁 新一代基于事件的嵌入式操作系统dyos在三星的s3c44b0的arm芯片上的完整移植代码
💻 C
📖 第 1 页 / 共 4 页
字号:
        *pg_nand_address = (uint8_t)(address >> 9);  // A9 ~ A16
        *pg_nand_address = (uint8_t)(address >> 17); // A17 ~ A22
        address_end();                      //完成写入地址

        __wait_ready_2808( );  //等待芯片内部操作完成

        for(loop=0; loop < read_size; loop++)
        {
            data = *pg_nand_address;    //读取数据
            if((data | buf[completed]) != buf[completed])   //查看有否0->1的位
            {
                ce_inactive();                      //关闭片选
                return false;       //有0->1的位,返回需要擦除
            }
            completed++;
        }
        ce_inactive();                      //关闭片选
        address += read_size;
        start_offset = 0;   //从第二个扇区开始,肯定从0开始读
    }
    return true;
}

//----查询是否需要擦除(buf)-----------------------------------------------
//功能: flash中的原来的内容在org_data中,如果要改成如new_data中的数据,查看是否
//      需要擦除。
//参数: new_data,新数据缓冲区
//      new_data,数据缓冲区
//      size,数据尺寸
//返回: flase = 需要擦除,true = 已准备好,不需要擦除
//-----------------------------------------------------------------------------
bool_t query_ready_with_data_2808(uint8_t *new_data,uint8_t *org_data,
                                        uint32_t size)
{
    uint32_t loop;
    if(org_data == NULL)
        return false;
    if(new_data != NULL)
    {
        for(loop = 0; loop < size; loop++)
        {
            if((org_data[loop] | new_data[loop]) != org_data[loop])
                return false;   //如果存在由0改1的数据,返回false
        }
    }else
    {
        for(loop = 0; loop < size; loop++)
        {
            if(org_data[loop] != 0xFF)
                return false;
        }
    }
    return true;
}

//坏块标记算法:
//1、三星出厂时,坏块OOB的头两页第6个字节被写入非0xFF数据,好块则保证是0xFF。
//2、使用过程中的新增坏块,也在头两页的第6字节写入0.
//3、永远不要擦除坏块,否则用于坏块标记的第6字节也被擦除。
//----有效块检查--------------------------------------------------------------
//功能: 检查一个块是否有效块,参考坏块标记算法。
//参数: block_no,块号
//返回: true=好块,false=坏块。
//----------------------------------------------------------------------------
bool_t check_block_2808(uint32_t block_no)
{
    uint16_t j;
    uint32_t address;
    uint8_t data;
    ce_active();
    for(j=0; j<2; j++)
    {
        address = tg_samsung_nand.block_size * block_no + 0x200 * j + 517;

        __write_command_2808(cn_2808_select_oob);

        address_start();
        *pg_nand_address = (uint8_t)address;         // A0 ~ A7
        *pg_nand_address = (uint8_t)(address >> 9);  // A9 ~ A16
        *pg_nand_address = (uint8_t)(address >> 17); // A17 ~ A22
        address_end();

        __wait_ready_2808( );  //等待芯片内部操作完成
        data = *pg_nand_address;

        if(data != 0xFF)
        {
            ce_inactive();
            return  false;
        }
    }
    ce_inactive();
    return true;
}

//----标记一个坏块-----------------------------------------------------------
//功能:在读、写、擦除等函数中调用,如果操作过程中发现某块是坏块,立即调用本函数
//      把它标记为坏块,即把首扇区的第517字节写0.
//参数: block_no,块号
//返回: true=成功标记,false=标记失败。
//----------------------------------------------------------------------------
bool_t __mark_invalid_block(uint32_t block)
{
    uint16_t j,k;
    uint32_t address;
    __write_command_2808(cn_2808_select_oob);
    for(j=0; j<2; j++)
    {
        ce_active();

        __write_command_2808(cn_2808_page_program);

        address_start();
        address = tg_samsung_nand.block_size * block + 0x200 * j + 517;
        *pg_nand_address = (uint8_t)address;         // A0 ~ A7
        *pg_nand_address = (uint8_t)(address >> 9);  // A9 ~ A16
        *pg_nand_address = (uint8_t)(address >> 17); // A17 ~ A22
        address_end();

        __wait_ready_2808( );  //等待芯片内部操作完成
        for(k = 0; k< 16;k++)
            *pg_nand_address = k;
//        *pg_nand_address = 0x00;
        __write_command_2808(cn_2808_startup_write);
        __wait_ready_2808_slow(cn_wait_page_write);  //等待芯片内部操作完成
        if(__read_status_2808() & cn_2808_failure)
        {
            ce_inactive();
            return -1;
        }

    }
    ce_inactive();
    return true;
}

//----查flash中好块数量--------------------------------------------------------
//功能: 查flash中好块数量
//参数: 无
//返回: 好块数量
//-----------------------------------------------------------------------------
uint32_t __check_all_ss(void)
{
    uint32_t i, j,sum = 0;
    uint32_t address;
    uint8_t data;

    for(i=0; i<tg_samsung_nand.block_sum; i++)
    {
        ce_active();
        for(j=0; j<2; j++)
        {
            address = tg_samsung_nand.block_size * i + 0x200 * j + 517;

            __write_command_2808(cn_2808_select_oob);

            address_start();
            *pg_nand_address = (uint8_t)address;         // A0 ~ A7
            *pg_nand_address = (uint8_t)(address >> 9);  // A9 ~ A16
            *pg_nand_address = (uint8_t)(address >> 17); // A17 ~ A22
            address_end();

            __wait_ready_2808( );  //等待芯片内部操作完成
            data = *pg_nand_address;
            if(data != 0xFF)
            {
                sum++;
                break;
            }
        }
    }
    ce_inactive();
    return sum;
}

//----计算扇区ecc码-----------------------------------------------------------
//功能: data中包含256字节数据,计算它的ecc码
//参数: data,数据缓冲区
//      ecc: 3字节的缓冲区,返回ecc码
//返回: 无
//-----------------------------------------------------------------------------
void __make_sector_ecc(const uint8_t *data,uint8_t *ecc)
{
    uint32_t i;
    for(i = 0; i < cn_sector_size/256; i++)
    {
        ecc_make_256(data + i*256, ecc + i*3);
    }
}

//----读flash 芯片id-----------------------------------------------------------
//功能: 读取flash芯片的id
//参数: 无
//返回: 芯片id
//-----------------------------------------------------------------------------
bool_t __read_chip_id (uint32_t *vendor_id,uint32_t *chip_id)
{
    ce_active();

    __write_command_2808(cn_2808_reset);
    __wait_ready_2808();  //等待芯片内部操作完成
    __write_command_2808(cn_2808_read_id);

    address_start();
    *pg_nand_address = 0;  // Address. 1cycle
    address_end();

    *vendor_id=*pg_nand_address;
    *chip_id=*pg_nand_address;

    ce_inactive();
    return true ;
}

//----复位芯片-----------------------------------------------------------------
//功能: 复位芯片
//参数: 无
//返回: 无
//-----------------------------------------------------------------------------
void __reset_2808(void)
{
  ce_active();

  __write_command_2808(cn_2808_reset);
  __wait_ready_2808_slow(cn_wait_reset);  //等待芯片内部操作完成
  ce_inactive();

}

//----初始化2808文件系统------------------------------------------------------
//功能:初始化2808文件系统,建立文件柜。
//参数: 无
//返回: true= 成功,false=失败
//-----------------------------------------------------------------------------
bool_t module_init_fs_samsung_flash(void)
{
    uint32_t vendor_id,chip_id;

    //初始化timer4作为等候flash内部操作完成的中断,无需ISR
    int_setto_asyn_signal(cn_irq_line_timer4);     //设为异步信号
    timer_set_clk_source(4,0);          //主频的1/2分频
    timer_set_precale(2,cn_timer_clk/8-1);   //预分频数:事定时器输入时钟约1Mhz
    timer_set_type(4,1);                //设置定时器连续工作
    int_restore_line(cn_irq_line_timer4);//启动中断,

    __reset_2808();
    __read_chip_id(&vendor_id,&chip_id);
    switch(chip_id)
    {
        default:
        {
            u32g_sectors_per_block = 32;
            tg_samsung_nand.block_sum = cn_blocks_sum;
            tg_samsung_nand.block_size = cn_block_size;
            tg_samsung_nand.DBX_read_buf_size = cn_fs_buf_len;
            tg_samsung_nand.DBX_write_buf_size = cn_fs_buf_len;
        }break;
    }
    pg_sector_buf = (uint8_t*)m_malloc_gbl(
                        tg_samsung_nand.block_size / u32g_sectors_per_block,0);
    if(pg_sector_buf == NULL)
    {
        return false;
    }
    tg_samsung_nand.query_block_ready_with_ecc= query_block_ready_ss_with_ecc;
    tg_samsung_nand.query_block_ready_no_ecc = query_block_ready_2808_no_ecc;
    tg_samsung_nand.query_ready_with_data = query_ready_with_data_2808;
    tg_samsung_nand.erase_block = erase_block_2808;
    tg_samsung_nand.check_block = check_block_2808;
    tg_samsung_nand.read_data_with_ecc = read_block_ss_with_ecc;
    tg_samsung_nand.write_data_with_ecc = write_block_ss_with_ecc;
    tg_samsung_nand.read_data_no_ecc = read_block_ss_no_ecc;
    tg_samsung_nand.write_data_no_ecc = write_block_ss_no_ecc;
    tg_samsung_nand.write_PCRB = write_PCRB_2808;
    tg_samsung_nand.restore_PCRB = restore_PCRB_2808;
    tg_samsung_nand.chip_name = "samsung little block nand flash";
    if(DFFSD_install_chip(&tg_samsung_nand,cn_reserve_blocks))
        return true;
    else
    {
        m_free(pg_sector_buf);
        return false;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -