대학원/대회 준비 관련

[ZCU-104]DMA + DDR 공부 내용

오비루 2024. 5. 28. 15:41
728x90
728x90

https://medium.com/@kavinduvsomadasa/axi-dma-in-scatter-gather-mode-e8c088e334e6

 

AXI DMA in Scatter Gather Mode

Xilinx SoC based FPGA

medium.com

 

 

SG모드의 데이터 전송 방식

데이터 전송을 위해 가장 중요한 요소

  • 데이터
  • 데이터가 저장된 주소

이로써, 해당 주소로부터 데이터를 가져올 수 있는 장치는 저장 장치와 통신 가능하고 데이터를 얻을 수 있다.

SG 모드에서 프로세서는 직접적으로 DRAM에 해당 데이터가 저장된 주소를 제공하지 않는다. 이 주소는 다른 저장 장치인 Buffer Descriptors(BD)에서 제공된다. 각 BD에는 AXI DMA가 DRAM으로부터 데이터를 수신하거나 전송해야 할 데이터에 관련된 세부 정보(가장 중요한 정보 = 데이터 버퍼의 주소 & 길이)가 포함되어 있다.

  • 전송 BD
    • DRAM → DMA로 데이터 전송에 관련이 있음
    • MM2S Channel을 통해 DRAM → DMA로 데이터 받는 것으로 식별될 수 있음
  • 수신 BD
    • DMA → DRAM으로 데이터 전송
    • S2MM Channel을 통해 DMA → DRAM으로 데이터를 전송하는 것으로 식별될 수 있음

하나 이상의 BD를 정의할 수 있으며, 이 BD는 BRAM에 저장될 수 있다. 각 BD는 AXI DMA에 의해 순차적으로 처리되며, 마지막 BD인 tail BD에 도달하면 AXI DMA가 데이터 전송을 중단한다. 전송이 중단되면 Processor는 이미 처리된 BD를 다른 데이터 전송을 위해 업데이트할 수 있다.

다음 sub-system에서는 단일 BD만 사용하기에 BRAM은 BD를 저장하기 위해 구성되지 않았다. 이 경우 BD는 프로세서에서 직접 M_AXI_SG 포트를 통해 AXI DMA에 제공될 것이다.

TxSetup 함수

TxRingPtr = xAxiDma_GetTxRing(AxiDmaInstPtr)

위의 함수는 AXI DMA 드라이버 인스턴스에서 생성한 TxRing에 대한 포인터를 가져온다. 이를 디버그 모드에서 정의된 변수 값은 아래와 같다.

{ChanBase=0x00000000a0000000, 
IsRxChannel=0, 
RunState=2, HasStsCntrlStrm=0, HasDRE=0, 
DataWidth=4, Addr_ext=0, 
MaxTransferLen=0x00003fff, 
FirstBdPhysAddr=0x0000000000000000, FirstBdAddr=0x0000000000000000, LastBdAddr=0x0000000000000000, 
Length=0x00000000, 
Separation=0x0000000000000000, 
FreeHead=0x0000000000000000, PreHead=0x0000000000000000, HwHead=0x0000000000000000, HwTail=0x0000000000000000, PostHead=0x0000000000000000, 
BdaRestart=0x0000000000000000, 
CyclicBd=0x0000000000000000, 
FreeCnt=0, PreCnt=0, HwCnt=0, PostCnt=0, AllCnt=0, 
RingIndex=0, 
Cyclic=0}
Hex: 00000000000114f8, Dec: 70904, Oct: 0212370, At: _el3_stack_end + 0x13b8
Bin: 0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0001,0001,0100,1111,1000
Size: 8 bytes, Type: XAxiDma_BdRing *
Address: 0x114c0

BdRingCreate

각 BD의 life cycle은 다음과 같이 4단계로 구성되어있다.

 

320x100

 

  1. Free
  2. Pre-process
  3. Hardware
  4. Post-process

TxBD의 경우 다음 주소 범위 사이에 메모리 영역을 할당할 것이다.

(다음 과정은 Setup에서 일어나는 과정임)

주어진 메모리 영역에 정의할 수 있는 BD의 수를 확인하기 위해서는 다음 함수를 사용해야 한다.

XAxiDma_BdRingCntCalc(XAXIDMA_BD_MINIMUM_ALIGNMENT,
TX_BD_SPACE_HIGH - TX_BD_SPACE_BASE + 1);

이제 위의 함수를 사용해 주어진 메모리 영역에 정의할 수 있는 BD의 수를 확인했으니 이 BD들로 주어진 BdRing의 세부 정보를 채워보자.

XAxiDma_BdRingCreate(TxRingPtr, TX_BD_SPACE_BASE,TX_BD_SPACE_BASE,
XAXIDMA_BD_MINIMUM_ALIGNMENT, BdCount);

이를 디버그 모드에서 BdRing을 다시 보면, 아래와 같다.

{ChanBase=0x00000000a0000000, 
IsRxChannel=0, 
RunState=2, HasStsCntrlStrm=0, HasDRE=0, 
DataWidth=4, Addr_ext=0, 
MaxTransferLen=0x00003fff, 
FirstBdPhysAddr=0x0000000001000000, FirstBdAddr=0x0000000001000000, LastBdAddr=0x0000000001000fc0, 
Length=0x00001000, 
Separation=0x0000000000000040, 
FreeHead=0x0000000001000000, PreHead=0x0000000001000000, HwHead=0x0000000001000000, HwTail=0x0000000001000000, PostHead=0x0000000001000000, 
BdaRestart=0x0000000001000000, 
CyclicBd=0x000000000000e150, 
FreeCnt=64, PreCnt=0, HwCnt=0, PostCnt=0, AllCnt=64,
RingIndex=0, 
Cyclic=0}
Hex: 00000000000114f8, Dec: 70904, Oct: 0212370, At: _el3_stack_end + 0x13b8
Bin: 0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0001,0001,0100,1111,1000
Size: 8 bytes, Type: XAxiDma_BdRing *
Address: 0x114c0

처음 확인했던 BdRing 생성 전후의 차이점을 확인해 보면,

첫 번째 BD 주소와 마지막 BD 주소가 TX_BD_SPACE_BASE와 동일하게 주어진다.

또한 Allcnt에서 할당 가능한 모든 BD수를 확인할 수 있으며, 프로세서가 이러한 BD를 할당하거나 정의할 수 있기에 할당 가능한 모든 BD가 Free 그룹에 추가된다.

(⇒ 따라서 FreeCnt에 모든 possible BD가 표시된다.)

Pre-Process는 프로세서가 실제로 Free 그룹에서 BD를 할당하거나 정의할 때 발생한다.(프로세서가 Free 그룹에서 BD를 정의할 때 FreeCnt는 감소하고 PreCnt는 증가한다.)

HW는 프로세서가 BD를 정의한 후 AXI DMA가 BD를 가져와서 주어진 BD에 관련된 데이터 버퍼에서 데이터를 읽고 처리하는 경우이다.

Post-Process는 BD를 가져와 처리한 후 프로세서에 의해 업데이트되거나 상태를 확인할 수 있는 경우이다.

이러한 단계를 통해 BD를 사용해 데이터를 DDR에 저장할 수 있따. 각 BD는 DMA가 처리할 데이터의 세부 정보를 제공하기에 DMA 엔진은 데이터를 올바른 주소로 전송 가능하다.

XAxiDma_BdClear(&BdTemplate);

BD = 데이터 버퍼 주소 & 전송할 데이터의 길이를 포함

 

728x90

 

Xilinx User Guides (pg021)_p38

 

각 필드는 32bit로 할당되며 전체적으로 단일 BD를 저장하려면 13*32bit가 필요하다. 그러나 일반적으로 사용자 응용 프로그램 필드를 사용하지 않으며 프로젝트의 경우에도 처음 8개의 필드만 있으면 된다.

모든 필드에 메모리를 할당하기 위해 BD는 16~32bit 워드의 배열로 설계된다.

BdClear function을 사용하면 할당된 BD array의 필요한 필드가 0으로 초기화된다.

XAxiDma_BdRingClone(TxRingPtr, &BdTemplate);

이 함수는 BdTemplate을 Free 그룹의 모든 BD에 복사합니다. (우리의 경우 64개입니다.) 위 함수에 대한 자세한 내용은 xaxibd_ring.c 소스 파일을 참조하십시오.

XAxiDma_BdRingStart(TxRingPtr);

이 함수는 제어 레지스터에서 실행/중지 비트를 1로 설정하고 상태 레지스터에서 중단된 비트를 SG 레지스터 공간에서 0으로 설정합니다.

(레지스터 공간은 AXI DMA의 주요 구성과 관련이 있습니다. - pg021의 12 페이지를 참조하십시오)

디버그 모드에서 확인한 후에는 Tx 채널의 제어 및 상태 레지스터의 변경 사항을 명확히 확인할 수 있습니다.

다음 그림과 같이 디버그 모드에서 확인하면 Tx 채널의 제어 및 상태 Register의 변경 사항을 명확하게 확인 가능하다.

SendPacket

다음으로 중요한 함수는 **sendPacket(XAxiDma *AxiDmaInstPtr)**이다.

XAxiDma_BdRingAlloc(TxRingPtr, 1, &BdPtr);

Free → Pre-Process 그룹으로 이동 시킴

Pre-processing에서 할당된 BD의 가장 중요한 부분인 전송할 데이터 버퍼의 주소 및 데이터 버퍼 길이 설정하는 부분이 나타난다.

XAxiDma_BdSetBufAddr(BdPtr, (UINTPTR) TxArray);
XAxiDma_BdSetLength(BdPtr, MAX_PKT_LEN * sizeof(u32), TxRingPtr->MaxTransferLen);

우리는 하나의 데이터 패킷을 포함하는 프레임만 보내기 때문에 BD에 SOF (프레임의 시작)와 EOF (프레임의 끝)를 설정합니다.

 

XAxiDma_BdSetCtrl(BdPtr, XAXIDMA_BD_CTRL_TXEOF_MASK | XAXIDMA_BD_CTRL_TXSOF_MASK);

Tail Descriptor를 설정하기 전에 BD의 cache 범위를 flush하는 것이 좋음.

이제 전송을 시작하기 위해 tail Descriptor를 다음과 같이 설정해야 한다. 이렇게 하면 AXI DMA가 tail descriptor를 가져올 때까지 BD를 가져올 수 있다.

(Tail Descriptor를 설정하면 데이터 전송이 시작된다.)

XAxiDma_BdRingToHw(TxRingPtr, 1, BdPtr);

 

728x90
반응형