본문 바로가기
Embedded SW/Embedded SW Introduction

14. MCU에서 메모리와 Memory-mapped I/O란 무엇인가?

by 방구석 임베디드 2021. 7. 26.
반응형

저는 MCU를 10년간 개발을 하면서, 다양한 주변기기를 설계해 보았습니다.

그중에서도, 가장 중요한 개념은 당연, 메모리였습니다.

메모리를 정확하게 이해하고, Section을 Allocation 및 관리하는 능력이

Firmware SW의 핵심이었습니다.

이부분에 대해서는 제가 추후, 어떻게 Linker Scipt파일을 관리해야하는지

어떻게 메모리를 잡고 설계해야하는지 정리하도록 하겠습니다.

 

그렇다면 제일 중요한 메모리에 대해서 잠시 글을 쓰도록 하겠습니다.

계속 우려먹는 그림인데요, 아래 빨강 박스가 MCU 입니다.

이 MCU안에는 CPU와 메모리 그리고 다양한 주변장치들이 있습니다.

주변장치의 예로 GPIO 모듈을 넣어놓았습니다.

저 검은 박스안에는 메모리가 들어가 있고,

크게 Flash Memory와 RAM Memory로 구분이 됩니다.

 

여기서 Flash는 제가 보드의 전원선이 빼넣어도, 전압을 그대로 유지하고 있습니다.

따라서, 데이터는 보존이 될것입니다.

 

하지만 RAM은 보드에 전원이 빠지게 되변, 전압도 빠지게되고 데이터는 없어지게 됩니다.

다시한번 말씀드리면, 데이터는 메모리안에 전압을 저장하고 저장하지 않는 개념으로 0과 1이 저장이 됩니다.

 

그래서 Flash는 비휘발성 메모리(Non-Volatile Memory)라고 부르고, RAM은 휘발성 메모리(Volatile Memory)

라고 부르게 됩니다.

 

그렇다면, 우리가 SW를 열심히 만들어서 다운로드 가능한, elf or hex 파일을 만들었다고 한다면,

이제 이것을 저 검은박스안에 넣어야 할것인데

Flash에 넣어야 할까요? 아니면 RAM에 넣어야 할까요?

 

전원이 꺼져도, 다시 전원을 넣어주면, SW를 동작시켜야 하니까 Flash에 넣어주어야 할것입니다.

그렇습니다. 보통 소프트웨어를 만들면 Flash Memory쪽에 다운로드를 합니다.

 

그리고 메모리를 찾으면 Flash말고 다양한 메모리가 존재합니다.

요즘에는 Flash는 다운로드한 소프트웨어를 그대로 CPU가 Flash에서 Read 가능합니다.

따라서, Flash 메모리에 직접 접근하여 Read 할수 있고,

또한 한번 Download하여 굽는 방식이 아니라, 지속적으로 Erase하고 Download할수 있습니다.

 

따라서, 요즘 왠만한 MCU안에는 Flash 메모리를 넣고 있습니다.

위의 검은 박스도, Flash 메모리가 넣어져 있습니다.

 

그렇다면 RAM은 어떠한 역할을 할까요?

RAM에는 주로 정적전역변수 및 지역변수를 저장합니다.

때로는 우리가 만든 함수들중에 RAM에서 동작을 시켜야할 특수 함수들이 존재합니다.

정리하면 RAM은 크게 2가지 일을 수행하겠네요

1) 변수 저장

2) RAM에서 동작할 함수 저장

 

코드가 돌아가게 되면, CPU는 연산을 수행하게 됩니다.

그리고 연산 결과를 레지스터, 또는 RAM에 저장을 합니다.

 

Flash에도 저장할수 있습니다.

하지만 Flash에 Write를 수행하기 위해서는 Driver를 가지고 여러가지 설정을 수행해 주어야 합니다.

실시간 바로바로 CPU가 Wirte를 수행하기는 어렵지요!

그래서 RAM에서 저장을 합니다.

 

RAM은 크게 3가지 영역으로 나눕니다.

1) Data RAM : 전역변수, 정적변수들이 저장되는 공간

2) Heap : 동적할당을 통하여 변수를 할당하는 공간

3) Stack : 지역 변수를 할당하는 공간, 또한 Function CAll이 발생할떄 현재의 레지스터를 저장하는 공간으로도 사용

 

추후, Flash에서 코드를 다운하고,

전원이 들어갔을때, 어떠한 Sequence로 Start코드를 거쳐서 Main함수로 진입하는지

그리고 그 과정에서 .bss, .data section이 어떻게 Flash에서 RAM으로 이동하는지

그리고 지역변수로 사용되는 Stack이 어떠한 움직임으로 동작하는지

이러한 것을 어떻게 Linker Script 파일에서 설계할수 있는지 내용을 정리해 보도록 하겠습니다.

 

오늘은 General한 내용만을 생각해 주시면 좋을것 같습니다.

 

두서 없이 이야기를 했네요.

다시 말해서 Memory는 코드 및 변수를 저장하는 아주 중요한 Device라는 것을 알게 되었습니다.

그리고 지금 아주 중요한 예기를 하나 하면!

CPU는 메모리에 저장을 할떄 어떻게 저장할까요?

주소를 통해 저장합니다.

메모리는 바이트 단위로 주소를 가지고 있습니다.

예를 들어 

CPU야 1이라는 값을 0x50000000 주소에 저장해줘!

CPU야 0x50000004의 값을 읽어와서

1을 더해서 다시 0x50000004에 저장해줘!

 

이러한 동작들을 수행하려면, 메모리는 반드시 주소를 가지고 있어야 하고, CPU와 그 물리적인 메모리주소가 회로적으로 연결이 되어야 합니다.

 

메모리느 주소를 가지고 있다!!!

그리고 그 주소에 0과 1이라는 값을 적을수 있다.

 

아주 중요한 개념입니다.

 

그렇다면 한가지만 더 생각해 보고, 마무리르 짓도록 하겠습니다.

 

나는 GPIO라는 모듈에서 GPO에 5V 전압을 발생시키고 싶습니다.

GPO는 MCU과 외부로 통하는 출력 핀을 가지고 있습니다.

GPO는 0V의 전압을 만들어 낼수고 있고 5V의 전압도 만들어 낼수 있습니다.

 

CPU는 어떻게 저 GPO에게 0V를 내어라 5V를 내어라 명령할수 있을까요?

GPO안에는 레지스터 라는 장치가 들어 있습니다.

메모리랑 비슷하게 그 레지스터에다가 0또는 1이라는값을 적을수 있습니다.

 

다시 말해서 0과 1을 적을수 있는 곳이라면!!

레지스터도 주소를 가지고 있겠네요!!

 

그렇습니다.

MCU안에 모든 주변기기들은 레지스터를 가지고 있고

이러한 레지스터는 모두 미리 정해진 주소를 가지고있습니다.

입출력과 메모리의 주소 공간을 분리하지 않고 하나의 메모리 공간에 취급,

CPU가 직접 접근하여 Write 가능하도록 만든 방식을

Memory-mapped I/O, MMIO 라고 부릅니다.

오늘 포스팅은 이것으로 마무리 하도록 하겠습니다.

 

 

 

반응형

댓글