CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

TMR1 & TMR3 errata on new chips

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
MikeValencia



Joined: 04 Aug 2004
Posts: 238
Location: Chicago

View user's profile Send private message Send e-mail Yahoo Messenger

TMR1 & TMR3 errata on new chips
PostPosted: Thu Feb 23, 2006 10:30 pm     Reply with quote

Can someone please clarify the TMR1 & TMR3 errata on the newer PIC18FXXX0 chips?

1. The errata does not affect Timer READs, right?

2. If I want to clear TMR1 for example, is this the proper procedure (or is it overkill?):
a. disable_interrupts();
b. stop timer 1;
c. set_timer1(0);
d. enable_interrupts(GLOBAL);

Is it necessary to clear interrupts? Or is it just necessary to stop the timer first? The errata says not to let any events occur between the writing of the register pair, thus i felt it necessary to disable interrupts.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Feb 26, 2006 3:34 pm     Reply with quote

Quote:
Can someone please clarify the TMR1 & TMR3 errata on the newer PIC18FXXX0 chips?

Can you post the exact part number of the PIC ? The we can download
the errata for it and look at it.
valemike
Guest







PostPosted: Tue Feb 28, 2006 11:12 am     Reply with quote

It's the PIC18F4580-I/PT. This has an errata for TMR1 and TMR2.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Feb 28, 2006 2:58 pm     Reply with quote

I've deleted this post because it referred to 8-bit read/write mode
for Timer1, but CCS uses 16-bit mode, so my post wasn't applicable.
I've deleted it to avoid causing confusion. See my new post below.


Last edited by PCM programmer on Wed Mar 01, 2006 1:47 pm; edited 1 time in total
MikeValencia



Joined: 04 Aug 2004
Posts: 238
Location: Chicago

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Wed Mar 01, 2006 3:46 am     Reply with quote

I'm just worried about the 16-bit mode.

The accompanying errata document says you cannot write to a free running timer without losing a few cycles, nor should you allow an 'event' to occur between a timer write.

I did not realize that set_timer1() may not work right in these chips!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 01, 2006 1:41 pm     Reply with quote

Disregard that post. I jumped the gun on it. If Timer1 was running in
8-bit read/write mode, then that post would be applicable. But CCS is
actually initializing Timer1 to run in 16-bit read/write mode.

Here's the setup code for the 18F4550, compiled with PCH vs. 3.245.
The top bit of T1CON is set, which puts Timer1 into 16-bit R/W mode.
Code:

.... setup_timer_1(T1_INTERNAL | T1_DIV_BY_4); 
0018:  MOVLW  A5
001A:  MOVWF  T1CON


The 18F4550 data sheet says that in 16-bit R/W mode, you should write
to the TMR1H register first and then write to TMR1L. CCS does this.
Code:
..... set_timer1(0);
001C:  CLRF   TMR1H
001E:  CLRF   TMR1L



The errata says:
Quote:

Module: Timer1/Timer3
When Timer1/Timer3 is operating in 16-bit mode
and the prescale setting is not 1:1, a write to the
TMR1H/TMR3H Buffer registers may lengthen the
duration of the period between the increments of
the timer for the period in which TMR1H/TMR3H
was written.

Work around
Do not write to TMR1H/TMR3H while Timer1/
Timer3 is running, or else write to TMR1L/TMR3L
immediately following a write to TMR1H/TMR3H
.
Do not write to TMR1H/TMR3H and then wait for
another event before also updating TMR1L/TMR3H.


CCS follows the method that I've underlined above, but what if an
interrupt occurred between the two instructions ? Then the errata
problem could occur. So the following code would be best:
Code:
disable_interrupts(GLOBAL);
set_timer1(0);
enable_interrupts(GLOBAL);
MikeValencia



Joined: 04 Aug 2004
Posts: 238
Location: Chicago

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Wed Mar 01, 2006 4:30 pm     Reply with quote

Quote:

Work around
Do not write to TMR1H/TMR3H while Timer1/
Timer3 is running, or else write to TMR1L/TMR3L
immediately following a write to TMR1H/TMR3H.


The wording is a bit confusing. It directly says not to write to TMR1H while the timer is running, thus it is probably more appropriate to stop timer1 first.

Quote:

Do not write to TMR1H/TMR3H and then wait for
another event before also updating TMR1L/TMR3H.

The above sentence then warrants the need to disable interrupts.

Thus shouldn't we add in a statement to stop timer1 in addition to disabling interrupts?

Code:

disable_interrupts(GLOBAL);
setup_timer_1(T1_DISABLED); // stops timer 1; is this necessary?
set_timer1(0);
enable_interrupts(GLOBAL);


I'm really confused on the wording of the errata and the workaround, and it's probably harmless anyways since I am ultimately setting the timer to 0x0000. So it probably doesn't matter if I "...lengthen the
duration of the period between the increments of
the timer for the period in which TMR1H/TMR3H
was written.
"...since i'll probably lose a harmless 2 or 3 machine cycles (which is an occasional few nanoseconds every now and then) Confused

I also hope that this errata doesn't apply to Timer1 READs! With the lengthening lead times of the '0'-less legacy chips (which have less erratas), I feel like i'm between a rock and a hard place.
MikeValencia



Joined: 04 Aug 2004
Posts: 238
Location: Chicago

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Wed Mar 01, 2006 4:31 pm     Reply with quote

Quote:

Work around
Do not write to TMR1H/TMR3H while Timer1/
Timer3 is running, or else write to TMR1L/TMR3L
immediately following a write to TMR1H/TMR3H.


The wording is a bit confusing. It directly says not to write to TMR1H while the timer is running, thus it is probably more appropriate to stop timer1 first.

Quote:

Do not write to TMR1H/TMR3H and then wait for
another event before also updating TMR1L/TMR3H.

The above sentence then warrants the need to disable interrupts.

Thus shouldn't we add in a statement to stop timer1 in addition to disabling interrupts?

Code:

disable_interrupts(GLOBAL);
setup_timer_1(T1_DISABLED); // stops timer 1; is this necessary?
set_timer1(0);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_4);
enable_interrupts(GLOBAL);


I'm really confused on the wording of the errata and the workaround, and it's probably harmless anyways since I am ultimately setting the timer to 0x0000. So it probably doesn't matter if I "...lengthen the
duration of the period between the increments of
the timer for the period in which TMR1H/TMR3H
was written.
"...since i'll probably lose a harmless 2 or 3 machine cycles (which is an occasional few nanoseconds every now and then) Confused

I also hope that this errata doesn't apply to Timer1 READs! With the lengthening lead times of the '0'-less legacy chips (which have less erratas), I feel like i'm between a rock and a hard place.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 01, 2006 4:38 pm     Reply with quote

The use of "or else" implies two solutions. It means you can fix it by
using the first method or the 2nd method.

The errata doesn't mention Read operations. It only applies to Writes.
MikeValencia



Joined: 04 Aug 2004
Posts: 238
Location: Chicago

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Wed Mar 01, 2006 4:56 pm     Reply with quote

Idea I sort of see now. So for the first suggested workaround:

Quote:
Work around
Do not write to TMR1H/TMR3H while Timer1/
Timer3 is running,...


If I follow this workaround, then I simply need to stop timer1 first, write the value to the tmr1 register pair, and then restart timer1. (** no interrupts disabled here **)

Quote:
... or else write to TMR1L/TMR3L
immediately following a write to TMR1H/TMR3H.


And if I follow this workaround, then I need NOT stop timer1. I just disable interrupts like you showed me earlier, then write the value i want to tmr1h/tmr1L, in the proper order, then re-enable interrupts.

Actually, in my original implementation on the '458, the only time I 'restart' timer1 from 0 is when I get an RB0 (external) interrupt. Since I don't have high priority interrupts enabled, then since I am in an ISR with interrupts already disabled, then I can simply write:

Code:

#int_ext
void my_rb0_isr(void)
{
...
    set_timer_1(0);
}


I guess it is much less complicated than I first thought.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group