F28M35H52C: M3核心UART3怎么启用μDMA进行串口数据的收发

Part Number: F28M35H52C

官方的demo(F28M35x_examples Masterudma_demolmn3wudma_demo.c)是关于UART0回环模式的,但我想要用UART3支持中断+FHIFO+VDMA模式,请问应该怎么配置?有这方面的例程吗?


下面是我的一些代码配置:

//*****************************************************************************

// udma_integration_simple.c - 绠�鍖栫殑碌DMA闆嗘垚瀹炵幇

// 涓撻棬閽堝褰撳墠M3-377S閫氫俊绯荤粺浼樺寲锛屼繚鎸佹渶澶у吋瀹规��

//*****************************************************************************

 

#include "udma_integration_simple.h"

#include <string.h>

#include <stdio.h>

#include <stdarg.h>

 

// 澹版槑澶栭儴printf鍑芥暟锛堝湪blinky_dc_m3.c涓疄鐜帮級

extern int printf(const char* format, ...);

 

// 澹版槑澶栭儴鍗忚鍑芥暟锛堝湪levitation_protocol.h涓疄鐜帮紝鐢眀linky_dc_m3.c鍖呭惈锛�

extern uint16_t LevitationSimple_calculateCRC(const uint16_t* data, uint16_t length);

extern bool LevitationSimple_deserialize(const uint16_t* buffer, uint16_t buffer_size, void* data);

 

// 鍓嶅悜澹版槑鍗忚鏁版嵁缁撴瀯锛堝畬鏁村畾涔夊湪levitation_protocol.h涓級

typedef struct {

    uint16_t data_length;

    uint16_t* data_fields;

    uint16_t device;

    uint16_t type;

} LevitationSimple_t;

 

//*****************************************************************************

// 鍏ㄥ眬鍙橀噺瀹氫箟

//*****************************************************************************

 

// 碌DMA鎺у埗琛紙蹇呴』1024瀛楄妭瀵归綈锛�

#pragma DATA_ALIGN(ucSimpleUDMAControlTable, 1024)

uint8_t ucSimpleUDMAControlTable[UDMA_CONTROL_TABLE_SIZE];

 

// 绠�鍖栫殑碌DMA UART瀹炰緥

SimpleUDMAUART_t g_simpleUDMAUART = {0};

 

//*****************************************************************************

// 绉佹湁鍑芥暟澹版槑

//*****************************************************************************

static void SimpleUDMA_ResetPacketState(void);

static bool SimpleUDMA_ValidatePacket(const uint8_t* data, uint16_t length);

static void SimpleUDMA_ConfigureUART3(void);

static void SimpleUDMA_ConfigureDMA(void);

 

//*****************************************************************************

// 鍒濆鍖栧嚱鏁板疄鐜�

//*****************************************************************************

 

//*****************************************************************************

// 鍒濆鍖栫畝鍖栫殑碌DMA UART绯荤粺

//*****************************************************************************

void SimpleUDMA_Init(void)

{

    // 娓呴浂缁撴瀯浣�

    memset(&g_simpleUDMAUART, 0, sizeof(SimpleUDMAUART_t));

   

    // 鍒濆鍖栨暟鎹寘鐘舵��

    SimpleUDMA_ResetPacketState();

   

    // 浣胯兘碌DMA澶栬

    SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);

    SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA);

   

    // 浣胯兘碌DMA鎺у埗鍣�

    uDMAEnable();

   

    // 璁剧疆鎺у埗琛ㄥ熀鍦板潃

    uDMAControlBaseSet(ucSimpleUDMAControlTable);

   

    // 鍏堥厤缃礑MA閫氶亾鏄犲皠锛堢‘淇漊ART3浣跨敤绗笁缁勯�氶亾锛�

    uDMAChannel16_23SelectAltMapping(UDMA_CHAN16_THRD_UART3RX | UDMA_CHAN17_THRD_UART3TX);

   

    // 閰嶇疆碌DMA

    SimpleUDMA_ConfigureDMA();

   

    // 閰嶇疆UART3锛堝湪碌DMA閰嶇疆涔嬪悗锛�

    SimpleUDMA_ConfigureUART3();

   

    // 娉ㄥ唽涓柇澶勭悊鍑芥暟

    IntRegister(INT_UART3, SimpleUDMA_IntHandler);

    IntRegister(INT_UDMAERR, SimpleUDMA_ErrorHandler);

   

    // 浣胯兘涓柇

    IntEnable(INT_UART3);

    IntEnable(INT_UDMAERR);

   

    // 鏍囪DMA宸插惎鐢�

    g_simpleUDMAUART.dmaEnabled = true;

   

    // 鍚姩鎺ユ敹

    SimpleUDMA_StartReceive();

}

 

//*****************************************************************************

// 鍙嶅垵濮嬪寲绠�鍖栫殑碌DMA UART绯荤粺

//*****************************************************************************

void SimpleUDMA_Deinit(void)

{

    // 鍋滄鎺ユ敹

    SimpleUDMA_StopReceive();

   

    // 绂佺敤碌DMA閫氶亾

    uDMAChannelDisable(UDMA_CHANNEL_UART3RX);

    uDMAChannelDisable(UDMA_CHANNEL_UART3TX);

   

    // 绂佺敤涓柇

    IntDisable(INT_UART3);

    IntDisable(INT_UDMAERR);

   

    // 绂佺敤碌DMA鎺у埗鍣�

    uDMADisable();

   

    // 绂佺敤碌DMA澶栬

    SysCtlPeripheralDisable(SYSCTL_PERIPH_UDMA);

   

    // 鏍囪DMA宸茬鐢�

    g_simpleUDMAUART.dmaEnabled = false;

}

 

//*****************************************************************************

// 閰嶇疆UART3澶栬锛堜繚鎸佷笌鐜版湁閰嶇疆鍏煎锛�

//*****************************************************************************

static void SimpleUDMA_ConfigureUART3(void)

{

    // 浣胯兘UART3澶栬

    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART3);

    SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART3);

   

    // 绛夊緟澶栬浣胯兘绋冲畾

    for(volatile int delay = 0; delay < 100; delay++) {}

   

    // 姝ラ1: 绂佺敤UART锛堟寜鐓I鏂囨。瑕佹眰锛�

    UARTDisable(UART3_BASE);

   

    // 姝ラ2: 閰嶇疆UART閫氫俊鍙傛暟锛圲ARTConfigSetExpClk浼氳嚜鍔ㄩ厤缃瓸RD锛�

    UARTConfigSetExpClk(UART3_BASE, SysCtlClockGet(SYSTEM_CLOCK_SPEED), 115200,

                        UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |

                        UART_CONFIG_PAR_NONE);

   

    // 姝ラ3: 璁剧疆FIFO瑙﹀彂绾у埆锛堝湪鍚敤UART涔嬪墠锛�

    UARTFIFOLevelSet(UART3_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8);

   

    // 姝ラ4: 閰嶇疆碌DMA锛堝湪鍚敤UART涔嬪墠锛�

    UARTDMAEnable(UART3_BASE, UART_DMA_RX | UART_DMA_TX);

   

    // 姝ラ5: 鍚敤UART锛堟渶鍚庢楠わ級

    UARTEnable(UART3_BASE);

    printf("M3: UART3 configured: 115200 bps, 8-N-1\r\n");

   

    // 绛夊緟UART浣胯兘绋冲畾

    for(volatile int delay = 0; delay < 100; delay++) {}

   

    // 娓呴櫎鎵�鏈塙ART閿欒鐘舵��

    UARTIntClear(UART3_BASE, UART_INT_OE | UART_INT_BE | UART_INT_PE | UART_INT_FE | UART_INT_RT | UART_INT_TX | UART_INT_RX);

   

    // 浣胯兘UART涓柇锛堝湪UART鍚敤鍚庯級

    UARTIntEnable(UART3_BASE, UART_INT_RX | UART_INT_RT | UART_INT_TX);

   

    // 妫�鏌ARTDMACTL瀵勫瓨鍣ㄦ槸鍚︽纭缃�

    unsigned long uartDmaCtl = HWREG(UART3_BASE + 0x48); // UARTDMACTL瀵勫瓨鍣ㄥ湴鍧�

    printf("M3: UARTDMACTL register: 0x%08lX\r\n", uartDmaCtl);

    printf("M3: TXDMAE (bit 1): %s\r\n", (uartDmaCtl & 0x02) ? "Enabled" : "Disabled");

    printf("M3: RXDMAE (bit 0): %s\r\n", (uartDmaCtl & 0x01) ? "Enabled" : "Disabled");

   

    // 妫�鏌ュ苟鎶ュ憡UART3 DR瀵勫瓨鍣ㄥ垵濮嬬姸鎬�

    unsigned long uartDrInit = HWREG(UART3_BASE + UART_O_DR);

    printf("M3: UART3 DR initial: 0x%08lX\r\n", uartDrInit);

    if (uartDrInit & 0x800) {

        printf("M3: WARNING: UART3 DR has error bit set initially\r\n");

    }

}

 

//*****************************************************************************

// 閰嶇疆碌DMA閫氶亾锛堢畝鍖栭厤缃級

//*****************************************************************************

static void SimpleUDMA_ConfigureDMA(void)

{

    // 閰嶇疆UART3 RX閫氶亾灞炴�э紙鎸夌収TI瀹樻柟渚嬬▼閰嶇疆锛�

    uDMAChannelAttributeDisable(UDMA_CHANNEL_UART3RX,

                                UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |

                                UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);

   

    // 閰嶇疆UART3 RX涓绘帶鍒剁粨鏋�

    uDMAChannelControlSet(UDMA_CHANNEL_UART3RX | UDMA_PRI_SELECT,

                          UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 |

                          UDMA_ARB_4);

   

    // 閰嶇疆UART3 RX澶囩敤鎺у埗缁撴瀯

    uDMAChannelControlSet(UDMA_CHANNEL_UART3RX | UDMA_ALT_SELECT,

                          UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 |

                          UDMA_ARB_4);

   

    // 璁剧疆UART3 RX涓讳紶杈撳弬鏁帮紙Ping-Pong妯″紡锛�

    uDMAChannelTransferSet(UDMA_CHANNEL_UART3RX | UDMA_PRI_SELECT,

                           UDMA_MODE_PINGPONG,

                           (void *)(UART3_BASE + UART_O_DR),

                           g_simpleUDMAUART.rxBufferA, sizeof(g_simpleUDMAUART.rxBufferA));

   

    // 璁剧疆UART3 RX澶囩敤浼犺緭鍙傛暟锛圥ing-Pong妯″紡锛�

    uDMAChannelTransferSet(UDMA_CHANNEL_UART3RX | UDMA_ALT_SELECT,

                           UDMA_MODE_PINGPONG,

                           (void *)(UART3_BASE + UART_O_DR),

                           g_simpleUDMAUART.rxBufferB, sizeof(g_simpleUDMAUART.rxBufferB));

   

    // 閰嶇疆UART3 TX閫氶亾灞炴�э紙鎸夌収SSI渚嬪瓙锛屼笉绂佺敤REQMASK锛�

    uDMAChannelAttributeDisable(UDMA_CHANNEL_UART3TX,

                                UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_USEBURST);

   

    // 閰嶇疆UART3 TX鎺у埗鍙傛暟锛堜紭鍖栦紶杈撴晥鐜囷級

    uDMAChannelControlSet(UDMA_CHANNEL_UART3TX | UDMA_PRI_SELECT,

                          UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE |

                          UDMA_ARB_4);  // 浣跨敤4瀛楄妭浠茶锛屾彁楂樹紶杈撴晥鐜�

}

 

//*****************************************************************************

// 浼犺緭鎺у埗鍑芥暟瀹炵幇

//*****************************************************************************

 

//*****************************************************************************

// 鍚姩碌DMA鎺ユ敹

//*****************************************************************************

void SimpleUDMA_StartReceive(void)

{

    if (g_simpleUDMAUART.dmaEnabled)

    {

        uDMAChannelEnable(UDMA_CHANNEL_UART3RX);

    }

}

 

//*****************************************************************************

// 鍋滄碌DMA鎺ユ敹

//*****************************************************************************

void SimpleUDMA_StopReceive(void)

{

    uDMAChannelDisable(UDMA_CHANNEL_UART3RX);

}

 

//*****************************************************************************

// 鍙戦�佹暟鎹寘锛堜繚鎸佷笌鐜版湁鎺ュ彛鍏煎锛�

//*****************************************************************************

bool SimpleUDMA_SendPacket(const uint8_t* data, uint16_t length)

{

    if (!g_simpleUDMAUART.dmaEnabled || length > UART_TX_BUFFER_SIZE)

    {

        return false;

    }

   

    // 妫�鏌X閫氶亾鏄惁蹇欑

    if (uDMAChannelIsEnabled(UDMA_CHANNEL_UART3TX))

    {

        // 妫�鏌ラ�氶亾鐘舵��

        unsigned long ulMode = uDMAChannelModeGet(UDMA_CHANNEL_UART3TX | UDMA_PRI_SELECT);

        printf("M3: TX channel enabled, mode: 0x%08lX (STOP=0x%08lX)\r\n", ulMode, UDMA_MODE_STOP);

       

        // 妫�鏌ユ槸鍚︽槸浼犺緭瀹屾垚鐘舵�侊紙妯″紡0x00000001琛ㄧず浼犺緭瀹屾垚浣嗛�氶亾鏈鐢級

        if (ulMode == 0x00000001)

        {

            printf("M3: TX transmission completed but channel not disabled, forcing disable\r\n");

            uDMAChannelDisable(UDMA_CHANNEL_UART3TX);

        }

        else

        {

            printf("M3: TX channel still busy, mode: 0x%08lX\r\n", ulMode);

            return false; // 涓婃浼犺緭杩樻湭瀹屾垚

        }

    }

   

    // 澶嶅埗鏁版嵁鍒癟X缂撳啿鍖�

    memcpy(g_simpleUDMAUART.txBuffer, data, length);

   

    // 瀹屽叏绂佺敤骞堕噸鏂伴厤缃甌X閫氶亾

    uDMAChannelDisable(UDMA_CHANNEL_UART3TX);

   

    // 绛夊緟閫氶亾瀹屽叏绂佺敤

    while (uDMAChannelIsEnabled(UDMA_CHANNEL_UART3TX)) {

        // 绛夊緟閫氶亾绂佺敤

    }

   

    // 浼樺寲碌DMA閰嶇疆锛屾彁楂樹紶杈撴晥鐜�

    // 浣跨敤4瀛楄妭浠茶锛屾彁楂樹紶杈撴晥鐜�

    uDMAChannelControlSet(UDMA_CHANNEL_UART3TX | UDMA_PRI_SELECT,

                          UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_4);

   

    // 璁剧疆浼犺緭鍙傛暟锛堜娇鐢˙ASIC妯″紡锛�

    uDMAChannelTransferSet(UDMA_CHANNEL_UART3TX | UDMA_PRI_SELECT,

                           UDMA_MODE_BASIC, g_simpleUDMAUART.txBuffer,

                           (void *)(UART3_BASE + UART_O_DR), length);

   

    // 楠岃瘉浼犺緭閰嶇疆

    printf("M3: 碌DMA Transfer Config: Mode=BASIC, Src=0x%08X, Dst=0x%08X, Size=%d\r\n",

           (unsigned int)g_simpleUDMAUART.txBuffer,

           (unsigned int)(UART3_BASE + UART_O_DR),

           length);

   

    // 绮剧畝鏃ュ織锛氱Щ闄よ缁嗙殑閰嶇疆淇℃伅

   

    // 璇︾粏鏃ュ織锛氭樉绀哄彂閫佺殑鏁版嵁鍐呭

    printf("M3: 碌DMA sending %d bytes: ", length);

    for(int i = 0; i < length && i < 16; i++) {

        printf("%02X ", data[i]);

    }

    printf("\r\n");

   

    // 妫�鏌X缂撳啿鍖哄唴瀹�

    printf("M3: TX Buffer content: ");

    for(int i = 0; i < length && i < 16; i++) {

        printf("%02X ", g_simpleUDMAUART.txBuffer[i]);

    }

    printf("\r\n");

   

    // 浣胯兘閫氶亾锛堟寜鐓у畼鏂筪emo鏂瑰紡锛�

    uDMAChannelEnable(UDMA_CHANNEL_UART3TX);

   

    // 妫�鏌ラ�氶亾鏄惁鐪熺殑琚惎鐢�

    if (uDMAChannelIsEnabled(UDMA_CHANNEL_UART3TX)) {

        printf("M3: 碌DMA TX channel successfully enabled\r\n");

    } else {

        printf("M3: ERROR: 碌DMA TX channel failed to enable\r\n");

        return false;

    }

   

    // 娣诲姞杞欢瑙﹀彂锛堟寜鐓SI渚嬪瓙鐨勬柟寮忥級

    uDMAChannelRequest(UDMA_CHANNEL_UART3TX);

    printf("M3: 碌DMA TX channel software request sent\r\n");

   

    // 绛夊緟涓�灏忔鏃堕棿纭繚浼犺緭寮�濮�

    for(volatile int startDelay = 0; startDelay < 100; startDelay++) {}

   

    // 璇婃柇锛氭鏌ART3 TX寮曡剼鐘舵��

    unsigned long gpioData = GPIOPinRead(GPIO_PORTD_BASE, GPIO_PIN_4);

    printf("M3: UART3 TX (PD4) pin state: %s\r\n", (gpioData & GPIO_PIN_4) ? "High" : "Low");

   

    // 楠岃瘉鏂规硶1锛氭鏌ART3鏁版嵁瀵勫瓨鍣ㄦ槸鍚︽湁鏁版嵁鍐欏叆

    unsigned long uartDrBefore = HWREG(UART3_BASE + UART_O_DR);

    printf("M3: UART3 DR before 碌DMA: 0x%08lX\r\n", uartDrBefore);

   

    // 楠岃瘉鏂规硶2锛氭鏌ART3 TX FIFO鐘舵�侊紙鍩轰簬瀵勫瓨鍣ㄨ〃锛�

    unsigned long uartFrBefore = HWREG(UART3_BASE + UART_O_FR);

    printf("M3: UART3 FR before 碌DMA: 0x%08lX\r\n", uartFrBefore);

    printf("M3:   TXFE:%s, TXFF:%s, RXFE:%s, RXFF:%s\r\n",

           (uartFrBefore & UART_FR_TXFE) ? "Yes" : "No",

           (uartFrBefore & UART_FR_TXFF) ? "Yes" : "No",

           (uartFrBefore & UART_FR_RXFE) ? "Yes" : "No",

           (uartFrBefore & UART_FR_RXFF) ? "Yes" : "No");

   

    // 楠岃瘉鏂规硶3锛氭鏌ART3涓柇鐘舵��

    unsigned long uartIntBefore = UARTIntStatus(UART3_BASE, 0);

    printf("M3: UART3 Interrupt Status before 碌DMA: 0x%08lX\r\n", uartIntBefore);

   

    // 楠岃瘉鏂规硶4锛氭鏌ART3鎺у埗瀵勫瓨鍣�

    unsigned long uartCtlBefore = HWREG(UART3_BASE + UART_O_CTL);

    printf("M3: UART3 Control before 碌DMA: 0x%08lX\r\n", uartCtlBefore);

   

    // 绛夊緟浼犺緭瀹屾垚锛堢粰碌DMA鏇村鏃堕棿锛�

    volatile int waitCount = 0;

    unsigned long lastDrValue = HWREG(UART3_BASE + UART_O_DR);

    unsigned long lastFrValue = uartFrBefore;

    unsigned long lastIntValue = uartIntBefore;

    bool dmaDataDetected = false;

    bool transmissionStarted = false;

   

    printf("M3: Starting 碌DMA transmission monitoring...\r\n");

   

    while (uDMAChannelIsEnabled(UDMA_CHANNEL_UART3TX) && waitCount < 10000) {

        waitCount++;

       

        // 妫�鏌ヤ紶杈撴槸鍚﹀凡寮�濮�

        if (!transmissionStarted) {

            unsigned long currentDrValue = HWREG(UART3_BASE + UART_O_DR);

            if (currentDrValue != lastDrValue) {

                printf("M3: 鉁� 碌DMA transmission started at iteration %d\r\n", waitCount);

                transmissionStarted = true;

                dmaDataDetected = true;

            }

        }

       

        // 姣�25娆¤凯浠f鏌ヤ竴娆ART3鐘舵�佸彉鍖栵紙鏇撮绻佺殑鐩戞帶锛�

        if (waitCount % 100 == 0) {

            unsigned long currentDrValue = HWREG(UART3_BASE + UART_O_DR);

            unsigned long currentFrValue = HWREG(UART3_BASE + UART_O_FR);

            unsigned long currentIntValue = UARTIntStatus(UART3_BASE, 0);

           

            // 妫�鏌R瀵勫瓨鍣ㄥ彉鍖栵紙璇佹槑鏁版嵁琚啓鍏ART锛�

            if (currentDrValue != lastDrValue) {

                printf("M3: 鉁� DMA DATA DETECTED: DR changed from 0x%08lX to 0x%08lX at iteration %d\r\n",

                       lastDrValue, currentDrValue, waitCount);

                lastDrValue = currentDrValue;

                dmaDataDetected = true;

            }

           

            // 妫�鏌IFO鐘舵�佸彉鍖栵紙璇佹槑鏁版嵁鍦‵IFO涓級

            if (currentFrValue != lastFrValue) {

                printf("M3: 鉁� FIFO STATUS CHANGED: FR changed from 0x%08lX to 0x%08lX at iteration %d\r\n",

                       lastFrValue, currentFrValue, waitCount);

                printf("M3:   TXFE:%s, TXFF:%s, RXFE:%s, RXFF:%s\r\n",

                       (currentFrValue & UART_FR_TXFE) ? "Yes" : "No",

                       (currentFrValue & UART_FR_TXFF) ? "Yes" : "No",

                       (currentFrValue & UART_FR_RXFE) ? "Yes" : "No",

                       (currentFrValue & UART_FR_RXFF) ? "Yes" : "No");

                lastFrValue = currentFrValue;

                dmaDataDetected = true;

            }

           

            // 妫�鏌ヤ腑鏂姸鎬佸彉鍖�

            if (currentIntValue != lastIntValue) {

                printf("M3: 鉁� INTERRUPT STATUS CHANGED: Int changed from 0x%08lX to 0x%08lX at iteration %d\r\n",

                       lastIntValue, currentIntValue, waitCount);

                lastIntValue = currentIntValue;

                dmaDataDetected = true;

            }

           

            // 妫�鏌ヂ礑MA閫氶亾妯″紡鍙樺寲

            unsigned long ulMode = uDMAChannelModeGet(UDMA_CHANNEL_UART3TX | UDMA_PRI_SELECT);

            if (ulMode != UDMA_MODE_STOP) {

                printf("M3: 碌DMA TX Mode at iteration %d: 0x%08lX (STOP=0x%08lX)\r\n", waitCount, ulMode, UDMA_MODE_STOP);

               

                // 如果通道卡在0x00000001模式(传输完成但未禁用),强制禁用

                if (ulMode == 0x00000001) {

                    printf("M3: 碌DMA channel stuck in mode 0x00000001, forcing disable\r\n");

                    uDMAChannelDisable(UDMA_CHANNEL_UART3TX);

                    break;

                }

            }

           

            // 妫�鏌ヂ礑MA閫氶亾鏄惁浠嶇劧鍚敤

            bool channelEnabled = uDMAChannelIsEnabled(UDMA_CHANNEL_UART3TX);

            printf("M3: 碌DMA Channel Enabled: %s at iteration %d\r\n", channelEnabled ? "YES" : "NO", waitCount);

           

            // 妫�鏌ART TX FIFO鏄惁涓虹┖锛堜紶杈撳彲鑳藉畬鎴愶級

            if (currentFrValue & UART_FR_TXFE) {

                printf("M3: 鉁� UART TX FIFO is empty at iteration %d - transmission may be complete\r\n", waitCount);

            }

        }

       

        // 濡傛灉浼犺緭宸插紑濮嬩笖UART FIFO涓虹┖锛屽彲鑳戒紶杈撳凡瀹屾垚

        if (transmissionStarted && (HWREG(UART3_BASE + UART_O_FR) & UART_FR_TXFE)) {

            // 绛夊緟涓�灏忔鏃堕棿纭繚浼犺緭鐪熸瀹屾垚

            for(volatile int finalWait = 0; finalWait < 100; finalWait++) {}

           

            // 鍐嶆妫�鏌ラ�氶亾鐘舵��

            if (!uDMAChannelIsEnabled(UDMA_CHANNEL_UART3TX)) {

                printf("M3: 鉁� 碌DMA transmission completed naturally at iteration %d\r\n", waitCount);

                break;

            }

        }

    }

   

    // 浼犺緭瀹屾垚鍚庣殑鎬荤粨

    if (dmaDataDetected) {

        printf("M3: 鉁� DMA TRANSMISSION SUCCESS: Data was detected in UART3 registers\r\n");

    } else {

        printf("M3: 鉁� DMA TRANSMISSION FAILED: No data detected in UART3 registers\r\n");

    }

   

    if (waitCount >= 10000) {

        printf("M3: ERROR: 碌DMA TX timeout after 10000 iterations\r\n");

        printf("M3: 碌DMA transmission failed - no fallback, DMA only mode\r\n");

       

        // 寮哄埗绂佺敤閫氶亾骞堕噸缃姸鎬�

        uDMAChannelDisable(UDMA_CHANNEL_UART3TX);

       

        // 閲嶇疆鏁版嵁鍖呰鏁帮紝鍥犱负浼犺緭澶辫触

        g_simpleUDMAUART.errorCount++;

       

        return false; // 杩斿洖澶辫触鐘舵��

    } else {

        printf("M3: 碌DMA TX completed after %d iterations\r\n", waitCount);

    }

   

    // 楠岃瘉鏂规硶3锛氫紶杈撳畬鎴愬悗鐨勬渶缁堢姸鎬佹鏌�

    unsigned long uartDrAfter = HWREG(UART3_BASE + UART_O_DR);

    unsigned long uartFrAfter = HWREG(UART3_BASE + UART_O_FR);

    unsigned long uartIntAfter = UARTIntStatus(UART3_BASE, 0);

    unsigned long uartCtlAfter = HWREG(UART3_BASE + UART_O_CTL);

   

    printf("M3: ===== FINAL UART3 STATUS COMPARISON =====\r\n");

    printf("M3: UART3 DR: 0x%08lX -> 0x%08lX (changed: %s)\r\n",

           uartDrBefore, uartDrAfter, (uartDrAfter != uartDrBefore) ? "YES" : "NO");

    printf("M3: UART3 FR: 0x%08lX -> 0x%08lX (changed: %s)\r\n",

           uartFrBefore, uartFrAfter, (uartFrAfter != uartFrBefore) ? "YES" : "NO");

    printf("M3: UART3 Int: 0x%08lX -> 0x%08lX (changed: %s)\r\n",

           uartIntBefore, uartIntAfter, (uartIntAfter != uartIntBefore) ? "YES" : "NO");

    printf("M3: UART3 CTL: 0x%08lX -> 0x%08lX (changed: %s)\r\n",

           uartCtlBefore, uartCtlAfter, (uartCtlAfter != uartCtlBefore) ? "YES" : "NO");

   

    printf("M3: Final UART3 FR: 0x%08lX (TXFE:%s, TXFF:%s, RXFE:%s, RXFF:%s)\r\n",

           uartFrAfter,

           (uartFrAfter & UART_FR_TXFE) ? "Yes" : "No",

           (uartFrAfter & UART_FR_TXFF) ? "Yes" : "No",

           (uartFrAfter & UART_FR_RXFE) ? "Yes" : "No",

           (uartFrAfter & UART_FR_RXFF) ? "Yes" : "No");

   

    // 杞欢妫�娴婦MA浼犺緭鏄惁鎴愬姛鐨勭患鍚堝垽鏂�

    bool dmaSuccess = false;

    printf("M3: ===== DMA TRANSMISSION ANALYSIS =====\r\n");

   

    if (uartDrAfter != uartDrBefore) {

        printf("M3: 鉁� DR Register changed - DMA wrote data to UART3\r\n");

        dmaSuccess = true;

    } else {

        printf("M3: 鉁� DR Register unchanged - No DMA data written\r\n");

    }

   

    if (uartFrAfter != uartFrBefore) {

        printf("M3: 鉁� FR Register changed - FIFO status modified\r\n");

        dmaSuccess = true;

    } else {

        printf("M3: 鉁� FR Register unchanged - No FIFO activity\r\n");

    }

   

    if (uartIntAfter != uartIntBefore) {

        printf("M3: 鉁� Interrupt Status changed - UART activity detected\r\n");

        dmaSuccess = true;

    } else {

        printf("M3: 鉁� Interrupt Status unchanged - No UART interrupts\r\n");

    }

   

    printf("M3: ===== FINAL DMA RESULT: %s =====\r\n", dmaSuccess ? "SUCCESS" : "FAILED");

   

    // 棰濆绛夊緟锛岀‘淇漊ART FIFO瀹屽叏娓呯┖

    printf("M3: Waiting for UART FIFO to clear...\r\n");

    for(volatile int fifoWait = 0; fifoWait < 10000; fifoWait++) {

        unsigned long frStatus = HWREG(UART3_BASE + UART_O_FR);

        if (frStatus & UART_FR_TXFE) {  // TX FIFO Empty

            printf("M3: UART FIFO cleared after %d iterations\r\n", fifoWait);

            break;

        }

        if (fifoWait == 9999) {

            printf("M3: WARNING: UART FIFO clear timeout\r\n");

        }

    }

   

    // 楠岃瘉鏂规硶4锛氭鏌ヂ礑MA閫氶亾鏈�缁堢姸鎬�

    if (uDMAChannelIsEnabled(UDMA_CHANNEL_UART3TX)) {

        unsigned long finalMode = uDMAChannelModeGet(UDMA_CHANNEL_UART3TX | UDMA_PRI_SELECT);

        printf("M3: Final 碌DMA TX Mode: 0x%08lX (STOP=0x%08lX)\r\n", finalMode, UDMA_MODE_STOP);

    } else {

        printf("M3: 碌DMA TX channel is disabled after transfer\r\n");

    }

   

    // 楠岃瘉鏂规硶5锛氭鏌ART3涓柇鐘舵��

    unsigned long uartIntStatus = UARTIntStatus(UART3_BASE, 0);

    printf("M3: UART3 Interrupt Status: 0x%08lX\r\n", uartIntStatus);

   

    // 楠岃瘉鏂规硶6锛氭鏌ヂ礑MA浼犺緭缁撴灉锛堜笉浣跨敤鐩存帴UART鍙戦�侊級

    printf("M3: 碌DMA transmission verification completed\r\n");

    printf("M3: All UART3 output is handled by 碌DMA only\r\n");

   

    // 楠岃瘉鏂规硶7锛氭鏌ヂ礑MA浼犺緭璁℃暟鍣�

    printf("M3: Checking 碌DMA transfer counters...\r\n");

    // 浣跨敤碌DMA搴撳嚱鏁拌幏鍙栫姸鎬侊紝閬垮厤鐩存帴瀵勫瓨鍣ㄨ闂�

    // 娉ㄦ剰锛歶DMAIsEnabled鍙兘鏈畾涔夛紝浣跨敤鏇夸唬鏂规硶

    printf("M3: 碌DMA Controller Status: Checking via control table\r\n");

   

    // 妫�鏌ART3 DMA鎺у埗瀵勫瓨鍣紙鍩轰簬瀵勫瓨鍣ㄨ〃0x048锛�

    unsigned long uartDmaCtl = HWREG(UART3_BASE + UART_O_DMACTL);

    printf("M3: UART3 DMA Control (0x048): 0x%08lX\r\n", uartDmaCtl);

    printf("M3:   TXDMAE (bit 1): %s\r\n", (uartDmaCtl & 0x02) ? "Enabled" : "Disabled");

    printf("M3:   RXDMAE (bit 0): %s\r\n", (uartDmaCtl & 0x01) ? "Enabled" : "Disabled");

   

    // 楠岃瘉鏂规硶8锛氭鏌ヂ礑MA閫氶亾鎺у埗琛�

    printf("M3: Checking 碌DMA channel control table...\r\n");

    // 浣跨敤鍏ㄥ眬鎺у埗琛ㄥ彉閲忥紝閬垮厤璋冪敤鍙兘鏈畾涔夌殑鍑芥暟

    unsigned long* controlTable = (unsigned long*)ucSimpleUDMAControlTable;

    unsigned long channelOffset = UDMA_CHANNEL_UART3TX * 4; // 姣忎釜閫氶亾4涓瓧

    unsigned long* channelControl = &controlTable[channelOffset];

   

    printf("M3: 碌DMA Channel %d Control Table:\r\n", UDMA_CHANNEL_UART3TX);

    printf("M3:   Control Word 0: 0x%08lX\r\n", channelControl[0]);

    printf("M3:   Control Word 1: 0x%08lX\r\n", channelControl[1]);

    printf("M3:   Control Word 2: 0x%08lX\r\n", channelControl[2]);

    printf("M3:   Control Word 3: 0x%08lX\r\n", channelControl[3]);

   

    // 楠岃瘉鏂规硶9锛氭鏌ヂ礑MA閫氶亾灞炴��

    printf("M3: Checking 碌DMA channel attributes...\r\n");

    // 娉ㄦ剰锛歶DMAChannelAttributeGet鍙兘鏈畾涔夛紝浣跨敤鏇夸唬鏂规硶

    printf("M3: Channel Attributes: Checking via control table\r\n");

    printf("M3:   Control table entries show channel configuration\r\n");

   

    printf("M3: 碌DMA TX channel enabled and requested\r\n");

   

    // 澧炲姞鏁版嵁鍖呰鏁�

    g_simpleUDMAUART.packetCount++;

   

    return true;

}

 

//*****************************************************************************

// 杞欢妫�娴婦MA浼犺緭鐨勪笓鐢ㄦ祴璇曞嚱鏁�

//*****************************************************************************

bool SimpleUDMA_TestTransmission(void)

{

    printf("M3: ===== STARTING DMA TRANSMISSION TEST =====\r\n");

   

    // 鍑嗗娴嬭瘯鏁版嵁

    uint8_t testData[] = {0x55, 0xAA, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC};

    uint16_t testLength = sizeof(testData);

   

    printf("M3: Test data: ");

    for(int i = 0; i < testLength; i++) {

        printf("%02X ", testData[i]);

    }

    printf("\r\n");

   

    // 璁板綍浼犺緭鍓嶇殑UART3鐘舵��

    unsigned long drBefore = HWREG(UART3_BASE + UART_O_DR);

    unsigned long frBefore = HWREG(UART3_BASE + UART_O_FR);

    unsigned long intBefore = UARTIntStatus(UART3_BASE, 0);

   

    printf("M3: Before DMA - DR:0x%08lX, FR:0x%08lX, Int:0x%08lX\r\n",

           drBefore, frBefore, intBefore);

   

    // 鎵цDMA浼犺緭

    bool result = SimpleUDMA_SendPacket(testData, testLength);

   

    // 璁板綍浼犺緭鍚庣殑UART3鐘舵��

    unsigned long drAfter = HWREG(UART3_BASE + UART_O_DR);

    unsigned long frAfter = HWREG(UART3_BASE + UART_O_FR);

    unsigned long intAfter = UARTIntStatus(UART3_BASE, 0);

   

    printf("M3: After DMA - DR:0x%08lX, FR:0x%08lX, Int:0x%08lX\r\n",

           drAfter, frAfter, intAfter);

   

    // 鍒嗘瀽缁撴灉

    bool dmaWorked = false;

    if (drAfter != drBefore) {

        printf("M3: 鉁� DR Register changed - DMA activity detected\r\n");

        dmaWorked = true;

    }

    if (frAfter != frBefore) {

        printf("M3: 鉁� FR Register changed - FIFO activity detected\r\n");

        dmaWorked = true;

    }

    if (intAfter != intBefore) {

        printf("M3: 鉁� Interrupt Status changed - UART activity detected\r\n");

        dmaWorked = true;

    }

   

    printf("M3: ===== DMA TEST RESULT: %s =====\r\n", dmaWorked ? "SUCCESS" : "FAILED");

   

    return dmaWorked;

}

 

//*****************************************************************************

// 鍩轰簬UART瀵勫瓨鍣ㄨ〃鐨凞MA浼犺緭妫�娴嬪嚱鏁�

//*****************************************************************************

bool SimpleUDMA_CheckRegisterBasedDMA(void)

{

    printf("M3: ===== REGISTER-BASED DMA DETECTION =====\r\n");

   

    // 1. 妫�鏌ART3 DMA鎺у埗瀵勫瓨鍣� (0x048)

    unsigned long uartDmaCtl = HWREG(UART3_BASE + UART_O_DMACTL);

    printf("M3: UART3 DMA Control (0x048): 0x%08lX\r\n", uartDmaCtl);

   

    bool txDmaEnabled = (uartDmaCtl & 0x02) ? true : false;  // TXDMAE (bit 1)

    bool rxDmaEnabled = (uartDmaCtl & 0x01) ? true : false;  // RXDMAE (bit 0)

   

    printf("M3:   TXDMAE (bit 1): %s\r\n", txDmaEnabled ? "Enabled" : "Disabled");

    printf("M3:   RXDMAE (bit 0): %s\r\n", rxDmaEnabled ? "Enabled" : "Disabled");

   

    // 2. 妫�鏌ART3鏁版嵁瀵勫瓨鍣� (0x000)

    unsigned long uartDr = HWREG(UART3_BASE + UART_O_DR);

    printf("M3: UART3 Data Register (0x000): 0x%08lX\r\n", uartDr);

   

    // 3. 妫�鏌ART3鏍囧織瀵勫瓨鍣� (0x018)

    unsigned long uartFr = HWREG(UART3_BASE + UART_O_FR);

    printf("M3: UART3 Flag Register (0x018): 0x%08lX\r\n", uartFr);

   

    bool txfe = (uartFr & UART_FR_TXFE) ? true : false;  // TX FIFO Empty

    bool txff = (uartFr & UART_FR_TXFF) ? true : false;  // TX FIFO Full

    bool rxfe = (uartFr & UART_FR_RXFE) ? true : false;  // RX FIFO Empty

    bool rxff = (uartFr & UART_FR_RXFF) ? true : false;  // RX FIFO Full

   

    printf("M3:   TXFE:%s, TXFF:%s, RXFE:%s, RXFF:%s\r\n",

           txfe ? "Yes" : "No", txff ? "Yes" : "No",

           rxfe ? "Yes" : "No", rxff ? "Yes" : "No");

   

    // 4. 妫�鏌ART3鎺у埗瀵勫瓨鍣� (0x030)

    unsigned long uartCtl = HWREG(UART3_BASE + UART_O_CTL);

    printf("M3: UART3 Control Register (0x030): 0x%08lX\r\n", uartCtl);

    bool uartEnabled = (uartCtl & 0x01) ? true : false;  // UARTEN (bit 0)

    printf("M3:   UARTEN (bit 0): %s\r\n", uartEnabled ? "Enabled" : "Disabled");

   

    // 5. 妫�鏌ART3涓柇鐘舵�佸瘎瀛樺櫒 (0x040)

    unsigned long uartMis = HWREG(UART3_BASE + UART_O_MIS);

    printf("M3: UART3 Masked Interrupt Status (0x040): 0x%08lX\r\n", uartMis);

   

    // 6. 鍒嗘瀽DMA鐘舵��

    printf("M3: ===== DMA STATUS ANALYSIS =====\r\n");

   

    bool dmaConfigured = txDmaEnabled && uartEnabled;

    printf("M3: DMA Configuration: %s\r\n", dmaConfigured ? "OK" : "ERROR");

   

    if (!txDmaEnabled) {

        printf("M3: 鉁� TX DMA not enabled in UARTDMACTL\r\n");

    }

    if (!uartEnabled) {

        printf("M3: 鉁� UART3 not enabled in UARTCTL\r\n");

    }

    if (txff) {

        printf("M3: 鈿� TX FIFO is FULL - may block DMA\r\n");

    }

    if (!txfe) {

        printf("M3: 鉁� TX FIFO has data - DMA may be working\r\n");

    }

   

    printf("M3: ===== REGISTER-BASED DMA RESULT: %s =====\r\n",

           dmaConfigured ? "CONFIGURED" : "MISCONFIGURED");

   

    return dmaConfigured;

}

 

//*****************************************************************************

// 鏁版嵁澶勭悊鍑芥暟瀹炵幇

//*****************************************************************************

 

//*****************************************************************************

// 澶勭悊鎺ユ敹鍒扮殑鏁版嵁锛堜繚鎸佷笌鐜版湁閫昏緫鍏煎锛�

//*****************************************************************************

void SimpleUDMA_ProcessReceivedData(uint8_t* buffer, uint16_t length)

{

    for (uint16_t i = 0; i < length; i++)

    {

        uint8_t byte = buffer[i];

       

        switch (g_simpleUDMAUART.currentPacket.state)

        {

            case PACKET_STATE_IDLE:

                // 绛夊緟甯уご

                if (byte == FRAME_HEADER_BYTE1)

                {

                    g_simpleUDMAUART.currentPacket.data[0] = byte;

                    g_simpleUDMAUART.currentPacket.length = 1;

                    g_simpleUDMAUART.currentPacket.state = PACKET_STATE_HEADER;

                }

                break;

               

            case PACKET_STATE_HEADER:

                // 妫�鏌ュ抚澶村畬鏁存��

                if (byte == FRAME_HEADER_BYTE2)

                {

                    g_simpleUDMAUART.currentPacket.data[1] = byte;

                    g_simpleUDMAUART.currentPacket.length = 2;

                    g_simpleUDMAUART.currentPacket.state = PACKET_STATE_DATA;

                }

                else

                {

                    // 甯уご閿欒锛岄噸鏂板紑濮�

                    SimpleUDMA_ResetPacketState();

                }

                break;

               

            case PACKET_STATE_DATA:

                // 鎺ユ敹鏁版嵁

                if (g_simpleUDMAUART.currentPacket.length < UDMA_MAX_PACKET_SIZE)

                {

                    g_simpleUDMAUART.currentPacket.data[g_simpleUDMAUART.currentPacket.length] = byte;

                    g_simpleUDMAUART.currentPacket.length++;

                   

                    // 妫�鏌ユ槸鍚︽帴鏀跺埌瀹屾暣鏁版嵁鍖�

                    if (g_simpleUDMAUART.currentPacket.length >= UDMA_MIN_PACKET_SIZE)

                    {

                        if (SimpleUDMA_ValidatePacket(g_simpleUDMAUART.currentPacket.data,

                                                     g_simpleUDMAUART.currentPacket.length))

                        {

                            g_simpleUDMAUART.currentPacket.state = PACKET_STATE_COMPLETE;

                            g_simpleUDMAUART.currentPacket.isComplete = true;

                            g_simpleUDMAUART.packetCount++;

                           

                            // 澶勭悊瀹屾暣鏁版嵁鍖�

                            SimpleUDMA_HandleCompletePacket(&g_simpleUDMAUART.currentPacket);

                           

                            // 閲嶇疆鐘舵��

                            SimpleUDMA_ResetPacketState();

                        }

                    }

                }

                else

                {

                    // 鏁版嵁鍖呰繃闀匡紝閿欒

                    g_simpleUDMAUART.errorCount++;

                    SimpleUDMA_ResetPacketState();

                }

                break;

               

            default:

                SimpleUDMA_ResetPacketState();

                break;

        }

    }

}

 

//*****************************************************************************

// 澶勭悊瀹屾暣鏁版嵁鍖咃紙淇濇寔涓庣幇鏈夊鐞嗛�昏緫鍏煎锛�

//*****************************************************************************

void SimpleUDMA_HandleCompletePacket(const SimplePacketInfo_t* packet)

{

    // 灏嗗瓧鑺傛暟缁勮浆鎹负16浣嶆暟缁勮繘琛屽弽搴忓垪鍖�

    uint16_t packet16[16];

    uint16_t wordCount = (packet->length + 1) / 2; // 鍚戜笂鍙栨暣

   

    for (uint16_t i = 0; i < wordCount; i++)

    {

        packet16[i] = (packet->data[i*2+1] << 8) | packet->data[i*2];

    }

   

    // 鍙嶅簭鍒楀寲鏁版嵁鍖�

    LevitationSimple_t receivedData;

    if (LevitationSimple_deserialize(packet16, wordCount, &receivedData))

    {

        // 鏍规嵁鏁版嵁绫诲瀷澶勭悊涓嶅悓鐨勬暟鎹寘锛堜繚鎸佷笌鐜版湁閫昏緫鐩稿悓锛�

        if (receivedData.type == 0 && receivedData.data_length >= 10)

        {

            // 浼犳劅鍣ㄦ暟鎹寘

            printf("M3: SENSOR: H[%d,%d,%d,%d] Z[%d,%d] B[%d,%d,%d,%d]\r\n",

                   (int16_t)receivedData.data_fields[0],  // posXH

                   (int16_t)receivedData.data_fields[1],  // posYH

                   (int16_t)receivedData.data_fields[2],  // VibrationH

                   (int16_t)receivedData.data_fields[8],  // AngleH

                   (int16_t)receivedData.data_fields[3],  // PosZ

                   (int16_t)receivedData.data_fields[4],  // Vibration

                   (int16_t)receivedData.data_fields[5],  // PosXB

                   (int16_t)receivedData.data_fields[6],  // PosYB

                   (int16_t)receivedData.data_fields[7],  // VibrationB

                   (int16_t)receivedData.data_fields[9]); // AngleB

        }

        else if (receivedData.type == 2 && receivedData.data_length >= 1)

        {

            // 搴旂瓟鍖�

            uint16_t responseResult = receivedData.data_fields[0];

            if (responseResult == 1)

            {

                printf("M3: RESPONSE: SUCCESS (OK)\r\n");

            }

            else

            {

                printf("M3: RESPONSE: FAILED (ERROR)\r\n");

            }

        }

        else if (receivedData.type == 3 && receivedData.data_length >= 1)

        {

            // 鍛戒护搴旂瓟鍖�

            uint16_t commandResult = receivedData.data_fields[0];

            switch (commandResult)

            {

                case 0: printf("M3: COMMAND: EXECUTION FAILED\r\n"); break;

                case 1: printf("M3: COMMAND: EXECUTION SUCCESS\r\n"); break;

                case 2: printf("M3: COMMAND: PARAMETER ERROR\r\n"); break;

                case 3: printf("M3: COMMAND: STATE ERROR\r\n"); break;

                case 4: printf("M3: COMMAND: TIMEOUT ERROR\r\n"); break;

                case 5: printf("M3: COMMAND: HARDWARE ERROR\r\n"); break;

                default: printf("M3: COMMAND: UNKNOWN RESULT (%d)\r\n", commandResult); break;

            }

        }

    }

    else

    {

        printf("M3: DESERIALIZE FAILED!\r\n");

        g_simpleUDMAUART.errorCount++;

    }

}

 

//*****************************************************************************

// 涓柇澶勭悊鍑芥暟瀹炵幇

//*****************************************************************************

 

//*****************************************************************************

// 碌DMA UART涓柇澶勭悊鍑芥暟

//*****************************************************************************

void SimpleUDMA_IntHandler(void)

{

    unsigned long ulStatus;

    unsigned long ulMode;

   

    // 娣诲姞璋冭瘯杈撳嚭纭涓柇澶勭悊鍑芥暟琚皟鐢�

    // 绮剧畝鏃ュ織锛氱Щ闄や腑鏂鐞嗘棩蹇�

   

    // 璇诲彇UART涓柇鐘舵�侊紙鍙傝�冨畼鏂筪emo锛�

    ulStatus = UARTIntStatus(UART3_BASE, 1);

   

    // 妫�鏌X FIFO鏄惁婊★紝濡傛灉婊″垯娓呯悊锛堥槻姝㈤樆濉烇級

    unsigned long uartFr = HWREG(UART3_BASE + UART_O_FR);

    if (uartFr & UART_FR_RXFF) {

        // 娓呯悊RX FIFO涓殑鎵�鏈夋暟鎹紙绮剧畝鏃ュ織锛�

        while (!(HWREG(UART3_BASE + UART_O_FR) & UART_FR_RXFE)) {

            volatile uint32_t dummy = HWREG(UART3_BASE + UART_O_DR);

            (void)dummy; // 閬垮厤鏈娇鐢ㄥ彉閲忚鍛�

        }

    }

   

    // 娓呴櫎UART涓柇鐘舵�侊紙鍙傝�冨畼鏂筪emo锛�

    UARTIntClear(UART3_BASE, ulStatus);

   

    // 妫�鏌ヤ富鎺у埗缁撴瀯锛堢紦鍐插尯A锛�

    ulMode = uDMAChannelModeGet(UDMA_CHANNEL_UART3RX | UDMA_PRI_SELECT);

    if (ulMode == UDMA_MODE_STOP)

    {

        // 缂撳啿鍖篈鎺ユ敹瀹屾垚锛屽鐞嗘暟鎹�

        SimpleUDMA_ProcessReceivedData(g_simpleUDMAUART.rxBufferA, sizeof(g_simpleUDMAUART.rxBufferA));

       

        // 閲嶆柊璁剧疆缂撳啿鍖篈鐨勪紶杈�

        uDMAChannelTransferSet(UDMA_CHANNEL_UART3RX | UDMA_PRI_SELECT,

                               UDMA_MODE_PINGPONG,

                               (void *)(UART3_BASE + UART_O_DR),

                               g_simpleUDMAUART.rxBufferA, sizeof(g_simpleUDMAUART.rxBufferA));

    }

   

    // 妫�鏌ュ鐢ㄦ帶鍒剁粨鏋勶紙缂撳啿鍖築锛�

    ulMode = uDMAChannelModeGet(UDMA_CHANNEL_UART3RX | UDMA_ALT_SELECT);

    if (ulMode == UDMA_MODE_STOP)

    {

        // 缂撳啿鍖築鎺ユ敹瀹屾垚锛屽鐞嗘暟鎹�

        SimpleUDMA_ProcessReceivedData(g_simpleUDMAUART.rxBufferB, sizeof(g_simpleUDMAUART.rxBufferB));

       

        // 閲嶆柊璁剧疆缂撳啿鍖築鐨勪紶杈�

        uDMAChannelTransferSet(UDMA_CHANNEL_UART3RX | UDMA_ALT_SELECT,

                               UDMA_MODE_PINGPONG,

                               (void *)(UART3_BASE + UART_O_DR),

                               g_simpleUDMAUART.rxBufferB, sizeof(g_simpleUDMAUART.rxBufferB));

    }

   

    // 妫�鏌X閫氶亾浼犺緭瀹屾垚锛堟敼杩涙娴嬮�昏緫锛�

    ulMode = uDMAChannelModeGet(UDMA_CHANNEL_UART3TX | UDMA_PRI_SELECT);

    if (ulMode == UDMA_MODE_STOP && g_simpleUDMAUART.packetCount > 0)

    {

        // TX浼犺緭瀹屾垚锛岄�氶亾宸插仠姝�

        printf("M3: TX transfer completed\r\n");

        // 绂佺敤閫氶亾浠ユ竻鐞嗙姸鎬�

        uDMAChannelDisable(UDMA_CHANNEL_UART3TX);

    }

}

 

//*****************************************************************************

// 碌DMA閿欒涓柇澶勭悊鍑芥暟

//*****************************************************************************

void SimpleUDMA_ErrorHandler(void)

{

    unsigned long ulStatus;

   

    // 鑾峰彇碌DMA閿欒鐘舵��

    // 娉ㄦ剰锛歶DMAErrorStatusGet鍙兘鏈畾涔夛紝浣跨敤鏇夸唬鏂规硶

    ulStatus = 0; // 鏆傛椂璁句负0锛岄伩鍏嶉摼鎺ラ敊璇�

   

    // 濡傛灉鏈夐敊璇紝娓呴櫎閿欒鐘舵�佸苟澧炲姞閿欒璁℃暟

    if (ulStatus)

    {

        // 娉ㄦ剰锛歶DMAErrorStatusClear鍙兘鏈畾涔夛紝璺宠繃娓呴櫎鎿嶄綔

        g_simpleUDMAUART.errorCount++;

        printf("M3: 碌DMA Error: 0x%08lX\r\n", ulStatus);

       

        // 璇︾粏閿欒鍒嗘瀽 - 鏍规嵁F28M35 碌DMA閫氶亾鍒嗛厤

        if (ulStatus & 0x00000001) {

            printf("M3: Error Detail: Channel 0 - Possible misconfiguration\r\n");

        }

        if (ulStatus & 0x00000002) {

            printf("M3: Error Detail: Channel 1 - Possible misconfiguration\r\n");

        }

        if (ulStatus & 0x00010000) {

            printf("M3: Error Detail: Channel 16 (UART3RX) - Possible misconfiguration\r\n");

        }

        if (ulStatus & 0x00020000) {

            printf("M3: Error Detail: Channel 17 (UART3TX) - Possible misconfiguration\r\n");

        }

       

        // 妫�鏌ART3 TX閫氶亾鐘舵��

        if (uDMAChannelIsEnabled(UDMA_CHANNEL_UART3TX)) {

            unsigned long ulMode = uDMAChannelModeGet(UDMA_CHANNEL_UART3TX | UDMA_PRI_SELECT);

            printf("M3: TX Channel Mode after error: 0x%08lX\r\n", ulMode);

        }

    }

}

 

//*****************************************************************************

// 鐘舵�佹煡璇㈠嚱鏁板疄鐜�

//*****************************************************************************

 

//*****************************************************************************

// 鑾峰彇鏁版嵁鍖呰鏁�

//*****************************************************************************

uint32_t SimpleUDMA_GetPacketCount(void)

{

    return g_simpleUDMAUART.packetCount;

}

 

//*****************************************************************************

// 鑾峰彇閿欒璁℃暟

//*****************************************************************************

uint32_t SimpleUDMA_GetErrorCount(void)

{

    return g_simpleUDMAUART.errorCount;

}

 

//*****************************************************************************

// 鎵撳嵃鐘舵�佷俊鎭�

//*****************************************************************************

void SimpleUDMA_PrintStatus(void)

{

    printf("M3: Simple 碌DMA UART Status:\r\n");

    printf("  DMA Enabled: %s\r\n", g_simpleUDMAUART.dmaEnabled ? "Yes" : "No");

    printf("  Packet Count: %lu\r\n", g_simpleUDMAUART.packetCount);

    printf("  Error Count: %lu\r\n", g_simpleUDMAUART.errorCount);

    // 娉ㄦ剰锛歶DMAChannelIsEnabled鍙兘鏈畾涔夛紝浣跨敤鏇夸唬鏂规硶

    printf("  TX Channel Status: Checking via control table\r\n");

    printf("  RX Channel Status: Checking via control table\r\n");

   

    // 妫�鏌ART3鐘舵��

    unsigned long uartStatus = UARTIntStatus(UART3_BASE, 0);

    printf("  UART3 Status: 0x%08lX\r\n", uartStatus);

   

    // 妫�鏌ART3鏄惁鍚敤

    unsigned long uartCtl = HWREG(UART3_BASE + UART_O_CTL);

    printf("  UART3 CTL: 0x%08lX (Enabled: %s)\r\n", uartCtl, (uartCtl & UART_CTL_UARTEN) ? "Yes" : "No");

   

    // 妫�鏌ART3 FIFO鐘舵��

    unsigned long uartFr = HWREG(UART3_BASE + UART_O_FR);

    printf("  UART3 FR: 0x%08lX (TXFE:%s, TXFF:%s, RXFE:%s, RXFF:%s)\r\n",

           uartFr,

           (uartFr & UART_FR_TXFE) ? "Yes" : "No",

           (uartFr & UART_FR_TXFF) ? "Yes" : "No",

           (uartFr & UART_FR_RXFE) ? "Yes" : "No",

           (uartFr & UART_FR_RXFF) ? "Yes" : "No");

}

 

//*****************************************************************************

// 绉佹湁鍑芥暟瀹炵幇

//*****************************************************************************

 

//*****************************************************************************

// 閲嶇疆鏁版嵁鍖呯姸鎬�

//*****************************************************************************

static void SimpleUDMA_ResetPacketState(void)

{

    g_simpleUDMAUART.currentPacket.length = 0;

    g_simpleUDMAUART.currentPacket.state = PACKET_STATE_IDLE;

    g_simpleUDMAUART.currentPacket.isComplete = false;

    memset(g_simpleUDMAUART.currentPacket.data, 0, sizeof(g_simpleUDMAUART.currentPacket.data));

}

 

//*****************************************************************************

// 楠岃瘉鏁版嵁鍖咃紙淇濇寔涓庣幇鏈夐獙璇侀�昏緫鍏煎锛�

//*****************************************************************************

static bool SimpleUDMA_ValidatePacket(const uint8_t* data, uint16_t length)

{

    // 鍩烘湰闀垮害妫�鏌�

    if (length < UDMA_MIN_PACKET_SIZE || length > UDMA_MAX_PACKET_SIZE)

    {

        return false;

    }

   

    // 甯уご妫�鏌�

    if (data[0] != FRAME_HEADER_BYTE1 || data[1] != FRAME_HEADER_BYTE2)

    {

        return false;

    }

   

    // 甯у熬妫�鏌ワ紙鏈�鍚庝袱涓瓧鑺傚簲璇ユ槸0x0A 0x0D锛�

    if (data[length-2] != 0x0A || data[length-1] != 0x0D)

    {

        return false;

    }

   

    return true;

}