본문 바로가기

[STM32F746G-DISCO] SDRAM 사용하기

by rudals.kim 2024. 7. 8. 댓글 개
반응형
아래 테스트는 STM32CubeIDE 1.6.1/STM32Cube_FW_F7_V1.16.1를 사용하여 테스트 되었습니다.


STM32F746G-DISCO보드에서 사용되는 SDRAM은 Micron사의 MT48LC4M32B2 SDRAM을 사용합니다.

MT48LC4M32B2 데이터시트를 살펴보니 아래와 같은 특징이 있습니다.
• PC100-compliant
• Fully synchronous; all signals registered on positive edge of system clock
• Internal pipelined operation; column address can be changed every clock cycle
• Internal banks for hiding row access/precharge
• Programmable burst lengths: 1, 2, 4, 8, or full page
• Auto precharge, includes concurrent auto precharge and auto refresh modes
• Self refresh mode (not available on AT devices)
• Auto refresh
– 64ms, 4096-cycle refresh (commercial and industrial)
– 16ms, 4096-cycle refresh (automotive)
• LVTTL-compatible inputs and outputs
• Single 3.3V ±0.3V power supply
• Supports CAS latency (CL) of 1, 2, and 3

MT48LC4M32B2 SDRAM은 1 Meg x 32 x 4 Banks(128Mbit = 16MBytes)로 구성되어 있습니다.
1Meg는 row(12bit) + col(8bit) = 총 20bit 입니다. 즉 2^20 = 1048576 (1048576/1024/1024 = 1Mbit, 32는 32bit의 데이터 라인을 의미하며 4는 4개의 뱅크를 가지고 있다는 의미입니다.

아래는 SDRAM의 state diagram입니다.
위쪽 4개의 연한 파란색의 원으로 되어 있는 부분은 SDRAM 초기화 관련 부분이며 초기화가 완료된 후 사용 가능한 idle상태로 진입합니다. (초기화 관련 코드는 stm32746g_discovery_sdram.c의 BSP_SDRAM_Initialization_sequence 함수를 참고하시면 됩니다.)

이 상태에서 요청 상태에 따라 refresh/active/read/write/precharge 등의 동작이 이루어집니다.

STM32CubeIDE에서 새 프로젝트를 생성 후 핀 초기화 후 SYS/RCC/USART1/FMC 부분만 설정하였습니다.

이전 게시글들의 클럭 설정은 내부 RC 클럭을 사용했었는데 FMC를 위해 안정적인 HSE를 Enable 시킨 후 HCLK를 200MHz로 설정하였습니다.

FMC는 SDRAM1을 사용하도록 설정하였습니다.
(이곳에서 설정한 SDRAM 속성 값은 실제 사용되지 않으며 stm32746g_discovery_sdram.c에 있는 다른 초기화 코드로 대체됩니다. 자세한 내용은 아래 부가적으로 설명하도록 하겠습니다.)

코드를 생성 후 main 함수를 보면 SDRAM 초기화를 위해 MX_FMC_Init 함수가 호출됩니다.

이 함수를 살펴보면 단순히 FMC 관련 설정만 초기화를 합니다. 그러나 SDRAM을 사용하기 위해서는 FMC 관련 포트, 클럭, SDRAM 초기화등의 설정이 더 필요한데 MX_FMC_Init 함수에서는 이러한 동작을 하지 않습니다.

STM32Cube_FW_F7_V1.16.1에서 제공되는 SDRAM 예제를 살펴보면 MX_FMC_Init 함수 대신에 BSP_SDRAM_Init함수를 사용하고 있습니다.

이 함수에서는 포트/클럭/SDRAM 초기화 같은 함수를 호출되고 있으며 이 함수만 사용하면 쉽게 SDRAM을 초기화할 수 있어서 MX_FMC_Init함수 부분을 주석 처리한 후 BSP_SDRAM_Init 함수를 추가하여 초기화하도록 main 함수 부분을 수정하였습니다.

/* Initialize all configured peripherals */
MX_GPIO_Init();
//MX_FMC_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart1, (uint8_t*)rxBuf, (uint16_t)RBSIZE);
BSP_SDRAM_Init();
sdram_test();
/* USER CODE END 2 */


아래는 sdram_test 함수로 stm32746g_discovery_sdram.h 파일에 정의되어있는 SDRAM_DEVICE_ADDR 주소에 데이터를 쓰고 다시 읽어 들여 두 버퍼를 비교하는 함수입니다. (SDRAM_DEVICE_ADDR는 0xC0000000로 정의되어있습니다.)

void sdram_test(void)
{
  int i = 0;
  uint32_t error = 0;

  for (i=0; i<BUFFER_SIZE; i++ ) {
    srcBuf[i] = i;
  }

  /* Write data to the SDRAM memory */
  BSP_SDRAM_WriteData(SDRAM_DEVICE_ADDR, srcBuf, BUFFER_SIZE);
  printf("Write data to the SDRAM memory\r\n");

  /* Read back data from the SDRAM memory */
  BSP_SDRAM_ReadData(SDRAM_DEVICE_ADDR, dstBuf, BUFFER_SIZE);
  printf("Read back data from the SDRAM memory\r\n");

  for (i=0; i<BUFFER_SIZE; i++ ) {
    if(srcBuf[i] != dstBuf[i])
      error++;
  }

  if(error == 0)
    printf("SDRAM Test: PASSED\r\n");
  else
    printf("SDRAM Test: FAILED\r\n");
}


빌드 후 실행해 보면 SDRAM 영역에 쓴 메모리와 다시 읽어 들인 메모리가 동일하므로 SDRAM이 정상적으로 동작됨을 확인할 수 있습니다.

 

반응형

댓글