• We will learn how much memory the compiler allocates for the numerical variables and we will investigate the relative efficiency of the routines used to perform arithmetic operations
Trang 1Hệ thống nhúng
Thạc sĩ Lê Mạnh Hải
Embedded Systems
Trang 2Lesson 3 : NUMBERS
Flight plan:
• In this lesson we will review all the numerical data types offered by the MPLAB® C30 compiler
• We will learn how much memory the compiler
allocates for the numerical variables and we will investigate the relative efficiency of the routines used to perform arithmetic operations by using the MPLAB
• SIM Stopwatch as a basic profiling tool This
experience will help you choose the “right”
numbers for your embedded-control application, understanding when and how to balance
Trang 3Preflight checklist
• MPLAB IDE, Integrated Development Environment
• MPLAB SIM, software simulator
• MPLAB C30 compiler (Student Version)
Trang 4The flight
1.MPLAB C30 User Guide
Trang 5The flight
unsigned long i,j,k;
main ()
{
i = 0x1234; // assign an initial value to i
j = 0x5678; // assign an initial value to j
k = i * j; // perform the product and store the result in k}
Trang 6Assembly code
Trang 7On optimization (or lack thereof)
• In fact, the compiler does not see things this clearly—its
role is to create “safe” code, avoiding (at least initially) any assumption and using standard sequences of
instructions
• Later on, if the proper optimization options are enabled,
a second pass (or more) is performed to remove the
redundant code
• During the development and debugging phases of a
project, though, it is always good practice to disable all optimizations as they might modify the structure of the code being analyzed and render single-stepping and
breakpoint placement problematic
Trang 8• Set the cursor on the first line containing the initialization of the first variable, and perform a Run To Cursor command to let the program initialize and stop the execution just before the first instruction we want to observe.
• Open the Watch window (“View→Watch”) and select WREG0 in the SFR selection box, then click on the “Add SFR” button.
• Repeat the operation for WREG1.
• Select “i” in the symbol selection box, and click on the “Add Symbol” button.
• Repeat the operation for j and k.
• Use the “Step Over” function to execute the next few program lines, observing the effects on the registers and variables in the Watch
window As we noted before, when the value of a variable in the
Watch window changes, it is conveniently highlighted in red.
Trang 9Post-flight briefing
• In this lesson, we have learned not only what data types are available and how much memory is allocated to them, but also how they affect the resulting compiled program—
code size and the execution speed
• We used the MPLAB SIM simulator Stopwatch function to measure the number of instruction cycles (and therefore
time) required for the execution of a series of code
segments
• Some of the information gathered will, hopefully, be useful
to guide our actions in the future when balancing our needs for precision and performance in embedded-control
applications
Trang 10• What is Interrupts?
• Why does ES need more and more
Interrupts?
• How does Interrupts work?
• How can we control Interrupts?
Trang 11Flight plan
• How the MPLAB® C30 compiler allows us to
easily manage the interrupt mechanisms offered
by the PIC24 microcontroller architecture.
• After a brief review of some of the C language
extensions and some practical considerations, we will present a short example of how to use the
secondary (low-frequency) oscillator to maintain a real-time clock.
Trang 12Preflight checklist
• MPLAB IDE,
• MPLAB C30 compiler and the MPLAB SIM
simulator.
• Use the “New Project Set-up” checklist to
create a new project called “Interrupts” and
a new source file similarly called
“interrupts.c”.
Trang 13• Interrupts can be completely asynchronous with the execution
fl ow of the main program They can be triggered at any point
in time and in an unpredictable order Therefore, the goal is to minimize the interrupt latency, defined as the time between the triggering event and the execution of the fi rst instruction of the Interrupt Service Routine (ISR)
• In the PIC24 architecture, the latency is not only very short but it is also fixed for each given interrupt source—only three instruction cycles for internal events and four instruction
Trang 14PIC24F Interrupt
• Up to 8 processor exceptions and software traps
• 7 user-selectable priority levels
• Interrupt Vector Table (IVT) with up to 118
vectors
• A unique vector for each interrupt or exception
source
• Fixed priority within a specified user priority level
• Alternate Interrupt Vector Table (AIVT) for debug
Trang 15Interrupt Vector Table (IVT)
MPLAB C30 compiler can automatically associate interrupt vectors with “special” user-defined C functions as long as a few limitations are kept in consideration, such as:
• They are not supposed to return any value (use type void).
• No parameter can be passed to the function (use parameter void).
• They cannot be called directly by other functions.
• Ideally, they should not call any other function.
Trang 18external sources
• 5 × External pins with level trigger detection
• 22 × External pins connected to the Change Notifi cation module
• 5 × Input Capture modules
• 5 × Output Compare modules
• 2 × Serial port interfaces (UARTs)
Trang 19internal sources
• 5 × 16-bit Timers
• 1 × Analog-to-Digital Converter
• 1 × Analog Comparators module
• 1 × Real-time Clock and Calendar
• 1 × CRC generator
Trang 201 Write a program that uses Timer2 as a stopwatch for
real-time performance measurements If the width of
Timer 2 is not sufficient: use the prescaler (and lose
some of the lsb), or use Timer2 and Timer3 joined in the new 32-bit timer mode
2 Test the relative performance of the division for the
various data types
3 Test the performance of the trigonometric functions
relative to standard arithmetic operations
Trang 21What is next?
• CHAPTER 5: Interrupts (pg 53 - pg68)
– Nesting of interrupts?
– A template and an example for Timer1 interrupt
– A real example with Timer1
– Testing the Timer1 interrupt
– The secondary oscillator
– The real-time clock calendar (RTCC)
– Managing multiple interrupts
• PIC24F family manuals Section 8 Interrupts
• How to get them?
http://www.microchip.com/stellent/idcplg?
IdcService=SS_GET_PAGE&nodeId=2575
Trang 22• This prevents new interrupts from being serviced until the
present one is completed In other words, when the NSTDIS bit
Trang 23• Eight additional vectors occupy the first
locations on top of the IVT table
• They are used to capture special error
conditions such as a failure of the selected CPU oscillator, an incorrect address (word access to odd address), stack underflow, or
a divide by zero (math error).
Trang 24A template and an example for
Timer1 interrupt
// 1 Timer1 interrupt service routine
void _ISR _T1Interrupt( void)
Trang 25{
// 2 initializations
_T1IP = 4; // set Timer1 priority, (4 is the default value)
TMR1 = 0; // clear the timer
PR1 = period-1; // set the period register
// 2.1 confi gure Timer1 module clock source and sync setting T1CON = 0x8000; // check T1CON register options
// 2.2 init the Timer1 Interrupt control bits
_T1IF = 0; // clear the interrupt fl ag, before
_T1IE = 1; // enable the T1 interrupt source
// 2.3 init the processor priority level
_IP = 0; // 0 is the default value
// 3 the main loop
while( 1)
{
// your main code here
Trang 26A real example with Timer1
• By adding only a couple of lines of code, we can turn this template into a more practical example
• where Timer1 is used to maintain a real-time
clock, with tenths of a second, seconds and
minutes As a
• simple visual feedback we can use the lower 8 bits
of PORTA as a binary display showing the
Trang 27Before 1., add the declaration of a few new integer variables that will act as the seconds and minutes counters:
Trang 28#include <p24fj128ga010.h>
int dSec = 0;
int Sec = 0;
int Min = 0;
// 1 Timer1 interrupt service routine
void _ISR _T1Interrupt( void)
{
// 1.1 your code here
dSec++; // increment the tens of a second counter
if ( dSec > 9) // 10 tens in a second
{
dSec = 0;
Sec++; // increment the minute counter
if ( Sec > 59) // 60 seconds make a minute
Trang 29{
// 2 init Timer 1, T1ON, 1:1 prescaler, internal clock source
_T1IP = 4; // this is the default value anyway
TMR1 = 0; // clear the timer
PR1 = 25000-1; // set the period register
TRISA = 0xff00; // set PORTA lsb as output•
// 2.1 configure Timer1 module
T1CON = 0x8020; // enabled, prescaler 1:64, internal clock
// 2.2 init the Timer 1 Interrupt, clear the flag, enable the source _T1IF = 0;
_T1IE = 1;
// 2.3 init the processor priority level
_IP = 0; // this is the default value anyway
Trang 30Testing the Timer1 interrupt
– dSec, select from the Symbol pulldown box, then click on Add
– TMR1, select from the SFR pulldown box, then click on Add
– SR, select from the SFR pulldown box, then click on Add
simply double click By setting the breakpoint here, we will be able to observe whether the interrupt is actually being triggered.
with the program counter cursor (the green arrow) pointing right at the
breakpoint inside the interrupt service routine.
Trang 31Testing the Timer1 interrupt
• Add the Sec and Min variables to the Watch window
• Execute the Run command a few more times to verify that, after 10 iterations, the seconds counter is incremented
(To test the minutes increment, you might want to remove the current breakpoint and place a new one a few lines below
—otherwise you will have to execute the Run command exactly 600 times!)
• Place the new breakpoint on the Min++ statement in 1.2
• Execute Run once and observe that the seconds counter
has already been cleared
• Execute the StepOver command once and the minute
Trang 33The real-time clock calendar
(RTCC)
• Although it would be somewhat
entertaining to develop such code,
considering lapsed years and working out all the details, the PIC24FJ128GA010
already has a complete Real-time Clock and Calendar (RTCC) module built in and ready for use.
Trang 34RTCC interrupt service routine
// 1 RTCC interrupt service routine
void _ISR _RTCCInterrupt( void)
{
// 1.1 clear the interrupt flag
_RTCIF = 0;
// 1.2 your code here, will be executed only once a year
// that is once every 365 x 24 x 60 x 60 x 16,000,000 MCU cycles