ARM1138平台UART-FIFO收发程序设计

版权申诉
0 下载量 49 浏览量 更新于2024-11-07 收藏 102KB RAR 举报
资源摘要信息:"本资源包含了easy arm1138平台下针对UART-FIFO(通用异步收发传输器-先进先出)的收发程序。UART是一种广泛应用于嵌入式系统中的串行通信协议,而FIFO是一种常见的数据缓冲技术。本资源主要涉及这两个技术领域的结合应用,为开发者提供了一种高效、稳定的数据收发解决方案。" 知识分享: 1. UART(通用异步收发传输器)基础知识: UART是一种异步串行通信协议,广泛应用于微控制器和微处理器与各种外围设备之间的通信。其主要特点包括: - 异步通信:不需要共享时钟信号即可进行通信。 - 可编程波特率:允许设备之间以不同的速率进行通信。 - 起始位、数据位、校验位和停止位组成的数据帧格式。 - 支持全双工通信:数据可以同时进行发送和接收。 - 通常用于短距离通信,如调试接口、传感器接口等。 2. FIFO(先进先出)数据结构: FIFO是一种基于“先进先出”原则的数据缓冲结构。在UART通信中,FIFO被用来临时存储发送或接收的数据,以应对数据传输速率不匹配和数据量大时的问题。其主要特点包括: - 简单的存储和检索操作。 - 支持多级深度,可以存储多帧数据。 - 在中断驱动或DMA(直接内存访问)通信中尤为重要,可以减少处理器的负载。 3. ARM1138平台UART编程: ARM1138是ARM公司的一类处理器核心,用于嵌入式系统开发。在该平台上开发UART-FIFO程序,通常需要进行以下操作: - 配置UART模块的波特率、数据位、停止位和校验位。 - 初始化FIFO缓冲区,并设置适当的读写指针。 - 编写中断服务程序或DMA传输程序来处理数据的发送和接收。 - 实现缓冲区溢出和数据校验等异常情况的处理。 4. UART-FIFO收发程序的工作流程: 一个典型的UART-FIFO收发程序的工作流程大致如下: - 初始化UART模块和FIFO。 - 主循环中监测FIFO状态,判断是否需要读取数据或写入待发送的数据。 - 接收端接收到数据后,将数据放入FIFO接收缓冲区。 - 发送端从FIFO发送缓冲区取出数据并发送。 - 通过中断或DMA处理数据的发送与接收,减轻CPU的负担。 5. 在编程中需要注意的要点: - 确保数据传输过程中FIFO不发生溢出或下溢。 - 在设计中断服务程序时,应尽量减少中断服务时间,避免影响系统的实时性。 - 考虑使用DMA进行数据传输,以降低CPU的使用率。 - 要有错误处理机制,比如奇偶校验错误、帧错误和溢出错误等。 - 在多任务环境下,需要考虑任务间的同步和互斥问题。 6. 实际应用中的优化策略: - 动态调整FIFO的大小以适应不同的应用场景。 - 实现流量控制机制,如硬件流控RTS/CTS或软件流控XON/XOFF。 - 采用环形缓冲区管理FIFO,以便高效利用内存空间。 - 在设计中加入缓冲区水位线,用于触发数据读写操作。 综合以上内容,本资源为开发人员提供了一个面向easy arm1138平台的UART-FIFO收发程序的参考,涉及UART通信、FIFO缓冲管理、ARM平台编程以及实际编程中可能遇到的各类问题和解决策略。通过深入理解和掌握这些知识点,开发者可以更有效地实现嵌入式设备之间的高效、稳定通信。

注释以下每一行代码#include "bflb_mtimer.h" #include "bflb_uart.h" #include "bflb_clock.h" #include "board.h" struct bflb_device_s *uartx; void uart_isr(int irq, void *arg) { uint32_t intstatus = bflb_uart_get_intstatus(uartx); int ret; uint32_t baudrate; if (intstatus & UART_INTSTS_RX_AD5) { bflb_uart_int_clear(uartx, UART_INTCLR_RX_AD5); ret = bflb_uart_feature_control(uartx, UART_CMD_GET_AUTO_BAUD, UART_AUTO_BAUD_0X55); baudrate = bflb_clk_get_peripheral_clock(BFLB_DEVICE_TYPE_UART, uartx->idx) / (ret + 1); printf("Detected baudrate by 0x55 is %d\r\n", baudrate); } if (intstatus & UART_INTSTS_RX_ADS) { bflb_uart_int_clear(uartx, UART_INTCLR_RX_ADS); ret = bflb_uart_feature_control(uartx, UART_CMD_GET_AUTO_BAUD, UART_AUTO_BAUD_START); baudrate = bflb_clk_get_peripheral_clock(BFLB_DEVICE_TYPE_UART, uartx->idx) / (ret + 1); printf("Detected baudrate by startbit is %d\r\n", baudrate); } } int main(void) { board_init(); board_uartx_gpio_init(); uartx = bflb_device_get_by_name(DEFAULT_TEST_UART); struct bflb_uart_config_s cfg; cfg.baudrate = 2000000; cfg.data_bits = UART_DATA_BITS_8; cfg.stop_bits = UART_STOP_BITS_1; cfg.parity = UART_PARITY_NONE; cfg.flow_ctrl = 0; cfg.tx_fifo_threshold = 7; cfg.rx_fifo_threshold = 7; bflb_uart_init(uartx, &cfg); bflb_uart_feature_control(uartx, UART_CMD_SET_AUTO_BAUD, 1); bflb_uart_feature_control(uartx, UART_CMD_SET_ABR_ALLOWABLE_ERROR, 3); bflb_irq_attach(uartx->irq_num, uart_isr, NULL); bflb_irq_enable(uartx->irq_num); while (1) { } }

264 浏览量

static void pl011_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); unsigned int lcr_h, old_cr; unsigned long flags; unsigned int baud, quot, clkdiv; if (uap->vendor->oversampling) clkdiv = 8; else clkdiv = 16; baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / clkdiv); if (baud > port->uartclk/16) quot = DIV_ROUND_CLOSEST(port->uartclk * 8, baud); else quot = DIV_ROUND_CLOSEST(port->uartclk * 4, baud); switch (termios->c_cflag & CSIZE) { case CS5: lcr_h = UART01x_LCRH_WLEN_5; break; case CS6: lcr_h = UART01x_LCRH_WLEN_6; break; case CS7: lcr_h = UART01x_LCRH_WLEN_7; break; default: // CS8 lcr_h = UART01x_LCRH_WLEN_8; break; } if (termios->c_cflag & CSTOPB) lcr_h |= UART01x_LCRH_STP2; if (termios->c_cflag & PARENB) { lcr_h |= UART01x_LCRH_PEN; if (!(termios->c_cflag & PARODD)) lcr_h |= UART01x_LCRH_EPS; if (termios->c_cflag & CMSPAR) lcr_h |= UART011_LCRH_SPS; } if (uap->fifosize > 1) lcr_h |= UART01x_LCRH_FEN; spin_lock_irqsave(&port->lock, flags); uart_update_timeout(port, termios->c_cflag, baud); pl011_setup_status_masks(port, termios); if (UART_ENABLE_MS(port, termios->c_cflag)) pl011_enable_ms(port); old_cr = pl011_read(uap, REG_CR); pl011_write(0, uap, REG_CR); if (termios->c_cflag & CRTSCTS) { if (old_cr & UART011_CR_RTS) old_cr |= UART011_CR_RTSEN; old_cr |= UART011_CR_CTSEN; port->status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS; } else { old_cr &= ~(UART011_CR_CTSEN | UART011_CR_RTSEN); port->status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS); } if (uap->vendor->oversampling) { if (baud > port->uartclk / 16) old_cr |= ST_UART011_CR_OVSFACT; else old_cr &= ~ST_UART011_CR_OVSFACT; } if (uap->vendor->oversampling) { if ((baud >= 3000000) && (baud < 3250000) && (quot > 1)) quot -= 1; else if ((baud > 3250000) && (quot > 2)) quot -= 2; } pl011_write(quot & 0x3f, uap, REG_FBRD); pl011_write(quot >> 6, uap, REG_IBRD); pl011_write_lcr_h(uap, lcr_h); pl011_write(old_cr, uap, REG_CR); spin_unlock_irqrestore(&port->lock, flags); 详细分析这段代码中哪些部分是设置波特率,哪些是设置校验位,哪些是设置停止位,拆分出来

169 浏览量

static int sbsa_uart_probe(struct platform_device *pdev) { struct uart_amba_port *uap; struct resource r; int portnr, ret; int baudrate; / * Check the mandatory baud rate parameter in the DT node early * so that we can easily exit with the error. */ if (pdev->dev.of_node) { struct device_node *np = pdev->dev.of_node; ret = of_property_read_u32(np, "current-speed", &baudrate); if (ret) return ret; } else { baudrate = 115200; } portnr = pl011_find_free_port(); if (portnr < 0) return portnr; uap = devm_kzalloc(&pdev->dev, sizeof(struct uart_amba_port), GFP_KERNEL); if (!uap) return -ENOMEM; ret = platform_get_irq(pdev, 0); if (ret < 0) { if (ret != -EPROBE_DEFER) dev_err(&pdev->dev, "cannot obtain irq\n"); return ret; } uap->port.irq = ret; #ifdef CONFIG_ACPI_SPCR_TABLE if (qdf2400_e44_present) { dev_info(&pdev->dev, "working around QDF2400 SoC erratum 44\n"); uap->vendor = &vendor_qdt_qdf2400_e44; } else #endif uap->vendor = &vendor_sbsa; uap->reg_offset = uap->vendor->reg_offset; uap->fifosize = 32; uap->port.iotype = uap->vendor->access_32b ? UPIO_MEM32 : UPIO_MEM; uap->port.ops = &sbsa_uart_pops; uap->fixed_baud = baudrate; snprintf(uap->type, sizeof(uap->type), "SBSA"); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ret = pl011_setup_port(&pdev->dev, uap, r, portnr); if (ret) return ret; platform_set_drvdata(pdev, uap); return pl011_register_port(uap); }linux内核uart驱动在设备注册时,使用acpi表定义的波特率来初始化串口,请根据我的要求和上述代码,在代码中添加这一功能

148 浏览量