ruanlingling2 2025-09-09 15:45 采纳率: 53.3%
浏览 9

嵌入式 C语言 keil

嵌入式C语言用keil开发
遇到一个以前同事写的程序 ,有一个现象不知道他是怎么做到的
程序分成两个程序 一个是底层程序 这个已经找不到源代码了,只有hex文件,一个是顶层程序
这个产品只有 经历 擦除->>下底层程序->>下顶层程序 才好用,而且走完流程之后 不能再下程序,也不能调试,我想改程序都不好改,只能先暂时新建一个项目重新挪进去

就下面这个照片这个语句我不懂是什么意思,其他的我基本都看了就是一些外设调用,没啥作用. 不知道以前同事是怎么做到这个现象流程的

img

img

  • 写回答

5条回答 默认 最新

  • 檀越@新空间 2025-09-09 15:46
    关注

    下午好🌅🌅🌅
    本答案参考通义千问

    你提到的现象,是典型的嵌入式系统中使用多个程序(或固件)进行引导和切换的场景。这种情况在一些需要多阶段启动(如 Bootloader + Application)的系统中非常常见。


    一、你描述的现象分析

    你提到:

    • 底层程序(Bootloader):只有 .hex 文件,没有源码;
    • 顶层程序(Application):通过擦除 -> 下载底层程序 -> 下载顶层程序才能正常运行;
    • 后续无法再次下载或调试:说明底层程序可能具有“保护”机制;
    • 代码中有一句你不懂的语句:可能是与跳转、内存操作、地址设置等有关。

    二、可能的实现方式

    1. Bootloader + Application 的结构

    这是最常见的实现方式:

    | 步骤 | 操作 | 作用 | |------|------|------| | 1 | 擦除整个 Flash | 清除旧程序 | | 2 | 下载 Bootloader | 引导程序,负责加载 Application | | 3 | 下载 Application | 主程序,执行具体功能 | | 4 | 跳转到 Application | 启动主程序 |

    注意: 一旦 Bootloader 和 Application 都写入 Flash,通常不能直接重新下载,除非 Bootloader 具备重新烧录的功能(例如通过串口、USB 等)。


    2. 为什么不能再次下载?

    这可能是因为:

    • Bootloader 设置了 Flash 写保护(如某些芯片支持 FLASH_LOCKPWR_LOCK);
    • Application 写入后,Bootloader 不再运行,导致无法再次进入下载模式;
    • 芯片被锁定(如 ST 的 IAP 功能未启用,或 Bootloader 有安全机制)。

    三、你看到的那句“不懂的语句”可能是什么?

    你提到“下面这个照片这个语句我不懂”,虽然没有图片,但我们可以推测几种可能性:

    可能的代码示例(假设)

    __attribute__((section(".bootloader"))) void JumpToApp(void) {
        uint32_t appAddr = *(uint32_t*)(APP_ADDR);
        void (*appEntry)(void) = (void (*)(void))appAddr;
        appEntry();
    }
    

    解释:

    • __attribute__((section(".bootloader"))):将函数放入特定的段(section),用于链接器脚本定位。
    • APP_ADDR:定义为 Application 的起始地址(如 0x08008000)。
    • JumpToApp():跳转到 Application 的入口函数。

    重点: 这个函数的作用是让 Bootloader 在完成初始化后,跳转到 Application 的起始地址,从而开始运行主程序。


    四、如何实现类似功能(新建项目)

    如果你要自己实现类似功能,可以参考以下步骤:

    1. 创建两个项目:Bootloader 和 Application

    • Bootloader 项目

      • 编译为 .hex 文件;
      • 包含跳转逻辑、外设初始化;
      • 保留足够的空间给 Application(如 0x08008000 开始)。
    • Application 项目

      • 编译为 .hex 文件;
      • 设置 Linker Script 中的 APP_ADDR 为合适的地址;
      • 不包含 Bootloader 逻辑。

    2. 修改 Linker Script(以 STM32 为例)

    .ld 文件中指定 Application 的起始地址:

    MEMORY
    {
        FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K
        RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
    }
    
    SECTIONS
    {
        .text : {
            . = ALIGN(4);
            KEEP(*(.isr_vector))
            . = ALIGN(4);
            *(.text*)
            . = ALIGN(4);
        } > FLASH
    
        .bootloader : {
            . = ALIGN(4);
            KEEP(*(.bootloader))
            . = ALIGN(4);
        } > FLASH
    
        .data : {
            . = ALIGN(4);
            * (.data)
        } > RAM AT> FLASH
    
        .bss : {
            . = ALIGN(4);
            * (.bss)
        } > RAM
    }
    

    注意: 你需要确保 Bootloader 和 Application 的地址不重叠。


    五、如何实现“一次烧录后无法再下载”?

    你可以通过以下方法实现:

    1. 设置 Flash 写保护

    在 Bootloader 中添加如下代码:

    FLASH_Unlock();
    FLASH_ErasePage(0x08000000); // 擦除整个 Flash
    FLASH_Lock();
    

    或者使用芯片厂商提供的 API 来锁定 Flash。

    2. 使用安全寄存器(如 ST 的 Option Bytes)

    例如,在 STM32 中,可以通过设置 Option Bytes 来禁止 Flash 写入:

    // 设置读保护
    HAL_FLASH_OB_Unlock();
    OB_DeferredConfig[0] = OB_RDP_LEVEL_1; // 设置为 RDP Level 1
    HAL_FLASH_OB_Program(&OB_DeferredConfig);
    HAL_FLASH_OB_Lock();
    

    注意: 设置 RDP Level 1 后,Flash 将无法通过 JTAG/SWD 下载,除非使用特定工具解除保护。


    六、总结:你同事是如何做到的?

    | 原因 | 说明 | |------|------| | Bootloader + Application 架构 | 使用 Bootloader 负责引导和跳转到 Application | | Flash 地址分配 | Bootloader 放在低地址,Application 放在高地址 | | 写保护机制 | 通过 Flash 锁定或 Option Bytes 禁止再次下载 | | 跳转指令 | 使用 JumpToApp() 函数跳转到 Application 入口 |


    七、建议

    1. 尝试反汇编 Bootloader 的 hex 文件:使用 objdump 或 Keil 自带工具查看其内容;
    2. 查看芯片数据手册:了解 Flash 地址、Option Bytes、IAP 等相关内容;
    3. 如果需要修改:可以将 Bootloader 和 Application 分离,使用独立的工程管理;
    4. 如果想保留原有流程:可复制 Bootloader 的 hex 文件,并在新项目中调用跳转逻辑。

    如果你能提供那句“不懂的语句”的具体内容(如 C 代码或汇编),我可以进一步帮你分析它的作用。

    评论

报告相同问题?

问题事件

  • 修改了问题 9月9日
  • 创建了问题 9月9日