adamransom
Posts: 3
Joined: Sun Nov 13, 2016 7:01 am

Mailbox clarifications

Sun Nov 13, 2016 7:24 am

I've been playing around with some bare-metal examples on the Raspberry Pi 3 for a while now and considering the changes to the ACT LED, the first thing you need to do is implement mailbox communication with the VideoCore.

Whilst the mailbox documentation (https://github.com/raspberrypi/firmware/wiki/Mailboxes) is a great start (as are all the implementations I've found whilst browsing source code), I would still like some things clarified. Now, I have manged to "correctly" implement the mailbox communication (given I can successfully control the ACT LED), but still feel confused about a few things.

The wiki states that the ARM should never write to mailbox 0 and never read from mailbox 1. In my head I model this as 2 separate mailboxes (in a real-world sense): Mailbox 0 being ours (ARM) and Mailbox 1 being theirs (VideoCore). Before sending a message, we should check that their mailbox is not full (check mailbox 1 status at offset 0x38). When reading a message, we should check that our mailbox is not empty (check mailbox 0 status at offset 0x18). However, all implementations seem to only check mailbox 0 status before both reading and writing (some places even stating that mailbox 0 write is the same as mailbox 1 read).

As I can't find any written documentation on mailboxes besides the wiki, I am basically wondering how I should be thinking about the mailboxes logically and how is it all being treated from the GPU side?

User avatar
Ultibo
Posts: 137
Joined: Wed Sep 30, 2015 10:29 am
Location: Australia
Contact: Website

Re: Mailbox clarifications

Tue Nov 15, 2016 1:53 am

adamransom wrote:The wiki states that the ARM should never write to mailbox 0 and never read from mailbox 1.
That's an interesting statement, I've never noticed it before and it conflicts with the fact that all of the working implementations only use Mailbox 0 (Read and Write) so it's possible that the documentation is in error or just means something different to what it seems to say.

Since only mailbox 0 is documented (and only a small number of the available channels) then it is hard to make any real assumptions about mailbox 1 and the usage of it.
adamransom wrote:(some places even stating that mailbox 0 write is the same as mailbox 1 read).
This could be correct, remember this is a peripheral and not memory so it has logic behind the address. It could very well use the same address with different purpose depending on whether you read or write.
adamransom wrote:I am basically wondering how I should be thinking about the mailboxes logically and how is it all being treated from the GPU side?
I don't know what is happening on the GPU side but you can think of the mailbox a bit like a UART really, you 'send' information by writing to it, 'receive' information by reading from it and you check the status register to see if there is something to read or space available to write.
Ultibo.org | Make something amazing
https://ultibo.org

Threads, multi-core, OpenGL, Camera, FAT, NTFS, TCP/IP, USB and more in 3MB with 2 second boot!

adamransom
Posts: 3
Joined: Sun Nov 13, 2016 7:01 am

Re: Mailbox clarifications

Tue Nov 15, 2016 7:28 am

Thanks for your reply!
all of the working implementations only use Mailbox 0 (Read and Write)
When those implementations write to Mailbox 0, they use offset 0x20, which according to the wiki is Mailbox 1's read/write. I haven't seen any implementations using offset 0x0 (Mailbox 0 read/write) for writing. This leads me to also think that the wiki may be worded a little confusingly.

Maybe it is better to think that we are only dealing with Mailbox 0, as that is the only one which is documented. I'm just slightly confused about the labelling of the registers/offsets in the wiki.

rst
Posts: 316
Joined: Sat Apr 20, 2013 6:42 pm
Location: Germany

Re: Mailbox clarifications

Tue Nov 15, 2016 4:40 pm

I did the following test:

Code: Select all

	/* prepare property tag buffer (get board revision) at nBufferAddress) */

	/* variable declarations */

	do
	{
		nTry++;

		write32 (MAILBOX_BASE + 0x20, 0x08 | nBufferAddress);

		nMailBox0Status = read32 (MAILBOX_BASE + 0x18);
		nMailBox1Status = read32 (MAILBOX_BASE + 0x38);
	}
	while (   !(nMailBox0Status & 0x80000000)
	       && !(nMailBox1Status & 0x80000000));

	/* show nMailBox0Status, nMailBox2Status and nTry */
Result: The while loop has been left because the FULL bit in nMailBox1Status is set after 8 tries (= FIFO size according to the Wiki article).

That means the status register of mailbox 1 at offset 0x38 is the right one, if one wants to check if the write FIFO (at ARM side) is full before writing to it.

Some implementations (including my own) use the status register of mailbox 0 instead. That's not a big problem because normally the FIFO is never completely filled and so the mailbox write function is always able to continue. But it seems to be wrong.

adamransom
Posts: 3
Joined: Sun Nov 13, 2016 7:01 am

Re: Mailbox clarifications

Wed Nov 16, 2016 2:30 am

Thanks rst, I actually did the same experiment (slightly differently) and came to the same conclusion. I also assumed that the common uses of mailboxes wont be filling them up, so checking for the wrong status (or checking at all) doesn't really matter.

However, I would like to implement it correctly if possible, but I was just unsure what "correctly" was as there is conflicting information about the place and was hoping for someone with more knowledge than I to help out. It's just a little odd that nearly all implementations only deal with Mailbox 0's status.

Thanks for you input!

Return to “Bare metal, Assembly language”