Noob Question: Accessing The Timer Count

Go To Last Post
21 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I doing an assember exercise on timers using VMLAB and coding for a ATtiny22.

It seems that reading or writing from/to TCNT0 causes an err:

Quote:
MOV TMP, TCNT0

* test6.asm, line 74: Illegal argument type or count

TMP is of course defined. Once again I am baffled. TCNT0 and TCCR0 are both defined in the ATtiny22 include file:

Quote:
;***** I/O Register Definitions
.equ SREG =$3f
.equ SPL =$3d
.equ GIMSK =$3b
.equ GIFR =$3a
.equ TIMSK =$39
.equ TIFR =$38
.equ MCUCR =$35
.equ MCUSR =$34
.equ TCCR0 =$33
.equ TCNT0 =$32
.equ WDTCR =$21
.equ EEAR =$1e
.equ EEARL =$1e
.equ EEDR =$1d
.equ EECR =$1c
.equ PORTB =$18
.equ DDRB =$17
.equ PINB =$16
What am I missing here?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you sure the error message complains about line 74, not line 47?

Warning: Grumpy Old Chuff. Reading this post may severely damage your mental health.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm sure it the one I made example of because VMLAB indicates the line containing the err with a red marks. The mark failed to get picked up when I copied it, probably because it was a graphic rather than text.

Here I deleted the line above it, and rebuilt.

Attachment(s): 

Last Edited: Sat. Mar 20, 2010 - 04:38 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The MOV opcode works only with the GPIO registers (R0-R31). You need to use IN instead.

Quote:
I'm sure it the one I made example of because VMLAB indicates the line containing the err with a red marks.

MBedder was making a joke. Around here if someone complains about an error in there code, but does not provide the code that contains the error, someone usually remarks that the error is in line 47.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I see. Well, I tried both:

IN TCNT0, ZER

// and

IN TCNT0, 0x00

ZER being defined as a GPR containing 0x00.

Same result. In the data sheet for the ATtiny22 IN and OUT are defined as IN Port, and OUT Port, rather than as register or immediate transfers.

VMLAB even has a problem with CLR TCNT0.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Tiny22 is a deadborn and obsolete device - throw it away along with VMLAB. Install AVR Studio and start learning the AVR architecture and instruction set using some of modern Tiny device - e.g. Tiny25.

Warning: Grumpy Old Chuff. Reading this post may severely damage your mental health.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would I AVRStudio would work under Linux, although I will look for a more modern device in VMLAB.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I see. Well, I tried both:
Code:
IN TCNT0, ZER

// and

IN TCNT0, 0x00
ZER being defined as a GPR containing 0x00.

Sorry, but you got it ALL BACKWARDS.
IN is used for reading I/O registers into a working register (r0-r31). Only low I/O registers can use this instruction. If you get an error telling you that I/O register is out of reach you need to use LDS istead of IN.

IN   r16,TCNT0  ;loads content of TCNT0 into r16
or
LDS   r16,ADCSR  ;load content of ADCSR into r16

Loading eg zero into a I/O register looks like this.

OUT   TCNT0,ZER  ;load zero into TCNT0
or
STS   ADCSR,r16  ;load content of r16 into ADCSR

It is never possible to directly access an I/O register, eg TCNT0 by

TCNT0,0x00

You need to load a working register (r0-r31) with the value you want to store into a I/O register.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For the details on the capabilities and limitations on the different assembler instructions the "AVR Instruction Set" document is invaluable. It can be downloaded from this web page: http://www.atmel.com/dyn/product...

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Lennart wrote:
Quote:
I see. Well, I tried both:
Code:
IN TCNT0, ZER

// and

IN TCNT0, 0x00
ZER being defined as a GPR containing 0x00.

Sorry, but you got it ALL BACKWARDS.
IN is used for reading I/O registers into a working register (r0-r31). Only low I/O registers can use this instruction. If you get an error telling you that I/O register is out of reach you need to use LDS istead of IN.

IN   r16,TCNT0  ;loads content of TCNT0 into r16
or
LDS   r16,ADCSR  ;load content of ADCSR into r16

Loading eg zero into a I/O register looks like this.

OUT   TCNT0,ZER  ;load zero into TCNT0
or
STS   ADCSR,r16  ;load content of r16 into ADCSR

It is never possible to directly access an I/O register, eg TCNT0 by

TCNT0,0x00

You need to load a working register (r0-r31) with the value you want to store into a I/O register.

Thank you SO much.

That got it going:

start:
	ldi TMP,2
	out TIMSK,TMP
	ldi TMP,250
	out TCNT0,TMP
	sei
	ldi TMP,1
	out TCCR0,TMP

Gees, is this something un-common or what? From the instruction summary I never would have guessed this is something that would work, because in the instruction summary P is defined like this:

Quote:
P: Constant (0-31/63), can be a constant expression
And the address for these registers is greater than 63.

Thanks again, :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Good to hear you solved the problem.

Quote:
Is this something un-common or what?

If you refer to getting it all backwards, it's quite normal to be confused first time approaching assembler.
As a rule of thumb: What's on the right side of comma goes into what's on the left side of comma.
Also if you use ADD, SUB, MOV etc the RESULT is on left side of comma.

Happy coding!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It was actually the way things were defined in the data sheet.

IN(In Port) Rd,P Rd<-P
OUT(Out Port) P,Rr P<-Rr

The direction was clear enough, although the data sheet lacks a defination for P, which had me thinking I/O Port like B, D etc, and the reference for P that I found separately mentinoed that it as a constant < 64.

The AVR instruction Set PDF that the link was given define the IN and OUT instruction as using A for I/O address, which I surmise means anything in the I/O register area.

IN Rd<-A and Out A<-Rr. That's clear in it's intent.

Cheers...

Last Edited: Sat. Mar 20, 2010 - 10:27 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
which I surmise means anything in the I/O register area.

NO NO.
IN/OUT have access to a limited range of I/O registers. I tried to tell you that!!
Just do some testing trying to use IN/OUT on I/O registers above 0x3F (64) and see if it works.
IIRC some of the old AVR's had so few I/O registers that they all could be reached by IN/OUT.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, I tried to tack this on the last post, but you beat me to it.

Maybe you could enlighten me about this. I'm beginning to see what you mean.

In the datasheet for the ATtiny22 in the Register Summary in the Address column there are two addresses listed. For TIMSK these are $39 and ($59) The parenthetical values being $20 higher then the others.

I noticed the plain values, those are the ones also used for the defines in the include file, work for the TIMSK definition with the IN and OUT instructions.

However, the parenthetical values work with indirect instructions like ST. What is going on there?

I used $59 for an indirect move, and noticed that was greater than 64 decimal, which was what got me wondering.

Apparently there's more than one way to access those registers... This works too:

	ldi TMP, 2
	ldi ZH, 0
	ldi ZL, $59
	st Z, TMP

Ok, I see the $20 difference is for the 32 GP registers, although why bother differentiating the offset? To me that just seems to confuse things.

***

I see, the plain $numbers are actually port numbers, and the parenthetical $numbers are actually addresses.

Hmm, the datasheet could be clearer about that. In any case I got it now. 8)

Last Edited: Sat. Mar 20, 2010 - 11:22 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Make the datasheet of your device the object of highest interest for a couple of weeks.
Very few questions regarding AVR behavior remains unanswered if you learn where to search.
I know it can feel overwhelming at first but there is really no other way to avoid hours/days of fruitless attempts to get eg SPI or PWM running.You need to read it as many times as needed to know where to search for answers. Not doing that WILL punish you.

As for the adressing of memories have a look in the chapter "AVR memories" and more specific at "SRAM Data Memory".

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yeah, sounds like good advice. I see the three divisions in the SRAM now. Interesting stuff.

Simplicity is why I started my learning exercises with the ATtiny22, the data sheets for the newer and more complex ones were overwhelming.

I feel my feet starting to get wet now. :)

Thanks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
The AVR instruction Set PDF that the link was given define the IN and OUT instruction as using A for I/O address, which I surmise means anything in the I/O register area.

Looking at the IN instruction in the document it says
Quote:
Syntax: IN Rd,A

and then describing hte restrictions on the operands as
Quote:
Operands: 0 ≤ d ≤ 31, 0 ≤ A ≤ 63

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
which I surmise means anything in the I/O register area.
...
Operands: 0 ≤ d ≤ 31, 0 ≤ A ≤ 63

In the case of the tiny22, the two are the same. In other chips, the I/O range goes beyond address 63.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Koshchi wrote:
Quote:
which I surmise means anything in the I/O register area.
...
Operands: 0 ≤ d ≤ 31, 0 ≤ A ≤ 63

In the case of the tiny22, the two are the same. In other chips, the I/O range goes beyond address 63.
I surmised that. What gets to me, is the two sets of addresses for the registers. I can live with that, although I tend to find comfort, and sanity for that matter, in single address space machines.

What's amusing about Intel, is that after all the segmented address space processors they made, they realized and admitted that single address space devices were just plain less trouble. The really ironic part of this story is that the Itanium processor was a commercial failure.

Everybody had gotten so use to data segments indices, code segment indice, and extraneous segment indices they forgot all about how simple and easy single address spaces were to deal with.

Granted in the case of AVRs, and micro-controllers in general, this is hardly any comparison, but the two sets of addresses do smack to such a situation.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
What's amusing about Intel, is that after all the segmented address space processors they made, they realized and admitted that single address space devices were just plain less trouble. The really ironic part of this story is that the Itanium processor was a commercial failure.

Segmented address and multiple address space are different kettles of fish. Intel went with segmented (and still do!) as they wanted an easy way to get extra addressing with little extra hardware. You have two choices - either go to larger registers or figure some means of bank switching some extra bits - segmentation! Motorola with the 68k went the other route - use 32 bit registers. With the '386 they added a MMU which does segmentation, but a lot smarter. It also needs more silicon to implement it. Intel still have the i/o address space!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

What's amusing about Intel, is that after all the segmented address space processors they made, they realized and admitted that single address space devices were just plain less trouble. The really ironic part of this story is that the Itanium processor was a commercial failure.

But the segmented thing was because the indexing registers in 8086 (SI etc) were just 16 bits wide which meant that they could only address 64KiB at a time. But remember this processor came just 4 years after the 8080 (8080=1974, 8085=1976, 80086=1978) and actually constituted a huge leap forwards.

To access memory beyond 64K they needed a banking mechanism. The unfortunate thing really is that they though that extending 16 bits to just 20 bits by a 4 bit shift would be enough. Things would have gone so much easier if they'd used the full 16 bit shift that could have been available so the segment register were just adjoined to the offset register for straight 32 bit addressing. They then had the chance at the 286 to correct things but didn't do very much better. It was only when they got to 386 that flat mode could be configured in the GDTs and IDTs that finally they broke away from the silly design limitation.