Undocumented I/O addresses and internal circuitry

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

AtMega328p

 

The following I/O addresses are reserved:

 

0x00, 0x01, 0x02, 0x0C through 0x14

 

Doing some tests, I found out that whenever the AVR does an INPUT instruction, the read value is stored somewhere other than the intended register of the INPUT, and stays there.  Later you can retrieve the read contents at of the above reserved addresses.  Yeah, the INPUT instructions make a copy of the read value in all the above I/O addresses, or, maybe all the above addresses gate the I/O register used to hold the INPUT read.

 

So, suppose PORTD register contains $F3.   If the AVR does an INPUT R5,PORTD, R5 will contain $F3, but also all the reserved addresses above, and will stay like this until another INPUT is executed.

 

Note that CBI and SBI is a Read-Modify-Write, operation, so doing  SBI PORTD,2 will first INPUT x,PORTD, lift bit 2 in "x", and Write the new contents $F7 to PORTD, as OUT PORTD,x.

I don't know where the "bit lift" is done and where is "x", but for sure the Reserved Addresses above will hold the result of the INPUT x,PORTD

 

Also, other instructions involving I/O addresses, such as SBIS and SBIC must read the I/O address, and the same results happens.  Whenever you do SBIC PORTD,7, the contents of PORTD, in this case $F7, will be hold on the Reserved I/O Addresses above.

 

LDS instructions changes nothing on such Reserved I/O Addresses.

 

Of course, this found wasn't planned by Atmel, it might be some unused address selection circuitry to be used on larger chips, that end up gating this INPUT temporary undocumented register.  But it is funny to have access to this special register, it may be useful in some circumstances.  One that comes up to mind, is when comparing two sequential INPUTs from PINB  for example, the first reading would be

 

INPUT R0, PINB   ; it will also store PINB on the reserved I/O addresses

You may lose R0 at this point, later (without any other INPUT done),

 

INPUT R16,$0    ; retrieve the last and long done INPUT R0, PINB

INPUT R17,PINB ; get a new and actual reading of PINB

CP  R16,R17      ; compare old and new

 

The gain?  During the time period of the first and second reading of PINB, that may be a long time, you don't need to store the first reading anywhere, saving one register or SRAM position is not always better than how fast is to store the first INPUT somewhere... goes to the ghost register at $0~$3 or $0C~$14.

 

Suppose you are creating a Logic Analyzer Capture routine and want to know when PINB changes somehow (no interrupts).

 

AAA:  INPUT R16, $0

      INPUT R17, PINB   ; this INPUT will be also saved on $0

      CP    R16, R17

      BREQ  AAA

Do something else... take some time (no INPUTs)...

      RJMP  AAA

 

Note that you don't need to save R17 (the last reading of PINB) anywhere, it will stay on $0 until the AAA is called again.   Obviously the first pass should be discarded.

 

Another use (yeah, I know), suppose you have a  loop of  random CBI / SBI at PORTD, want to halt and check PORTD, the previous value of PORTD, before the last CBI/SBI will be at $0.

 

Of course, AVRStudio Simulation is a joke in this matter, whenever you make an OUT to any reserved I/O addresses, it keeps the value there, and you can read it back nicely...  it treats all I/O addresses as pure memory for write/read  ;)

 

Wagner Lipnharski
Orlando Florida USA

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

That's interesting, undocumented stuff is always good to know, though it can't be used in practice, since Atmel can change it in future silicon revisions. I think I'll check my own ATmegas to see if they also work like that. We can call it LILA (last input latch) register.

These addresses would belong to ports A, E, F and G if the 328P had those ports, right? Maybe it's some side effect of the non-existent inputs. Also, when you toggle pins by writing to PINx, does that count as doing an input?

What I really would like to be mirrored in a low address I/O (<=31) would be a copy of the status register so that we could use sbic/sbis on flags.

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

Well, we could start a conspiracy theory about this, or just move along as there are probably all sorts of semi-useless things at undocumented addresses.

 

Conspiracy theories are always fun.

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

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

El Tangas wrote:
What I really would like to be mirrored in a low address I/O (<=31) would be a copy of the status register so that we could use sbic/sbis on flags.

Indeed the chip designers didn't do us Mega88-class users a favor when the omnibus I/O layout was introduced--lots of gaps in the precious low I/O space.

 

But doesn't the instruction set give a complete set of BR__ op codes on SREG?  "Skip" is the degenerate "branch past one instruction", isn't it?

 

BRBS/BRBC are the generic, with pseudonyms for e.g. BRCC/BRCS, right? 

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Fri. Sep 16, 2016 - 03:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yeah, but the more different ways you can do the same thing, the better cheeky

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

El Tangas wrote:
Yeah, but the more different ways you can do the same thing, the better

????

 

Doesn't the datasheet say

...when there are really about 2/3 unique instructions?  Aren't those extra powerful instructions good enough for you?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

The AVR instruction set is excellent, but I would do a couple of tweaks, actually. An instruction to complement flags. The adci instruction, that doesn't exist. Locating sreg in the lower 32 I/O addresses, in range of sbi/cbi sbic/sbis. BST/BLD should operate on the carry flag instead of T flag.

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

El Tangas wrote:
Locating sreg in the lower 32 I/O addresses, in range of sbi/cbi sbic/sbis.
theusch wrote:
But doesn't the instruction set give a complete set of BR__ op codes on SREG? "Skip" is the degenerate "branch past one instruction", isn't it? BRBS/BRBC are the generic, with pseudonyms for e.g. BRCC/BRCS, right?
El Tangas wrote:
Yeah, but the more different ways you can do the same thing, the better

I'm out.  Next you'll want HCF.  Where in the instruction set map would you add all your magic redundant instructions?  Refer to the several threads that thoroughly explored the "map" and the "holes" that are remaining.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

theusch wrote:

I'm out.  Next you'll want HCF.  Where in the instruction set map would you add all your magic redundant instructions?  Refer to the several threads that thoroughly explored the "map" and the "holes" that are remaining.

 

Of what I proposed, only adci would actually require opcode slots. I'm well aware there is limited room.

But c'mon, aren't you taking this too seriously? I was just thinking out loud, it's not like I am demanding those features...

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

wagnerlip wrote:
Of course, AVRStudio Simulation is a joke in this matter, whenever you make an OUT to any reserved I/O addresses, it keeps the value there, and you can read it back nicely... it treats all I/O addresses as pure memory for write/read ;)

 

This reminds me when I was at school (long time ago) and was learning something about asm for the 8080 (Even then an old processor)

I used 3 of 4 different simulators and they all had a different implementation of the half carry flag.

In the end I gave up using packed bcd, it was not like this software was critical.

 

@ school they had also bought a good looking but extremely slow and buggy simulator.

For the homework I used some small, lean & fast assembler & simulator with a debug like interface.

My program (rpn calculator) which took less than an eyeblink to run at home took several minutes to run at school and this was in the days of 486 or pentium.

 

 

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

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

Paulvdh wrote:

wagnerlip wrote:
Of course, AVRStudio Simulation is a joke in this matter, whenever you make an OUT to any reserved I/O addresses, it keeps the value there, and you can read it back nicely... it treats all I/O addresses as pure memory for write/read ;)

 

This reminds me when I was at school (long time ago) and was learning something about asm for the 8080 (Even then an old processor)

I used 3 of 4 different simulators and they all had a different implementation of the half carry flag.

In the end I gave up using packed bcd, it was not like this software was critical.

 

@ school they had also bought a good looking but extremely slow and buggy simulator.

For the homework I used some small, lean & fast assembler & simulator with a debug like interface.

My program (rpn calculator) which took less than an eyeblink to run at home took several minutes to run at school and this was in the days of 486 or pentium.

 

 

 

Oh, yes. The DAA instruction was pretty useless. I made a decimal calculator once using it, could add, subtract, multiply and divide 6 digit numbers, but it was lots easier to do two's complement math and convert to or from decimal for input and output.

 

Tip: To multiply by 10: Shift left. Save a copy. Shift left twice more and add the saved copy.

 

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead.