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.

[参考译文] LP-MSPM0G3507:LP-MSPM0G3507

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1518595/lp-mspm0g3507-lp-mspm0g3507

器件型号:LP-MSPM0G3507
Thread 中讨论的其他器件:MSPM0G3507、MSPM0-SDK

工具/软件:

您好:  

我正在使用 MSPM0G3507的自定义引导加载程序。 该引导加载程序使用 UART 实现、并在将新的十六进制文件写入闪存之前执行 CRC 和版本检查。

在我的引导加载程序中、重置引导加载程序后首先运行、然后在所需位置检查应用程序是否存在(如果不存在)、则跳转到该应用程序、如果不存在、则运行正常的引导加载程序代码。

如果接收到的代码的完整 CRC 和计算出的本地 CRC 匹配、则它最后会跳转到已刷写的新应用程序、但问题是当我通过跳转函数跳转、跳转应用程序的中断不起作用时、它将重置 UC 并从引导加载程序应用程序从0开始。 我之前说过、它将再次检查并跳转到该应用程序。

所以主要的错误是我的中断处理程序从不被执行,从不写入 bootcmd(1 at flash loc 0x0001F058 )。 每次中断我给出 GPIO 中断时、它都会重复。

因为我找不到这个问题、这是我的第一个引导加载程序代码、所以有人能帮我解决这个问题吗? 我附加了跳转函数和 IRQ 处理程序以及链接器文件。

  

链接器命令文件

#include "ti_msp_dl_config.h"
#include "string.h"
#include "stdio.h"
#include "core_cm0plus.h"

#define BOOTLOADER_VECTOR_TABLE_ADDRESS  0x00000000
#define BOOTLOADER_INT_LOCATION          0x0001F058 /* At this location flag set by applicant who wish to turn on boot mode to flesh nex hex */
#define VTOR_OFFSET                      (uint32_t *)0x00003E80
#define NO_ERROR                    0
#define ERROR_WRITE_32_BIT          6

void jump_to_app(uint32_t);
uint8_t BootCmdWrite(uint32_t);

volatile uint8_t gErrorType = NO_ERROR;
volatile DL_FLASHCTL_COMMAND_STATUS gCmdStatus;
uint32_t gCmd32 = 0x00000001;
uint32_t gCmdTemp;

int main(void) {

    //early_irq_enable();

    SYSCFG_DL_init();
    SCB->VTOR = (uint32_t)VTOR_OFFSET;
    __enable_irq();
    NVIC_ClearPendingIRQ(USR_BOOT_INT_IRQN);
    NVIC_EnableIRQ(USR_BOOT_INT_IRQN);

    while (1) {
        DL_GPIO_togglePins(USER_LED_PORT, USER_LED_RED_LED_PIN);
        delay_cycles(16000000);
    }
}
void GROUP1_IRQHandler(void)
{
    switch (DL_Interrupt_getPendingGroup(DL_INTERRUPT_GROUP_1)) {
        case USR_BOOT_INT_IIDX:
            /* If SW is high, turn the LED off */
            if (DL_GPIO_readPins(USR_BOOT_PORT, USR_BOOT_BT_PIN_PIN)) {
                BootCmdWrite(gCmd32);
                DL_GPIO_togglePins(RGB_PORT, RGB_GREEN_LED_PIN);
                delay_cycles(64000000);
                jump_to_app(BOOTLOADER_VECTOR_TABLE_ADDRESS);
//              NVIC_SystemReset();
            }
            break;
        default :
            break;
    }
}

uint8_t BootCmdWrite(uint32_t cmd) {
    if (gErrorType == NO_ERROR) {

        DL_FlashCTL_unprotectSector(FLASHCTL, BOOTLOADER_INT_LOCATION, DL_FLASHCTL_REGION_SELECT_MAIN);
//        gCmdStatus = DL_FlashCTL_programMemoryFromRAM64WithECCGenerated(
//                                   FLASHCTL, BOOTLOADER_INT_LOCATION, &cmd32[0]);
        DL_FlashCTL_programMemoryFromRAM32WithECCGenerated(
                                        FLASHCTL, BOOTLOADER_INT_LOCATION, &cmd);
        // Ensure write is fully committed
        __DSB();  // Data Synchronization Barrier
        __ISB();  // Instruction Synchronization Barrier
        if (gCmdStatus == DL_FLASHCTL_COMMAND_STATUS_FAILED)
        {
            /* If command was not successful, set error flag */
            gErrorType = ERROR_WRITE_32_BIT;
        }
        DL_FlashCTL_protectSector(FLASHCTL, BOOTLOADER_INT_LOCATION, DL_FLASHCTL_REGION_SELECT_MAIN);
        gCmdTemp  = *(uint32_t *)BOOTLOADER_INT_LOCATION;

    }
    return gErrorType;
}

void HardFault_Handler(void)
{
    // Debug indicator - blink LED or breakpoint
    while (1)
    {
        DL_GPIO_togglePins(RGB_PORT, RGB_GREEN_LED_PIN);
        for (volatile int i = 0; i < 100000; i++); // Simple delay
    }
}

void jump_to_app(uint32_t app_addr) {

   __disable_irq();
   // Disable and clear all interrupts
    for (uint32_t i = 0; i < 8; i++) {
        NVIC->ICER[i] = 0xFFFFFFFF;  // Disable IRQs
        NVIC->ICPR[i] = 0xFFFFFFFF;  // Clear pending IRQs
    }
       __DSB();
       __ISB();

    // Reset SysTick just in case
    SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL = 0;

    uint32_t sp = *((uint32_t *)app_addr);         // Stack pointer
    uint32_t reset = *((uint32_t *)(app_addr + 4)); // Reset handler

    __set_MSP(sp);
    SCB->VTOR = app_addr;  // If needed


    ((void (*)(void))reset)(); // Jump to reset handler
}

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

    你好 Helic,

    在我的应用程序中设置 VTOR 与在引导应用程序中设置相同、但区别在于我的源代码跳转函数定义存在于单独的.c 文件中而不是 main 中、它会在设置 VTOR 时引起任何问题?

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

    我不认为是这样、其他.c 文件中还使用了其他函数。

    您可以尝试修改项目结构、使其与引导应用程序结构相同。

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

    谢谢,但这将是一个时间,如果你找到任何与此 PLS 相关的事情让我知道。

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

    引导我从何处入手、因为它很难理解引导应用程序示例代码、如何获取详细信息? 然后能够跳转到应用程序。

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

    您好、Helic、

    我认为根据启动应用程序中的功能和映像验证、毕竟它直接通过地址跳转到应用程序、因此在我的应用程序验证通过 UART 进行、我在跳转之前进行检查、因此间接过程是相同的、但如何验证映像是不同的、所以如果必须根据启动应用程序修改代码、会出现问题吗?

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

    查看引导应用示例后、MSPM0G3507中是否有任何插槽? 用于示例、但在参考手册中没有提及这方面的任何内容。

    1)此外、在示例中、他们在链接器命令文件中分配了闪存= 0x5900、但在加载时、他们提到的闪存地址为0x5800、那么为什么这是256字节的间隔?

    2)是否有任何用于处理引导应用程序的标头或每个 bin 文件在256字节后都有标头和重置处理程序?

    3)我的主要问题是为什么引导应用程序示例代码能够将 VTOR 写入5900但在我的应用程序不能将 VTOR 写入3E80尽管使用了相同的功能,在引导应用程序示例中要额外注意写入 VTOR 吗?  

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

    以下是引导应用程序指南:

    https://dev.ti.com/tirex/explore/node?node=A__APjkYg9RWxwM6nRUc3InzA__MSPM0-SDK__a3PaaoK__LATEST

    1)另外在链接器命令文件中分配了 FLASH = 0x5900、但在加载时、他们提到闪存为0x5800、所以为什么这个256字节的间隔?

    它为 MCUBOOT HEAD 保留闪存的0x100长度。

    Building the image will require several modifications to a standard linker file: * The start of the flash will need to be considered as the beginning of the image slot plus the header offset. For example, if the primary image slot starts at 0x5400, and the mcuboot header is of size 0x100, the first element of flash of the application (the interrupt vector table) should be at address 0x5500.

    2)是否有任何用于处理引导应用程序的标头或每个 bin 文件都有256字节后的标头和重置处理程序?

    代码的每个部分都应该有一组 int vector。

    3)我的主要问题是、为什么引导应用程序示例代码能够将 VTOR 写入5900、但在我的应用程序中、尽管使用了相同的函数、但仍无法将 VTOR 写入3E80、在引导应用程序示例中要格外小心以写入 VTOR?  [/报价]

    从我以前的经验来看,没有什么需要注意的。

    您可以参阅此寄存器来进行特权 模式调试:

    https://developer.arm.com/documentation/dui0662/b/The-Cortex-M0--Processor/Programrs-model/Core-registers

    CONTROL register
    The CONTROL register controls the stack used, and the optional privilege level for software execution, when the processor is in Thread mode. See the register summary in Table 2.2 for its attributes. The bit assignments are:

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

    感谢您的建议。

    通过执行以下步骤可以解决我的问题

    1)将自定义引导加载程序和应用程序项目链接器文件设置为与引导应用程序和 BIM 示例相同。

    2)还将编译后步骤添加到引导应用程序示例代码中的自定义引导加载程序。

    3)仅在调试设置中擦除 MAIN 和 NONMAIN 存储器所需的扇区(开始调试时防止擦除存储器)

    但我测试了一件事、我尝试按如下方式设置链接器文件、但代码不起作用、但始终适用于0x5900

    引导加载程序链接器文件

    闪存= 0x0、长度= 0x3200 (12.8Kb)

    应用程序链接器文件(使用 BOOT 刷写的固件)

    闪存= 0x32C8、长度= 0x 1 BD50 (114Kb)

    保留1KB 用于验证参数、但我的代码不起作用、行为相同

    问题

    1)为什么会发生这种情况?

    2)根据参考手册、闪存大小为128KB、那么为什么在引导应用程序示例代码长度= 0x0002 0000 (近131KB)?

    3)引导加载程序长度可能足够大、以便适合通过引导加载程序刷写的另一个应用程序、然后只有在引导加载程序区域(引导加载程序知道的有效区域)中存在已刷写的应用程序时、我们才能设置 VTOR?

    4)是否有任何规定,您必须指定128的倍数地址?

    我认为我的编译后步骤可能是导致这种情况的原因

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

    我确实测试了设置 VTOR 的地址是128的倍数、并且每次都成功将所有这些地址写入 VTOR。

    因此、结论是 VTOR 仅支持地址、是128的倍数

    现在、Im 正在考虑删除上述所有提及的事项。我按照 BIM 示例代码执行了操作、并在代码中进行了引导、因此我可以找到顺利运行自定义引导加载程序和应用所需的内容、以及逐个使用此步骤的原因。

    我还需要澄清问题、我问您是否知道、

    您的建议确实有助于我找到解决方案。

    谢谢您、Helic。

    等待澄清和答案  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    1)那么为什么会发生这种情况呢?

    似乎您已经 将应用程序和引导分为两个不同的扇区。

    不 知道发生了什么。

    2)根据参考手册、闪存大小为128KB、那么为什么在引导应用程序中示例代码长度= 0x0002 0000 (近131KB)?

    1kB = 1000*1024字节

    1KB = 1个闪存扇区

    3)引导加载程序长度可能足够大、以便适合通过引导加载程序进行刷写的另一个应用程序、然后只有当引导加载程序区域(引导加载程序知道的有效区域)中存在已刷写的应用程序时、我们才能设置 VTOR?

    是的、引导加载程序负责验证 APP 区域。  

    4)是否必须以128的倍数指定地址?

    由于闪存的最小擦除大小为1KB、因此请将应用程序和启动分为扇区、 无法将相同的扇区地址范围用于启动和应用程序。

    这将导致在闪存应用程序时擦除整个扇区。

    我确实测试了如何使用128的倍数设置 VTOR、并且每次都将所有地址成功写入 VTOR。

    始终、我们将0x400对齐的地址设置为引导地址或应用起始地址。 因为这是扇区的起点。

    为了放入闪存最小擦除单元=扇区、也是0x400对齐的扇区。

    切勿测试未对齐0x400的地址。

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

    你能写更多关于行业的书吗?

    我的意思是、如果我要擦除之前编写的闪存、那么需要采取哪种预防措施?

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

    该扇区大小= 1KB 与闪存硬件结构相关。

    您需要了解的是、扇区是 MSPM0闪存的最小擦除大小。

    如果您使用任何方法将应用程序代码编程为闪存地址 a

    您需要确保此扇区中没有其他不应擦除的代码。

    因此、我们通常将整个闪存分为多个区域、以1KB (0x400)作为最小单元。

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

    好的、我会处理这个问题。

    从引导成功跳转到 APP 后、在我的应用中、当我尝试将0x1写入存储器位置  0x0001F058的闪存、但无法写入、并且没有显示错误。

    我尝试了更改链接器文件 FLASH = 0、然后成功写入0x1。

    如果我们需要进入引导加载程序来刷写新固件、则为引导加载程序验证写入0x1

    这是什么样的行为  

    #define BOOTLOADER_INT_LOCATION       ((uint32_t)0x0001F058) /* At this location flag set by applicant who wish to turn on boot mode to flash next hex */
    #define BOOTCMD                       0x00000001
    uint8_t bootCmd_Write(void) {
    
        uint32_t cmd = BOOTCMD;
    
        if (gErrorType == NO_ERROR) {
    
            DL_FlashCTL_unprotectSector(FLASHCTL, BOOTLOADER_INT_LOCATION, DL_FLASHCTL_REGION_SELECT_MAIN);
            gCmdStatus = DL_FlashCTL_programMemoryFromRAM32WithECCGenerated(
                                            FLASHCTL, BOOTLOADER_INT_LOCATION, &cmd);
    
            if (gCmdStatus == DL_FLASHCTL_COMMAND_STATUS_FAILED)
            {
                /* If command was not successful, set error flag */
                gErrorType = ERROR_WRITE_32_BIT;
            }
            if(gCmdStatus == DL_FLASHCTL_COMMAND_STATUS_IN_PROGRESS ) {
                gErrorType = MEMORY_WRITE_PROGRESS;
            }
        }
        return gErrorType;
    }

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我尝试了链接器文件闪存中的更改=0、然后成功写入0x1。

    什么是 FLASH = 0? 我没有看到链接器文件中有任何相关函数在做这样的工作。

    此外、请检查此地址是否为空(0xFF)、对非空地址的写入将导致具有闪存 ECC 的器件中出现 ECC 错误。

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

    FLASH == 0表示在应用程序闪存的链接器文件中、不会分配到其他0地址位置(默认位置)、以便测试存储器写入是否正确完成。 在默认位置时工作正常、但在闪存 0以外时工作正常。

    此外、I Test 用于不同的地址位置、但无法从刷写的引导加载程序写入闪存。

    但是、当 I Write 将 in 写入其长度(app 从0x9600开始、length = 0xA00、这个验证字节写入0x9F80)时、它就可以正常工作、并且通过完整的引导加载程序代码有效、所有这些都完成了。  

    所以最大的问题是为什么会发生这种情况??????? 任何参考?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    另外、我还要测试不同的地址位置、但无法从引导加载程序刷写应用程序写入闪存。

    这是如何不起作用的?

    应该会记录一些错误日志或返回一些错误、具体取决于您的引导加载程序函数。

    什么是这种现象[不能写],通信过程中有错误? 或者在引导过程中出现错误? 您是否尝试验证您正在写入的闪存?

    您是否尝试在向 M0发送应用代码期间使用引导加载程序进行调试?

    但当我用 in 输入其长度进行写入(app 从0x9600开始、长度= 0xA00、这个验证字节写入0x9F80)则很好、并且通过完整的引导加载程序代码有效、所有这些都完成。  [/报价]

    您在上面执行的测试之间是否有任何不同? [我的意思是不能写测试。]

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

    这种"无法写入"意味着我在尝试从使用引导加载程序刷写的应用程序进行写入时没有出现任何错误。

    我不知道这怎么不起作用,但这是我观察到的。 如果写入或未写入此引导命令、我还使用通用命令检查闪存。

    我试过调试。

    没有区别。

    那么、您能告诉我这是什么行为吗?  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [报价 userid="655847" url="~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1518595/lp-mspm0g3507-lp-mspm0g3507/5860418 #5860418"]

    这种"无法写入"意味着我在尝试从使用引导加载程序刷写的应用程序进行写入时没有出现任何错误。

    我不知道这怎么不起作用,但这是我观察到的。 如果写入或未写入此引导命令、我还使用通用命令检查闪存。

    [/报价]

    应用程序代码已成功编程到闪存中?

    您能告诉我这是什么行为吗?  [/报价]

    我不知道为什么跳跃是不成功的。

    您是否更改引导代码中的跳转地址?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    已成功将应用程序代码编程到闪存中?

    是成功、中断正常工作。

    [引述 userid="571933" url="~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1518595/lp-mspm0g3507-lp-mspm0g3507/5860627 #5860627"]

    我不知道为什么跳跃是不成功的。

    您是否更改引导代码中的跳转地址?

    [/报价]

    是的、为了成功实现分离跳转、但应用程序中的闪存写入除了其区域(长度)之外不会发生

    此外、我检查了不同的长度、并发现仅对0xA00长度才成功写入此闪存命令

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是的、要成功进行分离跳转、但应用程序中的闪存写入不会发生、而不是其区域(长度)

    您可以尝试根据 MSPM0 SDK 中的闪存演示验证此超出范围地址(修改链接器文件)