MCU나 SoC에서 외부 NOR/NAND 플래시를 제어할 때 어떤 명령어 흐름으로 동작하는지에 집중해서 정리한다. 아래는 일반적인 SPI NOR Flash 기준이지만, NAND나 병렬 NOR에서도 기본 개념은 유사하다.

⸻
<커맨드 시퀀스 정리>
Flash Device는 레지스터 기반이 아닌, 명령어(command)를 SPI 또는 병렬 버스를 통해 전송해서 제어한다. 따라서 플래시를 제어하려면 특정 커맨드 시퀀스를 정확히 따라야 한다. 각 동작별 기본적인 명령 흐름은 다음과 같다.
⸻
1. 읽기(Read)
목적: 특정 주소에서 데이터를 읽는다.
시퀀스:
[READ CMD] + [ADDRESS] → [데이터 수신]
• 일반적인 커맨드: 0x03 (Standard Read), 0x0B (Fast Read)
• 입력: 3 or 4바이트 주소
• 출력: 원하는 바이트 수 만큼 연속해서 읽을 수 있음
예시:
0x03 A2 A1 A0 → (optional dummy byte) → D0 D1 D2 ...
⸻
2. 쓰기(Program)
목적: 특정 주소에 데이터를 기록한다.
시퀀스:
[WRITE ENABLE CMD] → [PAGE PROGRAM CMD] + [ADDRESS] + [DATA]
• WRITE ENABLE (WREN) 커맨드: 0x06
• PAGE PROGRAM 커맨드: 0x02
• 보통 한 페이지(256 bytes)까지 가능, 경계를 넘으면 잘림
예시:
0x06 → 0x02 A2 A1 A0 D0 D1 ... Dn
※ 쓰기 후에는 상태 레지스터(Status Register) 확인이 필요하다.
⸻
3. 지우기(Erase)
목적: 특정 블록 또는 전체를 0xFF로 초기화
시퀀스:
[WRITE ENABLE CMD] → [SECTOR ERASE CMD] + [ADDRESS]
• SECTOR ERASE: 0x20 (4KB), 0xD8 (64KB), 0xC7 or 0x60 (Chip Erase)
• 실제로는 수 ms 소요되며, 진행 중에는 Busy 상태
예시:
0x06 → 0x20 A2 A1 A0
⸻
4. 상태 확인(Status Check)
목적: 쓰기/지우기 완료 여부 확인
시퀀스:
[READ STATUS REGISTER CMD] → [STATUS BYTE]
• 커맨드: 0x05
• 출력: 상태 바이트(보통 bit 0 = WIP, Write-In-Progress)
반복 확인 예시:
do {
send 0x05 → read status
} while (status & 0x01);
⸻
5. 쓰기 보호/잠금 제어
• 0x04: Write Disable
• 0x50: Volatile SR Write Enable
• 0x01: Write Status Register
이런 커맨드들을 통해 Status Register의 Block Protection bit 등을 제어한다.
⸻
6. 제조사 고유 커맨드
일부 플래시는 다음과 같은 고유 커맨드를 제공한다:
• JEDEC ID 읽기: 0x9F → 플래시 제조사, 종류, 용량 확인
• UID 읽기: 0x4B, 0x5A 등 (제조사별 다름)
• Quad Enable 설정: 특정 플래시는 Status Register의 특정 bit를 설정해야 QSPI 사용 가능
⸻
전체 플로우 요약
데이터 쓰기 전체 흐름 예:
0x06 // Write Enable
0x20 A2 A1 A0 // Erase 4KB
< 처리 기다림 >
0x06 // Write Enable again
0x02 A2 A1 A0 D0...Dn // Page Program
< 처리 기다림 >
⸻
<NAND Flash는 ECC, Bad Block 관리 필요>
• 커맨드는 유사하지만, 페이지/블록 단위 크기가 더 크고 복잡하다
• ECC가 필수이고, Bad Block Table(BBT) 관리 필요
• 명령 예: 0x00 + ADDR → 0x30 (읽기), 0x80 + ADDR + DATA → 0x10 (쓰기)
⸻
마무리
커맨드 기반으로 동작하는 플래시 메모리는 단순한 버스 접근보다 더 복잡한 순서를 필요로 한다. 특히 Write Enable → 명령 실행 → 상태 확인 이라는 3단계 구조는 거의 모든 플래시 동작에 공통적이다.
FlexSPI, QSPI 등 컨트롤러가 있는 경우 이 커맨드 시퀀스를 LUT(Look-Up Table)에 설정해서 자동화할 수 있으며, 직접 SPI를 제어하는 경우 이 순서를 코드로 명확히 구현해야 한다.
'임베디드' 카테고리의 다른 글
DMA(Direct Memory Access) 에 대해서 (0) | 2025.04.19 |
---|---|
Trace32 디버깅에 대해서 (0) | 2025.03.23 |
GDB 디버깅에 대해서 (0) | 2025.03.22 |
Endianess란 무엇일까? Big-Endian 과 Little-Endian (0) | 2025.03.21 |
ARM Exception Level(EL) 알아보기(2): EL2(하이퍼바이저)와 EL3(보안 모드) (0) | 2025.03.19 |