[첨단 헬로티]
메모리의 접근 속도, 다시 말해 메모리의 정보를 읽고 쓴는 속도는 메모리 구조상 ROM 또는 Flash 영역보다 RAM의 속도가 빠르다. 하지만 RAM은 휘발성 메모리이기 때문에 전원공급이 없으면 메모리의 데이터는 삭제된다. 따라서, 일반적으로 코드 저장 용도로 사용하지 않는다. 하지만 소스코드의 속도를 최대한 올려야하는 경우 코드를 RAM으로 복사해 RAM 메모리에서 수행하도록 하는 방법이 있다.
우선 코드를 RAM에 배치하는 크게 두 가지 경우가 있다. 디버깅 중 RAM에 모든 코드/데이터를 배치해 실행하는 방법과 ROM 또는 Flash 영역에 코드/데이터를 저장해 두고 MCU 초기화 과정에서 RAM으로 함수를 복사한 후 실행하는 방법이 있다.
디버깅에서 코드/데이터를 모두 RAM에 위치시키는 방법
이 방업은 별도의 특별한 코드의 수정이나 옵션의 설정 사항은 없다. 링커 설정 파일(.icf)내 readonly 속성의 코드와 데이터가 배치되는 영역을 모두 RAM의 주소 영역으로 변경하면 링커가 모든 위치를 RAM의 주소로 배치하게 된다. 다음의 링커 설정 파일의 예를 참조한다.
다음은 빌드 후 링커 map 파일의 내용이다. 모든 코드와 데이터가 RAM 영역에 들어가 있는 것을 확인할 수 있다.
위의 방법은 매우 간단해 디버깅 중 테스트의 목적으로 활용이 가능하다. 다만 모든 코드,데이터가 RAM에 위치하게되므로 디버깅 프로브가 보드에서 분리되고 전원이 끊어지면 단독 동작을 하지 않는다.
ROM 또는 Flash 영역에 코드/데이터를 저장 후 RAM으로 복사 방법
디버거가 연결 되지않는 단독 동작의 상태에서 코드와 데이터를 RAM으로 위치시키려면 우선 코드와 데이터 정보를 ROM/Flash 영역에 저장하고 MCU 디바이스에 전원 인가돼 초기화될 때 초기화 중 코드/데이터를 RAM으로 복사 후 동작시키는 방법이다.
코드의 종류와 작성 방법에 따라 크게 3가지 방법이 있다.
1. RAM에 배치하는 함수를 개별적으로 지정하는 방법
2. RAM에 배치하는 함수를 파일 단위로 지정하는 방법
3. RAM에 배치하는 함수를 전부 지정하는 방법
RAM에 배치하는 함수를 개별적으로 지정하는 방법
특정 함수 만 RAM에 배치하려는 경우에는 해당 함수 선언문 앞에 __ramfunc 지시어를 추가하는 방법을 사용할 수 있다. __ramfunc 지시어는 IAR Embedded Workbench에서 지원되는 확장 키워드이다. 다음의 예를 참조한다.
링커 설정 파일의 경우 이 전 디버거를 활용해 RAM에 배치한 방법과 다르게 실제 MCU의 RAM, ROM주소로 설정한다.
맵 파일을 보면 __ramfunc 선언한 함수 func1과 변수 x가 RAM에 배치되고 나머지 함수는 ROM 영역에 배치되어 있다.
RAM에 배치하는 함수를 파일 단위로 지정하는 방법
위의 예제에서 RAM으로 위치를 옮긴 함수는 main 함수이다. main 함수는 main.c에 포함되어 있다. 그리고 main.c 파일을 컴파일 한 결과인 오브젝트 파일은 main.o이다. 파일단위로 코드를 RAM으로 옮기는 방법은 컴파일된 결과인 오브젝트 파일을 사용한다.
링커 설정 파일(.icf)에서 initialize by copy라는 명령을 사용한다. 일반적으로 초기화가 필요한 변수를 RAM으로 복사하는데 사용되지만, 오브젝트의 코드/데이터 전체를 RAM으로 복사하도록 할 수 있다.
아래의 코드 예의 경우initialize by copy 를 사용해 RAM으로 위치 변경을 하면, 함수 func1, main과 변수 x가 RAM 영역에 배치되고 상수(변수) y가 ROM 영역에 배치된다.
링커 설정 파일에서initialize by copy 를 사용하여 main.o의 읽기 전용 속성의 코드를 RAM으로 복사, 초기화 한다.
여기서 함수뿐만 아니라 상수가 되는 변수 y를 RAM에 배치하려는 경우에는 ‘ro code object main.o’를 ‘ro object main.o’ 라고하는 것으로 변경하면 코드 뿐 아니라 데이터도 RAM으로 위치시킬 수 있다.
사용자 함수를 모두 RAM에 배치하는 방법
이 전 까지의 방법들은 함수단위 또는 컴파일 완료된 오브젝트 단위로 코드와 데이터를 RAM으로 위치 시키는 방법이었다. 하지만 전체의 모든 코드를 RAM으로 한번에 위치시켜야하는 경우 다음의 방법을 사용할 수 있다.
오브젝트 단위로 RAM으로 위치시키는 방법과 동일하게 initialize by copy 명령을 이용한다. 다만 특정 오브젝트를 지정하는 것이 아닌 모든 코드를 RAM으로 배치하도록 명령한다. 이 방법에서 인터럽트 벡터 테이블은 ROM의 시작주소에 위치해야 하기에 except를 사용해 인터럽트 벡터 영역을 initialize by copy에서 제외해야 한다.
주의점
벡터 테이블을 포함한 초기화 코드는 ROM에 배치해야 한다. 리셋에서 초기화 완료 되기까지 필요로하는 함수를 ROM에서 실행되도록 배치해야 한다.
맺음말
__ramfunc 지시어를 포함한 다양한 방법으로 코드를 RAM으로 옮겨 실행 할 수 있다. ROM보다는 읽기,쓰기 속도가 빠른 RAM으로 다양한 방법을 활용해 코드를 위치시키면 최적화된 소프트웨어 수행 속도를 만들 수 있다.
글 / IAR Systems 이현도 과장