3 AXI-UART

前言

  • 本日记尝试去使用ZCU106开发板PL端的串口资源,使用过ZCU106开发板的都知道,板子上只提供了一个串口接口和一个JTAG接口,但是手册上说串口接口支持四个串口模式,因此这次做个尝试,结果是成功的。又由于是个尝试,没有使用自己写的UART, 为了快速验证使用AXI UART IP,毕竟UART串口的的RTL实现不是什么困难的事情。

查阅手册

  • ug1244手册中(p67)显示zcu106 开发板提供四个串口, 其中UART2使用的是PL端的资源
    -在这里插入图片描述
  • 连接PL的引脚
    - 在这里插入图片描述

系统功能

  • 使用PL 端串口将收到的数据发送回去实现回环
    在这里插入图片描述

实验结果

  • PS 端串口打印结果
    在这里插入图片描述

  • PL 端串口打印结果
    在这里插入图片描述

BD设计

在这里插入图片描述

AXI UART LITE 中断(PL 对 PS中断)

在这里插入图片描述

IRQ NAMEIRQ NumberBitsRequired TypeDescription
PL_PS_Group0121:1287,8rising edge/high levelPL to PS interrupt signals 0 to 7.(3)
PL_PS_Group1136:1438rising edge/high levelPL to PS interrupt signals 8 to 15.(3)
  • ZCU106开发版对应的SOC支持两组PL to PS中断(共16个中断)
    • group0: 中断号为121–128,8个中断
    • group1: 中断号为136–143,8个中断

如何使用

  • 如果使能了IRQ0:第一组PL to PS中断
    • PL端对PS端产生多个中断,默认从ID 121开始分配
    • 第一个中断的ID:121
    • 第一个中断的ID:122
    • …累加但第一组最大ID不超过128
  • 记录使用过一个中断的过程

引脚约束

set_property PACKAGE_PIN AH17 [get_ports {uart_rxd}]
set_property PACKAGE_PIN AL17 [get_ports {uart_txd}]

set_property IOSTANDARD LVCMOS33 [get_ports {uart_rxd}]
set_property IOSTANDARD LVCMOS33 [get_ports {uart_txd}]

set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]

SDK设计

在这里插入图片描述

头文件

#include "xparameters.h"
#include "xil_printf.h"
#include "xil_exception.h"
#include "xscugic.h"
#include "xuartlite_l.h"
#include "xuartlite.h"

#define UARTLITE_DEVICE_ID XPAR_AXI_UARTLITE_0_DEVICE_ID    // UART LITE IP 的设备ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID         // 中断设备ID
#define UARTLITE_INT_IRQ_ID XPAR_FABRIC_UARTLITE_0_VEC_ID   // UART LITE IP中断ID,其实如果使能了IRQ0,第一个中断ID都是121

#define printf xil_printf

#define TEST_BUFFER_SIZE 100

XUartLite UartLite;
XScuGic Intc;
u8 RecvBuffer[TEST_BUFFER_SIZE];
u8 SendBuffer[TEST_BUFFER_SIZE];

int InitIntr(XScuGic *instancePtr, u16 deviceId, XUartLite *UartLitePtr, u16 UartLiteIntrId);
int InitUartLite(XUartLite *instancePtr, u16 deviceId);
void UartLiteRecvHandler(void *CallBackRef, unsigned int EventData);
void UartLiteSendHandler(void *CallBackRef, unsigned int EventData);

int main()
{
    int status;

    status = InitUartLite(&UartLite, UARTLITE_DEVICE_ID);   // 初始化AXI USRT LITE
    if (status != XST_SUCCESS) {
        printf("UART Lite initialization failed\r\n");
        return XST_FAILURE;
    }
    printf("UART Lite initialization passed\r\n");
    status = InitIntr(&Intc, INTC_DEVICE_ID, &UartLite, UARTLITE_INT_IRQ_ID);   // 初始化Interrupt
    if (status != XST_SUCCESS) {
        printf("Interrupt initialization failed\r\n");
        return XST_FAILURE;
    }
    printf("Interrupt initialization passed\r\n");

    XUartLite_Recv(&UartLite, RecvBuffer, TEST_BUFFER_SIZE);  // 挂起等待串口接收数据,如果上位机发送数据会触发接收中断执行中断处理函数
    while (1);

    return XST_SUCCESS;
}

初始化AXI-UART

int InitUartLite(XUartLite *instancePtr, u16 deviceId)
{
    int Status;
    Status = XUartLite_Initialize(instancePtr, deviceId); // 官方将lookconfig 和 cfginitial函数封装成了这个函数,使用传统的初始化方法也是可行的
    if (Status != XST_SUCCESS)
    {
        return XST_FAILURE;
    }

    XUartLite_ResetFifos(instancePtr);  // 重置串口FIFO

    XUartLite_SetSendHandler(instancePtr, UartLiteSendHandler, instancePtr);  // 串口发送回调
    XUartLite_SetRecvHandler(instancePtr, UartLiteRecvHandler, instancePtr);  // 串口接收回调
    return XST_SUCCESS;
}
发送回调函数
void UartLiteSendHandler(void *CallBackRef, unsigned int EventData)
{
    XUartLite *UartLitePtr = (XUartLite *)CallBackRef;
    UartLitePtr->Stats.TransmitInterrupts++;   // 发送中中断计数器
}


接受回调函数
void UartLiteRecvHandler(void *CallBackRef, unsigned int EventData)
{
    XUartLite *UartLitePtr = (XUartLite *)CallBackRef;

    int ReceivedCount = EventData;   // 接收的字节数
    printf("ReceivedCount: %d\r\n", ReceivedCount); // 添加调试信息
    for (int i = 0; i < ReceivedCount; i++)
        SendBuffer[i] = RecvBuffer[i];

    XUartLite_Send(UartLitePtr, SendBuffer, ReceivedCount);    
    XUartLite_Recv(UartLitePtr, RecvBuffer, TEST_BUFFER_SIZE);
    UartLitePtr->Stats.ReceiveInterrupts++;
    
}

初始化中断

  • 配置初始化
  • 建立终端函数
  • 配置异常
int InitIntr(XScuGic *instancePtr, u16 deviceId, XUartLite *UartLitePtr, u16 UartLiteIntrId)
{
    int status;
    XScuGic_Config *cfgPtr;

    cfgPtr = XScuGic_LookupConfig(deviceId);
    if (cfgPtr == NULL)
    {
        return XST_FAILURE;
    }

    status = XScuGic_CfgInitialize(instancePtr, cfgPtr, cfgPtr->CpuBaseAddress);
    if (status != XST_SUCCESS)
    {
        return XST_FAILURE;
    }
    
    XScuGic_SetPriorityTriggerType(instancePtr, UartLiteIntrId, 0xA0, 0x3);
    status = XScuGic_Connect(instancePtr, UartLiteIntrId, (Xil_ExceptionHandler)XUartLite_InterruptHandler, (void *)UartLitePtr);
    if (status != XST_SUCCESS)
    {
        return XST_FAILURE;
    }

    XUartLite_EnableInterrupt(UartLitePtr);      /* enable uart interrupt*/
    XScuGic_Enable(instancePtr, UartLiteIntrId); /* enable gic  interrupt*/

    Xil_ExceptionInit();
    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, instancePtr);
    Xil_ExceptionEnable();

    return XST_SUCCESS;
}

Last but not least

  • 修改xuartlite_intr.c 驱动文件
/****************************************************************************/
/**
*
* This function handles the interrupt when data is received, either a single
* byte when FIFOs are not enabled, or multiple bytes with the FIFO.
*
* @param	InstancePtr is a pointer to the XUartLite instance.
*
* @return	None.
*
* @note		None.
*
*****************************************************************************/
static void ReceiveDataHandler(XUartLite *InstancePtr)
{
	/*
	 * If there are bytes still to be received in the specified buffer
	 * go ahead and receive them
	 */
	if (InstancePtr->ReceiveBuffer.RemainingBytes != 0) {
		XUartLite_ReceiveBuffer(InstancePtr);
	}

	/*
	 * If the last byte of a message was received then call the application
	 * handler, this code should not use an else from the previous check of
	 * the number of bytes to receive because the call to receive the buffer
	 * updates the bytes to receive
	 */
	// TODO : 注销if语句
	//if (InstancePtr->ReceiveBuffer.RemainingBytes == 0) {
		InstancePtr->RecvHandler(InstancePtr->RecvCallBackRef,InstancePtr->ReceiveBuffer.RequestedBytes -InstancePtr->ReceiveBuffer.RemainingBytes);
	//}

	/*
	 * Update the receive stats to reflect the receive interrupt
	 */
	InstancePtr->Stats.ReceiveInterrupts++;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啥都不会的研究昇

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值