前言
- 本日记尝试去使用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 NAME | IRQ Number | Bits | Required Type | Description |
|---|---|---|---|---|
| PL_PS_Group0 | 121:128 | 7,8 | rising edge/high level | PL to PS interrupt signals 0 to 7.(3) |
| PL_PS_Group1 | 136:143 | 8 | rising edge/high level | PL 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++;
}
1万+

被折叠的 条评论
为什么被折叠?



