#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;
}






Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐