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.

关于tm4c123gh6pmi uart fifo发送中断问题

请问下大家,我配置uart tx 深度4/8,tx模式为fifo,为什么put 10字节以后才会产生中断呢?我设置fifo 接收深度4/8就没问题,接收到8字节数据产生一次中断,各寄存器得值我也取回来看了对照数据手册没有问题,但是如果使用udma的时候tx中断出发正常,如果我将tx fifo深度设置为6/8 的时候要put14字节数据才会产生中断,请问这是为什呢

  • 我估计是你的计算方法除了问题,因为从误差来看,4/8,6/8,都是前一位数加上1*2就对了,你可以试试配置为1/8,7/8试试,分别是多少位就触发呢?
  • 我直接调用的API
    ROM_UARTFIFOLevelSet(UART1_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8);
    并没有手工操作寄存器的API上是这么定义的 跟datasheet描述一致
    //*****************************************************************************
    //
    // Values that can be passed to UARTFIFOLevelSet as the ui32TxLevel parameter
    // and returned by UARTFIFOLevelGet in the pui32TxLevel.
    //
    //*****************************************************************************
    #define UART_FIFO_TX1_8 0x00000000 // Transmit interrupt at 1/8 Full
    #define UART_FIFO_TX2_8 0x00000001 // Transmit interrupt at 1/4 Full
    #define UART_FIFO_TX4_8 0x00000002 // Transmit interrupt at 1/2 Full
    #define UART_FIFO_TX6_8 0x00000003 // Transmit interrupt at 3/4 Full
    #define UART_FIFO_TX7_8 0x00000004 // Transmit interrupt at 7/8 Full

    //*****************************************************************************
    //
    // Values that can be passed to UARTFIFOLevelSet as the ui32RxLevel parameter
    // and returned by UARTFIFOLevelGet in the pui32RxLevel.
    //
    //*****************************************************************************
    #define UART_FIFO_RX1_8 0x00000000 // Receive interrupt at 1/8 Full
    #define UART_FIFO_RX2_8 0x00000008 // Receive interrupt at 1/4 Full
    #define UART_FIFO_RX4_8 0x00000010 // Receive interrupt at 1/2 Full
    #define UART_FIFO_RX6_8 0x00000018 // Receive interrupt at 3/4 Full
    #define UART_FIFO_RX7_8 0x00000020 // Receive interrupt at 7/8 Full

    //*****************************************************************************
    API原型赋值也没有问题
    //*****************************************************************************
    //
    //! Sets the FIFO level at which interrupts are generated.
    //!
    //! \param ui32Base is the base address of the UART port.
    //! \param ui32TxLevel is the transmit FIFO interrupt level, specified as one
    //! of \b UART_FIFO_TX1_8, \b UART_FIFO_TX2_8, \b UART_FIFO_TX4_8,
    //! \b UART_FIFO_TX6_8, or \b UART_FIFO_TX7_8.
    //! \param ui32RxLevel is the receive FIFO interrupt level, specified as one of
    //! \b UART_FIFO_RX1_8, \b UART_FIFO_RX2_8, \b UART_FIFO_RX4_8,
    //! \b UART_FIFO_RX6_8, or \b UART_FIFO_RX7_8.
    //!
    //! This function configures the FIFO level at which transmit and receive
    //! interrupts are generated.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    UARTFIFOLevelSet(uint32_t ui32Base, uint32_t ui32TxLevel,
    uint32_t ui32RxLevel)
    {
    //
    // Check the arguments.
    //
    ASSERT(_UARTBaseValid(ui32Base));
    ASSERT((ui32TxLevel == UART_FIFO_TX1_8) ||
    (ui32TxLevel == UART_FIFO_TX2_8) ||
    (ui32TxLevel == UART_FIFO_TX4_8) ||
    (ui32TxLevel == UART_FIFO_TX6_8) ||
    (ui32TxLevel == UART_FIFO_TX7_8));
    ASSERT((ui32RxLevel == UART_FIFO_RX1_8) ||
    (ui32RxLevel == UART_FIFO_RX2_8) ||
    (ui32RxLevel == UART_FIFO_RX4_8) ||
    (ui32RxLevel == UART_FIFO_RX6_8) ||
    (ui32RxLevel == UART_FIFO_RX7_8));

    //
    // Set the FIFO interrupt levels.
    //
    HWREG(ui32Base + UART_O_IFLS) = ui32TxLevel | ui32RxLevel;
    }
    但是,实际的效果就是TX的FIFO产生中断深度与设定不匹配,,1/8我也试了,4字节触发
  • 我回去测试看看,把你的代码都贴上了,不应该呀。
  • ConfigPeripheralsHelper.c

    #include <stdbool.h>
    #include <stdint.h>

    #include "inc/hw_ints.h"
    #include "inc/hw_types.h"
    #include "inc/hw_memmap.h"

    #include "driverlib/rom.h"
    #include "driverlib/pwm.h"
    #include "driverlib/gpio.h"
    #include "driverlib/uart.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/pin_map.h"

    #include "utils/uartstdio.h"

    //*****************************************************************************
    //
    //! The system clock frequency
    //
    //*****************************************************************************
    uint32_t g_uint32SysClkFreq;
    //*****************************************************************************
    //
    //! The control table used by the uDMA controller.
    //! This table must be aligned to a 1024 byte boundary.
    //
    //*****************************************************************************
    uint8_t g_ui8ControlTable[1024] __attribute__ ((aligned(1024)));

    //*****************************************************************************
    //
    //! Configures the Peripherals for the standard usages on the TM4C123GH6PMI.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void ConfigurePeripherals()
    {

    //****************************************************
    //
    //! Initialize the FPU unit.
    //
    //****************************************************
    ROM_FPUEnable();
    ROM_FPULazyStackingEnable();

    //****************************************************
    //
    //! Clock Run from the PLL at 80 MHz.
    //
    //****************************************************
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);
    // Gets the processor clock rate.
    g_uint32SysClkFreq = ROM_SysCtlClockGet();

    //****************************************************
    //
    //! Enables the processor interrupt.
    //
    //****************************************************
    ROM_IntMasterEnable();

    //****************************************************
    //
    //! Enables the GPIO module.
    //
    //****************************************************
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

    //****************************************************
    //
    //! Enable the uDMA module.
    //
    //****************************************************
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
    ROM_IntEnable(INT_UDMAERR);
    ROM_uDMAEnable();
    // Point at the control table to use for channel control structures.
    ROM_uDMAControlBaseSet(g_ui8ControlTable);

    //****************************************************
    //
    //! Initialize the UART0 module.
    //!
    //! Note: UART0 are used for console.
    //
    //****************************************************
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
    ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
    ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    UARTStdioConfig(0, UART_BAUD_RATE, g_uint32SysClkFreq);

    //****************************************************
    //
    //! Initialize the UART1 module.
    //!
    //! Note: UART1 are used for main CPU message.
    //
    //****************************************************
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);
    ROM_GPIOPinConfigure(GPIO_PC4_U1RX);
    ROM_GPIOPinConfigure(GPIO_PC5_U1TX);
    ROM_GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_4 | GPIO_PIN_5);
    // Configure the UART communication parameters.
    ROM_UARTConfigSetExpClk(UART1_BASE, g_uint32SysClkFreq, UART_BAUD_RATE,
    UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
    UART_CONFIG_PAR_NONE);
    // Sets the FIFO level at which interrupts are generated.
    ROM_UARTFIFOLevelSet(UART1_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8);
    ROM_UARTTxIntModeSet(UART1_BASE, UART_TXINT_MODE_FIFO);
    ROM_UARTFIFOEnable(UART1_BASE);
    // Disable UART1 flow
    UARTFlowControlSet(UART1_BASE,UART_FLOWCONTROL_NONE);
    // Disables SIR (IrDA) mode on the specified UART.
    ROM_UARTDisableSIR(UART1_BASE);
    // Enable the UART1 for operation
    ROM_UARTEnable(UART1_BASE);

    }

    main.c

    #include <stdint.h>
    #include <stdbool.h>

    #include "driverlib/rom.h"
    #include "driverlib/fpu.h"
    #include "driverlib/pwm.h"
    #include "driverlib/gpio.h"
    #include "driverlib/udma.h"
    #include "driverlib/uart.h"
    #include "driverlib/debug.h"
    #include "driverlib/EEPROM.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/interrupt.h"

    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_uart.h"
    #include "inc/hw_udma.h"

    #include "utils/uartstdio.h"

    #include "Helper/ConfigPeripheralsHelper.h"

    //*****************************************************************************
    //
    // !The size of the UART transmit and receive buffers.
    //
    //*****************************************************************************
    #define UART_TXBUF_SIZE 8
    #define UART_RXBUF_SIZE 8
    //*****************************************************************************
    //
    //! The transmit and receive buffers used for the UART transfers.
    //
    //*****************************************************************************
    static uint8_t g_ui8TxBuf[UART_TXBUF_SIZE];
    static uint8_t g_ui8RxBufA[UART_RXBUF_SIZE];
    static uint8_t g_ui8RxBufB[UART_RXBUF_SIZE];


    //*****************************************************************************
    //
    //! The interrupt handler for uDMA errors.
    //
    //! \return None.
    //
    //*****************************************************************************
    void uDMAErrorHandler(void)
    {
    uint32_t ui32Status;

    //
    // Check for uDMA error bit
    //
    ui32Status = ROM_uDMAErrorStatusGet();

    //
    // If there is a uDMA error, then clear the error and increment
    // the error counter.
    //
    if(ui32Status)
    {
    ROM_uDMAErrorStatusClear();
    UARTprintf("uDMA error interrupt! \r\n");
    }
    }
    //*****************************************************************************
    //
    // The interrupt handler for uDMA interrupts from the memory channel. This
    // interrupt will increment a counter, and then restart another memory
    // transfer.
    //
    //*****************************************************************************
    void
    uDMAIntHandler(void)
    {
    uint32_t ui32Mode;
    UARTprintf("uDMAIntHandler! \r\n");

    }
    //*****************************************************************************
    //
    //! The UART1 interrupt handler.
    //
    //! \return None.
    //
    //*****************************************************************************
    void UART1IntHandler(void)
    {
    uint32_t ui32Status;
    uint32_t ui32Mode;

    //
    // Get the interrrupt status.
    //
    ui32Status = ROM_UARTIntStatus(UART1_BASE, true);

    //
    // Clear the asserted interrupts.
    //
    ROM_UARTIntClear(UART1_BASE, ui32Status);

    ui32Mode = ROM_uDMAChannelModeGet(UDMA_CHANNEL_UART1RX | UDMA_PRI_SELECT);

    if(ui32Mode == UDMA_MODE_STOP)
    {
    UARTprintf("RX_Buff_A \r\n");
    UARTprintf("RX data: 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x \r\n",
    g_ui8RxBufA[0],g_ui8RxBufA[1],g_ui8RxBufA[2],g_ui8RxBufA[3],
    g_ui8RxBufA[4],g_ui8RxBufA[5],g_ui8RxBufA[6],g_ui8RxBufA[7]);
    ROM_uDMAChannelTransferSet(UDMA_CHANNEL_UART1RX | UDMA_PRI_SELECT,
    UDMA_MODE_PINGPONG,
    (void *)(UART1_BASE + UART_O_DR),
    g_ui8RxBufA, sizeof(g_ui8RxBufA));

    }

    ui32Mode = ROM_uDMAChannelModeGet(UDMA_CHANNEL_UART1RX | UDMA_ALT_SELECT);

    //
    // If the alternate control structure indicates stop, that means the "B"
    // receive buffer is done. The uDMA controller should still be receiving
    // data into the "A" buffer.
    //
    if(ui32Mode == UDMA_MODE_STOP)
    {

    UARTprintf("RX_Buff_B \r\n");
    UARTprintf("RX data: 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x \r\n",
    g_ui8RxBufB[0],g_ui8RxBufB[1],g_ui8RxBufB[2],g_ui8RxBufB[3],
    g_ui8RxBufB[4],g_ui8RxBufB[5],g_ui8RxBufB[6],g_ui8RxBufB[7]);

    ROM_uDMAChannelTransferSet(UDMA_CHANNEL_UART1RX | UDMA_ALT_SELECT,
    UDMA_MODE_PINGPONG,
    (void *)(UART1_BASE + UART_O_DR),
    g_ui8RxBufB, sizeof(g_ui8RxBufB));
    }

    }
    //*****************************************************************************
    //
    //! Initializes the UART1 peripheral and sets up the TX and RX uDMA channels.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void InitUART1Transfer(void)
    {
    // Enable the uDMA interface for both TX and RX channels.
    ROM_UARTDMAEnable(UART1_BASE, UART_DMA_RX | UART_DMA_TX);

    // Enable the UART peripheral interrupts.
    ROM_IntEnable(INT_UART1);

    // Put the attributes in a known state for the uDMA UART1RX channel.
    ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_UART1RX, UDMA_ATTR_ALTSELECT |
    UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_USEBURST |
    UDMA_ATTR_REQMASK);
    //ROM_uDMAChannelAttributeEnable(UDMA_CHANNEL_UART1RX, UDMA_ATTR_ALTSELECT |
    // UDMA_ATTR_USEBURST);
    // Configure the control parameters for the primary control
    ROM_uDMAChannelControlSet(UDMA_CHANNEL_UART1RX | UDMA_PRI_SELECT,
    UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 |
    UDMA_ARB_4);
    // Configure the control parameters for the alternate control
    ROM_uDMAChannelControlSet(UDMA_CHANNEL_UART1RX | UDMA_ALT_SELECT,
    UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 |
    UDMA_ARB_4);
    // Set up the transfer parameters for the UART RX primary control structure.
    ROM_uDMAChannelTransferSet(UDMA_CHANNEL_UART1RX | UDMA_PRI_SELECT,
    UDMA_MODE_PINGPONG,
    (void *)(UART1_BASE + UART_O_DR),
    g_ui8RxBufA, sizeof(g_ui8RxBufA));
    // Set up the transfer parameters for the UART RX alternate control structure.
    ROM_uDMAChannelTransferSet(UDMA_CHANNEL_UART1RX | UDMA_ALT_SELECT,
    UDMA_MODE_PINGPONG,
    (void *)(UART1_BASE + UART_O_DR),
    g_ui8RxBufB, sizeof(g_ui8RxBufB));


    // Put the attributes in a known state for the uDMA UART1TX channel.
    ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_UART1TX, UDMA_ATTR_ALTSELECT |
    UDMA_ATTR_HIGH_PRIORITY |
    UDMA_ATTR_REQMASK);
    ROM_uDMAChannelAttributeEnable(UDMA_CHANNEL_UART1TX, UDMA_ATTR_USEBURST);
    // Configure the control parameters for the primary control
    ROM_uDMAChannelControlSet(UDMA_CHANNEL_UART1TX | UDMA_PRI_SELECT,
    UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE |
    UDMA_ARB_4);
    // Configure the control parameters for the alternate control
    ROM_uDMAChannelControlSet(UDMA_CHANNEL_UART1TX | UDMA_ALT_SELECT,
    UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 |
    UDMA_ARB_4);

    // Enables UART RX uDMA channel
    ROM_uDMAChannelEnable(UDMA_CHANNEL_UART1RX);

    }
    //*****************************************************************************
    //
    //! UART Send data on the uDMA
    //
    //! \param ui32ChannelStructIndex is the logical OR of the uDMA channel number
    //! \param ui32UARTBase is the UART base address
    //! \param pvSrcAddr is the source address for the transfer.
    //! \param ui32TransferSize is the number of data items to transfer.
    //
    //! \return None.
    //
    //*****************************************************************************
    void UARTSendData(uint32_t ui32ChannelStructIndex,
    uint32_t ui32UARTBase,
    void *pvSrcAddr, uint32_t ui32TransferSize)
    {
    // Set up the transfer parameters for the UART TX primary control structure.
    ROM_uDMAChannelTransferSet(ui32ChannelStructIndex | UDMA_PRI_SELECT,
    UDMA_MODE_BASIC, pvSrcAddr,
    (void *)(ui32UARTBase + UART_O_DR),
    ui32TransferSize);
    // Enables a uDMA channel
    ASSERT((ui32ChannelStructIndex & 0xffff) < 32);
    HWREG(UDMA_ENASET) = 1 << (ui32ChannelStructIndex & 0x1f);
    }

    //*****************************************************************************
    //
    //! Program entry
    //
    //*****************************************************************************
    int main(void)
    {
    //
    // Configure the Peripherals.
    //
    ConfigurePeripherals();


    //
    // Initialize the uDMA UART transfers.
    //
    InitUART1Transfer();

    g_ui8TxBuf[0] = 0xF1;
    g_ui8TxBuf[1] = 0xF2;
    g_ui8TxBuf[2] = 0xF3;
    g_ui8TxBuf[3] = 0xF4;
    g_ui8TxBuf[4] = 0xF5;
    g_ui8TxBuf[5] = 0xF6;
    g_ui8TxBuf[6] = 0xF7;
    g_ui8TxBuf[7] = 0xF8;
    UARTSendData(UDMA_CHANNEL_UART1TX, UART1_BASE,
    g_ui8TxBuf, sizeof(g_ui8TxBuf));

    /*
    ROM_UARTCharPutNonBlocking(UART1_BASE, 0xF1);
    ROM_UARTCharPutNonBlocking(UART1_BASE, 0xF1);
    ROM_UARTCharPutNonBlocking(UART1_BASE, 0xF1);
    ROM_UARTCharPutNonBlocking(UART1_BASE, 0xF1);
    ROM_UARTCharPutNonBlocking(UART1_BASE, 0xF1);
    ROM_UARTCharPutNonBlocking(UART1_BASE, 0xF1);
    ROM_UARTCharPutNonBlocking(UART1_BASE, 0xF1);
    ROM_UARTCharPutNonBlocking(UART1_BASE, 0xF1);
    */

    //
    // Loop forever. All the work is done in interrupt handlers.
    //
    while(1){}
    }
  • 好的,我明天回去测试看看,记得以前测试过,不应该有这个问题的。
  • 好的谢谢,再不开启dma的情况下直接put数据tx fifo是没有中断响应的!所有中断寄存器我都打印了没有变化很奇怪