1
39
关于零地址0不是空指针。“空指针”是一个更抽象的东西:一个特殊的值,应用函数应该识别为无效。C表示特殊值为0,而 语言 称去引用它是“未定义的行为”,在微控制器的简单世界中,它通常具有非常明确的效果。 ATMega引导加载程序通常,在复位时,AVR的程序计数器(PC)初始化为0,因此微控制器开始在地址0处执行代码。 但是,如果设置了引导重置保险丝(“bootsrt”),则程序计数器将被初始化为内存上端的一个块的地址(这取决于保险丝的设置方式,请参见 a datasheet (PDF,7 MB)以获取详细信息)。如果你真的想要,从那里开始的代码可以做任何事情。如果你使用一个icsp,你可以把你自己的程序放在那里(引导加载程序通常不能覆盖自己)。 但通常情况下,这是一个特殊的计划-A 引导加载程序 -能够 从外部源读取数据 (通常通过UART,我 二 c、罐等)至 重写程序代码 (存储在内部或外部存储器中,具体取决于micro)。bootloader通常会寻找一个“特殊事件”,它实际上可以是任何事情,但是对于开发来说,它是从数据总线上提取新代码最方便的事情。(对于生产,它可能是一个特殊的逻辑级别,因为它几乎可以立即检查。)如果引导加载程序看到特殊事件,它可以进入引导加载模式,在那里它将重新刷新程序内存,否则它将控制权移交给用户代码。 另一方面,引导装载程序保险丝和上内存块的作用是允许使用引导装载程序 不 对原始软件的修改(只要它没有一直扩展到引导加载程序的地址中)。bootloader补充说,你可以用原来的十六进制和所需的保险丝来代替闪烁,而可以用原来的十六进制、bootloader和修改过的保险丝来闪烁。 无论如何,在Arduino的案例中,我相信它使用了来自 STK500 ,它试图通过UART进行通信,如果在分配的时间内没有得到响应:
或者,如果它通过获得意外响应而错误过多:
它将控制权传递回位于0的主程序。在上面看到的Arduino源中,这是通过调用
因为它是C函数调用,所以在PC跳到0之前,它会将当前PC值推送到堆栈上,该堆栈还包含引导加载程序中使用的其他变量(例如
bootloader唯一持久的影响是对硬件(外围设备)寄存器的修改,好的bootloader不会处于有害状态(打开可能在尝试睡眠时浪费电能的外围设备)。通常情况下,也可以完全初始化将要使用的外围设备,因此即使引导装载程序做了一些奇怪的事情,您也可以按照自己的意愿来设置它。 阁楼装载机
正如您所提到的,在Attinys上,引导装载程序的保险丝或内存并不奢侈,所以您的代码总是从地址0开始。您可以将引导加载程序放入一些更高的内存页,并将重置向量指向它,然后每当您收到要闪存的新十六进制文件时,获取地址为0:1的命令,将其替换为引导加载程序地址,然后将替换的地址存储到其他地方以调用正常执行。(如果是
|
2
1
编辑 我有兴趣尝试将引导加载程序移植到一个很小的AVR,它没有独立的内存空间来存放引导加载程序代码。在我看来,引导加载程序代码依赖于某些熔丝设置和芯片支持的情况下,我想我真正感兴趣的是如何将引导加载程序移植到一个没有熔丝和硬件支持的芯片上(但仍然具有自编程能力)? 根据您的最终目标,创建您自己的引导装载程序可能比移植一个要容易。你真的只需要为那部分学习一些东西。 1)UART 2)UART RX 3)自闪存编程 它可以单独学习,然后组合成一个引导装载程序。您将需要一个可以使用SPI或任何东西来编写flash的部分,这样,如果您的引导加载程序不工作,或者任何附带的部分出现问题,您仍然可以继续开发。 不管你是选择投球还是投球,你仍然需要理解这三个基本的方面。 |
gotti123 · 在MCU上查找Pin 6 年前 |
Daniel Barvík · 使用I2C\U主库AVR 7 年前 |
Bergi · 如何为数据保留固定的闪存部分? 7 年前 |
danieljimeneznz · AVR半双工接收器中断错误 7 年前 |
girikks · 结构值未在主源文件中更新 7 年前 |