Put characters on the screen


5 posts
by riccardo2 » Sun Aug 26, 2012 10:58 am
Reading the posts I've realized that many people would like to discover how to control the gpu and I know that it's not open. But what I'm looking for is simpler. On the x86 I've already done some bare metal experiment on writing to the VGA memory at the 0xB8000 address. It isn't related to a particular GPU, all the x86 use the 0xB8000 address to put characters during console mode. I'm looking for a similar standard address for Arm architecture in order to put a "Hello world". Can somebody help me?

I'm sorry for my english... but I'm Italian ;-)

Thanks you!
Posts: 2
Joined: Sun Aug 26, 2012 10:44 am
by DexOS » Sun Aug 26, 2012 2:13 pm
riccardo2 wrote:Reading the posts I've realized that many people would like to discover how to control the gpu and I know that it's not open. But what I'm looking for is simpler. On the x86 I've already done some bare metal experiment on writing to the VGA memory at the 0xB8000 address. It isn't related to a particular GPU, all the x86 use the 0xB8000 address to put characters during console mode. I'm looking for a similar standard address for Arm architecture in order to put a "Hello world". Can somebody help me?

I'm sorry for my english... but I'm Italian ;-)

Thanks you!

You can not do that in arm as you can on x86, you need to make your own font bit maps and draw them one pixel at a time.
But i and others have written demo to do some of the work for you.
This is how to do a bare metal Hello world.
http://www.dex-os.com/DexBasic/DexBasic.htm
Batteries not included, Some assembly required.
User avatar
Posts: 876
Joined: Wed May 16, 2012 6:32 pm
by riccardo2 » Sun Aug 26, 2012 3:34 pm
I had already looked at this wonderful tutorial... and it is in my favourite bookmarks. But what I'm looking for is the implementation of "print" function. I don't wont the "copy and paste" code. May you tell what resources I need, what protocol... what I must search and study?

Thanks a lot!
Posts: 2
Joined: Sun Aug 26, 2012 10:44 am
by DexOS » Sun Aug 26, 2012 6:33 pm
There's a C frame buffer and char example here: http://people.pwf.cam.ac.uk/nst25/rpi/2012062301.tar.gz
You need to do this
/*
* ************************************************************************ *
* **** BCM2835 Specific Stuff **** *
* ************************************************************************ *
* This is where things get interesting (and specific to the BCM2835).
* Most of this was worked out by reading the Linux source code (mostly
* drivers/video/bcm2708_fb.c and arch/arm/mach-bcm2708/) and experimentation.
*
*
* **** Basic procedure to get stuff on screen ****
* The basic procedure to get a frame buffer is:
* 1) Set up a structure with the frame buffer specification (resolution, etc)
* 2) Tell the GPU about this structure by writing to the mailbox
* 3) Wait by reading from the mailbox for the GPU to modify this structure
* 4) Write to the frame buffer at the pointer we got in stage 3
* Only step 4 is required for subsequent writes to the frame buffer. Currently,
* I do not know how to enable the HDMI output, so this will always operate the
* composite, and not the HDMI.
*
*
* **** Mailbox operations ****
* Read/write operatitons on the mailbox consist of transfering data via a
* 32 bit register. 28 bits of this 32 bit register are the data to be sent
* to the receiver, while the lower 4 bits specify the channel (channel 1 is
* the frame buffer, but there are others).
*
* To send data via the mailbox:
* 1) Wait for space in the mailbox
* 2) Write ((data << 4) || channel) to the write register TODO: Make implementation match
*
* To receive data via the mailbox:
* 1) Wait for the mailbox to be non-empty
* 2) Execute a memory barrier
* 3) Read from the read register
* 4) Check the lowest 4 bits of the read value for the correct channel
* 5) If the channel is not the one we wish to read from (i.e: 1), go to step 1
* 6) Return the read value >> 4 TODO: Make implementation match
* Note: This will not work if we're interested in reading from more than one
* channel as it does not handle the reception of other channels' data
*
*
* **** Memory mapped registers ****
* The bus address for the mailbox memory mapped registers is 0x7E00B880.
* This corresponds to an ARM physical address of 0x2000B880 (the address we
* use from the ARM processor, and hence here). We use three registers from
* the mail box:
* - The read register for mailbox 0 at offset 0x00
* - The status register for mailbox 0 at offset 0x1C
* - The write register for mailbox 0 at offset 0x20 (this is actually the read
* register for mailbox 1).
*
*
* **** Notes ****
* - The address of the frame buffer must be at least a multiple of 16 (in
* order to be accurately transmitted in the 28 bits available in the
* mailbox)
* - The 32 bit value we actually send over the mailbox (including the channel)
* is (ADDRESS | 1) where ADDRESS is the address of the structure. This is
* equivalent to sending as the data (ADDRESS >> 4) (remember we do data << 4)
* - This works if we set vwidth = width, vheight = height, x = 0, y = 0.
* - I haven't managaged to make anything but 24 bit depth work, however the
* Linux source seems to use 16 bit?!
* - Sometimes the procedure described to get stuff on the screen doesn't
* work first time. I've hacked around this by repeating until it does work.
* - The two conditions for successfully acquiring a frame buffer are:
* - The data read from the mailbox (with the 4 least significant bits set
* to zero) is 0 (or 1 including the channel)
* - The pointer in the structure is non-zero after the mailbox read
* - Once we have the frame buffer, we can just write to it. The pixels (in
* 24 bit mode) are RGB ordered by y then x coordinate. The address of a
* subpixel is given by: y * pitch + x * 3 + rgb_channel, where rgb_channel
* is 0 for red, 1 for green, and 2 for blue.
*/

Note: the converting of the structure address is no longer needed if you use a later boot loaders.
There's also some updated info here: https://github.com/raspberrypi/firmware ... -interface

Any ? just ask.
Batteries not included, Some assembly required.
User avatar
Posts: 876
Joined: Wed May 16, 2012 6:32 pm
by tufty » Mon Aug 27, 2012 6:31 am
Right.

Dex has shown you how to get a framebuffer up.
You'll also need some code to place a bitmap on the screen at some predefined position (typically called 'bitblt'. This can be a very simple sequence of 'put32's, or, more efficiently, use dma.
Then you can write a primitive 'putc' which will have to keep track of the current character position, deal with special characters like tab, newline and carriage return, as well as scrolling the screen if you go 'off the bottom'.
You're best off using a simple, single spaced non-proportional bitmap font, it makes bitblt much easier to write. I wouldn't worry about composition (overlaying one bitmap over another using a specific operation) yet.
Printing is then a simple repetition of 'putc's.

Simon
Posts: 1454
Joined: Sun Sep 11, 2011 2:32 pm