- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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];
- Labels:
-
PSoC 5LP
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
For an absolute asignment -
http://www.keil.com/support/docs/2829.htm
Note its a Keil page talking about ARM, GNU.
Regards, Dana.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
missa,
have you tried using -defsym?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Lleung
Look at section 4.3.1, "Bus Interface to SRAM Memory" in the PSOC5 Technical Reference Manual below:
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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....
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Or some one have experience with the toolchain developement can help...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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 };
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Based on Keil C manual absolute locations are supported,
both thru use of macros and linker commands.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What FAQ ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
http://www.cypress.com/?id=4&rID=57109 (its as KB article after all, calling it a FAQ might be a bit overstated...)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks hli for pointing out FAQ. I filed a CASE to get this corrected.
Regards, Dana.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Maybe this will help, summarizes some of what has already been said -
infocenter.arm.com/help/index.jsp
Regards, Dana.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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);