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:UART DMA TX CAN'工作。

Guru**** 2447530 points
Other Parts Discussed in Thread: SYSCONFIG

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1507297/lp-mspm0g3507-uart-dma-tx-can-work

器件型号:LP-MSPM0G3507
主题:SysConfig 中讨论的其他器件

工具/软件:

 此问题的源代码如下所示:

#include "ti_msp_dl_config.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>

volatile bool gCheckUART = false;
volatile bool gDMADone = false;
#define LOG_MAX_LENGTH 128

void UART_Console_Write(const char *data, ...)
{
    char log_buf[LOG_MAX_LENGTH] = { 0 };
    va_list args;
    va_start(args, data);
    vsnprintf(log_buf, LOG_MAX_LENGTH, data, args);
    va_end(args);

    DL_DMA_setSrcAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)(log_buf));
    DL_DMA_setDestAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)(&UART_0_INST->TXDATA));
    DL_DMA_setTransferSize(DMA, DMA_CH0_CHAN_ID, strlen(log_buf));

    DL_SYSCTL_disableSleepOnExit();

    DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);

    DL_UART_Main_enableDMATransmitEvent(UART_0_INST);

    while (false == gDMADone) {
        __WFE();
    }

    DL_UART_Main_disableDMATransmitEvent(UART_0_INST);

    while (false == gCheckUART) {
        __WFE();
    }

    gCheckUART = false;
    gDMADone = false;
}

int main(void)
{
    SYSCFG_DL_init();
    NVIC_EnableIRQ(UART_0_INST_INT_IRQN);
    DL_SYSCTL_disableSleepOnExit();
   
    UART_Console_Write("%s: %s\r\n", __FUNCTION__, __TIMESTAMP__);

    while (1) {
        ;
    }
}

void UART_0_INST_IRQHandler(void)
{
    switch (DL_UART_Main_getPendingInterrupt(UART_0_INST)) {
        case DL_UART_MAIN_IIDX_EOT_DONE:
            gCheckUART = true;
            break;
        case DL_UART_MAIN_IIDX_DMA_DONE_TX:
            gDMADone = true;
            break;
        default:
            break;
    }
}
但在 main()中添加如下所示的红色单词后、MCU 和 UART 将正常工作。
内部  main (void)
   SYSCFG_DL_init ();
   NVIC_EnableIRQ (UART_0_INST_INT_IRQN);
   DL_SYSCTL_disableSleepOnExit ();
  
   uart_tistamp__ Console_Write ("%s": %s\r\n"、__function__、__timestamp__);
    uart_date__ Console_Write ("%s:%s %s\r\n"、__function__、__date__、__time__);

   while (1){
    ;
  }
}
有许多情况会导致此问题。 我发现、 当  发生此问题时、.map 中的段分配映射将如下所示
如果没有发生此问题 、.map 中的段分配映射 将会很糟糕:
请帮助解决此问题。 谢谢!
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

     我这边带有单个 Console_Write 的演示运行正常。

    我正在使用 CCS 20.1.1.8

    相关性

    (SDK 2.4.0.6)

    SysConfig 1.22.0

    编译器 TI Clang 4.0.2 LTS

    e2e.ti.com/.../uart_5F00_log_5F00_tx_5F00_dmaInt_5F00_LP_5F00_MSPM0G3507_5F00_nortos_5F00_ticlang.zip

    这可能与编译器问题有关、您可以尝试在依赖项环境中将优化级别设置为无、然后再次进行测试。

    试用我的环境。

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

    我的环境:

    CCS:20.1.1.8__1.7.1

    SDK:2.4.0.06

    SysConfig 为1.22.0

    编译器: TI Clang 4.0.2 LTS

    我曾尝试将 优化级别设置为0、但仍然出现问题。

    请按如下方式修改 main():

    构建后、段分配映射将如下所示:

    加载.bin 而不是.out 文件

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

    在故障案例中、您看到了什么结果?

    -----

    您在.map 中看到的额外行是段对齐工件、并不重要。

    -----

    > DL_DMA_enableChannel (DMA、DMA_CH0_CHAN_ID);

    > DL_UART_Main_enableDMATransmitEvent (UART_0_INST);

    尝试反转这两行(即相反顺序)。

    -----

    此外、(a)增加栈大小或(b)将 log_buf[]设置为全局/静态。

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

    > DL_DMA_enableChannel (DMA、DMA_CH0_CHAN_ID);

    > DL_UART_Main_enableDMATransmitEvent (UART_0_INST);

    反转这两条线不起作用。

    增加栈大小或使 log_buf[]全局/静态也不起作用。

    发生此问题时、控制台上不会显示任何消息。

    我们的工程中也使用了 I2C。 此问题也会导致 I2C 无法正常工作。

    下面的 视频展示了该问题。  

    e2e.ti.com/.../ISSUE_5F00_2025_2D00_04_2D00_29-091816.mp4

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

    你看到 Helic 的项目和你的项目有什么不同吗? 我假设 Helic 从相同的 C 代码开始、因此可以查看 SysConfig。

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

    我直接使用了 Helic 的项目。

    我只在 main()中添加两行代码、如下所示:

    测试结果如下

    一条线路正常

      uart_tistamp__ Console_Write ("%s"%s\r\n"、__function__、__timestamp__);
    两行正常
       uart_tistamp__ Console_Write ("%s": %s\r\n"、__function__、__timestamp__);
       uart_tistamp__ Console_Write ("%s": %s\r\n"、__function__、__timestamp__);
    三行不正常
       uart_tistamp__ Console_Write ("%s": %s\r\n"、__function__、__timestamp__);
       uart_tistamp__ Console_Write ("%s": %s\r\n"、__function__、__timestamp__);
       uart_tistamp__ Console_Write ("%s": %s\r\n"、__function__、__timestamp__);
    四条线不能正常
       uart_tistamp__ Console_Write ("%s": %s\r\n"、__function__、__timestamp__);
       uart_tistamp__ Console_Write ("%s": %s\r\n"、__function__、__timestamp__);
       uart_tistamp__ Console_Write ("%s": %s\r\n"、__function__、__timestamp__);
       uart_tistamp__ Console_Write ("%s": %s\r\n"、__function__、__timestamp__);
    五行正常
       uart_tistamp__ Console_Write ("%s": %s\r\n"、__function__、__timestamp__);
       uart_tistamp__ Console_Write ("%s": %s\r\n"、__function__、__timestamp__);
       uart_tistamp__ Console_Write ("%s": %s\r\n"、__function__、__timestamp__);
       uart_tistamp__ Console_Write ("%s": %s\r\n"、__function__、__timestamp__);
       uart_tistamp__ Console_Write ("%s": %s\r\n"、__function__、__timestamp__);
    六行不正常
       uart_tistamp__ Console_Write ("%s": %s\r\n"、__function__、__timestamp__);
       uart_tistamp__ Console_Write ("%s": %s\r\n"、__function__、__timestamp__);
       uart_tistamp__ Console_Write ("%s": %s\r\n"、__function__、__timestamp__);
       uart_tistamp__ Console_Write ("%s": %s\r\n"、__function__、__timestamp__);
       uart_tistamp__ Console_Write ("%s": %s\r\n"、__function__、__timestamp__);
       uart_tistamp__ Console_Write ("%s": %s\r\n"、__function__、__timestamp__);
    此问题可以在没有规则的情况下重现。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    有两个潜在的点会导致此问题:编译器和事件。

    事件:

    请删除此处的 UART Tx DMA 事件禁用和启用功能:

    void UART_Console_Write(const char *data, ...)
    {
        char log_buf[LOG_MAX_LENGTH] = { 0 };
        va_list args;
    
        va_start(args, data);
        vsnprintf(log_buf, LOG_MAX_LENGTH, data, args);
        va_end(args);
    
        DL_DMA_setSrcAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)(log_buf));
        DL_DMA_setDestAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)(&UART_0_INST->TXDATA));
        DL_DMA_setTransferSize(DMA, DMA_CH0_CHAN_ID, strlen(log_buf));
    
        DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);
    
        while (false == gDMADone) {
            __WFE();
        }
    
        while (false == gCheckUART) {
            __WFE();
        }
    
        gCheckUART = false;
        gDMADone = false;
    }

    在此工程中、我  Console_Write 从1 ~ 6次开始测试 UART_EVM、所有操作都正常。

    e2e.ti.com/.../1212.uart_5F00_log_5F00_tx_5F00_dmaInt_5F00_LP_5F00_MSPM0G3507_5F00_nortos_5F00_ticlang.zip

    对于编译器、我默认使用 O2

    我尝试将 优化级别设置为0、但问题仍然存在。

    好的、很好。

    请尝试使用 gcc 版本 M0工程。

    您可以导入 gcc 工程并将源文件和 syscfg 复制到 gcc 工程。

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

     删除了 UART Tx DMA 事件禁用和启用功能后、仍然会发生该问题。

    这一次、当 Console_Write 执行 uart_uart() 1、2和5次时、就会出现问题。

    在删除 UART Tx  Console_Write 事件禁用和启用功能之前、当 UART_DMA ()执行3、4和6次时会发生问题。

    我想您无法看到此问题、因为您使用.out 文件进行加载。

    如果要看到此问题、必须使用.bin 文件进行加载。

    视频中的项目是您刚才提供的项目。

    此视频显示当 uart_uart() Console_Write 被执行1次时发生的问题。

    e2e.ti.com/.../ISSUE_5F00_2025_2D00_04_2D00_29-155723.mp4

    下面的视频展示了在 执行了3次 Console_Write ()时效果很好。

     .bin 和.out 文件均可正常运行。

    e2e.ti.com/.../OK_5F00_2025_2D00_04_2D00_29-161810.mp4

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

    让我寻求编译器团队的帮助。

    同时、请尝试以下操作

    您可以导入 gcc 工程并将源文件和 syscfg 复制到 gcc 工程。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我测试 uart_gcc  () 1~15次后,这个问题不会在 Console_Write 项目上发生。

    编译器:GNU v9.2.1

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

    很高兴听到这个消息。

    请使用 gcc。

    同时等待一些编译器团队注释。

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

    我无法使用 gcc 是因为一些原因。

    我想我需要您的编译器团队来修复它。

    谢谢你。

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

    让我们等待回复~

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

    请重新编译整个工程。  然后将 Output View (输出视图 )的内容保存到文本文件中。   该文本文件附加到下一个帖子。

    谢谢。此致、

    -乔治

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

    您请求的文件已附加。

    e2e.ti.com/.../1538.Output.txt

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

    请勿使用十六进制实用程序来创建二进制文件。  请改用 tiarmobjcopy。  以下是一个示例命令:

    tiarmobjcopy -O 二进制可执行文件 file.out binary_file.bin

    谢谢。此致、

    -乔治

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

    感谢您的答复。

    我知道如何使用此命令、因为我是初学者。

    我尝试更改如图所示的设置。

    我 认为 这与此命令相同、因为 在加载.bin 文件后不会发生问题   

    但是、我必须检查可以在我们的应用中使用 Arm objcopy 实用程序创建的 BIN 文件、因为我们计划了一段闪存空间来存储数据。

    此外、在我们的应用程序中 、我们将使用.map 文件中的信息 、因此我仍然有疑问。

    发生问题时、.map 文件的内容如下图所示。

    为什么  下图中1的长度(0x22d0)与2 (0x22c0+0x18 = 0x22d8)不同? 哪一个是正确的?

    为什么 Arm Hex Utility 创建的.bin 文件的大小为值1 (0x22d0)、但  Arm objcopy 实用程序创建的.bin 文件的大小为值 2 (0x22d8)?

    未出现问题时、.map 文件的内容如 下图所示。

    显然、值1 (0x22e8)和2 (0x22d0+0x18 = 0x22e8)是相同的

    为什么无法使用 Arm  Hex Utility 来创建二进制文件? 问题是由  Arm Hex Utility 引起的吗?

     使用 tiarmobjcopy  创建二进制文件是否是一个权变措施解决方案?

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

    您的配置 tiarmobjcopy 正确。

    请阅读文章 二进制文件简介。  重点关注名为  Holes in a Binary File (二进制文件中的孔)的部件。  默认情况下、 tiarmhex 创建二进制文件时忽略空洞。  有一种方法可以更改此行为。  但最好使用 tiarmobjcopy 而是用零填充孔洞。  在你的情况下,我不能从你到目前为止所显示的孔的位置来确定孔的位置。  但我相信有一个或多个孔存在。

    谢谢。此致、

    -乔治