This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] EK-TM4C1294XL:闪存中存在两个应用程序。 第1个应用程序选择这两个运行中的哪一个。

Guru**** 2318210 points
Other Parts Discussed in Thread: TM4C1294NCPDT, EK-TM4C1294XL, ENERGIA
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/582654/ek-tm4c1294xl-co-exist-of-two-apps-in-flash-1st-app-selects-which-of-the-two-runs

器件型号:EK-TM4C1294XL
主题中讨论的其他器件:TM4C1294NCPDTENERGIA

您好 Amit

我需要在闪存中同时存在2个程序。 第1个位于 前32 KB 空间(0x0000.0000 - 0x0000.7FFF)、第2个位于其上面的地址空间、起始地址 为0x0000.8000。

我想让这些程序 EPPROM 被驱动、这是因为在 POR 或简单复位发生后、第一个应用程序在0x0000.0000处开始执行、之后它在 EEPROM 中读取特定位置并找到它

假设是0xFF、然后 继续运行、但如果找到 0x00以退出、并将控制权交给第二个应用程序、地址为0x0000.8000。 第1个程序将是闪存引导加载程序类型的应用程序、第2个程序是常用的闪存应用程序。

如何 告知我的第1个应用程序停止运行并将程序指针发送到 0x0000.8000地址、以便第2个应用程序开始执行?

这是否只能通过直接操作程序指针和一个或两个寄存器来完成、或者我必须只使用 BOOTCFG 寄存器设置? 如果这样、还必须使用一个引脚

驱动选择?  

基本需要是执行远程引导加载、而无需  在 POR 发生时按下按钮来驱动引脚、从而启动引导加载。

谢谢、

John

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    尊敬的 John:

    如果 EEPROM 读数显示为0x00、不确定您要查找的内容是否类似于((void (*)(void)) FixedAddress (FixedAddress)()跳转至0x0000.8000。 BTW、Amit 还有其他职责、即他在 TM4C 论坛上的参与频率会降低。 如果我无法回答您的问题、我将寻求包括 Amit 在内的其他人的帮助。 谢谢。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Charles、感谢您的回答。

    几周前、我和 Amit 在类似问题上大同小异、认为他还在。

    你在 论坛上的帮助也是非常出色的,我为此感谢你。

    O.K.、我要做的是、在处理器期间无需按钮按压  

    处理器通过读取 bootcfg 寄存器的位来了解  

    如果它是遵循或需要跳转到闪存中的其他位置并直接跳转的引导加载

    开始运行我的应用程序。

    我稍微修改了 EMAC/BL_EMAC c 模块、以便读取 EEPROM 位置并根据

    到找到的值、或者 在循环中等待接收新的闪存应用程序映像、或者

    跳转至0x0000.8000并开始运行应用程序映像(如果已有)。 我的引导加载

    应用程序是 我按照我的做法首次加载到 TM4C129NCPDT 板中

    任何其他闪存 应用程序。 我的应用程序第一次读取的预定义 EEPROM 位置

    该电路板是由制造商提供的、它会发现为 0xff、因此会进入

    以太网更新过程、并开始接收主应用程序的映像 bin 数据包

     由 LM Flash Programmer 等远程 TFTP 服务器或其他服务器提供服务。 完成后、

    通过看到最后一个数据包包含大量 空字节、退出更新例程、写入0x00

    到 该"驱动程序"EEPROM 位置 、然后通过观察 dog0过期执行 POR 引导

    (SYSCTL_ONRST_WDOG0_POR)。 现在、应用程序在该 EEPROM 位置看到了一个0x00、您也是如此  

    告诉 Charles,只要 在我的代码中使用((void (*.)(void)0x0000.8000)(),处理器就会运行  

    然后从该地址开始运行我的主应用程序? 是否已完全确认? 这并不意味着  

    通过这种方式、我可以说在闪存中加载了3个不同的小应用程序、它们位于不同的地址

    由同一第一 个引导加载应用程序加载的空格(与"驱动程序"EEPROM 位置的值一起播放)

    然后、根据外部条件、让这些应用程序按需从一个应用程序跳转到另一个应用程序

    通过使用此 ((void (*)(void)) 0x0000.?000)()命令? 请 Charles 验证是否是这样。 您能不能

    另外、请给我一些线索、在这里可以找到有关此命令的更多详细信息

    TM4C129xxxxx 处理器。  

    非常感谢。  

    John

     

       

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    尊敬的 John:

    我认为这更多是表示函数指针的 C 语言方法。

    (void (*)(void)是一种函数指针类型、不接受任何参数、也不返回任何值。
    ((void (*)(void)) 0x00008000)将地址(0x00008000)转换为函数指针。
    ((void (*)(void)) 0x00008000)()是作为函数执行转换值。

    请尝试一下。 我建议在支持多个应用程序之前、只使用一个应用程序映像。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Charles、非常感谢您的回答。
    我知道 C 的这个加密指针/转换/函数表达式、swupdate.c 无论如何都会使用这个表达式、但它的使用与某些寄存器没有关系
    应该考虑的操作? 我将根据您的指示使用它、只需使用一张图片、我将在明天向您介绍结果。 再次,非常感谢
    John
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    尊敬的 John:
    我认为、您在闪存中使用多个应用并使用 EEPROM 在它们之间进行选择的方法是一种很好的方法。 如果我正确关注该线程、您会担心如何使每个应用程序独立于其他应用程序或引导加载程序所执行的配置。 一种方法是让每个应用程序自行初始化、然后通过对 EEPROM 进行编程来切换到另一个应用程序、然后执行系统软件复位。 引导代码可以简单地读取 EEPROM。 如果值为0xFFFFFFFF、则启动引导代码。 如果该值是有效的闪存位置、则会跳转到该位置。 如果应用1完成并想要传输到应用2、它只需将应用2的地址编程到 EEPROM 中并发出软件复位。 所有外设都返回到复位状态、因此应用2的运行就像它是器件中的唯一应用一样。 这是您要尝试做的吗?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Bob 您好、感谢您的准确回复。
    很棒! 这正是我要做的。 这种方式似乎可以获得自动、网络爬虫之类的行为。 除此之外、如果在复位之前、一个 TM4C1294NCPDT 中每个应用的状态都通过端口总线桥传递到附近的类似 DUDES、那么某些 Ting 状态机模型似乎可以在纯硬件级别实现。 这意味着可能会带来一些良好的教育优势和/或控制问题解决。 但我的需求不太重要、我只需要具备以下功能:a)通过以太网将新固件远程刷写到基于 TM4C1294NCPDT 的控制器上、b)在每个板的固件上具有3个或4个不同的应用、用于控制和监控情况、例如警报和自动化工业系统、 其中、与我们的控制器的交互配置文件可能会在非确定性时间跨度或序列中发生变化。
    在任何情况下、除了不同应用的内部逻辑和处理结果之外、还需要一个平均值、以便通知我们板的应用程序转到 EEPROM 位置并写入、然后重新启动。 因此、根据运行的应用程序、使用了一个 Web/TCP 服务器、使用一个客户端轮询远程位置的服务器、当然、SMS 和/或 GPRS 数据通道是因为我们的主板还托管一个 SIM800模块。
    我认为查尔斯的建议似乎能满足我的需要。 但我还不能弄清楚的是、当放弃引导加载应用程序并转到某个地址以开始运行另一个应用程序时、处理器的 SP 会发生什么情况、实际上是其中一个主要应用程序。
    如果可能、需要在 CCS7的调试窗口中检查该内容。
    再次感谢 Bob、
    祝你一切顺利、
    John
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    John、

    这是一个经过验证的解决方案:在您的0x00程序(也称为您的自定义引导加载程序)中-当然、您会考虑您选择的程序条件- 转移代码执行所需的操作是:

    {
    HWREG (0xE000E000 +(0xD08))=(0x4000 & 0xFFFF);//更新矢量表偏移寄存器
    asm (" MOVW r0、#0x4000");//将应用矢量地址加载到 SP
    ASM (" LDR SP、[r0]");
    asm (" LDR r0、[r0、#4]");//跳转至起始地址+ 4
    asm (" bx R0");
    }
    

    此示例将闪存上的执行转移到0x4000。 您的主应用程序必须已为此目的进行编译、因此.cmd 文件需要进行一些更改:

    /*
    *标准编译的设置
    *//
    #defineAPP_BASE 0x00000000
    //#defineAPP_Leng 0x00100000
    //#defineRAM_BASE 0x20000000
    //#define RAM_Leng 0x00040000
    
    //*
    AutoNL 更新编译的设置(应用程序基址偏移,应用程序长度较小)
    //
    #defineAPP_BASE 0x00004000//偏移以匹配主固件
    #defineAPP_Leng 0x00054000// 336KB
    #defineRAM_BASE 0x20000000
    #define RAM_Leng 0x00040000
    
    MEMORY
    {
    闪存(RX):origin = app_BASE,length = app_leng
    SRAM (rwx):origin = RAM_base,length = RAM_Leng
    }
    

    要调试/开发主应用、您需要将存储器映射恢复为标准配置并运行它。 如果您对结果满意、请将其重新编译以启动@ 0x4000并将其放入闪存中。

    此致

    布鲁诺

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好 Bruno、早上好。

    非常感谢您提供的指南。 如果我直截了当地说、这是一种行之有效的工作方法、可以实现我的目标

    查尔斯的建议也是同样的建议。  我要问的是、在我尝试您的指南时、  

    在我的应用程序内部、我还需要直接修改一些寄存器中的位、并为此使用位段。

    那么   、不应该在.cmd 文件中使用#define RAM_base 0x22000000而不是#define RAM_base 0x20000000?

    非常感谢、

    John

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 user="John Piliouni"]我还需要直接修改某些寄存器中的位[/引用]

    您是否意味着您需要修改与程序执行转移无关的其他位? 不确定我是否关注...

    [引用 user="John Piliouni"]然后不应在   .cmd 文件中使用#define RAM_base 0x22000000而不是#define RAM_base 0x20000000?

    RAM_base 定义是 RAM 变量开始存储的地址。 我们将其设置为0x20。。 在我复制示例的 TM4C129x 项目中。 它可能是正确的柱塞基座位置、但我现在无法打开数据表。

    这是"猜测"、 但我认为、当我们将执行从 CustomBootloader 转移到 MainApplication 时、我们只需从基址覆盖 RAM 中所需的任何内容、因此此类地址可以相同-因为我们不再关心 CustomBootloader 最初使用的任何内容。 两个(值的配置标志)之间的任何"数据传输"都将在绕路之前存储在 EEPROM 中。 但老实说、我从未需要调查 RAM 区域以检查是否完全正确、因为事情正如预期的那样正常...

    谢谢

    布鲁诺

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    你(们)好,Brun
    我的主应用程序是需要修改 SRAM 位带区和外设位带区中的位的应用程序、而不是我的引导应用程序。 由于中断、我需要避免读-更新-写操作直接操作寄存器在其 SRAM/外设0x20000000和0x40000000区域中的整个寄存器。 这就是我在0x22000000和0x42000000地址空间使用它们的位带别名的原因。 编译器需求
    要知道这一点、因为它不是为了使用位带逻辑、所以必须从 C 源内部对其进行显式声明、如
    有关我的主应用程序编译的指令.cmd 文件。 我将向您介绍结果。 再次非常感谢您提供了非常精确和有用的指导。 我非常感谢 TI 的所有帮助。
    祝你一切顺利、
    John
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你(们)好,查尔斯 使用引导加载程序中的以下两个例程、我尝试加载地址为65536的应用程序:[我不使用 BOOTP 例程]

    对于(ui32Idx = 0x00010000;ui32Idx < 0x000FA000;ui32Idx += 0x4000)

    while (ROM_FlashErase (ui32Idx))

    }  

    我已为要在闪存中引导加载的 bin 编码了 C# TCP 发送应用程序、地址为65536。 我已经在 TM4C1294NCPDT 板上启动了一个 TCP 服务器、并且其关联的客户端 在每次接收会话中成功接收4096字节。 然后、我使用以下例程写入闪存:

    void write_flash (int guide)

    如果(guide =0) // guide 是 file_size%4096 & base_address = 65536,0x10000 ****在发送 bin 开始之前,我通过远程 TCP 客户端的初始通信会话获取文件大小。

    base_address += j*4096;// j 是从0开始的全局计数器

    RET_val = ROM_FlashProgram (input_buffer、 base_address、 4096); // input_buffer 是我存储接收到的4096字节的字节缓冲区

    serial.print (ret_val);
    serial.print (">*< 4096字节块已传输.......... 块编号 ");
    serial.println (j+1);
    J++;

    其他

    RET_val = ROM_FlashProgram (input_buffer、 base_address、 guide);
    serial.print (ret_val);

    虽然我发出命令 ROM_SysCtlReset、但在编程结束后模块不会重新启动、看起来一切正常。 甚至不响应外部复位开关。 不是偶数  

    到看门狗复位、尽管在设置阶段 I 发出命令 ROM_SysCtlResetBehaviorSet (SYSCTL_ONRST_WDOG0_POR);当我使用 EK-TM4C1294XL Launchpad 时也会发生同样的情况  

    以进行测试。 然后、在我为模块加电后、它确实会遵循 EEPROM 驱动的例程和问题 ((void (*)(void)) 0x00010000)();命令。 但什么也不会发生。 我想我在某个地方犯了巨大的错误、但两天之后我无法弄清楚。 任何帮助都是非常受欢迎的。 谢谢、

    John

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    尊敬的 John:

    当您发出 SysCtlReset 或保持 RST 引脚时、您如何确认器件不会复位?
    编程时、RET_val 会说什么? 编程/擦除是否成功? 如果您在"Memory"窗口中转到0x10000、您在那里看到了您的二进制文件吗? 如果要将编程内容与原始二进制文件进行比较、可以在 CCS 存储器窗口中将内容写入一系列地址的文件中。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Charles 您好。

    我始终从 RET_val 获取0 (零)。 我将其打印在调试屏幕上、以便可以看到它。 编程后(?) 涂层、我的模块/板以及 EK-TM4C1294XL 都已冻结。

    对于复位、编程结束后、我永远不会使用引脚/按钮。 我只使用 ROM_SysCtlReset 命令、或带有 POR 标志的看门狗方法

    使能。 这两种方法似乎都没有使用、因为芯片在最后一条闪存写入/编程命令之后被冻结。 我的具体操作如下:

    引导加载一个小型应用程序时、将模块的 MAC、IP、子网掩码、网关和 DNS (未在我的应用程序中使用)编程到 EEPROM 的特定位置。

    然后、我加载读取 EEPROM 位置的引导加载程序应用程序、然后成功激活 TCP/IP 服务器。 然后、我使用 C# TCP/IP 远程或本地连接到该服务器

    在 PC 上运行的客户端应用、并成功将 bin 文件传输到我的模块。 我可以说已成功、因为在闪存编程时、RET_val 始终为0。 但在该模块之后  

    显示一个死屏幕、而它应该会重新启动。 如果您需要、我可以将 C#客户端应用程序和引导加载程序的代码发送给您以供您检查。 但明天(今天对我们来说)、因为  

    明天我们有一个非常严肃的国家假期,一切都被冻结了:-)

    再次感谢您的所有帮助、

    John

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 John:

     您是否能够连接到目标并使用 MEMORY 窗口查看引导加载程序在0x10000开始时编程的内容?

     您可以监控 DIVSCLK 吗?  我想知道时钟是否以某种方式变为无效。 但是、如果您仍然可以执行某些代码行、则时钟应处于活动状态。 您可以确认吗? 除非时钟处于非活动状态、否则我无法理解为什么 WD 复位不会生效? 您是否还可以在启动引导加载程序编程之前尝试导致 WD 复位的实验?

     很抱歉、我自星期三起仍在度假。 我只有 iPad、无法真正运行任何代码。  

      

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Charles、您好、非常感谢您的回复。 时钟始终运行。 我似乎在存储器指标方面出错、意外地覆盖了引导加载应用程序区域的区域。 也许这就是最终导致电路板冻结的原因。 现在、看门狗正常运行、但在我在闪存中写入的前41个部件变为0后、我开始为其余部分获取-1。 我在这上面已经有几天了、但我还没有清楚的图片。 我的方案如下所示:

    1) 1)我在开始时使用一个小型应用、通过 JTAG 端口将 特定的 EEPROM 位置标记为"1"、并将 IP、子网、网关和 MAC 写入其他位置。 (在 USERx 寄存器 中、也可通过 LM 闪存编程器烧写 MAC /在第一阶段提交)

    2) 2)然后、我再次通过 JTAG 端口加载引导加载程序应用程序、该端口从 EEPROM 位置读取所有参数、并且由于特定位置为"1"、因此启动 TCP 服务器等待连接。 此时已启动看门狗并正确馈送、同时还启用了串行调试端口以获取各种调试消息我在引导应用程序中有代码。  

    3) 3)现在、我通过在 PC 上运行的远程 TCP C#编码客户端成功远程连接到我的板上、然后我首先将要加载到板上的 bin 应用文件的文件大小发送到我的板上。 板上的引导应用程序获取此信息并创建两个变量:Parts = file_size/4096、LAST_part = file_size_4096 (剩余字节)。 然后、向远程 PC 应用程序发送 TCP 消息、以发送第一个包含4096字节的包(部分)、我在一个字节数组中读取该包。 当4096个字节已被读取时、我的应用程序填充了一个-> uint32_t flash_input_buffer[1024]<-使用->字节 input_buffer[4096]<-刚刚被填充。 执行此操作的步骤如下:(所述程序重复"零件"时间。)

    对于(j = 0;j < 1024;j++)

      flash_input_buffer[l]=(input_buffer[4*j + 0]<< 24 | input_buffer[4*j + 1]<< 16 | input_buffer[4*j + 2]<< 8 | input_buffer[4*j + 3]);

    }  

    然后、我的应用程序会立即按照如下方式进入并刷写数据: RET_val = ROM_FlashProgram (flash_input_buffer、base_address、1024);其中 base _address = 0x10000、并且在每次写入'parts'时增加 1024个地址、例如 base_address += q*1024、其中第一个器件的 q = 0、依此类推。  

    ///*** 请注意,input_buffer 在每个“部件”循环中都填充来自远程发送 TCP 应用程序的新字节。  远程 PC 应用程序从引导应用程序获取 TCP 通知、以开始发送下一个4096或最终数据流         在每次成功的读取和闪存写入之后。 因此所有字节都是可确定的读数***///

    引导应用程序中的最后一个循环如下所示:  

    对于(j = 0;j < LAST_PART/4;j++)

      flash_input_buffer[l]=(input_buffer[4*j + 0]<< 24 | input_buffer[4*j + 1]<< 16 | input_buffer[4*j + 2]<< 8 | input_buffer[4*j + 3]);

    然后 、RET_val = ROM_FlashProgram (flash_input_buffer、base_address、last_part/4)、 其中 base_address 之前已在最后一个'parts'循环中准备好。

    在第41或42部分之后、对于226884字节长的主应用程序、我开始获取-1。 我是否在某个地方犯了逻辑或指标错误?  (闪存擦除在任何新的闪存编程之前已正确完成、为了确保我的闪存擦除不会造成混乱、我还使用了 LM 闪存编程器闪存擦除实用程序选项、但在"getting -1s"中没有任何更改)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 John:

     我只是想确保您在第41或42部分之外的闪存上是否有任何写保护。 您是否还可以监控 base_address 以查看其是否在第41或42部分之后正确递增? 我假设您要编程的应用程序代码远远超过42个部分、对吧? 我假设 flash_input_buffer 包含正确的数据(非-1s)、其中 q>=42、对吧?

     我不清楚的一点是、你说前41个器件会变为零。 您是下载一个全为零的二进制文件作为实验、还是在前41个器件的上成功地对正确的二进制映像进行了编程?  

      

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Charles、您好、我又来了。

    还可以 我跟踪了误差。  如果你看一下我上面发送的代码、我在每次写入时为了增加内存地址1024个位置而做的操作是错的。 我写:

    (第2条  然后、我的应用程序会立即按照如下方式进入并刷写数据: RET_val = ROM_FlashProgram (flash_input_buffer、base_address、1024);其中 base _address = 0x10000、并且在每次写入'parts'时增加 1024个地址、例如 base_address += q*1024、其中第一个器件的 q = 0、依此类推。 *********

    base_address 应增加为:base_address += 1024,而不是 base_address += q*1024!!!  是的、正如您所说的、我的应用程序是55个块、每个块4096字节、末尾1604字节 现在、所有内容都按应有的方式接收、所有内容都按应有的方式写入闪存中、看门狗也按应有的方式重新启动。 在每次闪存写入之前、我打印当前编程位置的地址、并且所有地址值实际上是1024个位置之间的间隔。 我始终在每个 FlashProgram 命令中获得0 ret_val、并且在我 FashProgram 之前、我通过另一个 TCP 客户端将接收到的数据发送到另一台 PC、然后在那里重建原始 bin。 到所有闪存编程完成时、我会比较初始和最终的字节、并且始终相同。 因此、我确信已写入闪存的内容会反映到原始 bin 中。

    现在是最后一个问题。 看门狗引导物联网模块后、引导应用程序现在会查找写入"0"的 EEPROM 特定位置(在看门狗重新引导之前、我的引导应用程序执行的最后一项操作)。 因此直接发出命令 ((void (*)(void)) 0x00010000)()、但不会发生任何情况、调试屏幕始终保持空白。 即使我重启模块、主应用程序也不会启动。 我只能得到一个空白的调试屏幕。 是否需要在发出此命令之前发出其他命令?

    与往常一样,任何帮助都是非常受欢迎的。 非常感谢、John。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好 Bruno。 我想请您验证、如果我需要使用0x00010000地址作为闪存中应用程序的起始地址、那么我需要按如下方式修改您的 ASM 代码:

    HWREG (0xE000E000 +(0xD08))=(0x10000和0xFFFFFFF);//更新矢量表偏移寄存器
    asm (" MOVW r0、#0x0000");
    asm (" MOVT r0、#0x0001");
    asm (" ldr sp、[r0]");              //将应用程序矢量地址加载到 SP 中
    asm (" LDR r0、[r0、#4]");//跳转到起始地址+ 4.
    asm (" bx r0");

    或者、MOVT 命令可以使用 LDR r0、=0x00010000是之前选项中的任意一个或两个选项。是否要使用?

    此外、如果我仅包含/放置#define APP_base 0x00010000 //偏移以匹配主应用的定义区域中的主固件//区域、那么对于编译器、这是否正常?

    我是否必须包含这3个 Defs? (小部分
    #define APP_Leng 0x00054000 // 336KB //
    #define RAM_base 0x20000000
    #define RAM_Leng 0x00040000
    秘书长的报告
    非常感谢、
    John

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Charles、Bruno 和所有人。 虽然取得了逐渐的成功,但还是取得了成功。 项目的状态如下:

    由于我最终不确定我遵循的闪存编程过程是否成功正确刷写模块、因此我想遵循以下过程、以至少验证我的引导应用程序和主应用程序是否正确加载到闪存中并进行通信。 我所做的是像往常一样在"Program Address Offset: 0x00000000"上加载具有 LM 闪存编程器 的引导应用程序、并在"Program Address Offset: 0x00010000"上加载主应用程序、同样在 LM 闪存编程器上加载主应用程序。 现在、已经将特定 EEPROM 位置编程为"0"、每次重启后、我的引导应用程序0x00000000会立即将控制权交给0x00010000处的主应用程序。 我对你们有责任取得巨大成功、感谢你们为此提供的所有帮助。 现在、我们论坛中的所有社区成员都有一些非常有用的数据:

    a)我的启动应用程序使用以下代码、这是 Bruno 和 Charles 的建议、我对这些代码进行了细微修改、超出了2字节地址限制:

      方法1:(此代码从引导应用程序内部运行、此时我们决定将控制权交给我们的主应用程序、在我的示例 中、主应用程序位于0x000100000。 boot-app 位于0x00000000)

    HWREG (0xE000E000 +(0xD08))=(0x10000和0xFFFFFFF); //更新矢量表偏移寄存器
    asm (" MOVW r0、#0x0000"); // 32位地址的低字节  
    asm (" MOVT r0、#0x0001");  // 32位地址的高字节。 查看 Cortex-M3、M4的 ASM 命令表
    asm (" ldr sp、[r0]");          //将应用程序矢量地址加载到 SP 中
    asm (" LDR r0、[r0、#4]");       //跳转至起始地址+ 4.
    asm (" bx r0");               // 执行此命令后,您的模块将启动 main-app

      方法2:(再说一次,此代码从......运行)

    (*(void (*)(void))(*(uint32_t *) 0x00010004))();

    b) 正如 Bruno 所建议的、为了能够在所需的地址(在我的例子中为0x000100000)中成功地重定位主应用、我们需要执行两个重要步骤:

    步骤1:在主应用程序源代码的主体内、我们需要进行以下定义、因此编译器将了解在编译期间在何处放置一些寻址矢量。

    //******** 对编译器的指令、用于主应用代码的上部闪存重定位
    #define APP_BASE 0x00010000
    #define APP_Leng 0x00060000 //长度必须大于应用的长度。
    #define RAM_base 0x20000000
    #define RAM_Leng 0x00040000
    //********

    步骤2:链接器还需要了解如何处理 ARM 处理器特定存储器架构的二进制寻址空间。 在我们的案例中是雪花系列。 为此、我们需要对扩展名为.ld /.lds 的链接器指导文件进行少量修改。我们可以通过在开发环境目录中进行搜索来轻松找到此文件。  

    对于 CCS7、其网址为***\ccsv7\ccs_base\arm\include\tm4c1294ncpdt.lds;对于 ENERGIA、其网址为***** \Energia-0101E0017\hardware\lm4f\cores\lm4f\lm4fcpp_sowflake。

    该文件包含如下所示的源代码块:

    存储器

    闪存(Rx):origin = 0x00000000、length = 0x00100000
    RAM (rwx):origin = 0x20000000,length = 0x00040000

    在这里、我们只需要更改 闪存(Rx):origin = 0x00000000到 origin = 0x00010000、 length = 0x00100000、我们可以将其保留原样、或者将 其保留为 length = 0x00060000

    请注意、我们需要恢复为其他应用程序的原始值、我们需要在0x00000000处正常启动这些应用程序

    (三 到目前为止都很好。

    但是、Charles/Bruno、我还不知道为什么我的主应用程序的 bin 映像没有按照我昨天在帖子中描述的方法写入闪存中。 我今天所做的是、我使用了 LM 闪存编程器的实用程序"将闪存内容上载到.bin 文件"、并将0x000100000到0x000600000的所有内容读取到 test.bin 文件中、然后使用十六进制编辑器进行编辑。 不幸的是,所有的空间都是空的!!!! 这意味着,尽管我获得了0,因为 ret_val = ROM_FlashProgram (....、 ...、 ...) 闪存中没有写入任何内容。 我无法解释。 请告知我出错了什么、写入闪存的正确方法是什么。

    非常感谢大家、

    John

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Charles、Bruno 和所有人。 虽然取得了逐渐的成功,但还是取得了成功。 项目的状态如下:

    由于我最终不确定我遵循的闪存编程过程是否成功正确刷写模块、因此我想遵循以下过程、以至少验证我的引导应用程序和主应用程序是否正确加载到闪存中并进行通信。 我所做的是像往常一样在"Program Address Offset: 0x00000000"上加载具有 LM 闪存编程器的引导应用程序、并在"Program Address Offset: 0x00010000"上加载主应用程序、同样在 LM 闪存编程器上加载主应用程序。 现在、已经将特定 EEPROM 位置编程为"0"、每次重启后、我的引导应用程序0x00000000会立即将控制权交给0x00010000处的主应用程序。 我对你们有责任取得巨大成功、感谢你们为此提供的所有帮助。 现在、我们论坛中的所有社区成员都有一些非常有用的数据:

    a)我的启动应用程序使用以下代码、这是 Bruno 和 Charles 的建议、我对这些代码进行了细微修改、超出了2字节地址限制:

    方法1:(此代码从引导应用程序内部运行、此时我们决定将控制权交给我们的主应用程序、在我的示例中、主应用程序位于0x000100000。 boot-app 位于0x00000000)

    HWREG (0xE000E000 +(0xD08))=(0x10000和0xFFFFFFF);//更新矢量表偏移寄存器
    asm (" MOVW r0、#0x0000");// 32位地址的低字节
    asm (" MOVT r0、#0x0001");// 32位地址的高字节。 查看 Cortex-M3、M4的 ASM 命令表
    asm (" ldr sp、[r0]"); //将应用程序矢量地址加载到 SP 中
    asm (" LDR r0、[r0、#4]"); //跳转至起始地址+ 4.
    asm (" bx r0"); //执行此命令后,您的模块将启动 main-app

    方法2:(再说一次,此代码从......运行)

    (*(void (*)(void))(*(uint32_t *) 0x00010004))();

    b)正如 Bruno 所建议的、为了能够在所需的地址(在我的例子中为0x000100000)中成功地重定位主应用、我们需要执行两个重要步骤:

    步骤1:在主应用程序源代码的主体内、我们需要进行以下定义、因此编译器将了解在编译期间在何处放置一些寻址矢量。

    //******** 对编译器的指令、用于主应用代码的上部闪存重定位
    #define APP_BASE 0x00010000
    #define APP_Leng 0x00060000 //长度必须大于应用的长度。
    #define RAM_base 0x20000000
    #define RAM_Leng 0x00040000
    //********

    步骤2:链接器还需要了解如何处理 ARM 处理器特定存储器架构的二进制寻址空间。 在我们的案例中是雪花系列。 为此、我们需要对扩展名为.ld /.lds 的链接器指导文件进行少量修改。我们可以通过在开发环境目录中进行搜索来轻松找到此文件。

    对于 CCS7、其网址为***\ccsv7\ccs_base\arm\include\tm4c1294ncpdt.lds;对于 ENERGIA、其网址为***** \Energia-0101E0017\hardware\lm4f\cores\lm4f\lm4fcpp_sowflake。

    该文件包含如下所示的源代码块:

    存储器

    闪存(Rx):origin = 0x00000000、length = 0x00100000
    RAM (rwx):origin = 0x20000000,length = 0x00040000


    在这里、我们只需要更改闪存(Rx):origin = 0x00000000到 origin = 0x00010000、length = 0x00100000、我们可以将其保留原样、或者将其保留为 length = 0x00060000

    请注意、我们需要恢复为其他应用程序的原始值、我们需要在0x00000000处正常启动这些应用程序

    (三 到目前为止都很好。

    但是、Charles/Bruno、我还不知道为什么我的主应用程序的 bin 映像没有按照我昨天在帖子中描述的方法写入闪存中。 我今天所做的是、我使用了 LM 闪存编程器的实用程序"将闪存内容上载到.bin 文件"、并将0x000100000到0x000600000的所有内容读取到 test.bin 文件中、然后使用十六进制编辑器进行编辑。 不幸的是,所有的空间都是空的!!!! 这意味着,尽管我获得了0,因为 ret_val = ROM_FlashProgram (....、...、...) 闪存中没有写入任何内容。 我无法解释。 请告知我出错了什么、写入闪存的正确方法是什么。

    非常感谢大家、

    John
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    John、

    很抱歉、我无法更深入地分析这一点、因为我目前面临着无数技术挑战、这些挑战正在消耗剩下的一切...

    但是、有几个想法没有正确阅读您的帖子:

    -上传另一个固件时、您是否通过任何更改来重写其他应用程序的存储器区域? 如果您使用任何 PC 闪存器、除非您仔细选择目标、否则倾向于再次写入整个闪存。

    我们针对此引导加载程序/更新程序案例所做的是在"主"应用程序中使用库-因此它会接收更新包并将其存储在闪存的适当位置、而无需接触正在运行的应用程序;仅在下一个引导加载程序上、我们的引导加载程序会管理块。 事实上、我们的"实际"应用程序始终在相同的位置运行、并且旧备份或未来的"候选"暂时存储在某个位置。 仍然有一个永久的自定义引导加载程序应用程序(永远不会改变)、从0x0000到大约8K。

    实际上、查找真实表:

    后来、我们需要的固件超过可用存储器的1/3、因此我们有一些不同的安排、将备份和候选存储在外部存储器中、但这还没有进入生产产品中。

    此致

    布鲁诺

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    你好 John

    如 Bruno 所示、TM4C129x 器件系列上的闪存大小为1MB。 因此主应用程序不能驻留在闪存的末尾。 它应该位于引导映像之后的页面边界。