-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Accessing mailboxes
This page is a stub for completion by someone who knows more than I about the subject.
Mailboxes facilitate communication between the ARM and the VideoCore. This page describes the procedure for accessing a mailbox. For a list of the available mailboxes, see here.
To read from a mailbox:
-
Read the status register until the empty flag is not set
-
Read data from the read register
-
If the lower four bits do not match the channel number desired then repeat from 1
-
The upper 28 bits are the returned data
To write to a mailbox
-
Read the status register until the full flag is not set
-
Write the data (shifted into the upper 28 bits) combined with the channel (in the lower four bits) to the write register
Memory barriers may be required around mailbox accesses, details on these should be added to this page (or the page for the particular mailbox/channel that requires them) by someone who knows the details.
This code is untested and is written for clarity rather than brevity or efficiency, but is provided for convenience.
#define MAIL_BASE 0xB880 // Base address for the mailbox registers
// This bit is set in the status register if there is no space to write into the mailbox
#define MAIL_FULL 0x80000000
// This bit is set in the status register if there is nothing to read from the mailbox
#define MAIL_EMPTY 0x40000000
uint32 ReadMailbox(byte channel)
{
// Loop until we receive something from the requested channel
for (;;)
{
while ((ReadMemMappedReg<uint32>(MAIL_BASE, StatusOffset) & MAIL_EMPTY) != 0)
{
// Wait for data
}
// Read the data
uint32 data = ReadMemMappedReg<uint32>(MAIL_BASE, ReadOffset);
byte readChannel = data & 0xF;
data >>= 4;
// Return it straight away if it's for the requested channel
if (readChannel == channel)
return data;
}
}
void WriteMailbox(byte channel, uint32 data)
{
while ((ReadMemMappedReg<uint32>(MAIL_BASE, StatusOffset) & MAIL_FULL) != 0)
{
// Wait for space
}
// Write the value to the requested channel
WriteMemMappedReg(MAIL_BASE, WriteOffset, (data << 4) | channel);
}
template<class T>
static T ReadMemMappedReg(size_t BaseAddress, size_t Offset)
{
return *reinterpret_cast<const T *>(0x20000000 + BaseAddress + Offset);
}
template<class T>
static void WriteMemMappedReg(size_t BaseAddress, size_t Offset, T Data)
{
*reinterpret_cast<T *>(0x20000000 + BaseAddress + Offset) = Data;
}