(back to: main 5785 page, 5785 lab page)
Creating a Timer
Create a new project for your board in CodeWarrior using the same
steps as in Lab 1. Now develop code for a timer
based on the Programmable Interrupt Timer 0 (PIT0) module on your
ColdFire chip (see Chapter 22 of the reference manual for the MCF5223x).
Your assignment is to develop three functions:
void init_timer (void);
int start_timer (void);
int stop_timer (int);
init_timer() sets PIT0 as a free running timer that
counts down at the CPU frequency, resetting to 0xffff after it
reaches zero. Read about this in your processor manual.
This can be accomplished by writing the correct value to a
single configuration register MCF_PIT0_PCSR, using
macros found in the CodeWarrior header file
MCF52233_PIT.h. Be sure to set the PIT0 prescaler
properly so that it counts down at the bus clock frequency.
start_timer() returns an integer value corresponding
to the current value of the timer, as found in MCF_PIT0_PCNTR.
stop_timer() takes a timer start value as an argument
and compares this value to the current timer value. It
returns the number of elapsed cycles since the timer was started.
It must operate correctly even if the timer has
wrapped around to 0xffff between the call to start_timer()
and the call to stop_timer(). In other words, your
timer should correctly measure times from 0 to 65535 cycles.
Put these functions in a file timer.c
Using a Timer
Your task is to measure and report the average number of
cycles your ColdFire processor
requires to:
-
Add two random 32-bit integers.
-
Add two random 64-bit integers (long long ints).
-
Add two random double-precision floating point values.
-
Multiply two random 32-bit integers.
-
Multiply two random 64-bit integers.
-
Multiply two random double-precision floating point values.
-
Divide two random 32-bit integers.
-
Divide two random 64-bit integers.
-
Divide two random double-precision floating point values.
-
Copy a struct of size 8 bytes using struct assignment.
-
Copy a struct of size 128 bytes using struct assignment.
-
Copy a struct of size 1024 bytes using struct assignment.
More information:
-
For this part of the project ensure that your CodeWarrior compiler
is set to optimize for maximum speed.
-
You will need to write support functions generating random values of
the required types. Do not include the time to generate random
numbers in your measurements.
-
You should report the average
cycle count (rounded to nearest integer) for 100 different random
inputs.
-
You should
explicitly check to avoid dividing by zero.
-
You need to make sure the compiler is not optimizing
away the work that you are doing. Use CW's disassemble option to
look at the generated object code to make sure this is not happening.
The problem is that at high optimization levels the compiler is free to take an
operation such as x = y+z; and just eliminate it entirely, if the
compiler can show that x is never going to be used. This is correct
compiler behavior, even if it is a bit inconvenient for you here.
There are at least 3 ways -- all easy -- to prevent the compiler
from optimizing away your code. Figuring out one of these and implementing
it is part of your assignment.
Put all of this code in a file time_ops.c
Timer Interrupts
Starting with your init_timer() function, create
a new function init_timer_with_interrupts() that
makes PIT0 generate an interrupt when the timer rolls over.
Select the prescaler value for PIT0 that makes it flash LED0
(see code below) as close as possible to 1Hz (this just needs
to be close, not exact -- you can leave PIT0 as a free-running
timer).
Your interrupt handler should look like this:
__declspec(interrupt:0) void handler_pit0_int (void)
{
MCF_GPIO_PORTTC ^= 0x1;
MCF_PIT0_PCSR |= MCF_PIT_PCSR_PIF;
}
For this interrupt handler to blink the LED,
you will need to have set
bit 0 of port TC as GPIO and as an output pin.
You also need to install the interrupt handler by calling this function:
static unsigned char *fnSetIntHandler(int iVectNumber, unsigned char *new_handler)
{
extern unsigned long __VECTOR_RAM[];
unsigned char *old_handler;
old_handler = (unsigned char *)__VECTOR_RAM[iVectNumber];
__VECTOR_RAM[iVectNumber] = (unsigned long)new_handler;
return old_handler;
}
Its arguments should be the vector number, 119, and the address of your
interrupt handling function.
Also you need to use the following code to tell the interrupt controller
to give you interrupts for PIT0:
static void init_interrupt_controller (void)
{
MCF_INTC0_ICR55 |= MCF_INTC_ICR_IL (0x4) | MCF_INTC_ICR_IP (0x4);
MCF_INTC0_IMRH &= (~MCF_INTC_IMRH_INT_MASK55);
MCF_INTC0_IMRL &= (~MCF_INTC_IMRL_MASKALL);
}
After calling all hardware initialization functions, and before
entering your program's
main loop, you should enable interrupts by calling this function:
void enable_interrupts(void)
{
asm {
move.l #0x00002000,d0
move.w d0,SR
}
}
Put these functions in a file int_timer.c
Power-On Self Test
Modify your processor's boot code so that it performs some
power-on
self tests. You should:
-
Ensure that RAM is working properly; for example see
here and
here
and
here
-
Ensure that flash memory was loaded properly, using a checksum. You
should choose and implement a good checksum function. You'll need to
figure out how to compute this checksum after your system is compiled,
and how to insert the checksum into the compiled code. It is likely that
you will be modifying both makefiles and linker scripts.
-
Test this code by using it to perform a power-on self-test for a
ColdFire application such as your code for timing the different operations.
Put this code in a file self_test.c
Lab report
-
Handin the four (commented!) files of C code that you wrote.
-
For each
bit (or group of bits) you set or clear in any device driver, you must
have a comment explaining why you did this. In other words, for all
code you used for this lab, you must explain how it works in terms of
features described in the processor reference manual.
-
Handin a table (formatted in ASCII or PDF, but not MS Word!) of cycles
your processor requires to perform each of the 12 kinds of work.
-
Do not hand in the entire CodeWarrior project! Just source files
mentioned by name above.
Handin in the CADE Lab
To hand in file foo:
handin cs5785 lab2 foo
This page is maintained by John Regehr, mail me if you find a
mistake or if any content is unclear.