filling ram

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

I want to fill the entire RAM with 0x55.
my Ram address is (0x100 to 0x4ff). i am using stk500& 502 board. i am using assembly language program. I am using amega 169

ram size = 0x400 -0x100 = 0x3ff
code for this:

	LDI R27, 0X01 //ram low address high byte
	ldI R26,0x00 //ram low address low byte
	ldi R25,0X03 //ram size high byte
	ldi R24,0Xff //ram size low byte
	LDI R16,0x55  //to be written value
	st x,r16 // fill 0x100 with 0x55
loop2:  sbiw r25:r24,1 
	brne loop1
	nop

loop1: ld r2,x+
	st x,r16
	jmp loop2

My x pointer pointing to 0x100. ram size is in r25, r24. I want to decrement the ram size(0x3ff to 0)every time . When the count reaches 0, my pointer x will be in 0x4ff.

my doubt:

loop2:  sbiw r25:r24,1

is giving the following error

../RamInit.S: Assembler messages:
../RamInit.S:18: Error: register r24, r26, r28 or r30 required
../RamInit.S:18: Error: `,' required
../RamInit.S:18: Error: garbage at end of line
make: *** [RamInit.o] Error 1
Build failed with 1 errors and 0 warnings...

Does this instruction subract one from the r24 only?I don't understand how this instruction works in a loop.

How to decrement my count value(3ff-1)?

is there any other instruction or way to decrement my count value in a loop?because it need 2 bytes.

any help???

Last Edited: Fri. Sep 15, 2017 - 02:46 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you stop filling about 16 or 32 bytes from the end, you wont write over the stack return address in ram.

Imagecraft compiler user

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

In the upper 4 pairs of registers the adiw sbiw instruction can be used.

  LDI R27, 0X04 ;put here the comments
  ldI R26,0xff ;upper ram address
  ldi R25,0X01 ;lower address
  ldi R24,0X00 
  LDI R16,0x55  

lpp:
  st x,r16
  sbiw r26,1
  cp r26,r24
  cpc r27,r25
  brne lpp

[code] AND indentation added to this one

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

Is this correct?

	LDI R27, 0X01
	ldI R26,0x00
	ldi R28,0XFF
	ldi R29,0X03
	LDI R16,0xaa
	st x,r16
loop2:  ld r1,-y -----> instead of sbiw
	brne loop1
	nop

loop1: adiw XL,1 //ld r2,x+
	st x,r16
	jmp loop2

geoelec wrote:
In the upper 4 pairs of registers the adiw sbiw instruction can be used.

  LDI R27, 0X04 ;put here the comments
  ldI R26,0xff ;upper ram address
  ldi R25,0X01 ;lower address
  ldi R24,0X00 
  LDI R16,0x55  

lpp:
  st x,r16
  sbiw r26,1  how does this sbiw work?
  cp r26,r24
  cpc r27,r25
  brne lpp


could you please explain me 2 iteration?where is adiw instruction?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
.equ    memstrt = 0x100           ; First address of RAM to be filled
.equ    memend  = 0x4FF           ; Last address of RAM to be filled
.equ    fillchr = 0x55            ; Fill pattern

;---------------------------------------------------------------------------
; Fills RAM {memstrt..memend} with fillchr
; Uses only XL, XH, r16
; No ADIW/SBIW used.
;
fillmem:
        ldi     XL,low(memstrt)   ; Load the X pointer with start address
        ldi     XH,high(memstrt)  ;
 
        ldi     r16,fillchr       ; Load fill pattern to r16

fill_lp:
        st      X+,r16            ; Store a fill pattern, advance X pointer
        cpi     XL,low(memend+1)  ; Repeat until XL = low(memend+1)
        brne    fill_lp           ;

        cpi     XH,high(memend+1) ; Repeat until XH = high(memend+1)
        brne    fill_lp           ; (executed only on every 256th loop cycle)

        ret                       ; Done
;---------------------------------------------------------------------------

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

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

Quote:
If you stop filling about 16 or 32 bytes from the end
Or why not just check the current address against the stack pointer?

Regards,
Steve A.

The Board helps those that help themselves.

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

Adiw and Sbiw work only in register r24,r26,r28 and r30.Means add-substract an immediate value in a range from 0-63 from a pair of upper registers.
The four upper pairs of registers are:r24-r25,r26-r27(pointer X),r28-r29(pointer Y)and r30-r31(pointer Z).
Loading a 16 bit value to these register is easy to increment,decrement using the lower register of the pair and the carry in the high register is done by hardware.
sbiw r24,(0-63).

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

Thanks for your reply.
Could you please tell me about this implementation?

  LDI R27, 0X01
  ldI R26,0x00
  ldi R28,0XFF
  ldi R29,0X03
  LDI R16,0x55

loop2: ld r1,-y -----> instead of sbiw
  brne loop1
  nop

loop1:st x+,r16
  jmp loop2

Does this copy 0x55 to thr ram from (0x100 to 0x4ff)?

geoelec wrote:
Adiw and Sbiw work only in register r24,r26,r28 and r30.Means add-substract an immediate value in a range from 0-63 from a pair of upper registers.
The four upper pairs of registers are:r24-r25,r26-r27(pointer X),r28-r29(pointer Y)and r30-r31(pointer Z).
Loading a 16 bit value to these register is easy to increment,decrement using the lower register of the pair and the carry in the high register is done by hardware.
sbiw r24,(0-63).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
loop2: ld r1,-y -----> instead of sbiw 
brne loop1 
nop 

loop1:st x+,r16 
jmp loop2 


Does this copy 0x55 to thr ram from (0x100 to 0x4ff)? 



Not likely - looks like it will continue ad infinitum. If unsure, run the code in the simulator - you'll learn more. Look at MBedder's piece of code - nicely documented and using .equ for the magic numbers and using the assembler ops to do the grunt work for you. There's a handful of different solutions that will all do the same thing, so choose whichever suits you. Keep a loop counter or compare the pointer address, use adiw or not.....

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

I have to include the .section .init1 for accessing Ram? Am i Correct?

THis assembly code will run before the main() starts.
After running ,some of the RAm locations will be overwritten. i want to find the stack usage? For this I have started at the end of RAM (0x4FF), checked for the pattern 0x55,
Continue backwards in RAM until either:
a) I check for 3 consecutive 0x55 values. using multiple patterns

b)get to the start of RAM at 0x100.

My implementation for this is

#define RAM_PATTERN  		((unsigned char)0x55)
int stackused()
{

   int StackCount = 0;
    unsigned char  *p = NULL;

    p = (unsigned char *)MAX_MEM_ADDR; //0x4ff

    while( (p != NULL) && (p >= (unsigned char *)MIN_MEM_ADDR) ) //0x100
    {
        if( ((*p) == RAM_PATTERN) ) //1
        {
            StackCount++;
            --p;

            if((p != NULL) && (p >= (unsigned char *)MIN_MEM_ADDR)) 
            {
                if( ((*p) == RAM_PATTERN) ) //2
                {
                    StackCount++;
                    --p;

                    if ((p != NULL) && (p >= (unsigned char *)MIN_MEM_ADDR)) 
                    {    
                        if( ((*p) == RAM_PATTERN) ) //3
                        {    
                            StackCount++;    
                        
                        }
                        else
                        {
                            --p;
                        }
                    } 
                } 

                else
                {
                    --p;
                }
            } 
        } //1

        else
        {
            --p;
        }

    } 
 return StckCount;
}

It looks good when we copy the code into some notepad?
Is this efficient? How can I improve?

Kartman wrote:

loop2: ld r1,-y -----> instead of sbiw 
brne loop1 
nop 

loop1:st x+,r16 
jmp loop2 


Does this copy 0x55 to thr ram from (0x100 to 0x4ff)? 



Not likely - looks like it will continue ad infinitum. If unsure, run the code in the simulator - you'll learn more. Look at MBedder's piece of code - nicely documented and using .equ for the magic numbers and using the assembler ops to do the grunt work for you. There's a handful of different solutions that will all do the same thing, so choose whichever suits you. Keep a loop counter or compare the pointer address, use adiw or not.....

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

First up - does your code work? Use the simulator to convince yourself. Then worry about efficiency.

Also, when posting code, use the Code button so that the formatting is preserved.

Also realise that as part of the startup, the C code will zero certain areas of ram.

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

Moderator note:

Since we seem to have several offenders here at once can I ask that if anyone is posting segments of code in future you use the [code] button to maintain it's layout/indentation. Failing to do this makes the code close to unreadable.

After you have posted a code segment into your message just highlight the entire block then press the [code] button above the editor window.

I've now gone back and edited all the previous posts to do this - hopefully you can see how much more readable the code segments now look?

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

In the above code i tried to find the 3 consecutive occurrences of the 0x55 value in the ram. I don;t know for whatever reason my simulator is not working. I need to fix it. what's wrong in my code?Is there other way to find 3 consecutive occrrence in ram?

Kartman wrote:
First up - does your code work? Use the simulator to convince yourself. Then worry about efficiency.

Also, when posting code, use the Code button so that the formatting is preserved.

Also realise that as part of the startup, the C code will zero certain areas of ram.

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

Just to give you an idea this is what the ram for a small RAM AVR looks like for the following program:

#include 

int globalN = 0x5F27;
long globalL = 0xDEADBEEF;
char buffer[10];

void my_init(void) __attribute__((naked)) __attribute__ ((section (".init1")));
void my_init(void) {
	// Break into the C startup so I can clear SRAM to 
	// known values making it easier to see how it is used
	uint8_t *p;
	uint16_t i;
	
	for (i=0x60; i < RAMEND; i++) {
		p = (uint8_t *)i;
		*p = 0x5A;
	}
}

void function(void) __attribute__((noinline));
void function(void) {
   char str[] = "Hello";
   int n = 5;
   while (n--) {
     PORTB = str[n-1];
   }
}

int main(void) {
  int n, count;

  DDRB = 0xFF;
  function();
  for (n=SP, count=0; n>0x60; n--) {
    if (*((uint8_t *)n) == 0x5A) {
       count++;
    }
  }
  PORTB = count;
}

In simulating this when it hit the final PORTB=count line the variable 'count' held 0x5E. I built this for a 128 byte Tiny25.

I think your own code has forgotten that there'll be non-0x5A at BOTH ends of memory. So you cannot start your search at MAX_MEM_ADDR as there'll always be some existing stack usage up at that end. This is why my own code starts the search from "SP" which is a way you can directly access the stack pointer in a GCC program.

Attachment(s): 

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

Thanks . you are right. If I start my search like this.

unsigned char  *p = NULL;

	p = (unsigned char *)(MAX_MEM_ADDR - 1);

This should be fine. I hope my implemetation find 3 consecutive occurrences of 0x55 values in that RAM
array(0x100 to 0x4ff). Any suggestions on that?

clawson wrote:
Just to give you an idea this is what the ram for a small RAM AVR looks like for the following program:

#include 

int globalN = 0x5F27;
long globalL = 0xDEADBEEF;
char buffer[10];

void my_init(void) __attribute__((naked)) __attribute__ ((section (".init1")));
void my_init(void) {
	// Break into the C startup so I can clear SRAM to 
	// known values making it easier to see how it is used
	uint8_t *p;
	uint16_t i;
	
	for (i=0x60; i < RAMEND; i++) {
		p = (uint8_t *)i;
		*p = 0x5A;
	}
}

void function(void) __attribute__((noinline));
void function(void) {
   char str[] = "Hello";
   int n = 5;
   while (n--) {
     PORTB = str[n-1];
   }
}

int main(void) {
  int n, count;

  DDRB = 0xFF;
  function();
  for (n=SP, count=0; n>0x60; n--) {
    if (*((uint8_t *)n) == 0x5A) {
       count++;
    }
  }
  PORTB = count;
}

In simulating this when it hit the final PORTB=count line the variable 'count' held 0x5E. I built this for a 128 byte Tiny25.

I think your own code has forgotten that there'll be non-0x5A at BOTH ends of memory. So you cannot start your search at MAX_MEM_ADDR as there'll always be some existing stack usage up at that end. This is why my own code starts the search from "SP" which is a way you can directly access the stack pointer in a GCC program.

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

Why do you think MAX_MEM_ADDR-1 is low enough?? Assuming it's not inlined your stackused() function is going to have been called from main() and that will, itself have been called from the CRT. So at the very minimum you will have 2 bytes for the RET address of the CRT, any bytes used for automatics in main(), 2 bytes for the RET address within main(), the call saved registers of stack saved.

Plus the stack may have descended much deeper and set a much deeper low water mark before you make the call to stackused.

I think what I'd do is start at MAX_RAM_ADDR and keep decrementing until the first 0x55 is found then either count any from there downwards.

Or perhaps a better strategy is to recognise in your RAM layout that the linker will have placed .data at RAM start, followed by .bss and at the end of that it defines a label __bss_end (or __noinit_end if you use .noinit) and start your count/search from there up.

In fact if this is all about testing whether the stack has descended into .bss the ONLY check you really need make is that the single byte at _bss_end+1 is still the marker byte.

BTW you did look at the text of the program I presented above? As I say that returns account of the unused space between the end of .bss and the low water mark of the stack. It's all in C and I would have thought it's all that you require. The only "trick" it uses is to place a C routine into the .init1 memory section so that it runs before the .data and .bss setup loops to flood the entire SRAM (in this case from 0x60 to RAMEND) with the recognisable value.

Yet another approach is to forget filling RAM with a marker all together and instead run a fast timer interrupt that samples SP as the program runs and simply checks the low water mark and compares this against __bss_end of __noinit_end

Cliff

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

Thanks for your reply

	for ((p = (unsigned char *)MAX_MEM_ADDR); (p >= (unsigned char *)MIN_MEM_ADDR); --p ) //aa
	{
		if( ((*p) == RAM_PATTERN) ) //1
		{
			break;
		}

	}

	if( (p >= (unsigned char *)MIN_MEM_ADDR) && ((*p) == RAM_PATTERN) ) 
	{
		StackCount++;
		--p;
		if( (p >= (unsigned char *)MIN_MEM_ADDR) && ((*p) == RAM_PATTERN) )
		{  
			StackCount++;
			--p;
			if( (p >= (unsigned char *)MIN_MEM_ADDR) && ((*p) == RAM_PATTERN) )
			{  
				StackCount++;

			}
		}
		else
		{
			--p;
		}
	}
	else
	{
		--p;
	}

[/code]

I hope my for loop follow ur advice.

"I think what I'd do is start at MAX_RAM_ADDR and keep decrementing until the first 0x55 is found then either count any from there downwards."

After that it would find 3 consecutive values??
Could you please tell me some suggestions on my implemetation above.

clawson wrote:
Why do you think MAX_MEM_ADDR-1 is low enough?? Assuming it's not inlined your stackused() function is going to have been called from main() and that will, itself have been called from the CRT. So at the very minimum you will have 2 bytes for the RET address of the CRT, any bytes used for automatics in main(), 2 bytes for the RET address within main(), the call saved registers of stack saved.

Plus the stack may have descended much deeper and set a much deeper low water mark before you make the call to stackused.

I think what I'd do is start at MAX_RAM_ADDR and keep decrementing until the first 0x55 is found then either count any from there downwards.

Or perhaps a better strategy is to recognise in your RAM layout that the linker will have placed .data at RAM start, followed by .bss and at the end of that it defines a label __bss_end (or __noinit_end if you use .noinit) and start your count/search from there up.

In fact if this is all about testing whether the stack has descended into .bss the ONLY check you really need make is that the single byte at _bss_end+1 is still the marker byte.

BTW you did look at the text of the program I presented above? As I say that returns account of the unused space between the end of .bss and the low water mark of the stack. It's all in C and I would have thought it's all that you require. The only "trick" it uses is to place a C routine into the .init1 memory section so that it runs before the .data and .bss setup loops to flood the entire SRAM (in this case from 0x60 to RAMEND) with the recognisable value.

Yet another approach is to forget filling RAM with a marker all together and instead run a fast timer interrupt that samples SP as the program runs and simply checks the low water mark and compares this against __bss_end of __noinit_end

Cliff

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

This utility finds the first three occurances of the prewritten
test pattern 0xAA. This pattern is written in to all RAM
memory locations before any other initialization takes place.
The value returned is the maximum size of the stack in bytes.

What's wrong here?I get 5 bytes. any help?

int GetStackByteCount(void)
{
	

	int StackCount = 0;
	unsigned char consecutive = 0;
	unsigned char  *p = NULL;

	unsigned char  *temp = NULL;



	for ((p = (unsigned char *)MAX_MEM_ADDR); (p >= (unsigned char *)RAMSTART); --p )
	{
		if( ((*p) == RAM_PATTERN) ) 
		{
			break;
		}

	}

	while( ( (p >= (unsigned char *)RAMSTART) && (p <= (unsigned char *)MAX_MEM_ADDR) ) )	
	{ 
		temp = p;

		if (((*temp) == RAM_PATTERN) )
		{
			StackCount++;
			consecutive++;

			if( ((*(temp + 1)) == RAM_PATTERN) )
			{
				StackCount++;
				consecutive++;

				if( ((*(temp -1)) == RAM_PATTERN) )
				{
					StackCount++;
					consecutive++ ;
				}

				else 
				{ 
					--p;
					consecutive = 0;
			    }
			}
			else
			{
				--p;
				consecutive = 0;
			}

		}
		else
		{
			--p;
			consecutive = 0;
		}

			
		if(consecutive  == RAM_MIN_PATTERN)
		{
			break;
		}
		
	}
	
	return StackCount;
}

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

Stealing Proteus doesn't make you an engineer.

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

How use SBIW and ADIW on atmega88 proc?

avr lovers

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

Swinter wrote:

How use SBIW and ADIW on atmega88 proc?

 

This has nothing to do with the thread!

 

Stay in your other one:

http://www.avrfreaks.net/forum/a...

 

Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

Topic locked