data memory mapping microblaze

A

alb

Guest
INFO: this very same post was posted to comp.arch.embedded with no
follow up over few days, that's the reason why I decided to post
it here where I hope to get more feedback.

Hi everyone,

I'm dealing with an mb-lite which is clone of the microblaze
architecture and I'm trying to understand how the memory mapping works.

We have memory mapped registers which are needed to exchange data
between the uP and the FPGA and it should be pretty straight
forward to
map this memory into a segment in 'data memory', but unfortunately it
seems the object-dump does not seem to show anything but a list of
segments with no distinction between 'data memory' and 'instruction
memory'.

IIRC on similar Harvard Architectures (like the ADSP21xx) you could
write the linker script to store data and instructions.

I'm using a mb-gcc and I've looked to the ld refernce, but how can you
specify that a set of registers need to go to the data memory to a
specific address? Or is it implicitely assumed that .data segments
would
go to a 'data memory'?

Anyone with any pointer?

Al

--
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?



----Android NewsGroup Reader----
http://usenet.sinaapp.com/
 
On Sat, 07 Feb 2015 07:17:29 +0100, alb wrote:

INFO: this very same post was posted to comp.arch.embedded with no
follow up over few days, that's the reason why I decided to post it
here where I hope to get more feedback.

I'm using a mb-gcc and I've looked to the ld refernce, but how can you
specify that a set of registers need to go to the data memory to a
specific address? Or is it implicitely assumed that .data segments
would
go to a 'data memory'?

Anyone with any pointer?

Al

This is not MB-specific but applicable to gcc.
You can attach "section" pragmas (in C, attributes) to variables in the
source code as part of their declaration. This directs them to be placed
in the named section.

https://gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/Variable-Attributes.html

"Some file formats do not support arbitrary sections so the section
attribute is not available on all platforms."

I seem to remember having to do this AND effectively repeat the same
information in the .ld linker script, (via the SECTIONS command)

http://www.scoberlin.de/content/media/http/informatik/gcc_docs/
ld_3.html#SEC17

However I am now hazy on the details, and that may have been an artefact
of the rather old version of gcc I had to use on that project.

-- Brian
 
On Sat, 07 Feb 2015 07:17:29 +0100, alb wrote:

INFO: this very same post was posted to comp.arch.embedded with no
follow up over few days, that's the reason why I decided to post it
here where I hope to get more feedback.

Hi everyone,

I'm dealing with an mb-lite which is clone of the microblaze
architecture and I'm trying to understand how the memory mapping works.

We have memory mapped registers which are needed to exchange data
between the uP and the FPGA and it should be pretty straight
forward to
map this memory into a segment in 'data memory', but unfortunately it
seems the object-dump does not seem to show anything but a list of
segments with no distinction between 'data memory' and 'instruction
memory'.

IIRC on similar Harvard Architectures (like the ADSP21xx) you could
write the linker script to store data and instructions.

I'm using a mb-gcc and I've looked to the ld refernce, but how can you
specify that a set of registers need to go to the data memory to a
specific address? Or is it implicitely assumed that .data segments
would
go to a 'data memory'?

Anyone with any pointer?

Al

Hey Al:

Sorry I missed this on c.a.e. In fact, I'm cross-posting

Am I correct that all you need to do is to read/write from a register or
set thereof, which is mapped to a specific location in the processor's
memory space?

In that case, there are a number of things you can do. Doing a Google
search of "memory mapped registers in C" is a good start. If you find
something by Michael Barr or Jack Gansle -- believe it, even if I
contradict it below.

I'm going to assume that these memory-mapped registers are not part of the
"real" data memory -- e.g., if the real data memory runs from 0x00000000
to 0x00007ffff, then you won't find the registers there.

The thoroughly C way to do this, without really demanding much "gnu-ness",
is to declare your registers something like:

#define REGISTER_0 (*((volatile int32_t *)(0x00010000)))
#define REGISTER_1 (*((volatile int32_t *)(0x00010004)))

Etc. Then you use REGISTER_0, REGISTER_1 as if they were integers.

The way I do this, which is probably wrong on many levels, is to define
the register addresses directly in a linker script:

TIM2 = 0x40000000;
TIM3 = 0x40000400;

(This is for an ST STM32F303)

Then in the code I have these long structure definitions that match the
stackup of the registers in the pertinent register sets, and the header
files end with something like:

extern volatile SGenTimer1Regs TIM2;
extern volatile SGenTimer1Regs TIM3;

This automatically makes everything line up, and then in the code I can
reference a timer with code like this (different timer than above, but you
get the idea):

TIM4.CCER.bits.CC3E = 0; // disable CC3
TIM4.DIER.all = 0;
TIM4.DIER.bits.CC2IE = 1; // wait for falling edge
TIM4.SR.all = 0;

My way works happily for me, but isn't terribly standard.

--

Tim Wescott
Wescott Design Services
http://www.wescottdesign.com
 
On Sat, 07 Feb 2015 19:16:18 -0600, Tim Wescott wrote:

On Sat, 07 Feb 2015 07:17:29 +0100, alb wrote:

INFO: this very same post was posted to comp.arch.embedded with no
follow up over few days, that's the reason why I decided to post it
here where I hope to get more feedback.

Hi everyone,

I'm dealing with an mb-lite which is clone of the microblaze
architecture and I'm trying to understand how the memory mapping works.

We have memory mapped registers which are needed to exchange data
between the uP and the FPGA and it should be pretty straight
forward to
map this memory into a segment in 'data memory', but unfortunately it
seems the object-dump does not seem to show anything but a list of
segments with no distinction between 'data memory' and 'instruction
memory'.

IIRC on similar Harvard Architectures (like the ADSP21xx) you could
write the linker script to store data and instructions.

I'm using a mb-gcc and I've looked to the ld refernce, but how can you
specify that a set of registers need to go to the data memory to a
specific address? Or is it implicitely assumed that .data segments
would
go to a 'data memory'?

Anyone with any pointer?

Al

Hey Al:

Sorry I missed this on c.a.e. In fact, I'm cross-posting

Whoops -- no, I'm not cross-posting.

--

Tim Wescott
Wescott Design Services
http://www.wescottdesign.com
 
Hi Brian,

Brian Drummond <brian@shapes.demon.co.uk> wrote:
[]
I'm using a mb-gcc and I've looked to the ld refernce, but how can you
specify that a set of registers need to go to the data memory to a
specific address? Or is it implicitely assumed that .data segments
would
go to a 'data memory'?
[]
This is not MB-specific but applicable to gcc.
You can attach "section" pragmas (in C, attributes) to variables in the
source code as part of their declaration. This directs them to be placed
in the named section.

https://gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/Variable-Attributes.html

Thanks for the pointer, I was aware about this possibility and I used to
do that on an old DSP (ADSP2187L) espectially for memory mapped
registers, but I clearly remember the possibility to specify PM or DM in
a 'memory map' file that unfortunately I'm not able to recover anymore!.

"Some file formats do not support arbitrary sections so the section
attribute is not available on all platforms."

I seem to remember having to do this AND effectively repeat the same
information in the .ld linker script, (via the SECTIONS command)

http://www.scoberlin.de/content/media/http/informatik/gcc_docs/
ld_3.html#SEC17

I think I'm more concerned about the MEMORY command where I should be
writing something along these lines:


MEMORY
{
ROM (r): ORIGIN = 0x00000000, LENGTH = whatever
RAM (w): ORIGIN = 0x80000000, LENGTH = whatever
}

Now, on an Harvard Architecture the two might really be starting from
0x0, but I don't seem to understand how you can specify that to the
linker without incurring into a 'memory overlap' error message.

However I am now hazy on the details, and that may have been an artefact
of the rather old version of gcc I had to use on that project.

Not sure it is just an artefact, I clearly remember the need to specify
memory mapped registers in the linker script (to have those symbols
located to the right place) and in the source code.

Al
 
Hi Tim,

Tim Wescott <seemywebsite@myfooter.really> wrote:
[]
I'm using a mb-gcc and I've looked to the ld refernce, but how can you
specify that a set of registers need to go to the data memory to a
specific address? Or is it implicitely assumed that .data segments
would go to a 'data memory'?

Sorry I missed this on c.a.e. In fact, I'm cross-posting

I'm doing it for you, since I believe c.a.e. is more appropriate. It's
kind of funny the thread picked up more momentum here than there.

Am I correct that all you need to do is to read/write from a register or
set thereof, which is mapped to a specific location in the processor's
memory space?

Not really. Being able to map registers into a specific location is an
important thing, but here the subject is a bit different.

On an Harvard Architecture data memory and program memory are simply two
different worlds. They can both start at location 0x00000000, but I
didn't find a way to say that to the linker without getting a
'memory/section overlap'.

In that case, there are a number of things you can do. Doing a Google
search of "memory mapped registers in C" is a good start. If you find
something by Michael Barr or Jack Gansle -- believe it, even if I
contradict it below.

I knew Ganssle from 'The Art of Embedded Systems Designs', a must, but I
wasn't aware about Barr, I'll definitely have a look at his advices.

I'm going to assume that these memory-mapped registers are not part of the
"real" data memory -- e.g., if the real data memory runs from 0x00000000
to 0x00007ffff, then you won't find the registers there.

Actually I need to map the 'real memory', memory mapped registers are
just the second in line, but they should follow the same 'reasoning'.

I have a data memory space and I want to place it at address 0, but it
ain't working (section overlap). One thing I thought about was tricking
the linker into thinking that pm and dm are in different locations but
since I do not need 32bit address for my embedded system I can say
0x00000000 for pm and 0x80000000 for my dm. Say only 20bit for the dm
address are used, I can safely say that my dm really starts from
physical address 0. But is that really ortodox? It sounds a nasty
workaround to me.

The thoroughly C way to do this, without really demanding much "gnu-ness",
is to declare your registers something like:

#define REGISTER_0 (*((volatile int32_t *)(0x00010000)))
#define REGISTER_1 (*((volatile int32_t *)(0x00010004)))

Etc. Then you use REGISTER_0, REGISTER_1 as if they were integers.

The way I do this, which is probably wrong on many levels, is to define
the register addresses directly in a linker script:

TIM2 = 0x40000000;
TIM3 = 0x40000400;

(This is for an ST STM32F303)

Then in the code I have these long structure definitions that match the
stackup of the registers in the pertinent register sets, and the header
files end with something like:

extern volatile SGenTimer1Regs TIM2;
extern volatile SGenTimer1Regs TIM3;

Interesting, but how do you make sure you don't incur into memory
overlaps? I used to have some sort of BASEADDRESS and refer all
addressing w.r.t. it:

#define REGISTER_0 (*((volatile int32_t *)(BASEADDRESS + 0x00000000)))
#define REGISTER_1 (*((volatile int32_t *)(BASEADDRESS + 0x00000004)))

still there's high risk that you may fall into temptetion to change the
type without readjusting the address location.
An alternative might be doing something like:

#define REGISTER_0 (*((volatile int32_t *)(BASEADDRESS + 0*sizeof(int32_t))))
#define REGISTER_1 (*((volatile int32_t *)(BASEADDRESS + 1*sizeof(int32_t))))

but again you need to be rigourous, should a change in type occourr, to
change both the type and the address.

Anyway, this is off topic since I'm not able to specify the dm address
for .data section and others.

Al
 

Welcome to EDABoard.com

Sponsor

Back
Top