关于Atmega8L的bootloader的基于源代码的重新编译

我做了一个DIY 的基于Atmega8L的arduino的板子,参考了阿古(宫微宏老师)的博客介绍。我外接了8Mhz的晶振,因为Atmega8L手册上说,只允许最大加到8Mhz.

用avr编程器写入的bootloader,一个系列是由optiboot编译而来,这个版本做了一些优化,得到的bootloder跑不起来。思路回到arduino 自带源代码的Atmega8版本的bootloader , 就是在[D:\arduino\arduinosoftware]arduino-1.0-windows\arduino-1.0\hardware\arduino\bootloaders\atmega8文件夹内,


path.JPG

2012-7-19 08:11 上传
(42.85 KB)





可以看到Makefile自动编译配置文件,一个生成的bootloader文件AtmegaBOOT.hex ,还有AtMegaBOOT.c,这个目录就是我们编译所需要的源代码目录。

下面开始配置编译的环境,编译器是arduino自带的avr-gcc(avr-g++)编译器,这一套编译器组件的目录类似[D:\arduino\arduinosoftware]arduino-1.0-windows\arduino-1.0\hardware\tools\avr,实际上是winavr(读作whenever :-))的20081205版本,更多的版本在sourceforge上有,从20021111的第一版到最新的20101100都有,请goole一下。这里我们就不麻烦了,直接用arduino 的。为了方便命令行运行make命令,可以在path 中加入这个编译器的两个可执行文件目录,一个是[D:\arduino\arduinosoftware]arduino-1.0-windows\arduino-1.0\hardware\tools\avr\utils\bin,这个目录就包含了一些工具软件,例如make.exe就在这里头。还有一个可执行文件目录[D:\arduino\arduinosoftware]arduino-1.0-windows\arduino-1.0\hardware\tools\avr\bin,这里头是编译器的各个环节的工具,比如avr-gcc.exe等。下面说说怎么加path,我使用的是winxp,其它的类似。

1、先右击桌面“我的电脑”图标,点击属性

pathadding.JPG

2012-7-19 08:31 上传
(16.71 KB)







2、选择“高级”标签页,点击下方的环境变量


pathadding2.JPG

2012-7-19 08:35 上传
(36.77 KB)





3、选择当前用户的PATH 变量选项,并点击编辑


pathadding3.JPG

2012-7-19 08:39 上传
(34.89 KB)





4、在变量值内,我们可以看到系统原有的一些目录的路径,各个路径之间用分号隔开,所以,我们在最后增加一个分号,然后再在后面加上我们的两个目录,[D:\arduino\arduinosoftware]arduino-1.0-windows\arduino-1.0\hardware\tools\avr\utils\bin;[D:\arduino\arduinosoftware]arduino-1.0-windows\arduino-1.0\hardware\tools\avr\bin;注意,方括号内的内容改成你自己的arduino 目录。加好后,点击确定。这样环境变量就改好了。


path_edit

2012-7-19 10:56 上传
(10.43 KB)

path_edit





接下来测试编译环境是否正常,点击开始——》运行,输入"cmd.exe",打开命令行窗口。输入命令"make --version"和“avr-gcc--version",注意后面的参数之间用空格隔开。可以看到下面的图。


cmdtest

2012-7-19 08:55 上传
(57.1 KB)

cmdtest







好了,编译环境设置好了,下面回到刚才的源代码目录。

介绍一下这次编译的目标,使bootloader的运行的晶振频率从默认的16Mzh更改为8Mhz,波特率保持官方的19200不变。这个需要修改Makefile 文件了。

需要做3个地方的改动:

1、修改变量DIRAVR, 只需要加入这一行就可以:"DIRAVR = D://arduino/arduinosoftware/arduino-1.0-windows/arduino-1.0/hardware/tools/avr 。 说明:这是编译器组件所在的目录,我们使用的是arduino-1.0-windows所自带的winavr20081205版本,因为avr-gcc 的工具链来自gun平台,目录的斜杆尊重unix的传统,是"/",而不是windows 和dos 的传统""。

2、修改晶振频率,找到DEFS = -DF_CPU=16000000 -DBAUD_RATE=19200这一行,

修改为DEFS = -DF_CPU=8000000 -DBAUD_RATE=19200 。说明:这里设置频率为8Mhz,波特率为19200,没有更改。

3、修改优化参数,这是最重要的一步,也是整篇文章最关键的地方。winavr从20021111版到现在的最新的20100110版,gcc的内核版本,从原来的gcc-3.4.2,发展到了现在的gcc-4.3.2版本。而这个Atmega8BOOT.c 编写于2003年,Makefile的最新版本是2004年,年代太久远了。所以需要修改优化参数。如果不修改,生成的中间代码太大了,然后链接不成最后的hex文件。找到

OPTIMIZE = -Os , 修改为OPTIMIZE = -Os -fno-inline-small-functions -fno-split-wide-types -mshort-calls 。说明:-fno-inline-small-functions 这个优化选项是最重要的,意思是告诉gcc编译器,不要把一些短函数,变成inline的处理.inline 处理的原理是,把一些短小的函数,不是编译成rjmp,rcall之类的汇编指令,而是把这个短函数的代码,变成了不用回调的顺序执行码,安放到汇编代码所调用的位置。gcc 是想把速度提高起来,因为回调用到堆栈操作啊啥的,比较慢,可是代码却臃肿了,到处都是重复的代码。所以,加上了这个优化选项,等于是告诉gcc编译器,我不要速度了,我要的是魔鬼身材:-)。编译后得到的hex的代码有2718字节的大小,大约3K。



修改后的Makefile的内容如下:
# Makefile for ATmegaBOOT
# E.Lins, 2004-10-14

# program name should not be changed...
PROGRAM = ATmegaBOOT

PRODUCT=atmega8

# enter the parameters for the UISP isp tool
ISPPARAMS= -dprog=stk500 -dserial=$(SERIAL) -dspeed=115200


#DIRAVR = /usr/local/avr
DIRAVR = D://arduino/arduinosoftware/arduino-1.0-windows/arduino-1.0/hardware/tools/avr
DIRAVRBIN = $(DIRAVR)/bin
DIRAVRUTILS = $(DIRAVR)/utils/bin
DIRINC = $(DIRAVR)/include
DIRLIB = $(DIRAVR)/avr/lib


MCU_TARGET = atmega8
LDSECTION= --section-start=.text=0x1c00
FUSE_L = 0xdf
FUSE_H = 0xca
ISPFUSES = $(DIRAVRBIN)/uisp -dpart=ATmega8 $(ISPPARAMS) --wr_fuse_l=$(FUSE_L) --wr_fuse_h=$(FUSE_H)
ISPFLASH = $(DIRAVRBIN)/uisp -dpart=ATmega8 $(ISPPARAMS) --erase --upload if=$(PROGRAM).hex -v


OBJ = $(PROGRAM).o
#OPTIMIZE = -Os ;old version ,this trig for optimize,will lead to a too big bin file ,which will get out the region of .text ,we need to optimize more.the reason is this Make file is too old ,and should compiled under the winavr20040720 toolchain. but now we use the winavr20081205 toolchain.
OPTIMIZE = -Os -fno-inline-small-functions -fno-split-wide-types -mshort-calls

#DEFS = -DF_CPU=16000000 -DBAUD_RATE=19200 ; old version , the next is new ,which turn the crystal frequency from 16Mhz to 8 Mhz
DEFS = -DF_CPU=8000000 -DBAUD_RATE=19200
LIBS =

CC = $(DIRAVRBIN)/avr-gcc


# Override is only needed by avr-lib build system.

override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -D$(PRODUCT) $(DEFS) -I$(DIRINC)
override LDFLAGS = -Wl,-Map,$(PROGRAM).map,$(LDSECTION)

OBJCOPY = $(DIRAVRBIN)/avr-objcopy
OBJDUMP = $(DIRAVRBIN)/avr-objdump
SIZE = $(DIRAVRBIN)/avr-size

all: $(PROGRAM).elf lst text asm size

isp: $(PROGRAM).hex
$(ISPFUSES)
$(ISPFLASH)

$(PROGRAM).elf: $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)

clean:
rm -rf *.s
rm -rf *.o *.elf
rm -rf *.lst *.map

asm: $(PROGRAM).s

%.s: %.c
$(CC) -S $(CFLAGS) -g1 $^

lst:$(PROGRAM).lst

%.lst: %.elf
$(OBJDUMP) -h -S $< > $@

size: $(PROGRAM).hex
$(SIZE) $^

# Rules for building the .text rom images

text: hex bin srec

hex:$(PROGRAM).hex
bin:$(PROGRAM).bin
srec: $(PROGRAM).srec

%.hex: %.elf
$(OBJCOPY) -j .text -j .data -O ihex $< $@

%.srec: %.elf
$(OBJCOPY) -j .text -j .data -O srec $< $@

%.bin: %.elf
$(OBJCOPY) -j .text -j .data -O binary $< $@

复制代码准备了这么多,就是见证奇迹的时刻了:)

接下来,就是进行编译的过程了。

1、在打开命令行窗口,修改当前目录到所在的盘。介绍一下Dos 命令,默认打开的命令行窗口是C盘,我们要切换到保持源文件的盘,比如我的是D:盘,在命令行中输入"D:" ,按回车键。更改目录 ,输入" cd[\arduino\arduinosoftware]arduino-1.0-windows\arduino-1.0\hardware\arduino\bootloaders\atmega8" 。方括号内请你自己改成自己的目录。

cd

2012-7-19 10:00 上传
(33.09 KB)

cd



2、在atmega8目录下输入命令"make clean" ,这是把以前编译过程的中间代码,结果代码等.o .a .hex 扩展名文件全部清空,为新的编译清理空间。

make clean

2012-7-19 10:04 上传
(42.49 KB)

make clean



3、输入命令"make” ,是不是太容易了:)刷刷,编译过程一下子过了,最后生成AtmegaBOOT.hex文件等等,是不是特兴奋?


final files

2012-7-19 10:11 上传
(69.1 KB)

final files





打开Atmega8目录,可以看到我们自己搞出来的hex了吧,呵呵。



之后的事情,我想大家各显神通,用编程器把这个hex烧到Atmega8L芯片里头吧。

这个芯片写好了我们自制的bootloader,已经是arduino 的家族成员了。

下面还有一个工作要做,就是把我们的信息加到arduino 的board的参数选项中。打开D:\arduino\arduinosoftware\arduino-1.0-windows\arduino-1.0\hardware\arduino文件夹的boards.txt 文件,进行修改,修改的模板用ATmega8的直接复制修改。参考看下面的代码:##############################################################

atmega8.name=catnull modified w/ ATmega8L

atmega8.upload.protocol=arduino
atmega8.upload.maximum_size=7168
atmega8.upload.speed=19200

atmega8.bootloader.low_fuses=0xdf
atmega8.bootloader.high_fuses=0xca
atmega8.bootloader.path=atmega8
atmega8.bootloader.file=ATmegaBOOT.hex
atmega8.bootloader.unlock_bits=0x3F
atmega8.bootloader.lock_bits=0x0F

atmega8.build.mcu=atmega8
atmega8.build.f_cpu=8000000L
atmega8.build.core=arduino
atmega8.build.variant=standard复制代码说明:其实就把16000000L改成8000000L。

之后的事情,arduino 人都知道了。





思考题:1、编译过程中出现了一个警告,你打算如何把这个警告消除呢?是不是遵从GPL2.0的标准,改一下AtmegaBOOT.c的代码?

2、烧写bootloader时,avr芯片的熔丝位Hfuse 和Lfuse的数值在哪里可以找到?



最终生成的bootloader,在arduino1.0版测试通过,在arduino-0200版本测试通过,在1.0.1最新版测试通不过:(

经过一个下午的努力,在RXD 和TXD(2、3)脚和VCC之间接1K OM的电阻后,在1.0.1版本测试也正常了:)

atmega8l.rar

(30.23 KB, 下载次数: 136)

2012-8-31 21:18 上传
点击文件名下载附件

适合arduino1.0版测试通过


via - 极客工坊

标签: Arduino教程