Skip to content

Commit 692b4c6

Browse files
committed
Fix framebuffer configuration race
Previously the arm9 tried to use the framebuffer configuration passed in from the previous bootloader stage. However, the arm11 reconfigured the framebuffer to a new location shortly after power up. This led to the arm9 writing to a memory area which no longer displayed anything on the screen. And since the arm9 was no longer initializing the actual framebuffer random data was displayed on screen. The fix was to introduce another synchronization point between the arm9 and arm11. The arm9 start.S now waits for the arm11 to have reconfigured the framebuffer before entering main. This still left a minor flicker of unitialized data between the time that the arm11 moved the framebuffer memory location and when the arm9 initialized that memory - so an additional change in this commit is to have the arm11 initialize that memory before updating the framebuffer location.
1 parent ecb0f0d commit 692b4c6

File tree

5 files changed

+82
-43
lines changed

5 files changed

+82
-43
lines changed

arm11/source/start.S

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,17 @@
11
#include "linux_config.h"
22
#include "scu.h"
33

4-
@ LCD Frambuffers stuff (Physical Addresses)
5-
#define LCD_FB_PDC0 (0x10400400)
6-
#define LCD_FB_PDC1 (0x10400500)
7-
#define LCD_FB_A_ADDR_OFFSET (0x68)
8-
#define LCD_FB_FORMAT_OFFSET (0x70)
9-
#define LCD_FB_PDC0_FORMAT (0x80341)
10-
#define LCD_FB_SELECT_OFFSET (0x78)
11-
#define LCD_FB_STRIDE_OFFSET (0x90)
12-
#define LCD_FB_PDC0_STRIDE (0x2D0)
13-
#define LCD_FB_B_ADDR_OFFSET (0x94)
14-
#define FB_TOP_SIZE (400 * 240 * 3)
15-
#define FB_BOT_SIZE (320 * 240 * 3)
16-
#define FB_BASE_PA (VRAM_BASE)
17-
#define FB_TOP_LEFT1 (FB_BASE_PA)
18-
#define FB_TOP_LEFT2 (FB_TOP_LEFT1 + FB_TOP_SIZE)
19-
#define FB_TOP_RIGHT1 (FB_TOP_LEFT2 + FB_TOP_SIZE)
20-
#define FB_TOP_RIGHT2 (FB_TOP_RIGHT1 + FB_TOP_SIZE)
21-
#define FB_BOT_1 (FB_TOP_RIGHT2 + FB_TOP_SIZE)
22-
#define FB_BOT_2 (FB_BOT_1 + FB_BOT_SIZE)
23-
244
.arm
255
.section .text.start
266
.cpu mpcore
277

288
.global _start
299
_start:
10+
@ Initialize RAM value used to sync with arm9
11+
ldr r0, =SYNC_ADDR
12+
mov r1, #SYNC_INIT
13+
str r1, [r0]
14+
3015
@ Disable FIQs, IRQs, imprecise aborts
3116
@ and enter SVC mode
3217
cpsid aif, #0x13
@@ -91,6 +76,32 @@ _start:
9176

9277
@@@@@ Map Framebuffers @@@@@
9378

79+
@@@ Zero framebuffer region @@@
80+
ldr r0, =FB_TOP_LEFT1 @ address of buffer
81+
mov r1, #0 @ value to set
82+
ldr r2, =FB_TOP_SIZE @ number of bytes
83+
bl memset
84+
ldr r0, =FB_TOP_LEFT2
85+
mov r1, #0
86+
ldr r2, =FB_TOP_SIZE
87+
bl memset
88+
ldr r0, =FB_TOP_RIGHT1
89+
mov r1, #0
90+
ldr r2, =FB_TOP_SIZE
91+
bl memset
92+
ldr r0, =FB_TOP_RIGHT2
93+
mov r1, #0
94+
ldr r2, =FB_TOP_SIZE
95+
bl memset
96+
ldr r0, =FB_BOT_1
97+
mov r1, #0
98+
ldr r2, =FB_BOT_SIZE
99+
bl memset
100+
ldr r0, =FB_BOT_2
101+
mov r1, #0
102+
ldr r2, =FB_BOT_SIZE
103+
bl memset
104+
94105
@@@ Top screen @@@
95106
ldr r0, =LCD_FB_PDC0
96107

@@ -125,15 +136,19 @@ _start:
125136
@ Select framebuffer 0
126137
mov r1, #0
127138
str r1, [r0, #LCD_FB_SELECT_OFFSET]
139+
140+
ldr r0, =SYNC_ADDR
141+
mov r1, #SYNC_FB_RDY
142+
str r1, [r0]
128143

129144
@@@@@ Jump to the kernel @@@@@
130-
145+
131146
@ Wait until ARM9 tells Linux address...
132147
ldr r0, =SYNC_ADDR
133148
wait_arm9:
134149
ldr r1, [r0]
135-
cmp r1, #0
136-
beq wait_arm9
150+
cmp r1, #SYNC_BOOT_RDY
151+
bne wait_arm9
137152

138153
@ Setup the registers before
139154
@ jumping to the kernel entry

arm9/source/draw.c

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "font.h"
1111
#include "draw.h"
1212
#include "fs.h"
13+
#include "linux_config.h"
1314

1415
static u8 *top_screen0 = NULL;
1516
static u8 *top_screen1 = NULL;
@@ -19,26 +20,15 @@ static u8 *bot_screen1 = NULL;
1920
static char debugstr[DBG_N_CHARS_X * DBG_N_CHARS_Y] = { 0 };
2021
static u32 debugcol[DBG_N_CHARS_Y] = { DBG_COLOR_FONT };
2122

22-
void InitScreenFbs(int argc, char *argv[])
23+
void InitScreenFbs(int _argc, char *_argv[])
2324
{
24-
if (argc >= 2) {
25-
/* newer entrypoints */
26-
struct {
27-
u8 *top_left;
28-
u8 *top_right;
29-
u8 *bottom;
30-
} *fb = (void *)argv[1];
31-
top_screen0 = fb[0].top_left;
32-
top_screen1 = fb[1].top_left;
33-
bot_screen0 = fb[0].bottom;
34-
bot_screen1 = fb[1].bottom;
35-
} else {
36-
/* outdated entrypoints */
37-
top_screen0 = (u8 *)(*(u32 *)0x23FFFE00);
38-
top_screen1 = (u8 *)(*(u32 *)0x23FFFE00);
39-
bot_screen0 = (u8 *)(*(u32 *)0x23FFFE08);
40-
bot_screen1 = (u8 *)(*(u32 *)0x23FFFE08);
41-
}
25+
// The arm11 start.S remaps the frame buffers to new
26+
// locations, so we don't use the values which come
27+
// from args.
28+
top_screen0 = (u8 *) FB_TOP_LEFT1;
29+
top_screen1 = (u8 *) FB_TOP_LEFT2;
30+
bot_screen0 = (u8 *) FB_BOT_1;
31+
bot_screen1 = (u8 *) FB_BOT_2;
4232
}
4333

4434
void ClearScreen(u8 *screen, int width, int color)

arm9/source/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ int main(int argc, char *argv[])
100100
DeinitFS();
101101

102102
/* Make the ARM11 jump to the Linux payload */
103-
*(vu32 *)SYNC_ADDR = 1;
103+
*(vu32 *)SYNC_ADDR = SYNC_BOOT_RDY;
104104

105105
flushCaches();
106106

arm9/source/start.S

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#include "linux_config.h"
2+
13
.section .text.start
24
.global _start
35
_start:
@@ -59,6 +61,15 @@ _start:
5961
ldr r0, =0x10000020
6062
mov r1, #0x340
6163
str r1, [r0]
64+
65+
@ wait for arm11
66+
ldr r0, =SYNC_ADDR
67+
wait_arm11:
68+
ldr r1, [r0]
69+
cmp r1, #SYNC_FB_RDY
70+
bne wait_arm11
71+
72+
@@@ Jump to main @@@
6273

6374
mov r0, r9
6475
mov r1, r10

common/linux_config.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
#define MACHINE_NUMBER (0xFFFFFFFF)
66
#define ARM9LINUXFW_ADDR (0x08080000)
77
#define SYNC_ADDR (0x1FFFFFF0)
8+
#define SYNC_INIT (0)
9+
#define SYNC_FB_RDY (1)
10+
#define SYNC_BOOT_RDY (2)
811

912
#define LINUXIMAGE_FILENAME "linux/zImage"
1013
#define INITRAMFS_FILENAME "linux/initramfs.cpio.gz"
@@ -19,3 +22,23 @@
1922
#define AXI_WRAM_SIZE (0x00080000)
2023
#define FCRAM_BASE (0x20000000)
2124
#define FCRAM_SIZE (0x08000000)
25+
26+
/* LCD Frambuffers stuff (Physical Addresses) */
27+
#define LCD_FB_PDC0 (0x10400400)
28+
#define LCD_FB_PDC1 (0x10400500)
29+
#define LCD_FB_A_ADDR_OFFSET (0x68)
30+
#define LCD_FB_FORMAT_OFFSET (0x70)
31+
#define LCD_FB_PDC0_FORMAT (0x80341)
32+
#define LCD_FB_SELECT_OFFSET (0x78)
33+
#define LCD_FB_STRIDE_OFFSET (0x90)
34+
#define LCD_FB_PDC0_STRIDE (0x2D0)
35+
#define LCD_FB_B_ADDR_OFFSET (0x94)
36+
#define FB_TOP_SIZE (400 * 240 * 3)
37+
#define FB_BOT_SIZE (320 * 240 * 3)
38+
#define FB_BASE_PA (VRAM_BASE)
39+
#define FB_TOP_LEFT1 (FB_BASE_PA)
40+
#define FB_TOP_LEFT2 (FB_TOP_LEFT1 + FB_TOP_SIZE)
41+
#define FB_TOP_RIGHT1 (FB_TOP_LEFT2 + FB_TOP_SIZE)
42+
#define FB_TOP_RIGHT2 (FB_TOP_RIGHT1 + FB_TOP_SIZE)
43+
#define FB_BOT_1 (FB_TOP_RIGHT2 + FB_BOT_SIZE)
44+
#define FB_BOT_2 (FB_BOT_1 + FB_BOT_SIZE)

0 commit comments

Comments
 (0)