blm768
Posts: 24
Joined: Sun Nov 18, 2012 6:13 am

VideoCore mailboxes

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?

phil95
Posts: 141
Joined: Wed Sep 12, 2012 8:10 am
Location: Paris

Re: VideoCore mailboxes

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

blm768
Posts: 24
Joined: Sun Nov 18, 2012 6:13 am

Re: VideoCore mailboxes

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...

phil95
Posts: 141
Joined: Wed Sep 12, 2012 8:10 am
Location: Paris

Re: VideoCore mailboxes

Fri Dec 07, 2012 8:08 am

Sorry, I think the line must be:
send_message(1, (int)(((unsigned long)(&fb) + 0x40000000)) >> 4);
Philippe

blm768
Posts: 24
Joined: Sun Nov 18, 2012 6:13 am

Re: VideoCore mailboxes

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.

phil95
Posts: 141
Joined: Wed Sep 12, 2012 8:10 am
Location: Paris

Re: VideoCore mailboxes

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

blm768
Posts: 24
Joined: Sun Nov 18, 2012 6:13 am

Re: VideoCore mailboxes

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.

phil95
Posts: 141
Joined: Wed Sep 12, 2012 8:10 am
Location: Paris

Re: VideoCore mailboxes

Sat Dec 08, 2012 9:23 am

How is initialised your fb struct ?
Philippe

blm768
Posts: 24
Joined: Sun Nov 18, 2012 6:13 am

Re: VideoCore mailboxes

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};

phil95
Posts: 141
Joined: Wed Sep 12, 2012 8:10 am
Location: Paris

Re: VideoCore mailboxes

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

blm768
Posts: 24
Joined: Sun Nov 18, 2012 6:13 am

Re: VideoCore mailboxes

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?

phil95
Posts: 141
Joined: Wed Sep 12, 2012 8:10 am
Location: Paris

Re: VideoCore mailboxes

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

blm768
Posts: 24
Joined: Sun Nov 18, 2012 6:13 am

Re: VideoCore mailboxes

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?

phil95
Posts: 141
Joined: Wed Sep 12, 2012 8:10 am
Location: Paris

Re: VideoCore mailboxes

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

blm768
Posts: 24
Joined: Sun Nov 18, 2012 6:13 am

Re: VideoCore mailboxes

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!

mrvn
Posts: 58
Joined: Wed Jan 09, 2013 6:50 pm

Re: VideoCore mailboxes

Sat Jan 19, 2013 11:52 pm

phil95 wrote: MemoryBarrier(), DataCacheFlush() are the classicals fu,ctions
Philippe
Would you mind sharing them?

MfG
Mrvn

phil95
Posts: 141
Joined: Wed Sep 12, 2012 8:10 am
Location: Paris

Re: VideoCore mailboxes

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}");
}

Return to “Bare metal”

Who is online

Users browsing this forum: No registered users and 3 guests