Page 1 of 1

Baking PI in C (Screen 01 issues)

Posted: Tue Jul 23, 2013 9:10 pm
by simong
Hola fellow Rasperians

I'm gone through Lesson 1-7 in assembly (and it all works woo!), so I figured I'd try to
do the same now, but in C. So far I've successfully taken command of the LED, so I've got something working at least.
My problems starts with Lesson 6 Screen 01, I have with the usage of the LED managed to determine that
my mailboxRead() function gets stuck, however I can't for the life of me figure out why.

I am a little bit confused as to how the whole "storing the address of a c variable at the correct address (in the mailbox) works.
The code is pretty long and messy, so I'll try to just ask the things (I think) I'm struggling with.

To write to the mailbox, I do this:

Code: Select all

unsigned int info[256] __attribute__((aligned (16)));
info[0] = 1024;
info[1] = 768;
info[2] = 1024;
info[3] = 768;

// ... omitted the rest of the struct for brevity ....
unsigned int *mailboxStatus= (unsigned int *)(0x2000b898);
while(*mailboxStatus & MAILBOX_FULL){
}

unsigned int* mailboxWrite = (unsigned int *)0x2000b8a0;
*mailboxWrite = ((unsigned int)info + 0x40000000) | 1; // Write to channel 1
I feel like I might've gone wrong here already, I know these addresses work in assembly
and as far as I can tell I'm using the same logic as well.

Might be wondering what my mailboxRead function looks like as I mentioned it gets stuck there:

Code: Select all

unsigned int mailbox_Read(char channel){
	unsigned int data = 0;
	unsigned int* mailboxStatus = (unsigned int *)(0x2000b898);
	while(1){
		while (*mailboxStatus & 0x40000000){
		}

		data = *(unsigned int*) 0x2000B880;
		if((data & 0xF) == channel)
		{
			break; 
		}
	}
}
I'm not even sure if I can just access the mailbox like this.
Any pointers/ideas are greatly appreciated, thank you. :-)
(Sorry for a long first post by the way, I tried to keep it short!)

// Simon

Re: Baking PI in C (Screen 01 issues)

Posted: Wed Jul 24, 2013 12:34 am
by Pik
You need to declare the mailbox addresses (and, in fact, all peripheral addresses) as volatile, so that the optimizer don't turn this:

Code: Select all

while(*mailboxStatus & MAILBOX_FULL);
into this:

Code: Select all

unsigned int val = *mailboxStatus & MAILBOX_FULL;
while(val);
The volatile keyword tells the compiler that that address is out of its control and can change at any moment.
So change your declarations into this:

Code: Select all

volatile unsigned int *mailboxStatus= (unsigned int *)(0x2000b898);
volatile unsigned int* mailboxWrite = (unsigned int *)0x2000b8a0;
(probably unneeded for mailboxWrite, but you never know)

Note it's the only thing I checked, there may be other issues I didn't look for.

Re: Baking PI in C (Screen 01 issues)

Posted: Wed Jul 24, 2013 7:27 am
by ambivalent

Code: Select all

 data = *(unsigned int*) 0x2000B880; 
I've never seen this done before, but I unfortunately have no way of testing it. Why not use a pointer like you did prior, with mailbox write?

Also, I don't think you need to typecast when assigning values to a (dereferenced?) Pointer.

Alas, not home ATM so I can't be much more help.

Re: Baking PI in C (Screen 01 issues)

Posted: Wed Jul 24, 2013 7:50 am
by simong
Pik wrote:You need to declare the mailbox addresses (and, in fact, all peripheral addresses) as volatile, so that the optimizer don't turn this:

Code: Select all

while(*mailboxStatus & MAILBOX_FULL);
into this:

Code: Select all

unsigned int val = *mailboxStatus & MAILBOX_FULL;
while(val);
The volatile keyword tells the compiler that that address is out of its control and can change at any moment.
So change your declarations into this:

Code: Select all

volatile unsigned int *mailboxStatus= (unsigned int *)(0x2000b898);
volatile unsigned int* mailboxWrite = (unsigned int *)0x2000b8a0;
(probably unneeded for mailboxWrite, but you never know)

Note it's the only thing I checked, there may be other issues I didn't look for.
First off, thanks for helping.
I don't have the code at hand right now, but I do believe it is marked as volatile, I didn't copy paste
straight off the code, but extracted the pieces I thought was relevant so might've made a mistake there, my apologies.

@ambient Same as above really, shamefully bad copy paste, it is in a (I believe) volatile variable. :)

Re: Baking PI in C (Screen 01 issues)

Posted: Wed Jul 24, 2013 9:25 am
by ambivalent
Ah, I see it better now. When I looked at your code initially, I was on my cellular device, which was being fickle (and not wanting to show the entirety of your code box).

Code: Select all

*mailboxWrite = ((unsigned int)info + 0x40000000) | 1;
This, I believe, is your problem. Bear with me, I haven't used channel 1 for the framebuffer in a while and I don't remember it very well.

According to the tutorial,
So, now that we have our message, we can write code to send it. The communication will go as follows:
Write the address of FrameBufferInfo + 0x40000000 to mailbox 1.
Read the result from mailbox 1. If it is not zero, we didn't ask for a proper frame buffer.
Copy our images to the pointer, and they will appear on screen!
which would make your logic incorrect. You are writing the value of info (which appears to be a structure), when you should be writing the address to your structure. The correct code (should) be this:

Code: Select all

*mailboxWrite = ((unsigned int*)&info + 0x40000000) | 1;

Re: Baking PI in C (Screen 01 issues)

Posted: Wed Jul 24, 2013 1:53 pm
by simong
Thanks ambivalent, I'll look into your suggestions first thing I do when I get home from work.
If it doesn't work I'll try to clean up my code, reduce the size of it to a minimum and post it so you can see
the entire thing.