Microblaze address space and variables

Hallo, I must create a memory for a display lcd. This is part of a microcontroller based on microblaze.

I thought to do it using a variable, a matrix: display[X][Y] (the software video memory).

This variable should exaclty stay into microblaze address space where I have mapped a blockram (the hardware video memory) from 0x77200000 to 0x7720FFFF.

In this way, working with my variable I could edit hardware video memory.

But I'm not able... how may I do it?

Many Thanks in Advance Marco Toschi

Reply to
Marco
Loading thread data ...

#define HEIGHT ... #define WIDTH ...

unsigned char *display[HEIGHT][WIDTH] = (unsigned char *)0x77200000;

display[y][x] = ...

Regards,

John

Reply to
John Williams

I have tried using what you told me, but during compilation, I receive the following error message:

invalid initialize

What could I do?

Many Thanks Marco

Reply to
Marco

Try

unsigned char *display[HEIGHT*WIDTH] = (unsigned char *)0x77200000;

display[y*WIDTH+x] =

I think display[][] is a pointer to a list of pointers: char **, but that's not what you want.

If your WIDTH is a power of 2, use shifts instead of y*width.

HTH, Jan

Reply to
Jan Bernauer

I receive the same error message during compilation:

invalid initialize

What could I do?

Many Thanks Marco

Reply to
Marco

Hi Marco, I'm far from being good at C, but I have some hobby-interest in MicroBlaze and C in general... What you are trying to do is not specifically MicroBlaze related - try the same code in a linux gcc compiler, for example, and you will get the same error.

When you write something like:

unsigned char *display[HEIGHT][WIDTH] = (unsigned char *)0x77200000;

What I think you are trying to say is "I want a pointer to a 2-D array, which has a base address of 0x77200000"

But the compiler sees this as an attempt to initalize the contents of the memory - and says "invalid initalizer"

In order to memory map a perpherial, I have used my own simple hack which is the following:

volatile unsigned char *ptr_to_mem;

int main() { ptr_to_mem = (unsigned char *) 0x77200000;

ptr_to_mem[address] = data;

}

This is a simple and vaild way to access byte-wise any memory starting at the base address shown abloe. you delcare the pointer as just a pointer to memory, and you access successive bytes by using it as an array. (Note: the volaitle is important - as it forces the memory access to occur) (Note: If you try this on a linux machine, it will have a segmentation fault, as it doesn't want you to assign the memory addesses!! - works fine in a microblaze without an OS though)

To implement a 2-D array, it can be done as anohter poster suggested, by having a power of 2 width, hardware barrel shifter, and calculating the address from that, and using a single-subscripted array.

This is probably far from the recommended way to do this but it works! - maybe for the real answer it might be worth checking out some C related newsgroups?

Cheers, John

--
***********************************************************************

/ /\/  John McGrath
\ \    Xilinx Inc.           
       Mixed Signal IC Design Engineer
\_\/\                        
                   
  Telephone: +353 21 4355 704        
  FAX:  
  John.McGrath@xilinx.com   
                X I L I N X  I N C.                       
***********************************************************************
Reply to
John McGrath

There is a lot of confusion here about pointers and arrays in C.

The declaration: unsigned char *display[HEIGHT][WIDTH]; ...means "display is a two-dimensional array with elements of type 'pointer to character'."

Similarly: unsigned char *display[HEIGHT*WIDTH]; ...means "display is a one-dimensional array with elements of type 'pointer to character'."

Consequently, trying to initialize either of these "display" variables with an 'unsigned char *', that is, a 'pointer to character', will not work because the types of the variable and the initializer are different.

Now, a variable of pointer type in C can be initialized to point somewhere (like to the 1,998,585,856th location in memory, in this example), but an array (of any dimension) cannot. Your best bet is to make "display" into a variable of type "pointer to a two-dimensional array of characters", which is probably what you were trying to do in the first place. The syntax for this is:

unsigned char (*display)[HEIGHT][WIDTH];

Note that the brackets are vital, because [] has higher precedence than * (see K&R p53).

To initialize this variable "display" to point to the screen buffer, do this (I'm omitting 'unsigned' from now on for brevity):

char (*display)[HEIGHT][WIDTH] = (char (*)[HEIGHT][WIDTH])0x77200000;

Now, to write to location (x,y), do this:

(*display)[y][x] = value;

As a previous poster pointer out, you might be better off with a one-dimensional array. For a start, you'll probably get more efficient code than for the multiple indirection above.

As an aside: you can dispense with the [HEIGHT] part if you like, and just write:

char (*display)[][WIDTH] = (char (*)[][WIDTH])0x77200000;

Also, a typedef might make your code more readable:

typedef char display_buffer_t[HEIGHT][WIDTH];

display_buffer_t *display = (display_buffer_t*)0x77200000;

Good luck!

-Ben-

Reply to
Ben Jones

You can use

-- #define WIDTH 640 #define HEIGHT 480

unsigned char (*display)[WIDTH] = (unsigned char (*)[WIDTH]) 0x77200000;

--

or to make it more readable

-- #define WIDTH 640 #define HEIGHT 480

typedef unsigned char (*dtype)[WIDTH]; dtype display = (dtype) 0x77200000;

---

In both cases you can later access the display with display[i][j] = 0; // clear pixel

- Peter

Marco wrote:

Reply to
Peter Ryser

If instead I would access not only 1 pixel at a time, but 8 pixels at a time, so a byte, what should I do?

Many Thanks Marco

Reply to
Marco

Assuming that you use 1 bit per pixel a display[i][j] = 0; actually clears 8 pixels at a time.

- Peter

Marco wrote:

Reply to
Peter Ryser

Hallo, I followed what you said. I have made a for cicle to write to video the addresses and sequential addreesses are, in example (decimals -> hex):

1998595456 -> 77200000 1998605056 -> 77202580

How is it possible? Second should be 77200001, I think.

I have tried also to copy data into one address:

(*display)[y][x] = 0xFF;

But when I print to video (*display)[y][x] I see 0, not 255.

How is it possible?

Many Thanks Marco

Reply to
Marco

Hi Marco,

the addresses and sequential addreesses are, in example (decimals -> hex):

Those hex values don't correspond to those decimal values at all.

0x77202580 is 1998595456 in decimal.

If the value of the pointer "display" is 0x77200000, then the address of the element (0,0) is &((*display)[0][0]) and will also be 0x77200000. The address of the "next" element is &((*display)[0][1]) and will be 0x77200001.

The address of the element (1, 0) is &((*display)[1][0]) and will be 0x77200000 + WIDTH. If the hex values you gave above are correct, the difference between the two addresses is 9600 - a "nice" number which is probably not an accident. Is this one of your screen dimensions, by any chance?

That is a little surprising. I would triple-check your hardware is all connected up correctly. If you have some other data memory region in your design, try this test: allocate the display memory there (by changing 0x77200000 to something else) and see if you can read and write the first element succesfully.

Another thing to do is declare your array as "volatile":

volatile unsigned char (*display)[Y][X];

This will force the compiler never to optimize away reads and writes of this array. Otherwise, it may think they have no effect and not bother to perform them.

Cheers,

-Ben-

Reply to
Ben Jones

I made a mistake in writing numbers...

decimal -> hex

1998585856 -> 77200000

next address:

1998585896 -> 77200028

The display is black/white 320x240 pixels.

I defined: height 240 width 40 (because 320/8 = 40. I decided to write 8 bit at a time through software.)

...display[height][width]...

It seems it jumps of 40 from one address to the next.

Thanks Marco

Reply to
Marco

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.