정보공간_1

[6기 전주 황규하] TizenProject/platform/kernel/u-boot/drivers/serial/serial_s3c24x0.c 분석 본문

IT 놀이터/Elite Member Tech & Talk

[6기 전주 황규하] TizenProject/platform/kernel/u-boot/drivers/serial/serial_s3c24x0.c 분석

알 수 없는 사용자 2014. 10. 20. 16:43

이전에 TizenProject 소스를 받는 방법을 알아봤다면, 이번에는 TizenProject중 일부 소스를 분석하고자 합니다. 저는 개인적으로 커널에 관심이 많았기 때문에 커널 소스를 다루고자 합니다. 그 중에서도 TizenProject/platform/kernel/u-boot/drivers/serial/serial_s3c24x0.c라는 s3c24x0 시리즈의 serial통신 코드에 대해서 분석할 예정입니다. 일단 분석을 편하게 하기 위해서는 Ctags라는 것이 필요합니다. Ctags는 소스간의 연관관계에 대해 파일을 만들어 분석을 편하게 해주는 툴입니다. 자세한 사항은 다음 블로그를 참고하시면 좋을 것 같습니다.

 

Ctags 설정 및 사용방법 : http://blog.daum.net/heyjun/15705400

 

그러면 소스 파일을 한번 열어 보겠습니다.

DECLARE_GLOBAL_DATA_PTR의 정의로 이동해 살펴보면, 다음과 같습니다.

register 키워드는 변수가 생성되는 메모리를 register로 하겠다는 이야기입니다. Volatile은 이 변수가 바뀔 수 있으니 최적화를 하지말라는 키워드입니다.  gcc에서는 asm(“”)을 사용하면 어셈블리를 사용할 수 있습니다. Register25번을 gd_t *gd전용으로 사용할 목적으로 정의해 놓았습니다. 그렇다면 gd_t를 살펴보겠습니다.

gd_t struct global_data의 타입이 재정의 된 것으로 cpu clock, bus clock, board type malloc base, malloc limit, malloc ptr등 프로세서의 아키텍쳐에 관련된 것들을 저장할 수 있는 타입으로 정의 되어있습니다. 그러면 다시 원래 소스로 돌아와 보도록 하겠습니다.

전처리기로 처리되어있는 저 부분을 보면 CONFIG_SERIAL(n)이 정의 됨에 따라 UART_NR S3C24X0_UART(n)으로 정하는 부분입니다. 그리고 아무것도 정의되어 있지 않을 경우에는 #error 지시문을 사용하게 되는데 이것은 컴파일 타임에 에러를 출력하고 컴파일을 중지시킬 수 있는 지시문입니다.

다음 소스를 살펴보면 다음과 같습니다.

##을 사용하면 token-pasting을 할 수 있습니다. 즉 전처리 과정을 거칠 때, 그 부분의 값을 문자열로 처리하여 이어 붙여주는 역할을 합니다. 좀 더 자세히 이야기하자면 DECLARE_S3C_SERIAL_FUNCTIONS(0) 이라고 사용을 하게 되면 int s3serial0_init(void) 함수가 선언이 되고 port값에 1을 넣어주게 되면 int s3serial1_init(void)함수가 선언이 됩니다.

 아래의 INIT_S3C_SERIAL_STRUCTURE(port, __name) 부분이 있지만 위와 맥락이 같으므로 넘어가고 void _serial_setbrg(cons tint dev_index) 함수를 살펴보도록 하겠습니다.

Struct s3c24x0_uart의 정의로 이동해서 살펴보면 다음과 같습니다. u32 unsigned int, u8unsigned short을 나타냅니다.

다음은 s3c2440 uart 레지스터 부분입니다.


구조체내부에 정의 되어있는 부분이 순서대로 나타나있습니다. 구조체는 이 레지스터에 접근 하기 위한 구조체이고 ulcon부터 umstat까지는 레지스터간의 주소차이가 0x04차이가납니다. 다시말해보면 4바이트의 크기만큼의 정보를 가진다는 말이 됩니다. 이후, 레지스터 주소차이가 다르게 나는데 이 부분은 u8과 배열을 이용하여 매치 시켰습니다. 이 부분에서는 Endian에 따라 다르기 때문에 리틀인디안과 빅인디안을 구분하여 구조체를 정의한 것을 볼 수 있습니다.

 

s3c24x0_get_base_uart()함수의 정의를 따라가 보겠습니다.

S3C24X0_UART_BASE는 주소값이 매칭 정의 되어있습니다. 여기에 0x4000 uart번호에 곱한다음 그 값을 s3c24x0_uart 구조체를 가르키는 포인터형으로 변환한 다음 반환하고 있습니다.

위에 s3c2440 레지스터 표에서 보듯이 uart0번과 uart1의 시작 주소 차이가 0x4000이 나기 때문에 다음과 같이 함수를 정의해 놓았습니다.

 

다음으로 writel(reg, &uart->ubrdiv)를 살펴보도록 하겠습니다. reg라는 int형의 값을 get_PCLK() / (16* gd->baudrate) -1;로 정의가 되어있습니다. 이 부분은 ubrdiv 레지스터 부분을 데이터시트에서 찾아보도록 하겠습니다.

 Ubrdiv uart baudrate divisior로 정의가 되어있고, 다음과 같이 PCLOCK 값을 baudrate에 적용할 수 있도록 시간을 나누는데 쓰였습니다. 위 소스는 이 공식에 맞추어 쓰였습니다.

 

아직도 소스는 많이 남아있지만 이번 블로그는 여기까지 게재하도록 하겠습니다.

제가 게재한 것을 극히 일부분이긴 하지만 어떤 식으로 소스를 분석을 해야 하는지를 쓰려고 노력했습니다. 이 글이 오픈소스를 시작하는데 작은 도움이 됬으면 하는 바램입니다. 이상 마치겠습니다.