透過 Mailbox 來操作 framebuffer 輸出圖片,可以用於開機畫面(?)。
參考 官方文件 進行實作。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
| #include "mbox.h"
#include "peripherals/mbox.h"
#include "uart0.h"
unsigned int width, height, pitch, isrgb; /* dimensions and channel order */
unsigned char *fb; /* raw frame buffer address */
void fb_init() {
unsigned int __attribute__((aligned(16))) mbox[35];
mbox[0] = 35 * 4;
mbox[1] = MBOX_CODE_BUF_REQ;
// set physical width / height
mbox[2] = MBOX_TAG_SET_PHY_WIDTH_HEIGHT;
mbox[3] = 8;
mbox[4] = MBOX_CODE_TAG_REQ;
mbox[5] = 960; // width in pixels
mbox[6] = 720; // height in pixels
// set virtual width / height
mbox[7] = MBOX_TAG_SET_VTL_WIDTH_HEIGHT;
mbox[8] = 8;
mbox[9] = MBOX_CODE_TAG_REQ;
mbox[10] = 920; // width in pixels
mbox[11] = 720; // height in pixels
// set virtual offset
mbox[12] = MBOX_TAG_SET_VTL_OFFSET;
mbox[13] = 8;
mbox[14] = MBOX_CODE_TAG_REQ;
mbox[15] = 0; // X in pixels
mbox[16] = 0; // Y in pixels
// set depth
mbox[17] = MBOX_TAG_SET_DEPTH;
mbox[18] = 4;
mbox[19] = MBOX_CODE_TAG_REQ;
mbox[20] = 32; // bits per pixel
// set pixel order
mbox[21] = MBOX_TAG_SET_PIXEL_ORDER;
mbox[22] = 4;
mbox[23] = MBOX_CODE_TAG_REQ;
mbox[24] = 1; // 0x0: BGR, 0x1: RGB
// allocate buffer
mbox[25] = MBOX_TAG_ALLOCATE_BUFFER;
mbox[26] = 8;
mbox[27] = MBOX_CODE_TAG_REQ;
mbox[28] = 4096; // req: alignment in bytes / res: frame buffer base address in bytes
mbox[29] = 0; // frame buffer size in bytes
// get pitch
mbox[30] = MBOX_TAG_GET_PITCH;
mbox[31] = 4;
mbox[32] = MBOX_CODE_TAG_REQ;
mbox[33] = 0; // res: bytes per line
mbox[34] = 0x0;
mbox_call(mbox, 8);
if (mbox[20] == 32 && mbox[28] != 0) {
mbox[28] &= 0x3FFFFFFF; // convert GPU address to ARM address
width = mbox[5]; // get actual physical width
height = mbox[6]; // get actual physical height
pitch = mbox[33]; // get number of bytes per line
isrgb = mbox[24]; // get the actual channel order
fb = (void *)((unsigned long)mbox[28]);
}
else {
uart_printf("Unable to set screen resolution to 1024x768x32\n");
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| void fb_splash() {
int x, y;
unsigned char *ptr = fb;
unsigned int white = 255 << 16 | 255 << 8 | 255; // A B G R
unsigned int black = 0;
unsigned int current, start = black, spacing = 40;
for (y = 0; y < height; y++) {
if (y % spacing == 0 && y != 0) {
start = (start == white) ? black : white;
}
current = start;
for (x = 0; x < width; x++) {
if (x % spacing == 0 && x != 0) {
current = (current == white) ? black : white;
}
*((unsigned int *)ptr) = current;
ptr += 4;
}
}
}
|
在進行開機初始化時 call 這個 function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
void shell_init() {
// Initialize UART
uart_init();
uart_flush();
uart_printf("\n[%f] Init PL011 UART done", get_timestamp());
// Initialize Frame Buffer
fb_init();
uart_printf("\n[%f] Init Frame Buffer done", get_timestamp());
// Welcome Messages
fb_splash();
uart_printf("\n\n _ _ ___ _____ _ _ ___ ___ ___ ___ \n");
uart_printf("| \\| |/ __|_ _| | | |/ _ \\/ __| \\_ _|\n");
uart_printf("| .` | (__ | | | |_| | (_) \\__ \\ |) | | \n");
uart_printf("|_|\\_|\\___| |_| \\___/ \\___/|___/___/___|\n\n");
mbox_board_revision();
mbox_vc_memory();
uart_printf("\n");
}
|
會跳出一個視窗,效果如下
https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface