基于Nandflash的Bootloader的设计与实现

摘要:Bootloader是系统上电或复位后首先运行的一段代码,是连接操作系统和硬件的桥梁,负责初始化硬件和引导操作系统等。目前已有很多通用的Bootloader,但是如何根据特定的嵌入式平台,移植自己的引导程序是一个重点和难点。文章详细说明了从Nandflash引导操作系统要完成的主要任务和实现方法,并给出了在S3C2410上实现Nandflash启动的试验结果。
关键词:Bootloader; 移植;NandflashS3C2410

0
引言
  Bootloader通常称为系统的引导加载程序,是系统加电或复位后执行的第一段代码[ 1 ]。一般它只在系统启动时运行非常短的时间,但对于嵌入式系统来说,这是一个非常重要的系统组成部分。通过这段小程序,可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为调用操作系统内核准备好正确的环境,并同时提供基本输入、输出系统监控功能和程序调试功能。

  Bootloader是严重地依赖于硬件而实现的。每种不同体系结构的处理器都有不同的Bootloader。除了依赖于处理器的体系结构以外,Bootloader实际上也依赖于具体的嵌入式板级设备的配置,也就是说,对于两块不同的嵌入式板而言,即使它们是基于同一种处理器而构建的,要想让运行在一块板子上的Bootloader程序也能运行在另一块板子上,通常也都需要修改与目标硬件相关的代码。因此有必要分析Bootloader,并理解和找出其中的原理和规律,就其特定的嵌入式系统,移植或开发属于自己的Bootloader

1 系统硬件平台简介
  本系统采用的是SamSung公司的S3C2410处理器[ 2 ],它是专门为移动手持设备提供的高性价比和高性能的嵌入式微处理器解决方案。其内核是ARM920T,最高能工作在202.8MHz,为了减少系统总成本和减少外围器件,它集成了如下部件:分别为16KB指令和数据Cahce1LCD控制器、SDRAM控制器、NANDFLASH控制器、3通道UART4通道DMA4个具有PWM功能的计时器和1个内部时钟、8通道10ADC、触摸屏接口、I²S总线接口,2USB主机接口、1USB设备接口,2SPI接口、SDMMC卡接口、看门狗定时器、117位通用IO口、24位外部中断源、8通道10AD控制器等。本文涉及的S3C2410开发板的硬件结构如图1所示,本文主要阐述从Nandflash引导操作系统要完成的主要任务和实现方法,至于从Norflash引导操作系统,不打算具体实现。

2 存储空间分布和映射图
  硬件平台的Nandflash(型号是:K9F1208U0M[ 3])空间为64MBSDRAM(型号是:HY57V561620[ 4 ],32Mx2)空间为64M0x30000000-0x33ffffff),采用如图2所示的存储空间分布图,因为Nandflash只能存储程序,无法运行程序。为了能够从Nandflash启动,上电复位时,S3C2410通过硬件逻辑把Nandflash的前4KB的内容复制到片内SRAM中,而片内SRAM被映射到地址0x0,这样就可以从地址0x0处取到有效指令,开始执行bootloader,完成把Nandflash中的内核代码复制到sdram中等工作。

2 引导代码和操作系统内核在Nandflash和存储空间中的分布情况

3 Bootloader的设计流程
  Bootloader引导程序是硬件上电复位后首先运行的代码,由它来加载嵌入式操作系统。然后由操作系统接管整个系统,进行进程管理、内存管理、磁盘管理和各个外设管理等工作。 BootLoader是操作系统内核运行之前的一段自举程序,用来初始化硬件设备、改变处理器运行模式和重组中断向量,建立内存空间的映射图,将系统的软硬件环境带到一个由用户定制的特定状态,然后加载操作系统内核。从操作系统的角度来看,Bootloader的总目标就是正确地调用内核来执行。Bootloader一般分为stage1stage2两大部分[ 5 ],对于依赖于CPU体系结构的代码,比如设备初始化代码等,通常都放在stage1中,而且通常都用汇编语言来实现,以达到短小精悍的目的,也就是前面说的启动代码。而stage2则通常用C语言来实现,这样可以实现复杂的功能,而且代码会具有更好的可读性和可移植性。

3.1 Bootloaderstage1
  这部分代码必须首先完成一些基本的硬件初始化。为stage2 的执行以及随后的内核的执行准备好一些基本的硬件环境。Bootloader stage1 一般通用的内容包括:
  (1)设置中断和异常向量;(2)禁止看门狗;(3) 屏蔽所有的中断, Boot Loader 的执行全过程中可以不必响应任何中断, 中断屏蔽可以通过写CPU 的中断屏蔽寄存器或状态寄存器CPSR 寄存器来完成;(4) 设置CPU 的速度和时钟频率;(5) RAM进行初始化, 包括正确设置系统的内存控制器的功能寄存器等;(6)初始化LEDUART,就是通过GPIO来驱动LED,也可以通过初始化UART向串口打印Bootloader的调试信息来表明系统的状态是OK还是ERROR,以便跟踪系统运行情况;(7)关闭CPU 内部指令/数据高速缓存(cache);(8)为加载Bootloaderstage2准备RAM空间;(9)设置好堆栈;(10)跳转到stage2C入口点;其流程图如图3所示。

3 Bootloaderstage1的实现

3.2 Bootloaderstage2
  为了让程序跳入C 语言的“main”函数, 我们采用直接跳转到“main”函数的方法, 实现代码如下:
  b Main
  进入main 函数后即可以开始本阶段stage2 的初始化任务, 这包括:
  (1) 如果在stage1没有初始化UART,这时候至少初始化一个串口, 以便和终端用户进行交互,当然也可以继续点亮或熄 灭LED来判断程序执行情况;
  (2) 修改时钟频率;
  (3) 使能指令Cache
  (5) 从串口中打印一些必要的交互信息,了解系统状态;
  (6) 初始化中断, 包括屏蔽中断, 清除中断悬挂标志, 初始化中断向量表, 注册需要的中断处理函数等;
  (8)打印版本、时间等信息,并从Nandflash复制内核到SDRAM中;
  (9)修改指针,直接跳到内核在SDRAM中的首地址处,至此,完成了Bootloader的全部运行加载工作;

  下面是main()函数和从Nandflash复制内核到SDRAM中的ReadImageFromNandflash()函数的具体实现,但省略了一些具体细节,包括从串口打印的启动、交互、调试信息和一些具体函数的实现。一些具体函数的实现可以参考三星评估版源代码。
  void Main(void)
  {
  JumpAddr=0x30200000; //拷贝内核到sdram中的起始地址,也是内核开始执行的地址
  ChangeClockDivider(1,1); //1:2:4
  ChangeMPllValue(0x5c,0x1,0x1); // FCLK=202.8MHz
  MMU_EnableICache(); //使能指令Cache
  Uart_Init(); // 初始化串口
  Port_Init(); //初始化I/O
  NF_Init(); //初始化Nandflash控制器
  NF_ReadID(); //读取Nandflash存储器ID
  ReadImageFromNandflash();//把存储在Nandflash中的内核拷贝到SDRAM
  rINTMSK=BIT_ALLMSK; //屏蔽所有中断
  Launch(JumpAddr); //跳转到sdram中内核开始处,并运行内核
  }
  从NandflashFlashK9F1208U0M)拷贝内核到SDRAM的函数具体实现如下:
  void ReadImageFromNandflash(void)
  {
  U8 Image_Buf[512];
  U32 Sram_Space=0;
  U32 j,k, numberblock;
  static U32 i, SECTOR_SIZE=512;
  static U8 isbad;
  volatile U32 IMAGE_BASE=0x30200000; //内核在sdram中运行的开始地址
  rINTMSK = BIT_ALLMSK; //屏蔽所有中断
  i=2; //从第2block开始拷贝内核,第0个用于存储本文的bootloader,第1个没用到
  numberblock=2047; //拷贝多少个blocksdram中,视内核大小设置此值
  while(1)
  {
  nextblock:
  isbad=0;
  isbad=NF_IsBadBlock(i); //判断正在拷贝的block是否是坏block
  if (isbad) //是坏block,就进行相应的处理;否则就忽略此处,进行下面的拷贝
  {
  i=i+1; //调整,指向下一个block
  isbad=0;
  if(i>= numberblock) //判断是否拷贝完了所需的block
  {
  Launch(JumpAddr); //拷贝完了所需的block,就跳到sdram中内核开始处
  }
  goto nextblock;
  }
  for(k=0;k<32;k++) //1 block=32 pages
  { // FMD_ReadSector()函数实现从Nandflash存储器中读取数据到数据缓冲区中
  FMD_ReadSector(i, (U8 *)&Image_Buf, k);
  for (j=0;j<SECTOR_SIZE;j++) //1 page=512 bytes
  { //从数据缓冲区中拷贝到sdram
  *((U8 *)(IMAGE_BASE+Sram_Space+j))=Image_Buf[j];
  }
  Sram_Space=Sram_Space+SECTOR_SIZE; //调整sdram中的偏移地址
  }
  i=i+1; //调整,指向下一个block
  if(i>= numberblock) //判断是否拷贝完了所需的block
  {
  Launch(JumpAddr); //拷贝完了所需的block,就跳到sdram中内核开始处
  }
  }
  }

4
试验结果
  由于三星公司的S3C2410集成了Nandflash控制器,它通过硬件逻辑把Nandflash的前4KB内容,即把Bootloader复制到片内sram中,并被映射到地址0x0处。通过跳线设置默认从nandflash启动,那么,系统每次上电或复位后,首先开始运行的就是Bootloader。使用ADS1.2集成开发环境建立Bootloader应用工程,添加必需的文件并设置好编译环境,如BootloaderRO_Base设置为0x0RW_Base设置为0x33ff0000等,调试并最后生成可执行二进制文件,通过JTAG接口把Bootloader烧写到Nandflash的第0block地址开始处,通过usb下载工具把操作系统烧写到第2block地址开始处,复位启动系统运行后的结果如图4所示,该程序用于基于uCOS操作系统的图像采集系统的引导。用同样的方法烧写不同的操作系统内核应用程序,试验结果每一次表明:Bootloader运行良好,启动加载内核快,且简单、实用、可靠。

5 结论
  Bootloader的设计与实现是一个非常复杂的过程,因此要根据具体的硬件和软件需求分析来进行移植或设计。本文设计的Bootloader完成的主要功能包括:试验板硬件的初始化、串口初始化、时钟频率修改以及从Nandflash复制操作系统到SDRAM中运行等,并通过PC机上的超级终端显示了正确的启动运行信息,且可执行代码只有3K左右。因此,本文所详细描述的Bootloader启动运行的全过程,对理解、设计和移植Bootloader具有一定的参考意义。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/435607.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【开源项目】ollama:本地部署大模型

文章目录 1. 安装2. 使用体验2.1. 运行llama22.2. 运行llama2-chinese 项目地址&#xff1a;Github - ollama/ollama 注意&#xff1a;项目对硬盘容量、内存要求比较高。 1. 安装 从Github项目的最新release下载安装包&#xff0c;点击运行即可。 2. 使用体验 2.1. 运行ll…

个人博客系列-后端项目-用户验证(5)

介绍 创建系统管理app&#xff0c;用于管理系统的用户&#xff0c;角色&#xff0c;权限&#xff0c;登录等功能&#xff0c;项目中将使用django-rest_framework进行用户认证和权限解析。这里将完成用户认证 用户验证 rest_framework.authentication模块中的认证类&#xff…

Unity的相机跟随和第三人称视角二

Unity的相机跟随和第三人称视角二 展示介绍第二种相机模式远离代码总结 展示 我录的视频上可能看不太出来&#xff0c;但是其实今天的这个方法比原来写的那个方法更简便并且死角更少一些。 这里我也做了两个人物偏移的视角&#xff0c;按Q是原来的两个相机模式切换&#xff0c…

内容管理平台用这几个就够了,简单又好用

对于大多数企业和自由职业者来说&#xff0c;选择合适的内容管理平台已经成为一种必备的技能。良好的内容管理平台可以赋能你的团队&#xff0c;让你们更好地协作、管理和分享内容。不管你是要发布博客文章&#xff0c;还是需要管理复杂的项目文档&#xff0c;都可以通过内容管…

解读Linux文件目录权限:srw-rw----

在Linux系统中&#xff0c;文件或目录的权限由10个字符表示&#xff0c;分为四段&#xff1a; 第一个字符&#xff1a;表示文件类型。d代表目录&#xff0c;-代表普通文件&#xff0c;l代表符号链接&#xff0c;s代表套接字&#xff08;socket&#xff09;&#xff0c;c代表字符…

以太网帧格式

以太网帧格式 以太网帧格式前导码&#xff08;Preamble&#xff09;帧起始界定符&#xff08;SFD&#xff0c;Start Frame Delimiter&#xff09;以太网帧头目的MAC地址源MAC地址长度/类型 数据段帧检验序列&#xff08;FCS&#xff0c;Frame Check Sequence&#xff09;帧间隙…

Linux 文件操作命令

1 文件与目录操作 cd /home 进入 ‘/home’ 目录 cd .. 返回上一级目录cd ../.. 返回上两级目录cd - 返回上次所在目录cp file1 file2 将file1复制为file2cp -a dir1 dir2 复制一个目录 cp -a /tmp/dir1 . 复制一个…

网络安全审计是什么意思?与等保测评有什么区别?

网络安全审计和等保测评在信息安全领域中都是非常重要的环节。但不少人对于这两者是傻傻分不清楚&#xff0c;今天我们就来简单聊聊网络安全审计是什么意思&#xff1f;与等保测评有什么区别&#xff1f; 网络安全审计是什么意思&#xff1f; 网络安全审计是通过对网络系统和网…

selenium鼠标操作实战

鼠标操作实战 鼠标单击操作 click()内置鼠标操作包ActionChains鼠标双击操作double_click()鼠标右击操作context_click()鼠标指针悬浮操作move_to_element(ele)鼠标拖动操作drag_and_drop(source, target)其他鼠标操作汇总 鼠标单击操作 click() from selenium import webdriv…

MySQL存储过程2——if、case、while、repeat、loop、cursor、handler

1、if用作条件判断 1.1、语法结构 IF 条件1 THEN... ELSEIF 条件2 THEN... ELSE... END IF; 在if条件判断的结构中&#xff0c;Else if结构可以有多个&#xff0c;也可以没有。Else结构可以有&#xff0c;也可以没有 1.2、示例 根据定义的分数score变量&#xff0c;判断当…

openssl调试记录

openssl不能直接解密16进制密文&#xff0c;需要把密文转化成base64格式才能解密 调试记录如下&#xff1a;

搭建SpringBoot项目——开发环境搭建开发环境搭建

简介 SpringBoot 是 Java 社区最有影响力之一的开源的Spring后端开发框架&#xff0c;也是企业级应用开发的首选技术&#xff0c;Spring Boot 拥有良好的技术基因&#xff0c;它是伴随着Spring 4 而产生的技术框架&#xff0c;在继承了 Spirng 框架所有优点的同时也为开发者带来…

scrapy 爬虫:多线程爬取去微博热搜排行榜数据信息,进入详情页面拿取第一条微博信息,保存到本地text文件、保存到excel

如果想要保存到excel中可以看我的这个爬虫 使用Scrapy 框架开启多进程爬取贝壳网数据保存到excel文件中&#xff0c;包括分页数据、详情页数据&#xff0c;新手保护期快来看&#xff01;&#xff01;仅供学习参考&#xff0c;别乱搞_爬取贝壳成交数据c端用户登录-CSDN博客 最终…

AI智商排名:Claude-3首次突破100

用挪威门萨&#xff08;智商测试题&#xff09;中 35 个问题对chatGPT等人工智能进行了测试&#xff1a; ChatGPT 对ChatGPT进行了两次挪威门萨测试&#xff0c;在 35 个问题中&#xff0c;它平均答对了 13 个&#xff0c;智商估计为 85。 测试方法 每个人工智能都接受了两次…

【b站咸虾米】1 Vue介绍 2021最新Vue从基础到实例高级_vue2_vuecli脚手架博客案例

课程地址&#xff1a;【2021最新Vue从基础到实例高级_vue2_vuecli脚手架博客案例】 https://www.bilibili.com/video/BV1pz4y1S7bC/?share_sourcecopy_web&vd_sourceb1cb921b73fe3808550eaf2224d1c155 感觉尚硅谷的Vue看完忘得差不多了&#xff0c;且之前学过咸虾米的unia…

Java agent技术的注入利用与避坑点

什么是Java agent技术&#xff1f; Java代理&#xff08;Java agent&#xff09;是一种Java技术&#xff0c;它允许开发人员在运行时以某种方式修改或增强Java应用程序的行为。Java代理通过在Java虚拟机&#xff08;JVM&#xff09;启动时以"代理"&#xff08;agent…

Redis(十七)分布式锁

文章目录 面试题分布式锁锁的种类分布式锁需要具备的条件和刚需分布式锁 案例nginx分布式微服务部署&#xff0c;单机锁问题分布式锁注意事项lock/unlocklua脚本自研版的redis分布式锁搞定lua脚本 可重入锁可重入锁种类可重入锁hset实现&#xff0c;对比setnx&#xff08;重要&…

react高阶组件:如何同时兼容class类组件和函数式组件。

场景&#xff1a; 每个页面都要实现分享功能&#xff0c;但是页面有些是用class类&#xff0c;有些又直接是函数式。 方案1&#xff1a; 写2套方法。各自引用。&#xff08;维护不太好&#xff0c;改要改2遍&#xff09; 方案2&#xff1a; 可以封一个 jsx的组件&#xff0c…

NLP:spacy库安装与zh_core_web_sm配置

到公司来第一个项目竟然是偏文本信息抽取与结构化的&#xff0c;&#xff08;也太高看我了┭┮﹏┭┮&#xff09; 反正给机会了就上吧&#xff0c;我就一臭实习的&#xff0c;怕个啥。配置了两天的环境&#xff0c;也踩了不少坑&#xff0c;我把我的经历给大家分享一下&#…

HarmonyOS NEXT应用开发案例集

概述 随着应用代码的复杂度提升&#xff0c;为了使应用有更好的可维护性和可扩展性&#xff0c;良好的应用架构设计变得尤为重要。本篇文章将介绍一个应用通用架构的设计思路&#xff0c;以减少模块间的耦合、提升团队开发效率&#xff0c;为开发者呈现一个清晰且结构化的开发…