之前笔记:
Zynq上的存储器接口与差分时钟与DDR3_zynq ddr3-CSDN博客
使用Axi Lite接口访问寄存器列表作为缓冲区_两个参数共用axi lite中一个寄存器-CSDN博客
PS与PL互联与SCU以及PG082_pl能不能用ps-gtr-CSDN博客
ZYNQ上互联的AXI主要有三种:
AXI LITE
AXI HP
AXI ACP
AXI LITE(GP)
用途:
通信UART,I2C,SPI,CAN等接口
作为PS存储数据到PL端方便交互的缓冲区;
特色:
32位数据位宽,不可突发;
生成方式:
用途1.自然选通产生的以上接口的以AXI GP口的形式输出的;
用途2.创建IP的时候选择AXI接口:
非常注意:
直接生成的方法至今仍存在BUG,需要采用此方法解决:
Vitis IDE 2021.1 custom AXI IP core compile error (xilinx.com)
参考操作代码:
官方参考:注意!GP口每次操作的偏移量都是4个字节!因为是32位端口!
/**************************** Type Definitions *****************************/ /** * * Write a value to a AXILITE_REG_DEEPTH256 register. A 32 bit write is performed. * If the component is implemented in a smaller width, only the least * significant data is written. * * @param BaseAddress is the base address of the AXILITE_REG_DEEPTH256device. * @param RegOffset is the register offset from the base to write to. * @param Data is the data written to the register. * * @return None. * * @note * C-style signature: * void AXILITE_REG_DEEPTH256_mWriteReg(u32 BaseAddress, unsigned RegOffset, u32 Data) * */ #define AXILITE_REG_DEEPTH256_mWriteReg(BaseAddress, RegOffset, Data) \ Xil_Out32((BaseAddress) + (RegOffset), (u32)(Data)) /** * * Read a value from a AXILITE_REG_DEEPTH256 register. A 32 bit read is performed. * If the component is implemented in a smaller width, only the least * significant data is read from the register. The most significant data * will be read as 0. * * @param BaseAddress is the base address of the AXILITE_REG_DEEPTH256 device. * @param RegOffset is the register offset from the base to write to. * * @return Data is the data from the register. * * @note * C-style signature: * u32 AXILITE_REG_DEEPTH256_mReadReg(u32 BaseAddress, unsigned RegOffset) * */ #define AXILITE_REG_DEEPTH256_mReadReg(BaseAddress, RegOffset) \ Xil_In32((BaseAddress) + (RegOffset)) /************************** Function Prototypes ****************************/ /** * * Run a self-test on the driver/device. Note this may be a destructive test if * resets of the device are performed. * * If the hardware system is not built correctly, this function may never * return to the caller. * * @param baseaddr_p is the base address of the AXILITE_REG_DEEPTH256 instance to be worked on. * * @return * * - XST_SUCCESS if all self-test code passed * - XST_FAILURE if any self-test code failed * * @note Caching must be turned off for this function to work. * @note Self test may fail if data memory and device are not on the same bus. * */ XStatus AXILITE_REG_DEEPTH256_Reg_SelfTest(void * baseaddr_p);View Code
自己封装的函数读写单个和多个:
函数1:读写多个数据;
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; } }View Code
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)); } }View Code
使用示例1:
描述:
1.接收Uart数据并且校验;
2.校验成功则关闭硬中断,向CPU1发送软中断,把Uart接收到的数组写入指定的PL寄存器地址(地址A);
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); }View Code
使用示例2:
描述:
1.CPU1接收CPU0的软中断,据此读取地址A的数值并校验;
2.校验成功则把地址A的数值写入地址B,并且向CPU0发送软中断;
使用示例3:
描述:
CPU0接收CPU1的软中断,据此读取地址B的数值并UART发送;
void SGI_IntrHandler(void *CallBackRef){ Axi_ReadRamB(SendBuffer,8); XUartPs_Send(&Uart_Instance_point, SendBuffer, 8); print("SG0!\n\r"); }View Code
函数2:
/***************************** Include Files *******************************/ #include "axilite_reg_deepth256.h" /************************** Function Definitions ***************************/ /** * * @param BaseAddress : 写入缓冲区基地址 * @param Addr_Offset : 写入缓冲区的地址偏移量(会占用多少空间) * @param data :写入缓冲区的具体数据 * @return none * ***************************************************************************/ void AxiLite_W_Single(u32 BaseAddress, u32 Addr_Offset, u32 data){ AXILITE_REG_DEEPTH256_mWriteReg(BaseAddress, Addr_Offset << 2, data); } /** * * @param BaseAddress : 写入缓冲区基地址 * @param Data_addr_point : 即将写入缓冲区的数组所在的基地址 * @param Write_ByteLong :即将写入缓冲区的数组长度 * @return none * ***************************************************************************/ void AxiLite_W_Serial(u32 BaseAddress, u8 *Data_addr_point, u32 Write_ByteLong){ int i; for ( i = 0; i < Write_ByteLong; i++) { AXILITE_REG_DEEPTH256_mWriteReg(BaseAddress,i*4 ,*(Data_addr_point + i)); } } /** * * @param BaseAddress : 读出缓冲区基地址 * @param Data_addr_point :存放读出数组的缓冲区基地址 * @param Read_ByteLong :读出数组的长度 * @return 读出数据. * * 读出指定缓冲区的指定长度的数据存入某个区域 * * (Data_addr_point + i) = (u32) Read_Data_Origin;将所读出的数据赋值给指定的区域 * ***************************************************************************/ u32 AxiLite_R_Single(u32 BaseAddress, u32 Addr_Offset){ return AXILITE_REG_DEEPTH256_mReadReg(BaseAddress, Addr_Offset <<2); } /** * * @param BaseAddress : 读出缓冲区基地址 * @param Data_addr_point :存放读出数组的缓冲区基地址 * @param Read_ByteLong :读出数组的长度 * @return 读出数据. * * 读出指定缓冲区的指定长度的数据存入某个区域 * * (Data_addr_point + i) = (u32) Read_Data_Origin;将所读出的数据赋值给指定的区域 * ***************************************************************************/ void AxiLite_R_Serial(u32 BaseAddress, u32 *Data_addr_point, u32 Read_ByteLong){ int i; u32 Read_Data_Origin; for ( i = 0; i < Read_ByteLong; i++) { Read_Data_Origin = AXILITE_REG_DEEPTH256_mReadReg(BaseAddress, i*4); *(Data_addr_point + i) = (u32) Read_Data_Origin; } }View Code
使用范例:
描述:将TCP发送的数据包写入指定寄存器并且读出给PL端使用;
if (recv_buf[0] == 0x55 && recv_buf[1] == 0x55 && recv_buf[2] == 0x55 && recv_buf[3] == 0x55 && recv_buf[4] == 0x55 && recv_buf[5] == 0x55 && recv_buf[6] == 0x55 && recv_buf[7] == 0x55 ) { u32 RegAddr; u32 Direct_RW_Flag; u32 RegData = 0; RegAddr = recv_buf[8]; Direct_RW_Flag = recv_buf[9]; /* 将解析的配置数据写入指定好的PL端寄存器地址 */ if(Direct_RW_Flag == 0){ RegData = recv_buf[10]<<24; RegData |= recv_buf[11]<<16; RegData |= recv_buf[12]<<8; RegData |= recv_buf[13]<<0; if(RegAddr == 1){ ImageWeigh = RegData; xil_printf("ConfigSet ImageWeigh!\r\n"); } if(RegAddr == 2){ ImageHeigh = RegData; xil_printf("ConfigSet ImageHeigh!\r\n"); } if(RegAddr == 3){ ReadBack_Flag = RegData; xil_printf("ConfigSet ReadBack_Flag!\r\n"); } AxiLite_W_Single(AXI_ConFig_list_BaseAddr, RegAddr, RegData); RegData = AxiLite_R_Single(AXI_ConFig_list_BaseAddr, RegAddr); recv_buf[10] = (RegData>>24) & 0xff; recv_buf[11] = (RegData>>16) & 0xff; recv_buf[12] = (RegData>>8 ) & 0xff; recv_buf[13] = (RegData>>0 ) & 0xff; if((lwip_send(sock, recv_buf, read_bytes, 0))<0){ xil_printf("%s : Send Error!\r\n",sock); break; } } }View Code
标签:axi,GP,buf,Data,u32,AXI,recv,REG From: https://www.cnblogs.com/VerweileDoch/p/18080046