GPDMA 설정 및 예제

STM32U, STM32H 시리즈부터 GPDMA(General Purposes DMA)가 기본 DMA로 들어가 있습니다. 따라서 앞으로 출시되는 ST MCU에서는 GPDMA가 필수적은 DMA 시스템이 될 가능성이 높습니다. DMA를 사용하셨던 분들이나 앞으로 사용하실 분들은 GPDMA에 대해 필수적으로 알아야 합니다.

 

GPDMA의 핵심은 Linked-list를 통해 다중 블록전송이 가능해졌다는 것입니다. 실례로 I2C로 받은 데이터를 UART를 통해 소프트웨어 개입없이 송출하는게 가능합니다.

 

아래 번역은 ST Employee 가 작성한 "How to configure the GPDMA?" 포스트를 번역해 놓은 것입니다.

 

GPDMA를 구성하는 방법은 무엇입니까?

1. GPDMA 모듈 설정

STM32U5와 같이 시리즈로 제공되는 새로운 DMA 모듈(GPDMA 및 LPDMA 포함)은 일반 DMA와 약간 다릅니다. 이 글에서는 대부분의 STM32 시리즈에서 사용할 수 있는 표준 DMA와 유사한 방식으로 GPDMA를 사용하기 위한 설정에 대해 설명합니다.

2. 애플리케이션의 이점

모든 애플리케이션에서 DMA를 사용하는 주요 이점은 메모리 매핑 소스(Source)에서 메모리 매핑 대상(Destination)으로의 데이터 전송을 위해 CPU의 부하를 오프로드한다는 것입니다. 아래 이미지에서 GPDMA 및 LPDMA와 관련된 전력 도메인을 볼 수 있습니다.


위 이미지에서 볼 수 있듯이 GPDMA에는 2개의 포트가 제공됩니다. AHB 매트릭스 외부에 APB 주변 장치에 대한 직접적인 하드웨어 데이터 경로가 있으므로 일반적으로 주변 장치와의 전송을 위해 Port0을 할당해야 합니다. 반면에 Port1은 일반적으로 메모리와의 전송을 위해 할당되어야 합니다. 어떤 경우든 GPDMA 대상은 모든 포트에서 주소를 지정할 수 있습니다.


고려해야 할 또 다른 흥미로운 요소는 각 채널에 FIFO 크기가 있고 다음 규칙을 따른다는 것입니다. 채널0에서 채널 11까지의 FIFO는 8바이트(2워드)입니다. SRAM(예: UART)을 버퍼로. 채널 12~15에는 32바이트(8워드) FIFO가 있으므로 고속 AHB 주변 장치와 SRAM 간 전송 또는 외부 메모리와의 전송에 더 적합합니다.


자, 이제 기본 사항을 익혔으니 실제 프로젝트에 들어가 어떻게 진행되는지 살펴보겠습니다. 이 부분에서는 NUCLEO-U575ZI-Q 와 함께 STM32CubeIDE (v1.10.1) 를 사용 하지만 이 코드는 GPDMA가 있는 모든 STM32 시리즈로 쉽게 이식될 수 있습니다.

3. 새 프로젝트 만들기

지정된 보드를 시작점으로(Board Default peripheral setting) 사용하여 새 프로젝트를 생성하면 직렬 포트, LED, 키 및 USB를 포함하여 이 보드에 핀이 자동으로 할당됩니다. 보드를 사용하여 처음부터 프로젝트를 생성하는 방법에 대해 의문이 있는 경우 이 정보가 포함된 여러 기사가 있지만 여기에 해당 목적으로 사용할 수 있는 글이 있습니다(최종 5단계).

 

이 글의 내용을 가지고 실습을 할 경우 특정한 GPDMA가 있는 보드를 선택하는 것을 잊지 마세요. 이 데모에서는 UART에만 관심이 있으므로 나머지 부분은 무시하겠습니다.


생성된 *.ioc에서 "Connectivity" 섹션을 찾아 확장하여 VCOM에 연결된 USART1을 선택할 수 있습니다. 여기서는 USART에 대해 상당히 일반적인 설정인 115200/8/N/1을 사용합니다.

4. GPDMA 설정

이제 우리가 정말로 상호 작용하고 싶은 부분은 GPDMA입니다. "DMA 설정" 탭을 클릭하면 GPDMA1로 이동하라는 메시지가 표시됩니다.


GPDMA 채널 선택을 위한 이전 지침에 따라 채널 10과 11을 모두 2워드 FIFO로 할당하고 Standard Request Mode 설정하겠습니다.


드롭 목록 옵션에서 알 수 있듯이 Standard Request ModeLinked List Mode의 두 가지 선택이 가능합니다.

 

Linked List Mode 에 대해 더 자세히 알고 싶고 이를 사용하는 이유는 다음 설명을 참조하세요.

ARM 문서 :
 “Linked list은 List의 다음 요소에 대한 포인터를 포함하는 요소 목록입니다. 이는 요소를 메모리의 어느 곳에나 배치할 수 있고 주변 요소에 영향을 주지 않고 개별적으로 생성 및 제거할 수 있음을 의미합니다. 메모리에 알 수 없는 크기의 배열을 만드는 데 사용할 수 있습니다."

  • Linked list은 DMA 컨트롤러에서 DMACCxLLI 레지스터를 통해 분산/수집을 지원하는 데 사용됩니다. 이는 소스 및 대상 영역이 메모리에서 인접한 영역을 차지할 필요가 없음을 의미합니다. 분산/수집이 필요하지 않은 경우 DMACCxLLI 레지스터를 0으로 설정해야 합니다.
  • 소스 및 대상 데이터 영역은 일련의 연결된 목록으로 정의되며 각 LLI는 한 데이터 블록의 전송을 제어한 다음 선택적으로 추가 LLI를 로드하여 DMA 작업을 계속하거나 DMA 스트림을 중지합니다. 기술 참조 매뉴얼의 부록 C에 예가 나와 있습니다.
  • DMACCxConfiguration DMA 채널 구성 레지스터는 연결 목록 항목의 일부가 아니며 새 LLI가 요청될 때 구성 레지스터가 업데이트되지 않습니다.
  • 또한 DMA 채널이 활성화된 상태에서 DMACCxLLI 레지스터를 프로그래밍하면 예측할 수 없는 부작용이 발생한다는 점에 유의하십시오.

DMA 컨트롤러의 LLI는 소스(Source) 주소, 대상(Destination) 주소, LLI 레지스터 및 제어 레지스터를 순서대로 포함하는 4개의 단어로 구성됩니다. 일부 시스템의 경우 LLI 데이터 구조를 4단어로 정렬하여 LLI 로드를 보다 효율적으로 만들 수 있고 만들어야 합니다. 분산(Scatter)/수집(Gather)을 위해 PL080을 프로그래밍하는 방법에 대한 정보는 Technical Reference Manual의 3-35페이지에 있는 섹션 3.6에 나와 있습니다.
 

5. USART TX 및 USART RX 구성

이제 차이점이 분명해졌으므로 2개의 채널을 구성해 보겠습니다. 하나는 USART TX에 사용되고 다른 하나는 USART RX에 사용됩니다. 두 포트가 모두 동일한 주변 장치와 작동한다는 것을 보여주기 위해 TX는 Port0을 사용하고 RX는 Port1을 사용합니다.
TX에 대한 구성은 다음과 같습니다.


RX 구성은 다음과 같습니다.


이것이 필요한 모든 단계였으므로 이제 코드를 생성할 수 있습니다(Alt+K).
main.c 파일에서 2개의 전역 버퍼를 만듭니다.

/* USER CODE BEGIN PV */
uint8_t pRxBuff[10];
uint8_t pTxBuff[10] = "Count:  \r\n";
/* USER CODE END PV */

메인 함수의 무한 루프 앞에 수신 호출과 메인 루프에서 0..9부터 계산하는 데 사용할 로컬 변수를 추가한 다음 다시 시작합니다.

  /* USER CODE BEGIN 2 */
  HAL_UART_Receive_DMA(&huart1, pRxBuff, 10);
  uint8_t u8Inc = 0x30; // 0x30 => ‘0’ ASCII
  /* USER CODE END 2 */

무한 루프 내에서 5초마다 동일한 메시지를 전송해 보겠습니다.

/* USER CODE BEGIN 3 */
		pTxBuff[7] = u8Inc++;
		if(u8Inc > 0x39){
			u8Inc = 0x30;
		}
		HAL_UART_Transmit_DMA(&huart1, pTxBuff, 10);	  
        HAL_Delay(5000);

마지막으로 10바이트가 수신될 때마다 에코되도록 수신 완료 콜백을 생성합니다.

/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	HAL_UART_Transmit_DMA(&huart1,(uint8_t *) "Message Received!\r\n", sizeof("Message Received!\r\n"));
	HAL_UART_Receive_DMA(&huart1, pRxBuff, 10);
}
/* USER CODE END 4 */

6. 데모 코드 실행

다음은 'Hello ST!!'라고 입력된 메시지를 볼 수 있는 코드 흐름에 대한 간단한 데모입니다. pRxBuff 및 pTxBuff의 메시지를 변경하는 데 사용되는 로컬 변수:


참고로, 혹시 모를 경우를 대비해 STM32CubeIDE를 터미널 기능과 함께 사용하여 위의 데모에서 사용한 데이터를 보내고 받을 수 있습니다.  에서 수행 방법을 확인할 수 있으며, IDE를 어두운 테마로 사용자 정의하려는 경우  다른 기사를 확인하세요.

 

참조 : https://community.st.com/t5/stm32-mcus/how-to-configure-the-gpdma/ta-p/49412

참조 : https://www.infineon.com/dgdl/Infineon-IP_GPDMA_XMC4-TR-v01_01-EN.pdf?fileId=5546d4624ad04ef9014b0780d1fb2266