Bare metal framebuffer in C


44 posts   Page 2 of 2   1, 2
by DexOS » Sun Sep 30, 2012 7:52 pm
mvdhoning wrote:
DexOS wrote:Do you add 1 to the write mailbox 0x2000B8A0 +1 ?, i may of just mist it.

He does not seem to do that ( i don't do that either ) is there a reason why we should not use MAILBOX0_WRITE?

From my reading of the doc's, bit here, bit there, when i first started coding the PI, you need that.
MB_WRITE: dw $2000B8A1 ; PERIPHERAL_BASE + MAIL_BASE + MAIL_WRITE + MAIL_FB

MAIL_FB = 1
Batteries not included, Some assembly required.
User avatar
Posts: 851
Joined: Wed May 16, 2012 6:32 pm
by phil95 » Sun Sep 30, 2012 8:37 pm
Hello,
the write is at address 2000B8A0
MAIL_FB is put in the value writed thus
*0x2000B8A0 = (adr & 0xfffffff0) | MAIL_FB:
It is forbidden to write a DW in an address not multiple of 4;
Philippe
Posts: 105
Joined: Wed Sep 12, 2012 8:10 am
Location: Paris
by BrianW » Thu Oct 04, 2012 12:05 pm
BrianW wrote:I'm wondering a little whether this is the right approach, or if I should be reading the screen size from the ATAGS structure and using that.
It would seem from further experimentation that the answer to this is "no".

The ATAGS data filled in by the bootloader only has ATAG_CORE (though it doesn't seem to properly add the optional extra fields), ATAG_MEM, ATAG_CMDLINE and ATAG_INITRD2 if a ramdisk is specified in config.txt

The command line supplied through ATAGS contains additional data (not present in cmdline.txt and not included in the mailbox property request for the command line), including the serial number, and framebuffer width/height, but nothing which isn't available via the mailbox property interface.
Posts: 77
Joined: Sun Jul 29, 2012 9:03 pm
by mvdhoning » Sun Oct 07, 2012 1:20 pm
now i get something on screen, but ...

i have to follow brians way of using channel 8. The way with channel 1 and the record still wont work for me.

and it does not look good, the pixels drawn to the left side of the screen are drawn bright and the pixels next to that are dimmer of color also every pixel there appears to be a black gap inbetween.

now i am drawing in a not so clever way with just adding 2 to the current position in the framebuffer.
but more clever way give the same end result.

if i just take over the pixelcalculation from brian i get something that draws lines made out of \ on the screen. with some large gaps between the lines. wierd.

on a side note i may have destroyed the sdcard slot on my rpi as on taking out the sdcard a bit of the sd card decided to stay inside the rpi sdcard slot.
Posts: 18
Joined: Fri Sep 14, 2012 2:47 pm
by DexOS » Sun Oct 07, 2012 4:00 pm
To better understand what is going on you need to know if its your code, or your firmware (boot loaders) as they are changing all the time.

Try my kernel.img to see if it works, you can get it here
http://www.dex-os.com/MinDos/PiDexOS.zip
Then let me know.

Also hope you SD slot is ok, but i use a micro sd card with adapter like this
Image

This way your not risking the pi sd slot, just the adapters, plus the sd slot on my PI was very stiff, the micro sd is much smoother.
Batteries not included, Some assembly required.
User avatar
Posts: 851
Joined: Wed May 16, 2012 6:32 pm
by mvdhoning » Sun Oct 07, 2012 4:29 pm
thanks for the hint on the sd card adapter i should have bought one earlier.

but must be me doing something wrong i am sure :-)

i tried your kernel.img and it just shows your logo and 2 buttons fine.

instead of an 16 bit mode i now tried a 1024x768 24 bit mode.

and wierdly enough it shows red green bleu pattern on screen and not something white'ish.

some code:
Code: Select all
color := $FE;
addr:=0;
for y := 0 to (768-1) do
  for x := 0 to (1024-1) do
    begin
       tempfb := pointer(longword(framebufferbase) + addr);
       tempfb^ := byte(color);
       addr:=addr+1;
       tempfb := pointer(longword(framebufferbase) + addr);
       tempfb^ := byte(color);
       addr:=addr+1;
       tempfb := pointer(longword(framebufferbase) + addr);
       tempfb^ := byte(color);
       addr:=addr+1;
    end;


yes i know i dont do anything with x and y.

also found out what pitch is about (pitch divided by width gives bytes per pixel)
Posts: 18
Joined: Fri Sep 14, 2012 2:47 pm
by mvdhoning » Sun Oct 07, 2012 5:51 pm
:oops:

i made tempfb a pointer to longword and not a pointer to a byte

now i get a white'ish screen as expected.
Posts: 18
Joined: Fri Sep 14, 2012 2:47 pm
by DexOS » Sun Oct 07, 2012 7:30 pm
mvdhoning wrote::oops:

i made tempfb a pointer to longword and not a pointer to a byte

now i get a white'ish screen as expected.

So are you OK now or do you still need help ?

Ps: Did you not have a usb keyboard plugged in to the PI when test my kernel.img ?, it works with about 40% of keyboards.
Left and right arrow key and enter, for the menu and any key in the cli.
Batteries not included, Some assembly required.
User avatar
Posts: 851
Joined: Wed May 16, 2012 6:32 pm
by mvdhoning » Mon Oct 08, 2012 5:51 pm
i am ok now as for as drawing on the frame-buffer goes. somehow writing a byte as an longword gave some unwanted side effect as that overwrote some previously written values. in order to get writing to a 24 bit mode working (3 bytes) i introduced a packed record as there is no native type in freepascal that is 3 bytes wide.

Code: Select all
TRGB = packed record R, G, B: Byte; end;


next week i will try to init the frame-buffer again via the record and channel 1.

@dexos had not yet tried to use your kernel with a keyboard. did that this evening.
and both my usb keyboards gave no sign of life. one is a apple keyboard (small one) the other is one from the ps2 'homebrew' dev kit.
Posts: 18
Joined: Fri Sep 14, 2012 2:47 pm
by DexOS » Mon Oct 08, 2012 7:44 pm
mvdhoning wrote:i am ok now as for as drawing on the frame-buffer goes. somehow writing a byte as an longword gave some unwanted side effect as that overwrote some previously written values. in order to get writing to a 24 bit mode working (3 bytes) i introduced a packed record as there is no native type in freepascal that is 3 bytes wide.

Code: Select all
TRGB = packed record R, G, B: Byte; end;


next week i will try to init the frame-buffer again via the record and channel 1.

@dexos had not yet tried to use your kernel with a keyboard. did that this evening.
and both my usb keyboards gave no sign of life. one is a apple keyboard (small one) the other is one from the ps2 'homebrew' dev kit.

Thanks for the info, one thing i would do is use 32bit mode as it makes your life much easier also i use a off screen buffer to write to, then have a fast dump buffer to screen function.
Batteries not included, Some assembly required.
User avatar
Posts: 851
Joined: Wed May 16, 2012 6:32 pm
by Dasaan » Wed Oct 10, 2012 12:02 am
Using a cut down version of Brian's code I've got a basic framebuffer working to the point where I can set individual pixel colours reasonably reliably.

The only issue I've got now is that a second or so after drawing the final pixel the screen goes black as through switched off. Oddly if I set the framebuffer to a lower resolution and set the same pixels then display stays 'on'. Anyone seen this before or got any ideas what's going wrong?

It's mainly because of the disappearing display issue that I say 'reasonably reliably' above, the image doesn't stick about long enough to be 100% sure the pixels are exactly where I thought I was putting them.

I've attached a copy of the code I'm using for anyone that's interested.
Attachments
07_Screen02v2.zip
(10.33 KiB) Downloaded 109 times
Posts: 6
Joined: Mon Sep 24, 2012 6:34 pm
by gertk » Fri Oct 26, 2012 8:23 pm
For 16 bit depth I modified the DrawPixel routine to this:

Code: Select all
VOID DrawPixel(UINT32 x, UINT32 y, UINT16 colour)
{
   VUINT16 *ptr;
   UINT32 offset;
   
   offset = (y * fb_info.Pitch) + (x<<1);
   ptr = (UINT16 *)(fb_info.Pointer + offset);
   *ptr = colour;
   
   return;
}


The (X<<1) multiplies the X offset by two otherwise you will end up having bytewise offsets.
After some trying I ended up with this:
very_small_2012-10-26 21.49.55.jpg
pixel, line , circle and a VGA font
very_small_2012-10-26 21.49.55.jpg (44.5 KiB) Viewed 1149 times
Posts: 47
Joined: Mon Aug 29, 2011 9:08 am
by fkpwolf » Sat Nov 03, 2012 9:36 am
jojopi wrote:
SupremeSpod wrote:Just a quick question, is it possible to use your code to obtain a framebuffer from code that is running under raspbian rather than "bare metal"?
In Linux you can use the generic framebuffer interface, which is portable across multiple platforms. In the link below, ignore the first nine steps and skip straight to the example program in step10. It works perfectly on a Pi (although it could do with including <stdlib.h> to remove the warning about exit()).

http://web.njit.edu/all_topics/Prog_Lan ... howto.html


I gave a try to the howto and succeeded. Cool!

So what's the different between the way of the howto used and the way of your "bare metal"?
Posts: 2
Joined: Sat Nov 03, 2012 9:27 am
by gertk » Sat Nov 03, 2012 2:23 pm
fkpwolf wrote:
jojopi wrote:
I gave a try to the howto and succeeded. Cool!

So what's the different between the way of the howto used and the way of your "bare metal"?


The difference is the OS :) In bare metal mode there is no OS active, just the program you have named kernel.img
The boot time is nearly instant (aside from the HDMI handshake time....) as the file 'kernel.img' is the first thing that is loaded into the Pi from the SD card.
Bare Metal has advantages and disadvantages:

advantage: you have complete control over the hardware

disadvantage: you need to find out how to control the hardware :)
Posts: 47
Joined: Mon Aug 29, 2011 9:08 am
by fkpwolf » Mon Nov 05, 2012 3:29 pm
gertk wrote:
fkpwolf wrote:
jojopi wrote:
I gave a try to the howto and succeeded. Cool!

So what's the different between the way of the howto used and the way of your "bare metal"?


The difference is the OS :) In bare metal mode there is no OS active, just the program you have named kernel.img
The boot time is nearly instant (aside from the HDMI handshake time....) as the file 'kernel.img' is the first thing that is loaded into the Pi from the SD card.
Bare Metal has advantages and disadvantages:

advantage: you have complete control over the hardware

disadvantage: you need to find out how to control the hardware :)


Oh, I see. "bare metal" means there is no linux kernel, some like a AVR MCU...
Posts: 2
Joined: Sat Nov 03, 2012 9:27 am
by poglad » Wed Nov 07, 2012 9:31 am
Thanks for all this, have bookmarked this thread! Yes... one of the reasons I'd like to have a play with bare metal is because I used to have fun programming the Game Boy Color - specifically because there was no operating system! :D
User avatar
Posts: 102
Joined: Tue Jul 31, 2012 8:47 am
Location: Aberdeen, Scotland
by Vern » Fri Dec 14, 2012 9:28 pm
I stumbled upon this forum looking for answers regarding direct frame buffer access under Linux. The following FreePascal code was run under Ubuntu 12.04 , but perhaps some of the issues are the same regardless of the CPU .

When the program below is run , everything appears correct , but nothing is written to the screen , and I wonder if the latest kernel version have buried the graphics frame buffer inside the kernel and /dev/fb0 does nothing.
Posts: 2
Joined: Fri Dec 14, 2012 7:56 pm
by -rst- » Mon Dec 17, 2012 12:42 pm
Vern wrote:I stumbled upon this forum looking for answers regarding direct frame buffer access under Linux. The following FreePascal code was run under Ubuntu 12.04 , but perhaps some of the issues are the same regardless of the CPU .

When the program below is run , everything appears correct , but nothing is written to the screen , and I wonder if the latest kernel version have buried the graphics frame buffer inside the kernel and /dev/fb0 does nothing.


Not sure about Ubuntu and FreePascal, but at least on Raspbian the /dev/fb0 interface works fine using for example the code from step 10 in this http://web.njit.edu/all_topics/Prog_Lan ... howto.html .
http://raspberrycompote.blogspot.com/ - Low-level graphics and 'Coding Gold Dust'
Posts: 893
Joined: Thu Nov 01, 2012 12:12 pm
Location: Dublin, Ireland
by Vern » Mon Dec 17, 2012 11:49 pm
Thanks ... that is what I followed, but had to do a 2nd ioctl() to ACTIVATE the frame buffer , then it worked.

/* Refresh buffer manually */
vi.activate |= FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
if(0 > ioctl(fd, FBIOPUT_VSCREENINFO, &vi)) {
printf("Failed to refresh\n");
return -1;
}
Posts: 2
Joined: Fri Dec 14, 2012 7:56 pm