GoogleTV Update Procedure

Similar documents
GoogleTV Update Procedure

Chapter #01 Subject

GoogleTV Update Procedure

Mango220 Android How to compile and Transfer image to Target

Android Device Driver Hacks : interrupt handler, tasklet, work queue, kernel thread, synchronization, transferring data between kernel & user space (

untitled

Mango-AM335x LCD Type 커널 Module Parameter에서 변경하기

6주차.key

임베디드시스템설계강의자료 6 system call 2/2 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과

10주차.key

Microsoft PowerPoint - polling.pptx

KEY 디바이스 드라이버

untitled

[ 마이크로프로세서 1] 2 주차 3 차시. 포인터와구조체 2 주차 3 차시포인터와구조체 학습목표 1. C 언어에서가장어려운포인터와구조체를설명할수있다. 2. Call By Value 와 Call By Reference 를구분할수있다. 학습내용 1 : 함수 (Functi

DE1-SoC Board

K&R2 Reference Manual 번역본

C# Programming Guide - Types

PowerPoint 프레젠테이션

임베디드시스템설계강의자료 4 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과

UI TASK & KEY EVENT

PCServerMgmt7


1217 WebTrafMon II

<4D F736F F F696E74202D20B8B6C0CCC5A9B7CEC7C1B7CEBCBCBCAD202839C1D6C2F7207E203135C1D6C2F >

임베디드시스템설계강의자료 6 system call 1/2 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과

Microsoft Word - FunctionCall

MAX+plus II Getting Started - 무작정따라하기

10.

Embeddedsystem(8).PDF

Microsoft PowerPoint - 03-Development-Environment-2.ppt

<C0CCBCBCBFB52DC1A4B4EBBFF82DBCAEBBE7B3EDB9AE2D D382E687770>

Abstract View of System Components

슬라이드 1


슬라이드 제목 없음

¨ìÃÊÁ¡2

(Asynchronous Mode) ( 1, 5~8, 1~2) & (Parity) 1 ; * S erial Port (BIOS INT 14H) - 1 -

iii. Design Tab 을 Click 하여 WindowBuilder 가자동으로생성한 GUI 프로그래밍환경을확인한다.

Mango-IMX6Q mfgtool을 이용한 이미지 Write하기

<4D F736F F F696E74202D20BBB7BBB7C7D15F FBEDFB0A3B1B3C0B05FC1A638C0CFC2F72E BC8A3C8AF20B8F0B5E55D>

PowerPoint 프레젠테이션

Smart Power Scope Release Informations.pages

( )부록

- 코드로읽는리눅스디바이스드라이버 강남용

교육지원 IT시스템 선진화

서현수

강의10

SRC PLUS 제어기 MANUAL

C. KHU-EE xmega Board 에서는 Button 을 2 개만사용하기때문에 GPIO_PUSH_BUTTON_2 과 GPIO_PUSH_BUTTON_3 define 을 Comment 처리 한다. D. AT45DBX 도사용하지않기때문에 Comment 처리한다. E.

슬라이드 1

chap 5: Trees

hd1300_k_v1r2_Final_.PDF

Microsoft PowerPoint APUE(Intro).ppt

Microsoft PowerPoint Android-SDK설치.HelloAndroid(1.0h).pptx

슬라이드 1

Microsoft PowerPoint Driver-Time-7.ppt

Building Mobile AR Web Applications in HTML5 - Google IO 2012

PRO1_04E [읽기 전용]

CPX-E-EC_BES_C_ _ k1

UI TASK & KEY EVENT

CAN-fly Quick Manual

Here is a "PLDWorld.com"... // EXCALIBUR... // Additional Resources // µc/os-ii... Page 1 of 23 Additional Resources: µc/os-ii Author: Source: HiTEL D

Microsoft Word - ASG AT90CAN128 모듈.doc

Microsoft PowerPoint - ch09 - 연결형리스트, Stack, Queue와 응용 pm0100

휠세미나3 ver0.4

PowerPoint 프레젠테이션

Microsoft Word - PEB08_USER_GUIDE.doc

<4D F736F F F696E74202D20B8AEB4AABDBA20BFC0B7F920C3B3B8AEC7CFB1E22E BC8A3C8AF20B8F0B5E55D>

UI TASK & KEY EVENT

T-DMB lipsync issue 검토

vm-웨어-01장

CANTUS Evaluation Board Ap. Note

Chapter. 5 Embedded System I Bootloader, Kernel, Ramdisk Professor. Jaeheung, Lee

/chroot/lib/ /chroot/etc/

Microsoft PowerPoint SDK설치.HelloAndroid(1.5h).pptx

목차 BUG offline replicator 에서유효하지않은로그를읽을경우비정상종료할수있다... 3 BUG 각 partition 이서로다른 tablespace 를가지고, column type 이 CLOB 이며, 해당 table 을 truncate

(SW3704) Gingerbread Source Build & Working Guide

A Hierarchical Approach to Interactive Motion Editing for Human-like Figures

PowerPoint 프레젠테이션

지난시간에... 우리는 kernel compile을위하여 cross compile 환경을구축했음. UBUNTU 12.04에서 arm-2009q3를사용하여 간단한 c source를빌드함. 한번은 intel CPU를위한 gcc로, 한번은 ARM CPU를위한 gcc로. AR

구조체정의 자료형 (data types) 기본자료형 (primitive data types) : char, int, float 등과같이 C 언어에서제공하는자료형. 사용자정의자료형 (user-defined data types) : 다양한자료형을묶어서목적에따라새로운자료형을


00 SPH-V6900_....

Sena Technologies, Inc. HelloDevice Super 1.1.0

ESP1ºÎ-04

<4D F736F F D F4E464320B1E2BCFAB0FA20BCADBAF1BDBAC0C720C7F6C0E7BFCD20B9CCB7A120C0FCB8C15FBCF6C1A45F>

Microsoft Word - MV210_CPUSpec.doc

Microsoft Word - ExecutionStack

Microsoft PowerPoint - ch07.ppt

Special Theme _ 모바일웹과 스마트폰 본 고에서는 모바일웹에서의 단말 API인 W3C DAP (Device API and Policy) 의 표준 개발 현황에 대해서 살펴보고 관 련하여 개발 중인 사례를 통하여 이해를 돕고자 한다. 2. 웹 애플리케이션과 네이

13주-14주proc.PDF

PowerPoint Presentation

Microsoft Word doc

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

김기남_ATDC2016_160620_[키노트].key

Something that can be seen, touched or otherwise sensed

chap7.key

untitled

Transcription:

Android Device Driver Hacks : platform driver, work queue, tasklet, wakelock chunghan.yi@gmail.com, slowboot

Revision 작성자비고 0.1 이충한 최초작성 11/11/2011 0.2 이충한 11/15/2011 0.3 이충한 11/16/2011 0.4 이충한 11/17/2011

목차 1. Platform Device & Driver 2. Task & Scheduling 3. Bottom Halves and Deferring Work Tasklet, Softirq, Work Queue, Kernel thread 4. Timer 5. Wakelock 6. Synchronization 7. Notifier 8. Example Driver bluetooth sleep mode driver(todo) 9. Debug(TODO) Appendix TODO References

0. 이문서에서다루고자하는내용 1) Platform driver 2) Interrupt handler, tasklet, work queue, kernel thread, timer 3) Wakelock, synchronization & wait queue issue 4) Kernel panic/oops debug 평이하고일반적인내용은빼고 ( 이건 device driver book을참조하시길 ), Qualcomm Device Driver에서자주사용되는방식위주로기술 단순코드나열보다는그림을통해분석하고함!!! (*) 본문서는 Gingerbread 2.3.4(linux kernel 2.6.35) 를기준으로작성하였으나, 일부내용은 kernel version 과정확히일치하지않을수있음. (*) 본문서에기술되어있는 API 혹은 data structure 내용중에는오탈자가포함되어있을수있으며, 경우에따라서는의도적으로생략한부분도있으니, 정확한정보를위해서는관련헤더파일을참조해주시기바람.

1. Platform Device & Driver(1) - 개념 1) Embedded system 의시스템의경우, bus 를통해 device 를연결하지않는경우가있음. bus 는확장성 (enumeration), hot-plugging, unique identifier 를허용함에도불구하고... 2) platform driver/platform device infrastructure 를사용하여이를해결할수있음. platform device 란, 별도의 bus 를거치지않고, CPU 에직접연결되는장치를일컬음. bus CPU bus Platform Device 1 Platform Device 2 Platform Device 3

1. Platform Device & Driver(1) - 개념 - platform_device 정의및초기화 - resource 정의 (arch/arm/mach-msm/board- XXXX.c 파일에위치함 ) < 예 bluetooth sleep device> struct platform_device my_bluesleep_device = {.name = bluesleep,.id = 0,.num_resources = ARRAY_SIZE(bluesleep_resources),.resource = bluesleep_resources, }; - platform_driver 정의및초기화 - probe/remove.name 필드 ( bluesleep ) 로상호연결 (drivers/xxxx/xxxx.c 등에위치함 ) struct platform_driver bluesleep_driver = {.remove = bluesleep_remove,.driver = {.name = bluesleep,.owner = THIS_MODULE, }, };

1. Platform Device & Driver(2) platform driver (*) drivers/serial/imx.c file 에있는 imx serial port driver 를예로써소개하고자함. 이드라이버는 platform_driver structure 를초기화함. (*) init/cleanup 시, register/unregister 하기

1. Platform Device & Driver(3) platform_device (*) 플랫폼디바이스는동적으로감지 (detection) 가될수없으므로, static 하게지정해주어야함. static 하게지정하는방식은 chip 마다다를수있는데, ARM 의경우는 board specific code (arch/arm/mach-imx/mx1ads.c) 에서객체화및초기화 (instantiation) 를진행하게됨. (*) Platform 디바이스와 Platform 드라이버를 matching 시키기위해서는 name( 아래의경우는 "imx-uart") 을이용함.

1. Platform Device & Driver(4) - platform_device( 초기화 ) (*) platform device 는아래 list 에추가되어야하며, (*) platform_add_devices() 함수를통해서실제로시스템에추가됨.

1. Platform Device & Driver(5) - platform_device(resource) (*) 특정드라이버가관리하는각장치 (device) 는서로다른 H/W 리소스를사용하게됨. I/O 레지스터주소, DMA 채널, IRQ line 등이서로상이함. (*) 이러한정보는 struct resource data structure 를사용하여표현되며, 이들 resource 배열은 platform device 정의부분과결합되어있음. (*) platform driver 내에서 platform_device 정보 (pointer) 를이용하여 resource 를얻어오기위해서는 platform_get_resource_byname( ) 함수가사용될수있음.

1. Platform Device & Driver(6) - platform_device(device specific data) (*) 앞서설명한 resource data structure 외에도, 드라이버에따라서는자신만의환경혹은데이터 (configuration) 을원할수있음. 이는 struct platform_device 내의 platform_data 를사용하여지정가능함. (*) platfor_data 는 void * pointer 로되어있으므로, 드라이버에임의의형식의데이타전달이가능함. (*) imx 드라이버의경우는 struct imxuart platform data 가 platform_data 로사용되고있음.

1. Platform Device & Driver(7) platform driver(probe, remove) (*) 보통의 probe 함수처럼, 인자로 platform_device 에의 pointer 를넘겨받으며, 관련 resource 를찾기위해다른 utility 함수를사용하고, 상위 layer 로해당디바이스를등록함. 한편별도의그림으로표현하지는않았으나, probe 의반대개념으로드라이버제거시에는 remove 함수가사용됨.

다음장으로넘어가기전에 <work 정의 > 1) task 2) some function routine : interrupt handler, softirq, tasklet, work queue, timer function (*) 앞으로설명할 task/scheduling, top/bottom halves, timer routine 등은모두아래와같은형태로일반화시켜생각해볼수있을듯하다. 너무일반화시켰나 ^^ (*) 한가지재밌는것은이러한구조는 kernel 내에서뿐만아니라, Android UI 내부 Message 전달구조및 media framework 의핵심인 stagefright event 전달구조에서도유사점을찾을수있다는것이다 ^^. < 실행요청 > 1) schedule 2) Interrupt 3) it s own schedule func < 처리루틴 > w/, w/o queue 1) runqueue, waitqueue 2) work queue 3) no queue interrupt, tasklet, timer function 1) scheduler 2) interrupt handling, tasklet processing, timer processing, 3) worker thread

2. Task & Scheduling(1) 1) add_wait_queue 는 task 를 wait queue 에추가하고, task 의상태를 TASK_INTERRUPTIBLE 로변경시킴. 2) 이어호출되는 schedule() 함수는 task 를 runqueue 에서제거해줌. TASK_RUNNING current task_struct task_struct task_struct thread_info task_struct task_struct task_struct thread_info TASK_INTERRUPTIBLE <run queue> <wait queue> 1) Task 가기다리던 event 가발생하면, try_to_wake_up() 함수는 task 의상태를 TASK_RUNNING 으로변경시키고, activate_taks() 함수를호출하여 task 를 runqueue 에추가시킴. 2) remove_wait_queue 는 task 를 wait queue 에서제거함. (*) task 관련 queue 로는 wait queue 와 run queue 가있으며, run queue 에등록된 task 는실행되고, wait queue 에등록된 task 는특정조건이성립될때까지기다리게된다. (*) 위에서언급된특정함수는버전에따라차이가있을수있음. 단, 전체적인개념은동일함.

2. Task & Scheduling(2) (*) task, wait queue, run queue 간의관계를다른각도에서보여주는그림으로, wake_up 함수가호출되면, 대기중이던해당 task 가 run queue 로이동하여 CPU 를할당받게된다 (Scheduler 가그역할을담당함 ). wake_up CPU current wait queue wait queue wait queue 프로세스 task_struct 프로세스 task_struct 프로세스 task_struct run queue 프로세스 task_struct

2. Task & Scheduling(3) - schedule 함수 (*) schedule(), waitqueue, runqueue 등의개념을정확히이해하면앞으로설명하게될 bottom half & deferring work 관련코드를이해하는데도많은도움이될수있겠다 ^^ schedule( ) : runqueue 에서 process(task) 를하나꺼내어, 그것을 CPU 에게할당해주는것을의미 (scheduler 가작업해줌 ). 여러 kernel routine 에의해서직 / 간접적으로호출됨. < 직접호출방법요약 > 1) Insert current in the proper wait queue. current process(task) 를 wait queue 에넣어둠. 2) Changes the state of current either to TASK_INTERRUPTIBLE or to TASK_UNINTERRUPTIBLE. current process 의상태를 TASK_INTERRUPTIBL 혹은 TASK_UNINTERRUPTIBLE 로지정함. 3) Invokes schedule( ). schedule 함수를호출함. 즉, 다른 process(task) 에게 CPU 를사용할기회를줌. 4) Checks if the resource if available; if not, goes to step 2. current process 가사용할 resource 가사용가능한지체크하여, 없으면 2 로 jump 하여대기함. 5) Once the resource is available, removes current from the wait queue. current process 가사용할 resource 가사용가능하면, current process 를 wait queue 에서빼냄 (runqueue 로이동함 ).

2. Task & Scheduling(4) - sleeping & waking up (*) 아래내용은이전 page 의내용을 Sleeping & Waking up 관점에서다시정리한것임. (*) TODO: 현재 version 에맞게수정해야함. /* q is the wait queue we wish to sleep on */ DECLARE_WAITQUEUE(wait, current); add_wait_queue(q, &wait); while (!condition) { /* condition is the event that we are waiting for */ set_current_state(task_interruptible); if (signal_pending(current) /* handle signal */ schedule(); } set_current_state(task_running); remove_wait_queue(q, &wait);

3. Bottom Halves and Deferring Work - 개념 0. Interrupt Handler 를 top half 라고하며, 지연처리 (deferring work) 가가능한루틴을 bottom half 라고함. 1. (bottom half 중에서도 ) 해당작업이 sleep 가능하거나 sleep 이필요할경우 : work queue 사용 process context 에서실행 2. 1 의조건에해당하지않으며빠른처리가필수적인경우 : tasklet 사용 interrupt context 에서실행 Softirq 도 tasklet 과동일한구조이나, 사용되는내용이정적으로정해져있음. 따라서 programming 시에는동적인등록이가능한 tasklet 이사용된다고이해하면될듯 ^^ 3. tasklet 과 softirq 의관계와마찬가지로, work queue 는 kernel thread 를사용하여구현되어있음. CPU Interrupt handler(top half) Device interrupt I S R Tasklet( 지연가능, sleep 불가능 ) X Work Queue( 지연가능, sleep 가능 ) kernel thread 와연계

3. Bottom Halves and Deferring Work interrupt & process context <interrupt context(=atomic context) 의제약사항 > (*) user space 로의접근이불가능하다. Process context 가없으므로, 특정 process 와결합된 user space 로접근할방법이없다. (*) current 포인터 ( 현재 running 중인 task pointer) 는 atomic mode 에서는의미가없으며, 관련코드가 interrupt 걸린 process 와연결되지않았으므로, 사용될수없다 (current pointer 에대한사용불가 ). (*) sleeping 이불가하며, scheduling 도할수없다. Atomic code 는 schedule() 함수를 call 해서는안되며, wait_event 나 sleep 으로갈수있는어떠한형태의함수를호출해서도안된다. 예를들어, kmalloc(, GFP_KERNEL) 을호출해서는안된다. Semaphone 도사용할수없다. (*) 위의내용은앞으로설명할 interrupt handler 와 tasklet 에모두적용되는내용임. (*) 반대로, work queue 는 process context 에서동작하므로위에서제약한사항을모두사용할수있음 ^^.

3. Bottom Halves and Deferring Work - Interrupt Handler(top half) (*) Bottom half 를설명하기에앞서, top half(interrupt handler) 를먼저언급할필요가있어, 이곳에정리하였음. int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *), unsigned long flags, const char *devices, void *dev_id); Interrupt handler 등록 (*) /proc/interrupts 에서인터럽트상태를확인할수있음! Interrupt handler H/W interrupt 가발생할때마다호출됨 synchronize_irq() free_irq 를호출하기전에호출하는함수로, 현재처리중인 interrupt handler 가동작을완료하기를기다려줌. free_irq() 인터럽트 handler 등록해제함수 disable_irq() 해당 IRQ 라인에대한 interrupt 리포팅을못하도록함. disable_irq_nosync() Interrupt handler 가처리를끝내도록기다리지않고바로 return 함 enable_irq() 해당 IRQ 라인에대한 interrupt 리포팅을하도록함. *) 인터럽트처리중에또다른인터럽트가들어올수있으니, 최대한빠른처리가가능한코드로구성하게됨. *) 이부분을 tasklet 코드로도채울수있음!

3. Bottom Halves and Deferring Work - Interrupt Handler(top half) <Interrupt handler 사용예 >

3. Bottom Halves and Deferring Work - Tasklet tasklet list (*) tasklet 과 softirq 의동작원리는동일함. 다만, softirq 는 compile-time 에이미내용 (action) 이정해져있으며, tasklet 은 dynamic 하게등록할수있는형태임. (*) tasklet 은동시에하나씩만실행됨 (count 와 state 값을활용 ) 이는 multi-processor 환경에서도동일하게적용됨. (*) tasklet 은 task 개념과는전혀무관하며, 또한 work queue 와는달리 Kernel thread 를필요로하지않음 ( 그만큼간단한작업을처리한다고보아야할듯 ^^). my_tasklet my data my_tasklet_handler { } tasklet_schedule(&my_tasklet) 이것이호출되면 tasklet handler 실행됨 reference count, state tasklet_init(&my_tasklet, my_tasklet_handler) or DECLARE_TASKLET(my_tasklet, my_tasklet_handler, my_data) 초기화 my_tasklet_handler(my_data) will be run! 얘는빠르게처리되는코드이어야함!

3. Bottom Halves and Deferring Work - Tasklet <data structure 일부발췌 include/linux/interrupt.h>

3. Bottom Halves and Deferring Work - Tasklet <tasklet 사용예 >

3. Bottom Halves and Deferring Work - Work Queue(default) <my work work_struct> data func (work handler) (*) work queue 라고하면, work, queue, worker thread 의세가지요소를통칭함. (*) work queue 를위해서는반드시 worker thread 가필요함. (*) 기정의된 worker thread(events/0) 를사용하는방식과새로운 worker thread 및 queue 를만드는두가지방법이존재함. (*) work queue 에서사용하는 work 는 sleep 이가능하다. (*) worker thread 관련보다자세한사항은 kernel/workqueue.c 파일참조 <worker thread> Set task state to TASK_INTERRUPTIBLE schedule_work or schedule_delayed_work < 기정의된 work thread 를사용하는경우 > work queue schedule_work( ) 엔트리를 work queue 에추가함 schedule_delayed_work( ) 엔트리를 work queue 에추가하고, 처리를지연시킴 flush_scheduled_work( ) work queue 의모든엔트리를처리 ( 비움 ) cancel_delayed_work( ) delayed work( 엔트리 ) 를취소함. Add itself(thread) to wait queue ( sleep) If work list is empty then schedule Else set task state to TASK_RUNNING Remove itself from wait queue ( wakeup) Run work queue 여기서 func 함수호출됨 loop

3. Bottom Halves and Deferring Work - Work Queue( 사용자정의 ) < 사용자정의 work queue 관련 API 모음 > struct workqueue_struct *create_workqueue(const char *name); 사용자정의워크큐및 woker thread 를생성시켜줌. queue_work( ) my work queue int queue_work(struct workqueue_struct *wq, struct work_struct *work); 사용자정의 work 을사용자정의 work queue 에넣고, schedule 요청함. my work int queue_delayed_work(struct workqueue_struct *wq, struct work_struct *work, unsigned long delay); queue_work 과동일하나, delay 값을주어, delay 후에 schedule 하도록요청 my thread my work void flush_workqueue(struct workqueue_struct *wq); 사용자정의 work queue 에있는모든 work 을처리하여, queue 를비우도록요청 (create_workqueue 에인수로넘겨준 name 값이 thread name 이됨 ps 명령으로확인가능 ) (*) 사용자정의 work queue 를생성하기위해서는 create_workqueue() 를호출하여야하며, queue_work() 함수를사용하여 work 을 queue 에추가해주어야한다. (*) 보통은기정의된 work queue 를많이활용하나, 이는시스템의많은 driver 들이공동으로사용하고있으므로, 경우에따라서는원하는결과 ( 성능 ) 를얻지못할수도있다. 따라서이러한경우에는자신만의독자적인 work queue 를만드는것도고려해보아야한다. (*) 보다자세한사항은 include/linux/workqueue.h 파일참조

3. Bottom Halves and Deferring Work - Work Queue <data structure 일부발췌 include/linux/workqueue.h>

3. Bottom Halves and Deferring Work - Work Queue <work queue 사용예 > (*) 아래예는 default(system) work queue 의사용예이며, 사용자정의 work queue 의사용예는별도로정리하여야함 ^^.

3. Bottom Halves and Deferring Work - Kernel Threads struct task_struct *kthread_create(my_thread, data, ); Kernel thread 생성 int my_thread(void *data) Set task state to TASK_INTERRUPTIBLE (*) 옆의 kernel thread 내부는앞서설명한 worker thread 를거의그대로복사한것이라, 다음다음페이지의코드예를보는것이보다정확할듯 ^^ kthread_run( ) kernel thread 를만들고, thread 를깨워줌 kthread_create( ) kernel thread 를만듦 (sleeping 상태로있음 ) kthread_bind( ) thread 를특정 CPU 에 bind 시킬때사용함. kthread_stop( ) thread 를중지할때사용함. Kthread_should_stoip 을위한조건을설정해줌. kthread_should_stop( ) kernel thread 루틴을멈추기위한조건검사함수. loop Add itself(thread) to wait queue ( sleep) If work list is empty then schedule Else set task state to TASK_RUNNING Remove itself from wait queue ( wakeup) If (kthread_should_stop()) break Do my work (*) work queue 가 kernel thread 를기반으로하고있으므로, kernel thread 를직접만들필요없이, Work queue 를이용하는것이보다간편할수있다. (*) 보다자세한사항은 include/linux/kthread.h 파일참조

3. Bottom Halves and Deferring Work - Kernel Threads <data structure 일부발췌 include/linux/kthread.h>

3. Bottom Halves and Deferring Work - Kernel Threads <kernel thread 사용예 >

4. Timer(1) (*) 앞서설명한 bottom half 의목적은 work 을단순히 delay 시키는데있는것이아니라, 지금당장 work 을실행하지않는데있음. 한편 timer 는일정한시간만큼 work 을 delay 시키는데목적이있음! (*) timer 는 timer interrupt 를통해동작하는방식을취함 (software interrupt). 즉, 처리하려는 function 을준비한후, 정해진시간이지나면 timer interrupt 가발생하여해당 function 을처리하는구조임. (*) timer 는 cyclic( 무한반복 ) 구조가아니므로, time 이경과하면 timer function 이실행되고, 해당 timer 는제거된다. Timer interrupt timer_list run_timer_softirq( ) timer_list 실행 timer_list timer_list timer_list timer vector

4. Timer(2) timer list my_timer my data my_timer_handler { } expired time add_timer ( ) or mod_timer( ) 이를호출하여반복적으로 timer 를돌릴수있음 Time expired interrupt 시호출됨 void init_timer(struct timer_list *timer); or TIMER_INITALIZER(_function, _expires, _data) 초기화 add_timer( ) 초기화후, activation 시켜주면동작함. my_timer_handler(my_data) will be run! 얘는빠르게처리되는코드이어야함!

4. Timer(3) schedule_timeout(timoeut) : 현재실행중인 task 에대해 delay 를줄수있는보다효과적인방법. 이방법을사용하면현재실행중인 task 를지정된시간이경과할때까지 sleep 상태 (wait queue 에넣어줌 ) 로만들어주고, 시간경과후에는다시 runqueue 에가져다놓게함. schedule_timeout( ) 의내부는 timer 와 schedule 함수로구성되어있음. schedule_timeout (signed long timeout) { timer_t timer; unsigned long expire; expire = timeout * jiffies; init_timer(&timer); timer.expires = expire; timer.data = (unsigned long)current; timer.function = process_timeout; add_timer(&timer); schedule(); del_timer_sync(&timer); } timeout = expire jiffies; (*) schedule_timeout 말고도, process scheduling 과조합한타이머리스트관련함수로는아래와같은것들이있다. process_timeout, sleep_on_timeout, interruptible_sleep_on_timeout

4. Timer(4) <data structure 일부발췌 include/linux/timer.h>

4. Timer(5) <timer 사용예 >

5. Wakelock(1) (*) 시스템이 low power state 로가는것을막아주는메카니즘 (google 에서만듦 ). (*) Smart Phone 은전류를많이소모하므로, 항시 sleep mode 로빠질준비를해야한다. (*) wake_lock_init 의인자로넘겨준, name 값은 /proc/wakelocks 에서확인가능함. Declare and init wakelock (wake 잠금변수선언및초기화 ) <wakeup routine> <sleep routine> Start wakelock (wake 잠금시작 ) 여기서부터계속깨어있음 Release wakelock (wake 잠금해제 ) 여기서부터 sleep 가능해짐 Destroy wakelock (wake 잠금변수제거 driver 제거시 )

5. Wakelock(2) <Wakelock 관련 API 모음 > [ 변수선언 ] struct wakelock mywakelock; [ 초기화 ] wake_lock_init(&mywakelock, int type, wakelock_name ); type : = WAKE_LOCK_SUSPEND: 시스템이 suspending 상태로가는것을막음 = WAKE_LOCK_IDLE: 시스템이 low-power idle 상태로가는것을막음. [To hold(wake 상태로유지 )] wake_lock(&mywakelock); [To release(sleep 상태로이동 )] wake_unlock(&mywakelock); [To release(sleep 상태로이동 )] wake_lock_timeout(&mywakelock, HZ); [ 제거 ] wake_lock_destroy (&mywakelock);

5. Wakelock(3) (*) 이그림은 kernel wakelock 을설명하기에는많이부족하나, Android 관점에서 power manangement 를이해하기위해첨부하였다.

5. Wakelock(4) <data structure 일부발췌 include/linux/wakelock.h>

5. Wakelock(5) <wakelock 사용예 > (*) 위의내용은 drivers/mmc/core/core.c 파일에서발췌한것임.

5. Wakelock(5) <wakelock 사용예 ( 계속 )>

6. Synchronization(1) - Sleeping & Wait Queue (*) Spinlock, big kernel lock, mutex, semaphore 등일반적인내용은제외하고, wait queue 및 Completion function 만언급하고자함. wait_event ( 대기상태로빠짐 ) wait queue X task wakeup (CPU 를할당받을수있게됨 ) Critical section O run queue

6. Synchronization(2) - Sleeping & Wait Queue (*) wait queue 는 kernel mode 에서 running 중인 task 가특정조건이만족될때까지기다려야할때사용된다. (*) task 가필요로하는특정조건이나 resource 가준비될때까지, 해당 task 는 Sleep 상태에있어야한다. < 변수선언및초기화 > wait_queue_head_t wq; init_waitqueue_head(&wq); or DECLARE_WAIT_QUEUE_HEAD(wq); <Going to Sleep critical section으로들어가기전에대기상태로빠짐 > wait_event (wait_queue_head_t wq, int condition) wait_event_interruptible (wait_queue_head_t wq, int condition) wait_event_killable (wait_queue_head_t wq, int condition) wait_event_timeout (wait_queue_head_t wq, int condition, long timeout) wait_event_interruptible (wait_queue_head_t wq, int condition, long timeout) <Waking Up critical section으로들어가는조건을만들어줌 ( 풀어줌 )> void wake_up (wait_queue_head_t *wq); void wake_up_interruptible (wait_queue_head_t *wq); void wake_up_interruptible_sync (wait_queue_head_t *wq);

6. Synchronization(3) - Sleeping & Wait Queue <Wait Queue 사용예 >

6. Synchronization(4) - Completion write 후, complete() 호출 ( 대기해제 ) Read 전, wait_for_completion 호출 ( 대기상태진입 ) Common resources (critical section) struct completion { unsigned int done; wait_queue_head_t wait; }; void init_completion(struct completion *c); /* DECLARE_COMPLETION(x) 도사용가능 */ completion 초기화 void wait_for_completion(struct completion *c); /* timeout 함수도있음 */ critical section 에들어갈때호출 ( 대기를의미함 ) int wait_for_completion_interruptible(struct completion *c); /* timeout 함수도있음 */ critical section 에들어갈때호출 ( 대기를의미함 ). 이함수호출동안에 Interrupt 가능함. void complete(struct completion *c); critical section 에들어갈수있도록해줌 ( 대기조건을해지해줌 ) void complete_and_exit(struct completion *c, long code);

6. Synchronization(5) - Completion <completion 사용예 >

7. Notifier(1) <kernel routine A> { notifier callback 함수정의 notifier callback 함수등록 (*) notifier 는서로다른곳에위치한 kernel code 간에 event 를전송하기위한 mechanism 으로 callback 함수개념으로생각하면이해가쉽다 ^^. (*) 즉, kernel routine A 에서는호출되기를원하는 callback 함수를기술및등록하고, event 발생시점을아는 kernel routine B 에서해당함수를호출해주는것으로설명할수있겠음! } my_callback_func() { } <kernel routine B> { notifier chain register <event 발생시점예 - bluetooth> 1) HCI_DEV_UP(link up 시 ) 2) HCI_DEV_DOWN(linux down 시 ) 3) HCI_DEV_REG 4) HCI_DEV_UNREG 5) HCI_DEV_WRITE( 패킷전송시 ) } notifier chain unregister some_func() { call notifier_callback func 특정 event 발생시점에서호출 }

7. Notifier(2) (*) 자세한사항은 include/linux/notifier.h 파일참조!

7. Notifier(3) <notifier 사용예 >

JNI 8. Example Driver : bluetooth sleep mode driver(1) bluetoothd (*) 아래그림은 bluetooth sleep driver 의개념도로써, platform_driver, interrupt handler, GPIO, tasklet, workqueue, timer, wakelock 등의기법을사용하고있다. Sleep mode 일때는닫고, Wakeup mode 일때는열어준다 외부 Bluetooth 장치

8. Example Driver : bluetooth sleep mode driver(2) Broadcom chip Power on/off switch Qualcomm chip(cpu) off TX RX CTS RTS RX TX RTS CTS workqueue for sleep UART line host_wake/ ext_wake on HOST_WAKE (irq line) host_wake (interrupt) HOST_WAKE tasklet for wakeup EXT_WAKE EXT_WAKE GPIO line (*) bluetooth 가 wakeup 되는조건은위의 HOST_WAKE 가 enable(interrupt) 되는것이외에도실제로 bluetooth packet 이나가고나서발생하는 HCI event(callback) 에기인하기도한다. (*) 전력소모를최소로하기위해, 틈만나면 (?) sleep mode 로진입해야하며, HOST_WAKE 및 EXT_WAKE GPIO pin 이모두사용중이지않을때 (deasserted), sleep 으로들어가게된다.

8. Example Driver : bluetooth sleep mode driver(3) <tasklet routine> TODO

8. Example Driver : bluetooth sleep mode driver(4) <work queue routine> TODO

9. Debug TODO Debug 관련해서는일단은 Android_Debug_Guide4.pdf 파일을참조하기바람 ( 추후, 좀더보강예정임 ).

Appendix

Appendix 부록 1: kernel( 만 ) build 방법 부록 2: android boot.img 분해및 kernel 교체방법

부록 1: Kernel( 만 ) Build 하기 # make ARCH=arm YOUR_MACHINE_ARCH_CONFIG arch/arm/configs 사용중인 machine type 으로 configuratiobn 설정 ( 조정 ) # make ARCH=arm menuconfig Configuration 을원하는대로변경하고자할경우 # make -j3 ARCH=arm zimage Build 결과 : arch/arm/boot/zimage # make -j3 ARCH=arm modules wi-fi 등 kernel module build 함. [TIP] menuconfig 로수정한파일을, 이후에도재사용하고자할경우에는, 아래와같이하면된다. cp f.config arch/arm/configs/your_machine_arch_config

부록 2: Android boot.img 분해및 kernel 교체방법 (1) On application processor <boot.img> Boot loader Boot header( 1 page) Kernel(n pages) linux kernel Kernel(Image) Ramdisk(m pages) init (first user process) init.rc init.qcom.rc

부록 2: Android boot.img 분해및 kernel 교체방법 (2) ANDROID! mkbootimg --cmdline "console=ttyhs1 pmem_kernel_ebi1_size=0x200000 androidboot.hardware=qcom --kernel zimage --ramdisk ramdisk.gz -base 0x20000000 -o boot.img Boot header( 1 page) Kernel(n pages) - zimage Ramdisk(m pages) - rootfs (*) 주의 : 위의내용은 qualcomm chip 을기준으로작성한것이므로, 다른 chip 에적용하기위해서는빨간글씨부분이적절히수정되어야할것임. 따라서개념을이해하는용도로만이해하시기바람 ^^ Second stage(o pages) n = (kernel_size + page_size 1) / page_size m = (ramdisk_size + page_size 1) / page_size o = (second_size + page_size 1) / page_size (Example) Page size: 2048 (0x00000800) Kernel size: 4915808 (0x004b0260) Ramdisk size: 310311 (0x0004bc27) Second size: 0 (0x00000000)

부록 2: Android boot.img 분해및 kernel 교체방법 (3) ANDROID! [TIP] split_bootimg.pl 은인터넷에서구할수있음. [TIP] 앞서설명한 mkbootimg 와위에서설명한내용을토대로, 새로 build 한 kernel image 를적용한새로운 boot.img 를만들수있게됨. [TIP] fastboot 명령을사용하여새로만든 boot.img 를 flash 에 write 하면됨 ^^. Boot header( 1 page) Boot header( 1 page) Kernel(n pages) - zimage Ramdisk(m pages) - rootfs Second stage(o pages) split_bootimg.pl (boot.img 분해 ) Kernel(n pages) - zimage Ramdisk(m pages) - rootfs ANDROID! 새로 build 한 zimage 로교체 Boot header( 1 page) Boot header( 1 page) fastboot Kernel(n pages) - zimage Ramdisk(m pages) - rootfs mkbootimg (boot.img 재생성 ) Kernel(n pages) - zimage Second stage(o pages) Ramdisk(m pages) - rootfs

부록 2: Android boot.img 분해및 kernel 교체방법 (4) <boot.img 파일분해하기 > #./split_bootimg.pl boot.img -> boot header -> boot.img-kernel kernel -> boot.img-ramdisk.gz ramdisk root file system <boot.img 파일재생성하기 > # mkbootimg --cmdline "console=ttyhs1 pmem_kernel_ebi1_size=0x200000 androidboot.hardware=qcom --kernel zimage --ramdisk ramdisk.gz -base 0x20000000 -o boot.img 앞서설명한것처럼, 빨간색표시부분은시스템마다다르니, 주의요망 ( 잘못하면, 영영부팅안됨 ^^) <fastboot 으로 boot.img write 하기 > # adb reboot-bootloader fastboot mode 로전환 ( 혹은시스템에서정의한 key 조합선택하여 ) # fastboot flash boot./boot.img -- -- -- -- -- < 기타참고사항 1: ramdisk rootfs 파일해부하기 > # gzip -d boot.img-ramdisk.gz # cpio -i < boot.img-ramdisk 현재디렉토리에 ramdisk file system 을구성하는파일이풀리게됨. < 기타참고사항 2: 새로운 ramdisk file 만들기 init.rc, init.qcom.rc 등을수정후테스트시 > # find. cpio o H newc gzip >../newramdisk.cpio.gz <= 위에서 cpio 로파일을풀어둔디렉토리에서명령을실행.

TODO 1) Android Specific Driver 를일반화하여정리하기 PMIC, charger, SDIO, USB, Video/Audio, Camera, T-DMB, WiFi, Bluetooth, Telephony, GPS, Sensors/Input Thanks a lot!

References 1) Linux Kernel Development. [Robert Love] 2) Writing Linux Device Drivers [Jerry Cooperstein] 3) Essential Linux Device Drivers.. [Sreekrishnan Venkateswaran] 4) Linux kernel 2.6 구조와원리... [ 이영희역, 한빛미디어 ] 5) Linux Kernel architecture for device drivers.. 6) Some Internet Articles [Thomas Petazzoni Free Electronics(thomas.petazzoni@free-electronics.com)]