|
本帖最后由 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 ;
}
|
-
|