H8S timer configuration problem

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!

Reply to
Geek
Loading thread data ...

Dear Geek,

I have not used this mikro yet, but see below...

Geek wrote:

Did you check if (CLOCK/INTERRUPT_RATE)/16 evaluates to the correct value? I had often problems with bogus assemblers and compilers which were not able to handle as large numbers as CLOCKS is correctly.

HTH Wolfgang

--
From-address is Spam trap
Use: wolfgang (dot) mahringer (at) sbg (dot) at
Reply to
Wolfgang Mahringer

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.

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

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).

....

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

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 : 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 : 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
    PC Services
              GNU H8 & mailing list info
             For those web sites you hate
Reply to
Paul Carpenter

hex

two

make

its

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.

Reply to
Geek

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
Reply to
Wolfgang Mahringer

...

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
    PC Services
              GNU H8 & mailing list info
             For those web sites you hate
Reply to
Paul Carpenter

For

said.

and

evening

further

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.

Reply to
Geek

TPU1

triple

Found it! A stupid one on my part too embarrassing to mention. Thanks for assist.

Reply to
Geek

The Renesas web site has definitions using int and they have had people tell them they should be using short.

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
    PC Services
              GNU H8 & mailing list info
             For those web sites you hate
Reply to
Paul Carpenter

... snip ...

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
Reply to
CBFalconer

expected,

them

missing

for

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.

Reply to
Geek

We all do them and at least you can see we all do them.

Glad your problem is solved.

One thing helping with problems here and in other places I use, is that the bouncing of ideas can often help solve the problem. Sometimes I can learn things from other peoples approach to problems, sometimes it gives the spark to other ideas.

There is also a satisfying feel to having achieved something useful.

--
Paul Carpenter          | paul@pcserviceselectronics.co.uk
    PC Services
              GNU H8 & mailing list info
             For those web sites you hate
Reply to
Paul Carpenter

... snip ...

That gives someone with a similar problem one more thing to check.

--
"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
Reply to
CBFalconer

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.