MCU
|
STM32F746G DISCOVERY(ST)
|
IDE
|
Atollic(TrueSTUDIO), STM32CubeMX
|
목표
|
외부 SDRAM 추가
|
1. SDRAM External memory interface
1) STM32F746 DISCOVERY SDRAM Pin map(자세히는 MB1191 참고)

2) SDRAM signals
SDRAM signal
|
Port
|
I/O
type |
Description
|
Alternate function
|
SDCLK
|
PG8
|
O
|
SDRAM clock
|
-
|
SDCKE[1:0]
|
PC3
|
O
|
SDCKE0 : SDRAM Bank 1 Clock Enable
SDCKE1 : SDRAM Bank 2 Clock Enable |
-
|
SDNE[1:0]
|
PH3
|
O
|
SDNE0: SDRAM Bank 1 Chip Enable
SDNE1: SDRAM Bank 2 Chip Enable |
-
|
A[12:0]
|
A0~A11
|
O
|
Address
|
FMC_A[12:0]
|
D[31:0]
|
D0~D15
|
I/O
|
Bidirectional data bus
|
FMC_D[31:0]
|
BA[1:0]
|
PG5,PG4
|
O
|
Bank Address
|
FMC_A[15:14]
|
NRAS
|
PF11
|
O
|
Row Address Strobe
|
-
|
NCAS
|
PG15
|
O
|
Column Address Strobe
|
-
|
SDNWE
|
PH5
|
O
|
Write Enable
|
-
|
NBL[3:0]
|
PE1,PE0
|
O
|
Output Byte Mask for write accesses
(memory signal name: DQM[3:0]) |
FMC_NBL[3:0]
|
2. STM32CubeMX : SDRAM 추가
- 'Clock Configuration' Tab으로 이동
1) HCKL = 216MHz

- 'Pinout & Configuration' Tab으로 이동
1) Connectivity - FMC 선택

2) SDRAM1 선택
3) Clock and chip enable : SDCKE0 + SDNE0(PC3, PH3)
SDCKE0 기본 할당 PH2 → PC3으로 변경

4) Internal bank number : 4 banks(BA0, BA1)
5) Address : 12 bits(A0 ~ A11 ; 최대 13 bits)
6) Data : 16 bits
7) Byte enable : 16-bit byte enable

2. SDNRAS,SDNCAS,SDCLK는 회로도와 동일하게 자동 할당
1) column addr : 8bit(A0 ~A7)
2) row addr : 12bit(A0 ~A11)
3) CAS latency : 3 memory cycles(100MHz 이상 동작시)
4) write protection : disabled
5) SDRAM CLK = HCLK/2=108MHz(max 143MHz)
6) burst read : Disabled
7) read pipe delay : 1 HCLK clock cycle

8) Load mode register to active daly : 2
9) Exit self-refresh delay : 7
10) Self-refresh time : 4
11) SDRAM common row cycle delay : 7
12) write recovery time : 3
13) SDRAM common row precharge delay : 2
14) Row to column delay : 2

- GENERATE CODE 클릭
- FMC만 설정한다고 SDRAM을 바로 쓸수 있는게 아니고 SDRAM을 초기화 해줘야 하는데 여기서는 bsp sdram library를 사용함
- BSP library를 프로젝트 폴더에 넣고 시작할것

3. ATOLLIC 실행
1) C/C++ General > Paths and Symbols > Includes > GNU C에 BSP 폴더 추가

2) C/C++ General > Paths and Symbols > Source Location에 BSP 폴더 추가

3) BSP_SDRAM_Initialization() 수정
: Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1으로 되어있는지 확인
void BSP_SDRAM_Initialization(uint32_t RefreshCount)
{
__IO uint32_t tmpmrd =0;
/* 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);
/* Step 2: Insert 100 us minimum delay */
/* Inserted delay is equal to 1 ms due to systick time base unit (ms) */
HAL_Delay(1);
/* Step 3: Configure a PALL (precharge all) command */
Command.CommandMode = FMC_SDRAM_CMD_PALL;
Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command.AutoRefreshNumber = 1;
Command.ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT);
/* Step 4: Configure an Auto Refresh command */
Command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command.AutoRefreshNumber = 4;
Command.ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT);
/* Step 5: Program the external memory mode register */
tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 |
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
SDRAM_MODEREG_CAS_LATENCY_3 |
SDRAM_MODEREG_OPERATING_MODE_STANDARD |
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
Command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command.AutoRefreshNumber = 1;
Command.ModeRegisterDefinition = tmpmrd;
/* Send the command */
HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT);
/* Step 6: Set the refresh rate counter */
/* Set the device refresh rate */
HAL_SDRAM_ProgramRefreshRate(&hsdram1, RefreshCount);
}
4) main.c 수정
: BSP_SDRAM_Initialization(REFRESH_COUNT); 호출
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
#define SDRAM_ADDRESS 0xC0000000
/* USER CODE BEGIN 2 */
BSP_SDRAM_Initialization(REFRESH_COUNT);
5) Linker Script 수정
: SDRAM 추가
- SDRAM 사용 예제를 찾아보면 SDRAM 주소에 직접 데이터를 쓰는 경우를 봤는데, 변수 한두개도 아니고 64Mbit 용량을 주소에다가 직접 사용하는건 비효율적이라고 본다.
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 320K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K
SDRAM (xrw) : ORIGIN = 0xC0000000, LENGTH = 8M
}
Compile시에 아래와 같이 SDRAM이 할당된 것을 확인 할 수 있다.

6) 실제로 SDRAM에 변수를 사용하기 위해서 .bss를 SDRAM에 할당하자.
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >SDRAM
이게 잘 될까? 결론부터 얘기하면 동작하지 않는다.
SDRAM 초기화에 사용하는 변수중에 .bss로 할당 되는 변수가 있는데, SDRAM에 변수를 할당해야 하는데 SDRAM은 초기화가 되지 않았다? 아직 집을 짓지도 않았는데, 그 집주소에 택배를 보내는 꼴이다.
그러면 어떻게 해야 하나?
1. Bootloader로 SDRAM을 살리고 본 프로그램에서 변수를 SDRAM에 할당
2. 내가 쓰고자 하는 소스가 있는 폴더만 SDRAM에 할당 하도록 함
여기서는 2번 방법에 대해 설명한다. 아래와 같이 링커 스트립트를 수정하면, USER 폴더 안에 있는 소스의 모든 변수는 SDRAM에 할당 된다.
.bss_sdram :
{
. = ALIGN(8);
_sbss_sdram = .;
*USER* (.bss .bss* COMMON)
. = ALIGN(8);
} >SDRAM
/* Uninitialized data section into "RAM" Ram type memory */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss section */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM
Debug 폴더 안의 map 파일을 열어보면 USER 폴더안의 소스의 변수 'flag_filter'가 SDRAM에 할당 된것을 확인 할 수 있다.
.bss_sdram 0x0c010000 0x4
0x0c010000 _sbss_sdram = .
*USER*(.bss .bss* COMMON)
.bss.flag_filter
0x0c010000 0x4 USER\temp.o
0x0c010000 flag_filter
0x0c010004 _ebss_sdram = .
0x0c010004 . = ALIGN (0x4)
.bss 0x20000074 0x1fc
0x20000074 _sbss = .
0x20000074 __bss_start__ = _sbss
*(.bss)
'ST > STM32F746DIS' 카테고리의 다른 글
STM32F746G DISCOVERY - LCD + TOUCH (0) | 2025.04.19 |
---|---|
STM32F746G DISCOVERY - LCD I/F (0) | 2025.04.19 |
STM32F746G DISCOVERY - TIM(IC, OC, PWM) (0) | 2025.04.19 |
STM32F746G DISCOVERY - TIMER (0) | 2025.04.19 |
STM32F746G DISCOVERY - UART(DMA) (0) | 2025.04.19 |