https://medium.com/@kavinduvsomadasa/axi-dma-in-scatter-gather-mode-e8c088e334e6
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단계로 구성되어있다.
- Free
- Pre-process
- Hardware
- 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 = 데이터 버퍼 주소 & 전송할 데이터의 길이를 포함
각 필드는 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);
'대학원 > 대회 준비 관련' 카테고리의 다른 글
[ZCU-104]DMA + echo (0) | 2024.06.11 |
---|---|
[ZCU-104]AXI DMA Scatter Gather (1) | 2024.05.28 |
[ZCU-104] DMA 기본적인 배경 (2) | 2024.04.18 |
[ZCU-104]이미지 파일 전송해서 BRAM에 저장 (4) | 2024.03.23 |
[ZCU-104] Ethernet Echo 통신을 이용한 원하는 데이터 수신 (22) | 2024.03.15 |