实现思路:
1.通过PL实现定时器每隔特定的时间为CPU0和CPU1发送硬中断;
2.注册Uart中断,使用超时中断事件,当发送指定命令的时候,CPU0会因为Uart中断停止硬中断,将发送的命令中指定的数据写入到缓存区A中,并且向CPU1发送软中断;
3.CPU1收到来自CPU0的软中断,停止指向自身的硬中断,检查缓存区A中的指定数据,如果符合约定的命令,将缓存区A中的数据写入缓存区B,且向CPU0发送软中断;
4.CPU0收到来自CPU1的软中断,将缓存区B的数据读出并且通过Uart完成发送;
细节:
这里的缓存区RAM可以通过创建IP直接创建,也可以通过IP核:
Block Memory Generator
进行创建,因为是GP口,地址和数据默认为 32 位。
此外:对于AXI LITE缓存区主要是通过Xil提供的驱动实现的,但也可以输出给PL;
实验现象:

其中读写Bram的代码可参考:
Axi_Lite接口的IP核与地址与缓冲与AxiGP0-CSDN博客
设置的是超时中断触发,set阈值那个不太好用。
检测收到的Uart数据,符合标准则发送软中断给CPU1,并且禁用硬中断;
- void Uart0_IntrHandler(void *CallBackRef, u32 Event, unsigned int EventData)
- {
- if (Event == XUARTPS_EVENT_RECV_TOUT) {
- TotalReceivedCount = EventData;
- if (TotalReceivedCount == 8
- && RecvBuffer[0] == 0x55 && RecvBuffer[1] == 0x55
- && RecvBuffer[2] == 0x00 && RecvBuffer[3] == 0x01)
- {
- XScuGic_Disable(&GIC_SGI_instance_point, Interrupt_ID_Hardware_1);
- XScuGic_Disable(&GIC_SGI_instance_point, Interrupt_ID_Hardware_0);
- Axi_WriteRamA(RecvBuffer,TotalReceivedCount);
- printf("Close SPI\n\r");
- XScuGic_SoftwareIntr(&GIC_SGI_instance_point,
- Interrupt_ID_SGI_15,
- XSCUGIC_SPI_CPU1_MASK);
- }
- else if(TotalReceivedCount == 8 && RecvBuffer[0] == 0x66)
- {
- XScuGic_Enable(&GIC_SGI_instance_point, Interrupt_ID_Hardware_0);
- printf("Open SPI\n\r");
- }
- }
- XUartPs_Recv(&Uart_Instance_point, RecvBuffer, TEST_BUFFER_SIZE);
- }
检查缓存区A中的数据是否符合要求,如果符合要求则写入缓存区B,
同时向CPU0发送软中断;
-
- void SGI_IntrHandler(void *CallBackRef){
- u32 origin_command;
- print("SG1!\n\r");
- Axi_ReadRamA(COMMAND_BUFFER,8);
- if(COMMAND_BUFFER[4]==0x04 && COMMAND_BUFFER[5] == 0x05
- && COMMAND_BUFFER[6]==0x06 && COMMAND_BUFFER[7] == 0x07)
- {
- Axi_WriteRamB(COMMAND_BUFFER,8);
- XScuGic_SoftwareIntr(&GIC_SGI_instance_point, Interrupt_ID_SGI_14, CPU_id_0);
- }
- }
将缓存区B中的数据用Uart发送;
- void SGI_IntrHandler(void *CallBackRef){
- Axi_ReadRamB(SendBuffer,8);
- XUartPs_Send(&Uart_Instance_point, SendBuffer, 8);
- print("SG0!\n\r");
- }
- /******************************************************************************
- *
- * Copyright (C) 2009 - 2014 Xilinx, Inc. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * Use of the Software is limited solely to applications:
- * (a) running on a Xilinx device, or
- * (b) that interact with a Xilinx device through a bus or interconnect.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of the Xilinx shall not be used
- * in advertising or otherwise to promote the sale, use or other dealings in
- * this Software without prior written authorization from Xilinx.
- *
- ******************************************************************************/
-
- /*
- * helloworld.c: simple test application
- *
- * This application configures UART 16550 to baud rate 9600.
- * PS7 UART (Zynq) is not initialized by this application, since
- * bootrom/bsp configures it to baud rate 115200
- *
- * ------------------------------------------------
- * | UART TYPE BAUD RATE |
- * ------------------------------------------------
- * uartns550 9600
- * uartlite Configurable only in HW design
- * ps7_uart 115200 (configured by bootrom/bsp)
- */
-
- #include
- #include "platform.h"
- #include "xil_printf.h"
- #include "xil_mmu.h"
- #include "xscugic.h"
- #include "xuartps.h"
- #include "xparameters.h"
- #include "xil_exception.h"
- #include "Axi_REG_List.h"
-
- #define COMM_VAL (*(volatile unsigned long *)(0xFFFF0000))
- #define APP_CPU1_ADDR 0x02000000
- #define OCM_ADDR 0xFFFF0000
- #define Interrupt_ID_SGI_14 0x0D
- #define Interrupt_ID_SGI_15 0x0E
- #define Interrupt_ID_Hardware_0 61
- #define Interrupt_ID_Hardware_1 62
- #define DistBaseAddress XPAR_PS7_SCUGIC_0_DIST_BASEADDR
- //AXI BaseAddr
- #define Axi_RamA_BaseAddr 0x43C00000
- #define Axi_RamB_BaseAddr 0x43C10000
- //GIC
- #define XIL_EXCEPTION_ID_INT XIL_EXCEPTION_ID_IRQ_INT
- #define GIC_DECIVE_ID_INT XPAR_SCUGIC_0_DEVICE_ID
- //CPU_ID
- #define CPU_id_0 XSCUGIC_SPI_CPU0_MASK
- #define CPU_id_1 XSCUGIC_SPI_CPU1_MASK
- //Uart
- #define Interrupt_ID_Uart_0 XPS_UART0_INT_ID
- #define Uart_Decive_ID XPAR_PS7_UART_0_DEVICE_ID
- static XUartPs_Config *Uart_ConFig;
- static XUartPs Uart_Instance_point;
- #define TEST_BUFFER_SIZE 32
- u8 SendBuffer[TEST_BUFFER_SIZE]; /* Buffer for Transmitting Data */
- u8 RecvBuffer[TEST_BUFFER_SIZE]; /* Buffer for Receiving Data */
- volatile int TotalReceivedCount;
- //SGI
- static XScuGic_Config *GIC_SGI_ConFig;
- static XScuGic GIC_SGI_instance_point;
-
-
- int Uart_init();
- int GIC_SGI_init();
- void Uart_SetHandler_Event();
- void SGI_IntrHandler(void *CallBackRef);
- void Hardware_IntrHandler(void *CallBackRef);
- void Uart0_IntrHandler(void *CallBackRef, u32 Event, unsigned int EventData);
- void Axi_WriteRamA(u8 *Data_addr_point, u32 Write_ByteLong);
- void Axi_ReadRamB (u8 *Data_addr_point, u32 Read_ByteLong );
- int main()
- {
- int Status;
- COMM_VAL = 0;
- Status = Uart_init();
- if (Status != XST_SUCCESS) {
- return XST_FAILURE;
- }
- Status = GIC_SGI_init();
- if (Status != XST_SUCCESS) {
- return XST_FAILURE;
- }
- Xil_SetTlbAttributes(0xFFFF0000,0x14de2);
- Uart_SetHandler_Event();
- while(1){
- print("CPU0: Hello World CPU 0\n\r");
- COMM_VAL = 1;
- while(COMM_VAL == 1){
- }
- }
- return 0;
- }
-
- int GIC_SGI_init(){
- int Status;
-
- Xil_ExceptionInit();
- GIC_SGI_ConFig = XScuGic_LookupConfig(GIC_DECIVE_ID_INT);
- if (NULL == GIC_SGI_ConFig) {
- return XST_FAILURE;
- }
-
- Status = XScuGic_CfgInitialize(&GIC_SGI_instance_point,
- GIC_SGI_ConFig,
- GIC_SGI_ConFig->CpuBaseAddress);
- if (Status != XST_SUCCESS) {
- return XST_FAILURE;
- }
- Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
- (Xil_ExceptionHandler) XScuGic_InterruptHandler,
- &GIC_SGI_instance_point);
- //---------------------------------------------------------------//
- //SGI
- Status = XScuGic_Connect(&GIC_SGI_instance_point,
- Interrupt_ID_SGI_14,
- (Xil_InterruptHandler )SGI_IntrHandler,
- (void *)&GIC_SGI_instance_point
- );
- if (Status != XST_SUCCESS) {
- return XST_FAILURE;
- }
- XScuGic_Enable(&GIC_SGI_instance_point,
- Interrupt_ID_SGI_14);
- //SPI hardware----------------------------------------------------//
- Status = XScuGic_Connect(&GIC_SGI_instance_point,
- Interrupt_ID_Hardware_0,
- (Xil_InterruptHandler )Hardware_IntrHandler,
- (void *)&GIC_SGI_instance_point
- );
- if (Status != XST_SUCCESS) {
- return XST_FAILURE;
- }
- XScuGic_SetPriTrigTypeByDistAddr(DistBaseAddress,
- Interrupt_ID_Hardware_0,
- 0x20,
- 0x03);
- XScuGic_InterruptMaptoCpu(&GIC_SGI_instance_point,
- CPU_id_0,
- Interrupt_ID_Hardware_0);
- XScuGic_Enable(&GIC_SGI_instance_point,
- Interrupt_ID_Hardware_0);
- //Uart interrupt--------------------------------------------------//
- Status = XScuGic_Connect(&GIC_SGI_instance_point,
- Interrupt_ID_Uart_0,
- (Xil_InterruptHandler )XUartPs_InterruptHandler,
- (void *)&Uart_Instance_point
- );
- if (Status != XST_SUCCESS) {
- return XST_FAILURE;
- }
- XScuGic_Enable(&GIC_SGI_instance_point, Interrupt_ID_Uart_0);
- //---------------------------------------------------------------//
- Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);
- return XST_SUCCESS;
- }
- int Uart_init(){
- s32 Status = XST_SUCCESS;
- Uart_ConFig = XUartPs_LookupConfig(Uart_Decive_ID);
- if (NULL == Uart_ConFig) {
- return XST_FAILURE;
- }
- Status = XUartPs_CfgInitialize(&Uart_Instance_point,
- Uart_ConFig,
- Uart_ConFig->BaseAddress);
- if (Status != XST_SUCCESS) {
- return XST_FAILURE;
- }
- Status = XUartPs_SelfTest(&Uart_Instance_point);
- if (Status != XST_SUCCESS) {
- return XST_FAILURE;
- }
- Status = XUartPs_SetBaudRate(&Uart_Instance_point,115200);
- if (Status != XST_SUCCESS) {
- return XST_FAILURE;
- }
- return Status;
- }
-
- void Uart_SetHandler_Event(){
- u32 IntrMask = 0;
- int Index;
- XUartPs_SetHandler(&Uart_Instance_point,
- (XUartPs_Handler) Uart0_IntrHandler,
- &Uart_Instance_point);
- IntrMask = XUARTPS_IXR_TOUT|XUARTPS_IXR_RXOVR;
- XUartPs_SetInterruptMask(&Uart_Instance_point, IntrMask);
- XUartPs_SetOperMode(&Uart_Instance_point,XUARTPS_OPER_MODE_NORMAL);
- XUartPs_SetRecvTimeout(&Uart_Instance_point,8);
- // XUartPs_SetFifoThreshold(&Uart_Instance_point,8);
- // Clear Buffer
- for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) {
- SendBuffer[Index] = 0;
- RecvBuffer[Index] = 0;
- }
- XUartPs_Recv(&Uart_Instance_point, RecvBuffer, TEST_BUFFER_SIZE);
- // XUartPs_Send(&Uart_Instance_point, SendBuffer, TEST_BUFFER_SIZE);
- }
- void SGI_IntrHandler(void *CallBackRef){
- Axi_ReadRamB(SendBuffer,8);
- XUartPs_Send(&Uart_Instance_point, SendBuffer, 8);
- print("SG0!\n\r");
- }
- void Hardware_IntrHandler(void *CallBackRef){
- // print("Hardware:CLOCK Interrupt CPU0!\n\r");
- print("H0!\n\r");
- }
- /**************************************************************************/
- /**
- *
- * This function is the handler which performs processing to handle data events
- * from the device. It is called from an interrupt context. so the amount of
- * processing should be minimal.
- *
- * This handler provides an example of how to handle data for the device and
- * is application specific.
- *
- * @param CallBackRef contains a callback reference from the driver,
- * in this case it is the instance pointer for the XUartPs driver.
- * @param Event contains the specific kind of event that has occurred.
- * @param EventData contains the number of bytes sent or received for sent
- * and receive events.
- *
- * @return None.
- *
- * @note None.
- *
- ***************************************************************************/
- void Uart0_IntrHandler(void *CallBackRef, u32 Event, unsigned int EventData)
- {
- if (Event == XUARTPS_EVENT_RECV_TOUT) {
- TotalReceivedCount = EventData;
- if (TotalReceivedCount == 8
- && RecvBuffer[0] == 0x55 && RecvBuffer[1] == 0x55
- && RecvBuffer[2] == 0x00 && RecvBuffer[3] == 0x01)
- {
- XScuGic_Disable(&GIC_SGI_instance_point, Interrupt_ID_Hardware_1);
- XScuGic_Disable(&GIC_SGI_instance_point, Interrupt_ID_Hardware_0);
- Axi_WriteRamA(RecvBuffer,TotalReceivedCount);
- printf("Close SPI\n\r");
- XScuGic_SoftwareIntr(&GIC_SGI_instance_point,
- Interrupt_ID_SGI_15,
- XSCUGIC_SPI_CPU1_MASK);
- }
- else if(TotalReceivedCount == 8 && RecvBuffer[0] == 0x66)
- {
- XScuGic_Enable(&GIC_SGI_instance_point, Interrupt_ID_Hardware_0);
- printf("Open SPI\n\r");
- }
- }
- XUartPs_Recv(&Uart_Instance_point, RecvBuffer, TEST_BUFFER_SIZE);
- }
- void Axi_WriteRamA(u8 *Data_addr_point, u32 Write_ByteLong){
- int i;
- for ( i = 0; i < Write_ByteLong; i++)
- {
- AXI_REG_LIST_mWriteReg(Axi_RamA_BaseAddr,i*4 ,*(Data_addr_point + i));
- }
- }
- void Axi_ReadRamB(u8 *Data_addr_point, u32 Read_ByteLong){
- int i;
- u32 Read_Data_Origin;
- for ( i = 0; i < Read_ByteLong; i++)
- {
- Read_Data_Origin = AXI_REG_LIST_mReadReg(Axi_RamB_BaseAddr, i*4);
- *(Data_addr_point + i) = (u8) Read_Data_Origin;
- }
- }
- /******************************************************************************
- *
- * Copyright (C) 2009 - 2014 Xilinx, Inc. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * Use of the Software is limited solely to applications:
- * (a) running on a Xilinx device, or
- * (b) that interact with a Xilinx device through a bus or interconnect.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of the Xilinx shall not be used
- * in advertising or otherwise to promote the sale, use or other dealings in
- * this Software without prior written authorization from Xilinx.
- *
- ******************************************************************************/
-
- /*
- * helloworld.c: simple test application
- *
- * This application configures UART 16550 to baud rate 9600.
- * PS7 UART (Zynq) is not initialized by this application, since
- * bootrom/bsp configures it to baud rate 115200
- *
- * ------------------------------------------------
- * | UART TYPE BAUD RATE |
- * ------------------------------------------------
- * uartns550 9600
- * uartlite Configurable only in HW design
- * ps7_uart 115200 (configured by bootrom/bsp)
- */
-
- #include
- #include "platform.h"
- #include "xil_printf.h"
- #include "xil_mmu.h"
- #include "xscugic.h"
- #include "Axi_REG_List.h"
- #include "xuartps.h"
- #include "xparameters.h"
- #include "xil_exception.h"
-
- #define COMM_VAL (*(volatile unsigned long *)(0xFFFF0000))
- #define APP_CPU1_ADDR 0x02000000
- #define OCM_ADDR 0xFFFF0000
- #define Interrupt_ID_SGI_14 0x0D
- #define Interrupt_ID_SGI_15 0x0E
- #define Interrupt_ID_Hardware_0 61
- #define Interrupt_ID_Hardware_1 62
- #define DistBaseAddress XPAR_PS7_SCUGIC_0_DIST_BASEADDR
- #define CPU_id_0 XSCUGIC_SPI_CPU0_MASK
- #define CPU_id_1 XSCUGIC_SPI_CPU1_MASK
- //AXI BaseAddr
- #define Axi_RamA_BaseAddr 0x43C00000
- #define Axi_RamB_BaseAddr 0x43C10000
- //GIC
- #define XIL_EXCEPTION_ID_INT XIL_EXCEPTION_ID_IRQ_INT
- #define GIC_DECIVE_ID_INT XPAR_SCUGIC_0_DEVICE_ID
-
- #define TEST_BUFFER_SIZE 32
- u8 Media_Buffer[TEST_BUFFER_SIZE];
-
- static XScuGic_Config *GIC_SGI_ConFig;
- static XScuGic GIC_SGI_instance_point;
-
- int GIC_SGI_init();
- void SGI_IntrHandler(void *CallBackRef);
- void Hardware_IntrHandler(void *CallBackRef);
- void Axi_ReadRamA (u8 *Data_addr_point, u32 Read_ByteLong );
- void Axi_WriteRamB(u8 *Data_addr_point, u32 Write_ByteLong);
-
- int main()
- {
- int Status;
- Xil_SetTlbAttributes(0xFFFF0000,0x14de2);
- while(1){
- while(COMM_VAL == 1){
- print("CPU1: Hello World CPU 1\n\r");
- Status = GIC_SGI_init();
- if (Status != XST_SUCCESS) {
- return XST_FAILURE;
- }
- while (1){
- }
- }
- }
- return 0;
- }
-
- int GIC_SGI_init(){
- int Status;
-
- Xil_ExceptionInit();
- GIC_SGI_ConFig = XScuGic_LookupConfig(GIC_DECIVE_ID_INT);
- if (NULL == GIC_SGI_ConFig) {
- return XST_FAILURE;
- }
-
- Status = XScuGic_CfgInitialize(&GIC_SGI_instance_point,
- GIC_SGI_ConFig,
- GIC_SGI_ConFig->CpuBaseAddress);
- if (Status != XST_SUCCESS) {
- return XST_FAILURE;
- }
- Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
- (Xil_ExceptionHandler) XScuGic_InterruptHandler,
- &GIC_SGI_instance_point);
-
- Status = XScuGic_Connect(&GIC_SGI_instance_point,
- Interrupt_ID_SGI_15,
- (Xil_InterruptHandler )SGI_IntrHandler,
- (void *)&GIC_SGI_instance_point
- );
- if (Status != XST_SUCCESS) {
- return XST_FAILURE;
- }
- XScuGic_Enable(&GIC_SGI_instance_point,
- Interrupt_ID_SGI_15);
- //HGI
- Status = XScuGic_Connect(&GIC_SGI_instance_point,
- Interrupt_ID_Hardware_1,
- (Xil_InterruptHandler )Hardware_IntrHandler,
- (void *)&GIC_SGI_instance_point
- );
- if (Status != XST_SUCCESS) {
- return XST_FAILURE;
- }
- XScuGic_SetPriTrigTypeByDistAddr(DistBaseAddress,
- Interrupt_ID_Hardware_1,
- 0x21,
- 0x03);
- XScuGic_InterruptMaptoCpu(&GIC_SGI_instance_point,
- XSCUGIC_SPI_CPU1_MASK,
- Interrupt_ID_Hardware_1);
- XScuGic_Enable(&GIC_SGI_instance_point,
- Interrupt_ID_Hardware_1);
- Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);
- return XST_SUCCESS;
- }
-
- void SGI_IntrHandler(void *CallBackRef){
- u32 origin_command;
- print("SG1!\n\r");
- Axi_ReadRamA(Media_Buffer,8);
- if(Media_Buffer[4]==0x04 && Media_Buffer[5] == 0x05
- && Media_Buffer[6]==0x06 && Media_Buffer[7] == 0x07)
- {
- Axi_WriteRamB(Media_Buffer,8);
- XScuGic_SoftwareIntr(&GIC_SGI_instance_point, Interrupt_ID_SGI_14, CPU_id_0);
- }
- }
- void Hardware_IntrHandler(void *CallBackRef){
- print("H1!\n\r");
- }
- void Axi_ReadRamA(u8 *Data_addr_point, u32 Read_ByteLong){
- int i;
- u32 Read_Data_Origin;
- for ( i = 0; i < Read_ByteLong; i++)
- {
- Read_Data_Origin = AXI_REG_LIST_mReadReg(Axi_RamA_BaseAddr, i*4);
- *(Data_addr_point + i) = (u8) Read_Data_Origin;
- }
- }
- void Axi_WriteRamB(u8 *Data_addr_point, u32 Write_ByteLong){
- int i;
- for ( i = 0; i < Write_ByteLong; i++)
- {
- AXI_REG_LIST_mWriteReg(Axi_RamB_BaseAddr,i*4 ,*(Data_addr_point + i));
- }
- }