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.

[参考译文] TM4C123GH6PGE:针对基于 TX 中断的通信的 UART 设置

Guru**** 2391415 points
Other Parts Discussed in Thread: TM4C123GH6PGE, EK-TM4C123GXL

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1027641/tm4c123gh6pge-uart-setup-for-tx-interrupt-based-comms

器件型号:TM4C123GH6PGE
Thread 中讨论的其他器件: EK-TM4C123GXL

您好、

我不熟悉 TM4C123GH6PGE 系列。 目前、我尝试了解如何进行由中断控制的 FIFO TX 传输。

设计:

我想创建一个发送函数、该函数填充 FIFO 并等待 FIFO 完成。 由于我使用的是 RTOS (Zephir)、所以我想在 FIFO 传输过程中执行一些其他操作。 因此、传输应通过 TX/FIFO 中断进行控制。

我想知道我需要如何设置 FIFO/INTR

我附加了一些"伪代码"。 此代码是从我的 Zephir UART API 实现中编译的、该 API 是一个处理 UART 异步和一些应用函数的中间层。


"setup"和"Send"功能是入口点。

static char * pB;
static int N;

static int uart_tiva_fifo_fill(const struct device *dev, const uint8_t *buf, int len)
{
	const struct uart_tiva_config * const cfg = DEV_CFG(dev);
	const uint32_t base = cfg->base;
	int n = 0;

	while (n < len) {
		if (false == UARTCharPutNonBlocking(base, buf[n])) {
			break;
		}
		n++;
	}

	return n;
}


static void uart_tiva_isr(const struct device *dev)
{
	const struct uart_tiva_config * const cfg = DEV_CFG(dev);
	struct uart_tiva_runtime *const dev_data = DEV_DATA(dev);
	const uint32_t base = cfg->base;

	const uint32_t UIstatus = UARTIntStatus(base, true);
	if (dev_data->cb) {
		dev_data->cb(dev, dev_data->cb_data);
	}
	UARTIntClear(base, UIstatus);
}

static void uart0_fifo_callback(const struct device *dev, void *user_data) {
	ARG_UNUSED(user_data);

	if (uart_irq_tx_ready(dev) && (N)) {
		const uint32_t am = uart_fifo_fill(dev, pB, N);
		N -= am;
		pB += am;
		if (0 == N) {
			uart_irq_tx_disable(dev);
			k_sem_give(txDone);
		}
	}

}

void send(char * txt, int len) {

	pB = txt;
	N = len;

	const int n = uart_tiva_fifo_fill(uart0, pB, N);
	N -= n;
	pB += n;

	if (am) {
		k_sem_take(txDone, K_FOREVER);
	}
}

static int uart_tiva_configure(const struct device *dev, const struct uart_config *cfg) {
	const struct uart_tiva_config * const devCfg = DEV_CFG(dev);
	const uint32_t base = devCfg->base;
	uint32_t tiCfg = 0;

	switch(cfg->parity) {
		case UART_CFG_PARITY_NONE:
			tiCfg = UART_CONFIG_PAR_NONE;
			break;
		case UART_CFG_PARITY_ODD:
			tiCfg = UART_CONFIG_PAR_ODD;
			break;
		case UART_CFG_PARITY_EVEN:
			tiCfg = UART_CONFIG_PAR_EVEN;
			break;
		case UART_CFG_PARITY_MARK:
		case UART_CFG_PARITY_SPACE:
		default:
			return -ENOTSUP;
			break;
	};

	switch(cfg->stop_bits) {
		case UART_CFG_STOP_BITS_1:
			tiCfg |= UART_CONFIG_STOP_ONE;
			break;
		case UART_CFG_STOP_BITS_2:
			tiCfg |= UART_CONFIG_STOP_TWO;
			break;
		case UART_CFG_STOP_BITS_0_5:
		case UART_CFG_STOP_BITS_1_5:
		default:
			return -ENOTSUP;
			break;
	};

	UART9BitDisable(base);
	switch(cfg->data_bits) {
		case UART_CFG_DATA_BITS_5:
			tiCfg |= UART_CONFIG_WLEN_5;
			break;
		case UART_CFG_DATA_BITS_6:
			tiCfg |= UART_CONFIG_WLEN_6;
			break;
		case UART_CFG_DATA_BITS_7:
			tiCfg |= UART_CONFIG_WLEN_7;
			break;
		case UART_CFG_DATA_BITS_8:
			tiCfg |= UART_CONFIG_WLEN_8;
			break;
		case UART_CFG_DATA_BITS_9:
			// ToDo: check how 9bit mode is right fully setup
			// tiCfg |= UART_CONFIG_WLEN_8;
			// UART9BitEnable(base);
			// break;
		default:
			return -ENOTSUP;
			break;
	};

	UARTEnable(base);
	UARTConfigSetExpClk(base, SysCtlClockGet(), cfg->baudrate, tiCfg);
	/* Clear all UART interrupts */
	UARTIntClear(base,
		UART_INT_OE | UART_INT_BE | UART_INT_PE |
		UART_INT_FE | UART_INT_RT | UART_INT_TX |
		UART_INT_RX | UART_INT_CTS);

	switch(cfg->flow_ctrl) {
		case UART_CFG_FLOW_CTRL_NONE:
			UARTFlowControlSet(base,UART_FLOWCONTROL_NONE);
			break;
		case UART_CFG_FLOW_CTRL_RTS_CTS:
			UARTFlowControlSet(base, UART_FLOWCONTROL_RX | UART_FLOWCONTROL_TX);
			break;
		case UART_CFG_FLOW_CTRL_DTR_DSR:
		default:
			return -ENOTSUP;
	};

	UARTEnable(base);

	return 0;
}

void setup(void) {
	const struct uart_tiva_config * const cfg = DEV_CFG(dev);
	const uint32_t base = cfg->base;

	pinmux_tiva_arrayCfg(cfg->pinctrl_list, cfg->pinctrl_list_size);

	// switch uart on
	sysctl_activatePeripheral(base);

	IRQ_CONNECT(DT_INST_IRQN(n),
	DT_INST_IRQ(n, priority),
		uart_tiva_isr,
		DEVICE_DT_INST_GET(n),
		0);
	UARTIntClear(base, UART_INT_RX | UART_INT_RT);
	irq_enable(DT_INST_IRQN(n));
	
	UARTTxIntModeSet(base, UART_TXINT_MODE_EOT);

	const struct uart_config uart_cfg = {
			.baudrate = cfg->baudrate,
			.parity = UART_CFG_PARITY_NONE,
			.stop_bits = UART_CFG_STOP_BITS_1,
			.data_bits = UART_CFG_DATA_BITS_8,
			.flow_ctrl = UART_CFG_FLOW_CTRL_NONE
		};

	uart_tiva_configure(dev, &uart_cfg);

}



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

    TX intr 也会启用(我忘记复制该代码)

    static void uart_tiva_irq_tx_enable(const struct device *dev)
    {
    	const struct uart_tiva_config * const cfg = DEV_CFG(dev);
    	const uint32_t base = cfg->base;
    
    	UARTIntEnable(base, UART_INT_TX);
    }
    
    void send(char * txt, int len) {
    
    	pB = txt;
    	N = len;
    
    	uart_tiva_irq_tx_enable(uart0);
    	const int n = uart_tiva_fifo_fill(uart0, pB, N);
    	N -= n;
    	pB += n;
    
    	if (am) {
    		k_sem_take(txDone, K_FOREVER);
    	}
    }
    


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

    您好!

     请参阅 C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c123gxl\UART_echo 中的 UART_echo 示例。 此示例设置 UART 接收中断。 如果要启用 TX FIFO 中断、则需要对其进行修改、以便:

     1.通过调用 UARTFIFOEnable()启用 FIFO

     2.通过调用 UARTFIFOLevelSet()来配置产生中断的 FIFO 级别。 例如 、UARTFIFOLevelSet (UART0_BASE、 UART_FIFO_TX4_8、 UART_FIFO_RX4_8)。 这将配置 TX FIFO 和 RX FIFO、以便在 FIFO 中有4个输出8数据时产生中断。 换言之、半满。  

     3.通过调用 MAP_UARTIntEnable (UART0_BASE、UART_INT_TX)启用 TX FIFO 中断。

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

    Thx 表示快速回复
    我知道来自(https://github.com/yuvadm/tiva-c/tree/master/boards/ek-tm4c123gxl)的 UART 演示。 Windows 功能对我不起作用、因为我在 Linux (Ubuntu)上。

    目前、我在通过"UARTCharPutNonBlocking"填充 UART TX (非 FIFO 模式)时遇到一些问题。

    我的代码会填充 UART、直至上述函数失败。 之后、我正在等待 TX 中断。 当 intr 触发时,我传输下一个数据块。 当我发送数据的最后一个字节时、通过设置一个信号量来解除发送函数的阻断。

    那么、我的问题是、如果没有 FIFO 使能(这会破坏我的 RX 代码)、该怎么办?
    我喜欢这种超级通用的情况、它为我提供了一个全双工 UART。 RX 的工作独立于(进入一个振铃缓冲器) TX。 TX 发送一个数据块。 要停止加载 MCU、我想使用 DMA 或 FIFO

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

    您好!

    [引用 userid="495727" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1027641/tm4c123gh6pge-uart-setup-for-tx-interrupt-based-comms/3798957 #3798957"]我的问题是,如果没有启用 FIFO (中断了 RX 代码),如何解决?

    如果不想启用 FIFO,则需要通过调用 UARTFIFODisable()来专门禁用它。 当通过调用 UARTEnable()启用 UART 时,它还将同时启用 TX 和 RX FIFO。 实际上,当您通过调用 UARTConfigSetExpClk()来设置 UART 时会自动调用 UARTEnable()。 因此,如果不想使用 FIFO,必须调用   UARTFIFODisable()来禁用它。 否则、TX 中断将仅在 达到 FIFO 深度阈值后产生。  

    [编辑]请参阅以下不带 FIFO 的 UART 中断模式的示例。  

    #include <stdint.h>
    #include <stdbool.h>
    #include <string.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/debug.h"
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    
    //*****************************************************************************
    //
    //! \addtogroup example_list
    //! <h1>UART Echo (uart_echo)</h1>
    //!
    //! This example application utilizes the UART to echo text.  The first UART
    //! (connected to the USB debug virtual serial port on the evaluation board)
    //! will be configured in 115,200 baud, 8-n-1 mode.  All characters received on
    //! the UART are transmitted back to the UART.
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, uint32_t ui32Line)
    {
    }
    #endif
    
    char *string = "This example sends data to UART0 in interrupt mode without using FIFO";
    int len = 0;
    
    //*****************************************************************************
    //
    // The UART interrupt handler.
    //
    //*****************************************************************************
    void
    UARTIntHandler(void)
    {
        uint32_t ui32Status;
    
        //
        // Get the interrupt status.
        //
        ui32Status = MAP_UARTIntStatus(UART0_BASE, true);
    
        //
        // Clear the asserted interrupts.
        //
        MAP_UARTIntClear(UART0_BASE, ui32Status);
    
        if (len >= 0)
        {
            //
            // Write the next character to the UART.
            //
            MAP_UARTCharPutNonBlocking(UART0_BASE, *string++);
            len--;
        }
    }
    
    
    //*****************************************************************************
    //
    // This example demonstrates how to send a string of data to the UART.
    //
    //*****************************************************************************
    int
    main(void)
    {
        //
        // Enable lazy stacking for interrupt handlers.  This allows floating-point
        // instructions to be used within interrupt handlers, but at the expense of
        // extra stack usage.
        //
        MAP_FPUEnable();
        MAP_FPULazyStackingEnable();
    
        //
        // Set the clocking to run directly from the crystal.
        //
        MAP_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                           SYSCTL_XTAL_16MHZ);
    
        //
        // Enable the GPIO port that is used for the on-board LED.
        //
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    
        //
        // Enable the GPIO pins for the LED (PF2).
        //
        MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);
    
        //
        // Enable the peripherals used by this example.
        //
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Enable processor interrupts.
        //
        MAP_IntMasterEnable();
    
        //
        // Set GPIO A0 and A1 as UART pins.
        //
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
        MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // Configure the UART for 115,200, 8-N-1 operation.
        //
        UARTConfigSetExpClk(UART0_BASE, MAP_SysCtlClockGet(), 115200,
                                (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                                 UART_CONFIG_PAR_NONE));
    
        //
        // Disable FIFO
        //
        UARTFIFODisable(UART0_BASE);
    
        //
        // Enable the UART interrupt.
        //
        MAP_IntEnable(INT_UART0);
        MAP_UARTIntEnable(UART0_BASE, UART_INT_TX);
    
        len = strlen(string);
        //
        // Prompt for text to be entered.
        //
        MAP_UARTCharPut(UART0_BASE, ' ');
    
    
        //
        // Loop forever echoing data through the UART.
        //
        while(1)
        {
        }
    }

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

    将 FIFO 分解可解决我的问题