salferre
Posts: 1
Joined: Thu Feb 21, 2019 10:11 am

Error on set Palette - 8 bit Framebuffer

Tue Apr 23, 2019 3:25 pm

Hey there,
I'm trying to using the set Palette tag (0x0004800b) with Mailboxes but I've a problem with it.
I'm passing these parameters as input:
0 2 00000000 FFFFFFFF

where 0 is first palette index to set (0-255)
2 is number of palette entries to set (1-256)
00000000 FFFFFFFF are RGBA palette values (offset to offset+length-1)

as reported on this link https://github.com/raspberrypi/firmware ... et-palette.

But it doesn't work to me and I can't figured out how to solve this. I also tried with 256 entries and passing the RGBA values as 0xFFFFFFFF.

Can anyone help me to solve this?

Thank you in advance. :roll:

LdB
Posts: 1102
Joined: Wed Dec 07, 2016 2:29 pm

Re: Error on set Palette - 8 bit Framebuffer

Tue Apr 23, 2019 5:39 pm

The palette must have to be spaced out r,g, b, A on seperate message values which is obvious because of the minimum 24 byte request

It says ===> Length: 24..1032

see this is minimum 1 palette entry request

Code: Select all

u32    0x??  // offset: first palette index to set (0-255)  4 bytes
u32    0x1  // number of palette entries minimum being 1 .. 4 bytes
u32    Red  // red value 4 bytes
u32   Green // green value 4 bytes
u32   Blue   // blue value 4 bytes
u32  Alpha   // alpha value 4 bytes

Total =   6 x 4 = 24 bytes
So the request length formula is 8 + (16 * palette entries)
Given the length restriction to 1032 you can only change 64 palettes at a time

Also remember to 16 byte align the struct

titius93
Posts: 1
Joined: Wed Apr 24, 2019 6:54 am

Re: Error on set Palette - 8 bit Framebuffer

Wed Apr 24, 2019 6:59 am

LdB wrote:
Tue Apr 23, 2019 5:39 pm
The palette must have to be spaced out r,g, b, A on seperate message values which is obvious because of the minimum 24 byte request

It says ===> Length: 24..1032

see this is minimum 1 palette entry request

Code: Select all

u32    0x??  // offset: first palette index to set (0-255)  4 bytes
u32    0x1  // number of palette entries minimum being 1 .. 4 bytes
u32    Red  // red value 4 bytes
u32   Green // green value 4 bytes
u32   Blue   // blue value 4 bytes
u32  Alpha   // alpha value 4 bytes

Total =   6 x 4 = 24 bytes
So the request length formula is 8 + (16 * palette entries)
Given the length restriction to 1032 you can only change 64 palettes at a time

Also remember to 16 byte align the struct
Really thanks for your help.
Can you give us an example of this kind of request?
I tried many times but also received Data Abort Error, I probably made syntactical errors.

Thank You in advance.

LdB
Posts: 1102
Joined: Wed Dec 07, 2016 2:29 pm

Re: Error on set Palette - 8 bit Framebuffer

Wed Apr 24, 2019 1:57 pm

Calling testPallete() ... prints successful for me and changes the colour :-)
Change the two defines at top to suit Pi model
You may already have some functions by the sounds but I thought I might as well give you all of it.

Code: Select all

#include <stdint.h>

#define PIBASEADDR  0x3F000000     // Change to 0x20000000 for BCM2835 Pi1, PiZero etc
#define PIBASEALIAS 0xC0000000     // Change to 0x40000000 for BCM2835 Pi1, PiZero etc

uint32_t __attribute__((aligned(16))) setpallete_msg[20]
= {
	sizeof(setpallete_msg),	// size of tag message
	0x0,                    // clear response
	0x0004800b,             // set palette cmd
	56,                     // 8 + (3 pallete entries * 16)
	4,                      // response size
	0x0,                    // offset 0
	0x3,                    // 3 palette entries
	0xFFFFFFFF,             // Entry 1 Full red
	0x0,                    // Entry 1 0 green
	0x0,                    //  Entry 1 0 blue
	0xFFFFFFFF,             //  Entry 1 .. alpha 100%
	0x0,                    // Entry 2 0 red
	0xFFFFFFFF,             // Entry 2 Full green
	0x0,                    // Entry  2 0 blue
	0xFFFFFFFF,             // Entry 2 alpha 100%    
	0x0,                    // Entry 3 0 red
	0x0,                    // Entry 3 0 green
	0xFFFFFFFF,             // Entry 3 Full blue
	0xFFFFFFFF,             //  entry 3 alpha 100%
	0x0,                    // end tag
};

#define MAILEMPTY	0x40000000		/* Mailbox Status Register: Mailbox Empty */
#define MAILFULL	0x80000000		/* Mailbox Status Register: Mailbox Full  */

#define MAILBOXREAD	         ((volatile __attribute__((aligned(4))) uint32_t*)(uintptr_t)(PIBASEADDR + 0xB880 + 0x0))
#define MAILBOX_READ_STATUS  ((volatile __attribute__((aligned(4))) uint32_t*)(uintptr_t)(PIBASEADDR + 0xB880 + 0x18))
#define MAILBOXWRITE	     ((volatile __attribute__((aligned(4))) uint32_t*)(uintptr_t)(PIBASEADDR + 0xB880 + 0x20))
#define MAILBOX_WRITE_STATUS ((volatile __attribute__((aligned(4))) uint32_t*)(uintptr_t)(PIBASEADDR + 0xB880 + 0x38))

void do_mailbox_write (uint8_t channel, uint32_t message)
{
	message &= ~(0xF);												// Make sure 4 low channel bits are clear 
	message |= channel;												// OR the channel bits to the value							
    while ((*MAILBOX_WRITE_STATUS & MAILFULL) != 0) {};				// Make sure arm mailbox is not full
	*MAILBOXWRITE = message;										// Write value to mailbox
}

void do_mailbox_read (uint8_t channel)
{
	uint32_t value;													// Temporary read value
	do {
		while ((*MAILBOX_READ_STATUS & MAILEMPTY) != 0) {};			// Wait for data in mailbox
		value = *MAILBOXREAD;										// Read the mailbox	
	} while ((value & 0xF) != channel);								// We have response back
}

void testPallete(void)
{
	do_mailbox_write(8, (uintptr_t)&setpallete_msg[0] | PIBASEALIAS); // Write message
	do_mailbox_read(8);	  // Wait for write response
	if (setpallete_msg[1] == 0x80000000)  // check success
		printf("Palette set success\n");
	else printf("Palette set failed\n");
}

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

Re: Error on set Palette - 8 bit Framebuffer

Thu Apr 25, 2019 12:20 am

LdB wrote:
Tue Apr 23, 2019 5:39 pm
The palette must have to be spaced out r,g, b, A on seperate message values which is obvious because of the minimum 24 byte request

...

So the request length formula is 8 + (16 * palette entries)
Given the length restriction to 1032 you can only change 64 palettes at a time
This is not correct, the documentation clearly states that the palette entries are u32 RGBA values and you can set all 256 entries in one request which is what is done by the Linux fb driver and by every other example.
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!

LdB
Posts: 1102
Joined: Wed Dec 07, 2016 2:29 pm

Re: Error on set Palette - 8 bit Framebuffer

Thu Apr 25, 2019 1:21 am

The documentation also clearly states the minimum palette request can be 1 .... and that has a request size of 24 bytes, it should be 12 then ... you can't have it both ways the documentation is wrong one way or another :-)

Lets see if works ... nope this fails

Code: Select all

uint32_t __attribute__((aligned(16))) setpallete_msg[20]
= {
	sizeof(setpallete_msg),	// size of tag message
	0x0,                    // clear response
	0x0004800b,             // set palette cmd
	12,                     // 8 + (1 pallete entries * 4)
	4,                      // response size
	0x0,                    // offset 0
	0x1,                    // 1 palette entries
	0xFFFFFFFF,             // Entry 1 Full white
	0x0,                    // end tag
};
The funny part about the linux driver is the size calc

Code: Select all

 (2 + packet->length) * sizeof(u32)
Why the extra 2 u32 at the front .. the struct already has the offset and length ... amusing calc with no explaining. Even 1 u32 I could understand if the response was tacked at back rather than overwrite but 2 is strange.

So for a 1 palette entry that would give you a size of 20 ... lets try that ... nope this fails

Code: Select all

uint32_t __attribute__((aligned(16))) setpallete_msg[9]
= {
	sizeof(setpallete_msg),	// size of tag message
	0x0,                    // clear response
	0x0004800b,             // set palette cmd
	20,                     // Should be 8 + (1 pallete entries * 4) .. but use 20 instead
	4,                      // response size
	0x0,                    // offset 0
	0x1,                    // 1 palette entries
	0xFFFFFFFF,             // Entry 1 Full white
	0x0,                    // end tag
};
Okay lets add 2 phantom u32 at the end .. no idea why :-)
>>>>> SUCCESS <<<<<<

Code: Select all

uint32_t __attribute__((aligned(16))) setpallete_msg[11]
= {
	sizeof(setpallete_msg),	// size of tag message
	0x0,                    // clear response
	0x0004800b,             // set palette cmd
	20,                     // Should be 8 + (1 pallete entries * 4) .. but use 20 instead
	4,                      // response size
	0x0,                    // offset 0
	0x1,                    // 1 palette entries
	0xFFFFFFFF,             // Entry 1 Full white
	0x0,                    // stupid phantom 1
	0x0,                    // stupid phantom 2
	0x0,                    // end tag
};
So the documentation is very wrong :-)
The minimum size is 20 and this command is quirky compared to all the other tag commands you have to add 2 random entries at the back of the palette for no obvious reason. I can set values in those phantom u32 and they remain untouched but have to be there.

The linux driver doesn't explain the 2 phantom entries at the end either because they lie outside the struct and are not accessed.

It looks like it is a firmware bug and the documentation is wrong.
Last edited by LdB on Thu Apr 25, 2019 1:41 am, edited 1 time in total.

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

Re: Error on set Palette - 8 bit Framebuffer

Thu Apr 25, 2019 1:41 am

LdB wrote:
Thu Apr 25, 2019 1:21 am
So the documentation is very wrong :-)
The minimum size is 20 and this command is quirky compared to all the other tag commands you have to add 2 random entries at the back of the palette for no obvious reason. I can set values in those phantom u32 and they remain untouched but have to be there.

The linux driver doesn't explain the 2 phantom entries at the end either because they lie outside the struct and are not accessed.
That doesn't change the fact that the palette entries are u32 RGBA, 4 bytes each not 16.

The documentation also does say "Palette changes should not be partially applied." which tends to indicate that single entries are not acceptable anyway. Note that the Linux driver only applies either 16 or 256 entries at a time.
LdB wrote:
Thu Apr 25, 2019 1:21 am
The funny part about the linux driver is the size calc

Code: Select all

 (2 + packet->length) * sizeof(u32)
Why the extra 2 u32 at the front .. the struct already has the offset and length ... amusing calc with no explaining. Even 1 u32 I could understand if the response was tacked at back rather than overwrite but 2 is strange.
That would be the offset and length fields themselves which are included in the size.
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!

LdB
Posts: 1102
Joined: Wed Dec 07, 2016 2:29 pm

Re: Error on set Palette - 8 bit Framebuffer

Thu Apr 25, 2019 1:47 am

Ultibo wrote:
Thu Apr 25, 2019 1:41 am
That would be the offset and length fields themselves which are included in the size.
They are already in the struct which already accounts for them and again if that was the case the size would be 12 (8 + 1 palette) which fails. Remember the size of 1 palette entry has to be 20 bytes to work or 5 x u32 ... Offet + length + palette = 3 u32 what are the other 2 u32?

I agree the pallete entries are u32 by looks but it is a strange tag command. I got lucky in my guess of expanded RGBA meant I made the structure bigger which allowed the call to at least succeed but I would have had the wrong colours on the palette, that is true. I was not looking at any screen (as I had no code for 8 bit mode I never use it) just the response back from the VC4 so I missed that.

Even weirder is I just noticed the VC4 is changing the 2nd extra u32 to zero, so I take it that is the response.
Initially I set it to zero so it didn't change. Normally I would expect the response at the offset value which is already 0.

So if I do this

Code: Select all

uint32_t __attribute__((aligned(16))) setpallete_msg[11]
= {
	sizeof(setpallete_msg),	// size of tag message
	0x0,                    // clear response
	0x0004800b,             // set palette cmd
	20,                     // Should be 8 + (1 pallete entries * 4) .. but use 20 instead
	4,                      // response size
	0x0,                    // offset 0
	0x1,                    // 1 palette entries
	0xFFFFFFFF,             // Entry 1 Full white
	0x55AA,                    // weird entry 1
	0x55AA,                    // weird entry 2
	0x0,                    // end tag
};
Weird entry 2 gets set to zero, so that is clearly the response as per documentation but strange place it jumps entry 1.
Ultibo wrote:
Thu Apr 25, 2019 1:41 am
The documentation also does say "Palette changes should not be partially applied." which tends to indicate that single entries are not acceptable anyway. Note that the Linux driver only applies either 16 or 256 entries at a time.
I noticed all that but the documentation still doesn't line up and the response position is just strange.
Last edited by LdB on Thu Apr 25, 2019 4:09 am, edited 8 times in total.

LdB
Posts: 1102
Joined: Wed Dec 07, 2016 2:29 pm

Re: Error on set Palette - 8 bit Framebuffer

Thu Apr 25, 2019 3:15 am

Anyhow this palette complete with it's weirdness

Code: Select all

uint32_t __attribute__((aligned(16))) setpallete_msg[12]
= {
	sizeof(setpallete_msg),	// size of tag message
	0x0,                    // clear response
	0x0004800b,             // set palette cmd
	24,		             // Should be 8 + (2 pallete entries * 4) + weird phantom 8
	4,
	0x0,                    // offset 0
	0x2,                   // 2 palette entries
	0xFFFF0000,             // Entry 1 Blue
	0xFF0000FF,             // Entry 2 Red
	0x0,                    // Weird extra data 1
	0x0,                    // Weird extra data 2
	0x0,                    // end tag
};
Background set as palette 0, text set as palette 1 produces
Image
https://github.com/LdB-ECM/Docs_and_Ima ... alette.jpg
So the palette entry is AABBGGRR. I think you can turn that in the config.txt but that is the default.

It also appears to work for any random number of palette entries I select but the 2 extra u32 at end not mentioned in the documentation appear to be mandatory. Weird extra 2 appears to be the response discussed in the documentation.

All very weird and not surprising salferre was having trouble with the command and he can battle his way thru it now.

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

Re: Error on set Palette - 8 bit Framebuffer

Thu Apr 25, 2019 7:57 am

LdB wrote:
Thu Apr 25, 2019 1:47 am
Ultibo wrote:
Thu Apr 25, 2019 1:41 am
That would be the offset and length fields themselves which are included in the size.
They are already in the struct which already accounts for them...
It would if the driver used sizeof(packet) but it doesn't, it uses (2 + packet->length) * sizeof(u32) instead to account for the offset and length.
LdB wrote:
Thu Apr 25, 2019 3:15 am
So the palette entry is AABBGGRR. I think you can turn that in the config.txt but that is the default.
We've been using this for a couple of years and the default format is always ARGB, the same as the Set Cursor Info request.
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!

LdB
Posts: 1102
Joined: Wed Dec 07, 2016 2:29 pm

Re: Error on set Palette - 8 bit Framebuffer

Thu Apr 25, 2019 10:56 am

Okay I have worked out what is bugged it is the request size and response size you can just zero both it never uses them or uses them wrong. The relationship is then between the overall message size and the number of palette entries which makes it easier to deal with.

So your record size is simply (8 + number of palettes) * U32

So this is a single palette

Code: Select all

uint32_t __attribute__((aligned(16))) setpallete_msg[9]
	= {
		sizeof(setpallete_msg),  // size of tag message
		0x0,     // clear response
		0x0004800b,    // set palette cmd
		0x0,	// Just zero this entry = no request size
		0x0,        // Just zero this entry = no response size
		0x0,        // offset 0
		0x1,        // 1 palette entries
		0xFF0000FF,    // Entry 0 Red
		0x0,       // end tag
};
So this is two palettes and on and on it goes

Code: Select all

uint32_t __attribute__((aligned(16))) setpallete_msg[10]
	= {
		sizeof(setpallete_msg),  // size of tag message
		0x0,     // clear response
		0x0004800b,    // set palette cmd
		0x0,	// Just zero this entry = no request size
		0x0,        // Just zero this entry = no response size
		0x0,        // offset 0
		0x2,        // 2 palette entries
		0xFFFF0000,    // Entry 0 Blue
		0xFF00FF00,    // Entry 1 Green
		0x0,       // end tag
};

Return to “Bare metal, Assembly language”