개발

jackryu 2009. 5. 12. 16:42

 

falinux 유영창님의 글을 스크랩해왔습니다.

(http://forum.falinux.com/zbxe/?document_srl=406218)

 

 

랄랄랄...

강좌를 오랫만에 쓰니 은근히 즐겁네요
이거 몇일이나 갈까요? 흠..

어째든 리눅스에서 NAND 플래쉬를 다루기 위한 강좌를 진행하겠습니다.

제 실력이 워낙 허접해서리
중급 이상의 임베디드 리눅서나 실력있는 하드웨어 엔지니어들은 쨉싸게 이 강좌를
닫고 다른 좀더 수준높은 강좌를 찾아가 주세요 제발~~

이제 남은 분들은 초보자 들임을 가정하고 글을 쓰겠습니당.
(에혀 자꾸 습자가 읍자로 써지네 , 옛날 한글 교육세대의 비애로다... )

여러분이 임베디드 시스템을 하다보면 반드시 듣게되는 것이 플래쉬 메모리입니다.

플래쉬 메모리가 뭐냐구요?

뭐 그 있잖습니까?

USB 메모리...

그거 안에 있는 것이 플래쉬 메모리 입니다.

근디 이 플래쉬 메모리에는 두가지 종류가 있습니다.

NOR 하고 NAND라고 하는 플래쉬 메모리입니당.

이 두가지의 차이점을 초보자용 풀이를 하면요

NOR과 NAND 플래쉬 와의 차이점NOR는 PC 안에 있는 바이오스 롬 처럼 쓸수 있고요, NAND는 하드 디스크 처럼 쓸 수 있습니다.

(웬지 비유가 더 어렵당 ㅜㅜ )

이왕 강좌를 쓰는 김에 NOR와 NAND가 어떤 것의 약자인가를 찾아 볼까요?

이럴때는 저는 www.google.co.kr 이나 네이버를 찾아 봅니다.

허거덕... 별뜻이 없군요... 참내...

NAND 는 Not AND 즉 논리 회로중 NAND 회로를 의미합니다.


NOR 는 Not OR 즉 논리 회로중 NOR 회로를 의미합니다.

뭔가 특별한 다른 뜻을 가진 단어 인줄 알았는데 ... 별거 없군요 ㅜㅜ

하지만 앞에서 이야기 했듯이 동작하는 방법은 두가지가 정말 다릅니다.

어쨌든 NAND 가 되었든 NOR 가 되었든 이 두가지는 모두 플래쉬 메모리 입니다.

자 플래쉬 메모리가 일반 메모리와 다른 점은 뭘까요?

ROM 이야 읽기 전용 메모리라고 알고 있고
RAM 이야 읽고 쓸수 있는 메모리라고 알고 있습니다.

그렇다면 Flash 메모리는 ?

예 읽고 쓸수 있습니다.
또 전원이 꺼져도 내용이 지워지지 않습니다.

오호 이런면으로 보면 RAM 보다 좋아 보이네요 ?
ROM하고 같아 보이고요...

근디 안 좋습니다. ㅡㅡ;

RAM은 일단 고속으로 읽고 쓸수 있습니다만

플래쉬 메모리는 읽고 쓰는 속도가 저속입니다
요즘의 발빠른 프로세서 못 따라 갑니당 ㅜㅜ

또한 NAND의 경우 읽는 방법이 아주 복잡(?) 합니다.

플래쉬에 쓰는 방법은 솔찍히 G랄 같습니다. (여기는 한글로 G랄이 안 써지는 군요. ㅡㅡ;)

도대체 제가 왜 이렇게 투덜거릴까요?

하나씩 알아봅시다.

아직도 제어용 8비트 컨트롤러에 ROM이 많이 쓰입니다.

그런에 이 롬에는 여러가지 타입이 있었습니다.

제가 처음 하드웨어를 만지던 시기에는

ROM에 프로그램을 써 넣으려면 먼저 ROM을 지워야 했습니다.

ROM 중에 웃기게도 유리창이 달린 놈이 있었습니다.

이런 롬은 자외선을 유리창에 비춰서 칩에 썬텐(?)을 해야 했습니다. ㅋㅋ

음식점에서 사용하는 형광등중에 자외선 형광등 있잖습니까...

그거로 지워야 했습니다. 보통 30분이상 지워야 하기 땜시

보드의 디버깅 과정에서 기다림이 많았지요

덕분에 제가 좋아 하는 무협지 많이 봤습니다.

핑계 좋지 않습니까?

롬 지우는 중이라 무협지 본다고 ㅋㅋ

사장님, 아무 소리 못했습니다. 음하하..

다 지워진 롬은 롬 라이터라는 놈으로 프로그램을 써 넣습니다.

보통 이때 롬이 뜨끈 뜨끈 해지거든요..

그래서 롬에 프로그램을 써 넣는 것을 롬 굽는다고 했답니다.

그런데 나중에 EEPROM 이라고 하는 놈이 나옵니다.

이놈은 전기적으로 지워 버리죠...

그래서 롬을 지우는 시간이 짧습니다.

덕분에 그 뒤로는 무협지 못 읽었습니다. ( 삶에 낙이 없어져 버렸다는 이야그 입니다. ㅜㅜ )

이렇게 전기적으로 지우지만 지울때의 전압과 읽을때의 전압이 다릅니다.

보통 지우고 쓸때는 12V 또는 24V 를 사용하고 읽을때는 5V를 사용합니다.

뭐 용량도 무척 작습니다.

아직까지도 이런 롬이 쓰입니다. LAN 카드나 기타 디바이스의 정보 저장용으로도 쓰입니다.
컨트롤러용으로도 쓰입니다.

정보 저장용은 읽고 쓸때 I2C 라는 방식으로 많이 쓰고요
아마도 다른 강좌에서 이에 대한 내용을 쓸겁니다.

제어용은 현재 계속 ROM 형식을 사용합니다.

어쨌든 이런 것들을 ROM 이라고 하는데

이런 메모리는 보통 보드의 부팅과 동작을 위한 프로그램 용으로 사용합니다.

이런 ROM 이 발전한것이 바로 플래쉬 메모리 입니다.

플래쉬 메모리는 EEPROM과 비슷합니다.

하지만 몇가지 차이가 있습니다.

여기서 잠깐 ROM이 어떤식으로 동작하는지 봅시다.

왜냐하면 이런 동작 방식은 플래쉬와 같기 때문입니다.

ROM은 내부에 퓨즈가 있는 것으로 보면됩니다.

퓨즈가 뭐냐구요?

에헤라....

거 있잖습니까...

전기가 과열되면 끊어지는 거...

역쉬 세대차이가 나는 군요..

요즘은 두꺼비집이 없다보니 휴즈가 없는 경우가 많죠...

어쨌든 열이 나면 녹아 없어지는 납줄이 그겁니다.

근데 ROM은 이런 퓨즈가 연결되어 있을때 즉 끊어지기 전 상태를 1 로 봅니다.
반대로 끊어져 있으면 0 으로 봅니다.

그래서 ROM에 프로그램을 써 넣는다는 것은 1 상태는 무시하고 0 인상태인 경우에 해당하는
퓨즈를 끊어 버리는 겁니다.

예를 들어 8 비트 데이터가 있다고 합시다.

00101011

이 각 비트당 하나의 퓨즈가 할당되는데

퓨즈가 연결되어 있으면 1 이고 끊어지면 0 이므로 0 에 해당하는 퓨즈만 끊어 버리는 거죠..

그렇다는 이야기는

ROM을 지운후에 읽어 보면 모두 11111111 로 읽힌다는 거죠

쯕 모두 0xFF 로 읽히면 제대로 지워진 겁니다.

이렇게 연결된 퓨즈중 0으로 만들기 위해서 끊어버리는 것이 데이터를 써 넣는 행위가 되는 겁니당

끊긴 퓨즈를 다시 연결하려면 자외선을 쬐 주거나 높은 전압을 가해서 연결해 버리는 겁니다.

이것을 롬을 지운다고 합니다.

플래쉬도 ROM 과 마찬가지로 이렇게 지우는 과정이 필요한거죠...

그래서 플래쉬를 지우면 모두 11111111로 읽히게 됩니다.

프로그램을 써 넣는 다는 것은 ROM과 마찬가지로 0으로 만드는 부분만 끊어 버리는 거죠..

뭐 끊는다는 표현이 딱 맞는 표현은 아니지만 어쨌든 이렇게 지우고 씁니다.

그런데

잘 생각해 봅시다.

이렇게 지울때....

한꺼번에 지우게 되지요...

각각 특정 비트만 지울수가 없는 겁니다.

지우게 되면 통짜로 지우게 되기 땜시 RAM 처럼 쓸수 없는 겁니다.

물론 지우는 속도도 느리지만요...

그래도 다행인것은 플래쉬는 전체를 모두 지우지 않고 일정한 크기 단위로 지울수 있어서
약간의 숨통을 띄어 놓았다는 거죠...

자 이제 정리해 봅시다.

플래쉬 메모리는 ROM 과 같은 특성를 갖지만 단일 전원으로 지울수도 있고 읽을수도 있습니다.
또한 써 넣을수도 있습니다.

보통 플래쉬 메모리에 행하는 행동을 다음과 같이 이야기 합니다.

READ : 읽기
ERASE : 지우기
PROGRAM : 데이터 써 넣기 또는 프로그램 써 넣기

그래서 플래쉬 메모리는 다음과 같은 순서로 사용합니다.

1. ERASE
2. PROGRAM
3. READ

참! 플래쉬에는 지우지 않고 쓸수 있는 방법이 있기는 있습니다.
하지만 그 제약이 너무 엄청나서 쓰지 않습니다.

아까 원리를 설명 했죠?

퓨즈를 끊으면 0으로 된다고

그래서 이런 경우라면 또 쓸수 있죠

처음에 써 넣는 데이터가 00110010 이라고 하고
다시 써 넣는 데이터가 00010010 이라고 하면

1 이 0으로 바뀐는 경우이므로

또 써 넣을수 있습니다.

근디 누가 이렇게 사용하겠습니다.

꼼꼼한 개발자이거나 상황이 최악인 경우 아닌다음에야..

저같은 게으른 사람은 절.....대.....로.... 시도 하지 않습니다.

하지만 쓰는 분들이나 프로그램이 있다는 것은 기억해 주기 바랍니다.

오늘은 여기까지만 ...

손가락이 아프네요 ㅜㅜ

 

 

 

 

 

 

 

 저번 강좌에서 대략 플래쉬 메모리의 개념을 잡아 보았습니다.

그냥 플래쉬 메모리가 어떤것인가라는 감을 잡아보려고 쭈욱 썼던 내용이죠

하지만 우리는 리눅스에서 NAND 플래쉬 메모리를 다루어 보려는 것 아니겠습니까?

그런 고로 좀더 기술적인 내용을 알아야 겠죠?

이제 머리에 띠하나 둘르고 강좌를 읽어 주시기 바랍니다.

조금 어려워 집니다.

자... 자...

플래쉬 메모리는 3가지 동작이 있다고 했죠?

지우기, 쓰기 , 읽기

플래쉬 메모리 레퍼런스 메뉴얼에는 당근

erase, program , read 이런 식으로

설명되어 있습니다.

그러므로 저 역시 이런식으로 글을 써 나갈 것입니다.

이레이즈, 프로그램, 리딩.. 험험...

어.. 쩄.. 뜬 ... 알아서 읽어 주쇼...

아참... 잠시 딴길로 나갔다 와야 겠습니다.

이전 강좌에서 플래쉬 메모리에는 NOR 와 NAND 형이 있다고 말했습니다 .

우리가 관심을 갖는것은 NAND 형이지만 아무래도 NOR에 대해서도 조금 알고 넘어 가야 겠죠?

NOR 형 플래쉬 메모리는 읽을때는 ROM하고 똑같습니다.

쓸때만 플래쉬 메모리의 특징을 가집니다.

그래서 NOR 형 플래쉬는 보드 부팅용 프로그램을 담기 위해서 사용합니다.

대부분의 컨트롤러들은 부팅할 때 ROM이 필요하죠

그렇다고 요즘 처럼 대용량의 기억장치가 필요한 프로세스들에게
옛날의 64K 짜리 롬을 달수는 없지 않습니까?

그래서 이런 컨트롤러에 NOR형 플래쉬를 다는 겁니다.

NOR형 플래쉬에 대표적인 업체는 인텔사입니다.
그외에 인텔의 경쟁사인 AMD 가 있겠죠...
그외 도시바나 대만에서도 생산 합니다. 뭐 하이닉스나 삼성도 생산하는지는 잘 모르겠습니다만
아무래도 만들겠죠? IT 대국인데 ㅋㅋ

어쨌든 여러분은 그냥 NOR 형 플래쉬는 인텔,AMD 가 있다고 생각하시는 것이 편합니다.
가장 흔하거든요..

아무래도 개발자들은 남들이 쓰는 것을 쓰는 것이 심리적으로 안심이 되니까요.

그래도 제품은 대만산을 씁니다. 가격이 싸서리...

NOR 형은 읽을때는 ROM이지만 쓸수도 있다고 했습니다.

플래쉬 메모리니깐 당근 단일전원으로 쓸수 있습니다.

그런데 플래쉬 메모리를 ROM으로 사용해서 프로그램이 동작한다면
자기 자신이 돌고 있으므로 플래쉬에 무언가 쓰는 행위가 불가능합니다..

오호 그러면 아무 쓸모가 없잖습니까?

벗!!!

이렇게 생각하면 현대의 프로세스 흐름에 뒤쳐져 있음을 바로 들어내는 겁니다.
한마디로 무...식...한...거...죠

제가 이전에 플래쉬 메모리는 무척 느리다고 했잖습니까?

이게 무신 소리냐 하면

최근에 프로세서들은 최하가 50M Hz이고 보통 200M Hz에서 돕니다.

그런데 이런곳에 플래쉬 메모리에서 프로그램을 동작하도록 사용하면
프로세스의 속도를 전혀 활용하지 않고 16M 짜리 프로세서로 만들어 버리는 겁니다.

이 얼마나 슬픈일입니까...

근디 요즘 보드들은 램을 8M , 16M , 32M, 64M 이렇게 빵빵하게 답니다.

이램이 그냥 램이냐?

아닙니다. SDRAM 이라고 100M Hz 의 속도를 내는 고속 램입니다.
더구나 최근에는 임베디드 프로세스의 램에도 DDRAM 이 대세로 돌아 서고 있습니다.
DDRAM 은 SDRAM 보다 2배나 더 빠릅니다.

그래서 보드에서 동작하는 프로그램은 플래쉬 메모리에서 램에다 옮겨 놓고 씁니다.
그래서 프로세서의 속도를 제대로 활용하기 때문입니다.

즉!

프로그램이 플래쉬 메모리에서 동작하는 순간은 부팅순간이라는 거죠...

그뒤로는 모두 램에서 돕니다.

근데.............

지금 부터 하는 이야기는 정신 바짝 차리고 기억하십시오...

NOR 플래쉬에 무언가를 쓰려고 시도하면 ( 정확하게 쓰기모드로 진입 )
그 순간부터는 ROM이 아니고 그냥 장치일 뿐입니다.
이때부터는 무언가 쓰거나 지울수 있는 거죠
절대로 ROM이 아닙니다.

이런 상태에서 다시 ROM 으로 동작하기 위해서는 두가지 방법이 있습니다.

하나는 NOR 플래쉬 메모리의 RESET 핀에 리셋 신호를 인가하는 방법이고
또 하나는 ROM으로 동작하게 하기 위한 명령을 플래쉬 메모리에 써 넣는 겁니다.

이런 이유로 잘못 설계된 하드웨어는 보드가 부팅이 안될수 있습니다.

그게 뭐냐고요?

자 한번 상황을 만들어 봅시다.

보드에서 동작하는 프로그램이 플래쉬 메모리에 무언가 데이터를 기록하기 위해서
플래쉬 메모리를 쓰기 모드로 전환했습니다.

근데 이때 보드가 부팅 되었습니다.

문제는 하드웨어 설계하시는 분의 게으름으로 플래쉬 메모리 쪽의 RESET 신호가 처리 되지 않았습니다.

그런면 어떻게 되죠?

예 맞습니다. 먹통 됩니다. 전혀 부팅이 되지 않습니다.
이럴때 보드는 조금 오랫동안 전원을 내렸다가 키면 보드 재 부팅 됩니다.

이런 경험이 있다면 한번 여러분의 보드상에 플래쉬 메모리의 RESET 핀 쪽에
연결이 되어 있는가를 살펴봐 주십시오

자 또 다른 상황을 알아 봅시당.

리눅스 운영체제의 디바이스 드라이버에서 사용하는 것 또는 펌웨어의 인터럽트 서비스 루틴을 이용해서
플래쉬 메모리에 데이터를 쓰고 있습니다.

당근 플래쉬 메모리에 데이터를 쓰려고 하는 프로그램과 써지는 시점은 일치 하지 않을 수 있습니다.

이때 리부팅 처리를 합니다.

문제는 리부팅 처리를 하는 경우 플래쉬 메모리를 읽기 모드로 돌려 놓지 않고
웜 부팅 ...

즉 하드웨어적인 RESET 신호가 발생하지 않고 자체 프로세스만 리셋상태로 전환되면?

당근

보드 먹통됩니다.

이런 경우가 없다구요?

당신은 정말 행운아시군요...

어쨌든 NOR 플래쉬 메모리를 다룰때는 이런 경우를 고려해야 합니다.

솔찍히 NOR 플래쉬 메모리는 좀 비쌉니다.
더구나 인텔거 대따 비삽니다.

근디 요즘 임베디드 장비들 저장용 메모리 용량 엄청 큰거 요구합니다.
그거 맞추려고 하면 단가 꽤 올라갑니다.

그래서 저장용 메모리는 NAND 사용합니다.

이게 NAND 플래쉬 메모리 하면 그냥 삼성 생각하시면 됩니다.

워낙 핸드폰, MP3, 네비게이터 등등이 많이 사용하니깐

가격 쌉니다.

그래서 삼성은 잔머리를 굴리게 됩니다.

그게 뭐냐?

바로 NAND 부팅이라는 아이디어를 내 놓는 겁니다.

어쨌든 최근의 프로세서에는 플래쉬 메모리를 저장 장치로 이용하고
부팅용으로만 쓰입니다.

그렇다면 그쪽 시장도 노려 볼수 있는 거지요

그런데 기존 프로세서들은 이 NAND 부팅이라는 것이 없지요

그래서 삼성 프로세서 즉 S3C2410 이나 S3C2440 에 NAND 부팅을 지원하도록 한 겁니다.

즉 NAND 플래쉬만으로도 부팅이 되게 하는 거지요

일전에도 말했지만 NAND 는 읽는 방법이 복잡합니다.

그래서 프로세서안에 아주 작은 RAM을 집어 넣습니다.

그리고 프로세서가 부팅하고 NAND 부팅 모드 이면

자체적인 하드웨어 로직으로 NAND 의 첫번째 블럭만 읽어 오게 만들어서
그걸 RAM 에 옮깁니다.

보통 이 크기가 4K 정도 되는데 이정도면 충분하게 프로세스를 초기화 하고
NAND의 부트 프로그램을 램에다 옮길수 있는 프로그램을 만들수가 있는 겁니다.

이렇게 하면 앞에서 이야기한 NOR 플래쉬의 ROM 동작을 흉내 낼수 있고
가격이 싼 NAND 플래쉬를 사용할수 있는 겁니다.

그래서 최근의 프로세서들은 NAND 부팅을 지원합니다.

근디

인텔은 자체적으로 NOR 플래쉬 시장을 놓치기 싫어서
아직도 NAND 부팅을 지원하지 않습니다.

그냥 NOR 플래쉬를 사용하도록 하고 있습니다.

하지만 최근에 가격적인 측면 때문에 많은 업체들은 NAND 부팅을 선호 합니다.

대용량의 NAND 플래쉬가 계속 값 싸게 공급되고 굳이 부팅용 NOR 플래쉬를 쓰지 않아도
되므로 차지하는 면적이 적어지기 땜시 ...

여기서 한걸음 더 나아가 삼성에서는

지들이 만드는 3가지 솔루션

프로세서 와 SDRAM 과 NAND를 하나의 칩처럼 보이게 하는
프로세서를 판매하고 있습니다.

뭐 이름이 MSP 뭐라나 하는 겁니다.

뭐 아직은 가격이 쪼금 비쌉니다.

하지만 면적이 무척 작아서 작은 컨트롤러를 만들어야 하는 경우라면

최고의 솔루션이죠..

어쨌든 삼성 잔머리 많이 굴립니다. ㅋㅋ

아하

점심 시간이 다 되었네요

오늘의 강좌도 여기서 정지...

 

 

 

 

 

전 여름이 싫습니다.

제 체질이 더우면 버티기 힘든데

요즘은 후덥지근까지 하고 ...

그나마 회사에는 에어콘 빵빵해서 좋은데..

밖에 돌아 다니려면 정말 짜증나네요

여름분 여름 감기 조심합시당..

잡설은 고만하고

좀더 NAND 플래쉬 메모리에 대해서 알아보죠....

솔찍히 리눅스 디바이스 드라이버를 다룰려고 하는데

웬 NAND 플래쉬에 대한 이론이 거창하냐고 물으실지 모르지만

리눅스 디바이스 드라이버의 개념이 잡힌 이후

디바이스 드라이버를 작성하려면 다루려는 장치를 정확하게 이해해야 작성이 가능합니다.

즉 디바이스 드라이버의 기초를 공부하는 것은 C 언어 문법을 이해하는 것이고

실제로 프로그램을 작성하기 위해서는 해당 시스템이나 작성하려는 분야에 정통해야 하는것과 같습니다.

그래서 프로그래머들이 만물 박사가 되어 가는 것이 아니겠습니까...

알아야 짜니깐...

저는 프로그램을 작성할때 가장 중요시 하는 것중 하나가 왜? 라는 질문입니다.

도대체 리눅스 디바이스 드라이버의 MTD의 구조체는 왜 이런 모양이 되었을까?

하는 질문을 던지고 난후

나같으면 어떻게 작성할까를 생각하고 보면 훨씬 이해가 쉽기 때문입니다.

리눅스 디바이스 드라이버의 구조체는 해야할 일의 완결편이라고 보시는 것이 좋습니다.

그래서 하드웨어를 이해하면 리눅스 디바이스 드라이버의 구조체를 정확하게 알수 있습니다.

어찌 되었건간에....

NAND 플래쉬를 알아 봅시다.

일단 NAND 플래쉬는 NOR 플래쉬와 다르게 ROM 으로 사용 못합니다.

가장 비슷하게 닮은 놈이 하드디스크 입니다.

아래의 [그림 3-1 Hard Disk 와 Flash Memory 구조]을 참고하세요.

여러분이 가장 익숙한 하드 디스크라는 놈을 살펴보면 섹터 단위로 입출력을 합니다.

즉 한 섹터를 읽거나 쓰게 됩니다.

NAND 플래쉬도 이와 비슷하게 되어 있습니다.

NAND 플래쉬는 섹터와 비슷한 것으로 페이지라는 것이 있습니다.

섹터의 크기가 보통 512 이듯이 NAND의 페이지도 512 입니다.

아..

물론 이 크기는 요즘 나오는 플래쉬들은 다른 놈들이 생겼습니다만

일단 NAND 플래쉬를 이해 하려면 단순화 시키는 것이 좋으므로

그냥 한 페이지는 512 의 크기를 갖는다고 생각하십시오

하드 디스크는 섹터들이 모여서 하나의 트랙을 구성합니다.

마찬가지로 NAND 플래쉬도 512 바이트의 페이지를 모아서 블록이라는 것을 가지고 있습니다.


[그림 3-1 Hard Disk 와 Flash Memory 구조]

이렇게 서로 상당히 유사한 형태를 가지기 땜시..

USB 메모리 장치로 NAND 프래쉬 메모리를 사용하는 겁니다.

다루기가 유사하거던요...

하드 디스크와 NAND 플래쉬와 유사한 점이 또 있습니다.

바로 데이터를 읽고 쓰는 방식입니다.

일반적인 하드웨어 장치라면 항상 어드레스 버스와 연결되어서 레지스터 형태로 데이터를 읽고 씁니다.

하지만 NAND 플래쉬는 이런식으로 원하는 데이터를 읽거나 쓰지 못합니다.

하드 디스크 역시 마찬 가지 입니다 IDE 인터페이스에 연결된 하드 디스크라면

읽고 쓸때 읽기 위한 명령을 지정하거나 쓰기 위한 명령을 지정합니다.

마찬가지로 NAND 플래쉬도 원하는 데이터를 쓰거나 읽기 위해서는

NAND 플래쉬 장치에 데이터를 쓰기 위한 명령을 이용해야 하고 읽기 위한 명령을 이용해야 합니다.

그래서 NAND 플래쉬의 하드웨어적인 신호는 이런 명령을 처리 하기 위한 구조를 갖습니다.

일단 하드 디스크에 특정 섹터를 읽어 온다고 합시다.

이런 경우 당연하게 하드 디스크에 읽겠다는 명령을 전송하고 읽을 섹터 번호를 지정한후에 데이터를 읽어 와야 합니다.

반대로 하드 디스크에 데이터를 쓰기 위해서는 데이터를 쓰겠다는 명령을 지정하고

써 넣을 섹터를 지정하고 데이터를 씁니다.

이런 행위가 끝나면 당연히 데이터가 정상적으로 쓰여 지거나 읽을수 있는지를 검사 하게 되죠...

이런 과정은 NAND 플래쉬 역쉬 마찬가지 입니다.

자...

대충 전체적인 설명이 끝냈으니 좀 더 구체적으로 살펴 봅시다.

이제 부터가 진짜지요 ^^

아...

외부 약속 시간이 다 되었군요.. 쩝

구체적인 것은 내일 써야 할 듯 합니다.

 

 

강좌를 매일 아침에 시간 내서 쓰기로 했는데...

항상 뭔가 일이 생기는 구먼요.. 쩝쩝

오늘은 NAND 플래쉬에 대한 것을 실제적인 모습을 살펴 보기로 합니다.

일단 대상이 있어야 이해가 쉽겠죠?

뭐 알다시피 제가 에프에이 리눅스 라는 회사 기술 이사이다 보니

당근 사용 대상 하드웨어도 저희 회사가 즐겨 사용하는 플래쉬를 이용해야 겠죠?

현재 저희 보드에 가장 많이 장착된 플래쉬 메모리는 삼성에 생산되는 것입니다.

뭐 NAND 하면 삼성, 메모리 하면 삼성 아니겠습니까?

일단 설명하기 위해 사용되는 NAND 플래쉬는

64M 용량을 갖고 입출력 데이터 버스는 8 비트이고 페이지 크기는 512 입니다.

모델명은 K9K1208U0A 이란 불리고 있습니다.

일단 이 놈의 외관을 봅시당..


[그림3-2] NAND 핀 설명

그림을 보시면서 느끼는 것 있습니까?

예... 다리 열라 많습니다.
더구나 다리 폭 무척 열라 작습니다.

이거 하드웨어 디버깅 할때 스팀 만땅 됩니다.

가난한 회사의 스코프 끝은 항상 두껎습니다.

초보자들 이 핀에 스코프 단자 들이 밀때 열 받습니다.

그나마 다행인것은 핀들의 대부분들이 NC 라는 점입니다. ㅋㅋ

아마 NOR 였으면 각 핀들의 기능이 모두 살아 있을 겁니다. NAND 만쉐이....

핀 이름을 다시 살펴 봅시당.

뭐 하드웨어 고수들이라면 핀 명칭만 봐도 느낌이 팍!팍! 오겠지만...

이 강좌는 초보 대상이지 않습니까?

그러므로 제가 수고스럽게 자세하게 설명해야죠? 흠흠...

일단 N.C No Connection 즉 연결할 필요가 없는 핀들이라는 의미 입니다.
즉 신경 쓸 필요가 없다는 것이죠...

그 다음...VCC - Power

이거 전원 신호 입니다. 3.3V 죠....

그 다음... VSS - Ground

일반적으로 그라운드를 이야기 할때 GND 라고 표기들을 많이 합니다.
그런데 이렇게 VSS라는 표현도 쓰죠 ...

같은 이야기 입니다.

즉 0V 라는 이야기 입니다.

그 다음.. CE - Chip Enable

이 핀은 말이죠...

모든 하드웨어 장치에는 있는 핀이죠.. 즉 해당 하드웨어를 CPU가 사용하겠다고 표시를 하는 핀인데...
보통 네거티브 로직으로 동작 합니다. 그래서 실제로는 이렇게 표기 합니다.

nCE

회로도에서 표기 할때는 보통 CE 위에 윗줄을 긋습니다.

이 신호는 일반적인 다른 하드웨어 장치와 달리 처리 합니다.

이후 강좌에서 이 부분을 잘 설명할겁니다.

여기서 잠깐

프로그래머인 우리가 참이라고 하는 것은 보통 0 이 아닌 상태를 의미 합니다.
디지털 회로에서 참에 대한 표현도 역시 0 이 아닌 1을 사용합니다.
디지털 회로에서 1 이라는 것은 5V 난 3.3V 의 전압 레벨로 표현합니다.
그렇다면 무언가 동작 시킨다는 것은 우리는 보통 상식적으로 참으로 익식하므로
칩선택 같은 것은 당근 참값 신호로 주어야 하지 않겠습니까?

근데 여기서 경제 논리가 나옵니다.

그게 뭐냐...

칩이 선택되는 신호를 인식하는 회로를 구성할때
참 논리로 선택하게 하고 이를 인식하는 것보다. 부논리로 하는 것이 회로적으로 간단해 집니다.
그래서 CS 즉 칩선택 신호같은 것을 부 신호로 만드는 것이 더 유리 하다는 것이죠...

물론 옛날에 그랬다는 이야기 입니다. 지금은 그런 부분이 많이 약해졌지만
어쨌든 부논리 신호가 더 쉽게 구현이 되는 것은 변함없는 사실입니다.

그래서 CS 도 부논리가 되겠끔 설계되어서 nCS 와 같이 표기 하게 되죠
그외 RESET 같은 것도 마찬가지로 리셋을 건다는 것이 사실이므로
참논리가 맞겠지만 현실적인 이유로 nRESET 과 같이 만들어 버립니다.

이제 이것이 전통이 되어서 칩 선택은 당연히 부 논리 즉 0V 신호가 인가되면
선택되는 것으로 된거죠 이것이 네거티브 로직입니다.

여기서 문제가 되는 것은 엔지니어들이 혼란 스러워 하는 것입니다.
회로를 설명할때 보통 동작시킨다는 개념이 참인데 그것을 거짓으로 설명해야 하니깐..
뭔가 동작 시킨다는 개념과 그에 따른 적용 상태를 분리할 필요가 있는 거죠...
그래서 나온 말이 ACTIVE 와 DEACTVIE 입니다.

아...아... 영어의 비애가 다시 느껴지는 부분입니다.

우리나라말로 하면 활성화 비 활성화라는 건데..
미국 놈들은 지들 말이라 다른 늬앙스가 있어서 잘 알아 듣습니다.

즉 무언가 선택하거나 동작 시키거나 허가 하거나 하는 모든 말을 뭉뚱그려서 ACTVIE 라고
하고 ACTIVE 의 반대를 DEACTIVE 라고 하는 겁니다.

영어 메뉴얼을 읽을때 이런 부분이 나오면 활성화라고 이해하셔도 되고 동작 시킨다라고 이해하셔도 됩니다.
이렇게 동작시킬때 로직은 부정이냐 참이냐를 또 설명하게 되죠..
즉 칩을 선택을 Aactive 하려면 FALSE State 가 되어야 한다라고 표현하게 됩니다.
이런 경우 신호에는 n자를 앞에 붙이게 되는게 통례이고요 회로상에는 글짜 위에 윗줄을 그어서 표기하게 됩니다.

잘 칩 선택신호인 CE 에 대해서 봤으니 당연히 생각나는 신호 읽기 쓰기 신호를 찾아 봐야죠...

RE - Read Enable , WE - Write Enable

이것도 네거티브 로직입니다.

즉 nRE 와 nWE 로 표기되어야 정상인거죠...

NAND 플래쉬에서 무언가를 읽으려면 nRE 신호를 LOW 즉 0V 로 떨어 트려야 읽을수 있고
무언가를 쓰려면 nWE 신호를 LOW 즉 0V로 떨어 트려야 쓸수 있습니다.

이에 대한 자세한 이야기는 다음 강좌에서 신호 시그날을 설명할때 자세하게 이야기 하겠습니다.

평상시에는 두 신호는 HIGH 즉 3.3V를 유지 하고 있어야 합니다.

플래쉬 메모리는 프로그램에 의해서 쓸수 있습니다만 경우에 따라서 프로그램의 오동작에 의한
잘못된 자료가 써 지는 것을 강제로 방지 할 필요가 있을수 있습니다.

이때 사용하는 것이 바로 WP - Write Protect 즉 쓰기 금지 신호 선입니다.

이것 역시 네거티브 로직입니다. 즉 nWP 라고 표현되어야 합니다.

근디 실제로 이 핀은 대부분의 하드웨어에서는 그냥 HIGH 즉 3.3V를 걸어 버립니다.
쓸일이 거의 없다는 거죠...

읽기 전용으로만 사용해야 하는 특수한 경우 아니면 그냥 무시하는 핀입니다.

자 그리고 CPU에서 NAND 플래쉬에 데이터를 넣거나 빼기 위한 무언가의 통로가 필요하겠죠?

그게 다음 신호 입니다. I/O0 ~ I/O7 - Data Input/Outputs

총 8 비트의 데이터 버스 신호 입니다.

이 신호는 보통 D 라고 표기 하기도 합니다.

자 이제까지는 일반적인 하드웨어 신호와 유사 합니다.

근데 가만히 보니 무언가 이상하죠?

예 .... 눈치 채신분이 있겠지만

어드레서 버스 입력 핀이 없습니다.

그것참...

없죠?

대신에 다음과 같은 2 개의 핀이 있습니다.

이전 강좌에서 이야기 했죠?

데이터를 읽거나 쓸때의 순서..

자 다시 한번 기억해 보세용...

읽기 부분을 기억해 봅시당

읽기 명령을 전달하고
읽을 주소를 전달하고
읽을수 있는 상태를 확인하고
데이터를 읽는다.

오호..

이를 위한 핀이 다음입니다.

CLE - Command Latch Enable
ALE - Address Latch Enable
R/B - Ready/Busy output

명령을 전달하려면 CLE 핀을 HIGH 로 놓고 데이터 버스에 명령을 써 넣으면 됩니다.
주소를 전달하려면 ALE 핀을 HIGH로 놓고 데이터 버스에 주소를 써 넣으면 됩니다.

읽을 수 있는 상태를 확인하려면 R/B 핀을 사용하면 됩니다.

그리고 마직막으로 실제 플래쉬 데이터를 읽으려면 CLE와 ALE를 둘다 LOW상태로
놓고 데이터 버스에서 읽으면 됩니다.

쉽죠? ㅋㅋ

이와 관련된 타이밍은 다음 강좌에 자세하게 써 넣을 겁니다.

참...

R/B는 엄밀히 이야기 하면 이렇게 표기되어야 합니다. R_nB

무언가 바쁘면 0이고 평상시에는 HIGH 가 되어야 한다는 야그 입니다.

 

 

 

 

 

 

강좌를 쓰다보면 글 투가 가끔 무협지 나 판타지 체가 나올때가 있네요 ㅜㅜ
(제가 무협지하고 판타지 소설 무지 좋아 하거덩요... 이해해 주세용)

자...

오늘도 들어가 보죠...

하루마다 쓰니깐 내용을 다 써야 한다는 압박감이 없어서 좋군요... ㅋㅋ

저번 강좌에 하드웨어 핀 사양에 대해서 알아 봤죠...

JTAG 같은 프로그램을 작성하려면 이 핀에 인가되는 신호 시그널 타이밍도가 무척 중요하죠...

그래서 이 부분도 설명을 하려고 하지만

그 이전에 NAND 플래쉬의 내부 구성에 대한 이해가 조금 필요합니다.

그래야 어떤식으로 제어해야 하는지 감을 잡거든요..

NAND 플래쉬 메모리는 크게 두 분으로 나누어 져 있습니다.

기억을 저장하고 유지하는 부분과 이를 꺼내거나 써 넣도록 제어하는 로직 부분이죠...

자 그림을 봅시당.


[그림 3-3] NAND 플래쉬 내부 구조

아주 심플한 그림 한장 그렸습니다.

보시면 알겠지만 외부 버스와는 제어부와 연결되고 제어부는 다시 내부 메모리 셀과 연결되어 있습니다.

이 제어부는 일종의 컨트롤러와 같다고 보시면 됩니다.

메모리 셀을 지우고 데이터를 써 넣고 데이터를 읽어서 버스에 전달하는 기능을 담당합니다.

이 제어부에 무언가를 지시하기 위해서는 명령을 사용해야 합니다.

이 명령은 조금 있다가 살펴보고

이 메모리 셀은 가장 기초 단위는 BIT 입니다 즉 연결 상태 또는 끊김 상태를 가지게 됩니다.

이걸 회로적으로 보면 다음과 같은 그림이죠...


[그림 3-4] NAND BIT 구조

혹시 이 회로에 대해서 자세하게 설명해 달라고는 하지 마세요 ㅜㅜ

저도 잘 모르고 과시용으로 그냥 NAND 가 어떻다는 등의 기술적인 글 처럼 보이려고 붙여 놓은 거니깐

반도체 제조에 관심이 많은 분들은 인터넷을 뒤져 주세용.. ( 휘리릭~~~ )

우린 비트는 관심을 끕시당. 프로그래머 입장에서는 그냥 이런 비트들이 8 개 모여서 바이트 단위로
제어 한다고 보면 되니깐...

자 다시 설명을 진행하면

1비트 셀들을 8 개 모여 놓고 이를 바이트 라고 하는 단위로 묶습니다.

이 바이트 단위의 셀들을 다시 256 바이트 단위로 묶는데 이를 Half Page 라고 합니다.
이 Half Page 를 다시 2 개 묶어서 Page 라고 하죠 ...

여기서 제조사들은 덤으로 16 바이트를 더 줍니다.

그래서 앞에서 제가 한 페이지는 512 바이트라고 박박 우겼지만 그건 하드 디스크와 비교하기 위해서 그런것이지
제가 절대로 몰라서 그런것 아닙죠 ( 정말입니다. ㅜㅜ )

어쨌든 이렇게 page들을 다시 여러개 묶어서 블록이라고 합니다. 이 블록이 바로 플래쉬 메모리 지우기의 기본 단위
라는 겁니다.

이런 블록이 다시 모여서 전체 플래쉬 메모리가 된다는 야그 입니다.

이걸 그림으로 봅시당..


[그림 3-5] 내부 구조

그림을 보면서 정리해 보죠...

NAND 플래쉬 메모리는 내부적으로 여러 블록으로 나누어져 구성되어 있습니다 .
이 블록들은 다시 PAGE라는 영역으로 나누어져 구성되어 있습니다.
PAGE 는 다시 512 바이트 + 16 바이트 로 나누어져 있습니다.

지우기 단위는 블록이고 읽고 쓰는 단위는 페이지 입니다.

실제로 페이지가 항상 512 + 16 이지는 않습니다.
NAND 플래쉬 마다 조금 씩 다릅니다. 하지만 가장 보편적인 크기가 512 입니다.

하나의 블록이 몇 페이지를 가지고 있는지 역시 NAND 플래쉬 마다 틀립니다.

하나의 NAND 플래쉬 메모리 에 몇개의 블록이 있는가 역시 NAND 전체 용량에 따라 달라집니다.

제가 강좌의 예제로 다루고 있는 것은 다음과 같습니다.

Page = 512 + 16 : 읽고 쓰는 기본 단위
Block = 32 Pages : 지우는 기본 단위
전체 = 4096 Blocks : 전체 용량

이렇게 됩니다.

아항 벌써 저희 회사 점심시간인 1시네요.. 쩝

그림 그리다 시간 다 갔습니다.

조금더 내부 구조를 보면서 어떻게 접근 하는 지를 설명하기 위해서는
내일로 시간을 미뤄야 겠군요...

그럼...

 

 

 

 

맘은 항상 하루에 한편씩 쓰자고 먹는데
쩝..

꼭 일이 생겨서 맘같지 않네요...
오전 시간에 시간내서 강좌를 쓰고 있는데

꼭 오전에 일이 생겨요 ㅜㅜ

어쨌든 가능하면 계속 고고씽~~~

저번 강좌에 플래쉬 메모리 셀 구조에 대해서
설명을 했는데 이번에는 제어부 구조를 살펴보죠

NAND 플래쉬 메모리 레퍼런스 매뉴얼을 보면 다음 그림과 같이 설명을 하고 있습니다.

[그림 3-6] NAND 기능 구조

플래쉬 메모리는 이전 강좌에서 설명했듯이 페이지, 블록 구조를 갖고 있습니다.
이에 반해서 이 플래쉬 메모리를 쓰거나 읽거나 지우는 것을 지원하기 위한 구조는 좀 더 복잡합니다.

그림 처럼 여러가지 버퍼와 레지스터가 있습니다.

그림을 보면 제어부는 크게 3가지 부분으로 나누어져 있다고 보면 됩니다.

  • 첫째가 명령 레지스터 입니다.
  • 둘째가 주소 선택 레지스터 입니다.
  • 셋째가 페이지 레지스터입니다.

각각의 레지스터는 데이터 버스인 I/O 와 연결되는데
데이터 버스가 어떤 레지스터와 연결될지를 결정하는 것은 ALE, CLE 입니다.

CLE 가 HIGH 이면 I/O 데이터버스는 명령 레지스터에 연결됩니다.
ALE 가 HIGH 이면 I/O 데이터버스튼 주소 선택 레지스트에 연결됩니다.

CLE와 ALR 가 LOW 이면 페이지 레지스트에 연결된다고 생각하시면 됩니다.
(아닐 경우도 있기 때문에 이렇게 얼버무리는 겁니다. ㅜㅜ )

자 이걸 다루는 프로세서 하드웨어들은 어떻게 제작될까요?

뭐 일일이 각각의 CLE 와 ALE 그리고 nCE 를 GPIO 에 연결하고
데이터 버스와 R/W 신호핀을 연결하는 구조로 만드는 경우가 있겠죠...

흠 이런 경우에는 당근 GPIO 를 직접 다루기 땜시 일일히 CLE 올리고 내리고
같은 행위를 합니다.

좀 느리죠...

그림으로 보면 다음과 같은 그림이 됩니당.


[그림 3-7] NAND 연결 예 1(GPIO)

현실적인 이유에서 보통 R/nB는 신호는 사용하지 않습니다.
이 부분은 나중에 제어와 관련된 내용을 자세하게 설명할겁니다. ^^

이런 방식은 속도가 좀 느리기 땜시 조금 복잡하게 회로를 구성해서 연결합니다.
대부분 이런 방식을 사용합니당...


[그림 3-8] NAND 연결 예 1(버스 선택 회로)

이런 방식은 다음과 같은 주소가 존재하는 방식입니다.

  • nCS 를 HIGH 로 만드는 주소
  • nCS 를 LOW로 만드는 주소
  • 명령을 써 넣는 주소
  • 주소를 써 넣는 주소
  • 데이터를 써 넣는 주소

저희 회사에서 만드는 보드중 NAND 컨트롤러를 프로세서에서 지원하지 않을 경우
에 이런 회로를 만들어 씁니다.

마지막은 아예 프로세서가 위 방식의 컨트롤러를 지원하는 방식이죠

제일 편하겠죠?

삼성 계열이 이런 식으로 되어 있습네다...
(삼성이 NAND를 만들지 않습니까 그러니 당근 지원해야죠...)

일단 NAND 칩에 접근 하려면 nCE 를 LOW 상태로 만들어야 합니다.

일반적인 디바이스들은 쓰거나 읽는 순간만 nCE 단자를 활성화 시키는 것과 다르게.

NAND 플래쉬 메모리에 무언가를 하려면 접근할때는 nCE 단자를 계속
LOW 상태로 놓고 작업하고 작업이 끝나면 HIGH 상태로 돌려 높습니다.

이렇게 칩 제어를 시작하는것을 NAND Start 라고 합니다.
반대로 칩 제어가 끝난 상태를 NAND End 라고 합니다.

원래 올렸다 내렸다 해도 되는데 그렇게 하지 않는다는 야그 입니다.

주의이런 구조땜시 NAND 컨트롤러가 내장되지 않는 프로세서로 외부에 NAND 지원 회로를 만들때는 좀 조심해야 합니다. 즉 NAND 를 선택하는 nCS 가 LOW 로 되어 있어도 다른 하드웨어에 접근이 되도록 설계해야 합니다.

뭐 어떤 NAND 컨트롤러는 일반 디바이스와 비슷하게 제어되도록 하고 있지만은 일반적인 것은 아닙니다.

nCE 는 NAND 제어 시작부터 LOW로 만들고 NAND 제어가 끝날때 HIGH 로 만든다.
이것은 꼭! 기억해 두시는 것이 좋을 겁니다.

뭐 내부 구성의 동작 방식은 제어하는 방법을 알아가면서 이해 해야 하므로 일단 다음 강좌로 미룹시당
오늘은 대충 내부 모양과 회로 구성의 개요만 보여 드리는 것으로 쫑내죠..

왜냐하면 벌써 시간이 ...

몇줄 안썼는데 그림 그리고 나면 ㅜㅜ

다음 강좌에서 뵙죠...

 

 

 

 

서울에 사람들이 없네요 ..
확실히 휴가 기간이죠?

나도 정말 잃하기 싫군요... 으으으...

이번엔 진짜 NAND를 제어하는 방법에 대하여 알아 봅시당..
동작 원리하고...

지금 부터 쓰는 강좌가 사실 가장 핵심 강좌죠...
(시선 집중하세요!!!)

우리가 NAND 를 저장 장치로 쓰기 위해서는 다음과 같은
6가지 행동을 합니다.

  1. NAND 디바이스 리셋
  2. NAND 디바이스 정보 읽기
  3. NAND 상태 읽기
  4. NAND 지우기
  5. NAND 쓰기
  6. NAND 읽기

이걸 수행하려면 명령 레지스테에 해당하는 기능 값을 써 넣어야 합니다

레퍼런스 매뉴얼을 보면 다음과 같이 나와 있습니다.

function 1st. Cycle 2nd. Cycle Accept Command During
Read 1 00h/01h(1) -  
Read 2 50h -  
Read ID 90h -  
Reset FFh - 0
Page Program 80h 10h  
Block Erase 60h D0h  
Read Status 70h - 0
       

뭐 첫번째 뭐 하고 두번쨰 뭐하고 ..
아직은 잘 모르겠죠?

이제 하나씩 설명 하지용...

가장 첫번째...

***** 리셋하기 *****

뭐 이전 강좌에서 보거나 레퍼런트 매뉴얼을 보시면 아시겠지만
NAND 플래쉬 메모리의 칩 핀에는 리셋 핀이 없습니다.

당근 전원이 꺼졌다 새로 켜지기 이전에는 리셋이 동작하지 않겠죠..
흠...

그렇다면 어떻게 NAND 플래쉬를 제어 하다가 RESET을 주어야 할까용...

뭐 간단합니다.

리셋 명령을 써 넣으면 됩니다.

어떻게 써 넣어야 할까요?

메뉴얼에 이것에 대한 타이밍도가 없으므로
그냥 저도 말로 때우겠습니다.

뭐 간단합니다.

CLE 즉 명령 래치 이네이블 핀을 HIGH 로 하고 데이터 버스에 0xFF 를 써 넣으면 됩니다.
넘 간단하지 않아요?

여기서 기억할것!

앞으로도 당연히 생략할 건데...

이런 행위를 하기 이전에는 반드시 nCS 를 LOW로 NAND 처리가 끝났으면 nCS 를 HIGH로
만든다...

이것이 생략함을 기억해 주세요.

정리 합시다...

NAND 플래쉬를 리셋하려면

  • nCS = LOW
  • CLE = HIGH
  • DATA <== 0xFF
  • CLE = LOW
  • nCS = HIGH

쉽죠?

근데 이때 반드시 해 주어야 할것이 바로

대기죠..

즉 RESET 명령을 쓰면 NAND 플래쉬 메모리는 자체적으로 RESET 을 수행하게 되는데
이때 시간이 좀 걸립니다.

그래서 RESET 하고 난 이후에는 반드시 NAND 플래쉬 메모리가 바쁜지를 상태를 읽어서
체크 해야 하죠

그런데...

이거 귀찮거든요...

그리고 하드웨어라는 것이 대부분 어떤 시간은 일정하걸랑요

그래서

그냥 딜레이 줍니다....

괜히 귀찮게 상태 읽는 것 코딩 하기 싫으니깐...

뭐 편집증 계신분은 직접 상태 읽어서 하면 되겠지만

이거 읽으려면 R/nB 핀을 읽는게 좋은데...

보통 하드웨어에 이 핀 연결 안 하거든요

그리고 RESET은 딱 한번 씁니다.

처음 ID 디텍션 할때 ...

그러니깐...

그냥 딜레이로 처리 하세요...

그냥 널널 하게 1 msec 정도 주면 됩니다.

원래 레퍼런스를 보면 5 ~ 500 u Sec 인데 그냥 1 m Sec 주는 것이
안전 합니다.

뭐 한번만 할건데.. 조금 시간 낭비 하면 어떻습니까 ㅋㅋ

***** 생산회사 ID 와 디바이스 ID 읽기 *****

NAND 플래쉬를 제어 하려면 제어하려고 하는 프로그램은 다음과 같은 사항을
알아야 합니다.

  • 전체 용량
  • 지우기(erase) 단위 크기 블록 크기
  • 페이지 레지스터 크기
  • 데이터 버스 크기 (8비트, 16비트)
  • 등등...

근데 이것을 NAND 플래쉬 메모리에 내부적으로 저장하고 있는 것이 아니고
각 NAND 플래쉬 마다 고정되어 있기 땜시

디바이스 ID 를 읽어서 프로그램 내부에 자체적으로 설정해야 합니다.

그렇다면 여러분은 각 NAND 플래쉬 메모리 데이터 시트를 모두 구해서
그때 그때 프로그램을 짜야 할까요?

아.니.죠...

그런건 이미 누군가가 해 놨습니다.

어디에?

예 바로 리눅스죠...

그러면 이런 정보는 리눅스 소스 어디에 있을까요?

친절한 제가 여러분에게 알려 주죠...

바로 여기에 있습니다. ==>> drivers/mtd/nand/nand_ids.c

정말 리눅스 좋지 않습니까? ㅋㅋ

뭐 이 파일에 각 필드가 어떤 내용인지는
역시 리눅스 디바이스 드라이버인 MTD의 NAND 를 이야기 할때
설명하겠죠?

그러므로 지금은 이런 파일이 있다는 정도만 알려주고

NAND 동작에 대한 설명을 중점적으로 써 갑니다. 짜잔..

우선 ID 를 읽는 것에 대한 것은 레퍼런스에 나오므로 참조해 봅시당...


[그림 3-9] NAND ID 읽기 타이밍

그림을 보면 알수 있듯이

ID를 읽기 위한 명령은 0x90 입니다...

그 다음에 주소를 00 을 줍니다.

그리고 그냥 데이터를 두번 읽으면 됩니다.

쉽죠?

그러면 첫번째 읽는 데이터가 제조사 ID이고 그 다음 읽은 데이터가 디바이스 ID입니다.

솔찍히 제조사 ID는 별로 의미가 없습니다.

중요한것은 디바이스 ID죠

디바이스 ID는 중복되지 않기 때문에 이 ID를 보고 NAND를 제어하기 위한 파라메터를
설정 합니다.

보통 하드웨어를 테스트 할때 NAND 관련 회로는 이 ID만 정상적으로 읽어 오면
하드웨어는 정상인 겁니다.

그 나머지는 소프트웨어 문제로 봐야 합니다.

왜냐하면 ALE CLE nWE nRE 등 필요로 하는 모든 신호가 동작하기 때문이죠...

 

 

 

 

짜짠~~~

휴가 갔다가 돌아 왔습니다.

정말 비 맞은 휴가 였습니다. ㅠㅠ

아그들하고 속초 갔는데 비오는 바닷가 수영
진짜 죽입니다 크아~~~~

그외 판타지 & 무협지를 끝없이 봤습니다.
영화 마을 아저씨 무척 좋아 하시더만요...

어쨌든 재 충전 했으면 힘이 나야 하느데..

넘 일을 안했더니 모든것이 귀찮군요 ㅜㅜ

그래도 강좌는 해야 겠죠?

이전에 뭐 했는지 가물 가물 하지만 기억을 되 돌려서
시작해 봅시당... ㅋㅋ

NAND 읽기

이번 강좌는 NAND 읽기 입니다. 당근 읽기가 쓰기보다 편하지용...
(뭐 반드시 그런건 아니지만요 쩝~~~)
하지만 NOR 에 비하면 이전에 말한것과 같이 간단하지 않습니다.

어쨌든 NAND 읽기를 살펴보면 아마도 조금 더 내부동작을 이해 할 수 있을겁니다.

우리는 메모리를 읽을때 특정 위치를 지정합니다. 메모리라면 읽기 위한 주소를 지정해야 하죠...

그 주소라는 것이 실제로 두가지가 존재합니다.

하나는 시스템 메모리 전체를 기준으로 하는 주소와 그 메모리 자체적인 주소죠...

뭐 이걸 base address ( 베이스 어드레스), offset address ( 오프셋 어드레스 )
라고도 말할수 있겠네요 그쵸?

보통 NOR 플래쉬라면 이 두가지 개념을 생각해야 하지만...
NAND 플래쉬라면 오직 한가지 플래쉬 주소만 생각하면 됩니다.

이전에 핀 사양을 보시면 아시겠지만 주소 지정 핀이 없습니다.
그렇다고 각각의 어드레스를 접근하기 위한 주소나 데이터를 넣기 위한 주소를
베이스 어드레스라고 우기면 뭐 할수 없습니다만...

플래쉬 주소는 그 용량에 따라서 범위가 결정되죠..

예를 들어 64MByte 라면 유효 주소 범위는 ...
흠 잠시 계산 합시당.

64 * 1024 * 1024 = 67108864

이 범위가 되는데 저같이 이미 16진수에 익숙한 사람은 이렇게 큰 수치는 언뜻
머리에 들어 오지 않습니다.

이걸 16진수로 바꾸어 보면 다음과 같습니다.

0x4000000

즉 지정이 가능한 범위는 0x0000000 부터 0x3FFFFFF

이것도 보기 어렵죠... 워낙 길어야 말이죠...

그래서 32비트 프로세스가 등장한 이후부터는 이걸 이렇게 표시 합니다.

0000-0000 부터 03FF-FFFF

요렇게 표시 합니다.

어...쨌....든

우리는 플래쉬 메모리에서 특정 번지를 읽어 오고자 합니다.

예를 들어 013A-332F 의 데이터를 읽는 다고 합시당.

NOR 라면 당근 그냥 해당 위치의 주소를 읽어 오면 됩니다.
(물론 쓰기 모드 상태라면 읽기 모드로 변환해 주어야 하거나 좀 기달려야 하겠지만 말입니다)
NOR 플래쉬가 0 번지에 매달려 있다면 그냥 0x013A332F 번지를 읽어오면 끝입니다.

뭐 프로그램 적으로 표시하면 다음과 같이 코딩하면 됩니다.

volatile unsigned char *addr;

addr = (volatile unsigned char *) 0x013A332F;

printf( "%02X\n", *addr );

쉽죠?

근데...

NAND 에서는 이렇게 쉽게 못 읽어 옵니다.

왜냐?

이전에 말했죠?

NAND 내부 구조를 보면 PAGE 단위로 NAND 메모리 셀을 접근한다고요..
즉 NAND는 직접적으로 해당 위치의 데이터를 읽어 오지 못하고 항상
NAND PAGE 버퍼를 통해서 읽어 와야 합니당...

자 이걸 설명하려면 먼저 그림을 보면서 이해해야 합니다.
레퍼런스 매뉴얼에서 제공하는 그림을 슬쩍 봅시다...


[그림 3-10] 읽기 모드 1 타이밍

음...

우선 보아야 할 그림은 하단의 그림중 왼쪽에 있는 그림입니다.

보시면 아시겠지만 왼쪽 그림과 오른쪽 그림이 비슷합니다.

그림중 위에 있는 것이 플래쉬 메모리 셀들이라고 보시면 될것이고
그 밑에 한줄 박스가 바로 페이지 버퍼 레지스터라고 보시면 됩니다.

NAND 플래쉬 메모리에서 데이터를 읽기 위해서는 먼저 메모리 셀에서
페이지 버퍼 레지스터에 옮기는 과정이 필요합니다.

그 다음에 그냥 NAND 플래쉬에 읽기 신호를 주면 버퍼 레지스터에서 순차적으로 출력되고
그것을 프로세서는 읽어 들이는 거죠..

그래서 NAND를 읽기 위해서는

1) 읽으라는 명령을 주고
2) 읽을 위치를 지정하고
3) 읽을 동안 잠시 기다렸다가
4) 필요한 만큼 읽기를 반복

하면 되는 겁니다.

뭐 의외로 간단하죠?

자 그런데 ....

이게 좀 간단하지 않습니다. ...

왜 그럴까요?

우선 보면 아시겠지만 NAND 메모리의 페이지 버퍼는 크게

1st Half Array(256) , 2st Half Array(256), Spare Array(16)

이렇게 나뉘어져 있습니다.

각 영역을 어떤 그림에는 A,B, C 영역이라고도 합니다.

그래서 각 위치를 읽어 올때 명령이 다릅니다.

첫번째 영역에서 부터 읽어 들이려면 0x00 을 명령을 주어야 하고
두번째 영역에서 부터 읽어 들이려면 0x01 명령을 주어야 하고
세번째 영역에서 부터 읽어 들이려면 0x50 명령을 주어야 합니다.

간단한듯 한데

뭐가 복잡하냐?

위 세가지중 하나의 읽기 명령을 지정한 이후에 주소를 지정하는데
여기서 바로 A8 이 빠진 주소로 지정해야 한다는 겁니다.
그림에도 그렇게 표기 되어 있죠?

위에서도 이야기 했지만 플래쉬 메모리를 읽을때 내부 동작은
메모리에서 페이지 버퍼로 데이터가 이동하게 됩니다.

이때 이동되는 데이터 총 수는 528 바이트 입니다.
요거이가 바로 한 페이지죠

이중 16 바이트는 스페어죠..

그래서 실제로 플래쉬 메모리가 페이지 버퍼에 옮길 위치를 지정하기 위해서
사용되는 주소는 A9 부터 A25를 사용하게 됩니다.

그리고 A0 부터 A7 은 페이지 버퍼에서 읽어 오기 위한 위치 포인터로 사용됩니다.
그뒤로 위치 포인터는 읽기를 한번 수행할때마다 자동으로 증가 하게됩니다.

이 증가는 C 영역까지 계속 증가 합니다.
C 영역 끝까지 가면 어떻게 되냐?
그건 다음에 이야기 합시다. 어쨌건 할 이야기니깐...

그래서 스페어를 뺸 나머지 총 512 바이트의 위치를 지정하기 위해서는 A0 부터 A8 까지가 필요한데
이중 A8은 읽기 명령에 따라서 자동 지정되고
그 나머지 8비트 즉 A0 부터 A7은 페이지 버퍼의 각 영역의 시작 위치가 0으로 했을때의 위치가 지정되는 겁니다.

스페어 영역을 읽기 위해서는 A0 에서 부터 A3 까지만 필요하죠... 16 바이트 위치만 지정하면 되므로
A4 부터 A7까지는 별 의미가 없는 겁니다.

그래서 읽기 명령을 써 넣은 후 주소를 4 번 써넣게 되는데
읽기 명령에 읽을 위치중 페이지 버퍼의 영역중 첫번째을 영역을 읽을건지
두번째 영역을 읽을 건지 세번째 영역을 읽을 건지를 정한후 해당 명령를 결정하는 겁니다.

그 뒤에 가장 처음 버퍼의 상대 위치인 주소를 한 바이트로 표현해서 써 넣고 ( A0 ~ A7 )

그 다음 나머지를 주소를 써넣게 됩니다. 이 주소를 페이지 주소라고 합니다.

자....

정리하면 이렇습니다.

NAND 플래쉬 메모리의 주소는 크게 두가지 나누어 볼수 있는데

페이지 주소와 버퍼 위치 주소(또는 컬럼 주소)죠...

페이지 주소는 A9 부터 시작한다고 생각하시면 됩니다.
버퍼 위치 주소는 다시 명령과 주소 지정을 이용해서 지정하고
첫번째 영역과 두번째 영역의 읽기인 경우 A0 ~ A7 으로 지정 하는 것이죠
세번째 스페어 영역은 A0 ~ A7 을 모두 써 넣어야 하지만 (뭐 8비트 단위로 써 넣어야 하는데 당연하겠죠)
A4 부터 A7 은 어떤 값이 되든 상관 없다는 겁니다.

버퍼의 위치를 지정하기 위해서 사용되는 A0 ~ A7을 지정하는 것은
페이지 읽기는 한번에 수행되지만 마지막 위치를 읽기만 해야 한다면 굳이 0 부터 항상 순차적으로
읽어서 그 위치까지 읽을때 까지 읽기를 반복하는 것을 줄이기 위해서 입니다.

근데요...

현실적으로 NAND 플래쉬는 하드 디스크 처럼 사용하고 페이지를 섹터 개념으로 사용하기 땜시
실제로는 거의 0으로 지정해서 읽습니다.

즉 실제 사용할때는 별 의미가 없는데
뭐...

어떤 분들은 그렇게 사용하지 않는 분들도 있지 않겠습니까? 그쵸?

그런 분들에게는 A0 에서 A7도 의미가 있는 겁니다.

리눅스의 블록 디바이스 드라이버라면 거의 읽기 명령으로 00을 사용하고
항쌍 512 바이트를 쭈욱 읽는 방식을 사용합니다.

자 여기서 한가지 기억할 것은 NAND 플래쉬는 읽기 명령을 준후
읽을 주소를 4번 쓰면( 현재 예제로 사용하는 용량일 경우) 그 다음 자동으로
플래시 메모리 페이지에서 페이지 버퍼로 데이터를 옮기게 되는데
이때 시간이 소모 됩니다. 또 이렇게 읽고 있는 동안에는 R/nB 가 Low 로 떨어짐으로써
자기가 바쁘다고 알리는데 읽을수 있는 상태인가를 확인하려면 이 핀을 체크 하면 되겠죠..

벗!!

그러나 실제로 회로를 만들때 R/nB는 잘 사용하지 않습니다.
또 게으른 우리들 프로그래머들은 이 R/nB가 설령 연결되어 있더라도
이 핀의 상태를 체크하도록 프로그램 하지 않습니다.

왜냐...

요 시간이 기껏 해봐야 10uSec 입니다.

그냥 지연 루틴을 넉넉하게 20uSec 정도 준 후 읽어도 아무런 이상이 없기 땜시...

복잡하게 체크 루틴을 만드느니 그냥 지연을 넉넉하게 20uSec를 주는 것이 편하다는 거죠...
편하게 사는 것이 건강하게 사는 길입니다. 흠흠...

자 이렇게 읽는 것을 위에 타이밍도를 봐도 되겠지만 레퍼런스 매뉴얼에 조금 자세하게
나온것이 있는데 그 부분을 그림으로 올려 봅시당...


[그림 3-11] 읽기 모드 1 타이밍 2

보통 메뉴얼에 보면 읽기 모드 1 이라는 것은 첫번째 영역 또는 두번째 영역을 읽는 다는 것이고
이때 사용하는 명령은 0x00 또는 0x01 입니다.

읽기 모드 2 는 스페어 영역을 읽는 다는 것이고 명령은 0x50 입니다.

그리고 위 그림에서 보듯이 주소 지정은 총 4 사이클이 필요한데

가장 첫번째 사이클이 영역의 읽기 시작하는 위치를 지정하고
그 나머지 3 사이클이 페이지 어드레스를 지정하는 겁니다.

아...

오늘도 이정도에서 마무리 지어야 겠네요...

다음 강좌에서는 읽는 부분 방법중 시퀀스 하게 읽는 것을 설명하도록 하겠습니다.

그럼 바바이...

 

 

 

덥죠?

전 드디어 진정한 피서를 하고 있습니다.
회사에 에어콘 빵빵해서 더운줄 모르고 있답니다. ㅋㅋ

자 이번 강좌는 저번에 이어서 NAND 를 연속적으로 읽는 겁니다.

그래서 이번 강좌는 무척 짧습니다. ㅋㅋ

AND 읽기에 대한 개념 정리

저번에 읽기에 대한 것을 보면서 여러분이 개념적으로 하나 정리해야 할것은

NAND 는 페이지로 다루어야 한다는 거죠..

일반 메모리 처럼 어드레스로 생각하면 안된다는 거죠

그리고 페이지는 NAND 칩 마다 그 크기가 달라집니다.
뭐 이건 나중에 Large Block 을 지원하는 칩을 다룰때 다시 말할겁니다.

현재는 한페이지는 512 바이트 + 16 이라고 생각하십시오

그러므로 주소라고 말하는 것은 크게 두가지가 합쳐진 개념이죠

버퍼 위치 + 페이지 번호

주소를 구성하는 바이트 수는 이런 고로 용량에 따라서 달라지는데

현재 제가 강좌하고 있는 칩은 64 M 라서 총 4 바이트로 구성됩니다.

12 번째 페이지의 32 번째의 데이터를 읽고자 한다면
어드레스는 다음과 같이 구성되어죠..

읽을 버퍼 위치 : 32
페이지는 : 12

총 바이트는 4 바이트의 써 넣기 순서는 다음과 같죠

페이지 번호는 역순으로 입력 되어야 합니다. ^^

이때는 읽기 명령이 0x00 이 되어야 합니다.

0x003456 번째( 계산하기 쉽게 ^^ ) 페이지의 257 번째의 데이터를 읽고자 한다면
어드레스는 다음과 같이 구성되어죠..

  • 읽을 버퍼 위치 : 257 --> 257 - 256 = 1
  • 페이지는 : 0x003456

총 바이트는 4 바이트의 써 넣기 순서는 다음과 같죠

이때 읽기 명령은 0x01 이 사용되어야 하죠..

뭐 스페어 읽는 것은 굳이 다시 설명 안해도 되겠죠?

NAND 연속적으로 읽기

자 한페이지씩 읽었는데...

속도광이 오토바이족이나 자동차족만 있는 것이 아닌거 아시죠?
예..

맞습니다.

어셈블러 하시는 분들은 대부분 속도 광입니다.
임베디드 하시는 분들은 대부분(?) 속도 광입니다.

아주 조금만 빨리 할수 있는 방법이 있으면 죽어라 팝니다.

이런 분들을 위해서 나온 것이 연속적으로 읽기 입니다.

이게 뭐냐...

NAND 를 읽을 때 한 페이지 단위로 읽어야 하는데
이때 항상 명령 쓰고 주소 넣어야 하죠?

이시간을 아끼고자 하는 분들을 위한 것이 바로 ....

연속 읽기

즉...

Sequential Row Read

라고 합니당.
(흠 사대주의인가 ... 영어로 쓰니깐 뭔가 있어 보이네 쩝 )

근데요..

이게 뭐 특별한 명령이 필요한 것은 아니고 그냥 읽기를 계속 하면 처리 됩니다.
( ㅋㅋ 속았죠.. )

먼저 매뉴얼에 있는 그림을 여기서 봅시다.


[그림] 연속 읽기 모드 1 타이밍.bmp

그림을 보면 알수 있듯이

맨처음 한페이지를 읽기 처리는 같지만 계속 데이터를 읽으면 다음 페이지로 이동한다.

여기서 한 페이지의 읽기 단위는 528 이다. 즉 스페어 공간까지 계속 읽는 다는 의미..

그런데 페이지 버퍼에서 읽고 끝까지 읽었다면 다음 페이지를 메모리 공간에서
페이지 버퍼로 이동 시키는 시간이 필요하므로

한 페이지 끝에 도달할때까지 데이터를 읽은 이후에는
잠시 기달려야 합니다.

이 시간은?

예 맞습니다.

귀찮음의 반로인 지연 루틴으로 대치합니다.

괜히 RnB 신호 체크 하지 않습니다.

어쨌든 보통 연속 읽기 1 모드 에서는 ( Sequential Row Read 1 Mode)

실질적인 프로그램에서는 버퍼위치는 항상 0 으로 주고 처음부터
읽는 것이 처리 하기 편하기 땜시

읽기 명령은 0x00 을 사용합니다.

정리하면

  1. 연속 읽기 명령은 0x00 명령을 주로 사용하고
  2. 버퍼 포인터 위치는 0 으로 지정하고
  3. 원하는 페이지 주소를 지정하고
  4. 메모리에서 페이지 버퍼로 이동하는 시간동안 기다린후
  5. 528 번 데이터를 읽고
  6. 다시 4) 번과 5) 번을 반복하면 됩니다.

뭐 사실 기껏 시간 줄이는 것이 1) 과 2) 만 줄이는 거라서

개발자들은 귀찮게 이런식의 구현을 안합니다. ( 나만 그런가? )

그냥 한페이지 단위로 읽는 루틴을 정형화 하고
그걸 이용하는 것이 나을수 있다는 거지요

명령 주고 어드레스 주는 시간이 얼마나 걸린다고 ㅉㅉ

전 속도광이 아니거든요

편하게 살고 싶어요...

자 여기서 한가지 더

스페어 부분만 읽는 명령이 0x50 을 사용하는 경우는 어떻게 될까요?

ㅋㅋ

그건 다음 그림을 보시면 확실히 알수 있습니다.
이건 굳이 설명하지 않겠습니다.


[그림 3-12] 연속 읽기 모드 2 타이밍

이렇게 읽는 방식을

연속 읽기 2 모드 ( Sequential Row Read 2 Mode)

라고 합니다.

이것은 거의 사용되지 않는다는 점을 기억해 주세용...

이것으로 읽기에 대한 개념을 마치겠습니당...

랄랄랄 이번것은 그냥 그림으로 때웠네요 ㅋㅋ

 

 

 

 

오늘은 들어가는 잡설은 없이 바로 강좌 들어 갑니다.

NAND 지우기

여러분이 혹시 NAND를 제어할 일이 있다면 개발 함수 작성 및 순서를
제 강좌 순서를 따라 하시면 좋을 듯 합니다.

제어 순서 이기도 하고요...

지우기 쓰기 보다 읽기를 먼저 설명한 이유도 이 이유입니다.

NAND 가 지워 졌나 알아 보려면 읽기 부터 해야 하거든요 ^^

자...

원래는 읽기에서 BAD 블록 체크와 관련된 부분을 설명해야 하는데
이 부분은 나중에 설명하고 먼저 지우기 부터 해야 할듯 합니다.

뭐 아시겠지만( 모르실려나?) 강좌 쓸 양이 짧거든요 쩝..

우선 지우기에 대한 설명을 하기 전에 여러분이 기억해야 할 것중 하나는
지우기는 블록 단위로 해야 한다는 겁니다.

물론 지우기의 블록의 크기는 페이지의 배수이고 이전 강좌를 기억하시는 분들이
있겠지만 저같은 건망증이 심한 분들을 위해서 현재 강좌에서 다루는
플래쉬 기준으로 다시 알려 드리죠...

1 Block = 32 Page

이렇게 32 Page 단위로 지울수 있습니다.

일단 지우기를 어떻게 하는 가를 보기 위해서 그림을 봅시당.


[그림 3-14] 지우기 타이밍

이전 강좌에서 명령에 대한 것을 잠깐 언급할 때 1 Cycle 이니 2 Cycle 니 하는 것들을
나중에 이야기 한다고 했죠?

예..

지금이 이 이야기를 할 시점입니다.

위 타이밍도를 보면 아시겠지만

지우기 위해서는 두개의 명령이 필요 합니다.

0x60 : Auto Block Erase Setup 명령
0xD0 : Erase 명령

이렇게 하나의 행위를 하기 위해서 두개의 명령이 필요하면 2 Cycle이라고 하고요
읽기와 같이 하나의 행위를 하기 위해서 한개의 명령이 필요하면 1 Cycle이라고 합니당.

왜 두개의 명령이 필요하냐?

제 생각입니다만...

지울 주소 지정과 진짜 지워라 하는 명령으로 나누어져 있다고 보시면 됩니다.

0x60 명령이 지울 주소를 지정하기 위해서 사용되고요

0xD0 이 지정된 주소를 지우라는 명령이라는 의미죠..

NAND 플래쉬는 0xD0 이 명령으로 입력되면 즉시 지우기 시작한다는 거죠..

0x60으로 지울 주소는 페이지 단위로 지정하는데 1 블록은 32 페이지 이므로

페이지 주소의 하위 5 비트는 무시됩니다.

물론 프로그램에서는 이 비트를 항상 0 으로 클리어 해서 처리하도록 합니다.
실제로 영향은 미치지 않지만 혹시나 하는 마음으로 그렇게 합니다. ㅋㅋ

지울때는 버퍼에서 데이터를 읽거나 쓰지를 않기 때문에 주소를 써 넣을때
버퍼 위치가 필요하지 않으므로 페이지 주소만 써 넣으면 됩니다.

또 지울 경우에 버퍼와 관련된 첫번째 영역이니 두번째 영역이니 스페어 영역이니
하는 것이 해당 되므로 당근 ...

지우기 위한 주소 지정 명령도 0x60 하나면 되는 거죠...

이런 고로 주소 지정은 0x60으로 한후 페이지 주소 3 바이트를 역순으로 써 넣으면 됩니다.

지울 블록 주소가 지정된 후 바로 0xD0 명령을 써 넣어 NAND 플래쉬의 페이지를 지우면
NAND 플래쉬는 지우기를 시작합니다.

지우기는 프로세서 입장에서 보면 무척 긴 시간입니다.

현재 사용되는 칩의 지우기를 위한 최대 시간이 3 m sec 인데

흠...

이전에 읽기 처럼 무작정 3 m sec 기달리면 ....

쩝... 안되겠죠....

이번에는 귀찮더라도 다 지워 졌는지를 체크 해야 합니다.

또 혹시라도 ( 별로 그럴 가능성이 거의 없지만 )
지우라고 했는데 안 지워져 버리면 다시 한번 시도해야 하니깐...

현재 지워진 상태를 읽어 보는 것이 좋지 않겠습니까?

그래서리...

상태 읽기에 대한 이야기도 이번에 한꺼번에 해야 합니당...

(쯥... 귀찮은데.. 퍽~~~ )

NAND 상태 읽기

NAND 플래쉬의 상태 읽기는 두 경우 이외에는 할 필요가 없습니다.

지우기가 종료되었는지와 에러가 없는지 확인
데이터 쓰기가 종료 되었는지와 에러가 없는지 확인

이 두가지 경우 포맷은 갖습니다.

일단 이것도 명령 으로 처리하는데 워낙 간단해서리 타이밍도는 필요 없습니다. ( 휴~~~ )

그냥 상태 읽기 명령인 0x70 명령을 써 넣고 한 바이트 읽어 내면 됩니다. (진짜 간단하죠 ㅋㅋ)

근데 이 상태 읽기 명령의 비트는 각각 의미가 있으므로 다음과 같은 표로 보시는 것이 좋습니다.

일단 표를 봅시당...


[그림] 상태 읽기 테이블.bmp

이중에 가장 먼저 보아야 할 것은 Bit 6 입니다. 이 비트가 바로 현재 NAND 플래쉬가
먼가 하는가를 표시하는 놈이죠...

이 놈이 있기 땜시 굳이 하드웨어에서 RnB 핀을 사용하지 않는 거죠...

그냥 소프트웨어 적으로 처리가 가능하고 별로 시간도 안먹으므로
이렇게 처리해서 하드웨어에 따른 소프트웨어의 변화가 적도록 만드는 거죠..

일단 상태는 계속적으로 읽어 봅니다. 그래서 Bit 6 가 1로 되면
현재 진행되던 일이 끝났다는 것이므로

지우기와 쓰기의 경우에 Bit 0 를 보고 0 이 아니면 실패한것으로 판단합니다.

쉽죠?

그러면 Bit 7 은 뭘까요?

뭐 간단합니당...

NAND 플래쉬 핀 중 쓰기 금지 핀이 있지 않습니까?

그 상태를 읽어 오는 겁니다.

쓰기 금지가 되어 있지 않다면 쓰면 안되겠죠?
당근 쓰기나 지우기도 실패 합니당...

그냥 핀 상태를 돌려 주므로 쓰기 금지가 0 입니다.
이점 기억 하십시오

아....

다음번 강좌에 쓰기에 관련된 이야기 하고
전체적인 제어에 대한 이야기만 하면

드...뎌... 리눅스와 관련된 이야기를 할수 있겠네요..

두려워 집니다. ㅜㅜ

그래도 열라 쓸테니 기둘려 주시기 바랍니다. 쩝...

그럼 오늘도 바바이..

 

 

 

 

요즘 회사일이 좀 바쁩니다.
흠..

그래서 ..

그냥 그렇다구요.. 쩝

NAND 쓰기

자 이제 대망에 마지막...

NAND 에 쓰기 입니다.

지금까지의 강좌를 읽어 보신분들이라면 대충 눈치 채시겠지만 쓰기 역시 페이지 단위로 써 집니다.

자 여기서 우리는 외쳐 봅시당.

NAND 는 페이지 단위로 생각하자!!!

이제 NAND 에 페이지 단위로 써 넣어어야 하는데..

NAND 에 쓰는 것을 PROGRAM 이라고 합니다.

이 쓰기 명령은 2 Cycle 명령으로 0x80 과 0x10을 조합합니다.

왜 이렇게 나누어져 있냐?

우선 써 넣을 페이지를 지정해야죠?

그리고 읽기와 달리 쓰기는 쓸 데이터를 지정해야죠?

이게 끝나야 쓰기를 하라고 할수 있지 않겠습니까?

그래서 0x80 명령은 페이지 주소와 데이터를 버퍼에 써 넣기 위해서 필요한 명령이고요

0x10은 실제로 페이지 버퍼에 내용을 플래쉬 메모리에 쓰라는 명령이죠...

물론 다 쓴 다음에는 지우기와 동일한 방법으로 잘 써 져 있는지 검사 합니다.

일단 그림을 봅시당...


[그림 3-16] 쓰기 타이밍

이제 타이밍도에 익숙해 지셨습니까?

그림을 보듯이

0x80 을 쓰고 페이지 버퍼 주소와 페이지 주소를 ( 총 4 바이트 ) 써 넣고
데이터 528개를 쭈욱 밀어 넣습니다...
물론 이 데이터들은 페이지 버퍼에 써 넣어지게 되는 것이구요

그 이후에 페이지 버퍼의 내용을 플래쉬에 써 넣으라는 명령인 0x10을 씁니다.

물론 쓰고 난 이후에는 NAND 플래쉬가 쓰는 동안 기달려야죠..

이 기다리는 시간은 대략 500 u Sec 정도 됩니다.

좀 길죠?

그러므로 무식하게 기달리는 방식으로 짜면 안되겠죠? ^^

예 상태를 읽어서 종료 되기를 기다리는 것이 좋습니다.

왜냐 500 u Sec는 최대란 의미고 실제로는 200 u Sec 정도 되거든요..

귀찮으면 그냥 기달리시고요..

뭐 스피드 광들에게 혼날지 모릅니다.

아 ...

이 방식일 경우 페이지 버퍼 주소를 지정하는 첫번째 주소 값은
항상 0 으로 쓰셔야 할겁니다. .

왜냐?

중간을 지정하면 528 개를 모두 써 넣지 못하고 그 위치 만큼 뺴 주어야 하잖아요

또 ...

이게 제일 중요한건데

버퍼에는 이전에 지정된 값이 있거든요..

근데 0x10 명령은 페이지 버퍼의 내용을 플래쉬 메모리에 써 넣으라는 명령이잖아요

그러면 이전 내용과 이번에 쓴 내용이 짬뽕되잖아요...

그러면 원하는 결과와 다른 내용이 써 질수 있거든요..

그래서 이 방식으로 쓰기를 할 경우에는

페이지 버퍼 주소는 0x00 으로 지정하고 528 단위로 써 넣어야 한다는 거죠...

흠..

또 하나의 문제는 버퍼 주소값이 어디를 가리키냐는 문제가 있죠...
A 영역? B 영역 ? C 영역?

모드죠.. 아무도... 쩝

눈치를 채신분이 있을지 모르지만...

이걸 해결하기 위해서

이전에 사용했던 읽기 명령을 붙입니다.

첫번째 영역인 A 영역 부터 데이터를 쓰려면 0x00
두번째 영역인 B 영역 부터 데이터를 쓰려면 0x01
세번째 영영깅 C 영역 스페어 영역에 데이터를 쓰려면 0x50

이걸 설명한 것이 바로 다음 그림입니다.


[그림 3-17] 쓰기 영역 지정 타이밍

여기서 특이한 것은 처음에는 지정해야 하지만 다음번에는
생략해도 된다는 겁니다.

단 B 영역은 아니죠....

어쩄든 여기서 기억해야 하실것은...

현실적인 이유에서 데이터를 쓸 때

페이지 버퍼 지정 위치는 0 으로 하고
첫번째 영역부터 쓰기 시작하고
써 넣는 데이터는 528 바이트를 기준으로 합니다.

앗 여기서 우리가 조심해야 할 점은
만약 스페어 영역을 건들지 않고 싶다면?

예 맞습니다. 해당 영역을 미리 읽어 버리면 되겠죠?
만약 그렇게 하고 싶지 않다면?

잔머리를 조금 굴리면 됩니다.

이전 강좌에서 이런 이야기 했죠?
지우고 나면 모두 1 로 바뀌는데 0 으로 끊는 거라구요..

그렇습니다. 모두 1 값으로 쓰면 이전값을 유지 하게 됩니다.

그러므로 스페어 영역을 건들고 싶지 않다면 512 이후에는
모두 0xFF 로 스페어 공간만큼 밀어 버리면

이전 값을 유지 하게 됩니다.

 

근데요...

이거 귀찮지 않습니까?

또 매번 528 바이트씩 밀어 넣는 것도 조금 못 마땅 하죠?

그래서 이걸 제한적으로나마 풀어 놓은것이 카피 백 프로그램 이라는

조금 뭔가 있어 보이는 방법입니다. ^^

NAND 읽고 계속 쓰기 카피 백 프로그램

뭐 이름은 그럴듯 하지만 실제로는 간단합니다.

페이지 읽고 읽은거 계속 쓰기

허무하죠... 쩝

뭐 세상 다 그렇지 않습니까?

원래 다 그럴듯 해 보이는 것들이 실제로 다가가서 익숙해져 버리면 별거 없죠..

인생 다 그렇습니다.

이거 어디다 쓰느냐?

예 그렇습니다.

별로 쓸데가 없습니다.

단지 똑같은 데이터를 써 넣을 필요가 있을 때 사용하는 거지요

근데 이런 방식으로 할때 명령이 좀 틀립니다.

읽기 명령이야 0x00 인걸 알았겠지만요..
쓰기 명령은 0x8A 입니다.

아래 그림이 그 타이밍도 입니다.



[그림 3-18] 읽고 연속 쓰기 타이밍

솔찍하게 이런식으로 사용할 일은 별로 없구요...

차라리 읽고서 다시 쓰는 방식을 사용하죠...

물론 일기 명령 처리 흐름과 쓰기 명령 처리 흐름을 조합하는 겁니다.

어쨌든 이렇게 쓰기에 대한 이야기를 종료 합니다.

다음에는 리눅스로 바로 가는 것이 아니고

마지막 남은 배드 블럭이라는

숨겨진 난제를 해결해야죠...

그럼 다음 강좌에 보죠..

 

 

 

 

휴...

NAND 플래쉬에 대한 동작 설명이 막바지에 이르는 군요 ^^

NAND 배드 블록

복골복 복골복이라는 말 아십니까?
여러분이 LCD 모니터 살때 화면에 점 하나가 반짝 거립니다.
이상해서 구매한곳에 물어 보면 이렇게 이야기 합니다.

LCD의 PIXEL 중 몇개의 고장은 정상으로 취급합니다.
그러므로 환불이 불가능 합니다.

이런 경우를 뭐 밟았다고 하죠 ㅜㅜ

NAND 칩 고를때 바로 이말이 사용될수 있습니다.

NAND 플래쉬 메모리를 구매 했는데

배드 블럭이 몇개 나온다고 합니다. 즉 사용이 불가능한 블럭이라는 거지요

배드 페이지도 아니고 배드 블럭입니다.

더구나 어느 정도까지는 정상 제품이라고 합니다.

이런 경우 교환을 요청해도

삼성은 그건 정상 제품이라고 우기죠...

그래서 NAND 플래쉬 레퍼런스 매뉴얼을 보면

거기에 이런 문구가 떡 하니 써 있습니다.

VALID BLOCK

최대 4096 개인데 최소 4026 개 블럭이 유효한 블럭이다.

즉 60 개 정도는 배드 블럭이 나올수 있으니 사기 싫으면 관더라..

뭐 이런 말입죠...

대 삼성이 이러니 그 칩을 쓰는 회사 역시 버틸수 밖에요

여러분이 쓰는 MP3 니 평가 보드 같은 곳에 NAND 가 쓰일 때
배드 블럭 몇개 ...

이런식으로 나온다고 해서 환불 요청 하면 안된다는 거죠...
쩝...

이 놈의 배드 블럭은 프로그래머를 무척 괴롭히죠...

뭘 괴롭히는 지는 조금 있다가 알아보고..

우선

이 배드 블럭은 삼성에서 생산 시점에 검사합니다
문제는 배드 블럭이란 표시를 해야 하지 않겠습니까?

그래서 각 블럭의 첫번째 페이지와 두번째 페이지의
스페어 영역의 6번째에 표기 합니다.

메뉴얼을 보면 이 곳을 읽어서 0xFF 가 나오지 않으면
배드 블록으로 보아야 한다는 거지요...

물론 처음 사서 한번도 지우거나 쓰지 않아야 하는 조건입니다.

배드 블록 표시가 된 영역을 지우거나 써 버리면
그냥 지워지거나 써 져 버립니다.

그러므로 프로그램을 작성할 때 배드 블럭이 표시되는 블럭은
사용하지 않도록 해야 하죠...

근데 최소한 0 번 블록은 배드 블록이 아님을 삼성은 보장해
줍니다.

그나마 다행이지요...

그럼 정리하면서 기억 합시다.

  1. NAND 플래쉬는 생산시 20 개 이하의 BAD BLOCK 이 포함된 제품을 생산 판매한다.
  2. 생산 검사시 BAD 블록 표시는 BLOCK 의 첫번째 페이지 와 두번째 페이지의 517 번째 바이트를 읽었을때 0xFF가
    나오지 않으면 배드 블록이다.
  3. 배드 블럭이 검출된 블럭은 절대로 쓰거나 지우지 말아야 한다.
  4. 0 번 블럭은 절대로 배드 블록이 아니다.

자...

배드 블록이 이렇게 표시 되기도 하기 때문에 스페어 영역은
대부분의 경우 데이터 저장용으로 사용하지 않고 정보 저장용으로
사용합니다.

또 배드 블록 때문에

NAND는 1:1 복사가 불가능합니다.

어?

그렇다면 NAND 복사기들은 어떻게 작동하는데요?

흠...

전 잘 모릅니다. NAND 복사기를 써 본적이 없어서
하지만 뭔가 조치를 하나 봅니다.

어쨌든 1:1 복사를 하려면 배드 블록이 하나도 없는 놈들만 골라서 하시면 됩니다.
그나마 다행인것은 최근에 배드 블록이 발생하는 NAND 플래쉬가 거의 없다는 겁니다.

하지만

재수 없으면 배드 블록이 있는 놈을 구매 할수도 있다는 점 기억하십시오...

그래서 NAND 복사기도 이런 것에 대처방법이 있겠죠..

저희 회사는 NAND를 다룰때

배드 블록이 있는 놈들은 안 지웁니다.
그리고 물리적 블록과 논리적 블록을 별도로 취급하는 구조로 해서 작성하죠
논리적 블록은 배드 블록을 제외한 블록을 의미 합니다.

아마도 여러분이 펌웨어를 작성한다면 이렇게 해야 하겠죠...

어쨌든 오늘은 기쁘게도 짧게 끊습니다. (음하하하~~~)

다음 강좌는 아마도 좀 골치 아프실겁니다 .

ㅋㅋ

ECC 거든요...

그때 봅시당...

그 뒤로 정말 하드웨어에 관련된 강좌는 끝납니다.

바바이...

 

 

하드웨어 초보인데요.
아..오전 내내 감동깊게 읽었습니다..
읽어 보면서 저희 회사 보드를 직접 찍어 봤는데,
보면서 체크해 보니깐 정말 재미있군요..
좋은 정보 감사 드립니다.^^
종종 좋은 정보 부탁 드립니다..이히~^^