What is the difference between a CPU register and the rest of volatile memory on AVR?

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

Going to use ATmega328P as an example.

 

It has all of its CPU and IO registers memory address mapped on an SRAM. A section of this SRAM is also used as volatile memory used by the stack.

 

The term "register" is a bit ambiguous for me here. Comparing it with x86 which usually uses SRAM as internal CPU registers and DRAM as memory somewhere on the bus (SRAM being much faster).

 

But in AVR everything seems to be placed on a gigantic SRAM which acts both as a register and memory? Is there a difference between AVR SRAM and the type of SRAM used in an x86 CPU?

This topic has a solution.
Last Edited: Thu. Jan 13, 2022 - 05:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Although the registers are also mapped to appear as the first 32 bytes in the RAM region that is simply a convenience that dates from a time when there was no actual RAM but they are quite different in that the opcode like LDI, AND, OR, etc can only operate on those 32 registers. You need to ST/STS/LD/LDS to operate on real RAM which is a slow operation and you can't do ADD, EOR, AND, OR, etc on such memory locations. The idea then is that you pull in up to 32 values from RAM and keep those in the registers for as long as required, perform the ops on them and when they then start to go "stale" you store values back out to slower RAM so you can then free the registers for working on whatever comes next. 

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

avruser1523 wrote:
It has all of its CPU and IO registers memory address mapped on an SRAM

being mapped into the same address space as the SRAM doesn't make them SRAM.

 

In particular, the IO Registers (aka "Special Function Registers", SFRs) are not just RAM - they are control signals connected to the peripheral hardware

 

avruser1523 wrote:
Is there a difference between AVR SRAM and the type of SRAM used in an x86 CPU?

not really.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@awneil

 

From this SO post about Arm I understood that a "memory mapped" register doesn't mean it's a register connected to memory and that memory address just acts as a bridge,

instead the address IS the register itself, it just has an address instead of name like "r0":

https://stackoverflow.com/questi...

 

But you are saying this is not true in AVR and memory on SRAM is just a bridge to another register off of SRAM?

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

Why does it matter?

 

Just treat the SFRs and the r-registers as SRAM with special properties (and some instructions that operate on them, and no-where else) and be done with it!

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

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

IO registers can be addressed like RAM, but they do not necessarily behave like RAM.

There are many IO registers that might not read the same value if you read them twice in a row, for example.  Other IO registers will not read back the same value you just wrote.

 

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

It doesn't matter of course,

 

I was under the impression that (based on the above SO link) memory mapped registers are actual registers which happen to have a memory address, they are actual registers and not just a section of RAM being called a register, and the word "memory mapped" doesn't mean they are connected/mapped to a section of memory to act as a data bridge, the address IS the register itself.

 

But the above sentence saying: 

being mapped into the same address space as the SRAM doesn't make them SRAM.

Made it sound like it behave like Arm.

 

So then the registers on AVR are NOT part of the SRAM itself and are only mapped similar to Arm? because the image in the datasheet gave me the impression that hey are physically on SRAM.

Last Edited: Thu. Jan 13, 2022 - 01:41 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avruser1523 wrote:

 Is there a difference between AVR SRAM and the type of SRAM used in an x86 CPU?

 

Also worth noting is that the AVR does not execute code from RAM*.  x86 CPUs do, which is why buffer overflowing is so nasty and AVRs don't do that*.  S.

 

* Generally speaking.  Yes, you can make them do so, but it's hard and bad.  See bootloaders.

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



So then the registers on AVR are NOT part of the SRAM itself

Correct.  Unlike ARM, there are a bunch of special instructions that access (some of) the "registers" of the AVR with fewer cycles and in less space.

Some of these (SBI, CBI) can access only the registers 0-31 (NOT the CPU registers, which also appear in the RAM address space on some AVRs), some can access registers 0-63 (IN, OUT)


I drew this a while ago - it might help.

(newer AVRs don't map the CPU registers any more, though.)

 

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

westfw wrote:
Correct. 

 

So similar to Arm then. Registers are memory mapped, they are actual registers and not part of the SRAM (RAM) itself.

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

Note also that in some processors, certain registers may be completely inaccessible to your code.

They could exist in a walled off area of sram, or live as a small island of 8 flip flop bits in some inaccessible area of the processor (and you won't be told one way or another, none the wiser).

 

For example, I believe some PIC chips will give you no direct access whatsoever to the stack pointer (register), yet you can push & pop  ...maybe you won't call it a register...hmm...knock knock ---who's hiding in there?      

 

Next up:  You will ask about the Xmega's virtual IO registers crying

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

IOREGs are changed in Restart, RAM and CPUREGs are not.

 

It means that they can survive a Restart (not always, though) and be used for debugging.

 

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

A 'traditional' CPU design will likely have register to register move instructions, often moved via the ALU but sometimes moved directly depending on the hardware design. That usually needs you to operate both reading and writing of different registers in the same clock cycle. That requires dual ported ram which has independent read and write addresses, so the output of one selected register can be applied to the input of another register. In practice that requires two address decoders.

 

Normal static ram is either reading or writing; it can't do both at the same time, so you can't do memory to memory transfers without using a temporary register. So it's almost certain that while the registers may be mapped to ram, that's not where they physically live on the chip; it's a function of the address decoding which makes them visible in this way, not their physical construction.

 

There is at least one register which is always going to be different because it requires the setting of individual bits - the flag register holding the processor status flags. You need to be able to read and write it in one hit - to save it to the stack in interrupts, at a minimum - and you not only need to be able to set selected bits but they need to be available to other parts of the circuitry on a permanent basis without reading the register itself. The same logic applies to hardware control registers such as IO ports.

 

To really confuse the issue: while AVR maps the registers to ram, older processors such as the 8080 (and all its descendants) do the reverse: all of memory is mapped to a single register - the M register. Reading or writing to that register accesses the memory addressed by a couple of other registers and that memory location can be used as if it were another register. And a hidden advantage of that is that the same physical mechanism can be used to access external memory at any stage in the instruction cycle: microcode selects whether HL, the program counter, the stack pointer, or perhaps a specialised memory access register is used to provide the address, but in every case the internal access requires a read or write of the M register.

 

(More recent processors do the same thing in an even more horrible and convoluted way. Don't even start thinking about prefetch and pipeline queues and cache memory...)

 

Neil

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


If you are really interested in AVR internals here is a good read on the subject:

https://www.arxterra.com/2-introduction-to-the-atmel-avr-family-of-microcontrollers/

 

There's even some die photos:

 

 

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


Just picking a random datasheet (this 328P) you find things like:

 

In this the the 32 GPRs clearly are not the same thing as the "Data SRAM". You also find:

 

Again the mapping of the 32 registers into SRAM and the access to the Internal SRAM may be within the same "Data Memory" but they are completely separate elements of the thing. (as are the SFRs/ext-SFRs)

 

As time went on AVR design changed and the Xmega series (of which all recent releases have been derivatives) came along and they changed the memory map (this from Atxmega128A1U datasheet):

 

 

Note now how you can no longer see or gain access the 32 GPRs in this. Down at 0 is simply SFRs (of which there is room for considerably more than Tiny/Mega!) - the CPU register access is no longer there.

 

In traditional AVR (well after about 2005) Atmel put a scattering if "GPIO" (effectively "scratchpad", quick access) registers in early memory. What they then did in Xmega was to put 16 of these down near 0. They then mapped "VPORT"s above these to also be in a fast access area.

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

ka7ehk wrote:
Why does it matter?

It does help to remember that SFRs are not "just RAM"; in particular, because what you write to a register is not necessarily what you will read-back from that register.

 

Writing to SFRs controls hardware - what you write is not necessarily stored.

 

This is a common beginner's mistake; eg, "I wrote X to the UART data register, but don't get X when I immediately read it back"

 

Another one is the Bit Set/Clear/Toggle type of registers - particularly the Clear/Toggle, where writing a 1 does not (necessarily) result in a 1 appearing ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avruser1523 wrote:
you are saying this is not true in AVR and memory on SRAM is just a bridge to another register off of SRAM?

Not sure what you mean by that - I don't think that's what I'm saying.

 

See, for example, #6 and #16

 

avruser1523 wrote:

being mapped into the same address space as the SRAM doesn't make them SRAM.

Made it sound like it behave like Arm.

Yes, it does - that is how ARM-based chips commonly behave, and AVR is much the same.

 

For example, see https://www.avrfreaks.net/commen... - where you have separate Set/Clear/Toggle registers, which act to affect another register (and this example is about an ARM-based  chip).

 

 

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Need to ask one more question on this topic;

 

In AVR are the 32 CPU registers mainly used for arithmetic work and the rest of IO registers (SFRs) essentially the same type? I.e transistors/flip-flops on SRAM? they are just located on different places on the bus?

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


 

avruser1523 wrote:
the rest of IO registers (SFRs) essentially the same type?

Again, the SFRs are different - they are not "memory"; they are control connections to hardware.

 

transistors/flip-flops on SRAM? 

At the end of the day, everything just boils down to transistors!

Flip-flops are built of transistors;

SRAM is built of flip-flops.

 

As the diagram posted by clawson in #15 shows, one of the big differences between CPU registers and SRAM is that the CPU registers are directly connected to the ALU - so don't have to be accessed via the data bus:

 

 

As the page linked by  N.Winterbottom   says,

  • The Register File of the AVR CPU contains 32 x 8 bit mostly Orthogonal (or identical) General Purpose Registers Ã¢â‚¬â€œ instructions can use any register; therefore, simplifying compiler design.

     
  • Load-store memory access. Before you can do anything to data, you must first load it from memory into one of the general-purpose registers. You then use register-register instructions to operate on the data. Finally, you store your answer back into memory.

 

and shows that 'REGS' and SRAM are physically separate areas:

 

 

EDIT

 

remove duplicate diagram

 

EDIT 2

 

also from the ATmega238P datasheet:

 

I think the Block Diagram is slightly simplified, in that it doesn't show the direct output from ALU to Register File ?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Thu. Jan 13, 2022 - 03:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
Again, the SFRs are different - they are not "memory"

 

Right, i'm just asking if the IO registers are the same type as the 32 GPRs (as neither GRPs nor the SFRs are just a part of memory but rather an actual register). I'm just asking if they are of the same type and only differ on their location on the bus and their usage of course.

 

Last Edited: Thu. Jan 13, 2022 - 03:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In AVR are the 32 CPU registers mainly used for arithmetic work and the rest of IO registers (SFRs) essentially the same type? I.e transistors/flip-flops on SRAM? they are just located on different places on the bus?

You need to study those datasheet diagrams. I assume you understand CPU architecture? Traditionally CPUs had an "accumulator", often just 1 or 2 registers. They were the only things that had direct access to the Arithmetic Logic Unit (ALU) at the core of the CPU. You might do things like "ADD A, B" which might feed A and B into the ALU, perform "ADD" and return the result to A (for example).

 

The AVR is pretty unusual in this sense (and accounts for part of its popularity) as it co-designed between two guys at Atmel and the IAR compiler company (who write C/C++ compilers). They analysed typical compiler code generation and determined that a really efficient processor for implementing C code would have THIRTY-TWO accumulators. So the AVR has R0..R31 (the real low end ones just R16..R31).

 

Sure they are "8 bit gates" at the end of the day but the point is that they are 8 bit gates that can be switched as inputs to the ALU which is why you can do all the LSL, ROR, ADD, EOR,AND, ... operations on them. They are not RAM and they are not peripheral control registers ("Special Function registers" = SFR) either.

 

To understand what an SFR is take a peripheral like a UART:

 

 

The bits you can read/write using CPU opcodes are those blocks I have circled in red. Some bit in some registers are read/write, some are write only and some are read only. So, yeah they are transistor gates but they are not "storage locations" like RAM. What's more (the point Andy made above) some of them aren't even just one register. You will see "UDR" in this twice. I have put the letters W and R next to the two instances. If you Write then it goes to the top set of latches. If you Read you get what is in the bottom latch. So "UDR" is an SFR that is accessible at some address for the AVR to read/write but it is TWO separate registers. You can only write (but not read) the top one and you can only read (but not write) the bottom one. This is why Andy said some folks are surprised when debugging when they have their code write to "UDR" but the debug display (or even code to immediately read it back) does NOT read the value just written - that is on a one way journey out of the chip (shifted up the TXD line). Some beginners see this happening and claim "the chip is faulty". 

 

But all this stuff IS explained in the datasheet (often via diagrams such as this so you must read/look and absorb every last detail if you want to understand how the AVR works).

 

 

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

avruser1523 wrote:
i'm just asking if the IO registers are the same type as the 32 GPRs

No: the GPRs (General-Purpose Registers?) are just straight storage - what you write to them is just stored, and will be read back.

 

The SFRs (IO registers?) are not (just) storage.

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avruser1523 wrote:
Right, i'm just asking if the IO registers are the same type as the 32 GPRs (as neither GRPs nor the SFRs are just a part of memory but rather an actual register). I'm just asking if they are of the same type and only differ on their location on the bus and their usage of course.
As Andy says at the end of the day everything in the chip is just transistors (well OK, some areas of silicon might be used to create resistors and capacitors too). But if you have done the full throry from combinatorial logic upwards you will know that by different wiring 1/2/4 transistors can make NOT, AND, OR, EOR, NAND, NOR gates. Then those gates (often NAND in fact) can themselves be combined to make things like Latches. Then latches can be combined to make things like half-adders then they can be combined to make full adders and so it goes on. So transistors and gates will be placed to perform whatever specific operation some area of the chip needs them to do. In RAM (and CPU general purpose registers) it may be as simple as groups (8 wide) of latches. But various kinds of transistor/gates/etc might be combined elsewhere to make the shift register or parity generator within a whole block that is the "UART" or whatever.

 

The common pattern at the very bottom of the heap is that they are all transistors. After that it is just a question of how the transistors are combined and then how gates made from transistors are combined and so on.

 

You might want to explore things like CPLDs and FPGAs and "structural languages" like Verilog and VHDL if the way the internals of a CPU are built from raw transistors and logic gates.

 

(or you could just read every post that "barnacle" (Neil Barnes) has ever posted to freaks - he's mad enough to build whole CPUs just by combining separate logic gates though I don't think he's gone the whole hog and done it at the individual transistor level - but there's even some engineers who've done that - YouTube can be illuminating!).

 

EDIT: this is fun! https://www.megaprocessor.com/

also: https://www.youtube.com/watch?v=...

and: https://www.youtube.com/watch?v=...

(the list continues - there are a lot of dedicated (odd?) people in this world!!)

Last Edited: Thu. Jan 13, 2022 - 03:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@clawson

@awneil

 

Thank you for the detailed explanation. 

 

So when using say `UDR`, I will load/store to the same address but behind the scene the hardware is actually working on two different set of "registers" based on operation being load or store?

 

Essentially GPRs are generic storage locations used by the ALU to do arithmetic/logic work. And SFRs are also "registers" but could behave differently and are used for specific tasks as explained above.

 

And neither of them are just "memory", they are only address mapped.

Last Edited: Thu. Jan 13, 2022 - 03:49 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avruser1523 wrote:
when using say `UDR`, I will load/store to the same address but behind the scene the hardware is actually working on two different set of  "registers"  hardware based on operation being load or store?

Yes:

  • writing accesses the Transmit hardware buffer;
  • reading accesses the Receive hardware buffer.

 

Essentially GPRs are generic storage locations used by the ALU to do arithmetic/logic work.

yes.

 

And SFRs are also "registers" but could behave differently and are used for specific tasks as explained above.

Yes - "special function" = "specific tasks"

 

 

And neither of them are just "memory", they are only address mapped.

The Register File is just memory - all it does is store data; nothing else - nothing "special" 

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
The Register File is just memory - all it does is store data

 

I mean technically all of them are just memory to store and/or retrieve data. What I meant was the registers are not literally a section of SRAM, they are their own thing.

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

 

typically, what an address decoder gives you is an 'enable', plus the read/write control:

 

The 'Enable' says, "this is us!";

The read/write can simply be used as a logic signal.

 

Using this, we could create a very simple (simplistic) memory-mapped Red/Green LED:

  • Accessing the assigned address enables the LED;
  • a Read could turn on the Red colour;
  • a Write could turn on the Green colour.

 

As far as the CPU is concerned, it's just accessing an address in its memory space - it neither knows nor cares that there isn't actually any memory here.

 

(in practice, this is not very useful, as the LED would only light for the very brief period while its assigned address is active; you would probably add some sort of latch to persist the state)

 

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Thu. Jan 13, 2022 - 04:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avruser1523 wrote:
technically all of them are just memory to store and/or retrieve data

No - SFRs do not necessarily store anything at all - that's the big difference.

 

see #27 for a (conceptual) example

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


awneil wrote:
you would probably add some sort of latch to persist the state)

Which is what this does!

 

Keys to wealth:

Invest for cash flow, not capital gains!

Wealth is attracted, not chased! 

Income is proportional to how many you serve!

If you want something you've never had...

...you must be willing to do something you've never done!

Lets go Brandon!

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

awneil wrote:
SFRs do not necessarily store anything at all

 

I'm having a hard time understanding this, if it has nothing to do with holding data then why is it called a register?

 

From the `UDR` example I can see that it's a box which either you write data to, or it holds data and you read from it, or both.

 

I don't really understand the picture in #27, which part of it is a register?

Last Edited: Thu. Jan 13, 2022 - 04:34 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avruser1523 wrote:
if it has nothing to do with holding data then why is it called a register?

can you think of a better name?

 

Again, as far as the CPU is concerned, it can't tell the difference; the behaviour it sees is exactly that of a register - so, in that respect, the name fits ...

 

From the `UDR` example I can see that it's a box

It's actually two distinct boxes - one is write-only, and the other is read-only

 

 

I don't really understand the picture in #27, which part of it is a register?

As above, it behaves as a register as far as the CPU can see.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
It's actually two distinct boxes

 

Correct, but in that example the boxes are either holding data, or you write data to them, or both, essentially there is data in them.

 

But you are saying there are other examples of SFRs like in #27 where the "register" has nothing to do with loading or storing data. It could just be unit with an address which passes a signal on different paths depending on it being a load or store operation?

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


avruser1523 wrote:
you are saying there are other examples of SFRs like in #27 where the "register" has nothing to do with loading or storing data. It could just be unit with an address which passes a signal on different paths depending on it being a load or store operation?

Yes.

 

I gave the example of the set/Clear/Toggle registers earlier - those registers don't actually store anything.

 

There are also SFRs where writing to a bit simply triggers an action; eg, ADSC in the  ADC Control and Status Register A:

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks again for everyones help on this.

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

Usually registers imply the storing of information:  A location, and bits of information.  

Where the bits of information are physically stored is hidden and could be anywhere--in an array with other registers, or out in the wild with its own location.

You have no idea of where electronically it is truly stored & that is the whole point of the logic circuitry abstraction--you don't need to know.

 

The bits may be read (by code), or simply used (by the processor), or both.  

Since there are opcodes and address decoding mechanisms in place (either for reading, writing, or both), it is convenient to use them to establish other "registers" that might not permanently store anything.

For example, there could be a 'register' established using these means that merely generates an immediate internal system reset pulse. 

You used register addressing modes & addresses to interact with this "register", is is that enough to declare it a register? Probably (register 752, system reset register)

Is that what you want to know?

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

But you are saying there are other examples of SFRs like in #27 where the "register" has nothing to do with loading or storing data. It could just be unit with an address which passes a signal on different paths depending on it being a load or store operation?

The point is that the only way the AVR core can "do stuff" inside the chip is effectively by "writing" to start things and "reading" to see results. But what you write/read are not necessarily (but often are) JK or SR latches/flip-flops. 

 

Taking this to a much higher level it's not totally dissimilar to Linux where everything ultimately is made to look like a disk file stream. Whatever weird and wonderful device you might attach to the computer it's kind of bound to appear as a "device" in /dev and you can open/read/write to that device to either send or receive stuff. There are "character" devices that tend to read/write bytes one at a time and there are block devices that do multi-byte read/writes but no matter what is (soundcard, printer, USB-UART cable, real hard drive, USB memory stick, etc) then this common "file stream" metaphor is applied to it. It kind of proves that everything can be implemented as a read/write target at the end of the day and that's true in an AVR micro too where flash, EEPROM, RAM, CPU registers, IO device control registers can all be given a read/write interface that can use the same CPU operations to read/write (LD/ST/STS/LDS) 

 

(expect of course EEPROM and flash are not like that in "old" AVRs but modern ones are starting to make it more "unified")

 

PS actually Linux /dev'ices don't just have open/close/read/write - for those really weird things you need to do to some devices that cannot be fitted into the "disk file metaphor" there is another operation called IO Control (ioctl) and that is used to mop up special operations you might do to a device that is not as simple as just reading/writing data/commands to the actual /dev/XXX 

Last Edited: Thu. Jan 13, 2022 - 05:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Taking this to a much higher level it's not totally dissimilar to Linux where everything ultimately is made to look like a disk file stream.

I like that analogy. yes

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
(or you could just read every post that "barnacle" (Neil Barnes) has ever posted to freaks - he's mad enough to build whole CPUs just by combining separate logic gates though I don't think he's gone the whole hog and done it at the individual transistor level - but there's even some engineers who've done that - YouTube can be illuminating!).

 

Oh, only every five or ten years, surely? laugh And unpublished here, but I have considered proof-of-concept for logic gates using transistors, fets, relays, neon bulbs, and, er, sheep and pysical gates.

 

Though I'm just finishing up a script to record for youtube in which I develop an 8080 from first principles, gate by gate... I can run an interpreter (tiny basic) on an emulated gate-level processor running under a java interpreter... it takes less than ten minutes to count from one to three... I may have to use fast forward for the screen shots :)

 

Neil

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

Yup, as I say, completely stark, staring bonkers! 

 

:-) 

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

Wibble wibble wibble.

 

It turns out to be easier to use sheep for logic if you emulate fets with proper five-bar gates... takes a significant amount of real estate hillside though. And a few collies to keep things moving.

 

Neil

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

I hope you were typing that with a pencil inserted into each nostril! 

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

While we are at it I'm going to address this comment from #8:

Also worth noting is that the AVR does not execute code from RAM

Using `objdump` to check a linked binary I see this:

00000000 <__vectors>:
   0: 0c 94 34 00 jmp 0x68 ; 0x68 <__ctors_end>

So address `0x0` is the start of the jump table for the interrupt vector in program memory. But this address is not the same as the `0x0` address in SRAM (which is also the r0 register), they are 2 different places?

 

If true, then is there a way for code to access instruction memory at runtime? say for hot code patching?

 

Last Edited: Thu. Jan 13, 2022 - 07:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

then is there a way for code to access instruction memory at runtim

Yes code can certainly modify the flash (program area)....you want some self-modfying code, perhaps?  That's where the real fun is. 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

avrcandies wrote:
you want some self-modfying code, perhaps?

Yes, something like this on x86:

void f() {
   void (*fpointer)() = &f;
}

`fpointer` points to the instructions in .txt area.

but I guess the address returned by `&f` is not interpreted as the function address in program memory, but some random address in SRAM?

Last Edited: Thu. Jan 13, 2022 - 07:52 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:
you want some self-modfying code, perhaps?

Yes, something like this on x86:

void f() {
   void (*fpointer)() = &f;
}

`fpointer` points to the instructions in .txt area.

but I guess in avr the address returned by `&f` is not interpreted as the function address in program memory, but some random address in SRAM?

Last Edited: Thu. Jan 13, 2022 - 07:53 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The datasheet shows the steps needed to write to flash...it is not  "simply write" , for instance, I believe there is a minimum block size that must be more than 1 location (such as 128 bytes, etc).

You can write to the flash to store calibration values, or write to flash where the code is living....and change it.  For example, think of a bootloader (program) writing to the flash (program) area.

That has nothing to do with sram, at least in the AVR.  When prog memory is external, such as EPROM---you might have ROM, RAM, etc all existing in the address space. 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

I think I will open a different issue for this question, going off topic.

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


avruser1523 wrote:
So address `0x0` is the start of the jump table for the interrupt vector in program memory. But this address is not the same as the `0x0` address in SRAM (which is also the r0 register), they are 2 different places?

Yes: it's a Harvard architecture - it has separate code & data address spaces.

 

ADDENDUM:

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Thu. Jan 13, 2022 - 10:29 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In "von Neumann" architecture processors like x86 there's basically one linear address space and everything maps into it. Back in the original 8088/8086 it could address 1MB. IBM left room for RAM up to the 640KB mark - first PC had just 64KB fitted then after that often 512KB, it was a bit of a luxury to have the full 640KB as this actually involved fitting one lot of 512KB and one lot of 128KB (RAM comes in "binary sizes"). IBM then put things like graphic adapter memory above 640KB.

 

But it was one address space. There only was one location 0.

 

But AVR are "Harvard" architecture. This means a lot of separate address spaces and each one starts from its own 0 location. So you have address spaces like flash, ram/IO, EEPROM, fuses, lock bytes, signature row. Flash location 0 is not RAM location 0 (is not EEPROM location 0 etc etc) . They each have their own addressing system and are accessed in different ways. Ram is accessed using LDS/STS/LD/ST and small sections of it with IN/OUT. Flash is read using LPM and sometimes written using SPM. EEPROM is accessed via EEAR/EEDR and controlled with EECR.

 

The CPU core can only do opcode fetches from the flash space (indexed by the PC register). It cannot fetch opcode from RAM. 

 

So this is not like x86 (or many ARM for that matter) in which everything can be accessed in one space with one set of read/write opcode and in the one space you can find RAM, ROM, IO/SFR registers, etc, etc

 

Again the AVR datasheet explain all this. 

 

Oh and if you are looking at GCC ELF files with a tool like objdump note that there's a bit of a "trick" applied because GCC/ELF are only designed for von Neumann (the main targets being x86 and ARM) with one address range. So, yes, the ELF has separate memory sections called things like ".text" (flash), ".data" (RAM), ". eeprom" (EEPROM). But they cannot all be placed at 0. So in fact artificial offsets are added. The one at true 0 is "text" , "data" is offset to 0x800000, "eeprom" is offset to 0x810000, "lock" /"fuse" /others are offset to further increments above here (0x820000, 0x830000, etc) though I can never remember the order (you can see it in the .x file - linker script) 

Last Edited: Fri. Jan 14, 2022 - 12:33 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In "von Neumann" architecture processors like x86 there's basically one linear address space and everything maps into it.

the x86 has (had?) a separate IO space accessible only by IN an OUT instructions.

 

It might help to consider the CPU as separate from the memory or "SFRs" being read.
To do a read of something, you put an address on a bus, twiddle some signals that tell the other thing to put data on a different bus, and then read the bus.

What the "something" actually DOES using the address and the signals is entirely arbitrary.  It could toggle an LED for each read cycle and put random data on the bus, for example, and older computer designs were a peripheral only used part of the provided address...

 

In a microcontroller, all the stuff is crammed into one chip, but the CPU is still logically separate from the memory and IO.

 

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

westfw wrote:
What the "something" actually DOES using the address and the signals is entirely arbitrary.  It could toggle an LED for each read cycle

Indeed - that was my example in #27

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@clawson great explanation and information.

 

I noticed trying to write data to program memory with something like this:

int (*f)() = &main;
*(char*)f = 5;

generates this:

  96:	25 e0       	ldi	r18, 0x05	; 5
  9a:	20 83       	st	Z, r18

So now trying to figure where is the Z register being populated or what is it mapped to and how `st` figures destination (Z) is program memory and not SRAM.

From googling it seems Z is specially used to access program memory.

 

Last Edited: Fri. Jan 14, 2022 - 03:51 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avruser1523 wrote:
From googling it seems Z is specially used to access program memory.

For the definitive answer, look in the AVR Instruction Set Manual:

 

http://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf

 

 

It's used for Indirect addressing in general - not just for program memory:

 

EDIT

 

avruser1523 wrote:
where is the Z register being populated

 

look earlier in the code ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Fri. Jan 14, 2022 - 09:14 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avruser1523 wrote:
I think I will open a different issue for this question, going off topic.

I think it needs to be split at #42 ?

 

A Moderator can do that for you ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avruser1523 wrote:
generates this:
Your code is completely non-sensical.

 

main() is simply the address of a location in the flash based code space. You cannot write to that simply by writing through a pointer to it??. Sure some code will be generated because all that will happen is that the flash address (not a RAM address, it's in a different memory space!!) of "main" will be determined then a write to that location will be generated (you didn't actually show the bit where Z was loaded with the flash address of main() ). In fact if I repeat the exercise to show more code first you will notice::

D:\junkavr\testGCC\testGCC\main.c(10,1): warning: accessing data memory with program memory address

The compiler has cleverly spotted what you are up to and does not like it either! But it does generate some code:

0000020e <main>:


int main()
{
    int (*f)() = &main;
    *(char*)f = 5;
 20e:	85 e0       	ldi	r24, 0x05	; 5
 210:	80 93 0e 02 	sts	0x020E, r24	; 0x80020e <__TEXT_REGION_LENGTH__+0x7f720e>

Perhaps because circumstances are different (I haven't seen the rest of your code) the compiler has chosen not to go indirect via Z in my case but to make a direct write. So you can see it's going to STS to some location 0x20E in the RAM space. Sure the label in the disassembly shows that "main" is located at 0x20E in flash but flash 0x20E != RAM 0x20E and that is the important point. You cannot just pick the address of something in one address space and hen use it for any kind of access in another address space. It's tantamount to just picking random numbers! I mean who knows what might actually have been positioned at 0x20E in the RAM where this write is being made?? I'm probably corrupting something with this pernicious code!

 

As it happens the AVR does allow flash to be written (it's how bootloaders work) but it's not done with a an ST or STS. The opcode that does it is SPM (Self Program (flash) Memory). On Mega AVRs the SPM opcode is limited in that it cannot appear in the "normal" flash space but there is a region (towards the top of the flash space) called the "BootLoader Section" (BLS) and SPM can only be fetched and executed succcessfully in the BLS. But it's not as simple as:

ldi ZL, 0x0E
ldi ZH, 0x02
spm

In fact if you read the opcode manual:

 

http://ww1.microchip.com/downloa...

 

You will see that the "minimal example" to operate one SPM is:

 

 ;This example shows SPM write of one page for devices with page write
 ;- the routine writes one page of data from RAM to Flash
 ; the first data location in RAM is pointed to by the Y-pointer
 ; the first data location in Flash is pointed to by the Z-pointer
 ;- error handling is not included
 ;- the routine must be placed inside the boot space
 ; (at least the do_spm sub routine)
 ;- registers used: r0, r1, temp1, temp2, looplo, loophi, spmcrval
 ; (temp1, temp2, looplo, loophi, spmcrval must be defined by the user)
 ; storing and restoring of registers is not included in the routine
 ; register usage can be optimized at the expense of code size
.equ PAGESIZEB = PAGESIZE*2 ;PAGESIZEB is page size in BYTES, not words
.org SMALLBOOTSTART
write_page:
 ;page erase
 ldi spmcrval, (1<<PGERS) + (1<<SPMEN)
 call do_spm
 ;transfer data from RAM to Flash page buffer
 ldi looplo, low(PAGESIZEB) ;init loop variable
 ldi loophi, high(PAGESIZEB) ;not required for PAGESIZEB<=256
wrloop: ld r0, Y+
 ld r1, Y+
 ldi spmcrval, (1<<SPMEN)
 call do_spm
 adiw ZH:ZL, 2
 sbiw loophi:looplo, 2 ;use subi for PAGESIZEB<=256
 brne wrloop
 ;execute page write
 subi ZL, low(PAGESIZEB);restore pointer
 sbci ZH, high(PAGESIZEB) ;not required for PAGESIZEB<=256
 ldi spmcrval, (1<<PGWRT) + (1<<SPMEN)
 call do_spm
 ;read back and check, optional
 ldi looplo, low(PAGESIZEB) ;init loop variable
 ldi loophi, high(PAGESIZEB) ;not required for PAGESIZEB<=256
 subi YL, low(PAGESIZEB) ;restore pointer
 sbci YH, high(PAGESIZEB)
rdloop: lpm r0, Z+
 ld r1, Y+
 cpse r0, r1
 jmp error
 sbiw loophi:looplo, 2 ;use subi for PAGESIZEB<=256
 brne rdloop
 ;return
 ret
do_spm:
 ;input: spmcrval determines SPM action
 ;disable interrupts if enabled, store status
 in temp2, SREG
 cli
 ;check for previous SPM complete
wait: in temp1, SPMCR
 sbrc temp1, SPMEN
 rjmp wait
 ;SPM timed sequence
 out SPMCR, spmcrval
 spm
 ;restore SREG (to enable interrupts if originally enabled)
 out SREG, temp2
 ret

And that is the ONLY way to write to flash memory space.

 

As you will read elsewhere if you dig into the details of it (if using C/C++ in GCC then this is perhaps a good place to start: https://www.nongnu.org/avr-libc/... ) you cannot simply pick some byte location in flash and write 0x05 to it. Flash is broken up into "SPM pages" which are some binary multiple in size (often 32, 64 or 128 bytes long). To write a single byte location you would need to read the entire 32/64/128 in a page to the "SPM buffer" and, while doing so, locate where the 0x05 is to go and replace the current contents with that. You would then issue (using SPM and SPMCR) an "erase page" command which wipes all 32/64/128 back to 0xFF (a high voltage charge pump is applied to all the transistors in the NAND locations of the flash page to return any 0 bits to 1 so all the bytes read 0xFF). Then the contents of your SPM buffer will be written (by the issue of another SPM and the correct setting of SPMCR) back to the now erased page - so to change one byte you actually change all 32/64/128 in the adjacent bytes of the page it sits in. If you look at the code above you can see that is pretty much what it is doing.

 

In the AVR-Libc example pretty much the same thing is moved from the Asm level to the C level (which may make it a little easier to see the logic of what is going on):

void boot_program_page (uint32_t page, uint8_t *buf)
{
    uint16_t i;
    uint8_t sreg;
    // Disable interrupts.
    sreg = SREG;
    cli();
    eeprom_busy_wait ();
    boot_page_erase (page);
    boot_spm_busy_wait ();      // Wait until the memory is erased.
    for (i=0; i<SPM_PAGESIZE; i+=2)
    {
        // Set up little-endian word.
        uint16_t w = *buf++;
        w += (*buf++) << 8;
    
        boot_page_fill (page + i, w);
    }
    boot_page_write (page);     // Store buffer in flash page.
    boot_spm_busy_wait();       // Wait until the memory is written.
    // Reenable RWW-section again. We need this if we want to jump back
    // to the application after bootloading.
    boot_rww_enable ();
    // Re-enable interrupts (if they were ever enabled).
    SREG = sreg;
}

From your previous posts you seem to be an intelligent engineer so I'm not sure how you are having such a problem grasping this concept of multiple (and quite separate!) memory spaces in a Harvard architecture CPU. I wonder if you are possibly "over thinking" this a bit?

 

By the way one consequence of all this is that unlike a von Neumann machine it is difficult (though I ugess by SPM in the BLS just possible) for an AVR to run self modifying code. The way self modifying code is usually done is to arrange for the opcodes being fetched by the CPU to be located in RAM then some of those opcodes can make modifications to upcoming code that is just ahead of the code that does the modifying. It's a very dangerous thing to do but it's quite possible (I'm old enough to have "hacked" the protection systems on games like "Knightlore" on the Sinclair Spectrum and CPC464 to be able to "get in" and change the behaviour (infinite lives, map editor) on a machine like a Z80 (with games loaded into RAM from tape) such games had a tape loader that did protection by self-modifying code - thankfully you just couldn't do something like this on an AVR because the CPU will only opcode fetch from flash, not RAM and it is very very difficult to do "on the fly" changes to that flash. 

 

Also BTW you may have spotted it above but SRAM is made up of fairly complex flip-flops that hold the state of each bit and can be easily changed. In flash the technology is quite different and far simpler - it is a technology called NAND flash and the stored bits are basically a stored charge on the isolated gate of a transistor. Using the high voltage method the charges on each bit location transistor can be restored to 1. Then some bits can be written to 0. There is also a sensing mechanism for reading that can sense the state of the stored charge. But this is NOTHING like SRAM !

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

awneil wrote:
A Moderator can do that for you ...
I wouldn't bank on that - when I've tried splitting threads before I have sometimes lost part/all of the thread so personally I don't attempt splits.

 

Anyway to me the whole thread seems to be about the same thing - the understanding of Harvard versus von Neumann.

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

 

So now trying to figure where is the Z register being populated or what is it mapped to and how `st` figures destination (Z) is program memory and not SRAM.

You do know that the Z register is simply cute way of referring to registers r31:r30, right? Of course r31 to r00 live in common sram (or at least we are told this)...note otherwise we really have no way of knowing that it is in a common sram area, other than from documents...the opcodes, instructions, etc are there partly to make such matters invisible to us.  You don't really care whether r14 is in an sram array of storage or is in some separated flip flops tucked away in the corner of the AVR, apart from r09 & r21.

So Z is not in program memory, but in sram...prog memory (flash, we are told) is accessed through LPM & SPM instructions.

 

It might be beneficial to get thoroughly familiar with the AVR addressing modes & instruction set.  That in itself would probably answer the bulk of your uncertainties.

 

From googling it seems Z is specially used to access program memory.

That is not a good way to say it.  Z (r31:r30), Y (R29:r28), X (r27:r26), are simply different register pairs.  Z can be used for anything that X & Y can.  To access program memory you use LPM & SPM commands. Each of these commands must include Z as a parameter source (X & Y not allowed).  Not allowing X & Y, is a rare nonorthogonal AVR design tradeoff.

By studying the instruction set, you should (or will) know that rather quickly. 

 

The following needs to be looking very familiar, or you will continue to scratch your head in an infinite loop: 

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Fri. Jan 14, 2022 - 11:27 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:
You don't really care whether r14 is in an sram array of storage or is in some separated flip flops tucked away in the corner of the AVR

+1

 

But it is useful (important?) to understand that SFRs really are different...

 

(but I may have mentioned that before...?)
 

ADDENDUM

 

OP started with references to x86 for comparison.

A big difference between x86 and AVR (and other microcontrollers) is that the x86 has no internal RAM - so its CPU registers really are different from the rest of its SRAM

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Fri. Jan 14, 2022 - 11:34 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:
From googling it seems Z is specially used to access program memory.

Just to point out that Z can be used for more than one thing! Sure, if you are doing SPM stuff then (as well as SPMCR) the Z pair (ZH:ZL = R31:R30) are involved in that but in "normal running" Z (and Y and X) are used often and specially if you start doing anything that involves "offsets from a base address" - like array elements or struct{} members or, indeed, anything that is "indexed" (X, Y, Z are, indeed "index registers"). While this may not be what the compiler actually chooses to do one might envisage code such as:

uint8_t nums[10];

nums[3] = 17;
nums[5] = 26;
nums[8] = 34;

One way it could do this would be (say nums[] is based at 0x1C7):

ldi r24, 17
sts 0x1CA, r24
ldi r24, 26
sts 0x1CC, r24
ldi r24, 34
sts 0x1CF, r24

but STS is a large and slow opcode so it would be more efficient to use:

ldi r30, 0xC7
ldi r31, 0x01
ldi r24, 17
st Z+3, R24
ldi r24, 26
st Z+5, r24
ldi r24, 34
st Z+8, r24

Sure there is a bit more "overhead" in this at the start as you have to load the 0x1C7 base into Z but then the ST ops are more efficient than STS. The code you saw for writing 0x05 to the "main" address (but in RAM not flash) was using this "indirect/indexed through Z technique"

 

For your info when a function in GCC uses local variables on the stack then the way the compiler actually handles that is that it moves the stack down to make room for the locals and then it arranges for Y to point at the next location below this so all the stack frame variables are at Y+offset starting from Y+1 upwards. It's the same kind of technique as the Z thing but this means Y is almost always tied up for use as the stack frame pointer so it only leaves Z and X for the compiler to use for other things.

 

As an example in this fairly contrived program:

#include <avr/io.h>

void func() {
    volatile int arr[5];
    volatile long l;
    volatile char c;

    c = 'X';
    l = 0xBABEFACE;
    arr[3] = 12345;
}

int main()
{
    int (*f)() = &main;
    *(char*)f = 5;
    while(1) {
        func();
    }
}

The code of func() is:

0000020e <func>:
#include <avr/io.h>


void func() {
 20e:	cf 93       	push	r28
 210:	df 93       	push	r29
 212:	cd b7       	in	r28, 0x3d	; 61
 214:	de b7       	in	r29, 0x3e	; 62
 216:	2f 97       	sbiw	r28, 0x0f	; 15
 218:	cd bf       	out	0x3d, r28	; 61
 21a:	de bf       	out	0x3e, r29	; 62
    volatile int arr[5];
    volatile long l;
    volatile char c;

    c = 'X';
 21c:	88 e5       	ldi	r24, 0x58	; 88
 21e:	8f 87       	std	Y+15, r24	; 0x0f
    l = 0xBABEFACE;
 220:	8e ec       	ldi	r24, 0xCE	; 206
 222:	9a ef       	ldi	r25, 0xFA	; 250
 224:	ae eb       	ldi	r26, 0xBE	; 190
 226:	ba eb       	ldi	r27, 0xBA	; 186
 228:	8b 87       	std	Y+11, r24	; 0x0b
 22a:	9c 87       	std	Y+12, r25	; 0x0c
 22c:	ad 87       	std	Y+13, r26	; 0x0d
 22e:	be 87       	std	Y+14, r27	; 0x0e
    arr[3] = 12345;
 230:	89 e3       	ldi	r24, 0x39	; 57
 232:	90 e3       	ldi	r25, 0x30	; 48
 234:	8f 83       	std	Y+7, r24	; 0x07
 236:	98 87       	std	Y+8, r25	; 0x08
}
 238:	2f 96       	adiw	r28, 0x0f	; 15
 23a:	cd bf       	out	0x3d, r28	; 61
 23c:	de bf       	out	0x3e, r29	; 62
 23e:	df 91       	pop	r29
 240:	cf 91       	pop	r28
 242:	08 95       	ret

20e/210 starts by pusing the two halves of Y (R29:R28) to the stack to preserve them. 212/214 then reads in in the stackpointer SPL/SPH from the 0x3D/0x3E IO locations where it is made visible. The SBIW subtracts 0xF (15) from it before storing it back. That is 10 bytes for arr[], 4 bytes for l and 1 byte for c. So space has been opened up to hold the variables. Note that it very deliberately did the reading and sbtracting using R29/R28 (Y) so by the end Y is holding the address of the next empty stack location. arr[] will be the 10 bytes from Y+1 to Y+10, the long variable will be in the four bytes from Y+11 to Y+14 and the char variable, c, will be at Y+15. You can then see exactly that when, for example, the value of c is written as 'X' by ST Y+15 at 0x21E. The value for l is written by the ST Y+11 .. ST Y+14 at 0x228 .. 0x22E and the 12345 is written to the middle element of the array by the stores at 0x234/0x236.

 

Finally as the function unwinds (and remember that Y is still holding "base of stack frame") 0x238 adds the 0x0F that was "resereved" back to Y so it how holds the SP position as it was after R28/R29 had been pushed on entry. Thta is written OUT to the SPH/SPL location to change the stack pointer then the last couple of POPs recover whatever Y was on entry to this function and it can finally RET.

 

So X+offset (rarely), Y+offset (always for stack frame variables) and Z+offset (for general read/write of indexed data) are seen a lot in the code generated by GCC.

 

(note that other compilers do this in different ways, in compilers such as Codevision and Imagecraft they don't try to "share space" on the single hardware stack but only use the hardware stack for CALL/RET and PUSH/POP. Those compiers set up a separate "soft stack" for doing the stack frame variables (but this does require the compilers to reserve a special area for that "data stack").

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

@clawson

 

I actually first did suspect my C code was changing something in SRAM and not program memory, but since my compiler did't warn about anything (maybe I didn't use a proper flag) I thought it's smart enough to detect this and use a special instruction/offset to do what I want, turns out it doesn't. Of course this is not doable in x86 and ends up with a segfault as .text area is read-only, but I just wanted to see what the compiler generates.

 

Harvard is.... interesting. I should probably change the title of the thread to make it more relatable.

Last Edited: Fri. Jan 14, 2022 - 01:50 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avruser1523 wrote:
but since my compiler did't warn about anything
Where did you get your compiler? I forget when it was (maybe 4.6 ?) but the error reporting was greatly improved at one issue so the 5.4.0 that comes with Studio 7 definitely has this more thorough error reporting. I wonder if you are using something "really old" like "WinAVR" ? (that is 4.3.0 - it dates from December 2009)

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

clawson wrote:

Where did you get your compiler?

I'm on ubuntu, so `apt install gcc-avr avr-libc` and it's `5.4.0`, but no warnings.

Last Edited: Fri. Jan 14, 2022 - 02:04 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@awneil

awneil wrote:
x86 has no internal RAM - so its CPU registers really are different from the rest of its SRAM

which other SRAMs are you referring to? does x86 use SRAM beside its registers and cache?

Last Edited: Fri. Jan 14, 2022 - 02:53 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well that is odd. Just for the record this is a typical invocation of the 5.4.0 in Studio 7...

"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe"  -x c -funsigned-char -funsigned-bitfields -DDEBUG  -I"C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\XMEGAA_DFP\1.2.141\include"  -Og -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -mrelax -g2 -Wall -mmcu=atxmega32a4u -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\XMEGAA_DFP\1.2.141\gcc\dev\atxmega32a4u" -c -std=gnu99 -save-temps -MD -MP -MF "main.d" -MT"main.d" -MT"main.o"   -o "main.o" ".././main.c" 

I guess it must be the -Wall in there that is causing all warning to be shown?...

 

... nope, just turned off -Wall and I still get the warning (it did turn off the ones I was getting about variables being set but not used though).

 

I may have a go at this in one of my Ubuntu VMs but in theory, given the same command line switches, if it's the same 5.4.0 it should behave the same whether Windows or Linux.

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

clawson wrote:
it should behave the same whether Windows or Linux.

It's actually the optimization flag `-Og` that shows it.

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

Go back to the AVR1200 etc. It had NO RAM only the 32 registers.(and a HW stack to store return addresses, then was not memory mapped at all)

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

avrcandies wrote:
You don't really care whether r14 is in an sram array of storage or is in some separated flip flops tucked away in the corner of the AVR

Thing is i'm just trying to picture a bit of the details.

 

From the datasheet and previous discussions I figured registers (GPRs and SFRs) are separate from SRAM, as you say they are separated flip flops tucked away somewhere,  but are part of the address space of SRAM.

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


 

Well it is odd. I got gcc-avr and avr-libc in a VM and set up a short test where "int n" is a deliberately unrefd variable and also with the code to make a write to a code address and I find...

 

 

Like you found it does NOT object to the attempted use of a flash symbol as the target of a write. Not sure why this 5.4.0 is behaving different to a Windows based one???

 

EDIT: OK so doing exactly the same thing in Windows actually produces the SAME result...

 

 

So there's something else on the Studio 7 invocation that causes the warning to be thrown - let me experiment....

Last Edited: Fri. Jan 14, 2022 - 02:38 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
So there's something else on the Studio 7 invocation that causes the warning to be thrown - let me experiment....
avruser1523 wrote:
It's actually the optimization flag `-Og` that shows it.
Oh yeah, I get that now, how very curious indeed. I guess when I didn't specify -O it was an implied -O0 by default. But it's still generating AVR code so I wonder why the backend would not have spotted this?

 

I guess I'll just add this to my long list of reason why -O0 should never be used !!

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

clawson wrote:
let me experiment....

It's the optimization flag `-Og` that shows it.

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

avruser1523 wrote:

@awneil

awneil wrote:
x86 has no internal RAM - so its CPU registers really are different from the rest of its SRAM

which other SRAMs are you referring to? does x86 use SRAM beside its registers and cache?

Sorry for repeating the above comment, just wanted to make sure it doesn't get lost.

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

The IBM PC had DRAM not SRAM. Sure the registers in the CPU were probably static (is x86 CMOS?) but could you actually stop it clocking anyway? (can't remember anything like "SLEEP"?) 

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


awneil wrote:
x86 has no internal RAM - so its CPU registers really are different from the rest of its SRAM

avruser1523 wrote:
which other SRAMs are you referring to? does x86 use SRAM beside its registers and cache?

The x86 neither knows nor cares what type(s) of memory is/are connected to its external buses - SRAM, DRAM, Flash, EPROM, memory-mapped IO, ...

 

Perhaps I should have said, "... so its CPU registers really are different from any other SRAM in the system"

 

clawson wrote:
is x86 CMOS?

I think the original 8086 was NMOS ?

 

There were later 80C86 versions - also 80C186

 

I think it was certain 386 models that first introduced SRAM as cache?

 

EDIT

 

Fix quote.

 

From 'Intel 8086 Family User's Manual October', 1979:

 

https://edge.edx.org/c4x/BITSPilani/EEE231/asset/8086_family_Users_Manual_1_.pdf

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Fri. Jan 14, 2022 - 06:49 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have an idea that the original 8088/6 did not have static registers; the clock could not be stopped. Certainly the 8080 wasn't a static device and got quite upset if the clock went away. Ken Shirriff's blog is an excellent resource for gate-level analysis of processors and other parts (often by analysis of the actual silicon).

 

Neil

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

Thing is i'm just trying to picture a bit of the details.

The best source for programming details is to simply assimilate the datasheet--it gives all the details that are exposed to the public, in a form they want use to visualize.   

They show some registers on a diagram as next to each other, or in an array, then that is what we believe & go with.

What happens inside the chip (electronic details) could be very different, shown or unshown. The diagrams may generalize many aspects just to make it easier to understand, by filtering out details unrelated to programming needs. 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

avrcandies wrote:
The diagrams may generalize many aspects just to make it easier to understand, by filtering out details unrelated to programming needs

Absolutely.

 

eg,

at the end of #19, I wrote:
I think the Block Diagram is slightly simplified, in that it doesn't show the direct output from ALU to Register File ?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

barnacle wrote:

I have an idea that the original 8088/6 did not have static registers; the clock could not be stopped.

 

Correct. They were made in an HMOS process and the datasheet specifies both a minimum and maximum clock period.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

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

 

The 80C86/8 came later - as a fully-static design.

 

https://datasheetspdf.com/pdf-file/843377/Harris/80C88/1

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Sat. Jan 15, 2022 - 01:59 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So did 80C88 add instructions to sleep the CPU? 

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

I don't think so, but the hardware could. For a desktop processor it's more about how fast and how cheap than how slow and power-sipping.

 

Neil

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

clawson wrote:

So did 80C88 add instructions to sleep the CPU? 

 

No. Remember, the '86 family is a microprocessor not a microcontroller so the concept of 'sleep' doesn't really fit. With all the peripherals external to the chip you'd somehow have to put those to sleep as well. Even the clock for the CPU usually came from an external chip, something like an 8284, with that clock signal being fed to all the peripheral chips.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."