주요 내용으로 건너뛰기

4. External RAM

개요

이 단계에서는 외부 SDRAM을 활성화합니다. 다양한 해상도에서 내부 RAM에 프레임 버퍼를 배치하기에는 그 크기가 너무 크기 때문에 그래픽 애플리케이션에서는 보통 외부 RAM이 필요합니다. 2~3개의 프레임 버퍼를 사용하는 애플리케이션에서는 외부 RAM이 더더욱 필요합니다.

Note
외부 RAM이 보드 브링업과 관련이 없다면 이 단계를 건너뛰십시오.

프레임 버퍼를 외부 RAM에 배치할 때는 외부 RAM에서 다음을 확인해야 합니다.

  • 읽기와 쓰기가 가능한지 여부
  • 원하는 속도(보통 최대 속도) 로 실행되는지 여부

목표

이 섹션의 목표는 외부 RAM을 활성화하여 여기에서 데이터 읽기 및 쓰기를 수행하는 것입니다.

확인

다음은 이 섹션에서 확인해야 할 사항입니다.

확인사항확인근거
외부 RAM이 읽기 가능한지 여부외부 RAM을 프레임 버퍼 위치에서 사용할 수 있는지 여부
외부 RAM이 쓰기 가능한지 여부외부 RAM을 프레임 버퍼 위치에서 사용할 수 있는지 여부
외부 RAM 성능그래픽 성능이 외부 RAM의 프레임 버퍼에서 수용 가능한지 여부

전제 조건

다음은 이 단계에 대한 전제 조건입니다.

  • RAM 정보(일반적으로 제조사 데이터 시트의 정보)
  • MCU와 외부 RAM 간 연결 정보

실행

외부 SDRAM 컨트롤러는 STM32CubeMX에 Connectivity -> FMC -> SDRAM1 아래에서 구성됩니다.

SDRAM 구성

AHB 클록(HCLK) 은 FMC 메모리 컨트롤러를 위한 참조 클록입니다. "Clock Configuration" 아래에서 클록 주파수를 확인하고, 이를 사용해 다양한 SDRAM 클록 사이클을 계산하세요.

반드시 SDRAM에서 사용되는 GPIO를 모두 구성해야 합니다.

SDRAM GPIO 구성

추가 구성

일부 RAM 칩에서는 추가적인 장치별 구성 작업이 필요합니다. 이러한 구성 작업은 STM32CubeMX에서는 불가능하며 C 코드에서 수행해야 합니다. STM32Cube HAL에는 장치에 명령을 전송하기 위한 함수가 포함되어 있는데, 예를 들면 다음과 같습니다:

main.c
FMC_SDRAM_CommandTypeDef Command;

/* Step 1: Configure a clock configuration enable command */
Command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command.AutoRefreshNumber = 1;
Command.ModeRegisterDefinition = 0;

/* Send the command */
HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT);

RAM 테스트

외부 RAM을 구성한 후에는 이를 테스트해야 합니다. 최소한 다음과 같은 사항을 테스트해야 합니다:

  • RAM이 디버거에 표시되는지 여부
  • RAM이 전체 범위에서 읽기와 쓰기가 가능한지 여부
  • 예상대로 성능이 발휘되는지 여부

메모리 컨트롤러는 유형에 따라 외부 메모리에 대해 고정 주소 매핑을 사용합니다. 주소는 마이크로컨트롤러의 데이터 시트에서 확인하십시오. SDRAM은 보통 0xC0000000(bank1) 또는 0xD0000000(bank2) 으로 매핑됩니다.

RAM이 디버거에 표시되는지 테스트.

RAM이 활성화될 때 첫 테스트로 디버거에서 RAM을 액세스합니다. 이를 통해 메모리에 대한 읽기 및 쓰기 작업의 가능 여부를 간편하게 보여줍니다. 해당 주소에서 메모리 뷰어를 열기만 하면 됩니다.

디버거를 이용해 0xD0000000의 Bank2 에서 메모리 테스트

RAM이 전체 범위에서 읽기와 쓰기가 가능한지 여부

다음 테스트는 외부 메모리에 더 많은 데이터를 쓸 수 있도록 소규모 프로그램을 작성하는 것입니다. 되도록이면 전체 메모리를 테스트하십시오. 이것은 시작점입니다:

uint32_t *externalRAM = 0xC000000;
const uint32_t size = 1000;

//write external RAM
for(int i = 0; i < size; i++)
{
externalRAM[i] = i;
}

이제 디버거에서 메모리를 다시 확인합니다. 이를 통해 일부 주소 핀이 연결 또는 교체되지 않는 경우에 몇 가지 유형의 오류를 밝힐 수 있습니다. 값 패턴을 달리하면서 테스트를 시도해야 합니다. 0, 1, 2, 3 같이 낮은 숫자를 쓰면 일부 데이터 핀의 불량 여부를 밝힐 수 없습니다.

소규모 프로그램을 이용해 메모리를 읽을 수도 있습니다:

uint32_t *externalRAM = 0xC000000;
const uint32_t size = 1000;

//read external RAM
for(int i = 0; i < size; i++)
{
ASSERT(externalRAM[i] == i, "external RAM not as expected");
}

이러한 테스트로 주소의 정확성 여부는 알 수는 없다는 점에 유의하십시오.

모든 메모리 셀을 테스트하십시오. 더 긴 루프를 실행하거나 시작 주소를 변경하는 방식으로 테스트를 수행할 수 있습니다.

예상대로 성능이 발휘되는지 여부

이제, 외부 RAM의 성능을 테스트해야 합니다. 프레임 버퍼가 외부 메모리에 있을 때는 성능이 중요합니다. 메모리 속도가 느리면 시스템의 그래픽 성능이 저하됩니다.

RAM의 읽기, 쓰기 및 수정 속도를 테스트하십시오. 그래픽 애플리케이션에서는 보통 한 메모리에서 다른 메모리로 많은 데이터가 복사됩니다. 그리기 작업 중에는 프레임 버퍼에 대한 쓰기 작업이 많아지고, 디스플레이에 전송할 때는 읽기 작업이 많아집니다. 테스트 프로그램에서 이를 시뮬레이션할 수 있습니다.

volatile uint32_t *externalRAM = 0xC000000;
uint32_t sourcedata[10000];
const uint32_t size = 10000;

int begin = HAL_GetTick();
//write external RAM
for(int i = 0; i < size; i++)
{
externalRAM[i] = sourcedata[i];
}
int end = HAL_GetTick();
int begin = HAL_GetTick();
//Read external RAM
for(int i = 0; i < size; i++)
{
sourcedata[i] = externalRAM[i];
}
int end = HAL_GetTick();

그래픽 소프트웨어는 예를 들어 백그라운드에서 이미지를 블렌딩할 때 프레임 버퍼에서 데이터 읽기 및 쓰기 작업을 수행합니다.

//Time modifying external RAM
int begin = HAL_GetTick();
for(int i = 0; i < size; i++)
{
externalRAM[i] += 2;
}
int end = HAL_GetTick();

메모리 속도와 원하는 정확도에 따라 보다 신뢰할 수 있는 결과를 얻기 위해 테스트를 100회가량 반복적으로 수행할 수 있습니다.

외부 RAM에서 클록이 너무 빠른 속도로 생성되면 읽기 또는 쓰기 작업 중에 잘못된 값이 나올 수 있습니다. 이러한 오류는 간단한 테스트로는 확인이 어려울 수 있지만, 디스플레이에는 표시됩니다.