浙江大学嵌入式系统课程
这是一次痛并快乐着的实验。
以下引用实验要求:
David Welch的 GitHub 的
bootloader05给出了一个非常简单的RPi bootloader,他的代码链接在内存的0x00020000位置,一直在监听串口是否有XMODEM协议的文件下载,如果有就开始接收数据,并复制到0x00008000位置,传输完成后跳转到 0x00008000去执行。TA写了一个Python脚本,按照下面的命令调用脚本可以下载并执行用户程序
python xmodem-loader.py -p com3 -b 115200 output.bin你的任务是修改bootloader和python脚本实现如下功能:
调用命令
python xmodem-loader.py -p com3 -b 115200启动脚本并且与板卡建立串口连接,之后可以发送下面的命令。load *.bin 下载程序*.bin go 执行已下载的程序 peek addr 以一个字为单位读取内存中addr位置的数据(addr是4字节对齐,十六进行的形式,长度为8,例如 0x00008000),并以十六进制的形式输出 poke addr data 以一个字为单位修改内存中addr位置的数据为data(addr是4字节对齐,十六进行的形式,长 度为8, data也是十六进行的形式,长度为8) verify *.bin 验证已下载的程序和*.bin是否完全相同。
|
|
简要分析bootload05.c
这个bootloader确实很短,不过想弄明白还是得花点时间的。其主要思想就是用状态机控制数据的传输过程,简单来说就像下面这样:

可以看到传输过程中先发送一个0x01,即SOH(start of headline),然后分别检查第二次和第三次接收到的数据是否为block和255-block,block为当前块号,通过后就开始接收128位的数据流,最后在Statue 131检查CRC的值。另外,在数据全部传输完成后bootloader会收到一个0x04信号,即EOT (end of transmission),此时bootloader会跳转到0x00008000去执行下载的程序。
弄清楚流程后修改就容易多了,为了区分指令类型我在第一个号后添加了一个指令信号,状态机如下图所示:

也就是把133-136这几个状态作为PEEK和POKE的addr,137-140作为POKE的data.
另外原本的bootloader05对0x04这一信号的判定是放在状态机外的,总让人觉得不舒服,我就把它也合并到了State 0状态中去判断了。
xmodem-loader.py的修改
没学过Python的表示压力山大,所幸TA提供的xmodem-loader.py已经把关键的数据传输部分写好了,剩下的就是写一个能够接受用户输入,并对Raspberry Pi作出相应请求的控制器就好了(说的这么厉害其实还不就是while True= =)
效果演示
- load & verify

- peek & poke

- re-verify

- go

程序源码
因为代码实在太长了,就不贴在这篇博文里了,有兴趣的可以点 这里 查看。
补充内容
编译
kernel.img和blinker.bin进入
bootloader05目录,编辑Makefile第一行,修改ARMGNU为你使用的交叉编译器,如ARMGNU ?= arm-linux-gnueabi,保存后执行make命令。另外据同学反应在ubuntu 12.04及以下版本可能会出现
arm-linux-gnueabi-as错误。目前已知的解决方案是升级系统(别打我)。找不到blinker.bin,python脚本提示 “file not exist”
确保blinker.bin与脚本在同一目录下。找不到blinker.bin的请先编译
kernel.img和blinker.bin。