Forums

H8S timer configuration problem

Started by Geek February 13, 2005
Hello.

I am having a problem generating a period interrupt on an H8S2329.  For
example, I want an interrupt every 1ms.  I have the following code.

System clock is 22.1184MHz throughout.

#define CLOCK 22118400
#define INTERRUPT_RATE 1000

void SetupTimer( void )
{
    // Turn on TPU module.
    MSTPCR &= ~portMSTP13;

    // Configure for period count on compare match with TGR1A
    // Divide the clock by 16.
    TCR1 = 0x22;

    // Set compare match value.  Divide by 16 as the input
    // to the timer is divided by 16.
    TGR1A = ( CLOCK / INTERRUPT_RATE ) / 16;

    // Enable the interrupt
    TIER1 = 0x01;

    // Start the timer.
    TSTR = 0x02;
}

But I find the interrupt period is much to long.  It does not seem to make
any difference what I set TGR1A to, the interrupt is as if it is set to its
maximum 0xffff.

Is there anything wrong here?  Is there anything else I need to do?  Any
help gratefully received.

Thanks!




On Sunday, in article
     <2mMPd.51293$68.15015@fe1.news.blueyonder.co.uk>
     who@nowhere.com "Geek" wrote:
>Hello. > >I am having a problem generating a period interrupt on an H8S2329. For >example, I want an interrupt every 1ms. I have the following code. > >System clock is 22.1184MHz throughout.
My assumptions here are that you are using GCC, as you don't say what compiler you are using. Basic register setup order is correct as other poster has stated your problem may well be in the calculation of TGR1A value.
>#define CLOCK 22118400
I would rewrite as #define CLOCK 22118400L ^- force to be a long int As 22118400 is in hex 1518000, which if evaluated as an int could be 8000 hex depending on how the evaluation is done for YOUR compiler
>#define INTERRUPT_RATE 1000 > >void SetupTimer( void ) >{ > // Turn on TPU module. > MSTPCR &= ~portMSTP13; > > // Configure for period count on compare match with TGR1A > // Divide the clock by 16. > TCR1 = 0x22; > > // Set compare match value. Divide by 16 as the input > // to the timer is divided by 16. > TGR1A = ( CLOCK / INTERRUPT_RATE ) / 16;
The trouble is ( CLOCK / INTERUPT_RATE ) is VERY dependent on how the compiler operates when a divsion implied as int has a long parameter. Castings of long to int come into play. Also how is TGR1A defined hopefully as an unsigned short. Just in case you have GCC and forced -mint32 option which could cause the register to be viewed as 32 bit if the TGR1A definition is as an int or unsigned int. If using -mint32 and register is defined as int type then the firt two bytes would be loaded into TGR1A with 0 and TGR1B would be loaded with the remaining 16 bits (see later). ....
>But I find the interrupt period is much to long. It does not seem to make >any difference what I set TGR1A to, the interrupt is as if it is set to its >maximum 0xffff.
I think you will find that you are actually getting a result of 0 being loaded into TGR1A giving a period of 0x10000 either due to
>Is there anything wrong here? Is there anything else I need to do? Any >help gratefully received.
I am more suspicious of your TGR1A definition as a quick test of your evaluation of gives Result should be ( 22118400 / 1000 ) / 16 = 1382 (integer) 0x566 Quick compile using GNU GCC for H8 series of the following:- #define CLOCK 22118400 #define INTERRUPT_RATE 1000 int i; void main( void ) { i = ( CLOCK / INTERRUPT_RATE ) / 16; } Gives an objdump of:- Disassembly of section .text: 00000000 <_main>: 0: 01 00 6d f6 01 00 6d f6 mov.l er6,@-er7 4: 0f f6 0f f6 mov.l er7,er6 6: 79 02 05 66 79 02 05 66 mov.w #0x566,r2 a: 6b a2 00 00 6b a2 00 00 00 00 mov.w r2,@0x0:32 e: 00 00 10: 01 00 6d 76 01 00 6d 76 mov.l @er7+,er6 14: 54 70 54 70 rts At address 6 we have the value 0x566 which looks correct, so either you are using a different compiler (not GCC) or version or have another problem related to other definitions or how it is compiled. However if the above is compiled with the -mint32 option the following code is seen from objdump 00000000 <_main>: 0: 01 00 6d f6 01 00 6d f6 mov.l er6,@-er7 4: 0f f6 0f f6 mov.l er7,er6 6: 7a 02 00 00 7a 02 00 00 05 66 mov.l #0x566,er2 a: 05 66 c: 01 00 6b a2 01 00 6b a2 00 00 00 00 mov.l er2,@0x0:32 10: 00 00 00 00 14: 01 00 6d 76 01 00 6d 76 mov.l @er7+,er6 18: 54 70 54 70 rts Note that address 6 is loading a 32bit value, which would fit with my suspicion that you are actually loading 0x0 into physical TGR1A and 0x566 into TGR1B (the next physical address). If this is the case you need to change ALL your register definitions from unsigned int to unsigned short. Check the code generated for that function as to what it actually is loading and trace back. The above code is NOT how I would do it, but to show that the code should be doing the right thing if EVERYTHING else is defined and linked correctly. -- Paul Carpenter | paul@pcserviceselectronics.co.uk <http://www.pcserviceselectronics.co.uk/> PC Services <http://www.gnuh8.org.uk/> GNU H8 & mailing list info <http://www.badweb.org.uk/> For those web sites you hate
"Paul Carpenter" <paul$@pcserv.demon.co.uk> wrote in message
news:20050213.2200.306670snz@pcserv.demon.co.uk...
> On Sunday, in article > <2mMPd.51293$68.15015@fe1.news.blueyonder.co.uk> > who@nowhere.com "Geek" wrote: > >Hello. > > > >I am having a problem generating a period interrupt on an H8S2329. For > >example, I want an interrupt every 1ms. I have the following code. > > > >System clock is 22.1184MHz throughout. > > My assumptions here are that you are using GCC, as you don't say what > compiler you are using. > > Basic register setup order is correct as other poster has stated your > problem may well be in the calculation of TGR1A value. > > >#define CLOCK 22118400 > > I would rewrite as > > #define CLOCK 22118400L > ^- force to be a long int > > As 22118400 is in hex 1518000, which if evaluated as an int could be 8000
hex
> depending on how the evaluation is done for YOUR compiler > > >#define INTERRUPT_RATE 1000 > > > >void SetupTimer( void ) > >{ > > // Turn on TPU module. > > MSTPCR &= ~portMSTP13; > > > > // Configure for period count on compare match with TGR1A > > // Divide the clock by 16. > > TCR1 = 0x22; > > > > // Set compare match value. Divide by 16 as the input > > // to the timer is divided by 16. > > TGR1A = ( CLOCK / INTERRUPT_RATE ) / 16; > > The trouble is ( CLOCK / INTERUPT_RATE ) is VERY dependent on how the > compiler operates when a divsion implied as int has a long parameter. > Castings of long to int come into play. > > Also how is TGR1A defined hopefully as an unsigned short. Just in case > you have GCC and forced -mint32 option which could cause the register > to be viewed as 32 bit if the TGR1A definition is as an int or unsigned > int. If using -mint32 and register is defined as int type then the firt
two
> bytes would be loaded into TGR1A with 0 and TGR1B would be loaded with the > remaining 16 bits (see later). > > .... > > >But I find the interrupt period is much to long. It does not seem to
make
> >any difference what I set TGR1A to, the interrupt is as if it is set to
its
> >maximum 0xffff. > > I think you will find that you are actually getting a result of 0 being > loaded into TGR1A giving a period of 0x10000 either due to > > >Is there anything wrong here? Is there anything else I need to do? Any > >help gratefully received. > > I am more suspicious of your TGR1A definition as a quick test of your > evaluation of gives > > Result should be ( 22118400 / 1000 ) / 16 = 1382 (integer) > 0x566 > > Quick compile using GNU GCC for H8 series of the following:- > > #define CLOCK 22118400 > #define INTERRUPT_RATE 1000 > > int i; > > void main( void ) > { > i = ( CLOCK / INTERRUPT_RATE ) / 16; > } > > Gives an objdump of:- > > Disassembly of section .text: > > 00000000 <_main>: > 0: 01 00 6d f6 01 00 6d f6 mov.l er6,@-er7 > 4: 0f f6 0f f6 mov.l er7,er6 > 6: 79 02 05 66 79 02 05 66 mov.w #0x566,r2 > a: 6b a2 00 00 6b a2 00 00 00 00 mov.w r2,@0x0:32 > e: 00 00 > 10: 01 00 6d 76 01 00 6d 76 mov.l @er7+,er6 > 14: 54 70 54 70 rts > > > At address 6 we have the value 0x566 which looks correct, so either > you are using a different compiler (not GCC) or version or have another > problem related to other definitions or how it is compiled. > > However if the above is compiled with the -mint32 option the following > code is seen from objdump > > 00000000 <_main>: > 0: 01 00 6d f6 01 00 6d f6 mov.l er6,@-er7 > 4: 0f f6 0f f6 mov.l er7,er6 > 6: 7a 02 00 00 7a 02 00 00 05 66 mov.l #0x566,er2 > a: 05 66 > c: 01 00 6b a2 01 00 6b a2 00 00 00 00 mov.l er2,@0x0:32 > 10: 00 00 00 00 > 14: 01 00 6d 76 01 00 6d 76 mov.l @er7+,er6 > 18: 54 70 54 70 rts > > Note that address 6 is loading a 32bit value, which would fit with my > suspicion that you are actually loading 0x0 into physical TGR1A and > 0x566 into TGR1B (the next physical address). If this is the case you > need to change ALL your register definitions from unsigned int to > unsigned short. > > Check the code generated for that function as to what it actually is > loading and trace back. > > The above code is NOT how I would do it, but to show that the code > should be doing the right thing if EVERYTHING else is defined and linked > correctly. > > -- > Paul Carpenter | paul@pcserviceselectronics.co.uk > <http://www.pcserviceselectronics.co.uk/> PC Services > <http://www.gnuh8.org.uk/> GNU H8 & mailing list info > <http://www.badweb.org.uk/> For those web sites you hate >
Hi, Thanks for your detailed reply. Yes I am using GCC, sorry should have said. The value loaded was actually correct. I have also tried hard coding the value loaded into TGR1A (without the divides), and checked it in memory - but it made no difference. Could my clearing of the interrupt be the cause of the problem? void TimerISR( void ) __attribute__ ( ( interrupt_handler ) ); void TimerISR( void ) { //* Clear the interrupt. TSR1 &= ~0x01; } Thanks again.
Hi Geek,

Geek wrote:
>>> TGR1A = ( CLOCK / INTERRUPT_RATE ) / 16; >> ... >>Result should be ( 22118400 / 1000 ) / 16 = 1382 (integer) >> 0x566 >>
Since I do not know this chip in particular: Does it have an incrementing oder decrementing timer register? If it has it incrementing, which is common, that line should be either TGR1A = - ( CLOCK / INTERRUPT_RATE ) / 16; --or-- TGR1A = 65536 - ( CLOCK / INTERRUPT_RATE ) / 16; HTH Wolfgang -- From-address is Spam trap Use: wolfgang (dot) mahringer (at) sbg (dot) at
On Monday, in article
     <sWXPd.56024$68.28828@fe1.news.blueyonder.co.uk>
     who@nowhere.com "Geek" wrote:

>"Paul Carpenter" <paul$@pcserv.demon.co.uk> wrote in message >news:20050213.2200.306670snz@pcserv.demon.co.uk... >> On Sunday, in article >> <2mMPd.51293$68.15015@fe1.news.blueyonder.co.uk> >> who@nowhere.com "Geek" wrote: >> >Hello. >> > >> >I am having a problem generating a period interrupt on an H8S2329. For >> >example, I want an interrupt every 1ms. I have the following code. >> > >> >System clock is 22.1184MHz throughout. >> >> My assumptions here are that you are using GCC, as you don't say what >> compiler you are using. >> >> Basic register setup order is correct as other poster has stated your >> problem may well be in the calculation of TGR1A value. >>
...
>Hi, > >Thanks for your detailed reply. Yes I am using GCC, sorry should have said. > >The value loaded was actually correct. I have also tried hard coding the >value loaded into TGR1A (without the divides), and checked it in memory - >but it made no difference. > >Could my clearing of the interrupt be the cause of the problem? > >void TimerISR( void ) __attribute__ ( ( interrupt_handler ) ); >void TimerISR( void ) >{ > //* Clear the interrupt. > TSR1 &= ~0x01; >}
Assuming TSR1 and the other definitions point to the correct addresses as correct sizes and 'volatiles', that is all I use on 16 bit times on H8 and works fine. I would consider checking that you have the correct vectors setup (not in TGRB compare match vector on overflow, or overflow/underflow vectors), and catch the contents of the TSR1 to see what flags are set. You may have something else disabling interupts and using up time stopping the CPU from getting to the interupt. I am off to customer site so I will not see anything else until this evening so I would suggest looking at some of my links in the sig below for further assistance, possibly from others. -- Paul Carpenter | paul@pcserviceselectronics.co.uk <http://www.pcserviceselectronics.co.uk/> PC Services <http://www.gnuh8.org.uk/> GNU H8 & mailing list info <http://www.badweb.org.uk/> For those web sites you hate
"Paul Carpenter" <paul$@pcserv.demon.co.uk> wrote in message
news:20050214.0911.306684snz@pcserv.demon.co.uk...
> On Monday, in article > <sWXPd.56024$68.28828@fe1.news.blueyonder.co.uk> > who@nowhere.com "Geek" wrote: > > >"Paul Carpenter" <paul$@pcserv.demon.co.uk> wrote in message > >news:20050213.2200.306670snz@pcserv.demon.co.uk... > >> On Sunday, in article > >> <2mMPd.51293$68.15015@fe1.news.blueyonder.co.uk> > >> who@nowhere.com "Geek" wrote: > >> >Hello. > >> > > >> >I am having a problem generating a period interrupt on an H8S2329.
For
> >> >example, I want an interrupt every 1ms. I have the following code. > >> > > >> >System clock is 22.1184MHz throughout. > >> > >> My assumptions here are that you are using GCC, as you don't say what > >> compiler you are using. > >> > >> Basic register setup order is correct as other poster has stated your > >> problem may well be in the calculation of TGR1A value. > >> > ... > >Hi, > > > >Thanks for your detailed reply. Yes I am using GCC, sorry should have
said.
> > > >The value loaded was actually correct. I have also tried hard coding the > >value loaded into TGR1A (without the divides), and checked it in memory - > >but it made no difference. > > > >Could my clearing of the interrupt be the cause of the problem? > > > >void TimerISR( void ) __attribute__ ( ( interrupt_handler ) ); > >void TimerISR( void ) > >{ > > //* Clear the interrupt. > > TSR1 &= ~0x01; > >} > > Assuming TSR1 and the other definitions point to the correct addresses as > correct sizes and 'volatiles', that is all I use on 16 bit times on H8 > and works fine. > > I would consider checking that you have the correct vectors setup (not > in TGRB compare match vector on overflow, or overflow/underflow vectors),
and
> catch the contents of the TSR1 to see what flags are set. > > You may have something else disabling interupts and using up time stopping > the CPU from getting to the interupt. > > I am off to customer site so I will not see anything else until this
evening
> so I would suggest looking at some of my links in the sig below for
further
> assistance, possibly from others. > > -- > Paul Carpenter | paul@pcserviceselectronics.co.uk > <http://www.pcserviceselectronics.co.uk/> PC Services > <http://www.gnuh8.org.uk/> GNU H8 & mailing list info > <http://www.badweb.org.uk/> For those web sites you hate >
Hmmm. Very strange. I have checked the register definitions with the header available on the Renesas WEB site and they seem fine. I have also tried reading back the register values and they are set correctly. I have all the unused interrupt vectors set to null, if I uninstall the TPU1 vector then the program crashes - as expected. I find that the TIER1, TSTR and MSTPCR settings seem to work as expected, but the TCR1 and TGR1A registers don't make any difference what I set them to. This would make it look like a TCR1 setting problem - but I have triple checked and it seems fine. I am thinking there is something unrelated to the timer that I am missing setting up - or that my understanding of the manual is wrong.
> > Hmmm. Very strange. > > I have checked the register definitions with the header available on the > Renesas WEB site and they seem fine. I have also tried reading back the > register values and they are set correctly. > > I have all the unused interrupt vectors set to null, if I uninstall the
TPU1
> vector then the program crashes - as expected. > > I find that the TIER1, TSTR and MSTPCR settings seem to work as expected, > but the TCR1 and TGR1A registers don't make any difference what I set them > to. This would make it look like a TCR1 setting problem - but I have
triple
> checked and it seems fine. > > I am thinking there is something unrelated to the timer that I am missing > setting up - or that my understanding of the manual is wrong.
Found it! A stupid one on my part too embarrassing to mention. Thanks for assist.
On Monday, in article
     <n_5Qd.58731$68.10941@fe1.news.blueyonder.co.uk>
     who@nowhere.com "Geek" wrote:
>> Hmmm. Very strange. >> >> I have checked the register definitions with the header available on the >> Renesas WEB site and they seem fine. I have also tried reading back the >> register values and they are set correctly.
The Renesas web site has definitions using int and they have had people tell them they should be using short.
>> I have all the unused interrupt vectors set to null, if I uninstall the >TPU1 >> vector then the program crashes - as expected. >> >> I find that the TIER1, TSTR and MSTPCR settings seem to work as expected, >> but the TCR1 and TGR1A registers don't make any difference what I set them >> to. This would make it look like a TCR1 setting problem - but I have >triple >> checked and it seems fine. >> >> I am thinking there is something unrelated to the timer that I am missing >> setting up - or that my understanding of the manual is wrong. > >Found it! A stupid one on my part too embarrassing to mention. Thanks for >assist.
They are never too embarassing as somebody else will make the same mistake everyone comes to the same problem in their learning curve. People still forget the volatile attribute, I even spent a day chasing down a state machine problem that turned out to be a typo on the state change to 11 (decimal) instead of expected 0x11 (hex). We all make them and sharing them helps others to spot them in the future quicker. -- Paul Carpenter | paul@pcserviceselectronics.co.uk <http://www.pcserviceselectronics.co.uk/> PC Services <http://www.gnuh8.org.uk/> GNU H8 & mailing list info <http://www.badweb.org.uk/> For those web sites you hate
Geek wrote:
>
... snip ...
>> >> I am thinking there is something unrelated to the timer that I am >> missing setting up - or that my understanding of the manual is >> wrong. > > Found it! A stupid one on my part too embarrassing to mention. > Thanks for assist.
There have been others watching and thinking about it, and there will be more who access the archives and find this thread. We all make stoopidos, so just spit it out. That way a future hunter may actually find the answer. -- "If you want to post a followup via groups.google.com, don't use the broken "Reply" link at the bottom of the article. Click on "show options" at the top of the article, then click on the "Reply" at the bottom of the article headers." - Keith Thompson
"Geek" <who@nowhere.com> wrote in message
news:n_5Qd.58731$68.10941@fe1.news.blueyonder.co.uk...
> > > > Hmmm. Very strange. > > > > I have checked the register definitions with the header available on the > > Renesas WEB site and they seem fine. I have also tried reading back the > > register values and they are set correctly. > > > > I have all the unused interrupt vectors set to null, if I uninstall the > TPU1 > > vector then the program crashes - as expected. > > > > I find that the TIER1, TSTR and MSTPCR settings seem to work as
expected,
> > but the TCR1 and TGR1A registers don't make any difference what I set
them
> > to. This would make it look like a TCR1 setting problem - but I have > triple > > checked and it seems fine. > > > > I am thinking there is something unrelated to the timer that I am
missing
> > setting up - or that my understanding of the manual is wrong. > > > Found it! A stupid one on my part too embarrassing to mention. Thanks
for
> assist. >
I had the enable and disable interrupt routines the wrong way around. This meant the interrupts were only enabled for short periods, rather than the other way around. Ooops.