untitled

Similar documents
untitled

KEY 디바이스 드라이버

Chapter #01 Subject

슬라이드 1

untitled

6주차.key

강의10

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

Microsoft PowerPoint - lab14.pptx

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

Page 2 of 5 아니다 means to not be, and is therefore the opposite of 이다. While English simply turns words like to be or to exist negative by adding not,

교육지원 IT시스템 선진화

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

- 2 -

Page 2 of 6 Here are the rules for conjugating Whether (or not) and If when using a Descriptive Verb. The only difference here from Action Verbs is wh

Chap06(Interprocess Communication).PDF

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

Chap04(Signals and Sessions).PDF

DE1-SoC Board


Something that can be seen, touched or otherwise sensed

Embeddedsystem(8).PDF

Microsoft PowerPoint - polling.pptx

Microsoft Word - FunctionCall

10주차.key

untitled

SRC PLUS 제어기 MANUAL

PRO1_04E [읽기 전용]

- 이 문서는 삼성전자의 기술 자산으로 승인자만이 사용할 수 있습니다 Part Picture Description 5. R emove the memory by pushing the fixed-tap out and Remove the WLAN Antenna. 6. INS

사용시 기본적인 주의사항 경고 : 전기 기구를 사용할 때는 다음의 기본적인 주의 사항을 반드시 유의하여야 합니다..제품을 사용하기 전에 반드시 사용법을 정독하십시오. 2.물과 가까운 곳, 욕실이나 부엌 그리고 수영장 같은 곳에서 제품을 사용하지 마십시오. 3.이 제품은

chap7.key

T100MD+

Microsoft Word doc

13주-14주proc.PDF

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

Microsoft Word - ExecutionStack

Microsoft PowerPoint - ch03ysk2012.ppt [호환 모드]

<31342D3034C0E5C7FDBFB52E687770>

PowerPoint 프레젠테이션

K7VT2_QIG_v3

PowerPoint 프레젠테이션

K&R2 Reference Manual 번역본

<B1E2C8B9BEC828BFCFBCBAC1F7C0FC29322E687770>

슬라이드 1

untitled

Microsoft PowerPoint APUE(Intro).ppt

Microsoft Word - MPC850 SPI Driver.doc

2. GCC Assembler와 AVR Assembler의차이 A. GCC Assembler 를사용하는경우 i. Assembly Language Program은.S Extension 을갖는다. ii. C Language Program은.c Extension 을갖는다.

11¹Ú´ö±Ô

PRO1_09E [읽기 전용]

PowerPoint 프레젠테이션

Microsoft PowerPoint - lab15.pptx

INTRO Basic architecture of modern computers Basic and most used assembly instructions on x86 Installing an assembly compiler and RE tools Practice co

H3050(aap)

PCServerMgmt7

Microsoft PowerPoint - chap6 [호환 모드]

.. IMF.. IMF % (79,895 ). IMF , , % (, 2012;, 2013) %, %, %

PowerChute Personal Edition v3.1.0 에이전트 사용 설명서

1217 WebTrafMon II

Vol.257 C O N T E N T S M O N T H L Y P U B L I C F I N A N C E F O R U M

Stage 2 First Phonics

untitled

歯15-ROMPLD.PDF

C++-¿Ïº®Çؼ³10Àå

2 동북아역사논총 50호 구권협정으로 해결됐다 는 일본 정부의 주장에 대해, 일본군 위안부 문제는 일 본 정부 군 등 국가권력이 관여한 반인도적 불법행위이므로 한일청구권협정 에 의해 해결된 것으로 볼 수 없다 는 공식 입장을 밝혔다. 또한 2011년 8월 헌 법재판소는

< BFCFB7E15FC7D1B1B9C1A4BAB8B9FDC7D0C8B85F31352D31BCF6C1A4C8AEC0CE2E687770>

CD-RW_Advanced.PDF

±èÇö¿í Ãâ·Â

09김정식.PDF

solution map_....

thesis

본문01

DBPIA-NURIMEDIA

<C0CCBCBCBFB52DC1A4B4EBBFF82DBCAEBBE7B3EDB9AE2D D382E687770>

Sena Technologies, Inc. HelloDevice Super 1.1.0

MPLAB C18 C

프로그램을 학교 등지에서 조금이라도 배운 사람들을 위한 프로그래밍 노트 입니다. 저 역시 그 사람들 중 하나 입니다. 중고등학교 시절 학교 도서관, 새로 생긴 시립 도서관 등을 다니며 책을 보 고 정리하며 어느정도 독학으르 공부하긴 했지만, 자주 안하다 보면 금방 잊어

2 min 응용 말하기 01 I set my alarm for It goes off. 03 It doesn t go off. 04 I sleep in. 05 I make my bed. 06 I brush my teeth. 07 I take a shower.

#KM-250(PB)

CANTUS Evaluation Board Ap. Note

step 1-1

4. #include <stdio.h> #include <stdlib.h> int main() { functiona(); } void functiona() { printf("hihi\n"); } warning: conflicting types for functiona

<4D F736F F F696E74202D20B8B6C0CCC5A9B7CEC7C1B7CEBCBCBCAD202839C1D6C2F7207E203135C1D6C2F >


The Self-Managing Database : Automatic Health Monitoring and Alerting

bn2019_2

PowerPoint 프레젠테이션

#KM-235(110222)

Motor

example code are examined in this stage The low pressure pressurizer reactor trip module of the Plant Protection System was programmed as subject for

hlogin2

PowerPoint 프레젠테이션

슬라이드 1

Deok9_Exploit Technique

휠세미나3 ver0.4

Transcription:

Interrupt Programming in Linux Embedded System Lab. II

PXA255 CPU Embedded System Lab. II 1

IR CPU PC intr request intr ack data/address status reg data reg mechanism Embedded System Lab. II 2

Suppose a peripheral intermittently receives data, which must be serviced by the processor The processor can poll the peripheral regularly to see if data has arrived wasteful The peripheral can interrupt the processor when it has data Requires an extra pin or pins: Int If Int is 1, processor suspends current program, jumps to an Interrupt Service Routine (ISR) Known as interrupt-driven I/O Essentially, polling of the interrupt pin is built-into the hardware, so no extra time! Embedded System Lab. II 3

What is the address (interrupt address vector) of the ISR? Fixed interrupt Address built into microprocessor, cannot be changed Either ISR stored at address or a jump to actual ISR stored if not enough bytes available Vectored interrupt Peripheral must provide the address Common when microprocessor has multiple peripherals connected by a system bus Compromise: interrupt address table Embedded System Lab. II 4

I/O(fixed ISR location) Time 1(a): P is executing its main program. 1(b): P1 receives input data in a register with address 0x8000. 3: After completing instruction at 100, P sees Int asserted, saves the PC s value of 100, and sets PC to the ISR fixed location of 16. 2: P1 asserts Int to request servicing by the microprocessor. 4(a): The ISR reads data from 0x8000, modifies the data, and writes the resulting data to 0x8001. 4(b): After being read, P1 deasserts Int. 5: The ISR returns, thus restoring PC to 100+1=101, where µp resumes executing. Embedded System Lab. II 5

I/O(fixed ISR location) 1(a): µp is executing its main program 1(b): P1 receives input data in a register with address 0x8000. Program memory ISR 16: MOV R0, 0x8000 17: # modifies R0 18: MOV 0x8001, R0 19: RETI # ISR return... Main program... 100: 101: instruction instruction P PC Int Data memory System bus P1 P2 0x8000 0x8001 Embedded System Lab. II 6

I/O(fixed ISR location) 2: P1 asserts Int to request servicing by the microprocessor Program memory ISR 16: MOV R0, 0x8000 17: # modifies R0 18: MOV 0x8001, R0 19: RETI # ISR return... Main program... 100: 101: instruction instruction P PC Int 1 Data memory System bus P1 P2 0x8000 0x8001 Embedded System Lab. II 7

I/O(fixed ISR location) 3: After completing instruction at 100, µp sees Int asserted, saves the PC s value of 100, and sets PC to the ISR fixed location of 16. Program memory ISR 16: MOV R0, 0x8000 17: # modifies R0 18: MOV 0x8001, R0 19: RETI # ISR return... Main program... 100: 101: instruction instruction P PC 100 Int Data memory System bus P1 P2 0x8000 0x8001 Embedded System Lab. II 8

I/O(fixed ISR location) 4(a): The ISR reads data from 0x8000, modifies the data, and writes the resulting data to 0x8001. 4(b): After being read, P1 deasserts Int. Program memory ISR 16: MOV R0, 0x8000 17: # modifies R0 18: MOV 0x8001, R0 19: RETI # ISR return... Main program... 100: 101: instruction instruction P Int PC 100 0 Data memory System bus P1 P2 0x8000 0x8001 Embedded System Lab. II 9

I/O(fixed ISR location) 5: The ISR returns, thus restoring PC to 100+1=101, where µp resumes executing. Program memory ISR 16: MOV R0, 0x8000 17: # modifies R0 18: MOV 0x8001, R0 19: RETI # ISR return... Main program... 100: instruction 101: instruction P Int PC 100 +1 Data memory System bus P1 P2 0x8000 0x8001 Embedded System Lab. II 10

I/O(vectored interrupt) Time 1(a): P is executing its main program. 1(b): P1 receives input data in a register with address 0x8000. 3: After completing instruction at 100, P sees Int asserted, saves the PC s value of 100, and asserts Inta. 2: P1 asserts Int to request servicing by the microprocessor. 4: P1 detects Inta and puts interrupt address vector 16 on the data bus. 5(a): P jumps to the address on the bus (16). The ISR there reads data from 0x8000, modifies the data, and writes the resulting data to 0x8001. 5(b): After being read, P1 deasserts Int. 6: The ISR returns, thus restoring PC to 100+1=101, where µp resumes executing. Embedded System Lab. II 11

I/O(vectored interrupt) 1(a): P is executing its main program 1(b): P1 receives input data in a register with address 0x8000. Program memory ISR 16: MOV R0, 0x8000 17: # modifies R0 18: MOV 0x8001, R0 19: RETI # ISR return... Main program... 100: 101: instruction instruction P Inta Int PC 100 Data memory System bus P1 P2 16 0x8000 0x8001 Embedded System Lab. II 12

I/O(vectored interrupt) 2: P1 asserts Int to request servicing by the microprocessor Program memory ISR 16: MOV R0, 0x8000 17: # modifies R0 18: MOV 0x8001, R0 19: RETI # ISR return... Main program... 100: 101: instruction instruction P Inta Int PC 100 1 Data memory System bus P1 P2 16 0x8000 0x8001 Embedded System Lab. II 13

I/O(vectored interrupt) 3: After completing instruction at 100, P sees Int asserted, saves the PC s value of 100, and asserts Inta Program memory ISR 16: MOV R0, 0x8000 17: # modifies R0 18: MOV 0x8001, R0 19: RETI # ISR return... Main program... 100: 101: instruction instruction P Inta Int PC 100 1 Data memory System bus P1 P2 16 0x8000 0x8001 Embedded System Lab. II 14

I/O(vectored interrupt) 4: P1 detects Inta and puts interrupt address vector 16 on the data bus Program memory ISR 16: MOV R0, 0x8000 17: # modifies R0 18: MOV 0x8001, R0 19: RETI # ISR return... Main program... 100: 101: instruction instruction P Inta Int PC 100 16 Data memory System bus P1 P2 16 0x8000 0x8001 Embedded System Lab. II 15

I/O(vectored interrupt) 5(a): PC jumps to the address on the bus (16). The ISR there reads data from 0x8000, modifies the data, and writes the resulting data to 0x8001. 5(b): After being read, P1 deasserts Int. Program memory ISR 16: MOV R0, 0x8000 17: # modifies R0 18: MOV 0x8001, R0 19: RETI # ISR return... Main program... 100: instruction 101: instruction P Inta Int PC 100 0 Data memory System bus P1 P2 16 0x8000 0x8001 Embedded System Lab. II 16

I/O(vectored interrupt) 6: The ISR returns, thus restoring the PC to 100+1=101, where the P resumes Program memory ISR 16: MOV R0, 0x8000 17: # modifies R0 18: MOV 0x8001, R0 19: RETI # ISR return... Main program... 100: instruction 101: instruction P Int PC 100 +1 Data memory System bus P1 P2 0x8000 0x8001 Embedded System Lab. II 17

Interrupt address table Compromise between fixed and vectored interrupts One interrupt pin Table in memory holding ISR addresses (maybe 256 words) Peripheral doesn t provide ISR address, but rather index into table Fewer bits are sent by the peripheral Can move ISR location without changing peripheral Embedded System Lab. II 18

Additional interrupt issues Maskable vs. non-maskable interrupts Jump to ISR Maskable: programmer can set bit that causes processor to ignore interrupt Important when in the middle of time-critical code Non-maskable: a separate interrupt pin that can t be masked Typically reserved for drastic situations, like power failure requiring immediate backup of data to non-volatile memory Some microprocessors treat jump same as call of any subroutine Complete state saved (PC, registers) may take hundreds of cycles Others only save partial state, like PC only Thus, ISR must not modify registers, or else must save them first Assembly-language programmer must be aware of which registers stored Embedded System Lab. II 19

PXA255 General Purpose I/O Block Diagram Embedded SW I GPDR 1 : 0 : 2 0x40E0_000C/10/14 0x40E0_0054/58/5C 0x40E0_0060/64/68 0x40E0_0060/64/68 0x40E0_0060/64/68 Base Address 0x40E0_0000 0x40E0_0048/4C/50 0x40E0_0030/34/38 Power Manager Sleep Wake-up logic 0x40E0_003C/40/44 0x40E0_0000/04/08 Embedded System Lab. II 20

PXA255 Interrupt controller 40D0 0008 0 : IRQ 1 : FIQ 40D0 0004 40D0 0010 40D0 0000 40D0 000C 40D0 0014 : Interrupt controller control register (ICCR) ICCR.0 : disable idle mask(dim) Embedded System Lab. II 21

Interrupt Controller(2) All interrupts routed to FIQ or IRQ Two level interrupt structure 1. What module caused interrupt Serial channel, DMA, Power Management, etc 2. Why did an interrupt occur there? RX, TX, over-run, under-run, Data Done, Battery Fault, etc Template for servicing interrupts provided with firmware Peripheral/PCMCIA interrupt mask in each module GPIO masks determined per pin or group of pins Embedded System Lab. II 22

ICMR(Interrupt Controller Mask Register) 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 0000 0000 0000 000??000 0000???????? IM31 IM28 IM27 IM24 IM23 IM20IM19 IM17 IM14 IM12IM11 IM8 Reserved IM[x] Interrupt Mask x (where x= 8 through 14 and 17 through 31). 0 Pending interrupt is masked from becoming active (interrupts are NOT sent to CPU or Power Manager). 1 Pending interrupt is allowed to become active (interrupts are sent to CPU and Power Manager). NOTE: In idle mode, the IM bits are ignored if ICCR[DIM] is cleared. Reserved[0-7, 15, 16] Physical Address : 0x40D0/0004 Embedded System Lab. II 23

ICLR(Interrupt Controller Level Register) 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 0000 0000 0000 000# #000 0000 #### #### IL31 IL28IL27 IL24IL23 IL20IL19 IL17 IL14 IL12IL11 IL8 Reserved IL[x] Interrupt Level x (where n = 8 through 14 and 17 through 31). 0 Interrupt routed to IRQ interrupt input. 1 Interrupt routed to FIQ interrupt input. Reserved[0-7, 15, 16] Physical Address : 0x40D0/0008 Embedded System Lab. II 24

ICCR(Interrupt Controller Control Register) 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0???????????????????????????????X Reserved DIM DIM[0] Disable Idle mask. 0 All enabled interrupts bring the processor out of idle mode. 1 Only enabled and unmasked (as defined in the ICMR) bring the processor out of idle mode. This bit is cleared during all resets. Reserved[31:1] Physical Address : 0x40D0/0014 Embedded System Lab. II 25

ICIP(Interrupt Controller IRQ Pending Register) 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 0000 0000 0000 000??000 0000???????? IP31 IP28IP27 IP24IP23 IP20IP19 IP17IP14 IP12IP11 IP8 Reserved IP[x] : IRQ Pending x (where x = 8 through 14 and 17 through 31). 0 IRQ NOT requested by any enabled source. 1 IRQ requested by an enabled source. Reserved[0-7, 15, 16] Physical Address : 0x40D0/0000 Embedded System Lab. II 26

ICFP(Interrupt Controller FIQ Pending Register) 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 0000 0000 0000 000??000 0000???????? FP31 FP28 FP27 FP24FP23 FP20FP19 FP17 FP11 FP8 FP14 FP12 Reserved FP[x] : FIQ Pending x (where x = 8 through 14 and 17 through 31). 0 FIQ NOT requested by any enabled source. 1 FIQ requested by an enabled source. Reserved[0-7, 15, 16] Physical Address : 0x40D0/000C Embedded System Lab. II 27

31 30 29 28 ICPR(Interrupt Controller Pending Register) 0000 0000 0000 000??000 0000???????? IS31 IS28IS27 IS24IS23 IS20IS19 IS17 IS11 IS8 IS14 IS12 a 32-bit read-only register that shows all active interrupts in the system. These bits are not affected by the state of the mask register (ICMR). Clearing the interrupt status bit at the source, automatically clears the corresponding ICPR flag, provided there are no other interrupt status bits set within the source unit. 27 26 25 24 Table 4-36 23 22 21 20 19 18 17 16 Physical Address : 0x40D0/0010 15 14 13 12 11 10 9 8 7 6 5 4 Reserved 3 2 1 0 Embedded System Lab. II 28

Why Bottom Halves? Because interrupt handlers. run asynchronously and thus interrupt other potentially important code(even other interrupt handlers) run with current interrupt level disabled at best, and at worst (if SA_INTERRUPT set) with all interrupts disabled are often timing-critical because they deal with hardware cannot block Consequently, managing interrupts is divided into two parts (or halves) Some useful tips about how to divide work between top and bottom half if the work is time-sensitive if the work is related to the hardware itself if the work needs to ensure that another interrupt (particularly the same interrupt) does not interrupt it Embedded System Lab. II 29

Bottom Halves in Linux 2.4 the future when the system is less busy and interrupts are enabled again Three types of bottom halves in 2.4 softirq, tasklet, BH operations on deferrable functions initialization activation masking execution (* activation and execution on the same CPU? ) Embedded System Lab. II 30

Bottom Halves in Linux 2.4 History of bottom half status in Linux BH removed in 2.5 Task queues removed in 2.5 Softirq available since 2.3 Tasklet available since 2.3 Work queues available since 2.5 Embedded System Lab. II 31

Softirqs Each registered softirq in one entry of softirq_vec[32] (32 softirqs possible) /* 32-entry array of softirq_action (kernel/softirq.c) */ static struct softirq_action softirq_vec[32]; /* structure representing a softirq entry */ /* (linux/interrupt.h) */ struct softirq_action { }; void (*action) (struct softirq_action *); void *data; / irq_stat irq_cpustat_t irq_stat[nr_cpus]; typedef struct { unsigned int softirq_pending; unsigned int local_irq_count; unsigned int local_bh_count; unsigned int syscall_count; struct task_struct * ksoftirqd_task; unsigned int nmi_count; } irq_cpustat_t; Embedded System Lab. II 32

Softirqs Softirq handler with entire softirq_action as argument (why?) (ex) void net_tx_action(struct softirq_action *h) { } void net_rx_action(struct softirq_action *h) { } Remember that A softirq handler run with interrupts enabled and cannot sleep. softirqs on current CPU are disabled an interrupt handler can preempt a softirq Another softirq can run on another CPU. Four softirqs used in 2.4 (six in 2.6) HI_SOFTIRQ / TIMER_SOFTIRQ / NET_TX_SOFTIRQ / NET_RX_SOFTIRQ / SCSI_SOFTIRQ /( )/ TASKLET_SOFTIRQ Embedded System Lab. II 33

Softirqs Registering softirq handler at run-time by open_softirq( ) open_softirq(net_tx_softirq, net_tx_action, NULL); open_softirq(net_rx_softirq, net_rx_action, NULL); Raising softirq by raise_softirq( ) (usually, an interrupt handler raises its softirq before returning) raise_softirq(net_tx_softirq); Checking for pending softirqs (kernel version / supported hardware) After processing a hardware interrupt When one of ksoftirqd_cpun kernel threads is awoken When a packet is received on a NIC When local_bh_enable macro re-enables the softirqs Embedded System Lab. II 34

Softirqs Executing softirqs : do_softirq( ) local_irq_count(cpu) = = 0? // nested? local_bh_count(cpu) = = 0? // enabled? serializing execution on a CPU softirq not processed in this invocation? // goto restart only if different types // goto wakeup_softirqd(cpu) if same softirq re-activated if( in_interrupt( ) ) return; local_irq_save( flags ); // disable local INT pending = softirq_pending(cpu); if( pending ){ mask = ~pending; local_bh_disable(cpu); // disable softirq // local_bh_count++ restart: softirq_pending(cpu) = 0; local_irq_enable(); struct softirq_action* h = softirq_vec; do{ if( pending & 1 ) h->action(h); h++; pending >> 1; }while(pending); local_irq_disable(); pending = softirq_pending(cpu); if( pending & mask ){ mask &= ~pending; goto restart; } local_bh_enable(); if( pending ) wakeup_softirqd(cpu); } local_irq_restore( flags ); Embedded System Lab. II 35

Kernel Thread : ksoftirqd_cpun Softirq kernel thread for each CPU Q: what if softirqs raised or re-activated at very high frequency? either ignore new softirqs that occur while do_softirq( ) is running long softirq latency (even on idle machine) or continuous re-checking for pending softirqs user starving (long response time) softirq kernel threads ksoftirqd_cpun at low priority give user a priority but run immediately on idle for (; ;) { set_current_state(task_interrptible); schedule( ); // now in TASK_RUNNING state while (softirq_pending(cpu)) { do_doftirq( ); if (current->need_resched) schedule( ); } } Embedded System Lab. II 36

Tasklets Implemented on top of softirqs: HI_SOFTIRQ, TASKLET_SOFTIRQ Tasklet structure (linux/interrupt.h) struct tasklet_struct { struct tasklet_struct *next; // pointer to next tasklet in the list unsigned long state; // state of the tasklet : 0, SCHED, RUN atomic_t count; // enable (0) /disable (nonzero) tasklet void (*func)(unsigned long); // tasklet handler function unsigned long data; // argument to tasklet function } tasklet_vec[nr_cpus] and tasklet_hi_vec[nr_cpus] to store scheduled tasklets (like raised softirqs) for regular tasklets and high-priority tasklets Embedded System Lab. II 37

Tasklets Declaring your tasklets statically (linux/interrupt.h) DECLARE_TASKLET(name, func, data) / DECLARE_TASKLET_DISABLED( ) (ex) DECLARE_TASKLET(my_tasklet, my_tasklet_handler, dev); struct tasklet_struct my_tasklet = { NULL, 0, ATOMIC_INIT(0), my_tasklet_handler, dev}; open_softirq(tasklet_softirq, tasklet_action, NULL); open_softirq(hi_softirq, tasklet_hi_action, NULL); dynamically void tasklist_init(struct tasklet_struct *t, tasklet_handler, dev); Embedded System Lab. II 38

Tasklets Writing your tasklet handler void tasklet_handler(unsigned long data) {.; } Remember that Tasklets cannot sleep if a tasklet share any data with an interrupt handler? (tasklets run with all interrupts enabled) if a tasklet shares data with another tasklet or softirq? Embedded System Lab. II 39

Tasklets Activating your tasklet tasklet_schedule( ) / tasklet_hi_schedule( ) tasklet_schedule(&my_tasklet); /* mark my_tasklet as pending */ static void tasklet_schedule(struct tasklet_struct *t) { 1. if TASKLET_STATE_SCHED is set, returns; /* already been scheduled? */ otherwise set TASKLET_STATE_SCHED flag; 2. local_irq_save( flags); // save the state of interrupt system and disable local interrupts 3.insert the tasklet to the head of tasklet_vec or tasklet_hi_vec; 4. raise TASKLET_SOFTIRQ or HI_SOFTIRQ softirq; 5. local_irq_restore(flags); } * what if the same tasklet is scheduled again? * what if it is already running on another CPU? Embedded System Lab. II 40

Tasklets Handling tasklets via tasklet_action( ) : TASKLET_SOFTIRQ static void tasklet_action(struct softirq_action *a) { 1. disable local interrupts; 2. list = the address of the list pointed to by tasklet_vec[cpu]; 3. put NULL in tasklet_vec[cpu]; // list of scheduled tasklets is emptied // 4. enable local interrupts; 5. for each tasklet decriptor in the list a. if TASKLET_STATE_RUN set, // tasklet of the same type on another CPU reinsert the tasklet descriptor in the list of tasklet_vec[cpu] and activate TASKLET_SOFTIRQ again; otherwise, set TASKLET_STATE_RUN (in SMP) b. if the tasklet is disabled (count <> 0?) reinsert and activate TASKLET_SOFTIRQ; // defer tasklet otherwise, clear TASKLET_STATE_SCHED and execute the tasklet function; } Embedded System Lab. II 41

Tasklets Controlling tasklets Enable / Disable tasklets tasklet_enable( ) / tasklet_disable( ) tasklet_disable(&my_tasklet); /* we can now do stuff knowing that the tasklet cannot run.. */ tasklet_enable(&my_tasklet); Remove a tasklet from the pending queue tasklet_kill( ) Embedded System Lab. II 42

Tasklets In summary, In most cases, tasklets are preferred way to implement a bottom half for a normal hardware device Tasklets are dynamically created, easy to use, and relatively quick. Embedded System Lab. II 43

BH BH interface : a high-priority tasklet with no concurrency Note that at most one BH is running (global_bh_lock spin lock) only for backward compatibility (Linux 2.2 or older) Each BH must be statically defined and there are max 32 BHs. Modules could not directly use BH interface because BH handlers must be defined at compile-time. All BH handlers are strictly serialized. No two BH handlers (even of different types) can run concurrenlty Easy synchronization, but not good for SMP performance a driver using BH interface does not scale well to SMP Embedded System Lab. II 44

BH Task queues a group of kernel functions as a BH? (task queues) Three particular task queues Immediate queue (run by IMMEDIATE_BH) Timer queue (run by TQUEUE_BH) Scheduler queue (run by keventd kernel thread) (* Linux 2.4 *) Can dynamically create new task queues Later various queues tasklets scheduler queue + keventd --> work queue in 2.6 Embedded System Lab. II 45

Disabling Bottom Halves Data structures accessed by bottom halves must be protected against race conditions because bottom halves can be executed at any time. A trivial way to disable bottom halves on a CPU is to disable interrupts on that CPU. (no interrupts --> no softirqs) How to disable bottom halves without disabling interrupts? void local_bh_disable( ) --> local_bh_count++ (of irq_stat[cpu]) void local_bh_enable( ) Embedded System Lab. II 46

GPIO GPIO button gpio (gpio.c) #include <linux/kernel.h> /* gpio.c */ #include <linux/module.h> #include <linux/init.h> #include <linux/config.h> #include <linux/sched.h> #include <linux/string.h> #include <linux/delay.h> #include <linux/errno.h> #include <linux/types.h> #include <asm/hardware.h> #include <asm/uaccess.h> #include <asm/irq.h> #include <asm/param.h> #define IRQ_BUTTON IRQ_GPIO(16) static void button_interrupt(int irq, void *dev_id, struct pt_regs *regs); static int GPIO_MAJOR = 0; static DECLARE_WAIT_QUEUE_HEAD(wait_queue); Embedded System Lab. II 47

GPIO static void button_interrupt(int irq, void *dev_id, struct pt_regs *regs) { wake_up_interruptible(&wait_queue); } static ssize_t gpio_read(struct file *filp, char *buf, size_t count, loff_t *l) { char hello[] = "GPIO_16 port was pushed!"; interruptible_sleep_on(&wait_queue); copy_to_user(buf,&hello,sizeof(hello)); return 0; } static int gpio_open(struct inode *inode, struct file *filp) { int res; unsigned int gafr; gafr = 0x3; GAFR0_U &= ~gafr; printk("irq_button = %d\n",irq_button); printk("irq_to_gpio =%d\n",irq_to_gpio_2_80(irq_button)); GPDR(IRQ_TO_GPIO_2_80(IRQ_BUTTON)) &= ~GPIO_bit(IRQ_TO_GPIO_2_80(IRQ_BUTTON)); set_gpio_irq_edge(irq_to_gpio_2_80(irq_button), GPIO_FALLING_EDGE); Embedded System Lab. II 48

GPIO res = request_irq(irq_button,&button_interrupt,sa_interrupt, "Button",NULL); if(res < 0) printk(kern_err "%s: Request for IRQ %d failed\n", FUNCTION,IRQ_BUTTON); else { enable_irq(irq_button); } } MOD_INC_USE_COUNT; return 0; static int gpio_release(struct inode *inode, struct file *filp) { free_irq(irq_button,null); disable_irq(irq_button); } MOD_DEC_USE_COUNT; return 0; static struct file_operations gpio_fops = { read: gpio_read, open: gpio_open, release: gpio_release }; Embedded System Lab. II 49

GPIO int init_module(void) { int result; result = register_chrdev(gpio_major,"gpiointerrupt",&gpio_fops); if(result < 0) { printk(kern_warning"can't get major %d\n",gpio_major); return result; } if(gpio_major == 0) GPIO_MAJOR = result; printk("init module, GPIO major number : %d\n",result); } return 0; void cleanup_module(void) { unregister_chrdev(gpio_major,"gpio INTERRUPT"); return; } Embedded System Lab. II 50

GPIO #include <stdio.h> /* test.c */ #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> static int dev; int main(void) { char buff[40]; dev = open("/dev/gpio",o_rdwr); if(dev < 0) { printf( "Device Open ERROR!\n"); exit(1); } printf("please push the GPIO_16 port!\n"); read(dev,buff,40); printf("%s\n",buff); } close(dev); return 0; Embedded System Lab. II 51

Makefile # led Device Driver Makefile /* Makefile */ CC = arm-linux-gcc KERNELDIR = /usr/src/linux-2.4.19 INCLUDEDIR = -I$(KERNELDIR)/include CFLAGS = -D KERNEL -DMODULE -Wall -O2 $(INCLUDEDIR) MODULE_OBJS = gpio.o MODULE_SRCS = gpio.c TEST_TARGET = test TEST_OBJS = test.o TEST_SRCS = test.c all: $(MODULE_OBJS) $(TEST_TARGET) $(TEST_TARGET) : $(TEST_OBJS) $(CC) $(TEST_OBJS) -o $@ clean: rm -f *.o rm -f $(TEST_TARGET) Embedded System Lab. II 52

GPIO GPIO GPIO $ make gpio.o test insmod loading mknod $ insmod gpio.o Using gpio.o init module, GPIO major number : 252 $ mknod /dev/gpio c 252 0 $./test Embedded System Lab. II 53

GPIO Embedded System Lab. II 54