임베디드 개발(before)/IoT 임베디드 SW 개발자 양성과정

[29일차] ARM 프로세서 이해 및 활용 (Cache, MMU)

주운녕 2020. 8. 21. 14:17

● ARM 프로세서의 구조

 

더보기

Manual에 나와있는 블록도

● Cached ARM 프로세서의 제어

▷ CP15 인터페이스를 통해서 제어

- Cache, MPU,or MMU, endian 제어등

▷ Coprocessor Register Transfer 명령

- MRC : Move to Register from Coprocesser ::  내용을 ARM 레지스터로 전송

- MCR : Move to Coprocesser from Register :: ARM 레지스터 내용을 Coprocessor 레지스터로 전송

▷ 참고 자료 : https://blog.naver.com/kazama10/50179092022

 

[ARM Assembly] MRC, MCR

1. MRC 명령어 - coprocessor 내부의 레지스터를 에서 ARM 레지스터로 읽어들이는 명령어 - MRC{ c...

blog.naver.com

 

● Cache 메모리

2020/07/28 - [임베디드/IoT 임베디드 SW 개발자 양성과정] - [12일차] 임베디드 시스템 아키텍쳐-개발환경, 아키텍쳐

▷ Cache가 없으면 고속의 cpu가 버스 및 메모리 속도에 의존적이며 낮다.

▷ Cache가 있으면 CPU 주변에 고속의 메모리를 두고 자주 사용되는 명령과 데이터를 저장하여 시스템 성능을 개선한다.

 

Cache 메모리 : 프로세서가 최근에 액세스 한 메모리의 내용을 보관하고 있다가 다시 요청하면 메모리 액세스 없이 전달.

▷ 장점

- 버스의 사용장을 줄여 시스템 성능 향상

- 전력소모를 줄인다.

- 속도가 느린 메모리 시스템의 성능 개선

▷ 성능

- CPU가 데이터나 명령을 읽고자 하는데 cache 내에 원하는 명령이나 데이터가 없으면 -> Cache Miss

- Cache 제어기는 시스템 메모리 장치에서 line 크기 만큼 명령이나 데이터를 읽어 Cache 메모리에 저장(Line Fill)한다.

- Cache Line : Cache가 관리하는 최소한의 데이터 단위.

:: 4 word, 8 word 정도의 크기를 가진다.

▷ Cache Lockdown

- Cache의 일정 부분을 update 되지 않도록 한다.

:: 중요한 명령이나 데이터를 항상 Cache에 있도록 하여 성능 증가 및 보장.

- Cache Fluch 전에는 반드시 Lockdown을 해제하여야 한다.

(*Cache Fluch : Cache line의 data를 0으로 변경하여 초기화하는 작업)

set associative 방식

● Write Buffer

▷ Core와 버스의 서로 다른 속도 차 극복

- Core 속도로 write buffer에 데이터를 write

   :: write 후 cpu는 다른 작업 처리 가능

- Bus 속도로 write buffer의 내용을 메모리로 write

- write buffer는 FIFO형태(queue)의 구조를 가진다.

 

▷ Cache와 Write Buffer

▶ Write Through(buffer를 거치지 않을 때)

:: CPU가 특정 주소에 명령이나 데이터를 write하는 경우, 해당하는 명령이나 데이터가 Cache 메모리에 있을 때, Cache메모리와 외부메모리에 모두 쓰기 동작을 한다.

- write buffer를 거치지 않고 메모리에 저장.

 

▶ Write Back (Cpu가 buffer에 저장하고 돌아온다.)

- CPU가 특정 주소에 명령이나 데이터를 write하는 경우, 해당하는 명령이나 데이터가 Cache 메모리에 있을 때, Cache 메모리에만 쓰기 동작을 하고, 외부의 메모리에는 나중에 기록된다.

- Write Buffer를 사용한다.

 

● 메모리 관리 유닛(MMU) : 운영체제에 가상 메모리(Virtual Memory) 기능을 제공.

- (메모리 보호(MPU기능) + 메모리 주소 변환) 하기 위해 필요하다.

:: 연속적 물리 주소가 아니어도 CPU는 연속적 주소로 인식하여 메모리 확장 효과

:: 모든 프로세스마다 동일 주소 사용, CPU의 프로세스 관리 용이 및 구현 단순화

CPU는 가상주소로 메모리 찾고 그걸 mmu가 물리주소로 바꿔 메모리접근해서 데이터 찾은다음 전송한다!

▶ MMU의 구성

▷ Tanslation Lookaside Buffer (TLB)

- 최근에 사용된 가상주소를 물리적 주소로 변화하는 정보화 access permission에 대한 정보를 저장하고 있는 일종의 Cache.

▷ Translation Table Walking Logic

- TLB를 업데이트하고 관리하는 기능을 가진 logic

▷ Access Control Logic

 

▶ Translation Table (명령어와 데이터가 있는 System Memory에 위치!)

▷ Physical 메모리에 있는 translation 정보를 가지고 있는 Table

▷ Level 1 Translation Table

- 4096개의 32 비트 translation table entry

:: 4GB 메모리를 virtual address 1MB단위로 나누어 관리

:: virtual address 비트 [31:20] ( 0x[000]0 0000)

- Physical memory에 대한 1MB section 단위의 address translation 정보와 access control 정보를 가지거나, 레벨 2 table에 대한 주소 정보를 가진다.

 

▷ Level 2 Translation Table

- 64KB(large page), 4KB(small page), 1KB(tiny page) 단위의 translation table 정보를 가지고 있다.

- 각 translation table에는 address translation 정보와 access control정보를 가진다.

 

▶  Translation Lookaside Buffer(TLB) (ARM Processor 에 위치!)

▷ 최근에 사용된 가상 주소를 물리적 주소로 변화하는 정보접근 허용에 대한 정보를 저장하고 있는 일종의 "Cache"

▷ TLB가 가상 주소에 대한 translation table entry를 가지고 있으면 access control logic이 접근 가능을 판단.

- 접근이 허용되면 가상 주소를 물리적 주소로 변환 후 접근

- 접근의 허용이 안되면 cpu에서 abort 구동

▷ TLB에 가상 주소에 대한 정보가 없으면 translation table walkiong logic에서 table 정보를 physical메모리에서 읽어 TLB 업데이트.

 

 

● MMU 실습하기

▷ 가상의 주소와 물리적인 주소를 연결하는 실습.

 

▷ main문(main.c)

/*=========================*/
#include "my_lib.h"
#include "option.h"
#include "2450addr.h"
#include ".\images\bicycle.h"


void Main(void)
{
	int i;
	Uart_Init(115200);
	/* 
	 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
	 *   FROM HERE WE WILL TEST MMU
	 */
	
#if 1 /* MMU INIT */
	Uart_Printf("\nInitialize MMU..\n");
	
	/* 
	 * Initialize MMU 
	 * The MMU initialize routine was implemented at libc.c
	 */
	MMU_Init();
#else
	Uart_Printf("No-MMU..\n");
#endif

#if 1
{

	volatile unsigned long *value;
	value = (volatile unsigned long *)0x33000000;
	*value = 0x0;
	unsigned int result;
	
	/* 
	 * EXERCISE TODO : please compare the each cases below:
	 *	1. disable Cache, Write Buffer of TEXT(명령어)/DATA and TEST sections and measure it.
	 *  2. enable  Cache, Write Buffer of TEXT/DATA sections, 
	 *     disable Cache, Write Buffer of TEST and measure it.
	 *	3. enable  Cache, Write Buffer of TEXT/DATA and TEST area and measure it.
	 */

	Uart_Printf("Performance measure start ..\n");

	start_timer0();	   /* start timer */
	
	for (i=0;i<0x50000;i++)
		*value = *value + 1;  /* test */
	
	result = time();  /* get time lap */
	stop_timer0();		/* stop timer */
	
	Uart_Printf("Time spend for testing 0x%x.\n", result);

}
#endif

	Uart_Printf("MMU Test End\n");
	Uart_Send_String("\n\n");
	
#if 1
	/* Frame Buffer Access Test */
{
	Graphic_Init( );
	Lcd_Draw_BMP(0, 0, bicycle); 
}
#endif	
}

▷ mmu를 초기화 한 뒤, value 변수의 값을 0x50000번 1씩 증가시켜본다.

 

▶ mmu초기화 함수 MMU_Init.c  (lib.c 파일 내부)

void MMU_Init(void)
{
	unsigned long i,j;
	//========================== IMPORTANT NOTE =========================
	//The current stack and code area can't be re-mapped in this routine.
	//If you want memory map mapped freely, your own sophiscated MMU
	//initialization code is needed.
	//===================================================================

	MMU_DisableDCache();
	MMU_DisableICache();

	//If write-back is used,the DCache should be cleared.
	for(i=0;i<64;i++)
	for(j=0;j<8;j++)
    	    MMU_CleanInvalidateDCacheIndex((i<<26)|(j<<5));
	MMU_InvalidateICache();
       
	MMU_DisableMMU();
	MMU_InvalidateTLB();

	/* MMU_SetMTT(int vaddrStart,int vaddrEnd,int paddrStart,int attr) */
	MMU_SetMTT(0x00000000,0x07f00000,0x00000000,RW_NCNB); //bank0 C와 B비트 off
	MMU_SetMTT(0x08000000,0x0ff00000,0x08000000,RW_NCNB); //bank1
	MMU_SetMTT(0x10000000,0x17f00000,0x10000000,RW_NCNB); //bank2
	MMU_SetMTT(0x18000000,0x1ff00000,0x18000000,RW_NCNB); //bank3
	MMU_SetMTT(0x20000000,0x27f00000,0x20000000,RW_NCNB); //bank4
	MMU_SetMTT(0x28000000,0x2ff00000,0x28000000,RW_NCNB); //bank5
	
	/* 
	 * USER WILL TEST WITH BANK 6
	 * the each attribute value such as RW_CB, RW_NCNB, .... was decleared on libc.h
	 *
	 * 1. EXERCISE TODO: Please IMPLEMENT MMU_SetMTT function
	 */
	MMU_SetMTT(0x30000000,0x31f00000,0x30000000,RW_CB);//캐시 on/off설정이 아님. 캐시 쓸건지 안쓸건지 설정임.   //bank6-1, TEXT/DATA
	MMU_SetMTT(0x32000000,0x33e00000,0x32000000,RW_CB);   //bank6-2, TEST DATA,LCD FrameBuffer
	MMU_SetMTT(0x33f00000,0x33f00000,0x33f00000,RW_CB);   //bank6-3
	MMU_SetMTT(0x38000000,0x3ff00000,0x38000000,RW_NCNB); //bank7
    
	MMU_SetMTT(0x40000000,0x5af00000,0x40000000,RW_NCNB); //SFR+StepSram    
	MMU_SetMTT(0x5b000000,0xfff00000,0x5b000000,RW_FAULT);//not used

	/* 
	 * 2. EXERCISE TODO: Please IMPLEMENT MMU_SetTTBase function : libs.S 
	 */
	MMU_SetTTBase(_MMUTT_STARTADDRESS); //translation table 시작 주소
	
	/* DOMAIN1: no_access, DOMAIN0,2~15=client(AP is checked) */
	MMU_SetDomain(0x55555550|DOMAIN1_ATTR|DOMAIN0_ATTR); 

	MMU_SetProcessId(0x0);
	MMU_EnableAlignFault();

	/* 
	 * 3. EXERCISE TODO: Please IMPLEMENT MMU_EnableMMU,MMU_EnableICache and MMU_EnableDCache
	 *     : libs.S 
	 */
	MMU_EnableMMU();
	MMU_EnableICache(); //캐시 킴
	MMU_EnableDCache(); /* IMPORTANT : DCache should be turned on after MMU is turned on. */
}   

	/* 
	 * void MMU_SetMTT(int vaddrStart,int vaddrEnd,int paddrStart,int attr)
	 * -----------------------------------------------------------------
	 * Attribute : RW_CB,RW_CNB,RW_NCNB,RW_FAULT
	 */
void MMU_SetMTT(int vaddrStart,int vaddrEnd,int paddrStart,int attr)
{
	unsigned long *pTT;
	int i,nSec;
	
	/* 
	 * 1. EXERCISE TODO: Get Translation Table base address on Physical memory
	 *    Translation table held each 1 word translation descriptor for each 1MB section
	 *    The Level 1 translation descript location for each 1M section can be calcurated
	 *    from Translation Table Base address and virtual address 
	 *
	 *    The variable for actual translation descriptor location : pTT
	 *    MMU Translation Table Base Address : _MMUTT_STARTADDRESS
	 *	  Address bit [31:20] specify M byte address
	 */
	pTT=(unsigned long *) _MMUTT_STARTADDRESS +(vaddrStart>>20); //포인터 변수에 가상의 주소를 저장
	
	/*
	 * 2. EXERCISE TODO: We must configure each 1M section descriptor
	 *    So, we must get a number of section from start virtual address (vaddrStart)
	 *        to end of virtual address (vaddrEnd)
	 *    The number of scetion : nSec
	 */ 
	nSec=(vaddrEnd>>20)-(vaddrStart>>20);
	
	for(i=0;i<=nSec;i++) 
	{
		/*
		 * 3. EXERCISE TODO: We must write down physical address and attribute information to 
		 *    each section descriptor
		 *    Section descriptor location : *pTT
		 *    Configuration Value : (physical address information) | (attribute)
		 *        The physical address information was held from address bit 20 (1M byte address)
		 */
		*pTT++ = (((paddrStart>>20)+i)<<20) | attr ; //포인터 참조하여 가상의 주소안의 데이터로 물리적인 주소를 넣는다. 넣고 끝. 이제 가상주소의 안에 있는 데이터는 물리주소이다.
	}
} 

 

★이 함수에서 눈여겨볼 부분은 여기이다.

 *    MMU Translation Table Base Address : _MMUTT_STARTADDRESS
	 *	  Address bit [31:20] specify M byte address
	 */
	pTT=(unsigned long *) _MMUTT_STARTADDRESS +(vaddrStart>>20); //포인터 변수에 가상의 주소를 저장
	
	/*
	 * 2. EXERCISE TODO: We must configure each 1M section descriptor
	 *    So, we must get a number of section from start virtual address (vaddrStart)
	 *        to end of virtual address (vaddrEnd)
	 *    The number of scetion : nSec
	 */ 
	nSec=(vaddrEnd>>20)-(vaddrStart>>20);
	
	for(i=0;i<=nSec;i++) 
	{
		/*
		 * 3. EXERCISE TODO: We must write down physical address and attribute information to 
		 *    each section descriptor
		 *    Section descriptor location : *pTT
		 *    Configuration Value : (physical address information) | (attribute)
		 *        The physical address information was held from address bit 20 (1M byte address)
		 */
		*pTT++ = (((paddrStart>>20)+i)<<20) | attr ; //포인터 참조하여 가상의 주소안의 데이터로 물리적인 주소를 넣는다. 넣고 끝. 이제 가상주소의 안에 있는 데이터는 물리주소이다.

 

☆ 대략 진행

1) 가상의 주소 [31:20] (3byte)인 Translation table 의 기본(base) 주소를 설정한다.

2) 가상의 주소를 포인터 변수의 값으로 저장한다.

3) 포인터의 접근으로 가상의 주소 안에 [물리적인 주소 값]를 데이터로 넣는다.

 

가상의 주소를 간접 참조 연산으로 접근하면 물리적 주소로 접근할 수 있다.

결국 포인터를 잘 활용한 것!!!!!!

 

corprocessor의 P15인터페이스를 활용해서 캐시와 버퍼 비트를 켜거나 끌 수 있다.

이 부분의 어셈블리 함수 부분은 생략! (libs.S 에 저장되어 있다.)

 

 


 

@@ 참고하기

http://recipes.egloos.com/5170809

 

Cache, Cash?

Cache라는 건 뭡니까? Cash가 드는 넘 이죠. 흐흐. Cache라는 건 교활한 놈이에요. 돈 잡아 먹는 기계죠. 왜냐! 느린 Memory와 빠른 CPU사이에 장난을 쳐서 마치 빠른 것처럼 만들어 주는 사기꾼인 거죠. �

recipes.egloos.com

http://recipes.egloos.com/5232056

 

MMU (Memory Management Unit)

MMU는 CPU의 Memory 주소를 감쪽같이 속이는 거짓말쟁이에요. MMU는 표현하고 행동해요. CPU가 Memory를 Access할 때 마다 주소를 속인답니다. 주소를 속여서 어떻게 하느냐, Physical Address와 Virtual Address (Lo

recipes.egloos.com


* 개인적인 학습 목적으로 작성한 글이기에 내용에 잘못된 정보가 있을 수 있습니다.