mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 05:32:47 +00:00
make interrupt handlers more lazy, most processing is done in interruptible context now
- completely moved MCU interrupt handling outside of the critical section - refactored a bit of the PXI code and command names - merge the I2C read and write cmds to be one - remove SET_VMODE cmd, now it's always initialized to BGR565 on boot and to RGB565 on firmlaunch - atomic-ize more stuff
This commit is contained in:
parent
a6e20c641a
commit
9ecb90a2ba
@ -63,57 +63,73 @@ typedef struct {
|
|||||||
|
|
||||||
static u8 volumeSliderValue;
|
static u8 volumeSliderValue;
|
||||||
static u32 shellState;
|
static u32 shellState;
|
||||||
static _Atomic(u32) pendingEvents;
|
static _Atomic(u32) pendingEvents, pendingUpdate;
|
||||||
|
|
||||||
static void mcuUpdateVolumeSlider(void)
|
static void mcuEventUpdate(void)
|
||||||
{
|
{
|
||||||
volumeSliderValue = mcuReadReg(MCUREG_VOLUME_SLIDER);
|
u32 mask;
|
||||||
}
|
|
||||||
|
|
||||||
static void mcuUpdateShellState(bool open)
|
if (!atomic_exchange(&pendingUpdate, 0))
|
||||||
{
|
return;
|
||||||
shellState = open ? SHELL_OPEN : SHELL_CLOSED;
|
|
||||||
|
// reading the pending mask automagically acknowledges
|
||||||
|
// the interrupts so all of them must be processed in one go
|
||||||
|
mcuReadRegBuf(MCUREG_INT_MASK, (u8*)&mask, sizeof(mask));
|
||||||
|
|
||||||
|
if (mask & MCUEV_HID_VOLUME_SLIDER)
|
||||||
|
volumeSliderValue = mcuReadReg(MCUREG_VOLUME_SLIDER);
|
||||||
|
|
||||||
|
if (mask & MCUEV_HID_SHELL_OPEN) {
|
||||||
|
mcuResetLEDs();
|
||||||
|
shellState = SHELL_OPEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask & MCUEV_HID_SHELL_CLOSE) {
|
||||||
|
shellState = SHELL_CLOSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
atomic_fetch_or(&pendingEvents, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 mcuEventTest(u32 mask)
|
u32 mcuEventTest(u32 mask)
|
||||||
{
|
{
|
||||||
|
mcuEventUpdate();
|
||||||
return atomic_load(&pendingEvents) & mask;
|
return atomic_load(&pendingEvents) & mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 mcuEventClear(u32 mask)
|
u32 mcuEventClear(u32 mask)
|
||||||
{
|
{
|
||||||
|
mcuEventUpdate();
|
||||||
return atomic_fetch_and(&pendingEvents, ~mask) & mask;
|
return atomic_fetch_and(&pendingEvents, ~mask) & mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 mcuEventWait(u32 mask)
|
u32 mcuEventWait(u32 mask)
|
||||||
{
|
{
|
||||||
do {
|
do {
|
||||||
|
mcuEventUpdate();
|
||||||
u32 x = mcuEventClear(mask);
|
u32 x = mcuEventClear(mask);
|
||||||
if (x) return x;
|
if (x) return x;
|
||||||
ARM_WFE();
|
|
||||||
} while(1);
|
} while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 mcuGetVolumeSlider(void)
|
u8 mcuGetVolumeSlider(void)
|
||||||
{
|
{
|
||||||
|
mcuEventUpdate();
|
||||||
return volumeSliderValue;
|
return volumeSliderValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 mcuGetSpecialHID(void)
|
u32 mcuGetSpecialHID(void)
|
||||||
{
|
{
|
||||||
u32 ret = shellState, pend = mcuEventClear(MCUEV_HID_MASK);
|
u32 ret, pend = mcuEventClear(MCUEV_HID_MASK);
|
||||||
|
|
||||||
// hopefully gets unrolled
|
// hopefully gets unrolled
|
||||||
if (pend & (MCUEV_HID_PWR_DOWN | MCUEV_HID_PWR_HOLD))
|
if (pend & (MCUEV_HID_PWR_DOWN | MCUEV_HID_PWR_HOLD))
|
||||||
ret |= BUTTON_POWER;
|
ret |= BUTTON_POWER;
|
||||||
|
|
||||||
if (pend & MCUEV_HID_HOME_DOWN)
|
if (pend & MCUEV_HID_HOME_DOWN)
|
||||||
ret |= BUTTON_HOME;
|
ret |= BUTTON_HOME;
|
||||||
|
|
||||||
if (pend & MCUEV_HID_HOME_UP)
|
if (pend & MCUEV_HID_HOME_UP)
|
||||||
ret &= ~BUTTON_HOME;
|
ret &= ~BUTTON_HOME;
|
||||||
|
return ret | shellState;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mcuSetStatusLED(u32 period_ms, u32 color)
|
void mcuSetStatusLED(u32 period_ms, u32 color)
|
||||||
@ -162,25 +178,7 @@ void mcuResetLEDs(void)
|
|||||||
|
|
||||||
void mcuInterruptHandler(u32 __attribute__((unused)) irqn)
|
void mcuInterruptHandler(u32 __attribute__((unused)) irqn)
|
||||||
{
|
{
|
||||||
u32 mask;
|
atomic_store(&pendingUpdate, 1);
|
||||||
|
|
||||||
// reading the pending mask automagically acknowledges
|
|
||||||
// the interrupts so all of them must be processed in one go
|
|
||||||
mcuReadRegBuf(MCUREG_INT_MASK, (u8*)&mask, sizeof(mask));
|
|
||||||
|
|
||||||
if (mask & MCUEV_HID_VOLUME_SLIDER)
|
|
||||||
mcuUpdateVolumeSlider();
|
|
||||||
|
|
||||||
if (mask & MCUEV_HID_SHELL_OPEN) {
|
|
||||||
mcuResetLEDs();
|
|
||||||
mcuUpdateShellState(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mask & MCUEV_HID_SHELL_CLOSE) {
|
|
||||||
mcuUpdateShellState(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
atomic_fetch_or(&pendingEvents, mask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mcuReset(void)
|
void mcuReset(void)
|
||||||
@ -188,6 +186,7 @@ void mcuReset(void)
|
|||||||
u32 intmask = 0;
|
u32 intmask = 0;
|
||||||
|
|
||||||
atomic_init(&pendingEvents, 0);
|
atomic_init(&pendingEvents, 0);
|
||||||
|
atomic_init(&pendingUpdate, 0);
|
||||||
|
|
||||||
// set register mask and clear any pending registers
|
// set register mask and clear any pending registers
|
||||||
mcuWriteRegBuf(MCUREG_INT_EN, (const u8*)&intmask, sizeof(intmask));
|
mcuWriteRegBuf(MCUREG_INT_EN, (const u8*)&intmask, sizeof(intmask));
|
||||||
@ -195,8 +194,8 @@ void mcuReset(void)
|
|||||||
|
|
||||||
mcuResetLEDs();
|
mcuResetLEDs();
|
||||||
|
|
||||||
mcuUpdateVolumeSlider();
|
volumeSliderValue = mcuReadReg(MCUREG_VOLUME_SLIDER);
|
||||||
mcuUpdateShellState(true);
|
shellState = SHELL_OPEN;
|
||||||
// assume the shell is always open on boot
|
// assume the shell is always open on boot
|
||||||
// knowing the average 3DS user, there will be plenty
|
// knowing the average 3DS user, there will be plenty
|
||||||
// of laughs when this comes back to bite us in the rear
|
// of laughs when this comes back to bite us in the rear
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#include <arm.h>
|
#include <arm.h>
|
||||||
#include <pxi.h>
|
#include <pxi.h>
|
||||||
|
|
||||||
|
#include <stdatomic.h>
|
||||||
|
|
||||||
#include "arm/gic.h"
|
#include "arm/gic.h"
|
||||||
|
|
||||||
#include "hw/hid.h"
|
#include "hw/hid.h"
|
||||||
@ -44,10 +46,20 @@ static int prev_bright_lvl;
|
|||||||
static bool auto_brightness;
|
static bool auto_brightness;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static SystemSHMEM __attribute__((section(".shared"))) SharedMemoryState;
|
static SystemSHMEM __attribute__((section(".shared"))) sharedMem;
|
||||||
|
|
||||||
void vblankHandler(u32 __attribute__((unused)) irqn)
|
static _Atomic(u32) pendingVblank, pendingPxiRx;
|
||||||
|
|
||||||
|
static void vblankHandler(u32 __attribute__((unused)) irqn)
|
||||||
{
|
{
|
||||||
|
atomic_store(&pendingVblank, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vblankUpdate(void)
|
||||||
|
{
|
||||||
|
if (!atomic_exchange(&pendingVblank, 0))
|
||||||
|
return;
|
||||||
|
|
||||||
#ifndef FIXED_BRIGHTNESS
|
#ifndef FIXED_BRIGHTNESS
|
||||||
int cur_bright_lvl = (mcuGetVolumeSlider() >> 2) % countof(brightness_lvls);
|
int cur_bright_lvl = (mcuGetVolumeSlider() >> 2) % countof(brightness_lvls);
|
||||||
if ((cur_bright_lvl != prev_bright_lvl) && auto_brightness) {
|
if ((cur_bright_lvl != prev_bright_lvl) && auto_brightness) {
|
||||||
@ -57,128 +69,43 @@ void vblankHandler(u32 __attribute__((unused)) irqn)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SharedMemoryState.hidState.full = HID_GetState();
|
// handle shell events
|
||||||
|
u32 shell = mcuEventClear(MCUEV_HID_SHELL_OPEN | MCUEV_HID_SHELL_CLOSE);
|
||||||
|
if (shell & MCUEV_HID_SHELL_CLOSE) {
|
||||||
|
GFX_powerOffBacklights(GFX_BLIGHT_BOTH);
|
||||||
|
} else if (shell & MCUEV_HID_SHELL_OPEN) {
|
||||||
|
GFX_powerOnBacklights(GFX_BLIGHT_BOTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
sharedMem.hidState.full = HID_GetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool legacy_boot = false;
|
static void pxiRxHandler(u32 __attribute__((unused)) irqn)
|
||||||
|
|
||||||
void pxiRxHandler(u32 __attribute__((unused)) irqn)
|
|
||||||
{
|
{
|
||||||
u32 ret, msg, cmd, argc, args[PXI_MAX_ARGS];
|
atomic_store(&pendingPxiRx, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pxiRxUpdate(u32 *cmd, u32 *args)
|
||||||
|
{
|
||||||
|
u32 msg, lo, hi;
|
||||||
|
|
||||||
|
*cmd = PXICMD_NONE;
|
||||||
|
|
||||||
|
if (!atomic_exchange(&pendingPxiRx, 0))
|
||||||
|
return;
|
||||||
|
|
||||||
msg = PXI_Recv();
|
msg = PXI_Recv();
|
||||||
cmd = msg & 0xFFFF;
|
lo = msg & 0xFFFF;
|
||||||
argc = msg >> 16;
|
hi = msg >> 16;
|
||||||
|
|
||||||
if (argc >= PXI_MAX_ARGS) {
|
*cmd = lo;
|
||||||
PXI_Send(0xFFFFFFFF);
|
PXI_RecvArray(args, hi);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PXI_RecvArray(args, argc);
|
|
||||||
|
|
||||||
switch (cmd) {
|
|
||||||
case PXI_LEGACY_MODE:
|
|
||||||
{
|
|
||||||
// TODO: If SMP is enabled, an IPI should be sent here (with a DSB)
|
|
||||||
legacy_boot = true;
|
|
||||||
ret = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case PXI_GET_SHMEM:
|
|
||||||
{
|
|
||||||
ret = (u32)&SharedMemoryState;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case PXI_SET_VMODE:
|
|
||||||
{
|
|
||||||
GFX_init(args[0] ? GFX_BGR8 : GFX_RGB565);
|
|
||||||
ret = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case PXI_I2C_READ:
|
|
||||||
{
|
|
||||||
u32 devId, regAddr, size;
|
|
||||||
|
|
||||||
devId = (args[0] & 0xff);
|
|
||||||
regAddr = (args[0] >> 8) & 0xff;
|
|
||||||
size = (args[0] >> 16) % I2C_SHARED_BUFSZ;
|
|
||||||
|
|
||||||
ret = I2C_readRegBuf(devId, regAddr, SharedMemoryState.i2cBuffer, size);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case PXI_I2C_WRITE:
|
|
||||||
{
|
|
||||||
u32 devId, regAddr, size;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
case PXI_NVRAM_ONLINE:
|
|
||||||
{
|
|
||||||
ret = (NVRAM_Status() & NVRAM_SR_WIP) == 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case PXI_NVRAM_READ:
|
|
||||||
{
|
|
||||||
NVRAM_Read(args[0], (u32*)SharedMemoryState.spiBuffer, args[1]);
|
|
||||||
ret = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case PXI_NOTIFY_LED:
|
|
||||||
{
|
|
||||||
mcuSetStatusLED(args[0], args[1]);
|
|
||||||
ret = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case PXI_BRIGHTNESS:
|
|
||||||
{
|
|
||||||
ret = GFX_getBrightness();
|
|
||||||
#ifndef FIXED_BRIGHTNESS
|
|
||||||
s32 newbrightness = (s32)args[0];
|
|
||||||
if ((newbrightness > 0) && (newbrightness < 0x100)) {
|
|
||||||
GFX_setBrightness(newbrightness, newbrightness);
|
|
||||||
autoBr = false;
|
|
||||||
} else {
|
|
||||||
oldBrLvl = -1;
|
|
||||||
autoBr = true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* New CMD template:
|
|
||||||
case CMD_ID:
|
|
||||||
{
|
|
||||||
<var declarations/assignments>
|
|
||||||
<execute the command>
|
|
||||||
<set the return value>
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
default:
|
|
||||||
ret = 0xFFFFFFFF;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
PXI_Send(ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __attribute__((noreturn)) MainLoop(void)
|
void __attribute__((noreturn)) MainLoop(void)
|
||||||
{
|
{
|
||||||
|
bool runCmdProcessor = true;
|
||||||
|
|
||||||
#ifdef FIXED_BRIGHTNESS
|
#ifdef FIXED_BRIGHTNESS
|
||||||
u8 fixed_bright_lvl = brightness_lvls[clamp(FIXED_BRIGHTNESS, 0, countof(brightness_lvls)-1)];
|
u8 fixed_bright_lvl = brightness_lvls[clamp(FIXED_BRIGHTNESS, 0, countof(brightness_lvls)-1)];
|
||||||
GFX_setBrightness(fixed_bright_lvl, fixed_bright_lvl);
|
GFX_setBrightness(fixed_bright_lvl, fixed_bright_lvl);
|
||||||
@ -187,11 +114,14 @@ void __attribute__((noreturn)) MainLoop(void)
|
|||||||
auto_brightness = true;
|
auto_brightness = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
memset(&SharedMemoryState, 0, sizeof(SharedMemoryState));
|
// initialize state stuff
|
||||||
|
atomic_init(&pendingVblank, 0);
|
||||||
|
atomic_init(&pendingPxiRx, 0);
|
||||||
|
memset(&sharedMem, 0, sizeof(sharedMem));
|
||||||
|
|
||||||
// configure interrupts
|
// configure interrupts
|
||||||
gicSetInterruptConfig(PXI_RX_INTERRUPT, BIT(0), GIC_PRIO2, pxiRxHandler);
|
gicSetInterruptConfig(PXI_RX_INTERRUPT, BIT(0), GIC_PRIO0, pxiRxHandler);
|
||||||
gicSetInterruptConfig(MCU_INTERRUPT, BIT(0), GIC_PRIO1, mcuInterruptHandler);
|
gicSetInterruptConfig(MCU_INTERRUPT, BIT(0), GIC_PRIO0, mcuInterruptHandler);
|
||||||
gicSetInterruptConfig(VBLANK_INTERRUPT, BIT(0), GIC_PRIO0, vblankHandler);
|
gicSetInterruptConfig(VBLANK_INTERRUPT, BIT(0), GIC_PRIO0, vblankHandler);
|
||||||
|
|
||||||
// enable interrupts
|
// enable interrupts
|
||||||
@ -207,18 +137,93 @@ void __attribute__((noreturn)) MainLoop(void)
|
|||||||
// ARM9 won't try anything funny until this point
|
// ARM9 won't try anything funny until this point
|
||||||
PXI_Barrier(PXI_BOOT_BARRIER);
|
PXI_Barrier(PXI_BOOT_BARRIER);
|
||||||
|
|
||||||
// Process IRQs until the ARM9 tells us it's time to boot something else
|
// Process commands until the ARM9 tells
|
||||||
|
// us it's time to boot something else
|
||||||
|
// also handles Vblank events as needed
|
||||||
do {
|
do {
|
||||||
ARM_WFI();
|
u32 cmd, resp, args[PXI_MAX_ARGS];
|
||||||
|
|
||||||
// handle shell events
|
vblankUpdate();
|
||||||
u32 shell = mcuEventClear(MCUEV_HID_SHELL_OPEN | MCUEV_HID_SHELL_CLOSE);
|
pxiRxUpdate(&cmd, args);
|
||||||
if (shell & MCUEV_HID_SHELL_CLOSE) {
|
|
||||||
GFX_powerOffBacklights(GFX_BLIGHT_BOTH);
|
switch(cmd) {
|
||||||
} else if (shell & MCUEV_HID_SHELL_OPEN) {
|
case PXICMD_NONE:
|
||||||
GFX_powerOnBacklights(GFX_BLIGHT_BOTH);
|
ARM_WFI();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PXICMD_LEGACY_BOOT:
|
||||||
|
runCmdProcessor = false;
|
||||||
|
resp = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PXICMD_GET_SHMEM_ADDRESS:
|
||||||
|
resp = (u32)&sharedMem;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PXICMD_I2C_OP:
|
||||||
|
{
|
||||||
|
u32 devId, regAddr, size;
|
||||||
|
|
||||||
|
devId = (args[0] & 0xff);
|
||||||
|
regAddr = (args[0] >> 8) & 0xff;
|
||||||
|
size = (args[0] >> 16) % I2C_SHARED_BUFSZ;
|
||||||
|
|
||||||
|
if (args[0] & BIT(31)) {
|
||||||
|
resp = I2C_writeRegBuf(devId, regAddr, sharedMem.i2cBuffer, size);
|
||||||
|
} else {
|
||||||
|
resp = I2C_readRegBuf(devId, regAddr, sharedMem.i2cBuffer, size);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case PXICMD_NVRAM_ONLINE:
|
||||||
|
resp = (NVRAM_Status() & NVRAM_SR_WIP) == 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PXICMD_NVRAM_READ:
|
||||||
|
NVRAM_Read(args[0], (u32*)sharedMem.spiBuffer, args[1]);
|
||||||
|
resp = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PXICMD_SET_NOTIFY_LED:
|
||||||
|
mcuSetStatusLED(args[0], args[1]);
|
||||||
|
resp = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PXICMD_SET_BRIGHTNESS:
|
||||||
|
{
|
||||||
|
s32 newbrightness = (s32)args[0];
|
||||||
|
resp = GFX_getBrightness();
|
||||||
|
#ifndef FIXED_BRIGHTNESS
|
||||||
|
if ((newbrightness > 0) && (newbrightness < 0x100)) {
|
||||||
|
GFX_setBrightness(newbrightness, newbrightness);
|
||||||
|
auto_brightness = false;
|
||||||
|
} else {
|
||||||
|
prev_bright_lvl = -1;
|
||||||
|
auto_brightness = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
resp = 0xFFFFFFFF;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} while(!legacy_boot);
|
|
||||||
|
if (cmd != PXICMD_NONE)
|
||||||
|
PXI_Send(resp); // was a command sent from the ARM9, send a response
|
||||||
|
} while(runCmdProcessor);
|
||||||
|
|
||||||
|
// perform deinit in reverse order
|
||||||
|
gicDisableInterrupt(VBLANK_INTERRUPT);
|
||||||
|
gicDisableInterrupt(PXI_RX_INTERRUPT);
|
||||||
|
|
||||||
|
// unconditionally reinitialize the screens
|
||||||
|
// in RGB24 framebuffer mode
|
||||||
|
GFX_init(GFX_BGR8);
|
||||||
|
|
||||||
|
gicDisableInterrupt(MCU_INTERRUPT);
|
||||||
|
|
||||||
// Wait for the ARM9 to do its firmlaunch setup
|
// Wait for the ARM9 to do its firmlaunch setup
|
||||||
PXI_Barrier(PXI_FIRMLAUNCH_BARRIER);
|
PXI_Barrier(PXI_FIRMLAUNCH_BARRIER);
|
||||||
|
@ -19,7 +19,7 @@ static void SetNotificationLED(u32 period_ms, u32 rgb565_color)
|
|||||||
(rgb565_color >> 5) << (8+2) |
|
(rgb565_color >> 5) << (8+2) |
|
||||||
(rgb565_color << 3));
|
(rgb565_color << 3));
|
||||||
u32 args[] = {period_ms, rgb888_color};
|
u32 args[] = {period_ms, rgb888_color};
|
||||||
PXI_DoCMD(PXI_NOTIFY_LED, args, 2);
|
PXI_DoCMD(PXICMD_SET_NOTIFY_LED, args, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// there's some weird thing going on when reading this
|
// there's some weird thing going on when reading this
|
||||||
|
@ -12,7 +12,7 @@ u32 SetScreenBrightness(int level) {
|
|||||||
arg = 0;
|
arg = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return PXI_DoCMD(PXI_BRIGHTNESS, &arg, 1);
|
return PXI_DoCMD(PXICMD_SET_BRIGHTNESS, &arg, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GetBatteryPercent() {
|
u32 GetBatteryPercent() {
|
||||||
|
@ -108,8 +108,7 @@ u32 BootFirmHandler(const char* bootpath, bool verbose, bool delete) {
|
|||||||
if (delete) PathDelete(bootpath);
|
if (delete) PathDelete(bootpath);
|
||||||
DeinitExtFS();
|
DeinitExtFS();
|
||||||
DeinitSDCardFS();
|
DeinitSDCardFS();
|
||||||
PXI_DoCMD(PXI_SET_VMODE, (u32[]){1}, 1);
|
PXI_DoCMD(PXICMD_LEGACY_BOOT, NULL, 0);
|
||||||
PXI_DoCMD(PXI_LEGACY_MODE, NULL, 0);
|
|
||||||
PXI_Barrier(PXI_FIRMLAUNCH_BARRIER);
|
PXI_Barrier(PXI_FIRMLAUNCH_BARRIER);
|
||||||
BootFirm((FirmHeader*) firm, fixpath);
|
BootFirm((FirmHeader*) firm, fixpath);
|
||||||
while(1);
|
while(1);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#include "hid.h"
|
#include "hid.h"
|
||||||
|
|
||||||
SystemSHMEM *shmemGlobalBase;
|
SystemSHMEM *shmemBasePtr;
|
||||||
|
|
||||||
void main(int argc, char** argv, int entrypoint)
|
void main(int argc, char** argv, int entrypoint)
|
||||||
{
|
{
|
||||||
|
@ -13,7 +13,7 @@ bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size)
|
|||||||
if (size >= I2C_SHARED_BUFSZ)
|
if (size >= I2C_SHARED_BUFSZ)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ret = PXI_DoCMD(PXI_I2C_READ, &arg, 1);
|
ret = PXI_DoCMD(PXICMD_I2C_OP, &arg, 1);
|
||||||
|
|
||||||
ARM_InvDC_Range(ARM_GetSHMEM()->i2cBuffer, size);
|
ARM_InvDC_Range(ARM_GetSHMEM()->i2cBuffer, size);
|
||||||
memcpy(out, ARM_GetSHMEM()->i2cBuffer, size);
|
memcpy(out, ARM_GetSHMEM()->i2cBuffer, size);
|
||||||
@ -23,7 +23,7 @@ bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size)
|
|||||||
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;
|
||||||
const u32 arg = devId | (regAddr << 8) | (size << 16);
|
const u32 arg = devId | (regAddr << 8) | (size << 16) | BIT(31);
|
||||||
|
|
||||||
if (size >= I2C_SHARED_BUFSZ)
|
if (size >= I2C_SHARED_BUFSZ)
|
||||||
return false;
|
return false;
|
||||||
@ -33,7 +33,7 @@ bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size)
|
|||||||
ARM_WbDC_Range(ARM_GetSHMEM()->i2cBuffer, size);
|
ARM_WbDC_Range(ARM_GetSHMEM()->i2cBuffer, size);
|
||||||
ARM_DSB();
|
ARM_DSB();
|
||||||
|
|
||||||
ret = PXI_DoCMD(PXI_I2C_WRITE, &arg, 1);
|
ret = PXI_DoCMD(PXICMD_I2C_OP, &arg, 1);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
bool spiflash_get_status(void)
|
bool spiflash_get_status(void)
|
||||||
{
|
{
|
||||||
return PXI_DoCMD(PXI_NVRAM_ONLINE, NULL, 0);
|
return PXI_DoCMD(PXICMD_NVRAM_ONLINE, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool spiflash_read(u32 offset, u32 size, u8 *buf)
|
bool spiflash_read(u32 offset, u32 size, u8 *buf)
|
||||||
@ -19,7 +19,7 @@ bool spiflash_read(u32 offset, u32 size, u8 *buf)
|
|||||||
args[1] = blksz;
|
args[1] = blksz;
|
||||||
|
|
||||||
ARM_WbDC_Range(ARM_GetSHMEM()->spiBuffer, blksz);
|
ARM_WbDC_Range(ARM_GetSHMEM()->spiBuffer, blksz);
|
||||||
PXI_DoCMD(PXI_NVRAM_READ, args, 2);
|
PXI_DoCMD(PXICMD_NVRAM_READ, args, 2);
|
||||||
ARM_InvDC_Range(ARM_GetSHMEM()->spiBuffer, blksz);
|
ARM_InvDC_Range(ARM_GetSHMEM()->spiBuffer, blksz);
|
||||||
ARM_DSB();
|
ARM_DSB();
|
||||||
memcpy(buf, ARM_GetSHMEM()->spiBuffer, blksz);
|
memcpy(buf, ARM_GetSHMEM()->spiBuffer, blksz);
|
||||||
|
@ -1427,8 +1427,7 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
|
|||||||
fixpath[255] = '\0';
|
fixpath[255] = '\0';
|
||||||
DeinitExtFS();
|
DeinitExtFS();
|
||||||
DeinitSDCardFS();
|
DeinitSDCardFS();
|
||||||
PXI_DoCMD(PXI_SET_VMODE, (u32[]){1}, 1);
|
PXI_DoCMD(PXICMD_LEGACY_BOOT, NULL, 0);
|
||||||
PXI_DoCMD(PXI_LEGACY_MODE, NULL, 0);
|
|
||||||
PXI_Barrier(PXI_FIRMLAUNCH_BARRIER);
|
PXI_Barrier(PXI_FIRMLAUNCH_BARRIER);
|
||||||
BootFirm((FirmHeader*)(void*)firm, fixpath);
|
BootFirm((FirmHeader*)(void*)firm, fixpath);
|
||||||
while(1);
|
while(1);
|
||||||
|
17
common/pxi.h
17
common/pxi.h
@ -28,18 +28,17 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PXI_LEGACY_MODE = 0,
|
PXICMD_LEGACY_BOOT = 0,
|
||||||
PXI_GET_SHMEM,
|
PXICMD_GET_SHMEM_ADDRESS,
|
||||||
PXI_SET_VMODE,
|
|
||||||
|
|
||||||
PXI_I2C_READ,
|
PXICMD_I2C_OP,
|
||||||
PXI_I2C_WRITE,
|
PXICMD_NVRAM_ONLINE,
|
||||||
|
PXICMD_NVRAM_READ,
|
||||||
|
|
||||||
PXI_NVRAM_ONLINE,
|
PXICMD_SET_NOTIFY_LED,
|
||||||
PXI_NVRAM_READ,
|
PXICMD_SET_BRIGHTNESS,
|
||||||
|
|
||||||
PXI_NOTIFY_LED,
|
PXICMD_NONE,
|
||||||
PXI_BRIGHTNESS
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -36,7 +36,7 @@ typedef struct {
|
|||||||
#ifdef ARM9
|
#ifdef ARM9
|
||||||
#include <pxi.h>
|
#include <pxi.h>
|
||||||
|
|
||||||
extern SystemSHMEM *shmemGlobalBase;
|
extern SystemSHMEM *shmemBasePtr;
|
||||||
|
|
||||||
static inline SystemSHMEM *ARM_GetSHMEM(void)
|
static inline SystemSHMEM *ARM_GetSHMEM(void)
|
||||||
{
|
{
|
||||||
@ -44,11 +44,11 @@ static inline SystemSHMEM *ARM_GetSHMEM(void)
|
|||||||
// insert a compiler barrier to force the compiler not to assume
|
// insert a compiler barrier to force the compiler not to assume
|
||||||
// memory values will remain constant in between calls to getSHMEM
|
// memory values will remain constant in between calls to getSHMEM
|
||||||
asm_v("":::"memory", "cc");
|
asm_v("":::"memory", "cc");
|
||||||
return shmemGlobalBase;
|
return shmemBasePtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ARM_InitSHMEM(void)
|
static inline void ARM_InitSHMEM(void)
|
||||||
{
|
{
|
||||||
shmemGlobalBase = (SystemSHMEM*)PXI_DoCMD(PXI_GET_SHMEM, NULL, 0);
|
shmemBasePtr = (SystemSHMEM*)PXI_DoCMD(PXICMD_GET_SHMEM_ADDRESS, NULL, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user