VideoCore mailboxes


17 posts
by blm768 » Thu Dec 06, 2012 7:36 am
For some reason, I'm having a really tough time getting any messages from the VideoCore mailboxes. Currently, I'm getting a mailbox value of 15, which doesn't even seem to be a used mailbox channel.

Here's the code I'm using:

Code: Select all
#define MAIL_RECV   (*(volatile uint*)0x2000B880)
#define MAIL_PEEK   (*(volatile uint*)0x2000B890)
#define MAIL_SEND   (*(volatile uint*)0x2000B8A0)
#define MAIL_STATUS (*(volatile uint*)0x2000B898)

static inline volatile int get_send_status() {
   return MAIL_STATUS & (1 << 31);
};

static inline void send_message(int mBox, int msg) {
   peripheral_memory_barrier();
   while(get_send_status()) {}
   MAIL_SEND = mBox | msg;
}

static inline int get_recv_status() {
   return MAIL_STATUS & (1 << 30);
}

static inline uint recv_message(int mBox) {
   uint msg;
   peripheral_memory_barrier();
   do {
      while(get_recv_status()) {}
      gpio_clear(16);
      busy_wait(500000);
      gpio_set(16);
      busy_wait(500000);
      msg = MAIL_RECV;
   } while(msg & 0xF != mBox);
   return msg & ~0xF;
}

void kmain() {
   send_message(1, (int)(&fb + 0x40000000));
   uint status = recv_message(15);
}


The variable fb is a pointer to the framebuffer descriptor struct. Peripheral_memory_barrier() is just the standard memory barrier for peripheral access, and busy_wait() just loops for a specified number of microseconds.

I'm curious as to why this might be happening. I don't think it's a cache issue; I've tried adding 0x40000000 to the mailbox registers, and I get exactly the same results. Can anyone see something wrong with my code?
Posts: 24
Joined: Sun Nov 18, 2012 6:13 am
by phil95 » Thu Dec 06, 2012 9:27 am
Hello
I think you have a problem in line:
send_message(1, (int)(&fb + 0x40000000));
&fb is a pointer to a struct;
&fb + n is a pointer to fb + n * sizeof (struct);
try:
send_message(1, (int)((unsigned long)(&fb) + 0x40000000));
Philippe
Posts: 105
Joined: Wed Sep 12, 2012 8:10 am
Location: Paris
by blm768 » Thu Dec 06, 2012 7:20 pm
phil95 wrote:Hello
I think you have a problem in line:
send_message(1, (int)(&fb + 0x40000000));
&fb is a pointer to a struct;
&fb + n is a pointer to fb + n * sizeof (struct);
try:
send_message(1, (int)((unsigned long)(&fb) + 0x40000000));
Philippe


Oh... duh! I should have caught that. :oops:

Unfortunately, I'm still having the same issue even after fixing that...
Posts: 24
Joined: Sun Nov 18, 2012 6:13 am
by phil95 » Fri Dec 07, 2012 8:08 am
Sorry, I think the line must be:
send_message(1, (int)(((unsigned long)(&fb) + 0x40000000)) >> 4);
Philippe
Posts: 105
Joined: Wed Sep 12, 2012 8:10 am
Location: Paris
by blm768 » Fri Dec 07, 2012 5:33 pm
phil95 wrote:Sorry, I think the line must be:
send_message(1, (int)(((unsigned long)(&fb) + 0x40000000)) >> 4);
Philippe


I don't think that's it; my send_message function doesn't do any shifting internally, just a bitwise OR. Shifting would make the address overlap the mailbox number.

I'm starting to wonder if something's wrong with my hardware; the mailbox value just doesn't make any sense.
Posts: 24
Joined: Sun Nov 18, 2012 6:13 am
by phil95 » Fri Dec 07, 2012 9:04 pm
Exact, my send_message reshift the parameter left of 4 befor the or.with id.
Are you sure, low nibble of &fb is null ?
Philippe
Posts: 105
Joined: Wed Sep 12, 2012 8:10 am
Location: Paris
by blm768 » Sat Dec 08, 2012 2:32 am
phil95 wrote:Exact, my send_message reshift the parameter left of 4 befor the or.with id.
Are you sure, low nibble of &fb is null ?
Philippe


It is; I set an alignment attribute on it, and I verified in the disassembly that it's 16-byte aligned.
Posts: 24
Joined: Sun Nov 18, 2012 6:13 am
by phil95 » Sat Dec 08, 2012 9:23 am
How is initialised your fb struct ?
Philippe
Posts: 105
Joined: Wed Sep 12, 2012 8:10 am
Location: Paris
by blm768 » Sat Dec 08, 2012 10:42 am
Here's the code for my struct (both definition and initialization):

Code: Select all
typedef struct {
   uint width, height;
   uint vWidth, vHeight;
   volatile uint pitch;
   uint depth;
   uint x, y;
   color_rgb* volatile buffer;
   volatile size_t size;
} __attribute__((__aligned__(16))) FramebufferInfo;

FramebufferInfo fb = {
   1024, 768,
   1024, 768,
   0, 32,
   0, 0,
   NULL, 0};
Posts: 24
Joined: Sun Nov 18, 2012 6:13 am
by phil95 » Sat Dec 08, 2012 1:18 pm
Ok I have tested your prog:
I have removed:
gpio_clear and gpio_set
peripheral_memory_barrier
I have replaced busy_wait with my own tempo routines
I have added printf and dump (I'm using my own libraries)
And your prog is working:
08/12/12 14:08:19
C'est parti ...
Mon kiki ...
0c00000000000000 0c000000
C'est parti ...
Mon kiki ...
MemInit()
_stext=0x8000,_etext=0xa45c
_sdata=0xa750,_edata=0xa794
_sbss=0xa794,_ebss=0xa7a8
Allocation de 0xa7b0 a 0xc000000
0000a750 00 04 00 00 00 03 00 00 00 04 00 00 00 03 00 00 ................
0000a760 00 00 00 00 20 00 00 00 00 00 00 00 00 00 00 00 .... ...........
0000a770 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................

avant send_message()
apres send_message()
0000a750 00 04 00 00 00 03 00 00 00 04 00 00 00 03 00 00 ................
0000a760 00 00 00 00 20 00 00 00 00 00 00 00 00 00 00 00 .... ...........
0000a770 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................

avant recv_message_message()
apres recv_message()
0000a750 00 04 00 00 00 03 00 00 00 04 00 00 00 03 00 00 ................
0000a760 00 10 00 00 20 00 00 00 00 00 00 00 00 00 00 00 .... ...........
0000a770 00 50 38 4d 00 00 30 00 00 00 00 00 00 00 00 00 .P8M..0.........

Address 0xa770 receive the pixel buffer address ...

I think the routine peripheral_memory_barrier is the origin of yours problems ...
(I don't have the source ...)

Philippe
Posts: 105
Joined: Wed Sep 12, 2012 8:10 am
Location: Paris
by blm768 » Sun Dec 09, 2012 3:04 am
I tried removing the routine, but I'm still getting the same results. Could you post the code you're using?
Posts: 24
Joined: Sun Nov 18, 2012 6:13 am
by phil95 » Sun Dec 09, 2012 8:36 am
Hello,
Source code used
Code: Select all
#include "..\\mmt.h"

void   MailBoxWrite(U32 v, U32 id);
U32    MailBoxRead(U32 id);
U32    MailBoxStatus();


typedef unsigned int uint;
typedef unsigned int color_rgb;

typedef struct {
   uint width, height;
   uint vWidth, vHeight;
   volatile uint pitch;
   uint depth;
   uint x, y;
   color_rgb* volatile buffer;
   volatile size_t size;

} __attribute__((__aligned__(16))) FramebufferInfo;

FramebufferInfo fb = {
   1024, 768,
   1024, 768,
   0, 32,
   0, 0,
   (uint *)NULL, 0};




#define MAIL_RECV   (*(volatile uint*)0x2000B880)
#define MAIL_PEEK   (*(volatile uint*)0x2000B890)
#define MAIL_SEND   (*(volatile uint*)0x2000B8A0)
#define MAIL_STATUS (*(volatile uint*)0x2000B898)

static inline volatile int get_send_status() {
   return MAIL_STATUS & (1 << 31);
};

static inline void send_message(int mBox, int msg) {
//    peripheral_memory_barrier();
   while(get_send_status()) {}
   MAIL_SEND = mBox | msg;
}

static inline int get_recv_status() {
   return MAIL_STATUS & (1 << 30);
}

static inline uint recv_message(int mBox) {
   uint msg;
//    peripheral_memory_barrier();
   do {
      while(get_recv_status()) {}
//      gpio_clear(16);
//      busy_wait(500000);
     TempoMs(50);
//      gpio_set(16);
//      busy_wait(500000);
     TempoMs(50);
      msg = MAIL_RECV;
   } while(msg & 0xF != mBox);
   return msg & ~0xF;
}

void kmain() {
   send_message(1, (int)((U32)&fb + 0x40000000));
   uint status = recv_message(15);
}




   int main()
//   ******
{
   U32    i, j;
   bool   b;

   LedInit();
   Usart0Init(115200);

   printf("C'est parti ...\n");
   printf("Mon kiki ...\n");
   MemInit();


   Dump8((U32)&fb, sizeof(fb));
printf("\n");
//    send_message(1, (int)(&fb + 0x40000000));
   printf("avant send_message()\n");
   send_message(1, (int)((uint)&fb + 0x40000000));
//    MailBoxWrite(((U32)&fb + 0x40000000) >> 4, 1);
   printf("apres send_message()\n");
   Dump8((U32)&fb, sizeof(fb));
printf("\n");
   printf("avant recv_message_message()\n");
   uint status = recv_message(15);
//    uint status = MailBoxRead(1);
   printf("apres recv_message()\n");
   Dump8((U32)&fb, sizeof(fb));
printf("\n");



   while(true)
      ;

}

I can send kernel.img if you want
Philippe
Posts: 105
Joined: Wed Sep 12, 2012 8:10 am
Location: Paris
by blm768 » Sun Dec 09, 2012 12:15 pm
Hmm... so it's working with the recv_message function being given an argument of 15 when it theoretically should be 1...

I'll have to take a look at that pointer. If it's being set, something really strange is going on.

How do you implement your MailBoxRead() function?
Posts: 24
Joined: Sun Nov 18, 2012 6:13 am
by phil95 » Sun Dec 09, 2012 6:28 pm
Effectively, I have make a copy / paste of your soft
If I put 1 insteed 15, it is not working.
But if I put
while ((msg & 0xF) != mBox)
It is working with 1 ...
Can you confirm ?

Sources of my "MailBox.c"
Code: Select all
#include "..\\mmt.h"
#ifdef RPI



void   MemoryBarrier();
void   SynchronisationBarrier();
void   DataCacheFlush();
void   DataSynchronisationBarrier();
void   MailBoxWrite(U32 v, U32 id);
U32    MailBoxRead(U32 id);
U32    MailBoxStatus();



void   MailBoxWrite(U32 v, U32 id)
//      ***************************
{
   U32 s;

   MemoryBarrier();
   DataCacheFlush();
   while (true)
   {
      s = MailBoxStatus();
      if ((s & 0x80000000) == 0)
         break;
   }
   *((PU32)(0x20000000 + 0xb880 + 0x0 + 0x20)) = (v << 4) | id;
   MemoryBarrier();
}



U32    MailBoxRead(U32 id)
//      *******************
{
   U32 s;
   volatile U32 v;

   MemoryBarrier();
   DataCacheFlush();
   while (true)
   {
      while (true)
      {
         s = MailBoxStatus();
         if ((s & 0x40000000) == 0)
            break;
      }
      v = *((PU32)(0x20000000 + 0xb880 + 0x0 + 0x0));
      if ((v & 0xf) == id)
         break;
   }
   MemoryBarrier();
//     printf("v=0x%08x\n", v);
   return ((v >> 4) & 0x0fffffff);
//     return v;
}



U32    MailBoxStatus()
//      ***************
{
   volatile U32 v;
   MemoryBarrier();
   DataCacheFlush();
   v = *((PU32)(0x20000000 + 0xb880 + 0x0 + 0x18));
//     printf("status=0x%x\n", v);
   MemoryBarrier();
   return v;
}

#endif

MemoryBarrier(), DataCacheFlush() are the classicals fu,ctions
Philippe
Posts: 105
Joined: Wed Sep 12, 2012 8:10 am
Location: Paris
by blm768 » Sun Dec 09, 2012 7:15 pm
Oh... it's an operator precedence issue. I see what it's doing now.

Thanks for your help!
Posts: 24
Joined: Sun Nov 18, 2012 6:13 am
by mrvn » Sat Jan 19, 2013 11:52 pm
phil95 wrote:MemoryBarrier(), DataCacheFlush() are the classicals fu,ctions
Philippe


Would you mind sharing them?

MfG
Mrvn
Posts: 27
Joined: Wed Jan 09, 2013 6:50 pm
by phil95 » Sun Jan 20, 2013 11:21 am
Hereafter are the C synchronisation functions used
Philippe


__attribute__((naked)) void MemoryBarrier()
// ********************
{
__asm("mov r0, #0");
__asm("mcr p15, #0, r0, c7, c10, #5");
__asm("mov pc, lr");
}

__attribute__((naked)) void DataCacheFlush()
// *********************
{
__asm("mov r0, #0");
__asm("mcr p15, #0, r0, c7, c14, #0");
__asm("mov pc, lr");
}



__attribute__((naked)) void SynchronisationBarrier()
// *****************************
{
__asm("mov r0, #0");
__asm("mcr p15, #0, r0, c7, c10, #4");
__asm("mov pc, lr");
}

__attribute__((naked)) void DataSynchronisationBarrier()
// *********************************
{
__asm("stmfd sp!, {r0-r8,r12,lr}");
__asm("mcr p15, #0, ip, c7, c5, #0");
__asm("mcr p15, #0, ip, c7, c5, #6");
__asm("mcr p15, #0, ip, c7, c10, #4");
__asm("mcr p15, #0, ip, c7, c10, #4");
__asm("ldmfd sp!, {r0-r8,r12,pc}");
}
Posts: 105
Joined: Wed Sep 12, 2012 8:10 am
Location: Paris