Blackfin Timers Independent timers build into the processor

Blackfin Timers Independent timers build into the processor Timer Control Copyright M. Smith, ECE, University of Calgary, Canada

Timers available on Blackfin Watchdog timer – Hardware Reference 15 -49 l Core timer – Hardware Reference 15 -45 l General purpose timers 15 -1 l l Pulse Width Modulation Pulse Width Count and Capture External Event Application of timers to provide code safety and improved version of Use. Fixed. Time. ASM( ) l Introduction to timer interrupts l 12/17/2021 Timer Control Copyright M. Smith, ECE, University of Calgary, Canada 2

Basic concept – watchdog timer l Your code is running in the field l Something goes unexpectedly wrong, and one piece of code keeps running, and running l Other parts of the system self-destruct as there are no control signals send to them l Fix 12/17/2021 this issue with “Watch. Dog Timer” Timer Control Copyright M. Smith, ECE, University of Calgary, Canada 3

Watch. Dog. Timer int main( ) { Set. Up. Watch. Dog. Timer. ASM( ); Start. Watch. Dog. Timer. ASM( ); Reset. Watch. Dog. Timer. ASM( ); for ( ; ; ) { // For-ever loop Task 1( ); Reset. Watch. Dog. Timer. ASM( ); Task 2( ); Reset. Watch. Dog. Timer. ASM( ); Task 3( ); Reset. Watch. Dog. Timer. ASM( ); } } If a task does not return in time to Reset the Watch. Dog Timer then the system can be made to reboot, or send error message etc 12/17/2021 Timer Control Copyright M. Smith, ECE, University of Calgary, Canada 4

Watchdog Timer Operation 12/17/2021 Timer Control Copyright M. Smith, ECE, University of Calgary, Canada 5

Example code _Set. Up. Watch. Dog. Timer. ASM__Fv: P 0. H = hi(WDOG_CNT) P 0. L = lo(WDOG_CNT) // Get the address into P 0 // Put 0 x 40000000 into R 1; R 1. L = 0 x 0000; How long is 0 x 4000 0000 ticks? R 1. H = 0 x 4000; [P 0] = R 1; // Watchdog Count Register and Watchdog Register 12/17/2021 Timer Control Copyright M. Smith, ECE, University of Calgary, Canada 6

Better Code _Set. Up. Watch. Dog. Timer. ASM__Fv: P 0. H = hi(WDOG_CTL) P 0. L = lo(WDOG_CTL) // Get the address into P 0 // Put 0 x 0 AD 0 into R 1. L; R 1. L = 0 x 0 AD 0; W[P 0] = R 1; // Watchdog control register – disable SSYNC; // System synchronize P 0. H = hi(WDOG_CNT) P 0. L = lo(WDOG_CNT) // Get the address into P 0 // Put 0 x 40000000 into R 1; R 1. L = 0 x 0000; R 1. H = 0 x 4000; Timer. Register Control [P 0] = R 1; // Watchdog Count and Watchdog Register 12/17/2021 Copyright M. Smith, ECE, University of Calgary, Canada 7

Starting the watchdog timer _Start. Watch. Dog. Timer. ASM__Fv: P 0. H = hi(WDOG_CTL) P 0. L = lo(WDOG_CTL) // Get the address into P 0 // Put 0 x 0000 into R 1. L; Will force a “RESET EVENT” R 1. L = 0 x 0000; W[P 0] = R 1; // Watchdog control register – counter enabled 12/17/2021 Timer Control Copyright M. Smith, ECE, University of Calgary, Canada 8

Watchdog Status Register WDOG_STAT 12/17/2021 Timer Control Copyright M. Smith, ECE, University of Calgary, Canada 9

Reset. Watch. Dog. Timer. ASM( ); TAKE-HOME EXERCISE l You write the required code – base on standard Blackfin Assembly language Stub _Reset. Watch. Dog. Timer. ASM: l 12/17/2021 Timer Control Copyright M. Smith, ECE, University of Calgary, Canada 10

Temperature Sensor Q – how can you time “High” time? +5 V GROUND SIGNAL TO BLACKFIN HIGH 12/17/2021 ANALOG DEVICES TMP 03 Temperature Sensor LOW Timer Control Copyright M. Smith, ECE, University of Calgary, Canada 11

C++ version of code Develop a routine Use. Up. Fixed. Amout. Time( ) that uses up a fixed amount of time l Count how many time this routine must be called while the temperature signal is HIGH l Could be constructed using “for-loop” void Use. Up. Fixed. Amout. Time(unsigned long int time. To. Use) { unsigned short int counter = 0; for (counter = 0; count <= time. To. Use; count++) { counter = counter; // Waste time } // Spin the wheels 12/17/2021 Timer Control Copyright M. Smith, ECE, University of Calgary, Canada 12

Improved Version void Use. Up. Fixed. Amount. Time(unsigned long int time. To. Use) { 1. Load the core timer counter register with parameter “time_to_use” 2. Start the core timer 3. While the core timer counter register ! = 0 4. continue 4. Return 5. } 1. Core timer changes at 500 MHz – so can get very accurate timing values 12/17/2021 Timer Control Copyright M. Smith, ECE, University of Calgary, Canada 13

Core Timer You set Core timer register TSCALE to 0 (decrement by 0 + 1) You set register TPERIOD to 0 x 2000 You set register TCOUNT to 0 x 4000 You enable timer using control register TCNTL TCOUNT is decreased by 1 until it reaches 0 (0 x 4000 system clock ticks) When TCOUNT reaches 1, interrupt is caused and TCOUNT is reloaded with TPERIOD (0 x 2000) – counts down again 12/17/2021 Timer Control Copyright M. Smith, ECE, University of Calgary, Canada 14

TCOUNT and TPERIOD registers 12/17/2021 Timer Control Copyright M. Smith, ECE, University of Calgary, Canada 15

TSCALE and TCNTL registers 12/17/2021 Timer Control Copyright M. Smith, ECE, University of Calgary, Canada 16

Two new instructions The INTERRUPT mask contains information (bits set or clear) about which devices are allowed to interrupt the processor l CLI Rx l l l Save a copy of the “INTERRUPT” mask into data register Rx and then clear the mask (block all interrupts) STI Rx l 12/17/2021 Copy the bit pattern from data register Rx into the “INTERRUPT” mask, effectively reactivating all the devices that were allowed to interrupt the processor Timer Control Copyright M. Smith, ECE, University of Calgary, Canada 17

void Use. Up. Fixed. Amout. Time (unsigned long int time. To. Use) - 1 Stop interrupts -- Why is this needed CLI R 2; // Clear interrupts -- re-enable interrupts STI R 2; Stop the timer P 0. H = hi(TCNTL) P 0. L = lo(TCNTL) // Get the address into P 0 R 1 = 0; [P 0] = R 1; SSYNC; Load the core timer counter register with parameter “time_to_use (R 0)” P 0. H = hi(TCOUNT) P 0. L = lo(TCOUNT) // Get the address into P 0 [P 0] = R 0; SSYNC; Start the core timer P 0. H = hi(TCNTL) P 0. L = lo(TCNTL) // Get the address into P 0 R 1 = 3; [P 0] = R 1; Timer Control SSYNC; 18 12/17/2021 Copyright M. Smith, ECE, University of Calgary, Canada

void Use. Up. Fixed. Amout. Time (unsigned long int time. To. Use) - 2 Stop interrupts Stop the timer Load the core timer counter register with parameter “time_to_use” Start the core timer P 0. H = hi(TCNTL) P 0. L = lo(TCNTL) // Get the address into P 0 R 1 = 3; // Bit pattern %0000 0011 [P 0] = R 1; SSYNC; While the core timer counter register ! = 0 continue P 0. H = hi(TCOUNT) P 0. L = lo(TCOUNT) // Get the address into P 0 SSYNC // Necessary or not? TIMER_LOOP: R 0 = [P 0]; // Keep reading the timer counter CC = R 0 == 0; // TIMER COUNTER IS VOLATILE IF !CC JUMP TIMER_LOOP DE-ACTIVATE TIMER REACTIVATE INTERRUPTS – Old Timer values stored in R 2 Control RETURN 12/17/2021 Copyright M. Smith, ECE, University of Calgary, Canada 19

void Use. Up. Fixed. Amout. Time (unsigned long int time. To. Use) - 3 While the core timer counter register ! = 0 continue P 0. H = hi(TCOUNT) P 0. L = lo(TCOUNT) // Get the address into P 0 SSYNC // Necessary or not? TIMER_LOOP: R 0 = [P 0]; // Read the timer counter CC = R 0 == 0; IF !CC JUMP TIMER_LOOP DE-ACTIVATE TIMER // You provide the required code REACTIVATE INTERRUPTS – Old values stored in R 2 RETURN 12/17/2021 Timer Control Copyright M. Smith, ECE, University of Calgary, Canada 20

Problem -- CODE IS WAITING While the core timer counter register ! = 0 continue P 0. H = hi(TCOUNT) P 0. L = lo(TCOUNT) // Get the address into P 0 SSYNC // Necessary or not? TIMER_LOOP: R 0 = [P 0]; // Read the timer counter CC = R 0 == 0; IF !CC JUMP TIMER_LOOP Here the processor is waiting, which means that the processor can’t be calculating other values or servicing other requests Fixed by using interrupts Perhaps there are no other values to calculate. In that case we need to put the processor in a low power mode, and then wake it up Fixed with IDLE instruction and then wake-up enable register Timer Control 12/17/2021 Copyright M. Smith, ECE, University of Calgary, Canada 21

Concepts of interrupt code Task 2 – file 2 (C++ or ASM) Task 1 – file 1 volatile int foo_flag = 8; int main( ) { Set. Up. Timer. Interrupts(ISR_count); Start. Timer. Interrupts( ); while (foo_flag != 0) { Write. LEDASM(foo_flag); Do. Something Complicated( ); } Stop. Timer. Interrupts(); } extern volatile int foo_flag; Tell “C++” that I am not a function or subroutine that is called within the program. I am an ISR – interrupt service routine and proud of it. I can happen at any time because of an outside action void ISR_count( ) { foo_flag--; Tell the timer that the interrupt has been serviced } 12/17/2021 Timer Control Copyright M. Smith, ECE, University of Calgary, Canada 22

How it is supposed to work Task 1 – starts Sets up the timer so that it will cause an interrupt When this interrupt starts – task 1 will stop, task 2 will start doing some processing – spend NO time looking at the timer NOTE – if ISR – interrupt service routine – does not work then task 1 will never stop When Task 1 stops – turn off the interrupts 12/17/2021 Timer Control Copyright M. Smith, ECE, University of Calgary, Canada 23

Task 2 and Task 1 l Task 1 and Task 2 communicate via the “volatile foo_flag” variable – “message” l Every time the timer counts down to zero The TCOUNTER register is reloaded with TPERIOD register value l The timer counts down again l An interrupt is issued and latched l 12/17/2021 Timer Control Copyright M. Smith, ECE, University of Calgary, Canada 24

Unanswered questions 1. 2. 3. 4. 5. 6. 7. 8. What does “volatile” mean? Why will “optimized code” probably not work if volatile is not used? How do you tell C++ that this function is an ISR and not a standard function? Why do you need to tell C++ that this function is an ISR and not a standard function? What is the difference (in coding) between an ISR and a standard function? How does an interupt get latched, why and where? Why do I have to tell the timer that the interrupt has been serviced, and how do I do it? Remind me to ask Googan to help me with the “human microprocessor example” on Thursday. 12/17/2021 Task 2 – file 2 (C++ or ASM) extern volatile int foo_flag; Tell “C++” that I am not a function but I am an ISR – interrupt service routine void ISR_count( ) { foo_flag--; Tell the timer that the interrupt has been serviced } Timer Control Copyright M. Smith, ECE, University of Calgary, Canada 25

Tackled today Watchdog timer – Hardware Reference 15 -49 l Core timer – Hardware Reference 15 -45 l General purpose timers 15 -1 l l Pulse Width Modulation Pulse Width Count and Capture External Event Application of timers to provide code safety and improved version of Use. Fixed. Amount. Time. ASM( ) l Introduction to timer interrupts l 12/17/2021 Timer Control Copyright M. Smith, ECE, University of Calgary, Canada 26

l Information taken from Analog Devices On-line Manuals with permission http: //www. analog. com/processors/resources/technical. Library/manuals/ l Information furnished by Analog Devices is believed to be accurate and reliable. However, Analog Devices assumes no responsibility for its use or for any infringement of any patent other rights of any third party which may result from its use. No license is granted by implication or otherwise under any patent or patent right of Analog Devices. Copyright Analog Devices, Inc. All rights reserved. 12/17/2021 Timer Control Copyright M. Smith, ECE, University of Calgary, Canada 27
- Slides: 27