laboratorio di architetture e programmazione...
TRANSCRIPT
LABORATORIO DI ARCHITETTURE E PROGRAMMAZIONE DEI SISTEMI
ELETTRONICI INDUSTRIALILaboratory Lesson 3:
- Interrupt intuitions
-Advanced Debug with System Workbench for STM32
Prof. Luca Benini <[email protected]> Simone Benatti <[email protected]>Prof Davide Rossi <[email protected]> Victor Kartsch<[email protected]>
Info & Communications
Recap
Lab1: IDE & Debug
Lab2: GPIO & Systick
• GPIO configuration and LED hello world
• SysTick for periodic interrupts
Interrupts
Dealing with asynchronous events
• Many sources of asynchronous “events” during the execution of a program
• Application makes a system call
• Software executes illegal instruction (e.g. division by zero)
• Peripheral needs attention or has completed a requested action
• How do we know that an event has occurred?
• Broadly, two options to “detect” events
• Polling
• We can repeatedly poll the app/processor/peripherals
• When an event occurs, detect this via a poll and take action
• Interrupts
• Let the app/processors/peripheral notify us instead
• Take action when such a notification occurs (or shortly later)
Possible solutions
CPU periodically checks each device to see if it needs service
• Polling is like picking up your phone every few seconds to see if you have a call.
Pros: can be efficient if events arrive rapidly Cons: takes CPU time even when no requests pending
POLLING
INTERRUPT
Give each device an interrupt line that it can use to request the CPU’s attention
• When interrupt signaled (interrupt request), CPU executes a the associated routine (interrupt handler) to deal with the interrupt
• No overhead when no requests pending
Interrupts
Interrupt: an event external to the currently executing process that causes a change in the normal flow of instruction execution
• Usually generated by hardware devices external to the CPU
• Key point is that interrupts are asynchronous w.r.t. current process
• Typically indicate that some peripheral/device needs service
Why use interrupts?
• External peripherals need CPU service, but we can’t predict when
• We need a way for the CPU to find out devices need attention
• We want to keep the CPU free from continuously checking all the peripherals
• it can do other tasks
• it can go to sleep to save power
Interrupts on STM32
Interrupt Vector Table(startup_stm32f4xx.s)
Code in FLASH (ISR implemented)
#Interrupt n
#interrupt pISR n
ISR p
CPU Interrupts
Peripheral Interrupts
When IRQ arrives: • Corresponding interrupt address is read from the Interrupt Vector Table• The address points to the Interrupt Service Routine (ISR) (the interrupt handler)
• SystTick CPU interrupt part of the ARM Cortex M core.
• System timer that can generate periodic interrupts
• SysTick is used to schedule periodic events (usually configured to fire in the range of 1 - 100ms)
• When enabled, it periodically generates an interrupt• The state of the current process is saved (registers, program status and
counter)
• The IRQ handler is exectured: SysTick_Handler
• After its completion, the current process is restored and restarts
Interrupt example: SysTick
Debugging
Debugger
• Becoming confident with the debug tools is a fundamental skill for all embedded system designers
• The debugger interface provides you all the information on the currently executed code: call stack, variables status, registers stats, memory, etc
• It is fundamental to correct errors, find bugs, weird behaviors of your code and to look inside the code execution.
• You can also check the assembler code: how your C code was translated in ASM instructions
Breakpoints
Memory view
Registers view
ASM code
Eclipse View Perspectives
Debug Interface
Coding and Compiler interface
Eclipse offers 2 perspectives:
• C/C++ perspective for developing code
• Debug perspective
The Debug interface will start when you start a debug session
To change the current perspective: Window (main menu) -> Perspective -> Open Perspectiveor click on buttons in upper right corner
Start Debugger
Right click on project-> Debug as
-> Ac6 STM32 C/C++ Application
Debug Interface
Start / pause code execution
Stop / disconnect debugger
Debug steps:- Step Into- Step Over- Step Out
Call stack:The sequence of the functions
called up to this point
Next step enters in functions (if encounters a function call)
Next step executes all the function and goes over
Next step exits the currently executed function
Debug Interface
Mouse over a variable name to check its value
or look in the Variables panel (top right)
Current debugger location
Breakpoints(code execution will pause here)
Debug Tips
• Before starting a new debug session always terminate and remove the previous instances of the debugger.
• The code execution stops the line before the breakpoint position. (i.e. the last executed instruction is the line before the breakpoint).
• You can freeze the execution of the code with the pause button.
• If you get reference not found errors even if you included the correct headers, rebuild the index: Project -> C/C++ Index -> Rebuild
Practice with debug (1)
• Download the code: main-Lab3-debug.c
• It is organized in blocks: de-comment only one at a time, compile and debug• Select a section of code -> Source -> Toggle Comment
• Now look and de-comment the block at:
/******** Find MAX*******/
• Put a breakpoint at line: int size = ...;
• What is the state of the variables after you stopped at the breakpoint? why?
• Analyze execution of function with step into and step over
• Is everything ok? Correct results?
• Fix the bugs! (if any... )
Advanced Debug Tools
More Views
You can add more views to monitor:
• Assembly code
• Memory addresses
• Global variables
• Microcontroller’s registers
Variables monitoring
Memory View
To Explore the memory:
• Open Memory view
• Click New Readings
• Add memory address to monitor by variable name or its address
• You can check a variable’s monitor description to know at which address it is in memory
Memory View
To look at the memory cell corresponding to a variable:
• Go to the variables window• Right click • Select view memory (you also can see
the address)• It creates a new memory reading for
that variable
Practice with debug (2)
• Now look and de-comment the block at:
/******** !!!! ACCUMULATION!!!!! *******/
• Set a break point at: accumulator_count = 0;
• Execute and analyze step by step…
• Is everything ok? Correct results?
• (Hint) Use variable monitoring and various step into, step over…
• Fix the bug(s)! (if any... )
Variables Vs Pointers
Variables are programming elements that store a value (number, char, …)
• Every variable is actually stored in a memory location (check with debugger)
• Every variable type occupies different memory space
• For the compiler all variables are just memory addresses and sizes
• char = 1Byte, int = 4Byte, …
Pointers are variables that hold the memory address of another variable
• Pointers to variables are declared using the modifier *
• The & operator gets the address of a variable
• The * operator gets the value stored at the address in a pointer
Pointers
int myVar1 = 7
int var2;
int *myPointer;
myPointer = &myVar1
myVar2 = *myPointer
Variables
Pointer
Assign address of variable to pointer
Assign value at address in pointer to variable
Value to variable OKValue to pointer NOAddress to variable NOAddress to pointer OK
Pointers
Arrays are pointers to a block of memory
char array[12] -> 12 x sizeof(char) = 12 x 1Byte = 12 Byte
int arrayInt[12] -> 12 x sizeof(int) = 12 x 4Byte = 48 Byte
You can assign an array to a pointer and access its fields as with an array
• You have to pay attention not to exceed the dimension of a pointer or array
myPointer = arrayInt; OK
myVar1 = myPointer; NO
myVar2 = myPointer[1]; OK
myPointer[2] = myVar2 OK
Attention: wrong value/address assignments are not error for the compiler, you have to take care of what you do!
Practice with debug (3)
• Now look and de-comment the block at:
/******** !!!! POINTERS!!!!! *******/
• Set a break point at: myPointer = &myVar1;
• Execute and analyze step by step…
• Is everything ok? Correct results?
• (Hint) Use variable monitoring and memory view…
Practice with debug (4)
• Now look and de-comment the block at:
/******** !!!! FUNNY POINTERS!!!!! *******/
• Set a break point at: funnyPointer1 = arrayInt;
• Execute and analyze step by step…
• Is everything ok? Correct results?
• (Hint) Use variable monitoring and memory view…
Practice with debug (5)
• Now look and de-comment the block at:
/******** !!!! SIGNS !!!!! *******/
• Set a break point at: yes_sign_value = 10;
• Execute and analyze with step into and step over
• Is everything ok? Correct results?
• (Hint) Use variable monitoring and memory view…
Deep into the ARM
• What you want to do:
Simple assignment (put a value into a variable)
• What you write in C:
z = 1
• What actually happens:
ldr r3, [pc, #196] (put in register r3 the value in pc+196)
movs r2, #1 (put the value “1” in register r2)
str r2, [r3,#0] (store the value of r2 in the address contained in r3+0)
C code line number
What’s going on? ASM view
• Going deeply inside the ARM Cortex architecture
• See exactly what the machine is doing
• Disassembly window shows you the ASM code corresponding to the C instruction (C seems to be very high level here!)
Memory location of the ASM instruction
C instruction
ASM code
ASM code
if (r0 == 0)
{
r1 = r1 + 1;
}
else
{
r2 = r2 + 1;
}
Practice with debug (6)
• Now look and de-comment the block at:
/******** !!!! ASSEMBLER VIEW !!!!! *******/
• Execute and analyze step by step…
• Turn on Disassembly View and follow the ASM instructions
• Differences between C and ASM depend on the compiler and its optimization options
• We will not write ASM code, but here you can see in practice what you learn in the theory lessons
• Now you are ready to test and debug (advanced) programs
Only the brave…
We can also write code directly in ASM:main-Lab3-ASM.c
Looking at this simple code we understand better how the microcontroller works.(Remember the lessons on ARM architecture)
• r0-r15 registers are forgeneric operations
• sp is the stack pointer
stack is allocated for 3*4 bytes (3 local variables)
r7 stores the sp value
Assignments
Our ASM block:• Load in r3 value of pos0• Put 0d13 in r1• Add r3 and r1• Store the result in all the 3
cells
Check the results! 0xE = 1+13(Check the value of the sp register!)
The faster the better!
We can measure the number of clock cycles of pieces of code (functions, instructions, …)
Counter initialization
Counter setup
Counter start
Counter stop
To see the number of clock cycles fora desired block of code: Put the START and STOP defines
before and after it Put a breakpoint after the
STOPWATCH instruction Execute the code Read the value cyc[1] when the
execution breaks
See example in main-lab3-profiling.c
Evaluated code
Weekly assignments
Look at the provided code in main-lab3-mean-01.c and main-lab3-mean-02.c
• There is a dataBuffer, with examples for different data types (char, int and float)
• At every second the mean of a window of 5 samples is computed (mean on sliding window of size 5 and offset 5)
• When we reach the end of the buffer, it starts again from the beginning
• The two versions have the same final results, but
• 01 computes the mean in the SysTick ISR
• 02 sets a flag in the ISR and performs the computation back in main
• 01 is how NOT to do things! Use it as a bad example and from now on use 02!
Code example
Starting from the provided code for the mean:
1) Implement a function to compute the variance. Given a window of data xi, i = 1,…,N, we define:
• For the variance, implement functions for every data type as for the mean (char, int and float)
• The functions should have the same definitions and arguments/returns as the mean ones
int compute_var_XXX(int data[], int offset, int size)
2) Profile the execution times in cycles and seconds for every function (mean and var)
• You can prepare only one main and add comment to report the times
Assignments
𝑚𝑒𝑎𝑛 =1
𝑁
𝑖=1
𝑁
𝑥𝑖 𝑣𝑎𝑟 =1
𝑁
𝑖=1
𝑁
(𝑥𝑖 −𝑚𝑒𝑎𝑛)2
With reference to the provided main-lab3-debug.c code
1) Explain the bugs and how you fixed them in the Find MAX block
Where is the array maximum value? Why?
2) Explain the bugs and how you fixed them in the ACCUMULATION block
Which should be correct final result in the output vector? Why results are weird?
3) Fill up a table as the one below (it can be also reported in simple text) with the addresses and values of the provided variables at the end of the FUNNY POINTERS block
Explain what is in var1 and var2 and why? How you can fix it?
var1 var2 funnyPointer1 funnypointer2
Address
Value
Questions