axi_uartlite测试
·
参考
AXI UART_LITE linux测试
AXI UART16550测试
axi_uartlite
BD

PS 直接操作寄存器
#include "xparameters.h"
#include "xil_printf.h"
#include "sleep.h"
#include <stdint.h>
// 定义AXI UART Lite基地址(从xparameters.h获取)
#define UART_BASE_ADDR XPAR_AXI_UARTLITE_0_BASEADDR
// 寄存器地址(基地址 + 偏移)
#define UART_RX_FIFO (*(volatile uint32_t *)(UART_BASE_ADDR + 0x00)) // 接收数据寄存器
#define UART_TX_FIFO (*(volatile uint32_t *)(UART_BASE_ADDR + 0x04)) // 发送数据寄存器
#define UART_STATUS (*(volatile uint32_t *)(UART_BASE_ADDR + 0x08)) // 状态寄存器
#define UART_CONTROL (*(volatile uint32_t *)(UART_BASE_ADDR + 0x0C)) // 控制寄存器
// 状态寄存器位定义
#define RX_VALID (1 << 0) // 接收FIFO有数据
#define TX_FULL (1 << 1) // 发送FIFO满
// 控制寄存器位定义
#define RX_RESET (1 << 0) // 复位接收FIFO
#define TX_RESET (1 << 1) // 复位发送FIFO
// 初始化UART(复位FIFO)
void UART_Init() {
// 复位接收和发送FIFO(写1生效,自动清零)
UART_CONTROL = RX_RESET | TX_RESET;
// 短暂延时确保复位完成
usleep(100);
}
// 发送一个字节
void UART_SendByte(uint8_t data) {
// 等待发送FIFO非满
while (UART_STATUS & TX_FULL);
// 写入发送FIFO
UART_TX_FIFO = data;
}
// 接收一个字节(返回1表示成功,0表示无数据)
uint8_t UART_RecvByte(uint8_t *data) {
// 检查接收FIFO是否有数据
if (UART_STATUS & RX_VALID) {
*data = (uint8_t)(UART_RX_FIFO & 0xFF); // 只取低8位
return 1;
}
return 0;
}
int main() {
uint8_t recv_data;
UART_Init();
xil_printf("UART Direct Register Test (Echo Mode)\n\r");
while (1) {
// 尝试接收数据
if (UART_RecvByte(&recv_data)) {
// 收到数据后回传
UART_SendByte(recv_data);
}
// 短暂延时,降低CPU占用
usleep(1000);
}
return 0;
}
PS 用库函数
#include "xparameters.h"
#include "xuartlite.h"
#include "xil_printf.h"
#include "sleep.h"
#define UART_DEVICE_ID XPAR_AXI_UARTLITE_0_DEVICE_ID
#define MAX_RECV_LEN 16
XUartLite UartInstance;
int main() {
int status;
u8 recv_buf[MAX_RECV_LEN];
u32 recv_len;
xil_printf("UART Library API Echo Example\r\n");
// 初始化 UARTLite
status = XUartLite_Initialize(&UartInstance, UART_DEVICE_ID);
if (status != XST_SUCCESS) {
xil_printf("UART Init Failed!\r\n");
return -1;
}
XUartLite_ResetFifos(&UartInstance);
while (1) {
// 发送固定测试字节
XUartLite_SendByte(UartInstance.RegBaseAddress, 0x55);
// 批量接收
recv_len = XUartLite_Recv(&UartInstance, recv_buf, MAX_RECV_LEN);
if (recv_len > 0) {
// 回显收到的全部内容
for (u32 i = 0; i < recv_len; i++) {
XUartLite_SendByte(UartInstance.RegBaseAddress, recv_buf[i]);
}
}
usleep(1000);
}
return 0;
}
PS 库函数 LookupConfig + CfgInitialize
#include "xparameters.h"
#include "xuartlite.h"
#include "xil_printf.h"
#include "sleep.h"
#define UART_DEVICE_ID XPAR_AXI_UARTLITE_0_DEVICE_ID
#define MAX_RECV_LEN 16
XUartLite UartInstance;
int main() {
int status;
XUartLite_Config *Config;
u8 recv_buf[MAX_RECV_LEN];
u32 recv_len;
xil_printf("UART Init using LookupConfig + CfgInitialize\r\n");
// 🔍 手动查找 UART 配置结构体
Config = XUartLite_LookupConfig(UART_DEVICE_ID);
if (Config == NULL) {
xil_printf("UART LookupConfig failed!\r\n");
return -1;
}
// ⚙️ 手动初始化实例(相当于 Initialize)
status = XUartLite_CfgInitialize(&UartInstance, Config, Config->RegBaseAddr);
if (status != XST_SUCCESS) {
xil_printf("UART CfgInitialize failed!\r\n");
return -1;
}
// 清空 FIFO
XUartLite_ResetFifos(&UartInstance);
while (1) {
// 发送固定测试字节
XUartLite_SendByte(UartInstance.RegBaseAddress, 0x55);
// 批量接收
recv_len = XUartLite_Recv(&UartInstance, recv_buf, MAX_RECV_LEN);
if (recv_len > 0) {
for (u32 i = 0; i < recv_len; i++) {
XUartLite_SendByte(UartInstance.RegBaseAddress, recv_buf[i]);
}
}
usleep(1000);
}
return 0;
}
axi_uart16550
BD


PS 直接操作寄存器
#include "xparameters.h"
#include "xil_printf.h"
#include "xil_io.h" // 用于 Xil_In32 / Xil_Out32
/**************************** 配置 ******************************/
#define UART_BASEADDR XPAR_UARTNS550_0_BASEADDR
#define UART_CLK_FREQ XPAR_PS7_UART_0_UART_CLK_FREQ_HZ
#define UART_BAUD_RATE 115200
/**************************** UART 寄存器偏移 ******************************/
// AXI UART 16550 寄存器偏移
#define UART_REG_RBR 0x00 // 接收缓冲寄存器 (读)
#define UART_REG_THR 0x00 // 发送保持寄存器 (写)
#define UART_REG_IER 0x04 // 中断使能寄存器
#define UART_REG_IIR 0x08 // 中断识别寄存器 (只读)
#define UART_REG_FCR 0x08 // FIFO 控制寄存器 (写)
#define UART_REG_LCR 0x0C // 线路控制寄存器
#define UART_REG_MCR 0x10 // 调制控制寄存器
#define UART_REG_LSR 0x14 // 线路状态寄存器
#define UART_REG_MSR 0x18 // 调制状态寄存器
#define UART_REG_SCR 0x1C // 用户自定义寄存器
#define UART_REG_DLL 0x00 // 除数锁存低字节 (DLAB=1)
#define UART_REG_DLM 0x04 // 除数锁存高字节 (DLAB=1)
/**************************** 宏定义 ******************************/
// LSR 寄存器标志位
#define UART_LSR_DR 0x01 // 数据就绪
#define UART_LSR_THRE 0x20 // 发送保持寄存器空
/***************** 寄存器操作辅助宏 ******************/
#define UART_READ(reg) Xil_In8(UART_BASEADDR + (reg))
#define UART_WRITE(reg,val) Xil_Out8(UART_BASEADDR + (reg), (val))
/***************** 波特率计算 ******************/
static void uart_set_baud(u32 clk, u32 baud)
{
u16 divisor;
// 1️⃣ 使能 DLAB 位,才能访问 DLL/DLM
u8 lcr = UART_READ(UART_REG_LCR);
UART_WRITE(UART_REG_LCR, lcr | 0x80); // 设置 DLAB=1
// 2️⃣ 计算除数: divisor = UART_CLK / (16 * baud)
divisor = (u16)(clk / (16 * baud));
UART_WRITE(UART_REG_DLL, divisor & 0xFF); // 低字节
UART_WRITE(UART_REG_DLM, (divisor >> 8) & 0xFF);// 高字节
// 3️⃣ 清除 DLAB 位,设置数据格式 8N1
UART_WRITE(UART_REG_LCR, 0x03); // 8 数据位,无校验,1 停止位
}
/***************** 发送单字节 ******************/
static void uart_send_byte(u8 c)
{
// 等待发送寄存器空
while (!(UART_READ(UART_REG_LSR) & UART_LSR_THRE));
UART_WRITE(UART_REG_THR, c);
}
/***************** 接收单字节 ******************/
static u8 uart_recv_byte(void)
{
// 等待接收寄存器有数据
while (!(UART_READ(UART_REG_LSR) & UART_LSR_DR));
return UART_READ(UART_REG_RBR);
}
/***************** 发送字符串 ******************/
static void uart_send_str(const char* str)
{
while (*str) {
uart_send_byte(*str++);
}
}
/***************** 主函数 ******************/
int main(void)
{
u8 c;
// 1️⃣ 设置波特率 + 8N1 数据格式
uart_set_baud(UART_CLK_FREQ, UART_BAUD_RATE);
xil_printf("UART initialized at %d bps using pure registers\r\n", UART_BAUD_RATE);
// 2️⃣ 发送 Hello World
uart_send_str("Hello World\r\n");
xil_printf("Entering echo loop...\r\n");
// 3️⃣ 回环逻辑: 收到啥就发啥
while (1) {
c = uart_recv_byte();
uart_send_byte(c);
}
return 0; // 永远不会到达
}
PS 库函数
#include "xparameters.h"
#include "xuartns550.h"
#include "xil_printf.h"
/**************************** 配置 ******************************/
#define UART_DEVICE_ID XPAR_UARTNS550_0_DEVICE_ID
#define UART_BASEADDR XPAR_UARTNS550_0_BASEADDR
#define UART_CLK_FREQ XPAR_PS7_UART_0_UART_CLK_FREQ_HZ // 注意 _HZ 结尾
#define UART_BAUD_RATE 115200
/**************************** 全局变量 **************************/
XUartNs550 UartNs550; // UART 实例
/***************** 函数原型 ******************/
int UartNs550_HelloWorldAndEcho(u16 DeviceId);
/***************** 主函数 ******************/
int main(void)
{
int Status;
Status = UartNs550_HelloWorldAndEcho(UART_DEVICE_ID);
if (Status == XST_FAILURE) {
xil_printf("UART Example Failed\r\n");
return XST_FAILURE;
}
xil_printf("UART Example Running\r\n");
return XST_SUCCESS;
}
/***************** 示例函数 ******************/
int UartNs550_HelloWorldAndEcho(u16 DeviceId)
{
int Status;
u8 c;
// 1️⃣ 初始化 UART
Status = XUartNs550_Initialize(&UartNs550, DeviceId);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
// 2️⃣ 设置波特率
XUartNs550_SetBaud(UART_BASEADDR, UART_CLK_FREQ, UART_BAUD_RATE);
xil_printf("UART initialized at %d bps\r\n", UART_BAUD_RATE);
// 3️⃣ 发送 Hello World
char HelloWorld[] = "Hello World\r\n";
int SentCount = 0;
while (SentCount < sizeof(HelloWorld) - 1) {
SentCount += XUartNs550_Send(&UartNs550,
(u8*)&HelloWorld[SentCount],
1);
}
xil_printf("Entering echo loop...\r\n");
// 4️⃣ 接收并回发逻辑
while (1) {
if (XUartNs550_IsReceiveData(UART_BASEADDR)) {
XUartNs550_Recv(&UartNs550, &c, 1);
XUartNs550_Send(&UartNs550, &c, 1);
}
}
return XST_SUCCESS; // 永远不会到达
}
PS 库函数+中断
XUartNs550 是 Xilinx 提供的 “NS16550 兼容 UART” 的软件驱动(BSP 层), 专门用来驱动 AXI UART16550 这个 IP。
这里axi_uart16550_0的中断号是62
#define XPAR_UARTNS550_0_DEVICE_ID 0U
#define XPAR_UARTNS550_0_BASEADDR 0x42C00000U
#define XPAR_UARTNS550_0_HIGHADDR 0x42C0FFFFU
/* Definitions for Fabric interrupts connected to ps7_scugic_0 */
#define XPAR_FABRIC_AXI_UART16550_0_IP2INTC_IRPT_INTR 62U
#include "xparameters.h"
#include "xuartns550.h"
#include "xil_printf.h"
#include "xil_exception.h"
#include "xscugic.h"
/**************************** 配置 ****************************/
#define UART_DEVICE_ID XPAR_UARTNS550_0_DEVICE_ID
#define UART_BASEADDR XPAR_UARTNS550_0_BASEADDR
#define UART_CLK_FREQ XPAR_PS7_UART_0_UART_CLK_FREQ_HZ
#define UART_BAUD_RATE 115200
#define INTC_DEVICE_ID XPAR_SCUGIC_0_DEVICE_ID
#define UART_INT_IRQ_ID XPAR_FABRIC_AXI_UART16550_0_IP2INTC_IRPT_INTR
/**************************** 全局变量 ****************************/
XUartNs550 UartNs550;
XScuGic Intc;
u8 RxChar;
volatile int RxFlag = 0;
/**************************** UART 中断回调 ****************************/
void UartNs550Handler(void *CallBackRef,
unsigned long Event,
unsigned int EventData)
{
XUartNs550 *UartInstPtr = (XUartNs550 *)CallBackRef;
switch (Event) {
case XUN_EVENT_RECV_DATA:
XUartNs550_Recv(UartInstPtr, &RxChar, 1);
RxFlag = 1;
break;
case XUN_EVENT_SENT_DATA:
/* 发送完成(EventData 是发送的字节数) */
break;
default:
break;
}
}
/**************************** 中断系统初始化 ****************************/
int SetupInterruptSystem(XScuGic *IntcInstPtr,
XUartNs550 *UartInstPtr)
{
int Status;
XScuGic_Config *IntcConfig;
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (!IntcConfig) return XST_FAILURE;
Status = XScuGic_CfgInitialize(
IntcInstPtr,
IntcConfig,
IntcConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) return XST_FAILURE;
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(
XIL_EXCEPTION_ID_IRQ_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
IntcInstPtr);
Status = XScuGic_Connect(
IntcInstPtr,
UART_INT_IRQ_ID,
(Xil_InterruptHandler)XUartNs550_InterruptHandler,
(void *)UartInstPtr);
if (Status != XST_SUCCESS) return XST_FAILURE;
XScuGic_Enable(IntcInstPtr, UART_INT_IRQ_ID);
Xil_ExceptionEnable();
/* 注册 UART 回调 */
XUartNs550_SetHandler(
UartInstPtr,
UartNs550Handler,
(void *)UartInstPtr);
/* 使能 RX / TX 中断(直接写 IER) */
XUartNs550_WriteReg(
UART_BASEADDR,
XUN_IER_OFFSET,
XUN_IER_RX_DATA | XUN_IER_TX_EMPTY);
XUartNs550_EnableIntr(UART_BASEADDR);
return XST_SUCCESS;
}
/**************************** 主函数 ****************************/
int main(void)
{
int Status;
Status = XUartNs550_Initialize(&UartNs550, UART_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("UART init failed\r\n");
return XST_FAILURE;
}
XUartNs550_SetBaud(
UART_BASEADDR,
UART_CLK_FREQ,
UART_BAUD_RATE);
Status = SetupInterruptSystem(&Intc, &UartNs550);
if (Status != XST_SUCCESS) {
xil_printf("Interrupt setup failed\r\n");
return XST_FAILURE;
}
xil_printf("AXI UART16550 interrupt RX/TX ready\r\n");
/* 主循环:完全不轮询 UART */
while (1) {
if (RxFlag) {
XUartNs550_Send(&UartNs550, &RxChar, 1); // 回显
RxFlag = 0;
}
}
}
更多推荐


所有评论(0)