ZYNQ 同时使能PL-PS中断和串口中断
zynq使能pl-ps中断和串口中断,zynq的多中断使用方法
·
#include "xparameters.h"
#include "xuartps.h"
#include "xil_printf.h"
#include "xscugic.h"
#include "stdio.h"
#include <string.h>
#include "sleep.h"
#include "xil_exception.h"
// PS串口中断
#define UART_DEVICE_ID XPAR_XUARTPS_0_DEVICE_ID //串口设备ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID //中断ID
#define UART_INT_IRQ_ID XPAR_XUARTPS_0_INTR //串口中断ID
// PL中断相关定义
#define INT_CFG0_OFFSET 0x00000C00
#define SW1_INT_ID 121// PL端中断ID
//#define INTC_DEVICE_ID XPAR_XUARTPS_0_DEVICE_ID
#define INT_TYPE_RISING_EDGE 0x03
#define INT_TYPE_HIGHLEVEL 0x01
#define INT_TYPE_MASK 0x03
static XScuGic Intc; //中断控制器驱动程序实例
XUartPs Uart_Ps; //串口驱动程序实例
// 全局标志位(volatile确保中断和主循环可见性)
volatile int uart_recv_flag = 0; // UART接收完成标志
volatile int sw1_trigger_flag = 0; // PL中断触发标志
volatile int TotalReceivedCount;
volatile int TotalSentCount;
int TotalErrorCount;
// 全局缓冲区
u8 uart_recv_buff[5]; // UART接收缓冲区
// PL中断类型设置:上升沿/高电平
void IntcTypeSetup(XScuGic *InstancePtr, int intId, int intType)
{
int mask;
intType &= INT_TYPE_MASK;
mask = XScuGic_DistReadReg(InstancePtr, INT_CFG0_OFFSET + (intId/16)*4);
mask &= ~(INT_TYPE_MASK << (intId%16)*2);
mask |= intType << ((intId%16)*2);
XScuGic_DistWriteReg(InstancePtr, INT_CFG0_OFFSET + (intId/16)*4, mask);
}
//UART初始化函数
int uart_init(XUartPs* uart_ps)
{
int status;
XUartPs_Config *uart_cfg;
uart_cfg = XUartPs_LookupConfig(UART_DEVICE_ID);
if (NULL == uart_cfg)
return XST_FAILURE;
status = XUartPs_CfgInitialize(uart_ps, uart_cfg, uart_cfg->BaseAddress);
if (status != XST_SUCCESS)
return XST_FAILURE;
//UART设备自检
status = XUartPs_SelfTest(uart_ps);
if (status != XST_SUCCESS)
return XST_FAILURE;
//设置工作模式:正常模式
XUartPs_SetOperMode(uart_ps, XUARTPS_OPER_MODE_NORMAL);
//设置波特率:115200
XUartPs_SetBaudRate(uart_ps,115200);
//设置RX FIFO的中断触发阈值 sdk+1 xcom+2
XUartPs_SetFifoThreshold(uart_ps, 4+1);
return XST_SUCCESS;
}
//XUartPs_InterruptHandler(&Uart_Ps);
// UART中断处理函数
void uart_intr_handler(void *call_back_ref)
{
XUartPs *uart_instance_ptr = (XUartPs *) call_back_ref;
u32 isr_status;
// 读取中断状态
isr_status = XUartPs_ReadReg(uart_instance_ptr->Config.BaseAddress, XUARTPS_IMR_OFFSET);
isr_status &= XUartPs_ReadReg(uart_instance_ptr->Config.BaseAddress, XUARTPS_ISR_OFFSET);
// 处理接收溢出中断(RXOVR)
if (isr_status & XUARTPS_IXR_RXOVR) {
// 读取数据到全局缓冲区
XUartPs_Recv(uart_instance_ptr, uart_recv_buff, 5);
// 清除中断标志
XUartPs_WriteReg(uart_instance_ptr->Config.BaseAddress,
XUARTPS_ISR_OFFSET,
XUARTPS_IXR_RXOVR);
// 设置接收完成标志
uart_recv_flag = 1;
}
if (isr_status & XUARTPS_IXR_TXEMPTY) {
if (uart_instance_ptr->SendBuffer.RemainingBytes == (u32)0) {
XUartPs_WriteReg(uart_instance_ptr->Config.BaseAddress,
XUARTPS_IDR_OFFSET,
((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL));
/* Call the application handler to indicate the sending is done */
uart_instance_ptr->Handler(uart_instance_ptr->CallBackRef,
XUARTPS_EVENT_SENT_DATA,
uart_instance_ptr->SendBuffer.RequestedBytes -
uart_instance_ptr->SendBuffer.RemainingBytes);
}
/* If TX FIFO is empty, send more. */
else if((isr_status & ((u32)XUARTPS_IXR_TXEMPTY)) != (u32)0) {
(void)XUartPs_SendBuffer(uart_instance_ptr);
}
else {
/* Else with dummy entry for MISRA-C Compliance.*/
;
}
XUartPs_WriteReg(uart_instance_ptr->Config.BaseAddress,
XUARTPS_ISR_OFFSET,
XUARTPS_IXR_TXEMPTY);
}
}
void Handler(void *CallBackRef, u32 Event, unsigned int EventData)
{
/* All of the data has been sent */
if (Event == XUARTPS_EVENT_SENT_DATA) {
TotalSentCount = EventData;
}
/* All of the data has been received */
if (Event == XUARTPS_EVENT_RECV_DATA) {
TotalReceivedCount = EventData;
}
/*
* Data was received, but not the expected number of bytes, a
* timeout just indicates the data stopped for 8 character times
*/
if (Event == XUARTPS_EVENT_RECV_TOUT) {
TotalReceivedCount = EventData;
}
/*
* Data was received with an error, keep the data but determine
* what kind of errors occurred
*/
if (Event == XUARTPS_EVENT_RECV_ERROR) {
TotalReceivedCount = EventData;
TotalErrorCount++;
}
/*
* Data was received with an parity or frame or break error, keep the data
* but determine what kind of errors occurred. Specific to Zynq Ultrascale+
* MP.
*/
if (Event == XUARTPS_EVENT_PARE_FRAME_BRKE) {
TotalReceivedCount = EventData;
TotalErrorCount++;
}
/*
* Data was received with an overrun error, keep the data but determine
* what kind of errors occurred. Specific to Zynq Ultrascale+ MP.
*/
if (Event == XUARTPS_EVENT_RECV_ORERR) {
TotalReceivedCount = EventData;
TotalErrorCount++;
}
}
//各个中断的回调函数
static void SW1_intr_Handler(void *param)
{
// 设置PL中断触发标志
sw1_trigger_flag = 1;
}
//中断初始化
int all_intr_init(XUartPs *uart_ps)
{
int status;
// 初始化中断控制器
XScuGic_Config *intc_cfg;
intc_cfg = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (NULL == intc_cfg)
return XST_FAILURE;
status = XScuGic_CfgInitialize(&Intc,
intc_cfg,
intc_cfg->CpuBaseAddress);
if (status != XST_SUCCESS)
return XST_FAILURE;
// 设置并打开中断异常处理功能 固定
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
(void *)&Intc);
Xil_ExceptionEnable();
// 注册回调函数
XUartPs_SetHandler(uart_ps, (XUartPs_Handler)Handler, uart_ps);
// 关联串口中断处理函数
status = XScuGic_Connect( &Intc,
UART_INT_IRQ_ID,
(Xil_ExceptionHandler) uart_intr_handler,
(void *) uart_ps);
if (status != XST_SUCCESS)
return XST_FAILURE;
status = XScuGic_Connect(&Intc,
SW1_INT_ID,
(Xil_ExceptionHandler)SW1_intr_Handler,
(void *)1);
if(status != XST_SUCCESS) return XST_FAILURE;
//设置UART中断触发方式
XUartPs_SetInterruptMask(uart_ps, XUARTPS_IXR_RXOVR|XUARTPS_IXR_TXEMPTY);
//设置PL-PS中断触发方式
IntcTypeSetup(&Intc, SW1_INT_ID, INT_TYPE_RISING_EDGE);
//设置中断优先级:0x00代表最高优先级;0x1代表电平触发; 0x3代表上升沿触发;
XScuGic_SetPriorityTriggerType(&Intc, UART_INT_IRQ_ID, 0x00, 0x1);
XScuGic_SetPriorityTriggerType(&Intc, SW1_INT_ID, 0x20, 0x3);
//使能GIC中的串口中断、PL中断
XScuGic_Enable(&Intc, UART_INT_IRQ_ID);
XScuGic_Enable(&Intc, SW1_INT_ID);
return XST_SUCCESS;
}
int main()
{
int status;
char str[5]; // 用于字符串转换
u8 send_buff[1000]; // 发送缓冲区(保持不变)
// xil_printf("start\r\n");
// 初始化发送缓冲区(填充'0')
for(int i=0; i<1000; i++){
send_buff[i] = '0';
}
// 初始化UART和中断
status = uart_init(&Uart_Ps);
if (status == XST_FAILURE) {
xil_printf("Uart Initial Failed\r\n");
return XST_FAILURE;
}
all_intr_init(&Uart_Ps);
// 主循环:处理标志位
while(1) {
// 处理UART接收数据
if (uart_recv_flag) {
// 1. 转换为字符串(原中断中的逻辑)
for(int i=0; i<4; i++) {
str[i] = (char)uart_recv_buff[i];
}
str[4] = '\0'; // 字符串结束符
// 2. 检查是否为"aaaa"(原中断中的逻辑)
if(strncmp(str, "aaaa", 4) == 0) {
const char response[] = "Triggered!\r\n";
// 确保UART空闲时再发送
while (XUartPs_IsSending(&Uart_Ps));
XUartPs_Send(&Uart_Ps, (u8*)response, strlen(response));
// 打印send_buff前20字节(原中断中的逻辑)
for(int i=0; i<20; i++) {
xil_printf("%02X ", send_buff[i]);
}
xil_printf("\r\n");
} else {
// 打印接收的字符串(原中断中的逻辑)
xil_printf("String: %s\r\n", str);
}
// 3. 清除接收标志(处理完成)
uart_recv_flag = 0;
}
// 处理PL中断触发(发送send_buff)
if (sw1_trigger_flag) {
// 确保UART空闲时再发送
while (XUartPs_IsSending(&Uart_Ps));
XUartPs_Send(&Uart_Ps, send_buff, 500);
// 清除PL触发标志
sw1_trigger_flag = 0;
}
}
return status;
}
更多推荐



所有评论(0)