Define absolute variable location in memory

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

I have a project where I'm using the DMA to access memory in RAM. The whole problem is that I need to specify the base address of a 2D array, so for example how do I specify the starting address for:

   

uint8 frame[2][19200];

0 Likes
31 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Well, we are here in C and the address of an array is best expressed with the array-name

   

uint8 buffer[2][200];

   

now the address is

   

buffer

   

or

   

&buffer[0][0]

   

 

   

both may be type-casted as for instance

   

(char *) buffer

   

 

   

 

   

Happy coding

   

Bob

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

For an absolute asignment -

   

 

   

http://www.keil.com/support/docs/2829.htm

   

 

   

Note its a Keil page talking about ARM, GNU.

   

 

   

Regards, Dana.

0 Likes
Anonymous
Not applicable

 Bob:

   

That doesn't work because I will be just changing where the pointer points. I want to change where it's allocated in memory.

   

Dana:

   

I want to specify where the memory set aside for my array starts. So the RealView and Keil seem to solve the problem, but I'm using PSoC 5, which uses the GNU GCC compiler, right? The GCC example assumes that the data already exists at a specific position in memory.

   

Missael

0 Likes
Anonymous
Not applicable

How about this

   

http://www.cypress.com/?app=forum&id=2233&rID=55749

   

Hope this helps 🙂

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

One approach, not being GNU knowlegeable, is the equivalent of an AREA command,

   

where you set aside an area of memory, then are free to allocate whatever ande wherever

   

in that area. Or alternatively malloc ?

   

 

   

Bob may have more insight into this.

   

 

   

Regards, Dana.

0 Likes
Anonymous
Not applicable

 Hello

   

I already read that info before, but the problem is that the way they're explaining it is to allocate memory in flash and I need to allocate it in SRAM. The linker command doesn't allow me to specify the 32 bit address in order to locate in SRAM. Actually I need my array to start at the address 0x1FFFC000.

   

Missael

0 Likes
Anonymous
Not applicable

 My problem could be solved if someone can help me to make my own linker section! That way I could use the section attribute.

   

Missael

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

You may use simple pointers. To make life (typing and reading) easier use the "typedef" declaration.

   

typedef uint8 MyMemory[2][9];

   

   

MyMemory *Array1 = (void*)0x1FFFC000;

   

Later on in the program you may change the base-address

Array1 = (void*) 0xDeadBeef;

To access an element in Array1 you simply write

*Array1[0][2] = 27;

 

Happy coding

Bob

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Missa,

   

you wrote "That doesn't work because I will be just changing where the pointer points."

   

That's exactly how pointers work, If you just change the address on a letter, the envelope and its contents will go to a completely different location.

   

Setting up DMA requires the addresses of the source and destination which are pointers as well, so when you change one of them, you'll have to set up DMA anew.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Missa,

   

   

The methodssuggested are to read and write to the address.

   

   

I think your question is how to allocate/reserved the array in the RAM address you want. it to be?  Is this corret? 

0 Likes
Anonymous
Not applicable

 LLeung that is exactly what I'm asking... I need to allocate a variable (array) in a specific desired address (the reason is due to DMA and CPU priorities in certain memory areas). I'm not asking how to read or write to a certain address; I want to declare an array, and I want the compiler to reserve a specific space for it in memory, starting at my desired address. I want to decide where that array is going to be allocated. This needs to be done at compilation time, not when the program is already running.

   

The link you posted is only useful to allocate my array from 0x00000000 to 0x0000FFFF (mainly flash I think), for some reason the Linker fails after that range, or more specifically the cyhextool when I try to compile it (alternative methods like writing the number in decimal or binary just result in the linking process to be endless), I need to allocate my array (several kb) in 0x1FFFC000 (starting at that address).

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

As I already mentioned: ARM says exactly:

   

"With the GNU GCC Compiler you may use only pointer definitions to access absolute memory locations. "

   

Look here for more Infos: http://www.keil.com/support/docs/2829.htm

   

 

   

Bob

0 Likes
Anonymous
Not applicable

@Bob
To my understanding.

   

missa wants to "ALLOCATE AN ARRAY AT RAM ADDRESS 0X1FFFC000". missa has no problem reading or writing to/from  this array.

   

@missa
Why you need to have it at a fix address? why not declare the array inside your program and let the compiler assign it for you.

   

It's not necessary to have array in fix memory  location to use the DMA. The address of the array for the DMA can be handle by the compiler and resolve during compile time.

   

The fix address of the PSOC HW are handling by the macro defines of the creator.
 

   

The other reason I think people needs that is the memory (most likely external memory)  is shared with another processor. So the address must be fixed in order to pass the data around. Is this your issue?

0 Likes
Anonymous
Not applicable

missa,

   

have you tried using -defsym?

0 Likes
Anonymous
Not applicable

 Lleung

   

Look at section 4.3.1, "Bus Interface to SRAM Memory" in the PSOC5 Technical Reference Manual below:

       

   

   

http://www.cypress.com/?rID=55603

       

               

It states, "The priority decoder gives a higher priority to the C-Bus in the upper 32 KB of SRAM, whereas the PHUB DMA takes a higher priority in the lower 32KB of SRAM."

   

In my application, the DMA needs to have the highest priority when accessing the memory in question, so it needs to be in one half of the memory, not the other. I need to ensure that the memory allocated for the array that the DMA will use is put in this half.  Besides this, the DMA has nothing to do with my problem.  I know how to use the peripherals in question.

   

And... the defsym works just perfectly!!! For people reading this post in the future, this is how you do it for the PSoC 5, Compiler GNU GCC:

   

Project>>Build Settings>>ARM GCC 4.4.1>>Linker>>Command Line

   

In Custom Flags write down the following:

   

-Wl,--defsym,frame=0x1FFFC000

   

So that will put your base address for the array (called frame in my case) in 0x1FFFC000

   

Missael

0 Likes
Anonymous
Not applicable

Good to hear that.

   

But one thing you have to check because I am not 100% sure.

   

The linker should be ok to locate the section of memory for you, but check if the compiler is not assigning it for other use, ie stacks or vairalbes....

0 Likes
Anonymous
Not applicable

 Lleung

   

I just came back to this thread to say exactly what you are--a look at the map file shows that it in fact did not work.  The desired memory is not being set aside for the array.  Other variables are still being put there, so I'm still looking for a solution to my problem. I still need to allocate memory for my array.

0 Likes
Anonymous
Not applicable

May be it's time to get the big gun- to modify the ld file :-).

   

I think it is time for Cypress support to help.

0 Likes
Anonymous
Not applicable

Or some one have experience with the toolchain developement can help...

0 Likes
Anonymous
Not applicable

Is it possible to create a assembler file ie .s file and in that file

   

set absolute address and then DB ( or something similar) the length of the array.

   

This may work.

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

Even though its a little bit late, but for anybody coming here looking for an answer:

   

Look at this FAQ http://www.cypress.com/?id=4&rID=57109 for PSoC3, and from there go to http://www.cypress.com/?rid=91945 page 30 for PSoC5LP / PSoC4.

   

In short:

   

for PSoC3 do

   
int myVariable _at_ 0x1000;
   

(its not possible to define an absolute location in flash on PSoC3)

   

and for PSoC4/5 do:

   
uint32 const var_in_flash[] __attribute__((at(0x300))) = { default values };
0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

Based on Keil C manual absolute locations are supported,

   

both thru use of macros and linker commands.

   

 

   

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

Oh, Keil can do absolute locations on the 8051. But according to the FAQ its not possible to create an absolute location in Flash memory.

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

What FAQ ?

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

http://www.cypress.com/?id=4&rID=57109 (its as KB article after all, calling it a FAQ might be a bit overstated...)

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

Thanks hli for pointing out FAQ. I filed a CASE to get this corrected.

   

 

   

Regards, Dana.

0 Likes
JeCo_264681
Level 5
Level 5
100 replies posted 50 replies posted 25 replies posted

 I tried Bob Marlowe's idea, too. For two arrays of 2040 integers:

   

typedef uint16 MyMemory[2040];

   

MyMemory *Filter_Ch_A = (void*)0x1FFF9130;  // Put filter output in high SRAM to avoid

   

MyMemory *Filter_Ch_B = (void*)0x1FFF8120;  // crossing 64K boundary and get high R/W out of Flash memory.

   
        
   

When I looked at the map, it only allocated two bytes for each array.  Will probably have to edit the ld file to accommodate this:

   

uint16 Filter_Ch_A[2040] CY_SECTION(".MY_section"); // Holds output from Filter Channel A in SRAM

   

uint16 Filter_Ch_B[2040] CY_SECTION(".MY_section"); // Holds output from Filter Channel B in SRAM

   
        
0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

          Maybe this will help, summarizes some of what has already been said -

   

 

   

infocenter.arm.com/help/index.jsp

   

 

   

Regards, Dana.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

When talking about arrays or structures in SRam that additionally migtht get accessed by DMA, why not use malloc() to get what is needed. The upcoming 3.1 version of creator corrects and error in the implementation and now uses the heap to manage the amount of memory to be handled. The advantage is: you may give back temporarily unused areas and re-allocate them at need. DMA APIs use addresses of the transfer-areas which are supported by the pointers received by malloc().

   

Since usually there is no need for a fixed address in SRam this method will be the most portable.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

To allocate some memory at a given address in SRAM, one can add the following lines (in bold) in his linker script. In this example we allocate 256 bytes 8bytes aligned.

   

 

   

  .bss : ALIGN(8)
  {
    PROVIDE(__bss_start__ = .);
    *(.shbss)
    *(.bss .bss.* .gnu.linkonce.b.*)
    *(COMMON)
    . = ALIGN (8);
    *(.ram.b)
    . = ALIGN (8);
    _myallocateddata = .;
    . += 0x100;

    _end = .;
    __end = .;
  } >ram AT>rom
 

   

The linker script is accessible through the workspace explorer in the cy_boot component, the file is called cm3gcc.ld. The cy_boot component must be imported in the current project. You must modify the imported instance, not the generated code...

   

 

   

To use this buffer :

   

extern char *_myallocateddata;

   

 

   

Regards,

   

PNN

0 Likes
Anonymous
Not applicable

While you can do this relatively easily, my question is why?  Use the DMA Wizard to get a starting point and modify it.

   

 

   

Something like this:

   

 

   
/* Variable declarations for USB_ep1 */ /* Move these variable declarations to the top of the function */ uint8 USB_ep1_Chan; uint8 USB_ep1_TD[1];  /* DMA Configuration for USB_ep1 */ #define USB_ep1_BYTES_PER_BURST 127 #define USB_ep1_REQUEST_PER_BURST 0 #define USB_ep1_SRC_BASE (CYDEV_SRAM_BASE) #define USB_ep1_DST_BASE (CYDEV_SRAM_BASE)  USB_ep1_Chan = USB_ep1_DmaInitialize(USB_ep1_BYTES_PER_BURST, USB_ep1_REQUEST_PER_BURST,      HI16(USB_ep1_SRC_BASE), HI16(USB_ep1_DST_BASE)); USB_ep1_TD[0] = CyDmaTdAllocate(); CyDmaTdSetConfiguration(USB_ep1_TD[0], 1024, CY_DMA_DISABLE_TD, TD_INC_SRC_ADR | TD_INC_DST_ADR); CyDmaTdSetAddress(USB_ep1_TD[0], LO16((uint32)src), LO16((uint32)dest)); CyDmaChSetInitialTd(USB_ep1_Chan, USB_ep1_TD[0]); CyDmaChEnable(USB_ep1_Chan, 1);
   
        
   
    You can see from there that it uses CyDmaTdSetAddress() to set up the pointer. No need to know the address, as the compiler will get the right locations at build time.   
   
        
0 Likes