From 8a4597635dcd0ec6b98a2802aa51428eb31c0509 Mon Sep 17 00:00:00 2001 From: Wolfvak Date: Tue, 26 Sep 2017 19:56:19 -0300 Subject: [PATCH] Potentially fix screen init on some systems Sanitized I2C Reorganized the memory layout - Moved GM9 to ARM9 RAM - Increased RAMdisk size to 88MiB --- Makefile | 10 +- common/pxi.h | 1 + link.ld | 6 +- screeninit/Makefile | 2 +- screeninit/source/main.c | 27 ++--- source/common/common.h | 6 +- source/main.c | 15 ++- source/start.s | 156 +++++++++++----------------- common/i2c.h => source/system/i2c.c | 43 ++------ source/system/i2c.h | 56 ++++++++++ 10 files changed, 165 insertions(+), 157 deletions(-) rename common/i2c.h => source/system/i2c.c (82%) create mode 100644 source/system/i2c.h diff --git a/Makefile b/Makefile index 7d4c444..30928c9 100644 --- a/Makefile +++ b/Makefile @@ -74,7 +74,7 @@ endif CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -LDFLAGS = -T../link.ld -nostartfiles -g $(ARCH) -Wl,-Map,$(TARGET).map +LDFLAGS = -T../link.ld -nostartfiles -g $(ARCH) -Wl,-Map,$(TARGET).map,-z,max-page-size=512 LIBS := @@ -152,12 +152,12 @@ binary: common @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile firm: binary screeninit - firmtool build $(OUTPUT).firm -n 0x08006000 -A 0x08006000 -D $(OUTPUT).bin $(OUTPUT_D)/screeninit.elf -C NDMA XDMA -S nand-retail -g - firmtool build $(OUTPUT)_dev.firm -n 0x08006000 -A 0x08006000 -D $(OUTPUT).bin $(OUTPUT_D)/screeninit.elf -C NDMA XDMA -S nand-dev -g + firmtool build $(OUTPUT).firm -D $(OUTPUT).elf $(OUTPUT_D)/screeninit.elf -C NDMA XDMA -S nand-retail -g + firmtool build $(OUTPUT)_dev.firm -D $(OUTPUT).elf $(OUTPUT_D)/screeninit.elf -C NDMA XDMA -S nand-dev -g ntrboot: binary screeninit - firmtool build $(OUTPUT)_ntr.firm -n 0x08006000 -A 0x08006000 -D $(OUTPUT).bin $(OUTPUT_D)/screeninit.elf -C NDMA XDMA -S spi-retail -g - firmtool build $(OUTPUT)_ntr_dev.firm -n 0x08006000 -A 0x08006000 -D $(OUTPUT).bin $(OUTPUT_D)/screeninit.elf -C NDMA XDMA -S spi-dev -g + firmtool build $(OUTPUT)_ntr.firm -D $(OUTPUT).elf $(OUTPUT_D)/screeninit.elf -C NDMA XDMA -S spi-retail -g + firmtool build $(OUTPUT)_ntr_dev.firm -D $(OUTPUT).elf $(OUTPUT_D)/screeninit.elf -C NDMA XDMA -S spi-dev -g release: @-rm -fr $(BUILD) $(OUTPUT_D) $(RELEASE) diff --git a/common/pxi.h b/common/pxi.h index f3c4ab4..ca4746d 100644 --- a/common/pxi.h +++ b/common/pxi.h @@ -18,6 +18,7 @@ enum { PXI_NONE = 0, PXI_READY, PXI_BUSY, + PXI_SCREENINIT, PXI_BRIGHTNESS }; diff --git a/link.ld b/link.ld index c8ea737..4f3cfce 100644 --- a/link.ld +++ b/link.ld @@ -4,7 +4,7 @@ ENTRY(_start) SECTIONS { - . = 0x23F00000; + . = 0x08006000; __start__ = ABSOLUTE(.); .text.start : ALIGN(4) { *(.text.start) } @@ -17,7 +17,7 @@ SECTIONS __end__ = ABSOLUTE(.); - __stack_abt = __start__; - __stack_top = __start__ - 0x80000; + __stack_abt = 0x22800000; + __stack_top = __stack_abt - 0x80000; __code_size__ = __end__ - __start__; } diff --git a/screeninit/Makefile b/screeninit/Makefile index f77b637..46fbb6e 100644 --- a/screeninit/Makefile +++ b/screeninit/Makefile @@ -19,7 +19,7 @@ ASFLAGS := $(ARCH) -x assembler-with-cpp $(INCLUDE) CFLAGS := $(ARCH) -Wall -Wextra -MMD -MP -fno-builtin \ -Wno-unused-function -Wno-unused-variable \ -std=c11 -O2 -flto -ffast-math -Wno-main $(INCLUDE) -LDFLAGS := -nostdlib -nostartfiles +LDFLAGS := -nostdlib -nostartfiles -Wl,-z,max-page-size=512 objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ diff --git a/screeninit/source/main.c b/screeninit/source/main.c index 4f49a53..1a3d944 100644 --- a/screeninit/source/main.c +++ b/screeninit/source/main.c @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -19,6 +18,21 @@ void PXI_IRQHandler(void) default: break; + case PXI_SCREENINIT: + { + GPU_Init(); + GPU_PSCFill(VRAM_START, VRAM_END, 0); + GPU_SetFramebuffers((u32[]){VRAM_TOP_LA, VRAM_TOP_LB, + VRAM_TOP_RA, VRAM_TOP_RB, + VRAM_BOT_A, VRAM_BOT_B}); + + GPU_SetFramebufferMode(0, PDC_RGB24); + GPU_SetFramebufferMode(1, PDC_RGB24); + + PXI_SetRemote(PXI_BUSY); + break; + } + case PXI_BRIGHTNESS: { PXI_RecvArray(pxi_args, 1); @@ -50,17 +64,6 @@ void main(void) u32 entry; PXI_Reset(); - GPU_Init(); - GPU_PSCFill(VRAM_START, VRAM_END, 0); - GPU_SetFramebuffers((u32[]){VRAM_TOP_LA, VRAM_TOP_LB, - VRAM_TOP_RA, VRAM_TOP_RB, - VRAM_BOT_A, VRAM_BOT_B}); - - GPU_SetFramebufferMode(0, PDC_RGB24); - GPU_SetFramebufferMode(1, PDC_RGB24); - - I2C_writeReg(I2C_DEV_MCU, 0x22, 0x2A); - GIC_Reset(); GIC_SetIRQ(IRQ_PXI_SYNC, PXI_IRQHandler); PXI_EnableIRQ(); diff --git a/source/common/common.h b/source/common/common.h index b5226d7..3661fd6 100644 --- a/source/common/common.h +++ b/source/common/common.h @@ -91,6 +91,6 @@ #define TEMP_BUFFER_SIZE (0x1800000) // 24MB(!) // buffer area defines (in use by image.c, for RAMdrive) -#define RAMDRV_BUFFER ((u8*)0x24000000) // top half of FCRAM -#define RAMDRV_SIZE_O3DS (0x04000000) // 64MB -#define RAMDRV_SIZE_N3DS (0x0C000000) // 192MB +#define RAMDRV_BUFFER ((u8*)0x22800000) // top of STACK +#define RAMDRV_SIZE_O3DS (0x5800000) // 88MB +#define RAMDRV_SIZE_N3DS (0xD800000) // 216MB diff --git a/source/main.c b/source/main.c index 5981f8b..15843ab 100644 --- a/source/main.c +++ b/source/main.c @@ -1,6 +1,7 @@ #include "godmode.h" #include "power.h" #include "pxi.h" +#include "i2c.h" void main(int argc, char** argv) { @@ -8,14 +9,18 @@ void main(int argc, char** argv) // Wait for ARM11 PXI_WaitRemote(PXI_READY); - + + PXI_DoCMD(PXI_SCREENINIT, NULL, 0); + I2C_writeReg(I2C_DEV_MCU, 0x22, 0x2A); + #ifdef AUTORUN_SCRIPT // Run the script runner - if (ScriptRunner(argc) == GODMODE_EXIT_REBOOT) Reboot(); - else PowerOff(); + if (ScriptRunner(argc) == GODMODE_EXIT_REBOOT) #else // Run the main program - if (GodMode(argc) == GODMODE_EXIT_REBOOT) Reboot(); - else PowerOff(); + if (GodMode(argc) == GODMODE_EXIT_REBOOT) #endif + Reboot(); + + PowerOff(); } diff --git a/source/start.s b/source/start.s index 381869e..f36fb84 100644 --- a/source/start.s +++ b/source/start.s @@ -5,91 +5,50 @@ #include #include -@ Make sure to preserve r0-r2 .global _start _start: - @ Switch to supervisor mode and disable interrupts - msr cpsr_c, #(SR_SYS_MODE | SR_IRQ | SR_FIQ) + @ Disable interrupts + mrs r4, cpsr + orr r4, r4, #(SR_IRQ | SR_FIQ) + msr cpsr_c, r4 - @ Short delay (not always necessary, just in case) - mov r3, #0x40000 - .Lwaitloop: - subs r3, #1 - bgt .Lwaitloop - - @ Check the load address - adr r3, _start - ldr r4, =__start__ - cmp r3, r4 - beq _start_gm - - @ Relocate the binary to the correct location and branch to it - ldr r5, =__code_size__ - .Lbincopyloop: - subs r5, #4 - ldrge r6, [r3, r5] - strge r6, [r4, r5] - bge .Lbincopyloop - - mov r5, r0 - mov r6, r1 - mov r7, r2 - ldr r3, =BRF_WB_INV_DCACHE - blx r3 - mov r0, r5 - mov r1, r6 - mov r2, r7 - - mov lr, #0 - mcr p15, 0, lr, c7, c5, 0 @ Invalidate ICache - - bx r4 - -_start_gm: - ldr sp, =__stack_top - - mov r9, r0 @ argc - mov r10, r1 @ argv - - ldr r4, =0xBEEF - lsl r2, #16 - lsr r2, #16 - cmp r2, r4 @ magic word - movne r9, #0 - - @ Disable caches / mpu - ldr r1, =(CR_ENABLE_MPU | CR_ENABLE_DCACHE | CR_ENABLE_ICACHE | \ - CR_ENABLE_DTCM) - ldr r2, =(CR_ENABLE_ITCM | CR_CACHE_RROBIN) - mrc p15, 0, r0, c1, c0, 0 - bic r0, r1 - orr r0, r2 - mcr p15, 0, r0, c1, c0, 0 + @ Preserve boot registers + mov r9, r0 + mov r10, r1 + mov r11, r2 @ Clear bss ldr r0, =__bss_start ldr r1, =__bss_end mov r2, #0 - .Lbss_clr: + .LBSS_Clear: cmp r0, r1 - strlt r2, [r0], #4 - blt .Lbss_clr + strlo r2, [r0], #4 + blo .LBSS_Clear - @ Invalidate caches - mov r5, #0 - mcr p15, 0, r5, c7, c5, 0 @ invalidate I-cache - mcr p15, 0, r5, c7, c6, 0 @ invalidate D-cache - mcr p15, 0, r5, c7, c10, 4 @ drain write buffer + ldr r0, =BRF_WB_INV_DCACHE + blx r0 @ Writeback & Invalidate Data Cache + ldr r0, =BRF_INVALIDATE_ICACHE + blx r0 @ Invalidate Instruction Cache - @ Give read/write access to all the memory regions - ldr r5, =0x33333333 - mcr p15, 0, r5, c5, c0, 2 @ write data access - mcr p15, 0, r5, c5, c0, 3 @ write instruction access + @ Disable caches / DTCM / MPU + ldr r1, =(CR_ENABLE_MPU | CR_ENABLE_DCACHE | CR_ENABLE_ICACHE | \ + CR_ENABLE_DTCM) + ldr r2, =(CR_ENABLE_ITCM) + mrc p15, 0, r0, c1, c0, 0 + bic r0, r1 + orr r0, r2 + mcr p15, 0, r0, c1, c0, 0 - @ Sets MPU regions and cache settings + @ Give full access to defined memory regions + ldr r0, =0x33333333 + mcr p15, 0, r0, c5, c0, 2 @ write data access + mcr p15, 0, r0, c5, c0, 3 @ write instruction access + + @ Set MPU regions and cache settings adr r0, __mpu_regions ldmia r0, {r1-r8} - mov r0, #0b00101101 @ bootrom/itcm/arm9 mem and fcram are cacheable/bufferable + mov r0, #0b00101000 mcr p15, 0, r1, c6, c0, 0 mcr p15, 0, r2, c6, c1, 0 mcr p15, 0, r3, c6, c2, 0 @@ -98,13 +57,22 @@ _start_gm: mcr p15, 0, r6, c6, c5, 0 mcr p15, 0, r7, c6, c6, 0 mcr p15, 0, r8, c6, c7, 0 - mcr p15, 0, r0, c3, c0, 0 @ Write bufferable 0, 2, 5 - mcr p15, 0, r0, c2, c0, 0 @ Data cacheable 0, 2, 5 - mcr p15, 0, r0, c2, c0, 1 @ Inst cacheable 0, 2, 5 + mcr p15, 0, r0, c3, c0, 0 @ Write bufferable + mcr p15, 0, r0, c2, c0, 0 @ Data cacheable + mcr p15, 0, r0, c2, c0, 1 @ Inst cacheable @ Enable dctm - ldr r0, =0x3000800A @ set dtcm - mcr p15, 0, r0, c9, c1, 0 @ set the dtcm Region Register + ldr r0, =0x3000800A + mcr p15, 0, r0, c9, c1, 0 @ set the DTCM Region Register + + @ Enable caches / select low exception vectors + ldr r1, =(CR_ALT_VECTORS | CR_DISABLE_TBIT) + ldr r2, =(CR_ENABLE_MPU | CR_ENABLE_DCACHE | CR_ENABLE_ICACHE | \ + CR_ENABLE_DTCM | CR_CACHE_RROBIN) + mrc p15, 0, r0, c1, c0, 0 + bic r0, r1 + orr r0, r2 + mcr p15, 0, r0, c1, c0, 0 @ Install exception handlers ldr r0, =XRQ_Start @@ -112,28 +80,30 @@ _start_gm: ldr r2, =0x00000000 .LXRQ_Install: cmp r0, r1 - ldrlt r3, [r0], #4 - strlt r3, [r2], #4 - blt .LXRQ_Install + ldrlo r3, [r0], #4 + strlo r3, [r2], #4 + blo .LXRQ_Install - @ Enable caches / select low exception vectors - ldr r1, =(CR_ALT_VECTORS | CR_DISABLE_TBIT) - ldr r2, =(CR_ENABLE_MPU | CR_ENABLE_DCACHE | CR_ENABLE_ICACHE | \ - CR_ENABLE_DTCM) - mrc p15, 0, r0, c1, c0, 0 - bic r0, r1 - orr r0, r2 - mcr p15, 0, r0, c1, c0, 0 - - @ Fixes mounting of SDMC - ldr r0, =0x10000000 + @ Fix SDMC mounting + mov r0, #0x10000000 mov r1, #0x340 str r1, [r0, #0x20] - mov r0, r9 - mov r1, r10 + @ Check arguments + lsl r2, r11, #16 + lsr r2, r2, #16 - bl main + ldr r3, =0xBEEF + cmp r2, r3 + + moveq r0, r9 + moveq r1, r10 + movne r0, #0 + + @ Switch to system mode, disable interrupts, setup application stack + msr cpsr_c, #(SR_SYS_MODE | SR_IRQ | SR_FIQ) + ldr sp, =__stack_top + b main __mpu_regions: .word 0xFFFF001F @ FFFF0000 64k | bootrom (unprotected / protected) diff --git a/common/i2c.h b/source/system/i2c.c similarity index 82% rename from common/i2c.h rename to source/system/i2c.c index 0ee4537..0c027d8 100644 --- a/common/i2c.h +++ b/source/system/i2c.c @@ -16,39 +16,10 @@ * along with this program. If not, see . */ -#pragma once - -#include #include +#include "i2c.h" -#define I2C_STOP (1u) -#define I2C_START (1u<<1) -#define I2C_ERROR (1u<<2) -#define I2C_ACK (1u<<4) -#define I2C_DIRE_WRITE (0u) -#define I2C_DIRE_READ (1u<<5) -#define I2C_IRQ_ENABLE (1u<<6) -#define I2C_ENABLE (1u<<7) - -#define I2C_GET_ACK(reg) ((bool)((reg)>>4 & 1u)) - - -typedef enum -{ - I2C_DEV_POWER = 0, // Unconfirmed - I2C_DEV_CAMERA = 1, // Unconfirmed - I2C_DEV_CAMERA2 = 2, // Unconfirmed - I2C_DEV_MCU = 3, - I2C_DEV_GYRO = 10, - I2C_DEV_DEBUG_PAD = 12, - I2C_DEV_IR = 13, - I2C_DEV_EEPROM = 14, // Unconfirmed - I2C_DEV_NFC = 15, - I2C_DEV_QTM = 16, - I2C_DEV_N3DS_HID = 17 -} I2cDevice; - #define I2C1_REGS_BASE (0x10161000) #define REG_I2C1_DATA *((vu8* )(I2C1_REGS_BASE + 0x00)) #define REG_I2C1_CNT *((vu8* )(I2C1_REGS_BASE + 0x01)) @@ -94,12 +65,14 @@ static const struct {2, 0x54} }; -static inline void i2cWaitBusy(vu8 *cntReg) + + +static void i2cWaitBusy(vu8 *cntReg) { while(*cntReg & I2C_ENABLE); } -static inline vu8* i2cGetBusRegsBase(u8 busId) +static vu8* i2cGetBusRegsBase(u8 busId) { vu8 *base; if(!busId) base = (vu8*)I2C1_REGS_BASE; @@ -161,7 +134,7 @@ static bool i2cStartTransfer(I2cDevice devId, u8 regAddr, bool read, vu8 *regsBa else return false; } -static void I2C_init(void) +void I2C_init(void) { i2cWaitBusy(i2cGetBusRegsBase(0)); REG_I2C1_CNTEX = 2; // ? @@ -176,7 +149,7 @@ static void I2C_init(void) REG_I2C3_SCL = 1280; // ? } -static bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size) +bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size) { const u8 busId = i2cDevTable[devId].busId; vu8 *const i2cData = i2cGetBusRegsBase(busId); @@ -199,7 +172,7 @@ static bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size) return true; } -static bool I2C_writeReg(I2cDevice devId, u8 regAddr, u8 data) +bool I2C_writeReg(I2cDevice devId, u8 regAddr, u8 data) { const u8 busId = i2cDevTable[devId].busId; vu8 *const i2cData = i2cGetBusRegsBase(busId); diff --git a/source/system/i2c.h b/source/system/i2c.h new file mode 100644 index 0000000..8229e3f --- /dev/null +++ b/source/system/i2c.h @@ -0,0 +1,56 @@ +#pragma once + +/* + * This file is part of fastboot 3DS + * Copyright (C) 2017 derrek, profi200 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include "common.h" + + +#define I2C_STOP (1u) +#define I2C_START (1u<<1) +#define I2C_ERROR (1u<<2) +#define I2C_ACK (1u<<4) +#define I2C_DIRE_WRITE (0u) +#define I2C_DIRE_READ (1u<<5) +#define I2C_IRQ_ENABLE (1u<<6) +#define I2C_ENABLE (1u<<7) + +#define I2C_GET_ACK(reg) ((bool)((reg)>>4 & 1u)) + + +typedef enum +{ + I2C_DEV_POWER = 0, // Unconfirmed + I2C_DEV_CAMERA = 1, // Unconfirmed + I2C_DEV_CAMERA2 = 2, // Unconfirmed + I2C_DEV_MCU = 3, + I2C_DEV_GYRO = 10, + I2C_DEV_DEBUG_PAD = 12, + I2C_DEV_IR = 13, + I2C_DEV_EEPROM = 14, // Unconfirmed + I2C_DEV_NFC = 15, + I2C_DEV_QTM = 16, + I2C_DEV_N3DS_HID = 17 +} I2cDevice; + + + +void I2C_init(void); +bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size); +bool I2C_writeReg(I2cDevice devId, u8 regAddr, u8 data);