DSPRelated.com
Forums

accessing memory addresses using C

Started by techie March 20, 2007
Hi

Im new to the world of embedded systems.. Can anyone give me any
examples of accessing memory locations using C as well, as say,
clearing them ..

For example, if i have to clear addresses from 3000h to 3300h, how do
i go about doing the same ???

thanks heaps..

techie

techie wrote:
> Hi > > Im new to the world of embedded systems.. Can anyone give me any > examples of accessing memory locations using C as well, as say, > clearing them .. > > For example, if i have to clear addresses from 3000h to 3300h, how do > i go about doing the same ??? > > thanks heaps.. > > techie >
hello Newbe, err techie, If you are a techie, then you would know that it depends on the C compiler you are using, what processor you are using and your abilities. So, What C compiler are you using ? What processor are you using ? I leave the third one as an exercise for the user. donald

> So, > What C compiler are you using ? > What processor are you using ? > > I leave the third one as an exercise for the user. > > donald
The target processor is TMS320F2812 ( 32-bit DSP ) Im using the Code composer studio IDE
techie wrote:

> Im new to the world of embedded systems.. Can anyone give me any > examples of accessing memory locations using C as well, as say, > clearing them .. > > For example, if i have to clear addresses from 3000h to 3300h, how do > i go about doing the same ???
First you need a pointer to the start address, then call memset to clear the contents of this memory region: unsigned char* start = (unsigned char*)0x3000; memset(start, 0, 0x3300 - 0x3000); bye Andreas -- Andreas H�nnebeck | email: acmh@gmx.de ----- privat ---- | www : http://www.huennebeck-online.de Fax/Anrufbeantworter: 0721/151-284301 GPG-Key: http://www.huennebeck-online.de/public_keys/andreas.asc PGP-Key: http://www.huennebeck-online.de/public_keys/pgp_andreas.asc

Andreas Huennebeck wrote:


>>Im new to the world of embedded systems.. Can anyone give me any >>examples of accessing memory locations using C as well, as say, >>clearing them .. >> >>For example, if i have to clear addresses from 3000h to 3300h, how do >>i go about doing the same ??? > > > First you need a pointer to the start address, then call memset to clear > the contents of this memory region: > > unsigned char* start = (unsigned char*)0x3000; > memset(start, 0, 0x3300 - 0x3000); >
What a dirty hack. The physical adresses should never appear in C code. The dedicated memory area should be defined as the section in linker file, and the variables should be placed in that section. The C program should work with the C defined variables only. Using the nonportable types like (unsigned char) is a dirty hack also, and so is using memset() to reset the variables. Vladimir Vassilevsky DSP and Mixed Signal Design Consultant http://www.abvolt.com

techie wrote:

> Hi > > Im new to the world of embedded systems.. Can anyone give me any > examples of accessing memory locations using C as well, as say, > clearing them .. > > For example, if i have to clear addresses from 3000h to 3300h, how do > i go about doing the same ??? >
This is the right way to do that: //--------------------------------------------------- linker file: MEMORY { MEM_FUBAR { TYPE(RAM) WIDTH(8) START(0x3000) END(0x32FF) } } SECTIONS { SEC_FUBAR { INPUT_SECTIONS($objects(fubar)) } > MEM_FUBAR } //----------------------------------------------- C source file: typedef unsigned int u32; typedef unsigned char u8; #define ZERO_INIT(x) ZeroInit((x), sizeof((x))/sizeof(x[0])) template <class T> void ZeroInit(T *t, u32 n) { while(n--) *t++ = 0; } static section("fubar") u8 blablabla[0x300]; main() { ZERO_INIT(blablabla); } //---------------------------------------------- Vladimir Vassilevsky DSP and Mixed Signal Design Consultant http://www.abvolt.com
Vladimir Vassilevsky wrote:
> This is the right way to do that: > > //--------------------------------------------------- > linker file:
[...]
> //----------------------------------------------- > C source file: > > #define ZERO_INIT(x) ZeroInit((x), sizeof((x))/sizeof(x[0])) > > template <class T> void ZeroInit(T *t, u32 n) > { > while(n--) *t++ = 0; > } > > static section("fubar") u8 blablabla[0x300];
Congratulations. Compared to Andreas' simple solution, unsigned char* start = (unsigned char*)0x3000; memset(start, 0, 0x3300 - 0x3000); you have (1) duplicated the knowledge about the size of the memory area in the C++ (not C!) source file and the linker file. Having it all in one language allows the use of a header file with appropriate definitions. (2) taken away from the compiler the ability to optimize based on actual addresses of the objects you are dealing with. If you let the compiler resolve addresses (instead of the linker), it can easily know that the MMR you access in line 20 is just 8 bytes after the one in line 10, and access both using the same base register. Resolving memory accesses through a linker file requires costly reloads (at least for platforms that don't have a "mov (imm32), %eax"-type instruction, i.e. most RISC). (3) used compiler-specific syntax. Whereas most compilers for an architecture agree how an integer-to-pointer cast looks like, 'section("fubar")' is supported only by few. Others want '#pragma' or '__attribute__'. If you insist on doing it in the linker file, better define a single absolute symbol instead of a section. This also avoids that someone accidentally allocates an unrelated variable in the section. (4) written (bad) C++ instead of C. If you insist on C++, do it right: template<typename T, std::size_t Size> void ZeroInit(T (&m)[Size]) { for (std::size_t i = 0; i < Size; ++i) m[i] = T(); } (works for types whose initial value is not 0, and avoids the macro) Stefan

Stefan Reuther wrote:

>>This is the right way to do that: >> >>//--------------------------------------------------- >>linker file: > > [...] > >>//----------------------------------------------- >>C source file: >> >>#define ZERO_INIT(x) ZeroInit((x), sizeof((x))/sizeof(x[0])) >> >>template <class T> void ZeroInit(T *t, u32 n) >>{ >>while(n--) *t++ = 0; >>} >> >>static section("fubar") u8 blablabla[0x300]; > > > Congratulations. Compared to Andreas' simple solution, > > unsigned char* start = (unsigned char*)0x3000; > memset(start, 0, 0x3300 - 0x3000);
Crude, nonportable, dependent and dirty hack.
> > you have > > (1) duplicated the knowledge about the size of the memory area in the > C++ (not C!) source file and the linker file. Having it all in one > language allows the use of a header file with appropriate definitions.
No. The point is that it is not the business of C code to know anything about memory areas and sizes. The code deals with the sensible objects only.
> (2) taken away from the compiler the ability to optimize based on actual > addresses of the objects you are dealing with. If you let the compiler > resolve addresses (instead of the linker), it can easily know that the > MMR you access in line 20 is just 8 bytes after the one in line 10, and > access both using the same base register. Resolving memory accesses > through a linker file requires costly reloads (at least for platforms > that don't have a "mov (imm32), %eax"-type instruction, i.e. most RISC).
Who cares. Premature optimization is the root of all evil.
> (3) used compiler-specific syntax.
Unfortunately, there is no universal way. I usually solve this problem with the compiler specific macro header.
> (4) written (bad) C++ instead of C.
C is the ancient dialect of C++. If you insist on C++, do it right: Yes, you go ahead and do it right. Your code won't compile for several reasons.
> template<typename T, std::size_t Size> > void > ZeroInit(T (&m)[Size]) > { > for (std::size_t i = 0; i < Size; ++i) > m[i] = T(); > } > (works for types whose initial value is not 0, and avoids the macro)
VLV
techie wrote:
> >> So, >> What C compiler are you using ? >> What processor are you using ? >> >> I leave the third one as an exercise for the user. >> >> donald > > The target processor is TMS320F2812 ( 32-bit DSP ) > Im using the Code composer studio IDE > >
The advice you received in this thread has some merits. Unfortunately it also appears that the thread is degenerating into a flame war over the merits of C versus C++ and how to appropriately handle certain constructs in the language. The address range you specified (3000h to 3300h) is in the external interface Zone 0 of the F2812, which may make things more complex. If need be, you can find a lot of documentation on accessing the external interface in the manuals and in the TI discussion groups. The external interface regions will also be effected by the XINTF configuration settings. Anyway, the part about needing to define the memory in the linker command (cmd) file is correct. You will need to define a MEMORY and a SECTIONS block in the file. These blocks will spell out the memory type, starting address, length, alignment, and WHAT YOU WILL CALL THE SECTION OF MEMORY! Also note, the F2812 uses 16 bits as its natural width and while CHAR declarations are supported and will work (though not necessarily as you intended) you need to be extra careful when doing so. Once this is done, in you C or C++ code, you will need to use a #pragma directive to declare a variable that is located in that section of memory. The exact syntax of the variable will depend on whether you are using C or C++ (consult the compiler manual for examples). After you have declared the variable, you will be able to access it like any other variable in your program using assignment statements. To clear the section of memory, you could write a simple loop to initialize the memory to whatever you want it to be. As far as C++ and the F2812 goes, the compiler does support a limited subset of C++. I am not an expert on what portions of the lanugage are not supported, but I believe that virtual inheritance and templates are amongst the parts left out, though I may be wrong.
Vladimir Vassilevsky wrote:
> Stefan Reuther wrote: >> Congratulations. Compared to Andreas' simple solution, >> >> unsigned char* start = (unsigned char*)0x3000; >> memset(start, 0, 0x3300 - 0x3000); > > Crude, nonportable, dependent and dirty hack.
It uses a language feature for exactly the purpose it was intended for. If one replaces the magic constants by proper macros, I don't see where this is crude and dirty.
>> (2) taken away from the compiler the ability to optimize based on actual >> addresses of the objects you are dealing with. [...] > > Who cares. Premature optimization is the root of all evil.
I do care whether my interrupt handler takes 300 or 500 cycles to complete.
>> (3) used compiler-specific syntax. > > Unfortunately, there is no universal way. I usually solve this problem > with the compiler specific macro header.
So, where exactly is this less nonportable, dependent and dirty than the other solution?
>> If you insist on C++, do it right: > > Yes, you go ahead and do it right. Your code won't compile for several > reasons.
I tried it, it does compile, and it yields the correct assembly code. Stefan