210 likes | 315 Vues
This session covers essential concepts in embedded systems, focusing on interrupts and multitasking. Participants will learn about the function of the program counter and hardware stack, the limitations of polling, and how interrupts can optimize CPU resource usage by notifying the CPU of events. The session also introduces event buffering strategies, comparing linked lists and circular buffers, and demonstrates multitasking strategies in the context of a simple operating system suitable for microcontroller deployment. Engage with practical examples and learn how to implement these concepts in robotics.
E N D
Robocon 2007Electronics Quickstart! Session 5 Interrupt and OS Prepared by KI Chi Keung [chikeung@ust.hk] WONG Long Sing (Sam) [sam@hellosam.net]
Today’s Timeline • Program Counter and Hardware Stack • Interrupt • Buffering for Events • Multitasking
0000 0001 0002 0006 MOV A,0 ADD A,B JMP HEY SEI A,1 CLR C SUB B,C CMP B OUT 20 XOR A,9 MOV A,0 ADD A,B JMP HEY SEI A,1 CLR C SUB B,C CMP B OUT 20 XOR A,9 MOV A,0 ADD A,B JMP HEY SEI A,1 CLR C SUB B,C CMP B OUT 20 XOR A,9 MOV A,0 ADD A,B JMP HEY SEI A,1 CLR C SUB B,C CMP B OUT 20 XOR A,9 HEY Program Counter • Program Counter is an Integer register • A.k.a. as PC. • Has the address of the executing byte code • It advance by 1 step when execution is finish • Or being rewritten to some other value when CPU faces branching instruction, or calling a function • or being interrupted! 0000
0FFF int A 0FFE 0FFD int B 0FFC 0FFB char i 0FFA Rtn Addr 0FF9 0FF8 void* j 0FF7 0FF6 char i 0FF5 Rtn Addr 0FF4 int i[2] 0FF3 0FF2 0FF1 0FF0 0FF1 Hardware Stack • Hardware Stack is a piece of storage • Top located by the register - Stack Pointer, a.k.a. SP • Located at a specific position of main memory • For temporary storage, grows and shrink during execution • Local variable • Return address after calling a function • Grows towards lower address • An entire record is pushed when calling a function. • Usually, Only the top frame is used, others are ignored. 0FFF int A 0FFE 0FFD int B 0FFC 0FFB char i 0FFA Rtn Addr 0FF9 0FF8 void* j 0FF7 0FF6 char i 0FF5 0FF4 0FF3 0FF2 0FF1 0FF0 0FF6
Hardware Stack Another illustration from the Wikipedia
Heap Dynamic Allocation Stack Local Variable Global Variables Memory Arrangement Start End
Interrupt • So far we use while loop to keep on eyes on event (Switch, UART…) • This is called polling • It’s problematic • When we have a lot of events, it’s so hard to code • At the end, 99% of CPU time is used on busy waiting • Wouldn’t it be good if you are notified about an event instead? • So that CPU time is spent wisely instead of busy waiting • And this is interrupt
Interrupt • Tell the CPU that you want to be notified for an specific event. • Enabling the specific Interrupt line in register • Your interrupt service routine, a.k.a. ISR, will be called if such event occurs. • PC and Stack are modified in the same way, compare to that of calling a function • When ISR returns, execution resumes in main program
Interrupt • Interrupt is a hardware feature. All modern CPU have it. • It could never detect an in interrupt has happened, unless you tell it. • It could never prevent an interrupt from occurring, it can occur at any time • Of course unless the interrupt is disabled These characteristics will bring you a new set of problem.
Buffering for Events By using the interrupt • SendHandover all the data to be sent to the ISR • ReceiveNeed to store the data. Wait for CPU to process them i.e. You need a buffer. A temporary storage that making the transition smooth. So what is the data structure?
Buffering for Events A Queue! ISR Pop CPU Push
Buffering for Events Yeah! 勝った(我贏了)。 almost. The word Queue is just a concept. What are the implementations? • Linked List • Circular Buffer
Buffering for Events Linked list Advantage • Clean and clear concept! Has been explained for 100 times • Dynamically expandable Disadvantage • 2/3 memory overhead • No dynamic allocation, or otherwise expensive, in MCU! struct queue { char data; struct queue* next; } struct queue *head, *tail;
Buffering for Events Circular Buffer Advantage • Compact, almost no overhead • Fast to process Disadvantage • Fixed size char queue[128]; char head, tail; Head points to a free cell Tail points to the oldest occupied cell
Task Modify the echo program with output using circular buffer.
Multitasking We have a new problem. Imagine if we have many I/O queue like the UART. int main() { while (true) { // Check UART Queue // Response to computer command // Check Playstation Queue // Response to operator input // Auto Machine check Sensor // Auto Machine Calculation // Auto Machine Motor Output } }
Multitasking Won’t it be more logical if we… void UART_handler() { while (true) { // Wait for Check UART Queue // Response to computer command } } void manual_control() { while (true) { // Wait for Playstation Queue // Response to operator input } } void auto_machine_the_brain() { while (true) { // Wait for Playstation Queue // Response to operator input } }
Multitasking And that is multitasking, with the help of OS. People have written mini-OS that suitable for MCU deployment, to solve that problem.
Multitasking • There is only one processing unit. It looks like everything is running at the same time but it is not. • The CPU take care of different task from time to time. • When it change its task, it’s called Context Switching. Overhead: backup and restore all registers. • Context switching can be triggered at fixed interval (Preemptive) or task give up CPU time voluntary (Non-preemptive)
Thread Safety Traps produced by Multitasking and Interrupt • I/O device is shared. Make sure it is either shared or a task has exclusive right to use. • Interrupt/Context switch can happen at any time. Variable update and Race condition! • New task access to the same function, is the function reentrant? • Specific to AVR: you need to shutdown interrupt for accessing 16-bit SFR like Timer value. (Atomic operation problem) See http://en.wikipedia.org/wiki/Thread-safe for more
Thread Safety Non-preemptive VS Preemptive • Less responsive • but higher throughput • Less to worry about reentrancy problem