Memory Colision with CVAVR

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

Using CodeVision with a Mega1281 and external RAM.

 

I need to keep several variable in memory and in the same order that I declare them.  I thought the best solution would be to define exact memory locations for these variables as follows:

 


uint8_t StatusMsg      @ 0x1200;    
uint8_t CtrlAddr       @ 0x1201;   
uint8_t Power          @ 0x1202;    
uint8_t CurrentSlot    @ 0x1203;    
uint8_t Test           @ 0x1204;     
uint8_t Subtest        @ 0x1205;  
uint16_t PassCount[8]  @ 0x1206;
uint16_t FailCount[8]  @ 0x1216;  

But I have found that strings declared in my code are using the same memory area, so the following line will have part of the string erased when I clear the above variables.

 

ErrorHandlerString("Timeout waiting for response");

 

What can I do to prevent strings and variables from using the same memory space?

 

Is there a better way to define variables and keep them in a specific order?

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

Why is it important to you to specify their location, just define them and let the compiler manage where they are, just reference them by name!???

 

Jim

 

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

Because they are part of a message sent in an interrupt driven background task.  A pointer to memory sends the bytes in an expected order for the receiving system to process.

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

dksmall wrote:
But I have found that strings declared in my code are using the same memory area,

Perhaps show a small complete test program that exhibits the behaviour.  It shouldn't be too hard, right?

 

When you say "strings", you mean "SRAM"?  And not flash-based constant strings.

 

(guessing) I've done what I think you are after several times in past lives.  The trickiest thing is to clear up the "rules".  If the message stays the same format then a structure for each message seems obvious.  But if one is going to the trouble, different wording or such, then some type of parameter-driven engine is often invented.

 

Re CV and overlap (which version?):  I don't remember exactly the "rules".  But I do remember doing intentional overlap on register variables to be able to do single and pair work. 

 

NB:  I'd at least consider putting the fields in a struct and using offsetof()

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

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

Last Edited: Mon. Nov 13, 2017 - 10:06 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dksmall wrote:
I need to keep several variable in memory and in the same order that I declare them

Then use a struct.

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

I seem to recall that a structure doesn’t garentee order, but maybe the brain isn’t working. I’ll give it a try.

Last Edited: Tue. Nov 14, 2017 - 12:14 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

It does guarantee order, of the members. It does not guarantee byte order within members. That is a consequence of 'endianness', and you can expect it to be consistent for a given implementation. If sending between two different systems (different architecture, compiler), then it becomes your responsibility. There are libraries to assist you, like protobufs.

Padding may be performed between members for alignment purposes, or packed to remove unused bytes.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

dksmall wrote:
What can I do to prevent strings and variables from using the same memory space?
Allocate strings from the heap.

http://hpinfotech.ro/cvavr_documentation.html

CodeVisionAVR manual

4.17 RAM Memory Organization and Register Allocation

 

"Dare to be naïve." - Buckminster Fuller

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

You can store strings in flash memory without having them copied to RAM using PSTR.  See http://www.nongnu.org/avr-libc/u...

 

For example:

        char OutBuff[BUF_SIZE];
	memset(OutBuff, 0, BUF_SIZE);
	strcpy_P(OutBuff, PSTR("\r\nBUFFER OVERFLOW!!! BUFFER OVERFLOW!!! BUFFER OVERFLOW!!!\r\n"));
	UART_Transmit_Buffer(OutBuff);

Notice the _P on the strcpy_P.  The string is stored in program memory, and then copied to OutBuff[] in RAM and sent out UART.  I don't know if this will help you, but it saves on RAM for strings

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

MarkThomas wrote:
You can store strings in flash memory without having them copied to RAM using PSTR

Wrong compiler! This thread is about CodeVision (it says in the title).

joeymorin wrote:
It does guarantee order, of the members. It does not guarantee byte order within members.
The other thing that is implementation defined is the packing.

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

If you want a fixed order of fields/variables use a struct.

 

Access the struct by name in the regular way.

 

Codevision will handle the struct according to the C language.  Just like any other C compiler.

 

If you have a problem,  attach a complete buildable CV or AS7 project.   (ZIP up the project directory)

It takes you a few minutes to prepare information and provide the files.   In return you will probably get an accurate answer within hours.

 

If you do not present your questions carefully,   the thread goes on for days and weeks.

 

David.

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

I will plan on using a structure.  Placing variables in reserved memory using the heap seems like voodoo to this old assembly programmer, so I'll keep it simple. :-)

 

Using CodeVision, I can place string in flash with something like

ErrorHandlerString(flash char *message);

That won't prevent the original problem I was having with memory locations, but it will use less RAM.

 

Thanks everyone!

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

Arggg.  I am going to stop posting on this forum.  I'm tired of being the guy who says stupid stuff.  I'll come back if I have a legitimate question.  Take care, all.  You are great.

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

You have the right idea, just a syntax difference between compilers. smiley

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

dksmall wrote:
That won't prevent the original problem I was having with memory locations,

Hmmm--is allowing overlap a "feature" or a "problem"?  I'd still like to see a stripped-down complete example to poke at...

 

 

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

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

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

The overlap was the problem.  Might be difficult to strip it down to a small example.  Basically a simple line this this

 

ErrorHandlerString("This is the error message");

was not working because the string is stored in xram at the same location that my global variables were stored at, using the @ to specify the exact memory location.  I would assume that the compiler was smart enough to know I was using xram at locations I declared, and not copy strings like the above, into those same locations.

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

dksmall wrote:
I would assume
  We have all been bitten by that one! 

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

Indeed.

 

If RTFM doesn't confirm it, then contact support.

 

I don't use CV, but other here who do report that they are responsive ...

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

If there are any doubt about order and the endian I would simply make a mapper function that index into an array of bytes so: 

U8 X=ar[10] ;

U16 Y=ar[11]*256+ar[12]  ;

 

and then have the protocol "defined" in a enum that is used as the index. 

 

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

dksmall wrote:
was not working because the string is stored in xram at the same location that my global variables were stored at,

 

That is the so-called anonymous string, right?  And you are passing what to that function?  char*?  If indeed a constant string, why force an SRAM copy? [I'd probably jigger the API to force flash work -- you need a flash copy for init anyway.]

 

Side note:  I see a couple references to "xram" in your posts, but the addresses are internal SRAM.

 

 

dksmall wrote:
Might be difficult to strip it down to a small example.

 

Why would that be?  You are 90% of the way there.  I'm only curious, as I've used overlap as a "feature".  Can it be both "feature" and "problem" without some kind of compiler/linker option, or at least warning?  Dunno.

 

 

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

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

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

theusch wrote:

 

dksmall wrote:
Might be difficult to strip it down to a small example.

 

Why would that be?  You are 90% of the way there.  I'm only curious, as I've used overlap as a "feature".  Can it be both "feature" and "problem" without some kind of compiler/linker option, or at least warning?  Dunno.

 

Well I certainly wasn't making it a feature.  This is a fairly large program and once I strip out all the error message calls like the string I used as an example, I'd have to find the one remaining string's memory location and then assign my global variables to that location.  Doable but it will take time from this project that needs to get finished.

 

I did contact HP Infotech and was recommended to use a structure.  He also showed how I should be using a flash version of my error handler to keep the string in flash, i.e. ErrorHandlerString(flash char * message);

So I made all those changes and the project continues.  I'm kicking myself because I didn't make note of how much RAM was being used before making these changes, so I could compare.  My co-worker has his own test development using my code, so before I convert his to use a structure, I'll make note of the RAM usage before and after.

 

Lee, if you're still curious I'll try to make a small example when I get a chance.  But if memory servers, you're not a CV user, do I send you a map file?

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

dksmall wrote:
I didn't make note of how much RAM was being used before making these changes, so I could compare.
Strong argument for using a revision control system ;-)

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

Even without a revision control system, it is trivial to take "snapshot" copies of the project for reference ...

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

awneil wrote:

Even without a revision control system, it is trivial to take "snapshot" copies of the project for reference ...

Which is what I do, I have multiple backup revisions.  I finished the co-workers update and was able to compare before and after.  It uses 943 bytes less RAM now.

 

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

dksmall wrote:
This is a fairly large program and once I strip out all the error message calls like the string I used as an example, I'd have to find the one remaining string's memory location and then assign my global variables to that location. Doable but it will take time from this project that needs to get finished.

???  I'm just looking for a complete program that demonstrates the situation.  The only thing we have to go on so far is one partial demonstration of what I think is "anonymous string" -- but we cannot see how the function parameter is declared.  Or even if that is a function invocation.

 

dksmall wrote:
But if memory servers, you're not a CV user,

;)  Been doing almost all CV since 2000.  Didja ever notice

 

I say "feature" because, as I mentioned, a couple times I have used the @ syntax for >>purposeful<< overlay.

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

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

Last Edited: Thu. Nov 16, 2017 - 08:20 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dksmall wrote:
It uses 943 bytes less RAM now.

"XRAM", or internal SRAM?  I.e., what about my query about the addresses?

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

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

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

theusch wrote:

dksmall wrote:
This is a fairly large program and once I strip out all the error message calls like the string I used as an example, I'd have to find the one remaining string's memory location and then assign my global variables to that location. Doable but it will take time from this project that needs to get finished.

???  I'm just looking for a complete program that demonstrates the situation.  The only thing we have to go on so far is one partial demonstration of what I think is "anonymous string" -- but we cannot see how the function parameter is declared.  Or even if that is a function invocation.

 

dksmall wrote:
But if memory servers, you're not a CV user,

;)  Been doing almost all CV since 2000.  Didja ever notice

 

I say "feature" because, as I mentioned, a couple times I have used the @ syntax for >>purposeful<< overlay.

No I didn't read the fine print, good for you!!

I can strip it down to something that outlines what I was doing, but it may not reproduce the error that I was seeing with memory being overwritten, unless I change the @ address to point at where the strings are now, meaning things will move once I make a smaller version of the code.  Hopefully that makes sense.

Since the area in question was 0x1200 I would say that is internal SRAM.  The external SRAM is mapped (wired) from 0 to 0x8000 and if I understand the way the 1281 works, it's internal SRAM from 0x200 to 0x2200, then it uses the external SRAM.

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

OK, let's start with a simple program dealing with the "anonymous string".  No @ syntax yet.  Built for Mega328PV.

#include <io.h>
#include <stdint.h>
#include <delay.h>

char ramstring[12] = "ABC"; 

void dumbfunc (char * aptr)
{
// Stupid code to force access?
char * localptr = aptr;

while (*localptr)
    {
    PORTD = *aptr;
    delay_ms (123);
    }
return;
}



void main(void)
    {                
                while (1)      // endless loop
                    {
                    dumbfunc (ramstring);
                    
                    dumbfunc ("Anonymous string");   // anonymous string
                    }   
    }
       

The .MAP doesn't tell us much...

RAM Allocation [bytes]
Variable                                                                          Address   Size
------------------------------------------------------------------------------------------------
ramstring                                                                         0x0191      12

...so let's look at the .LST:

                 	.DSEG
                 _0xA:
000180           	.BYTE 0x11
                 ;
                 
                 	.DSEG
                 _ramstring:
000191           	.BYTE 0xC
                 

The anonymous string is located at the "next" .DSEG location.  .DSEG starts at 0x180 for this model and this is the first thing.  If you really need me to, we can follow back to the initial value in flash and the copy loop during the C prologue...

 

                 _0x3:
000034 4241
C:\AtmelC\TestProgs\Debug\List\M88t.asm(1134): warning: .cseg .db misalignment - padding zero byte
000035 0043      	.DB  0x41,0x42,0x43
                 _0x0:
000036 6e41
000037 6e6f
000038 6d79
000039 756f      	.DB  0x41,0x6E,0x6F,0x6E,0x79,0x6D,0x6F,0x75
00003a 2073
00003b 7473
00003c 6972
00003d 676e      	.DB  0x73,0x20,0x73,0x74,0x72,0x69,0x6E,0x67
C:\AtmelC\TestProgs\Debug\List\M88t.asm(1138): warning: .cseg .db misalignment - padding zero byte
00003e 0000      	.DB  0x0
                 
                 __GLOBAL_INI_TBL:
00003f 0003      	.DW  0x03
000040 0191      	.DW  _ramstring
000041 0068      	.DW  _0x3*2
                 
000042 0011      	.DW  0x11
000043 0180      	.DW  _0xA
000044 006c      	.DW  _0x0*2
                 
                 _0xFFFFFFFF:
000045 0000      	.DW  0
                 
                 #define __GLOBAL_INI_TBL_PRESENT 1
                 
 

Now, let's put some variables on top of those areas...

 

 

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

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

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#include <io.h>
#include <stdint.h>
#include <delay.h>

char ramstring[12] = "ABC"; 

// "Hard" located items.
uint8_t c180 @0x180; // overlaps the anonymous string
uint8_t c181 @0x181;
uint8_t c191 @0x191; // overlaps "ramstring"
uint8_t c192 @0x192;

void dumbfunc (char * aptr)
{
// Stupid code to force access?
char * localptr = aptr;

while (*localptr)
    {
    PORTD = *aptr;
    delay_ms (123);
    }
return;
}



void main(void)
    {                   
                while (1)      // endless loop
                    { 
                    c180+= PINB;
                    dumbfunc (ramstring);
                    c181+= PINB;
                    
                    c191 += PIND;
                    dumbfunc ("Anonymous string");   // anonymous string
                    c192 += PIND;
                    
                    OCR0A = c180 + c181 + c191 + c192;
                    }   
    }
       

A clean build!  Let's see if there is overlap... hmmm; "partial" results.  From the .MAP:

RAM Allocation [bytes]
Variable                                                                          Address   Size
------------------------------------------------------------------------------------------------
ramstring                                                                         0x0193      12
c180                                                                              0x0180       1
c181                                                                              0x0181       1
c191                                                                              0x0191       1
c192                                                                              0x0192       1

...there is no overlap with global variable "ramstring"--the compiler pushed it out of the way.  What about the anonymous string?

 

                 
                 	.DSEG
                 _0xA:
000180           	.BYTE 0x11
                 ;
                 
                 	.DSEG
                 
                 	.ORG 0x193
                 _ramstring:
000193           	.BYTE 0xC
                 
                 	.ORG 0x180
                 _c180:
000180           	.BYTE 0x1
                 
                 	.ORG 0x19F
                 
                 	.ORG 0x181
                 _c181:
000181           	.BYTE 0x1
                 
                 	.ORG 0x19F
                 
                 	.ORG 0x191
                 _c191:
000191           	.BYTE 0x1
                 
                 	.ORG 0x19F
                 
                 	.ORG 0x192
                 _c192:
000192           	.BYTE 0x1
                 
                 	.ORG 0x19F
                 

Kind of a mixed bag.  If I had to guess, not taking into account the anonymous (strings, variables, whatever) might be an oversight.  But in practice, as discussed earlier, it is wasteful to have such constructs in an AVR8 app.  As another guess:  That is why it hasn't been addressed in the compiler, because it hasn't arisen before?  Dunno.

 

 

 

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

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

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

dksmall wrote:
Since the area in question was 0x1200 I would say that is internal SRAM.

But you mentioned XRAM a couple times, so I had to check...

dksmall wrote:
was not working because the string is stored in xram at

dksmall wrote:
I would assume that the compiler was smart enough to know I was using xram at locations I

 

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

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

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

I would guess that the mind set is why waste RAM space with anonymous strings, as you call them, when CV allows you to keep them in flash.  So as you say, it never came up.  But someone diving in and using this compiler for the first time, or someone with a limited knowledge of C (waving hand) would not realize that such an option exists, without diving into the manuals.  But since a function like strcpyf isn't standard C, I'm surprised this issue hasn't happened before.  OR it's because no one is using the @ address construct and anonymous strings.