FX10 외부 QSPI 플래시 복구: 잘못된 bitstream 뒤 정상 기록이 실패한 문제
팀에서 만든 잘못된 bitstream을 FX10 외부 QSPI 플래시에 기록한 뒤, Efinity USB
프로그램으로 정상 bitstream을 다시 넣으려 해도 작업이 실패했습니다. 화면에는
erase가 완료된 것으로 보였지만, 새 데이터를 쓴 뒤 읽어 비교하는 단계에서 오류가
났습니다. 잘못된 bitstream이 Configuration Register 3의
CR3NV[3]을 건드려 sector mode를 hybrid로 바꿨지만, 기존
programmer는 계속 uniform mode를 전제로 erase 범위를 계산한 것이 원인이었습니다.
이 글은 그 실패 위치를 해석해 플래시를 복구하고, 정상 firmware와 bitstream을
다시 기록한 과정입니다.
1. 문제 상황
팀에서 만든 잘못된 bitstream을 외부 QSPI 플래시에 한 번 기록한 뒤 문제가
시작됐습니다. 이후 Efinity USB 프로그램으로 정상 bitstream을 다시 넣으려고
했지만, 프로그램은 erase가 완료됐다고 표시한 뒤 page index 2에서
기록을 멈췄습니다.
오류는 새 데이터를 쓴 뒤 읽어 비교하는 단계에서 나타났습니다. 즉, 기존 내용을
지우고 올바른 firmware와 bitstream을 다시 기록하는 다음 단계까지 도달하지
못했습니다. 먼저 host와 센서 레지스터도 확인했지만 장치 연결과 제어는
정상적이어서, 원인을 외부 QSPI 플래시의 erase와 기록 과정으로 좁혔습니다.
이후 잘못된 bitstream이 CR3NV[3]을 변경해 flash를 hybrid mode로
바꾼 반면, programmer는 uniform mode를 전제로 동작하고 있음을 확인했습니다.
page index 2를
읽어 비교하는 단계에서 값이 맞지 않았습니다.
2. 오류 로그에서 확인한 내용
Total number of sectors to erase : 82
Successfully erased 82 sectors
Total number of bytes to be written : 5343105
Total number of pages to write : 2609
Read buffer mismatch for page index : 2
Failed to write into page index : 2
Firmware download failed
이 프로그램은 데이터를 2 KiB씩 나누어 기록했고 index는 0부터 시작했습니다.
따라서 세 번째 블록인 page index 2는 주소 0x1000에서
시작합니다. 이 지점부터 읽기 비교가 반복적으로 실패한다는 사실을 보고, 플래시 앞부분이
실제로 지워졌는지와 0x1000이 어떤 erase 단위에 속하는지를
확인했습니다.
3. 0x1000에서 실패한 이유: sector 모드
sector mode가 관리하는 것
NOR flash는 임의의 주소 한 바이트씩 지우는 메모리가 아닙니다. 주소 공간을 sector라는 구간으로 나누고, erase는 그 구간 단위로 수행합니다. sector mode는 플래시 앞부분을 어떤 크기의 sector들로 나눌지를 정하는 flash map입니다. 따라서 프로그램은 현재 mode를 알아야 특정 주소를 지울 때 어디부터 어디까지 하나의 erase 단위인지 올바르게 계산할 수 있습니다.
이 계열 QSPI NOR flash에는 앞부분을 4 KiB sector들로 세분화하는 hybrid mode와,
앞부분 구분 없이 전체를 64 KiB 단위로 구성하는 uniform mode가 있습니다. 이 선택은
Configuration Register 3의 CR3NV[3] bit에 저장됩니다.
0은 hybrid, 1은 uniform 구성을 뜻합니다.
잘못된 bitstream을 기록하는 과정에서 이 register bit가 바뀌면서 flash의 sector
mode가 hybrid로 변경됐습니다. 하지만 기존 programmer는 이 변화를 확인하지 않고
uniform 구성을 전제로 erase 범위를 계산하고 있었습니다.
bitstream이 바꾼 hybrid sector map과 programmer의 uniform 가정이 충돌했습니다.
flash의 실제 erase 단위는 hybrid map을 따르고 있었지만 programmer는 uniform
map으로 주소를 계산했습니다. 그 결과 erase 성공 메시지와 달리
0x1000의 기존 데이터가 남았습니다.
그래서 Successfully erased 82 sectors라는 표시만으로는
0x1000이 포함된 앞부분이 실제로 지워졌다고 볼 수 없었습니다.
해당 위치를 다시 읽어 보니 이전 데이터가 남아 있었습니다. NOR flash는 지워지면
모든 bit가 1, 즉 0xFF가 됩니다. 남은 데이터 위에 새
데이터를 기록하면, 다시 읽은 값이 원본과 달라져 이번과 같은 read buffer
mismatch가 발생합니다.
4. 해결: flash를 직접 지운 뒤 다시 기록
제가 직접 만든 복구 helper로 CR3NV[3]과 현재 flash map을 확인한 뒤
실제 erase 범위를 처리했습니다. bitstream에 의해 바뀐 hybrid 영역을 uniform
sector처럼 가정하지 않고 실제 sector 구성에 맞춰 플래시를 지운 뒤, 문제가 났던
0x1000을 포함한 앞부분을 다시 읽어 0xFF 상태인지
확인했습니다.
확인이 끝난 뒤에는 정상 firmware를 다시 올리고, 마지막으로 정상 bitstream을 기록했습니다. 이 순서로 복구한 뒤에는 같은 위치에서 기록이 멈추지 않았습니다.
5. 해결 검증
0x1000을 포함한 주소에서 0xFF 상태를
확인했습니다. 확인 뒤 정상 firmware와 정상 bitstream을 순서대로 기록했습니다.
programmer의 uniform 가정에 erase 검증을 맡기지 않고, helper가 hybrid map을
기준으로 0x1000을 포함한 주소를 직접 읽어 모두
0xFF인지 확인했습니다. 그 뒤 정상 firmware와 정상 bitstream을 다시
기록했으며, 이후 FX Control Center에서 firmware download와 bitstream 기록이
정상적으로 완료됐습니다.
6. 정리
이번 문제의 직접적인 원인은 잘못된 bitstream이
CR3NV[3]을 변경해 sector mode를 hybrid로 바꿨는데도, 기존
programmer가 uniform flash map을 계속 전제로 사용한 것이었습니다. 이 사례는
프로그램이 표시한 erase 성공 메시지와 실제 플래시 상태가 다를 수 있으며,
외부 flash의 실제 주소 map과 programmer의 erase 단위가 맞지 않아도 기록 오류가
발생할 수 있음을 보여줬습니다.
이번에는 page index 2를 0x1000 주소로 바꾸고,
CR3NV[3]이 나타내는 현재 sector mode와 그 주소가 속한 erase 구간을
함께 확인하면서 원인을 좁혔습니다. 전공에서 다뤘던 주소 계산과 메모리 map 개념을
실제 장비의 복구 과정에 적용해 볼 수 있었습니다. 이후에는 erase 완료 표시만 믿지
않고, 현재 flash map에 맞춰 필요한 주소를 다시 읽어 0xFF 상태를
확인한 다음 정상 firmware와 bitstream을 기록했습니다.
NRV 장비 개발 과정에서 직접 확인하고 해결한 내용을 개인 기술 노트로 정리했습니다. 제품별 firmware와 flash 구성은 달라질 수 있으므로 실제 장비의 부품 번호와 설정을 함께 확인해야 합니다.