[RTEMS bsp] raspberry pi mailbox and framebuffer implementation

Hi,

In order to communicate with GPU videocore, which control the early boot up and video output, I’ve implemented some structures and functions to simplify the work.

First of all, the common mailbox read/write functions which would be available in <bsp/mailbox.h>:

extern unsigned int  raspberrypi_mailbox_read(unsigned int channel);
extern void raspberrypi_mailbox_write(unsigned int channel, unsigned int data);

These two functions are the lower level functions to read/write the data from/to videocore.

extern unsigned int  raspberrypi_mailbox_read(unsigned int channel);
extern void raspberrypi_mailbox_write(unsigned int channel, unsigned int data);

In general, we have two mailboxes, and the mailbox 0 is what we use in most cases. channel 0 for Power management, channel 1 for Framebuffer, channel 2 for Virtual UART, channel 3 for VCHIQ, channel 4 for LEDs, channel 5 for Buttons, channel 6 for Touch screen, channel 8 for Property tags (ARM -> VC), channel 9 for Property tags (VC -> ARM). More details can be found on rpi firmware wiki.

One thing important to note, the address data that we pass to mailbox should be physical address instead of virtual address, which means that if L2 cache is enabled, the physical address= virtual address + 0x40000000, and this shift value should be 0xC0000000 if L2 cache is disabled.

Although not all details of mailbox are published or hacked, but we can already get the usage of framebuffer channel, and property tags (ARM->VC) from the wiki page or elinux.org.

In order to simplify the use of mailbox property tags, I’ve implemented some structures and functions.  To query or setup a property, we just need to create a structure with all necessary entries, pass the structure to the related operation function and then get the result from the structure.To allocate the framebuffer for exemple, all structures and operation functions are defined in <bsp/vc.h>

typedef struct
{
uint32_t align;
uint32_t base;
uint32_t size;
}bcm2835_allocate_buffer_entries;

int
bcm2835_mailbox_allocate_buffer(bcm2835_allocate_buffer_entries* _entries);

To allocate the framebuffer:

  bcm2835_allocate_buffer_entries allocate_buffer_entries;
allocate_buffer_entries.depth = 32;
bcm2835_mailbox_allocate_buffer(&allocate_buffer_entries);

Then the response of videocore will be retrieved and filled in the structure, which means, we will have the pointer to the framebuffer and its size from the item “base” and “size” of the structure allocate_buffer_entries.

For the moment, not all functions of property tags are implemented as not all of them are frequently used This can be completed in the future.

To allocate a framebuffer for the video output, we just need to well setup the display size, buffer size, color depth, pixel order, alpha mode, virtual offset, overscan, cursors etc, over the mailbox property tags interfaces. Since the mailbox framebuffer channel has been reported to be unstable in some cases, so we decide to use the property tags channel instead. Attention, to initialize framebuffer is a bit special, for all the related tags should be queued in the buffer. These tags shouldn’t be proceeded one after another.

Once we get the framebuffer’s pointer, we can write pixel color values to it for video output. From user space, we can also access the device /dev/fb and use ioctl to get the pointer , and play around the screen.

One problem is posed here about the memory table setup. As we have to active the memory pages that we need in the mm_config_table, I can’t figure out how the cpu choose the base address of framebuffer and it seems impossible to allocate the buffer to a given address. I’ve set up the base address and the length which would cover my situation, but I can’t make sure that this would cover all situations with other displays or rpis. So I invite other developpers to update the base value and the length value so that it would cover most cases. If you’ve found some message like this in kernel info output:

[#]fb_fix_screeninfo: smem_start : C100000
[#]fb_fix_screeninfo: smem_len : 12C000

and the video is freezed, try to check if the segement of memory from 0xC100000, with length 0x12C000 is covered in BCM2835_FBMEM_BASE with length of BCM2835_FBMEM_SIZE, defined in raspberrypi.h. When we try to write to the memory which is not activated in mm_config_table, all process would just freeze. If you are encountering this problem, you may modify the value of the two macros and update it. Normally for the same display the base address would always be the same if the configuration is not changed.

My works can be reviewed on github : https://github.com/yangqiao/rtems/tree/framebuffer

Have fun !

2 thoughts on “[RTEMS bsp] raspberry pi mailbox and framebuffer implementation

Leave a comment