rtems, gsoc, libbsd,

Writing an RTEMS LibBSD app using framebuffer device

Vijay K. Banerjee (thelunatic) Vijay K. Banerjee (thelunatic) Jul 23, 2019 · 3 mins read
Writing an RTEMS LibBSD app using framebuffer device
Share this

While porting the framebuffer drivers from FreeBSD to RTEMS, the very first requirement was to have something simple to test the framebuffer. And the app should be very simple and should only use the fb device instead of anything fancy, to make it simple to debug. My search for such an app ended when I found this app from the freebsd list, written by a freeBSD : https://github.com/gonzoua/tslib/blob/freebsd/tests/fbutils-bsd.c

Making it a standalone libbsd app

Once some reference code was found, my first step was to remove the unnecessary parts of the code like font related stuffs, so that I only have a simple polygon drawing app that will interact with the fb device. In this section I’ll do a walk through of the parts of the app that I wrote for framebuffer testing.

The sample app can be found here

The Init function

The init function is where the execution of the application will start and hence it’s the first place to look for, to understand the app.

	exit_code = bbb_register_i2c_0();
	assert(exit_code == 0);
	sc = rtems_bsd_initialize();
	assert(sc == RTEMS_SUCCESSFUL);
	exit_code = open_framebuffer();
	assert(exit_code == 0);
	setcolor (4, 0xff0000);
	rect(100, 200, 200, 300, 4);
	exit_code = close_framebuffer();

The above is a snippet taken from the Init function and the sequence of the calls is very important to notice. The first call bbb_register_i2c_0() is very important and we cannot afford to leave this out. The bbb register call is from the RTEMS I2C framework API and hence the use of it is interesting in the libBSD application. This could be possible to use the RTEMS I2C interface through LibBSD because of the i2c adaptation layer that I discussed in another article. After the i2c-0 device is registered by the RTEMS, we can call the rtems_bsd_initialize() function which will initialize the libbsd module, including our am335x_lcd and TDA drivers which are responsible for handling the lcd and the HDMI framer through the i2c interface.

The further calls are for opening the framebuffer device, drawing a rectangle and freeing the memory. Below I paste a snippet from the open_framebuffer() function and discuss the important parts. It’s important to note that the framebuffer driver is incapable of reading or writing directly to the fb0 device and an mmap call is necessary to do that. During the time of writing this article the mmap has not been merged to upstream LibBSD, I have written a patch for the same and hope to get the mmap support added to LibBSD soon.

    int line_length;

	fb_fd = open(fbdevice, O_RDWR);
	if (fb_fd == -1) {
		perror("open fbdevice");
		return -1;

	if (ioctl(fb_fd, FBIOGTYPE, &fb) != 0) {
		return -1;

	if (ioctl(fb_fd, FBIO_GETLINEWIDTH, &line_length) != 0) {
		return -1;

	fbsize = ((int) line_length*yres + pagemask) & ~pagemask;

	fbuffer = (unsigned char *)mmap(0, fbsize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
	if (fbuffer == (unsigned char *)-1) {
		perror("mmap framebuffer");
		return -1;
	memset(fbuffer,0, fbsize);

After the open call, the first ioctl with FBIOGTYPE flag, is used to to see the type of framebuffer present and thereby to select the appropriate mode. The second ioctl call gets the screen width from the set resolution and stores it in line_length. What follows is the mmap call that maps the framebuffer to the memory and hence I/O can be done on the fb0 device through simple assignments.

The app could not yet be tested on libbsd due to some hardware initialization bugs in the framebuffer port but the app has been tested on FreeBSD 12-RELEASE image and hence I’m hopeful that it’ll work with the ported drivers as well. As always, I’m always up for any discussion or questions regarding the topics discussed in the article and will also post an update when it runs on RTEMS.

Thanks for stopping by. ;-)