Hi all,

大家都还记得我有说过做那个开源的USB键盘吧。最近是在忙毕业论文的事情,所以这个项目当然是耽搁了。
但是不怕,这个项目已经开始进入测试阶段了,程序还是很不稳定。可是坑会在不久的将来就会填好的。:-)

前几天,我在看相关代码的时候,顺带把一个积蓄已久的问题发给LUFA的作者,问了他一下关于某些代码的实现方式,并获得他的回复,鉴于这个回复有不少知识可以学习,也有不少地方是值得大家来借鉴学习参考的,我就来分享一下吧。

主要的问题是,
    1、关于一个程序,在进入 main()
这个函数入口之前,做了什么;退出这个函数的时候,做了什么?对于不同的(操作)系统,我们又应该如何关注这个问题?程序指针?
    2、如果是需要深入了解这个相关知识的话,应该学习哪门课程,从哪门课程的哪个章节获得相关的知识?
    3、如果针对单片机 MCU 编程,和针对操作系统上的应用系统编程,是有很大差别的,大家都有什么好见解呢?
    欢迎大家一起来探讨下。


以下部分,纯属代码分析,有时间有兴趣有想法就看看,没时间没兴趣就忽略吧。 :-)

    1、流程。
    关于LUFA bootloader的启动过程,是这样的。a)执行 .init[0-9]()
这些初始函数,来把相应的运行环境给初始化完成;b)进入 main() 函数;c)执行 main() 函数内的相应任务;
d)如果没有任务要执行,启动定时器,准备热重启;e) 热重启。

    2、代码分析
    这个bootloader的精妙之处在于:他设定了一个函数 void Application_Jump_Check(void)
用于检测某个内存中的变量,以检测该变量是否等于某个预设值,从而判断是否要继续进入 Bootloader 的 main()。
    这个特殊变量的定义如下:
        uint16_t MagicBootKey __attribute__ ((section (".noinit")));
    该函数的定义如下:
        void Application_Jump_Check(void) __attribute__ ((used, naked,
section (".init3")))
    **注意,这两个定义,我把原作者做过的原始宏定义给做了替换,展开了。**
    接下来,什么时候给 MagicBootKey 赋值的语句就不找出来了,没太大意思了。

    3、工作流程
        热启动 ->
        程序指针指向 bootloader 程序的起始位置,开始顺序执行 .init[0-9] 里面的相关初始化函数 ->
        注意到 .init3 里面,有 Application_Jump_Check() 这么一个函数被执行了 ->
        函数 Application_Jump_Check(),检查内存中的 MagicBootKey 是否符合需求 ->
            是 -> 继续执行 bootloader 的 main() 函数 ->
                完成任务,修改 MagicBootKey 的值 ->
                设定定时器,准备热重启 ->
                热重启,所有寄存器内的值清零 ->
                重新顺序执行 .init[0-9],直到.init3,再次检查 MagicBootKey ->
            否 -> 把程序指针跳转到 Application 区(这里是0x0000) ->
        完成 bootloader 的程序任务



Best Regards,
Bill Chen

-- 
您收到此邮件是因为您订阅了 Google 网上论坛的“广州 GNU/Linux 用户组”论坛。
要退订此论坛并停止接收此论坛的电子邮件,请发送电子邮件到gzlug+unsubscr...@googlegroups.com。
要向此网上论坛发帖,请发送电子邮件至 gzlug@googlegroups.com。
通过以下网址访问此论坛:http://groups.google.com/group/gzlug。
要查看更多选项,请访问 https://groups.google.com/d/optout。

回复