[转载]自己动手编写嵌入式Bootloader之(3)

ARM学习(0)NXP MCU BootLoader的理解与实现 BootLoader的理解与实现 阅读详情
第三部分:源代码,运行结果

这一部分将对前文没有提到的几段关键代码进行简单说明,介绍一下源代码组织结构和Makefile系统,展示一下实验运行结果,并提供全部源代码下载。

1. 定时器初始化和延时程序

因为在 CS8900A的驱动程序中需要用到延时,因此有必要对S3C2440的计时器进行使能和初始化,并编写延时程序。

S3C2440A共有5个定时器,编号为Timer0 ~ Timer4。其中Timer0 ~ Timer3都有输出引脚,可以通过定时器来控制引脚电平周期性的变化,这称为脉冲宽度调制(PWM:Pulse Width Modulation)功能。而Timer4没有输出引脚,也就没有PWM功能,所以Timer4常被程序里的延时函数使用。

定时器部件的时钟源为PCLK,但是需要经过两级预分频之后才真正供定时器使用。第一级预分频由TCFG0寄存器控制,其位[7:0]设置预分频器0的值,供Timer0和Timer1使用,位[15:8]设置预分频器1的值,供Timer2 ~ Timer4使用。第二级预分频由TCFG1寄存器控制,其每四位控制一个定时器,可以从2分频、4分频、8分频、16分频、外接TCLK0/TCLK1 这五种频率中选择。

我们的延时函数使用Timer4,其它定时器全部关闭。初始化程序中设置:TCFG0 = 0x0f00; 表示Timer4的第一级预分频值为 15+1 = 16。寄存器TCFG1使用默认值全0,表示第二级预分频为2分频。前面已经设置PCLK为50MHz,这样Timer4实际的工作频率为:

50MHz/16/2 = 50000000/32 = 1562500Hz

注意计算时钟频率时的MHz是指10^6,而不是2^20;同理KHz是指1000Hz,而不是1024Hz。

我们在TCON中把Timer4设为”自动加载“。当Timer4启动时,TCNTB4的值将被自动装入内部寄存器TCNT4,然后在工作频率下,TCNT4开始减1计数,当到达0时,TCNTB4的值又被自动装入TCNT4,下一个计数流程开始。我们把TCNTB4设为15625,则一个计数流程的的长度为10毫秒。

假设要延时的时间为msec毫秒,则共需要的计数值为 tmo = msec*15625/10,设一个变量timestamp保存已经过去的时间戳,每次读取TCNT4的值后更新timestamp,直到它大于 tmo 。程序如下:

    while( timestamp < tmo )
    {
        thisdec = TCNTO4 & 0xffff;
        if( lastdec >= thisdec )  
/* normal mode */
        {  
            timestamp += lastdec - thisdec;
        }
        else         
/* we have an overflow ... */
        {  
            timestamp += lastdec + TIMER_LOAD_VAL - thisdec;
        }
        lastdec = thisdec;
    }


TCNT4的值可由寄存器TCNTO4读出。程序中保存了最近两次读出的TCNTO4值, 如果本次值比上次小,说明在同一个计数流程内;如果本次值比上次大,说明已经进入了下一个计数流程。

2. 串口标准输入输出

要想在Bootloader中使用scanf()和print()并不容易,因为不能直接使用C库函数。scanf()要从串口获得输入, print()要向串口进行输出。必须自己实现常用的C库函数, 不仅包括输入输出函数,还包括字符串操作函数如strcmp(), strcpy()等。幸好在《嵌入式Linux应用开发完全手册》这本书的源代码中提供了这样简化的C库,所以就直接拿来用了。

代码中定义了两个全局数组作为输入输出缓冲区:
static unsigned char g_pcOutBuf[ 1024 ];
static unsigned char g_pcInBuf[ 1024 ];
其实我们可以把这两个缓冲区定位在CPU的 SteppingStone 里面,这样可以节省2K的空间。

scanf()的实现里面调用 getc() 函数, printf() 的实现里面调用 putc() 函数。我们自己写getc()函数为从串口读取字符, putc()函数实现为向串口发送字符, 这样标准输入输出就跟串口联系在一起了。

/* 发送一个字符 */
void putc(unsigned char c)
{
    /* 等待,直到发送缓冲区中的数据已经全部发送出去 */
    while (!(UTRSTAT0 & TXD0READY));
    /* 向UTXH0寄存器中写入数据,UART即自动将它发送出去 */
    UTXH0 = c;
}

/* 接收字符 */
unsigned char getc(void)
{
    unsigned char ret;
    /* 等待,直到接收缓冲区中的有数据 */
    while(!(UTRSTAT0 & RXD0READY));
    /* 直接读取URXH0寄存器,即可获得接收到的数据 */    
    ret = URXH0;
    if (ret == 0x0d || ret == 0x0a)
    {
        putc(0x0d);
        putc(0x0a);
    }
    else
    {
        putc(ret);        
    }
    return ret;
}


3. 源代码组织结构

源代码跟目录下只有两个文件, 主Makefile和链接脚本sboot.lds。
文件夹start内有start.S和nand.c,前者是上电后最初运行的汇编代码,后者含有Nand Flash的读函数,负责把S-Boot代码从Nand拷贝到RAM中。
文件夹main内有main.c,是一个死循环,提供若干菜单供用户选择,然后调用相应功能的程序。
文件夹lib内是简化和移植过的C标准库,包括输入输出和字符串操作函数。
文件夹include内是一些头文件。
文件夹app内有boot_linux.c和tftp.c,从名字就能看出它们的功能。
文件夹device内含有设备驱动程序,如串口初始化、定时器初始化和延时函数、网卡驱动、网络协议实现等。

每个文件夹内都有自己的Makefile,根目录下的主Makefile会进入各个子目录并调用各自的Makefile。每个子目录下的Makefile把自己编译的代码链接成一个build-in.o文件, 主Makefile把各个子目录下的build-in.o链接成一个可执行文件。

编译器使用自己制作的 arm-hwlee-linux-gnueabi-gcc. 可以从这里下载。  给gcc增加 -nostdinc 选项, 表示不使用标准C库函数,不到/usr/include目录下寻找包含文件, 只在-I$(INCLUDEDIR)指定的目录寻找包含文件。

4. 提供全部源代码下载:


文件:S-Boot.tar.gz
大小:41KB
下载:下载


5. 运行结果截图



图中,首先选择3从TFTP服务器下载内核到RAM中, 然后选择4从RAM成功启动内核。

选择2还有通过串口Kermit协议下载内核的功能,前文没有对这部分代码作分析,有时间再补上。下面附一张截图:


 

 TAG ARM Linux Bootloader
IsaacLab从入门到精通(二) 导入自定义机器人 IsaacLab系列第二讲,导入自定义的机器人及设置 阅读详情

相关推荐

手把手教你搞定Pattern Recognition期刊的LaTeX投稿(附完整模板下载与避坑指南)

本文详细指导如何在Pattern Recognition期刊上使用LaTeX进行投稿,包括模板下载、环境配置、核心排版规范及投稿材料准备。特别强调期刊对格式的严格要求,如数学符号、图像引用等细节,并提供实用技巧和避坑指南,帮助作者高效完成投稿流程。

weixin_30876945的博客 394

自己动手编写嵌入式Bootloader之(3)

jun2ran的专栏 892

【Agent】多智能体框架MetaGPT入门教程

创建一个 Action 类的子类 SimpleWriteCode,子类中定义好 prompt,并解析返回结果。在 MetaGPT 中,

酒酿小圆子呀~ 3137

自己动手写一个简单的bootloader

自己动手写一个简单的bootloader 15年10月31日19:44:27 (一) start.S 写这一段代码前,先要清楚bootloader开始的时候都做什么了。无非就是硬件的初始化,我们想要写一个简单的bootloader,它的功能只是要能启动内核就行,因此,与uboot相比,它要做的东西很少。 总结出来就是: (1)关看门狗; (2)初始化时钟,设置分频系数,让板子跑的更

吾皇的博客 1万+

MOS 管驱动设计细节,波形分析

一般认为MOSFET是电压驱动的,不需要驱动电流。然而,在MOS的G S两级之间有结电容存在,这个电容会让驱动MOS变的不那么简单。 如果不考虑纹波和EMI等要求的话,MOS管开关速度越快越好,因为开关时间越短,开关损耗越小,而在开关电源中开关损耗占总损耗的很大一部分,因此MOS管驱动电路的好坏直接决定了电源的效率。 对于一个MOS管,如果把GS之间的电压从0拉到管子的开启电压所用的时间越短,那么MOS管开启的速度就会越快。与此类似,如果把MOS管的GS电压从开启电压降到0V的时间越短,那么MOS管关断的

m0_50862404的博客 1万+

Tomcat漏洞——弱口令爆破

靶机:CentOS7 IP:192.168.100.40。攻击机:kali IP:192.168.100.60。版 权 声 明:本博客所有文章除特别声明外,均采用。文章版权归作者所有,未经允许请勿转载!作 者:PeiyuJue。

weixin_57379923的博客 909

浅析嵌入式系统之uboot详解(5.3)—PWM定时器(番外)

uboot详解—PWM定时器(番外)1. 前言2. PWM定时器2.1 概述2.2 实例3. 小结 1. 前言   这篇文章是一些拓展内容,如果想了解uboot的启动过程,可以先跳过本章,如果需要掌握一些编写裸机程序或者内核与计时器相关的驱动的知识,可以了解一下。 2. PWM定时器 2.1 概述   脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在测量、通信到功率控制与变换的许多

一只立志于养老婆的程序猿 1374

写给音响工程师的科普文章(二)——从模电角度去了解调音台话放

    上一篇讲到调音台第一级放大电路为差分放大器,关于差分放大器的基础知识可以参考以下资料:https://wenku.baidu.com/view/e6a46aaa2af90242a995e537 在教材中的差分放大器基本形式是这样子的,在实际电路中把RE电阻换成两个2倍RE,于是变成这样 然后我们现在来对比调音台中的差分放大器和教材中的有什么区别,我就拿yamaha 01V 96来说...

huanghaoAudio的博客 7702

这样开发PWM,保证你准时下班

摘要本篇笔记主要记录基于MBD模型设计的PWM输出步骤和方法。前期工具箱的安装不在本文档讨论范围内。准备工作安装好MPC5744基于模型的工具箱和支持包,这个可以在NXP官网下载2,按照文档配置编译器和设置路径以及license激活,QSG里面写的很清楚,这里不在赘述。模型设计正确安装MBD工具箱后,在simulink里面可以看到到MPC5744的外设和例程,这里我们设计...

wgp2hpp的博客 842

水文仿真软件:HEC-RAS (Hydrologic Engineering Center‘s River Analysis System)_(7).一维非稳态水力模型

自定义脚本是通过编程语言(如 Python)编写的一系列自动化任务,可以帮助用户更高效地处理数据和运行模型。编写脚本:使用 Python 或其他编程语言编写自定义脚本。集成脚本:将脚本集成到 HEC-RAS 中,实现自动化数据处理和模型运行。

kkchenjj的博客 932

2025华为杯第二十二届中国研究生数学建模竞赛E题:高速列车轴承智能故障诊断问题 - 完整解题分析+完整MATLAB源码!

🎓 本文收录于 《滚雪球学数学建模》专栏,本专栏专注于从零基础出发,带你循序渐进掌握数学建模的核心方法与思维路径。通过“滚雪球式”学习法,从最简单的生活化案例到经典建模工具,再到省赛、国赛真题实战演练,逐步积累知识与技能,帮助你搭建完整的建模体系。无论你是刚接触建模的新生,还是希望提升科研与竞赛能力的学者与工程师,本专栏都将为你提供一条清晰、高效、可实操的建模成长路线,助力你快速进阶,突破难点,迈向数学建模竞赛与实际应用的更高峰 🚀!

**My Coding Family** 1992

[转载]自己动手编写嵌入式Bootloader之(2)

第二部分:通过网口下载内核映像要实现通过网口下载文件的功能,从底层到上层需要做的工作包括:开发板上的网卡芯片的驱动程序;TCP/IP协议栈的实现;TFTP客户端应用程序的实现。我们使用的OK2440开发板配备CS8900A网卡芯片。 为了简单起见,网络数据包的发送和接收都使用轮询方式,不使用中断;协议栈只使用ARP/IP/UDP协议,不涉及TCP及其他协议;应用程序

DerekYao的专栏 1220

STM32F103(二十三)通用同步异步收发器(USART)

学习板:STM32F103ZET6 往期博客: STM32F103五分钟入门系列(一)跑马灯(库函数+寄存器)+加编程模板+GPIO总结 STM32F103五分钟入门系列(二)GPIO的七大寄存器+GPIOx_LCKR作用和配置 STM32F103五分钟入门系列(三)GPIO的常用库函数使用方法总结+一个网络上的误区 STM32F103五分钟入门系列(四)蜂鸣器实验(库函数+寄存器) STM32F103五分钟入门系列(五)按键实验(库函数+寄存器) STM32F103五分钟入门系列(六)时钟框图+相关寄存器

Curnane0_0的博客 1019

[转载]自己动手编写嵌入式Bootloader之(1)

第一部分:基本功能流程CPU上电后会从IO空间的某地址取第一条指令。但此时:PLL没有启动,CPU工作频率为外部输入晶振频率,非常低;CPU工作模式、中断设置等不确定;存储空间的各个BANK(包括内存)都没有驱动,内存不能使用。在这种情况下必须在第一条指令处做一些初始化工作,这段初始化程序与操作系统独立分开,称之为bootloader。实际上,很少有必要自己写一个Bootloader,因为

DerekYao的专栏 1674

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Bootloader

我认为学习和应用u-boot对于刚接触的人来说最大的困难在于其功能比较全,文件(.S .c .h makefile文件)非常多,结构也比较复杂,难以理清各方面的关系。熟悉了一段时间之后,发现还是有很多的规律可以总结的。 一、首先要理解bootloader的作用,以及U-boot具体可以实现什么样的一些功能。 二、弄清U-boot的启动流程,这时候需要跟着整个程序走一遍,先不管实现这个流程的代码

颇锐克(公众号:颇锐克科技共享) 1万+

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

如何学习嵌入式bootloader

本文是摘自一个大侠对vivi源码的分析的一篇文章,个人觉得前面这些文字对那些苦苦挣扎在研究bootloader的同志们会有一些帮助,甚至是鼓励,所以充满感激地将它转载了过来。 通过vivi研究bootloader有一段时间了,基本是在与之相关的基础方面做工作,还没有真正深入研究vivi。以后的学习重心就要放到研究vivi源代码上面了。我想,真正细致地弄清楚vivi实现的细节,

u012138828的专栏 1016

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

自己动手写bootloader

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://doublewen.blog.51cto.com/3097132/802508                                                 为了写一个bootloader让板子跑起来,首先我们要知道bootloader是个什么东东才行。简单

shangyaowei的专栏 609

嵌入式开发实战指南:从环境搭建到AI部署的进阶路线与资源

嵌入式系统作为连接物理世界与数字世界的核心技术,其核心在于对硬件资源的直接控制与实时响应。其工作原理基于微处理器或微控制器,通过编写底层驱动和应用程序,实现对传感器、执行器等外设的精准管理。掌握嵌入式开发,对于实现物联网、智能硬件和边缘计算等现代技术至关重要,广泛应用于工业自动化、消费电子和汽车电子等领域。本文聚焦于嵌入式开发中的关键实践,特别是针对STM32和嵌入式Linux的环境配置,以及AI模型在边缘设备(如Jetson Nano)的部署流程,提供了从工具链选择到项目实战的清晰路径,旨在帮助开发者高效

weixin_33853827的博客 421

嵌入式linux系统移植(一)

内容: 交叉编译环境 bootloader功能子系统 内核核心子系统 文件系统子系统要点: 搭建交叉编译环境 bootloader的选择和移植 kernel的配置、编译、移植和调试 根文件系统的制作 移植的基本步骤: 确定目标机、主机的连接方式 安装交叉编译环境 搭建主机-目标机的数据传输通道 编写三大子系统 烧写测试 目标机和主机的连接方式...

a619861986的博客 493

ARM与嵌入式linux的入门建议 (六步曲)(转载)

由于很多人总问这个问题,所以这里做一个总结供大家参考。这里必须先说明,以下的步骤都是针对Linux系统的,并不面向WinCE。也许你会注意到,现在做嵌入式的人中,做linux研究的人远比做WinCE的人多,很多产家提供的资料也是以linux为主。我一直很难理解,其实WinCE的界面比linux的界面好看多了,使用起来也很方便,更为重要的是,WinCE的开发和Windows下的开发基本一样,学起来简

只有不想做的,没有做不到的 1028

<2012 12 09> [原创]Bootloader(U-boot)学习研究心得

  我认为学习和应用u-boot对于刚接触的人来说最大的困难在于其功能比较全,文件(.S .c .h makefile文件)非常多,结构也比较复杂,难以理清各方面的关系。熟悉了一段时间之后,发现还是有很多的规律可以总结的。 一、首先要理解bootloader的作用,以及U-boot具体可以实现什么样的一些功能。 二、弄清U-boot的启动流程,这时候需要跟着整个程序走一遍,先不管实现...

dizhuang5374的博客 631

嵌入式Linux软件开发学习计划

无意中看到这篇文章,博主也

Robot Man的技术博客 1390

bootloader启动过程详细说明

今天早上看了一上午的bootloader简单源码,终于捋顺了bootloader的执行过程,之前只是知道bootloader代码会先被irom中的代码拷贝到iram中一部分,然后执行这部分代码,会把整个bootloader代码拷贝到sdram中,最终在sdram执行剩下的代码,而这段代码会把kernel拷贝到sdram的某个地址,最终引导起来整个内核。但是我今天早上看代码的时候看到一个问题,我所有...

weixin_30788619的博客 136

(转载)循序渐进学习嵌入式Linux开发技术

<br />再次申明,本文是转载,为以后查找留个记号。<br /> <br />嵌入式时代已经来临,你还在等什么?<br />  ---循序渐进学习嵌入式开发技术<br />最近经常有用人单位给我打来电话,问我这有没有嵌入式Linux方面的开发人员,他们说他们单位急需要懂得在嵌入式linux环境下的软件开发人员,我回答说,现在每年毕业的大学生那么多,还招不到合适的软件开发人员吗?他跟我说,毕业大学生虽然多,但大部分都能力不够,不能达到他们的工作的要求。<br />该公司HR的一句话说出来我们现在的大学教学和

ohmytime的专栏 1154
上一篇: [转载]自己动手编写嵌入式Bootloader之(2)
下一篇: boost源码剖析之:Tuple Types(rev#2)
NetGeek
博客等级 码龄22年 15粉丝 2原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值