EmbeddedRelated.com
Forums
Memfault Beyond the Launch

Problem with LPC2129, simple delay function

Started by madid87 July 29, 2006
Here is the program code:
--------------------------
//Header datoteke
#include

//Prototipi funkcija
void delay(int msec);

int main()
{
IODIR1 = 0xFF0000; // LEDice izlazne
IOCLR1 = 0xFF0000; // Ugasi ih
T1IR=0x0F;
while(1)
{
IOSET1=0xFF0000;
delay(2001);
IOCLR1=0xFF0000;
delay(2000);
}
return 0;
}

void delay(int msec)
{
T1MCR = 0x07; // Interrupt and stop
T1MR0 = 0x3A98*msec; // Ovoliko cekaj
T1TCR = 0x01; // Kreni
while(!(T1IR & 1)); // Cekaj kraj
T1IR = 0x01; // Ocisti interrupt
}
----------------------------------
----
It simple turn on and off LEDs on MCB2100 in intervals set by delay
function call.
When I run above program in Keil uVision3 Simulator it work normal, but
when I upload it in the chip it wont work !!!???

LEDs go on, then off and off they stay.
If a modify while(1) part to this
while(1)
{
IOSET1=0xFF0000;
delay(2000); //Notice, now there are 2 same delay calls (2001 before)
IOCLR1=0xFF0000;
delay(2000);
}

IT WORKS !! I'm killing mysefl with this, where is the bug? What is the
differance if I call delay 2x the same or I change parameters??

Please help me.

Greetings from Croatia!

An Engineer's Guide to the LPC2100 Series

--- madid87 wrote:

> void delay(int msec)
> {
> T1MCR = 0x07; // Interrupt and stop
> T1MR0 = 0x3A98*msec; // Ovoliko cekaj
> T1TCR = 0x01; // Kreni
> while(!(T1IR & 1)); // Cekaj kraj
> T1IR = 0x01; // Ocisti interrupt
> }
>
----------------------------------
> ----

I ran into something similar to this myself, but it
wasa a quick program and I worked around it.

I took a look at the User manual. The text implies
all actiions take place at the same time but take a
look at the timing diagrams on page 221. They imply
that the actions take place on different edges. It
might be worth trying a few things to see if the
diagrams more closely represent the truth. It could
be you are stopping immediately on reentering with the
same value.

A check (and workaround) might be to set the counter
to 0 (T1TC = 0) at the beginning of the delay routine.

Robert

__________________________________________________
--- In l..., "madid87" wrote:

> void delay(int msec)
> {
> T1MCR = 0x07; // Interrupt and stop
> T1MR0 = 0x3A98*msec; // Ovoliko cekaj
> T1TCR = 0x01; // Kreni
> while(!(T1IR & 1)); // Cekaj kraj
> T1IR = 0x01; // Ocisti interrupt
> }

The above code a disaster waiting to happen. Here is what I think is
happening:

1/ When the counter matches, it stops immediately and raises the
interrupt. This causes the first call to return immediately.

2/ Depending on prescale counter value, it takes a number of PCLKs
after the interrupt is raised to actually reset the counter to its
initial state.

3/ The second 2000ms delay arrived after counter stopped but before
it was reset.

4/ Writing (the same value) to the match register most likely
generates another interrupt immediately. This causes the call to
return prematurely.

Making the two calls with different values avoids this because the
counter values do not match when match register is written to.

The real solution is to fix the code so that the counter is reset to a
known state writing 0x20 to TCR. You have to leave this 0x20 bit set
in TCR for at least one PCLK or it can be missed because reset input
is synchronous.

Hope this helps.

Jaya
--- In l..., "jayasooriah" wrote:
> The above code a disaster waiting to happen. Here is what I think is
> happening:

> 4/ Writing (the same value) to the match register most likely
> generates another interrupt immediately. This causes the call to
> return prematurely.
> Making the two calls with different values avoids this because the
> counter values do not match when match register is written to.
> The real solution is to fix the code so that the counter is reset to a
> known state writing 0x20 to TCR. You have to leave this 0x20 bit set
> in TCR for at least one PCLK or it can be missed because reset input
> is synchronous.

Heh, I think you miss understood. When I call 2x with the same value it
WORKS, but when values are diffirent it doesnet work.

Thanks to you and Robert i solved this problem.
void delay(int msec)
{
T1TCR = 0x02; // Reset
T1MCR = 0x7; // Interrupt,stop and reset
T1MR0 = 0x3A98*msec; // Wait this long
T1TCR = 0x01; // Go
while(!(T1IR & 1)); // Wait for int flag
T1IR = 0x01; // Clear interrupt
}

Again thanks very much, this was killing me :-(
The problem was in that I tried to re_init timer to fast not leaving him
enough time for reset.

Ivan
--- In l..., "madid87" wrote:

> Heh, I think you miss understood. When I call 2x with the same
> value it WORKS, but when values are diffirent it doesnet work.

Looks like I guessed wrong.

Guess #2: The counter got re-armed before it was reset and triggered
the interrupt in just one ms instead of 2001 ms.

> Thanks to you and Robert i solved this problem.

Thats always good to know :)

Jaya

Memfault Beyond the Launch