banner



How Much Can One Register Hold In Atmega328p

Path: Home => AVR-overview => Assembler intro => SRAM use    (Diese Seite in Deutsch: Flag DE) Logo

Introduction to AVR assembler programming for beginners

Using SRAM in AVR assembler language

All AT90S-AVR-type MCUs have static RAM (SRAM) on lath. Just very uncomplicated assembler programs tin can avoid using this retentivity space by putting all info into registers. If you run out of registers you should be able to program the SRAM to use more infinite.

What is SRAM?

SRAM are memories that are not directly accessable to the cardinal processing unit of measurement (Arithmetic and Logical Unit ALU, sometimes called accumulator) like the registers are. If yous access these retentiveness locations you usually use a annals every bit acting storage. In the following example a value in SRAM will be copied to the register R2 (1st command), a adding with the value in R3 is made and the effect is written to R3 (control 2). After that this value is written back to the SRAM location (command 3, not shown hither).

SRAM ways

So it is clear that operations with values stored in the SRAM are slower to perform than those using registers solitary. On the other hand: the smallest AVR type has 128 bytes of SRAM available, much more than the 32 registers can hold.

The types from AT90S8515 upwards offer the additional opportunity to connect additional external RAM, expanding the internal 512 bytes. From the assembler point- of-view, external SRAM is accessed similar internal SRAM. No extra commands must be used for that external SRAM.

To the acme of that folio

For what purposes tin can I utilize SRAM?

Besides simple storage of values SRAM offers boosted opportunities for its use. Not only access with fixed addresses is possible, but also the use of pointers, and so that floating admission to subsequent locations can be programmed. This way you tin build up ring buffers for interim storage of values or calculated tables. This is not possible with registers, considering they are too few and demand fixed access.

Fifty-fifty more relative is the admission using an offset to a stock-still starting address in one of the pointer registers. In that instance a fixed accost is stored in a pointer annals, a abiding value is added to this address and read/write access is made to that address with an offset. With that kind of admission tables are meliorate used.

The most relevant use for SRAM is the so-chosen stack. You can push values to that stack, be it the content of a annals, a render accost prior to calling a subroutine, or the return address prior to an hardware-triggered interrupt.

To the tiptop of that page

How to employ SRAM?

To copy a value to a retention location in SRAM yous accept to define the accost. The SRAM addresses you tin can utilize achieve from 0x0060 (hex annotation) to the stop of the physical SRAM on the scrap (in the AT90S8515 the highest accessable internal SRAM location is 0x025F). With the control

    STS 0x0060, R1

the content of register R1 is copied to the first SRAM location. With

    LDS R1, 0x0060

the SRAM content at address 0x0060 is copied to the annals. This is the direct admission with an accost that has to be defined by the developer.

Symbolic names can be used to avoid handling stock-still addresses, that crave a lot of work, if yous later desire to change the construction of your data in the SRAM. These names are easier to handle than hex numbers, so requite that address a proper noun like:

.EQU MyPreferredStorageCell = 0x0060
STS MyPreferredStorageCell, R1

Aye, it isn't shorter, but easier to call up. Employ whatever name that you find to be convenient.

Another kind of access to SRAM is the use of pointers. Y'all demand two registers for that purpose, that hold the 16-chip address of the location. As we learned in the Pointer-Annals-Segmentation pointer registers are the pairs X (XH:Xl, R27:R26), Y (YH:YL, R29:R28) and Z (ZH:ZL, R31:R30). They allow access to the location they point to straight (e.g. with ST Ten, R1), afterwards prior decrementing the address by ane (east.chiliad. ST -X, R1) or with subsequent incrementation of the address (east.g. ST 10+, R1). A consummate access to three cells in a row looks like this:

.EQU MyPreferredStorageCell = 0x0060
.DEF MyPreferredRegister = R1
.DEF AnotherRegister = R2
.DEF AndAnotherRegister = R3
LDI XH, Loftier(MyPreferredStorageCell)
LDI XL, LOW(MyPreferredStorageCell)
LD MyPreferredRegister, 10+
LD AnotherRegister, X+
LD AndAnotherRegister, X

Easy to operate, those pointers. And as easy as in other languages than assembler, that merits to exist easier to acquire.

The third structure is a little bit more exotic and merely experienced programmers utilise this. Allow's assume we very often in our program need to access iii SRAM locations. Let'southward futher assume that we have a spare pointer annals pair, and then we can afford to employ it exclusively for our purpose. If we would use the ST/LD instructions we always have to change the pointer if we access some other location. Not very convenient.
To avoid this, and to confuse the beginner, the admission with offset was invented. During that access the register value isn't changed. The address is calculated past temporarly adding the fixed offset. In the above example the access to location 0x0062 would wait like this. First, the arrow register is prepare to our central location 0x0060:

.EQU MyPreferredStorageCell = 0x0060
.DEF MyPreferredRegister = R1
LDI YH, HIGH(MyPreferredStorageCell)
LDI YL, LOW(MyPreferredStorageCell)

Somewhere later on in the programme I'd like to access prison cell 0x0062:

    STD Y+2, MyPreferredRegister

Notation that 2 is not actually added to Y, just temporarly. To misfile you farther, this tin only exist done with the Y- and Z-register-pair, not with the X-pointer!

The corresponding didactics for reading from SRAM with an offset

    LDD MyPreferredRegister, Y+two

is also possible.

That's it with the SRAM, but wait: the most relevant employ equally stack is notwithstanding to be learned.

To the peak of that page

Employ of SRAM every bit stack

The nearly mutual employ of SRAM is its apply as stack. The stack is a belfry of wooden blocks. Each boosted block goes onto the top of the belfry, each call up of a value removes the upmost block from the belfry. This structure is called Last-In-First-Out (LIFO) or easier: the last to proceed top will be the first coming downwardly.

Defining SRAM as stack

To use SRAM as stack requires the setting of the stack pointer first. The stack pointer is a sixteen-bit-arrow, accessable like a port. The double annals is named SPH:SPL. SPH holds the most pregnant accost byte, SPL the least significant. This is only true, if the AVR type has more than 256 byte SRAM. If not, SPH is undefined and must not and cannot exist used. We presume we take more than 256 bytes in the following examples.

To construct the stack the stack pointer is loaded with the highest available SRAM address. (In our instance the tower grows downwards, towards lower addresses!).

.DEF MyPreferredRegister = R16
LDI MyPreferredRegister, High(RAMEND)
; Upper byte
    OUT SPH,MyPreferredRegister ; to stack pointer
    LDI MyPreferredRegister, Depression(RAMEND) ; Lower byte
    OUT SPL,MyPreferredRegister ; to stack pointer

The value RAMEND is, of course, specific for the processor type. It is divers in the INCLUDE file for the processor blazon. The file 8515def.inc has the line:

.equ RAMEND =$25F ; Last On-Fleck SRAM Location

The file 8515def.inc is included with the assembler directive

.INCLUDE "C:\somewhere\8515def.inc"

at the starting time of our assembler source lawmaking.

So we divers the stack at present, and nosotros don't accept to care about the stack arrow any more than, because manipulations of that arrow are automated.

Use of the stack

Using the stack is easy. The content of registers are pushed onto the stack like this:

    Button MyPreferredRegister ; Throw that value

Where that value goes to is totally uninteresting. That the stack pointer was decremented after that push, we don't have to care. If we demand the content again, we but add the following teaching:

    Pop MyPreferredRegister ; Read back the value

With Pop we just get the value that was terminal pushed on top of the stack. Pushing and popping registers makes sense, if

  • the content is again needed some lines of lawmaking subsequently,
  • all registers are in use, and if
  • no other opportunity exists to store that value somewhere else.
If these conditions are non given, the use of the stack for saving registers is useless and just wastes processor fourth dimension.

More sense makes the use of the stack in subroutines, where you take to return to the program location that called the routine. In that example the calling program code pushes the return address (the current program counter value) onto the stack and jumps to the subroutine. After its execution the subroutine pops the render address from the stack and loads it back into the program counter. Program execution is continued exactly i instruction behind the phone call education:

    RCALL Somewhat ; Leap to the characterization somewhat
[...] here we keep with the program.

Here the jump to the label somewhat somewhere in the program code,

Somewhat: ; this is the bound address
[...] Here we do something
[...] and we are finished and desire to jump dorsum to the calling location:
    RET

During execution of the RCALL pedagogy the already incremented programme counter, a 16-bit-address, is pushed onto the stack, using two pushes. Past reaching the RET education the content of the previous program counter is reloaded with 2 pops and execution continues there.
You don't demand to intendance about the accost of the stack, where the counter is loaded to. This accost is automatically generated. Fifty-fifty if yous call a subroutine within that subroutine the stack function is fine. This just packs 2 return addresses on top of the stack, the nested subroutine removes the get-go i, the calling subroutine the remaining one. Every bit long as in that location is enough SRAM everything is fine.

Servicing hardware interrupts isn't possible without the stack. Interrupts terminate the normal exection of the plan, wherever the program currently is. After execution of a specific service routine as a reaction to that interrupt program execution must return to the previous location, earlier the interrupt occurred. This would not be possible if the stack is not able to store the render accost.

Common bugs with the stack operation

For the beginner there are a lot of possible bugs, if you first learn to use stack.
Very clever is the use of the stack without first setting the stack pointer. Because this arrow is set to zero at program start the arrow points to register R0. Pushing a byte results in a write to that register, overwriting its previous content. An boosted push to the stack writes to 0xFFFF, an undefined position (if yous don't have external SRAM there). A RCALL and RET will return to a strange address in plan retentivity. Be certain: there is no warning, like a window popping up saying something like Illegal Access to Mem location xxxx.
Another opportunity to construct bugs is to forget to pop a previously pushed value, or popping a value without pushing one first.
In a very few cases the stack overflows to below the starting time SRAM location. This happens in case of a never-ending recursive call. Afterward reaching the lowest SRAM location the side by side pushes write to the ports (0x005F to 0x0020), and then to the registers (0x001F to 0x0000). Funny and unpredictable things happen with the bit hardware, if this goes on. Avoid this issues, it tin can destroy your hardware!

To the meridian of that page

©2002 by http://world wide web.avr-asm-tutorial.net

How Much Can One Register Hold In Atmega328p,

Source: http://www.avr-asm-tutorial.net/avr_en/beginner/SRAM.html

Posted by: dickenaticeyound.blogspot.com

0 Response to "How Much Can One Register Hold In Atmega328p"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel