硬汉嵌入式论坛

 找回密码
 立即注册
查看: 284|回复: 1
收起左侧

zynq中sg dma用法求助

[复制链接]

1

主题

0

回帖

3

积分

新手上路

积分
3
发表于 2024-4-1 19:11:24 | 显示全部楼层 |阅读模式
本帖最后由 HanDou 于 2024-4-1 19:18 编辑

求助大佬们,板子用的是黑金的7015,用sg dma接收网口数据,会丢帧,不知道是我dma代码用法不对,还是速率不够,求指点(mac帧数据部分是连续的,用来检测是否丢帧)


打印错误信息

源码如下



#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xaxidma.h"
#include "xaxiethernet.h"
#include "xaxiethernet_example.h"
#include "xtime_l.h"
#include "xscugic.h"
#include "xdebug.h"


#ifndef DEBUG
extern void xil_printf(const char *format, ...);
#endif






#define         AXIDMA_DEVICE_ID        XPAR_AXIDMA_0_DEVICE_ID
#define         BD_ALIGNMENT                0x40
#define         RXBD_CNT                        281
#define         TXBD_CNT                        281


#define RXBD_SPACE_BYTES (XAxiDma_BdRingMemCalc(BD_ALIGNMENT, RXBD_CNT))
#define TXBD_SPACE_BYTES (XAxiDma_BdRingMemCalc(BD_ALIGNMENT, TXBD_CNT))


char RxBdSpace[RXBD_SPACE_BYTES] __attribute__ ((aligned(BD_ALIGNMENT)));
char TxBdSpace[TXBD_SPACE_BYTES] __attribute__ ((aligned(BD_ALIGNMENT)));
int SetInterruptInit(XScuGic *InstancePtr, u16 IntrID) ;
#define INT_DEVICE_ID      XPAR_SCUGIC_SINGLE_DEVICE_ID
#define XAXIDMA_BD_STS_ALL_ERR_MASK        0x70000000 /**< All errors */
#define S2MM_INTR_ID       XPAR_FABRIC_AXI_ETHERNET_0_DMA_S2MM_INTROUT_INTR
#define MM2S_INTR_ID       XPAR_FABRIC_AXI_ETHERNET_0_DMA_MM2S_INTROUT_INTR
void Dma_Interrupt_Handler(void *CallBackRef);
void Dma_Interrupt_Handler1(void *CallBackRef);
int dma_init(XAxiDma *DmaInstancePtr,XScuGic *InstancePtr);
int dma_data(XAxiDma *DmaInstancePtr);
//dma init


volatile int s2mm_flag ;
volatile int mm2s_flag ;
XScuGic INST ;
XAxiDma DmaInstance;
int ial;
u32 RxFrameLength;
u32 RxFrameLength_next;


//u32 RxFrame[1600] ;
//u32 TxFrame[1600] ;
static EthernetFrame TxFrame ;        /* Transmit buffer */
static EthernetFrame RxFrame ;        /* Receive buffer */
uint8_t mac_data[1600];


u64 frame_num = 0;
u64 frame_num_last = 0;
int err_indx;


int main()
{
    init_platform();
    int status;
    ial = 0 ;
    SetInterruptInit(&INST, INT_DEVICE_ID) ;
    status =  dma_init(&DmaInstance,&INST);
        if(status != XST_SUCCESS){
                    printf("init err");
                    return XST_FAILURE;
            }
        for(int i = 0; i<10;i++){
                status = dma_data(&DmaInstance);
                if(status != XST_SUCCESS){
                        printf("err");
//                        xil_printf("ial = %d \n",ial);
                        break;
                }
        }


        xil_printf("ial = %d \n",ial);
        xil_printf("err_indx = %d \n",err_indx);
        printf("frame_num = %llu \n", frame_num);
        printf("frame_num_last = %llu \n", frame_num_last);
    cleanup_platform();
    return 0;
}


int dma_data(XAxiDma *DmaInstancePtr) {
        int Status;
        XAxiDma_BdRing *RxRingPtr = XAxiDma_GetRxRing(DmaInstancePtr);
        XAxiDma_BdRing *TxRingPtr = XAxiDma_GetTxRing(DmaInstancePtr);
        s2mm_flag = 0;
        mm2s_flag = 0;
        XAxiDma_Bd *Bd1Ptr;
        XAxiDma_Bd *Bd2Ptr;
        XAxiDma_Bd *BdCurPtr;
        XAxiDma_Bd *Tx_BdCurPtr;
        UINTPTR RxBufferPtr;
        UINTPTR TxBufferPtr;
        u32 BdSts;
        int FreeBdCount;
        int Tx_FreeBdCount;
        /*
         * Clear variables shared with callbacks
         */




        memset(RxFrame,0,sizeof(RxFrame));




        Xil_DCacheInvalidateRange((UINTPTR)&RxFrame, sizeof(RxFrame));




//        XAxiDma_BdRingIntEnable(RxRingPtr, XAXIDMA_IRQ_ALL_MASK);


//        set Rx Bd
    FreeBdCount = XAxiDma_BdRingGetFreeCnt(RxRingPtr);
        Status = XAxiDma_BdRingAlloc(RxRingPtr, FreeBdCount, &Bd1Ptr);
        if (Status != XST_SUCCESS) {
//                xil_printf("14   ");
                return XST_FAILURE;
        }
        BdCurPtr = Bd1Ptr;
        RxBufferPtr = (UINTPTR)&RxFrame;
        for (int Index = 0; Index < FreeBdCount; Index++) {
                Status = XAxiDma_BdSetBufAddr(BdCurPtr, RxBufferPtr);
                if (Status != XST_SUCCESS) {
                                        xil_printf("Rx set buffer addr %x on BD %x failed %d\r\n",
                                        (unsigned int)RxFrame,
                                        (UINTPTR)BdCurPtr, Status);


                                        return XST_FAILURE;
                }
                // 构建BD,设定每个RX BD的传输长度
                Status = XAxiDma_BdSetLength(BdCurPtr, 1600,
                                        RxRingPtr->MaxTransferLen);
                if (Status != XST_SUCCESS) {
                                        xil_printf("Rx set length %d on BD %x failed %d\r\n",
                                            1600, (UINTPTR)BdCurPtr, Status);


                                        return XST_FAILURE;
                }
                XAxiDma_BdSetCtrl(BdCurPtr, 0);
                RxBufferPtr += 1600;
                BdCurPtr = (XAxiDma_Bd *)XAxiDma_BdRingNext(RxRingPtr, BdCurPtr);
        }
        // 传输BD链给DMA 准备启动传输
        Status = XAxiDma_BdRingToHw(RxRingPtr, FreeBdCount, Bd1Ptr);
        if (Status != XST_SUCCESS) {
                xil_printf("Rx ToHw failed with %d\r\n", Status);
                return XST_FAILURE;
        }
//
        while(!s2mm_flag){
//                        xil_printf("520");
                        }
        if (XAxiDma_BdRingFromHw(RxRingPtr, FreeBdCount, &Bd1Ptr) == 0) {
                                                                xil_printf("13");
                                                                return XST_FAILURE;
        }
        Status = XAxiDma_BdRingFree(RxRingPtr, FreeBdCount, Bd1Ptr);
                if (Status != XST_SUCCESS) {
                        xil_printf("6");
                        return XST_FAILURE;
        }
//        Xil_DCacheFlushRange((UINTPTR)RxFrame, sizeof(RxFrame));
        Xil_DCacheInvalidateRange((UINTPTR)&RxFrame, sizeof(RxFrame));
        TxBufferPtr = (UINTPTR)&RxFrame;
        for (int i = 0; i < FreeBdCount; i++) {
                // 访问每个BD的数据长度
                memcpy(mac_data, TxBufferPtr, 100);
                memcpy(&frame_num, mac_data+42, 8);
                ial = ial + 1;
                if((frame_num_last != 0) && ((frame_num-frame_num_last) > 1)){
                        err_indx = err_indx + 1;
                        return XST_FAILURE;
                }
                frame_num_last = frame_num;
                TxBufferPtr = TxBufferPtr +        1600;
        }




        return XST_SUCCESS;
}




void Dma_Interrupt_Handler1(void *CallBackRef)
{
        XAxiDma *XAxiDmaPtr ;
        int Status;
        XAxiDmaPtr = (XAxiDma *) CallBackRef ;
        XAxiDma_BdRing *TxRingPtr = XAxiDma_GetTxRing(XAxiDmaPtr);
        XAxiDma_Bd *Bd2Ptr;
        int mm2s_sr ;
        mm2s_sr = XAxiDma_IntrGetIrq(XAxiDmaPtr, XAXIDMA_DMA_TO_DEVICE) ;
        if (mm2s_sr & XAXIDMA_IRQ_IOC_MASK)
        {
                /* Clear interrupt */
                XAxiDma_IntrAckIrq(XAxiDmaPtr, XAXIDMA_IRQ_IOC_MASK,
                                XAXIDMA_DMA_TO_DEVICE) ;
                /* Invalidate the Data cache for the given address range */
                Xil_DCacheInvalidateRange(TxFrame, sizeof(TxFrame));
                mm2s_flag = 1 ;


        }


}
void Dma_Interrupt_Handler(void *CallBackRef)
{
        XAxiDma *XAxiDmaPtr ;
        XAxiDmaPtr = (XAxiDma *) CallBackRef ;
        int s2mm_sr ;
        int Status;
        XAxiDma_Bd *BdCurPtr;
        XAxiDma_BdRing *RxRingPtr = XAxiDma_GetTxRing(XAxiDmaPtr);
        XAxiDma_Bd *Bd1Ptr;
        u32 BdSts;
        s2mm_sr = XAxiDma_IntrGetIrq(XAxiDmaPtr, XAXIDMA_DEVICE_TO_DMA) ;
        if (s2mm_sr & XAXIDMA_IRQ_IOC_MASK)
        {
                /* Clear interrupt */
                XAxiDma_IntrAckIrq(XAxiDmaPtr, XAXIDMA_IRQ_IOC_MASK,
                                XAXIDMA_DEVICE_TO_DMA) ;
                /* Invalidate the Data cache for the given address range */


                Xil_DCacheInvalidateRange(RxFrame, sizeof(RxFrame));
                s2mm_flag = 1 ;


        }


}


int dma_init(XAxiDma *DmaInstancePtr,XScuGic *InstancePtr){


        int Status;
        XAxiDma_Config* DmaConfig;
        XAxiDma_BdRing *RxRingPtr = XAxiDma_GetRxRing(DmaInstancePtr);
        XAxiDma_BdRing *TxRingPtr = XAxiDma_GetTxRing(DmaInstancePtr);


        XAxiDma_Bd BdTemplate;


        DmaConfig = XAxiDma_LookupConfig(AXIDMA_DEVICE_ID);


        Status = XAxiDma_CfgInitialize(DmaInstancePtr, DmaConfig);
        if(Status != XST_SUCCESS) {
                return XST_FAILURE;
        }


        // optimize cache
#if defined(__aarch64__)
        Xil_SetTlbAttributes(TxBdSpace, NORM_NONCACHE | INNER_SHAREABLE);
        Xil_SetTlbAttributes(RxBdSpace, NORM_NONCACHE | INNER_SHAREABLE);
#endif


        //create Rx bd ring
        // XAxiDma_BdRingIntDisable(RxRingPtr, XAXIDMA_IRQ_ALL_MASK);


        Status = XAxiDma_BdRingCreate(RxRingPtr, (UINTPTR) &RxBdSpace,
                                             (UINTPTR) &RxBdSpace, BD_ALIGNMENT, RXBD_CNT);
        if (Status != XST_SUCCESS) {
                return XST_FAILURE;
        }


        XAxiDma_BdClear(&BdTemplate);
        Status = XAxiDma_BdRingClone(RxRingPtr, &BdTemplate);


         //Create the TxBD ring


        Status = XAxiDma_BdRingCreate(TxRingPtr, (UINTPTR) &TxBdSpace,
                                (UINTPTR) &TxBdSpace, BD_ALIGNMENT, TXBD_CNT);


        if (Status != XST_SUCCESS) {
                return XST_FAILURE;
        }


        Status = XAxiDma_BdRingClone(TxRingPtr, &BdTemplate);
        if (Status != XST_SUCCESS) {
                return XST_FAILURE;
        }


        Status = XScuGic_Connect(InstancePtr, S2MM_INTR_ID,
                                (Xil_ExceptionHandler)Dma_Interrupt_Handler,
                                (void *)DmaInstancePtr) ;
        Status = XScuGic_Connect(InstancePtr, MM2S_INTR_ID,
                                        (Xil_ExceptionHandler)Dma_Interrupt_Handler1,
                                        (void *)DmaInstancePtr) ;
        XScuGic_Enable(InstancePtr, S2MM_INTR_ID);
        XScuGic_Enable(InstancePtr, MM2S_INTR_ID);
        /* Disable MM2S interrupt, Enable S2MM interrupt */
        XAxiDma_IntrEnable(DmaInstancePtr, XAXIDMA_IRQ_IOC_MASK,
                                XAXIDMA_DEVICE_TO_DMA);
        XAxiDma_IntrEnable(DmaInstancePtr, XAXIDMA_IRQ_ALL_MASK,
                        XAXIDMA_DMA_TO_DEVICE);


        /*
         * Start DMA TX channel. Transmission starts at once.
         */


        Status = XAxiDma_BdRingStart(TxRingPtr);
                if (Status != XST_SUCCESS) {
                        xil_printf("Status  = %d ",Status);
                        return XST_FAILURE;
                }




        // 开始传输
        Status = XAxiDma_BdRingStart(RxRingPtr);
        if (Status != XST_SUCCESS) {
                xil_printf("Rx start BD ring failed with %d\r\n", Status);
                return XST_FAILURE;
        }
}




int SetInterruptInit(XScuGic *InstancePtr, u16 IntrID)
{


        XScuGic_Config * Config ;
        int Status ;


        Config = XScuGic_LookupConfig(IntrID) ;


        Status = XScuGic_CfgInitialize(InstancePtr, Config, Config->CpuBaseAddress) ;
        if (Status != XST_SUCCESS)
                return XST_FAILURE ;


        Xil_ExceptionInit();
        Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
                        (Xil_ExceptionHandler) XScuGic_InterruptHandler,
                        InstancePtr);


        Xil_ExceptionEnable();




        return XST_SUCCESS ;


}

微信图片_20240401191739.png
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106738
QQ
发表于 2024-4-2 07:40:44 | 显示全部楼层
帮顶。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-3 08:39 , Processed in 0.177931 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表