了解 Arduino 引导加载程序的闪存组成
Understanding flash composition of Arduino bootloader
我正在尝试了解 Arduino 引导加载程序。我在这里找到了一些介绍:Arduino Bootloader,但我需要更多详细信息,因此我正在寻求帮助。
在我的研究过程中,我找到了一个起点:好吧,Arduino(atmega 系列)有一个特定的闪存块专用于引导加载程序。一旦 mcu 有了引导加载程序,它就可以通过串口下载新程序并将其存储在闪存中,地址为 0x00。
让我们为这道题分配atmega328p。
#1 - 如果您查看数据表第 343 页,您会看到一个 table,显示有关引导加载程序大小的一些信息:
通过这个table我明白了:如果我将BOOTSZ1/0设置为0/0,我可以有一个2K的bootloader,它将存储在闪存堆栈中:0x3800 ~ 0x3FFF。
#2 - 如果您打开 Arduino 生成的 ATMEGA328_BOOTLOADER 的 hex 文件,您将看到存储在以下位置的引导加载程序:
:10**7800**000C94343C0C94513C0C94513C0C94513CE1
至
:10**7FF0**00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF91
如果您考虑 7FF0 - 7800,您将得到 7F0(2K 字节的程序)
#3 - 如果您打开 makefile (C:\Program Files (x86)\Arduino\hardware\arduino\avr\bootloaders\atmega),您将看到 atmega328 的这个参数:
atmega328: LDSECTION = --section-start=.text=0x7800
其中 0x7800 与来自引导加载程序的 hexa 文件匹配。
问题:
1- 为什么数据表告诉我引导加载程序有一个特殊的位置,而 Arduino 的 makefile 强制它存储在不同的地方?
2- hexa 文件的行是什么意思?
:10E000000D9489F10D94B2F10D94B2F10D94B2F129
:10 : (?)
E000 : Address
00 : (?)
0D9489F10D94B2F10D94B2F10D94B2F1 : data (?)
29 : CRC (?)
首先,我不确定我们有相同的 atmel 数据表;你的 table 我的是 27-7,但无论如何数据是一样的。
免责声明:我对此不是 100% 确定,但我非常有信心。
我认为这里的"problem"就是那个"words"。阅读他们写的核心概述
Most AVR instructions have a single 16-bit word format. Every program memory address contains a 16- or 32-bit instruction
这意味着指令是 2 字节宽。所以你的地址0x3800对应的是从内存开始的0x7000字节,而bootloader的结尾0x3FFF对应的是字节0x7FFE和0x7FFF。
这可以从内存大小上得到证实:0x7FFF对应32k,也就是可用的flash。由于引导加载程序位于内存的末尾(如 DS 中的图片所示),这意味着 0x3FFF 应该是最后一个内存单元。
编辑:
我回答的时候没有看问题的第二部分。该格式就是所谓的 Intel Binary 格式。有关详细信息,请参阅 Wikipedia。这是一个简短的总结。
您正确识别了字段划分:
: : Start code
10 : Number of data bytes (in this case: 16)
E000 : Starting address of the data bytes
00 : Record type (in this case: data)
0D9489F10D94B2F10D94B2F10D94B2F1 : data payload (in this case: 16 bytes)
29 : CRC
记录类型可以是
- 00: 数据
- 01: 文件结束
- 02:扩展段地址
- 03:起始段地址
- 04:扩展线性地址
- 05:起始线性地址
CRC是对所有字节求和(从长度1开始,所以最开始),然后得到LSB,最后进行2补码。在这种情况下,总和为 2519,即十六进制的 0x9D7。低位字节D7对应215,其2的补码可以计算为256-x,所以41,也就是16进制的0x29。
我正在尝试了解 Arduino 引导加载程序。我在这里找到了一些介绍:Arduino Bootloader,但我需要更多详细信息,因此我正在寻求帮助。
在我的研究过程中,我找到了一个起点:好吧,Arduino(atmega 系列)有一个特定的闪存块专用于引导加载程序。一旦 mcu 有了引导加载程序,它就可以通过串口下载新程序并将其存储在闪存中,地址为 0x00。
让我们为这道题分配atmega328p。
#1 - 如果您查看数据表第 343 页,您会看到一个 table,显示有关引导加载程序大小的一些信息:
通过这个table我明白了:如果我将BOOTSZ1/0设置为0/0,我可以有一个2K的bootloader,它将存储在闪存堆栈中:0x3800 ~ 0x3FFF。
#2 - 如果您打开 Arduino 生成的 ATMEGA328_BOOTLOADER 的 hex 文件,您将看到存储在以下位置的引导加载程序:
:10**7800**000C94343C0C94513C0C94513C0C94513CE1
至
:10**7FF0**00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF91
如果您考虑 7FF0 - 7800,您将得到 7F0(2K 字节的程序)
#3 - 如果您打开 makefile (C:\Program Files (x86)\Arduino\hardware\arduino\avr\bootloaders\atmega),您将看到 atmega328 的这个参数:
atmega328: LDSECTION = --section-start=.text=0x7800
其中 0x7800 与来自引导加载程序的 hexa 文件匹配。
问题:
1- 为什么数据表告诉我引导加载程序有一个特殊的位置,而 Arduino 的 makefile 强制它存储在不同的地方?
2- hexa 文件的行是什么意思?
:10E000000D9489F10D94B2F10D94B2F10D94B2F129
:10 : (?)
E000 : Address
00 : (?)
0D9489F10D94B2F10D94B2F10D94B2F1 : data (?)
29 : CRC (?)
首先,我不确定我们有相同的 atmel 数据表;你的 table 我的是 27-7,但无论如何数据是一样的。
免责声明:我对此不是 100% 确定,但我非常有信心。
我认为这里的"problem"就是那个"words"。阅读他们写的核心概述
Most AVR instructions have a single 16-bit word format. Every program memory address contains a 16- or 32-bit instruction
这意味着指令是 2 字节宽。所以你的地址0x3800对应的是从内存开始的0x7000字节,而bootloader的结尾0x3FFF对应的是字节0x7FFE和0x7FFF。
这可以从内存大小上得到证实:0x7FFF对应32k,也就是可用的flash。由于引导加载程序位于内存的末尾(如 DS 中的图片所示),这意味着 0x3FFF 应该是最后一个内存单元。
编辑:
我回答的时候没有看问题的第二部分。该格式就是所谓的 Intel Binary 格式。有关详细信息,请参阅 Wikipedia。这是一个简短的总结。
您正确识别了字段划分:
: : Start code
10 : Number of data bytes (in this case: 16)
E000 : Starting address of the data bytes
00 : Record type (in this case: data)
0D9489F10D94B2F10D94B2F10D94B2F1 : data payload (in this case: 16 bytes)
29 : CRC
记录类型可以是
- 00: 数据
- 01: 文件结束
- 02:扩展段地址
- 03:起始段地址
- 04:扩展线性地址
- 05:起始线性地址
CRC是对所有字节求和(从长度1开始,所以最开始),然后得到LSB,最后进行2补码。在这种情况下,总和为 2519,即十六进制的 0x9D7。低位字节D7对应215,其2的补码可以计算为256-x,所以41,也就是16进制的0x29。