Skip to content

Commit 8892992

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 8892992

5 files changed

Lines changed: 73 additions & 43 deletions

File tree

arm11/source/start.S

Lines changed: 29 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,23 @@ _start:
9176

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

79+
@@@ Zero framebuffer region @@@
80+
mov r1, #0 @ value to set
81+
ldr r2, =FB_TOP_SIZE @ number of bytes
82+
ldr r0, =FB_TOP_LEFT1 @ address of buffer
83+
bl memset
84+
ldr r0, =FB_TOP_LEFT2
85+
bl memset
86+
ldr r0, =FB_TOP_RIGHT1
87+
bl memset
88+
ldr r0, =FB_TOP_RIGHT2
89+
bl memset
90+
ldr r2, =FB_BOT_SIZE
91+
ldr r0, =FB_BOT_1
92+
bl memset
93+
ldr r0, =FB_BOT_2
94+
bl memset
95+
9496
@@@ Top screen @@@
9597
ldr r0, =LCD_FB_PDC0
9698

@@ -125,15 +127,19 @@ _start:
125127
@ Select framebuffer 0
126128
mov r1, #0
127129
str r1, [r0, #LCD_FB_SELECT_OFFSET]
130+
131+
ldr r0, =SYNC_ADDR
132+
mov r1, #SYNC_FB_RDY
133+
str r1, [r0]
128134

129135
@@@@@ Jump to the kernel @@@@@
130-
136+
131137
@ Wait until ARM9 tells Linux address...
132138
ldr r0, =SYNC_ADDR
133139
wait_arm9:
134140
ldr r1, [r0]
135-
cmp r1, #0
136-
beq wait_arm9
141+
cmp r1, #SYNC_BOOT_RDY
142+
bne wait_arm9
137143

138144
@ Setup the registers before
139145
@ 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)