ZYNQ AXI 片上互联的再思考:AXI GP口/axi lite

之前笔记:

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

 

posted @ 2024-03-18 12:22  NoNounknow  阅读(587)  评论(0)    收藏  举报