LP-MSPM0G3507: UART DMA TX 有時會無法正常運作

Part Number: LP-MSPM0G3507

在實作 UART DMA TX 時發生怪異現象就是有時候無法正常輸出字串到終端機

以下是無法正常運作的程式

#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() 裡多加輸出一串字串又可正常運作。如下紅字所示:
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__);
    UART_Console_Write("%s: %s %s\r\n", __FUNCTION__, __DATE__, __TIME__);

    while (1) {
        ;
    }
}
可正常運作及無法常運作的案例有很多情況。例如以下寫法也實無法輸出字串
 
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__);
    UART_Console_Write("%s: %s\r\n", __FUNCTION__, __TIMESTAMP__);

    while (1) {
        ;
    }
}
但變成以下寫法又可正常輸出:
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__);
    UART_Console_Write("%s: %s\r\n", __FUNCTION__, __TIMESTAMP__);
    UART_Console_Write("%s: %s %s\r\n", __FUNCTION__, __DATE__, __TIME__);

    while (1) {
        ;
    }
}
觀察發現正常時候的 .map 檔裡的 SEGMENT ALLOCATION MAP:如下:
而無法正常輸出的都會變成配置:
請協助解決這個問題,謝謝!