全志A10/A20 nand启动系统

  • 全志A10/A20 nand flash系统开发
    • 解决的问题
    • A10/A20启动原理
    • 如何制作nand flash 刷机包
    • 如何下载boot到nand
    • 全志soc nand 控制器

全志A10/A20 nand flash系统开发

本文介绍 全志soc(A10/A20) 从nand flash启动系统,包括下载系统到nand flash的原理及方法,强调是nand flash启动而不是sd卡启动。

解决的问题

全志的资料真的太少了,而且很多不开源,这个坑真的巨大。
文本主要解决了以下几点问题
1.全志soc nand 启动原理;
2. 研究了 全志soc nand 控制器的使用,及驱动;
3. 如何下载bootloader(boot0)到nand flash, 并启动 ;

A10/A20启动原理

A10的启动过程大概可分为5步:
BootRom --> SPL --> Uboot --> Kernel --> RootFileSystem

系统上电后,ARM处理器在复位时从地址0x000000开始执行指令,把板上ROM或Flash映射到这一地址。
A10将启动设备选择程序固化在CPU内部的一个32KB ROM中,

默认的启动时序为SD Card0,NAND FLASH,SD Card2,SPI NOR FLASH。另外通过外部的一个启动选择引脚可以使其跳转到USB启动模式。通常情况下,启动选择引脚状态连接50K内部上拉电阻。在上电后,执行存储在ROM中的启动代码,将自动检测启动选择引脚状态。只有当该引脚状态为低电平时选择USB启动模式。

这可以看作是主程序加载程序。SoC开始从地址0xffff0000获取指令,这是BROM所在的位置。
BROM分为两部分:
第一部分(在0xffff0000处)是FEL模式,
第二部分是eGON模式。BRM(位于0xffff4000)

重置向量位于FEL模式的最开始:地址0xffff0000。
在重置时,它跳到0xffff0028,并将0xffff4000 (eGON.BRM)加载到接下来要执行的程序计数器中。

BROM引导加载程序已经从芯片中提取,可以在 hno’s repository中找到。
The magic signature is “eGON.BRM”.
BROM似乎从0x4000开始。如果BROM在NAND中标识了boot0,则加载并执行它。

A10/A20 芯片上电启动的时候,会自动读取SD卡 8K偏移处24K 内容,从而得到 bootloader,所以我们需要将boot0,烧写到tf卡8K偏移处.
而nand flash启动却不是这样,
BROM将尝试从page 0, 0x40, 0x80, 0xC0开始读取Boot0,…, 0 x1c0。只有这样,它才会放弃并继续使用其他启动选项(或FEL)。所以我们只需要讲boot0 刷到nand flash,0地址就可以了。

参考:https://linux-sunxi.org/BROM

如何制作nand flash 刷机包

制作nand flash 刷机包的工具在 github上可以找到,比如:
https://github.com/z4yx/sunxi-pack
https://github.com/jiangdoudou/linux-sdk-a20
我目前就是使用第一个仓库的工具,自己简单修改后就可以制作刷机包了。
当然工具里面如何制作刷机镜像,及原理 可以自己去研究,有些是开源的,有些是闭源的。

制作好的nand-镜像,如:xxx.img ,可以用 usb刷机工具LiveSuitPack (下载地址:) 刷到nand flash 中。

如果还是不懂,而且需要的人比较多,我可以专门出一篇文章来介绍。

如何下载boot到nand

重点 难点 重点 重点

刚开始想着 只需要把boot0 刷到 nand 的最前面,就能在nand启动了吧。这确实想的有点简单了。
第一步 我先在 uboot中实现对nand flash 的读写,然后使uboot从sd卡启动。
第二部 直接将 boot0,uboot,uboot-spl,刷到 nand 中。

结果很残酷,不管是刷 什么 boot ,都无法启动。

但是上面介绍的使用usb刷boot进 nand 就可以启动,这就很奇怪了
我们可以看看 usb 刷机时的uart log

NB1 : nand phy init ok
boot1 last block 0x0x00000006 .
open nand.
boot1 0x00000002
erasing block 2 succeeded…
Succeed in erasing block 2.
succeed in programming block 2.
boot1 0x00000003
erasing block 3 succeeded…
Succeed in erasing block 3.
succeed in programming block 3.
boot1 0x00000004
erasing block 4 succeeded…
Succeed in erasing block 4.
succeed in programming block 4.
boot1 0x00000005
erasing block 5 succeeded…

NB1 : nand phy init ok
open nand.
read retry mode: 0x0x00010604
lsb enalbe
boot0 0x00000000
boot0 0x00000001
boot0 0x00000000
boot0 0x00000001
lsb disalbe

(完整的log:allwinner-usb-fel.log )
这很明显,这些是对nand 进行操作的。
我对boot0,boot1源码修改过,我就发现 全志 的nand驱动代码其实是同一套。我提供个我修改使用的boot源码allwinner-boot,目前支持对 boot0,boot1的编译使用

static __s32  burn_boot0_lsb_mode( __u32 read_retry_type, __u32 Boot0_buf )
{__u32              i;__u32               length;struct boot_flash_info info;__u32 nand_version, nand_version0, nand_version1;__u8  oob_buf[32];__u32 page_size;__inf("burn boot0 lsb mode!\n");memset(oob_buf, 0xff, 32);nand_version = NAND_GetNandVersion();nand_version0 = (nand_version>>16)&0xff;nand_version1 = (nand_version>>24)&0xff;oob_buf[0] = 0xff;oob_buf[1] = 0x00;oob_buf[2] = nand_version0;oob_buf[3] = nand_version1;if( NAND_PhyInit( ) == FAIL )return -1;__inf("open nand.\n");__inf("read retry mode: 0x%x\n", read_retry_type);if( NAND_LSBInit(read_retry_type) ){__inf("lsb init failed.\n");goto error;}NAND_LSBEnable(0, read_retry_type);__inf("lsb enalbe \n");if( NAND_GetFlashInfo( &info ) == FAIL ){__inf("get flash info failed.\n");goto error;}/* 检查 page count */page_size = info.pagesize*512;for( i = BOOT0_START_BLK_NUM;  i <= BOOT0_LAST_BLK_NUM;  i++ ){struct boot_physical_param  para;__u32  k;__inf("boot0 %x \n", i);/* 擦除块 */para.chip  = 0;para.block = i;if( NAND_PhyErase( &para ) != SUCCESS ){__inf("Fail in erasing block %d.\n", i );continue;}/* 在块中烧写boot0备份, lsb mode下,每个块只能写前4个page */for( k = 0;  k < 4;  k++ ){para.chip  = 0;para.block = i;para.page  = k;para.mainbuf = (void *) (Boot0_buf + k * page_size);para.oobbuf = oob_buf;if( NAND_PhyWrite_Seq( &para ) != SUCCESS ){__inf("Warning. Fail in writing page %d in block %d.\n", k, i );}}}//check boot0for( i = BOOT0_START_BLK_NUM;  i <= BOOT0_LAST_BLK_NUM;  i++ ){struct boot_physical_param  para;__u32  k;__inf("boot0 %x \n", i);/* 在块中烧写boot0备份, lsb mode下,每个块只能写前4个page */for( k = 0;  k < 4;  k++ ){para.chip  = 0;para.block = i;para.page  = k;para.mainbuf = (void *) (Boot0_buf + k * page_size);para.oobbuf = oob_buf;if( NAND_PhyRead_Seq( &para ) != SUCCESS ){__inf("Warning. Fail in reading page %d in block %d.\n",  k, i );}}}NAND_LSBDisable(0, read_retry_type);NAND_LSBExit(read_retry_type);__inf("lsb disalbe \n");NAND_PhyExit( );return 0;error:NAND_PhyExit( );return -1;
}

既然nand 驱动也有源码了,那我们看看 usb 是如何把boot刷到nand的,那应该就能解决其中的问题了。

全志soc nand 控制器

既然要对nand进行读写,那对nand 驱动也必然要熟悉了。
先看 A10 / A20 nand 控制器的使用
NFC_Register_Guide.

这里面坑最大的就是 硬件ECC配置,就是NFC_ECC_CTL寄存器的配置,为什么这么说,我们仔细看看这个寄存器
NFC_REG_ECC_CTL 0x0034 ECC & Random control

NFC_ECC_CTL_ECC_EN (1 << 0)
NFC_ECC_CTL_ECC_PIPELINE (1 << 3)
NFC_ECC_CTL_ECC_EXCEPTION (1 << 4)
NFC_ECC_CTL_ECC_BLOCK_SIZE (1 << 5)
NFC_ECC_CTL_RANDOM_EN (1 << 9)
NFC_ECC_CTL_RANDOM_DIRECTION (1 << 10)
(1 << 11) ??
NFC_ECC_CTL_ECC_MODE (0xf << 12)
NFC_ECC_CTL_RANDOM_SEED (0x7fff << 16))

这里面的NFC_ECC_CTL_ECC_MODE,NFC_ECC_CTL_RANDOM_SEED位如果 写和读的时候 配置不一样,那写完了nand,你想读出来,就会出现 ecc 校验出错的问题,这就是 为什么 之前使用uboot 刷boot到nand 不能启动的原因了,因为 在片上的固件BROM里面对boot0的读取是固定的配置。
如果有人需要对 nand 驱动手动实现,我这里提供一个快速驱动nand的系列命令(boot0.ush-nand flash-registers )

启用硬件ECC后,每次写页面数据都会导致一个空闲区域的数据(oob_buf)写入。有时页面大于1K,所以需要多次写入一个页面。备用区域也将按顺序多次写入ECC数据。一次数据写操作会将存储在NFC_USER_DATA(i)上的4byte用户数据写在ECC数据后面,ECC数据的长度取决于ECC的模式。

nand 简单驱动boot0
通过实现nand的读写功能,将uboot-spl.bin 写到nand flash 中,

最后通过nand 启动效果

后面可能会研究 usb 启动方式。

如果有志同道合的朋友,可以联系我 QQ 839281922

全志A10/A20 nand flash系统开发相关推荐

  1. a10 linux 烧写,全志 A10 A20 A31 A13固件配置,打包,烧写指南.pdf

    全志 A10 A20 A31 A13固件配置,打包,烧写指南 SPR 用户手册 SPR 用户手册 Vers Data Author Change Description ion V1.00 2011- ...

  2. 全志A10/A20 Bootloader加载过程分析

    原文 : http://blog.csdn.net/allen6268198/article/details/12905425 从这里开始:http://linux-sunxi.org/Bootabl ...

  3. 【转】全志A10/A20 Bootloader加载过程分析

    原文 : http://blog.csdn.net/allen6268198/article/details/12905425 从这里开始:http://linux-sunxi.org/Bootabl ...

  4. 基于全志A10\A20产品跑分测试结果对比

    笔者通过两个分别基于A10\A20的产品跑分测试来对比性能,A20双核处理能力.DRAM访问速度明显提高,但是绘图功能跑分没有怎么提高,是不是跑分软件的问题,A20是双GPU,按理说应该会快很多的,整 ...

  5. 嵌入式开发 SRAM SROM DRAM DROM DDR NAND FLASH EMMC 区别

    http://blog.sina.com.cn/s/blog_bda999510102vm9u.html RAM(Random Access Memory)的全名为随机存取记忆体,它相当于PC机上的移 ...

  6. nor flash 和nand flash 的区别

    ROM和RAM指的都是半导体存储器,ROM是Read Only Memory的缩写,RAM是Random Access Memory的缩写.ROM在系统停止供电的时候仍然可以保持数据,而RAM通常都是 ...

  7. nor flash和nand flash

    FLASH和EEPROM的最大区别是FLASH按扇区操作,EEPROM则按字节操作,二者寻址方法不同,存储单元的结构也不同,FLASH的电路结构较简单,同样容量占芯片面积较小,成本自然比EEPROM低 ...

  8. NAND Flash和NOR Flash的比较

    目前Flash主要有两种NOR Flash和NADN Flash.NOR Flash的读取和我们常见的SDRAM的读取是一样,用户可以直接运行装载在NOR FLASH里面的代码,这样可以减少SRAM的 ...

  9. nand flash、nor flash、sdram、ram、dram的区别

    创建于 2013-05-23 迁移自个人的百度空间 -------------------------------- ROM和RAM指的都是半导体存储器,ROM是Read Only Memory的缩写 ...

最新文章

  1. 黄铁军:沉迷于寻求通用智能理论,将是阻碍 AI 发展的最大障碍 | Yann LeCun 自传《科学之路》序...
  2. Xcode11 上传苹果卡在Authenticating with the iTunes store 或者transpoter上传卡在正在验证 APP - 正在通过App Store进行认证
  3. 初探 Headless Chrome
  4. hj212协议如何和php通讯,HJ212数据传输标准报文解析
  5. 什么工作经常出差_商旅人群洞察:什么样的人经常坐飞机出差?
  6. Web.py Cookbook 简体中文版 - 保存上传的文件
  7. Android NDK开发Crash错误定位
  8. android 自定义绘画,【整理】Android 自定义视图之画图
  9. odoo Botton标签属性详解
  10. Python编程实践之Choose
  11. python怎么写入txt文件_python 如何将数据写入本地txt文本文件的实现方法
  12. 模板方法 (宝,我输液了,输的想你的夜)
  13. 中芯国际任命高永岗为董事长 周子学辞任执行董事职务
  14. python语句分号_你知道分号在各种编程语言中的作用吗?
  15. php+html文本域,html的文本域和表单域
  16. 这几款app疫情期间活跃度为何如此高?方法太可了吧
  17. Applilet2 for V850ES/Fx3生成代码
  18. Druid配置好之后sql监控界面不显示sql语句的可能原因
  19. linux中解压rar文件处理
  20. 什么是导航?导航具有什么样的作用?

热门文章

  1. “不差钱”的蔚来,为何着急回港上市?
  2. ECharts天气预报折线图
  3. PCL Super4PCS点云粗配准(源码编译)
  4. 互联网摸鱼日报(2022-12-21)
  5. png的计算机储存图片的格式吗,我电脑打不开png格式的图片,如何解决?
  6. 结束语-放弃完美主义,执行力就是限时限量认真完成
  7. Elasticsearch基础
  8. 看完南京前11年房价,我哭了!今年实在太特么狠了
  9. vue3项目使用Element Plus icon库:统一导入、全局注册组件
  10. Android 通过外网IP定位城市