removed the cross allocator, use the shared memory region instead for I2C and NVRAM transfers

This commit is contained in:
Wolfvak 2020-07-19 11:44:03 -03:00
parent 30f0b004c2
commit 5905fb84fb
12 changed files with 77 additions and 161 deletions

View File

@ -20,11 +20,11 @@ VRAM_OUT := $(OUTDIR)/vram0.tar
VRAM_DATA := data VRAM_DATA := data
VRAM_FLAGS := --make-new --path-limit 99 --size-limit 3145728 VRAM_FLAGS := --make-new --path-limit 99 --size-limit 3145728
ifeq ($(OS),Windows_NT) #ifeq ($(OS),Windows_NT)
PY3 := py -3 # PY3 := py -3
else #else
PY3 := python3 PY3 := python3
endif #endif
# Definitions for ARM binaries # Definitions for ARM binaries
export INCLUDE := -I"$(shell pwd)/common" export INCLUDE := -I"$(shell pwd)/common"

View File

@ -46,6 +46,15 @@ SECTIONS
__rodata_len = . - __rodata_va; __rodata_len = . - __rodata_va;
} >AXIWRAM } >AXIWRAM
.shared (NOLOAD) : ALIGN(4K)
{
__shared_pa = LOADADDR(.shared);
__shared_va = ABSOLUTE(.);
*(.shared*)
. = ALIGN(4K);
__shared_len = . - __shared_va;
} >AXIWRAM
.bss (NOLOAD) : ALIGN(4K) .bss (NOLOAD) : ALIGN(4K)
{ {
__bss_pa = LOADADDR(.bss); __bss_pa = LOADADDR(.bss);

View File

@ -31,9 +31,6 @@
#include "hw/nvram.h" #include "hw/nvram.h"
#include "system/sys.h" #include "system/sys.h"
#include "system/xalloc.h"
static GlobalSharedMemory SharedMemory_State;
#ifndef FIXED_BRIGHTNESS #ifndef FIXED_BRIGHTNESS
static const u8 brightness_lvls[] = { static const u8 brightness_lvls[] = {
@ -46,6 +43,8 @@ static int prev_bright_lvl = -1;
static bool auto_brightness = true; static bool auto_brightness = true;
#endif #endif
static SystemSHMEM __attribute__((section(".shared"))) SharedMemoryState;
void VBlank_Handler(u32 __attribute__((unused)) irqn) void VBlank_Handler(u32 __attribute__((unused)) irqn)
{ {
#ifndef FIXED_BRIGHTNESS #ifndef FIXED_BRIGHTNESS
@ -57,12 +56,7 @@ void VBlank_Handler(u32 __attribute__((unused)) irqn)
} }
#endif #endif
// the state should probably be stored on its own SharedMemoryState.hidState.full = HID_GetState();
// section without caching enabled, since it must
// be readable by the ARM9 at all times anyway
SharedMemory_State.hid_state = HID_GetState();
ARM_WbDC_Range(&SharedMemory_State, sizeof(SharedMemory_State));
ARM_DMB();
} }
static bool legacy_boot = false; static bool legacy_boot = false;
@ -93,32 +87,38 @@ void PXI_RX_Handler(u32 __attribute__((unused)) irqn)
case PXI_GET_SHMEM: case PXI_GET_SHMEM:
{ {
ret = (u32)&SharedMemory_State; ret = (u32)&SharedMemoryState;
break; break;
} }
case PXI_SET_VMODE: case PXI_SET_VMODE:
{ {
int mode = args[0] ? GFX_BGR8 : GFX_RGB565; GFX_init(args[0] ? GFX_BGR8 : GFX_RGB565);
GFX_init(mode);
ret = 0; ret = 0;
break; break;
} }
case PXI_I2C_READ: case PXI_I2C_READ:
{ {
ARM_InvDC_Range((void*)args[2], args[3]); u32 devId, regAddr, size;
ret = I2C_readRegBuf(args[0], args[1], (u8*)args[2], args[3]);
ARM_WbDC_Range((void*)args[2], args[3]); devId = (args[0] & 0xff);
ARM_DMB(); regAddr = (args[0] >> 8) & 0xff;
size = (args[0] >> 16) % I2C_SHARED_BUFSZ;
ret = I2C_readRegBuf(devId, regAddr, SharedMemoryState.i2cBuffer, size);
break; break;
} }
case PXI_I2C_WRITE: case PXI_I2C_WRITE:
{ {
ARM_InvDC_Range((void*)args[2], args[3]); u32 devId, regAddr, size;
ARM_DMB();
ret = I2C_writeRegBuf(args[0], args[1], (u8*)args[2], args[3]); devId = (args[0] & 0xff);
regAddr = (args[0] >> 8) & 0xff;
size = (args[0] >> 16) % I2C_SHARED_BUFSZ;
ret = I2C_writeRegBuf(devId, regAddr, SharedMemoryState.i2cBuffer, size);
break; break;
} }
@ -130,10 +130,7 @@ void PXI_RX_Handler(u32 __attribute__((unused)) irqn)
case PXI_NVRAM_READ: case PXI_NVRAM_READ:
{ {
ARM_InvDC_Range((void*)args[1], args[2]); NVRAM_Read(args[0], (u32*)SharedMemoryState.spiBuffer, args[1]);
NVRAM_Read(args[0], (u32*)args[1], args[2]);
ARM_WbDC_Range((void*)args[1], args[2]);
ARM_DMB();
ret = 0; ret = 0;
break; break;
} }
@ -161,12 +158,6 @@ void PXI_RX_Handler(u32 __attribute__((unused)) irqn)
break; break;
} }
case PXI_XALLOC:
{
ret = (u32)XAlloc(args[0]);
break;
}
/* New CMD template: /* New CMD template:
case CMD_ID: case CMD_ID:
{ {
@ -185,14 +176,15 @@ void PXI_RX_Handler(u32 __attribute__((unused)) irqn)
PXI_Send(ret); PXI_Send(ret);
} }
extern u32 pdcerr;
void __attribute__((noreturn)) MainLoop(void) void __attribute__((noreturn)) MainLoop(void)
{ {
#ifdef FIXED_BRIGHTNESS #ifdef FIXED_BRIGHTNESS
LCD_SetBrightness(FIXED_BRIGHTNESS); LCD_SetBrightness(FIXED_BRIGHTNESS);
#endif #endif
// clear up the shared memory section
memset(&SharedMemoryState, 0, sizeof(SharedMemoryState));
// enable PXI RX interrupt // enable PXI RX interrupt
GIC_Enable(PXI_RX_INTERRUPT, BIT(0), GIC_HIGHEST_PRIO + 2, PXI_RX_Handler); GIC_Enable(PXI_RX_INTERRUPT, BIT(0), GIC_HIGHEST_PRIO + 2, PXI_RX_Handler);

View File

@ -26,6 +26,7 @@ DEF_SECT_(text)
DEF_SECT_(data) DEF_SECT_(data)
DEF_SECT_(rodata) DEF_SECT_(rodata)
DEF_SECT_(bss) DEF_SECT_(bss)
DEF_SECT_(shared)
#undef DEF_SECT_ #undef DEF_SECT_
#define SECTION_VA(n) ((u32)&__##n##_va) #define SECTION_VA(n) ((u32)&__##n##_va)

View File

@ -82,6 +82,7 @@ void SYS_CoreZeroInit(void)
MMU_Map(SECTION_TRI(data), MMU_FLAGS(CACHED_WB_ALLOC, READ_WRITE, 1, 1)); MMU_Map(SECTION_TRI(data), MMU_FLAGS(CACHED_WB_ALLOC, READ_WRITE, 1, 1));
MMU_Map(SECTION_TRI(rodata), MMU_FLAGS(CACHED_WT, READ_ONLY, 1, 1)); MMU_Map(SECTION_TRI(rodata), MMU_FLAGS(CACHED_WT, READ_ONLY, 1, 1));
MMU_Map(SECTION_TRI(bss), MMU_FLAGS(CACHED_WB_ALLOC, READ_WRITE, 1, 1)); MMU_Map(SECTION_TRI(bss), MMU_FLAGS(CACHED_WB_ALLOC, READ_WRITE, 1, 1));
MMU_Map(SECTION_TRI(shared), MMU_FLAGS(STRONGLY_ORDERED, READ_WRITE, 1, 1));
// IO Registers // IO Registers
MMU_Map(0x10100000, 0x10100000, 4UL << 20, MMU_FLAGS(DEVICE_SHARED, READ_WRITE, 1, 1)); MMU_Map(0x10100000, 0x10100000, 4UL << 20, MMU_FLAGS(DEVICE_SHARED, READ_WRITE, 1, 1));

View File

@ -1,37 +0,0 @@
/*
* This file is part of GodMode9
* Copyright (C) 2019 Wolfvak
*
* 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 2 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 <http://www.gnu.org/licenses/>.
*/
// super simple watermark allocator for ARM9 <-> ARM11 xfers
// designed to be request once, free never
#include "system/xalloc.h"
static char ALIGN(4096) xalloc_buf[XALLOC_BUF_SIZE];
static size_t mark = 0;
void *XAlloc(size_t size)
{ // not thread-safe at all
void *ret;
size_t end = size + mark;
if (end >= XALLOC_BUF_SIZE)
return NULL;
ret = &xalloc_buf[mark];
mark = end;
return ret;
}

View File

@ -1,25 +0,0 @@
/*
* This file is part of GodMode9
* Copyright (C) 2019 Wolfvak
*
* 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 2 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "types.h"
#define XALLOC_BUF_SIZE (16384)
void *XAlloc(size_t size);

View File

@ -27,12 +27,12 @@ static void SetNotificationLED(u32 period_ms, u32 rgb565_color)
// separate things - hopefully LTO won't get in the way // separate things - hopefully LTO won't get in the way
u32 HID_ReadState(void) u32 HID_ReadState(void)
{ {
return ARM_GetSHMEM()->hid_state; return ARM_GetSHMEM()->hidState.keys;
} }
u32 HID_ReadRawTouchState(void) u32 HID_ReadRawTouchState(void)
{ {
return ARM_GetSHMEM()->hid_state >> 32; return ARM_GetSHMEM()->hidState.touch;
} }
// ts_mult indicates a scalar for each axis // ts_mult indicates a scalar for each axis

View File

@ -3,65 +3,44 @@
#include "i2c.h" #include "i2c.h"
#include "pxi.h" #include "pxi.h"
#include "shmem.h"
// buffer is allocated only once and remains through runtime
static char *i2c_xfer_buf = NULL;
static bool I2C_AllocBuffer(void)
{
if (!i2c_xfer_buf) {
u32 xbuf = PXI_DoCMD(PXI_XALLOC, (u32[]){256}, 1);
if (xbuf == 0 || xbuf == 0xFFFFFFFF)
return false;
i2c_xfer_buf = (char*)xbuf;
}
return true;
}
bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size) bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size)
{ {
int ret; int ret;
u32 *args; const u32 arg = devId | (regAddr << 8) | (size << 16);
if (!I2C_AllocBuffer()) if (size >= I2C_SHARED_BUFSZ)
return false; return false;
args = (u32[]){devId, regAddr, (u32)i2c_xfer_buf, size}; ret = PXI_DoCMD(PXI_I2C_READ, &arg, 1);
ARM_WbDC_Range(i2c_xfer_buf, size); ARM_InvDC_Range(ARM_GetSHMEM()->i2cBuffer, size);
ARM_DSB(); memcpy(out, ARM_GetSHMEM()->i2cBuffer, size);
ret = PXI_DoCMD(PXI_I2C_READ, args, 4);
ARM_InvDC_Range(i2c_xfer_buf, size);
memcpy(out, i2c_xfer_buf, size);
return ret; return ret;
} }
bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size) bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size)
{ {
int ret; int ret;
u32 *args; const u32 arg = devId | (regAddr << 8) | (size << 16);
if (!I2C_AllocBuffer()) if (size >= I2C_SHARED_BUFSZ)
return false; return false;
args = (u32[]){devId, regAddr, (u32)i2c_xfer_buf, size}; ARM_InvDC_Range(ARM_GetSHMEM()->i2cBuffer, size);
memcpy(ARM_GetSHMEM()->i2cBuffer, in, size);
memcpy(i2c_xfer_buf, in, size); ARM_WbDC_Range(ARM_GetSHMEM()->i2cBuffer, size);
ARM_WbDC_Range(i2c_xfer_buf, size);
ARM_DSB(); ARM_DSB();
ret = PXI_DoCMD(PXI_I2C_WRITE, args, 4); ret = PXI_DoCMD(PXI_I2C_WRITE, &arg, 1);
return ret; return ret;
} }
u8 I2C_readReg(I2cDevice devId, u8 regAddr) u8 I2C_readReg(I2cDevice devId, u8 regAddr)
{ {
u8 data; u8 data = 0xFF;
if (!I2C_readRegBuf(devId, regAddr, &data, 1)) I2C_readRegBuf(devId, regAddr, &data, 1);
data = 0xFF;
return data; return data;
} }

View File

@ -1,10 +1,7 @@
#include "common.h" #include "common.h"
#include "arm.h" #include "arm.h"
#include "pxi.h" #include "pxi.h"
#include "shmem.h"
#define SPIFLASH_CHUNK_SIZE (0x1000)
static char *spiflash_xfer_buf = NULL;
bool spiflash_get_status(void) bool spiflash_get_status(void)
{ {
@ -13,27 +10,19 @@ bool spiflash_get_status(void)
bool spiflash_read(u32 offset, u32 size, u8 *buf) bool spiflash_read(u32 offset, u32 size, u8 *buf)
{ {
u32 args[3]; u32 args[2];
if (!spiflash_xfer_buf) {
u32 xbuf = PXI_DoCMD(PXI_XALLOC, (u32[]){SPIFLASH_CHUNK_SIZE}, 1);
if (xbuf == 0 || xbuf == 0xFFFFFFFF)
return false;
spiflash_xfer_buf = (char*)xbuf;
}
args[1] = (u32)spiflash_xfer_buf;
while(size > 0) { while(size > 0) {
u32 blksz = min(size, SPIFLASH_CHUNK_SIZE); u32 blksz = min(size, SPI_SHARED_BUFSZ);
args[0] = offset; args[0] = offset;
args[2] = blksz; args[1] = blksz;
ARM_WbDC_Range(ARM_GetSHMEM()->spiBuffer, blksz);
PXI_DoCMD(PXI_NVRAM_READ, args, 2);
ARM_InvDC_Range(ARM_GetSHMEM()->spiBuffer, blksz);
ARM_DSB(); ARM_DSB();
PXI_DoCMD(PXI_NVRAM_READ, args, 3); memcpy(buf, ARM_GetSHMEM()->spiBuffer, blksz);
ARM_InvDC_Range(spiflash_xfer_buf, blksz);
memcpy(buf, spiflash_xfer_buf, blksz);
buf += blksz; buf += blksz;
size -= blksz; size -= blksz;

View File

@ -39,9 +39,7 @@ enum {
PXI_NVRAM_READ, PXI_NVRAM_READ,
PXI_NOTIFY_LED, PXI_NOTIFY_LED,
PXI_BRIGHTNESS, PXI_BRIGHTNESS
PXI_XALLOC,
}; };
/* /*

View File

@ -20,19 +20,28 @@
#include <arm.h> #include <arm.h>
#define I2C_SHARED_BUFSZ 1024
#define SPI_SHARED_BUFSZ 1024
typedef struct { typedef struct {
u64 hid_state; union {
} GlobalSharedMemory; struct { u32 keys, touch; };
u64 full;
} hidState;
u8 i2cBuffer[I2C_SHARED_BUFSZ];
u32 spiBuffer[SPI_SHARED_BUFSZ/4];
} __attribute__((packed, aligned(8))) SystemSHMEM;
#ifdef ARM9 #ifdef ARM9
#include <pxi.h> #include <pxi.h>
static inline const GlobalSharedMemory *ARM_GetSHMEM(void) static inline SystemSHMEM *ARM_GetSHMEM(void)
{ {
return (const GlobalSharedMemory*)ARM_GetTID(); return (SystemSHMEM*)ARM_GetTID();
} }
static void ARM_InitSHMEM(void) static inline void ARM_InitSHMEM(void)
{ {
ARM_SetTID(PXI_DoCMD(PXI_GET_SHMEM, NULL, 0)); ARM_SetTID(PXI_DoCMD(PXI_GET_SHMEM, NULL, 0));
} }