mirror of
https://github.com/LNH-team/dspico-usb-examples.git
synced 2026-06-02 09:16:50 +02:00
Initial commit
This commit is contained in:
152
examples/mass-storage/arm9/Makefile
Normal file
152
examples/mass-storage/arm9/Makefile
Normal file
@@ -0,0 +1,152 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
include $(DEVKITARM)/ds_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# INCLUDES is a list of directories containing extra header files
|
||||
# DATA is a list of directories containing binary files
|
||||
# all directories are relative to this makefile
|
||||
#---------------------------------------------------------------------------------
|
||||
BUILD := build
|
||||
SOURCES := source \
|
||||
source/core
|
||||
INCLUDES := include source ../common
|
||||
DATA := data
|
||||
GRAPHICS := gfx
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -marm -mthumb-interwork -DLIBTWL_ARM9 -DARM9
|
||||
|
||||
CFLAGS := -g -Wall -O2\
|
||||
-march=armv5te -mtune=arm946e-s -fomit-frame-pointer\
|
||||
-ffunction-sections -fdata-sections\
|
||||
-ffast-math \
|
||||
-fno-devirtualize-speculatively \
|
||||
-Werror=return-type \
|
||||
$(ARCH)
|
||||
|
||||
CFLAGS += $(INCLUDE)
|
||||
CXXFLAGS := $(CFLAGS) -std=gnu++23 -Wno-volatile -fno-rtti -fno-exceptions -fno-threadsafe-statics\
|
||||
-Wsuggest-override -Werror=suggest-override
|
||||
|
||||
CFLAGS += -Werror=implicit-function-declaration
|
||||
|
||||
ASFLAGS := -g $(ARCH) $(INCLUDE) -march=armv5te -mtune=arm946e-s
|
||||
|
||||
LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),--gc-sections,--use-blx -ffunction-sections -fdata-sections
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with the project
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS := -ltwl9 -lnds9
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(LIBNDS) $(CURDIR)/../../../libs/libtwl/libtwl9 $(CURDIR)/../../../libs/libtwl/common
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export ARM9ELF := $(CURDIR)/$(TARGET).elf
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir))
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||
$(PNGFILES:.png=.o)\
|
||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
.PHONY: $(BUILD) clean
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) *.elf *.nds* *.bin
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
$(ARM9ELF) : $(OFILES)
|
||||
@echo linking $(notdir $@)
|
||||
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
%.nft2.o : %.nft2
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# This rule creates assembly source files using grit
|
||||
# grit takes an image file and a .grit describing how the file is to be processed
|
||||
# add additional rules like this for each image extension
|
||||
# you use in the graphics folders
|
||||
#---------------------------------------------------------------------------------
|
||||
%.s %.h: %.png %.grit
|
||||
#---------------------------------------------------------------------------------
|
||||
grit $< -fts -o$*
|
||||
|
||||
-include $(DEPSDIR)/*.d
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
||||
2
examples/mass-storage/arm9/source/common.h
Normal file
2
examples/mass-storage/arm9/source/common.h
Normal file
@@ -0,0 +1,2 @@
|
||||
#pragma once
|
||||
#include <nds/ndstypes.h>
|
||||
164
examples/mass-storage/arm9/source/dldiIpc.cpp
Normal file
164
examples/mass-storage/arm9/source/dldiIpc.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
#include "common.h"
|
||||
#include <string.h>
|
||||
#include <nds/memory.h>
|
||||
#include <nds/arm9/cache.h>
|
||||
#include <nds/arm9/dldi_asm.h>
|
||||
#include <libtwl/rtos/rtosEvent.h>
|
||||
#include <libtwl/rtos/rtosMutex.h>
|
||||
#include <libtwl/ipc/ipcFifoSystem.h>
|
||||
#include "ipcChannels.h"
|
||||
#include "dldiIpcCommand.h"
|
||||
#include "dldiIpc.h"
|
||||
|
||||
extern u8 gDldiStub[];
|
||||
|
||||
static rtos_mutex_t sMutex;
|
||||
static rtos_event_t sEvent;
|
||||
|
||||
alignas(32) static dldi_ipc_cmd_t sIpcCommand;
|
||||
|
||||
alignas(32) static u8 sTempBuffers[2][512];
|
||||
|
||||
static bool sDldiInitSuccess;
|
||||
|
||||
static void ipcMessageHandler(u32 channel, u32 data, void* arg)
|
||||
{
|
||||
sDldiInitSuccess = data;
|
||||
rtos_signalEvent(&sEvent);
|
||||
}
|
||||
|
||||
static bool setup()
|
||||
{
|
||||
u32 dldiFeatures = *(vu32*)(gDldiStub + 0x64);
|
||||
if (dldiFeatures & FEATURE_SLOT_NDS)
|
||||
REG_EXMEMCNT |= (1 << 11); // slot 1 to arm7
|
||||
if (dldiFeatures & FEATURE_SLOT_GBA)
|
||||
REG_EXMEMCNT |= (1 << 7); // slot 2 to arm7
|
||||
sDldiInitSuccess = false;
|
||||
sIpcCommand.cmd = DLDI_IPC_CMD_SETUP;
|
||||
sIpcCommand.buffer = gDldiStub;
|
||||
sIpcCommand.sector = 0;
|
||||
sIpcCommand.count = 0;
|
||||
rtos_clearEvent(&sEvent);
|
||||
DC_FlushRange(gDldiStub, 16 * 1024);
|
||||
DC_FlushRange(&sIpcCommand, sizeof(sIpcCommand));
|
||||
ipc_sendFifoMessage(IPC_CHANNEL_DLDI, (u32)&sIpcCommand >> 2);
|
||||
rtos_waitEvent(&sEvent, false, true);
|
||||
return sDldiInitSuccess;
|
||||
}
|
||||
|
||||
bool dldi_init()
|
||||
{
|
||||
rtos_createMutex(&sMutex);
|
||||
rtos_createEvent(&sEvent);
|
||||
ipc_setChannelHandler(IPC_CHANNEL_DLDI, ipcMessageHandler, nullptr);
|
||||
return setup();
|
||||
}
|
||||
|
||||
static void readSectorsCacheAligned(void* buffer, u32 sector, u32 count)
|
||||
{
|
||||
sIpcCommand.cmd = DLDI_IPC_CMD_READ_SECTORS;
|
||||
sIpcCommand.buffer = buffer;
|
||||
sIpcCommand.sector = sector;
|
||||
sIpcCommand.count = count;
|
||||
DC_InvalidateRange(buffer, 512 * count);
|
||||
rtos_clearEvent(&sEvent);
|
||||
DC_FlushRange(&sIpcCommand, sizeof(sIpcCommand));
|
||||
ipc_sendFifoMessage(IPC_CHANNEL_DLDI, (u32)&sIpcCommand >> 2);
|
||||
rtos_waitEvent(&sEvent, false, true);
|
||||
}
|
||||
|
||||
static void readSectorsNotCacheAligned(void* buffer, u32 sector, u32 count)
|
||||
{
|
||||
rtos_clearEvent(&sEvent);
|
||||
sIpcCommand.cmd = DLDI_IPC_CMD_READ_SECTORS;
|
||||
sIpcCommand.count = 1;
|
||||
// not cache aligned, use a temp buffer
|
||||
DC_InvalidateRange(sTempBuffers[0], 512);
|
||||
for (u32 i = 0; i < count; i++)
|
||||
{
|
||||
sIpcCommand.buffer = sTempBuffers[i & 1];
|
||||
sIpcCommand.sector = sector + i;
|
||||
DC_FlushRange(&sIpcCommand, sizeof(sIpcCommand));
|
||||
ipc_sendFifoMessage(IPC_CHANNEL_DLDI, (u32)&sIpcCommand >> 2);
|
||||
if (i != 0)
|
||||
memcpy((u8*)buffer + 512 * (i - 1), sTempBuffers[(i - 1) & 1], 512);
|
||||
if (i != count - 1)
|
||||
DC_InvalidateRange(sTempBuffers[(i + 1) & 1], 512);
|
||||
rtos_waitEvent(&sEvent, false, true);
|
||||
}
|
||||
memcpy((u8*)buffer + 512 * (count - 1), sTempBuffers[(count - 1) & 1], 512);
|
||||
}
|
||||
|
||||
extern "C" void dldi_readSectors(void* buffer, u32 sector, u32 count)
|
||||
{
|
||||
if (count == 0)
|
||||
return;
|
||||
rtos_lockMutex(&sMutex);
|
||||
{
|
||||
if ((u32)buffer & 0x1F)
|
||||
{
|
||||
readSectorsNotCacheAligned(buffer, sector, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
readSectorsCacheAligned(buffer, sector, count);
|
||||
}
|
||||
}
|
||||
rtos_unlockMutex(&sMutex);
|
||||
}
|
||||
|
||||
static void writeSectorsCacheAligned(const void* buffer, u32 sector, u32 count)
|
||||
{
|
||||
sIpcCommand.cmd = DLDI_IPC_CMD_WRITE_SECTORS;
|
||||
sIpcCommand.buffer = (void*)buffer;
|
||||
sIpcCommand.sector = sector;
|
||||
sIpcCommand.count = count;
|
||||
DC_FlushRange(buffer, 512 * count);
|
||||
rtos_clearEvent(&sEvent);
|
||||
DC_FlushRange(&sIpcCommand, sizeof(sIpcCommand));
|
||||
ipc_sendFifoMessage(IPC_CHANNEL_DLDI, (u32)&sIpcCommand >> 2);
|
||||
rtos_waitEvent(&sEvent, false, true);
|
||||
}
|
||||
|
||||
static void writeSectorsNotCacheAligned(const void* buffer, u32 sector, u32 count)
|
||||
{
|
||||
rtos_clearEvent(&sEvent);
|
||||
sIpcCommand.cmd = DLDI_IPC_CMD_WRITE_SECTORS;
|
||||
sIpcCommand.count = 1;
|
||||
// not cache aligned, use a temp buffer
|
||||
memcpy(sTempBuffers[0], (u8*)buffer, 512);
|
||||
DC_FlushRange(sTempBuffers[0], 512);
|
||||
for (u32 i = 0; i < count; i++)
|
||||
{
|
||||
sIpcCommand.buffer = sTempBuffers[i & 1];
|
||||
sIpcCommand.sector = sector + i;
|
||||
DC_FlushRange(&sIpcCommand, sizeof(sIpcCommand));
|
||||
ipc_sendFifoMessage(IPC_CHANNEL_DLDI, (u32)&sIpcCommand >> 2);
|
||||
if (i != count - 1)
|
||||
{
|
||||
memcpy(sTempBuffers[(i + 1) & 1], (u8*)buffer + 512 * (i + 1), 512);
|
||||
DC_FlushRange(sTempBuffers[(i + 1) & 1], 512);
|
||||
}
|
||||
rtos_waitEvent(&sEvent, false, true);
|
||||
}
|
||||
memcpy((u8*)buffer + 512 * (count - 1), sTempBuffers[(count - 1) & 1], 512);
|
||||
}
|
||||
|
||||
extern "C" void dldi_writeSectors(const void* buffer, u32 sector, u32 count)
|
||||
{
|
||||
if (count == 0)
|
||||
return;
|
||||
rtos_lockMutex(&sMutex);
|
||||
{
|
||||
if ((u32)buffer & 0x1F)
|
||||
{
|
||||
writeSectorsNotCacheAligned(buffer, sector, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
writeSectorsCacheAligned(buffer, sector, count);
|
||||
}
|
||||
}
|
||||
rtos_unlockMutex(&sMutex);
|
||||
}
|
||||
14
examples/mass-storage/arm9/source/dldiIpc.h
Normal file
14
examples/mass-storage/arm9/source/dldiIpc.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
bool dldi_init();
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void dldi_readSectors(void* buffer, u32 sector, u32 count);
|
||||
void dldi_writeSectors(const void* buffer, u32 sector, u32 count);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
100
examples/mass-storage/arm9/source/dldi_stub.s
Normal file
100
examples/mass-storage/arm9/source/dldi_stub.s
Normal file
@@ -0,0 +1,100 @@
|
||||
/*---------------------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2006 - 2016
|
||||
Michael Chisholm (Chishm)
|
||||
Dave Murphy (WinterMute)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you
|
||||
must not claim that you wrote the original software. If you use
|
||||
this software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
---------------------------------------------------------------------------------*/
|
||||
|
||||
#include <nds/arm9/dldi_asm.h>
|
||||
|
||||
.align 4
|
||||
.arm
|
||||
.global gDldiStub
|
||||
@---------------------------------------------------------------------------------
|
||||
|
||||
.equ DLDI_ALLOCATED_SPACE, 16384
|
||||
|
||||
gDldiStub:
|
||||
|
||||
dldi_start:
|
||||
|
||||
@---------------------------------------------------------------------------------
|
||||
@ Driver patch file standard header -- 16 bytes
|
||||
.word 0xBF8DA5ED @ Magic number to identify this region
|
||||
.asciz " Chishm" @ Identifying Magic string (8 bytes with null terminator)
|
||||
.byte 0x01 @ Version number
|
||||
.byte DLDI_SIZE_16KB @16KiB @ Log [base-2] of the size of this driver in bytes.
|
||||
.byte 0x00 @ Sections to fix
|
||||
.byte DLDI_SIZE_16KB @16KiB @ Log [base-2] of the allocated space in bytes.
|
||||
|
||||
@---------------------------------------------------------------------------------
|
||||
@ Text identifier - can be anything up to 47 chars + terminating null -- 16 bytes
|
||||
.align 4
|
||||
.asciz "Default (No interface)"
|
||||
|
||||
@---------------------------------------------------------------------------------
|
||||
@ Offsets to important sections within the data -- 32 bytes
|
||||
.align 6
|
||||
.word 0x037F8000 //dldi_start @ data start
|
||||
.word 0x037FC000 //dldi_end @ data end
|
||||
.word 0x00000000 @ Interworking glue start -- Needs address fixing
|
||||
.word 0x00000000 @ Interworking glue end
|
||||
.word 0x00000000 @ GOT start -- Needs address fixing
|
||||
.word 0x00000000 @ GOT end
|
||||
.word 0x00000000 @ bss start -- Needs setting to zero
|
||||
.word 0x00000000 @ bss end
|
||||
|
||||
@---------------------------------------------------------------------------------
|
||||
@ DISC_INTERFACE data -- 32 bytes
|
||||
.ascii "DLDI" @ ioType
|
||||
.word 0x00000000 @ Features
|
||||
.word _DLDI_startup @
|
||||
.word _DLDI_isInserted @
|
||||
.word _DLDI_readSectors @ Function pointers to standard device driver functions
|
||||
.word _DLDI_writeSectors @
|
||||
.word _DLDI_clearStatus @
|
||||
.word _DLDI_shutdown @
|
||||
|
||||
@---------------------------------------------------------------------------------
|
||||
|
||||
_DLDI_startup:
|
||||
_DLDI_isInserted:
|
||||
_DLDI_readSectors:
|
||||
_DLDI_writeSectors:
|
||||
_DLDI_clearStatus:
|
||||
_DLDI_shutdown:
|
||||
mov r0, #0x00 @ Return false for every function
|
||||
bx lr
|
||||
|
||||
|
||||
|
||||
@---------------------------------------------------------------------------------
|
||||
.align
|
||||
.pool
|
||||
|
||||
dldi_data_end:
|
||||
|
||||
@ Pad to end of allocated space
|
||||
.space DLDI_ALLOCATED_SPACE - (dldi_data_end - dldi_start)
|
||||
|
||||
dldi_end:
|
||||
.end
|
||||
@---------------------------------------------------------------------------------
|
||||
55
examples/mass-storage/arm9/source/main.cpp
Normal file
55
examples/mass-storage/arm9/source/main.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#include "common.h"
|
||||
#include <libtwl/gfx/gfxStatus.h>
|
||||
#include <libtwl/mem/memExtern.h>
|
||||
#include <libtwl/rtos/rtosIrq.h>
|
||||
#include <libtwl/rtos/rtosThread.h>
|
||||
#include <libtwl/rtos/rtosEvent.h>
|
||||
#include <libtwl/ipc/ipcSync.h>
|
||||
#include <libtwl/ipc/ipcFifoSystem.h>
|
||||
#include "dldiIpc.h"
|
||||
|
||||
static rtos_event_t sVblankEvent;
|
||||
|
||||
static void vblankIrq(u32 irqMask)
|
||||
{
|
||||
rtos_signalEvent(&sVblankEvent);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
*(vu32*)0x04000000 = 0x10000;
|
||||
*(vu16*)0x05000000 = 31 << 10;
|
||||
*(vu16*)0x0400006C = 0;
|
||||
|
||||
mem_setDsCartridgeCpu(EXMEMCNT_SLOT1_CPU_ARM7);
|
||||
|
||||
rtos_initIrq();
|
||||
rtos_startMainThread();
|
||||
ipc_initFifoSystem();
|
||||
|
||||
rtos_createEvent(&sVblankEvent);
|
||||
|
||||
while (ipc_getArm7SyncBits() != 7);
|
||||
|
||||
if (dldi_init())
|
||||
{
|
||||
*(vu16*)0x05000000 = (31 << 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
*(vu16*)0x05000000 = 31;
|
||||
}
|
||||
|
||||
ipc_setArm9SyncBits(6);
|
||||
|
||||
rtos_setIrqFunc(RTOS_IRQ_VBLANK, vblankIrq);
|
||||
rtos_enableIrqMask(RTOS_IRQ_VBLANK);
|
||||
gfx_setVBlankIrqEnabled(true);
|
||||
|
||||
while (true)
|
||||
{
|
||||
rtos_waitEvent(&sVblankEvent, true, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user