diff options
| author | spicyjpeg <thatspicyjpeg@gmail.com> | 2022-10-13 23:21:32 +0200 |
|---|---|---|
| committer | spicyjpeg <thatspicyjpeg@gmail.com> | 2022-10-13 23:21:32 +0200 |
| commit | b458ea70700739bf8a64217af369c7ace08fc954 (patch) | |
| tree | 77281ebd18e5049fcb1c86718854ff3ce91e54c2 | |
| parent | 8e92156bc6a977651771d2cf91ac5800a0e9a913 (diff) | |
| download | psn00bsdk-b458ea70700739bf8a64217af369c7ace08fc954.tar.gz | |
Fix dropped IRQs, clean up psxcd and psxetc logging
| -rw-r--r-- | doc/known_bugs.md | 7 | ||||
| -rw-r--r-- | examples/system/childexec/CMakeLists.txt | 18 | ||||
| -rw-r--r-- | examples/system/childexec/child/child.c | 8 | ||||
| -rw-r--r-- | examples/system/childexec/parent.c | 27 | ||||
| -rw-r--r-- | libpsn00b/psxcd/isofs.c | 20 | ||||
| -rw-r--r-- | libpsn00b/psxcd/psxcd.c | 9 | ||||
| -rw-r--r-- | libpsn00b/psxetc/dl.c | 98 | ||||
| -rw-r--r-- | libpsn00b/psxetc/interrupts.c | 50 |
8 files changed, 107 insertions, 130 deletions
diff --git a/doc/known_bugs.md b/doc/known_bugs.md index 9e4785c..620a805 100644 --- a/doc/known_bugs.md +++ b/doc/known_bugs.md @@ -37,11 +37,6 @@ fixed. due to the SPU status register being emulated incorrectly. They work as expected on other emulators as well as on real hardware. -`psxcd`: - -- Custom callbacks registered using `CdReadyCallback()` seem to be unstable on - DuckStation (and possibly on real hardware), occasionally dropping sectors. - `psxetc`: - `DL_LoadSymbolMapFromFile()`, `DL_LoadDLLFromFile()` and `dlopen()` have been @@ -54,4 +49,4 @@ fixed. See [README.md in the examples directory](../examples/README.md#examples-summary). ----------------------------------------- -_Last updated on 2022-10-11 by spicyjpeg_ +_Last updated on 2022-10-13 by spicyjpeg_ diff --git a/examples/system/childexec/CMakeLists.txt b/examples/system/childexec/CMakeLists.txt index 0c25ca4..e542d2a 100644 --- a/examples/system/childexec/CMakeLists.txt +++ b/examples/system/childexec/CMakeLists.txt @@ -13,14 +13,14 @@ project( file(GLOB _sources *.c) file(GLOB _child_sources child/*.c) -psn00bsdk_add_executable(parent GPREL ${_sources}) -psn00bsdk_add_executable(child GPREL ${_child_sources}) -#psn00bsdk_add_cd_image(childexec_iso childexec iso.xml DEPENDS parent) +psn00bsdk_add_executable(childexec GPREL ${_sources}) +psn00bsdk_add_executable(childexec_child GPREL ${_child_sources}) +#psn00bsdk_add_cd_image(childexec_iso childexec iso.xml DEPENDS childexec) -psn00bsdk_target_incbin(parent PRIVATE ball16c ball16c.tim) +psn00bsdk_target_incbin(childexec PRIVATE ball16c ball16c.tim) psn00bsdk_target_incbin( - parent PRIVATE child_exe - ${PROJECT_BINARY_DIR}/child.exe + childexec PRIVATE child_exe + ${PROJECT_BINARY_DIR}/childexec_child.exe ) # Relocate the child executable to a non-default address to prevent it from @@ -28,9 +28,9 @@ psn00bsdk_target_incbin( # NOTE: child executables are not position-independent and can't be relocated # at runtime. If you need your code to be relocatable (e.g. to load it into a # dynamically-allocated buffer), consider using a DLL instead. -target_link_options(child PRIVATE -Ttext=0x80030000) +target_link_options(childexec_child PRIVATE -Ttext=0x80030000) # Make sure the child executable is built before the parent. -add_dependencies(parent child) +add_dependencies(childexec childexec_child) -install(FILES ${PROJECT_BINARY_DIR}/parent.exe TYPE BIN) +install(FILES ${PROJECT_BINARY_DIR}/childexec.exe TYPE BIN) diff --git a/examples/system/childexec/child/child.c b/examples/system/childexec/child/child.c index bd17440..dcfbfaf 100644 --- a/examples/system/childexec/child/child.c +++ b/examples/system/childexec/child/child.c @@ -98,8 +98,8 @@ MATRIX light_mtx = { char pad_buff[2][34]; /* Function declarations */ -void init(); -void display(); +void init(void); +void display(void); /* Main function */ @@ -245,7 +245,7 @@ int main(int argc, const char *argv[]) { } -void init() { +void init(void) { /* Reset the GPU, also installs a VSync event handler */ ResetGraph( 0 ); @@ -300,7 +300,7 @@ void init() { } -void display() { +void display(void) { /* Wait for GPU to finish drawing and vertical retrace */ DrawSync( 0 ); diff --git a/examples/system/childexec/parent.c b/examples/system/childexec/parent.c index 3e7d218..83d964c 100644 --- a/examples/system/childexec/parent.c +++ b/examples/system/childexec/parent.c @@ -67,12 +67,12 @@ extern const uint32_t ball16c[]; TIM_IMAGE tim; -void run_child(); +void run_child(void); char pad_buff[2][34]; -void init() { +void init(void) { int i; @@ -270,10 +270,7 @@ typedef struct { // Child program address extern char child_exe[]; -// Manually defined as its not defined in psxapi by default -void SetDefaultExitFromException(); - -void run_child() { +void run_child(void) { // Arguments for the child program char *args[] = @@ -289,29 +286,23 @@ void run_child() { // Copy child executable to its intended adddress memcpy((void*)exe->param.t_addr, child_exe+2048, exe->param.t_size); - // Enter critical section to prepare for program execution - EnterCriticalSection(); + // Prepare for program execution and disable interrupts + //EnterCriticalSection(); + StopCallback(); // Stop pads, enable auto acknowledge StopPAD(); ChangeClearPAD(1); ChangeClearRCnt(3, 1); - - // Set default exception handler just in case - //SetDefaultExitFromException(); - - // Last three function calls could be relegated to - // a StopCallback() function in the future. - + // Execute child printf("Child exec!\n"); Exec(&exe->param, 3, args); // Restore interrupts for this PS-EXE - EnterCriticalSection(); RestartCallback(); - ExitCriticalSection(); - + //ExitCriticalSection(); + // Re-init and re-enable pads InitPAD(pad_buff[0], 34, pad_buff[1], 34); StartPAD(); diff --git a/libpsn00b/psxcd/isofs.c b/libpsn00b/psxcd/isofs.c index fb1f6c9..16e64ef 100644 --- a/libpsn00b/psxcd/isofs.c +++ b/libpsn00b/psxcd/isofs.c @@ -148,7 +148,7 @@ static int _CdReadIsoDirectory(int lba) CdIntToPos(lba, &loc); i = CdPosToInt(&loc); - _LOG("psxcd_dbg: Seek to sector %d\n", i); + _LOG("psxcd: Seek to sector %d\n", i); if( !CdControl(CdlSetloc, (uint8_t*)&loc, 0) ) { @@ -232,7 +232,7 @@ static void dump_directory(void) strncpy(namebuff, _cd_iso_directory_buff+dir_pos+sizeof(ISO_DIR_ENTRY), dir_entry->identifierLen); - _LOG("P:%d L:%d %s\n", dir_pos, dir_entry->identifierLen, namebuff); + _LOG("psxcd: P:%d L:%d %s\n", dir_pos, dir_entry->identifierLen, namebuff); dir_pos += dir_entry->entryLength; i++; @@ -251,7 +251,7 @@ static void dump_directory(void) } } - _LOG("--\n"); + _LOG("psxcd: --\n"); } @@ -534,7 +534,7 @@ CdlFILE *CdSearchFile(CdlFILE *fp, const char *filename) } #ifndef NDEBUG - dump_directory(); + //dump_directory(); #endif if( find_dir_entry(fp->name, &dir_entry) ) @@ -582,7 +582,7 @@ CdlDIR *CdOpenDir(const char* path) for( i=1; i<num_dirs; i++ ) { rbuff = resolve_pathtable_path( i, tpath_rbuff+127 ); - _LOG( "psxcd_dbg: Found = %s|\n", rbuff ); + _LOG( "psxcd: Found = %s|\n", rbuff ); if( rbuff ) { @@ -596,14 +596,14 @@ CdlDIR *CdOpenDir(const char* path) if( !found_dir ) { - _LOG( "psxcd_dbg: Directory path not found.\n" ); + _LOG( "psxcd: Directory path not found.\n" ); return NULL; } - _LOG( "psxcd_dbg: Found directory at record %d!\n", found_dir ); + _LOG( "psxcd: Found directory at record %d!\n", found_dir ); get_pathtable_entry( found_dir, &tbl_entry, NULL ); - _LOG( "psxcd_dbg: Directory LBA = %d\n", tbl_entry.dirOffs ); + _LOG( "psxcd: Directory LBA = %d\n", tbl_entry.dirOffs ); _CdReadIsoDirectory( tbl_entry.dirOffs ); @@ -668,11 +668,11 @@ int CdReadDir(CdlDIR *dir, CdlFILE* file) file->size = dir_entry->entrySize.lsb; - _LOG("dir_entry->entryLength = %d, ", dir_entry->entryLength); + _LOG("psxcd: dir_entry->entryLength = %d, ", dir_entry->entryLength); d_dir->_pos += dir_entry->entryLength; - _LOG("d_dir->_pos = %d\n", d_dir->_pos); + _LOG("psxcd: d_dir->_pos = %d\n", d_dir->_pos); // Check if padding is reached (end of record sector) if( d_dir->_dir[d_dir->_pos] == 0 ) diff --git a/libpsn00b/psxcd/psxcd.c b/libpsn00b/psxcd/psxcd.c index 65dea48..160a1ed 100644 --- a/libpsn00b/psxcd/psxcd.c +++ b/libpsn00b/psxcd/psxcd.c @@ -46,7 +46,7 @@ int CdInit(void) { CdControl(CdlDemute, 0, 0); _LOG("psxcd: setup done\n"); } else { - _LOG("psxcd: initialization error, bad disc/drive or no disc inserted\n"); + _LOG("psxcd: setup error, bad disc/drive or no disc inserted\n"); } return 1; @@ -106,14 +106,8 @@ int CdControlF(unsigned char com, const void *param) param_len = 2; break; case CdlSetmode: - param_len = 1; - break; case CdlSetsession: - param_len = 1; - break; case CdlTest: - param_len = 1; - break; case CdlGetTD: param_len = 1; break; @@ -126,6 +120,7 @@ int CdControlF(unsigned char com, const void *param) _cd_control(CdlSetloc, param, 3); _cd_last_setloc = *((CdlLOC*)param); } + break; } // Issue CD command diff --git a/libpsn00b/psxetc/dl.c b/libpsn00b/psxetc/dl.c index 3d8f3ab..cf4e466 100644 --- a/libpsn00b/psxetc/dl.c +++ b/libpsn00b/psxetc/dl.c @@ -34,9 +34,6 @@ /* Compile options */ -// Uncomment before building to enable debug logging (via printf()). -//#define DEBUG - // Comment before building to disable functions that rely on BIOS file APIs, // i.e. DL_LoadSymbolMapFromFile() and DL_LoadDLLFromFile(). // FIXME: those seem to be broken currently, and shouldn't be used anyway @@ -95,7 +92,7 @@ void *_dl_resolve_helper(DLL *dll, uint32_t index) { address = DL_GetSymbolByName(_name); if (!address) { - _LOG("psxetc: FATAL! Can't resolve %s, locking up\n", _name); + _LOG("psxetc: FATAL! can't resolve %s, locking up\n", _name); while (1) __asm__ volatile("nop"); } @@ -136,7 +133,7 @@ static uint32_t _elf_hash(const char *str) { static uint8_t *_dl_load_file(const char *filename, size_t *size_output) { int32_t fd = open(filename, 1); if (fd < 0) { - _LOG("psxetc: Can't open %s, error = %d\n", filename, fd); + _LOG("psxetc: can't open %s, error = %d\n", filename, fd); _ERROR(RTLD_E_FILE_OPEN, 0); } @@ -147,11 +144,11 @@ static uint8_t *_dl_load_file(const char *filename, size_t *size_output) { uint8_t *buffer = malloc(size); if (!buffer) { - _LOG("psxetc: Unable to allocate %d bytes for %s\n", size, filename); + _LOG("psxetc: unable to allocate %d bytes for %s\n", size, filename); _ERROR(RTLD_E_FILE_ALLOC, 0); } - _LOG("psxetc: Loading %s (%d bytes)..", filename, size); + //_LOG("psxetc: loading %s (%d bytes)..", filename, size); for (uint32_t offset = 0; offset < size; ) { int32_t length = read(fd, &(buffer[offset]), 0x800); @@ -164,7 +161,7 @@ static uint8_t *_dl_load_file(const char *filename, size_t *size_output) { _ERROR(RTLD_E_FILE_READ, 0); } - _LOG("."); + //_LOG("."); offset += length; } @@ -196,7 +193,7 @@ int32_t DL_ParseSymbolMap(const char *ptr, size_t size) { _symbol_map.nbucket = entries; _symbol_map.nchain = entries; _LOG( - "psxetc: Allocating nbucket = %d, nchain = %d\n", + "psxetc: allocating nbucket = %d, nchain = %d\n", _symbol_map.nbucket, entries ); @@ -208,7 +205,7 @@ int32_t DL_ParseSymbolMap(const char *ptr, size_t size) { _symbol_map.chain = malloc(sizeof(uint32_t) * entries); if (!_symbol_map.entries || !_symbol_map.bucket || !_symbol_map.chain) { - _LOG("psxetc: Unable to allocate symbol map table\n"); + _LOG("psxetc: unable to allocate symbol map table\n"); _ERROR(RTLD_E_MAP_ALLOC, -1); } @@ -251,13 +248,10 @@ int32_t DL_ParseSymbolMap(const char *ptr, size_t size) { (_type == 'D') || // .data (_type == 'B') // .bss )) { - _LOG( - "psxetc: Map sym: %08x,%08x [%c %s]\n", - address, - _size, - _type, - name - ); + //_LOG( + //"psxetc: map sym: %08x,%08x [%c %s]\n", + //address, _size, _type, name + //); MapEntry *entry = &(_symbol_map.entries[index]); entry->hash = hash; @@ -280,7 +274,7 @@ int32_t DL_ParseSymbolMap(const char *ptr, size_t size) { pos++; } - _LOG("psxetc: Parsed %d symbols\n", entries); + _LOG("psxetc: parsed %d symbols\n", entries); if (!entries) _ERROR(RTLD_E_NO_SYMBOLS, -1); @@ -313,7 +307,7 @@ void DL_UnloadSymbolMap(void) { void *DL_GetSymbolByName(const char *name) { if (!_symbol_map.entries) { - _LOG("psxetc: Attempted lookup with no map loaded\n"); + _LOG("psxetc: attempted lookup with no map loaded\n"); _ERROR(RTLD_E_NO_MAP, 0); } @@ -326,9 +320,8 @@ void *DL_GetSymbolByName(const char *name) { for (uint32_t i = _symbol_map.bucket[hash_mod]; i != 0xffffffff;) { if (i >= _symbol_map.nchain) { _LOG( - "psxetc: GetSymbolByName() index out of bounds (i = %d, n = %d)\n", - i, - _symbol_map.nchain + "psxetc: GetSymbolByName() index out of bounds (%d >= %d)\n", + i, _symbol_map.nchain ); _ERROR(RTLD_E_HASH_LOOKUP, 0); } @@ -336,14 +329,14 @@ void *DL_GetSymbolByName(const char *name) { MapEntry *entry = &(_symbol_map.entries[i]); if (hash == entry->hash) { - _LOG("psxetc: Map lookup [%s = %08x]\n", name, entry->ptr); + //_LOG("psxetc: map lookup [%s = %08x]\n", name, entry->ptr); return entry->ptr; } i = _symbol_map.chain[i]; } - _LOG("psxetc: Map lookup [%s not found]\n", name); + _LOG("psxetc: map lookup [%s not found]\n", name); _ERROR(RTLD_E_MAP_SYMBOL, 0); } @@ -359,14 +352,14 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) { DLL *dll = malloc(sizeof(DLL)); if (!dll) { - _LOG("psxetc: Unable to allocate DLL struct\n"); + _LOG("psxetc: unable to allocate DLL struct\n"); _ERROR(RTLD_E_DLL_ALLOC, 0); } dll->ptr = ptr; dll->malloc_ptr = (mode & RTLD_FREE_ON_DESTROY) ? ptr : 0; dll->size = size; - _LOG("psxetc: Initializing DLL at %08x\n", ptr); + _LOG("psxetc: initializing DLL at %08x\n", ptr); // Interpret the key-value pairs in the .dynamic section to obtain info // about all the other sections. The pairs are null-terminated, which makes @@ -375,33 +368,33 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) { uint32_t first_got_sym = 0; for (Elf32_Dyn *dyn = (Elf32_Dyn *) ptr; dyn->d_tag; dyn++) { - _LOG("psxetc: .dynamic %08x=%08x ", dyn->d_tag, dyn->d_un.d_val); + //_LOG("psxetc: .dynamic %08x=%08x ", dyn->d_tag, dyn->d_un.d_val); switch (dyn->d_tag) { // Offset of .got section case DT_PLTGOT: - _LOG("[PLTGOT]\n"); + //_LOG("[PLTGOT]\n"); dll->got = (void *) (ptr + dyn->d_un.d_val); break; // Offset of .hash section case DT_HASH: - _LOG("[HASH]\n"); + //_LOG("[HASH]\n"); dll->hash = (void *) (ptr + dyn->d_un.d_val); break; // Offset of .dynstr (NOT .strtab) section case DT_STRTAB: - _LOG("[STRTAB]\n"); + //_LOG("[STRTAB]\n"); dll->strtab = (void *) (ptr + dyn->d_un.d_val); break; // Offset of .dynsym (NOT .symtab) section case DT_SYMTAB: - _LOG("[SYMTAB]\n"); + //_LOG("[SYMTAB]\n"); dll->symtab = (void *) (ptr + dyn->d_un.d_val); break; @@ -413,67 +406,67 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) { // Length of each .dynsym entry case DT_SYMENT: - _LOG("[SYMENT]\n"); + //_LOG("[SYMENT]\n"); // Only 16-byte symbol table entries are supported. if (dyn->d_un.d_val != sizeof(Elf32_Sym)) { free(dll); - _LOG("psxetc: Invalid symtab entry size %d\n", dyn->d_un.d_val); + _LOG("psxetc: invalid DLL symtab entry size %d\n", dyn->d_un.d_val); _ERROR(RTLD_E_DLL_FORMAT, 0); } break; // MIPS ABI (?) version case DT_MIPS_RLD_VERSION: - _LOG("[MIPS_RLD_VERSION]\n"); + //_LOG("[MIPS_RLD_VERSION]\n"); // Versions other than 1 are unsupported (do they even exist?). if (dyn->d_un.d_val != 1) { free(dll); - _LOG("psxetc: Invalid DLL version %d\n", dyn->d_un.d_val); + _LOG("psxetc: invalid DLL version %d\n", dyn->d_un.d_val); _ERROR(RTLD_E_DLL_FORMAT, 0); } break; // DLL/ABI flags case DT_MIPS_FLAGS: - _LOG("[MIPS_FLAGS]\n"); + //_LOG("[MIPS_FLAGS]\n"); // Shortcut pointers (whatever they are) are not supported. if (dyn->d_un.d_val & RHF_QUICKSTART) { free(dll); - _LOG("psxetc: Invalid flags\n"); + _LOG("psxetc: invalid DLL flags\n"); _ERROR(RTLD_E_DLL_FORMAT, 0); } break; // Number of local (not to resolve) GOT entries case DT_MIPS_LOCAL_GOTNO: - _LOG("[MIPS_LOCAL_GOTNO]\n"); + //_LOG("[MIPS_LOCAL_GOTNO]\n"); local_got_len = dyn->d_un.d_val; break; // Base address DLL was compiled for case DT_MIPS_BASE_ADDRESS: - _LOG("[MIPS_BASE_ADDRESS]\n"); + //_LOG("[MIPS_BASE_ADDRESS]\n"); // Base addresses other than zero are not supported. It would // be easy enough to support them, but why? if (dyn->d_un.d_val) { free(dll); - _LOG("psxetc: Invalid base address %08x\n", dyn->d_un.d_val); + _LOG("psxetc: invalid DLL base address %08x\n", dyn->d_un.d_val); _ERROR(RTLD_E_DLL_FORMAT, 0); } break; // Number of symbol table entries case DT_MIPS_SYMTABNO: - _LOG("[MIPS_SYMTABNO]\n"); + //_LOG("[MIPS_SYMTABNO]\n"); dll->symbol_count = dyn->d_un.d_val; break; @@ -485,7 +478,7 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) { // Index of first symbol table entry which has a matching GOT entry case DT_MIPS_GOTSYM: - _LOG("[MIPS_GOTSYM]\n"); + //_LOG("[MIPS_GOTSYM]\n"); first_got_sym = dyn->d_un.d_val; break; @@ -495,8 +488,8 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) { //_LOG("[MIPS_HIPAGENO]\n"); //break; - default: - _LOG("[ignored]\n"); + //default: + //_LOG("[ignored]\n"); } } @@ -510,8 +503,7 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) { dll->got_length = local_got_len + (dll->symbol_count - first_got_sym) - 2; _LOG( "psxetc: %d symbols, %d GOT entries\n", - dll->symbol_count, - dll->got_length + dll->symbol_count, dll->got_length ); // Relocate the DLL by adding its base address to all pointers in the GOT @@ -538,12 +530,10 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) { continue; sym->st_value += (uint32_t) ptr; - _LOG( - "psxetc: DLL sym: %08x,%08x [%s]\n", - sym->st_value, - sym->st_size, - _name - ); + //_LOG( + //"psxetc: DLL sym: %08x,%08x [%s]\n", + //sym->st_value, sym->st_size, _name + //); // If RTLD_NOW was passed, resolve GOT entries ahead of time by // cross-referencing them with the symbol table. @@ -651,7 +641,7 @@ void *DL_GetDLLSymbol(const DLL *dll, const char *name) { // provided. for (uint32_t i = bucket[hash_mod]; i != 0xffffffff;) { if (i >= nchain) { - _LOG("psxetc: DL_GetDLLSymbol() index out of bounds (i = %d, n = %d)\n", i, nchain); + _LOG("psxetc: DL_GetDLLSymbol() index out of bounds (%d >= %d)\n", i, nchain); _ERROR(RTLD_E_HASH_LOOKUP, 0); } @@ -659,7 +649,7 @@ void *DL_GetDLLSymbol(const DLL *dll, const char *name) { const char *_name = &(dll->strtab[sym->st_name]); if (!strcmp(name, _name)) { - _LOG("psxetc: DLL lookup [%s = %08x]\n", name, sym->st_value); + //_LOG("psxetc: DLL lookup [%s = %08x]\n", name, sym->st_value); return sym->st_value; } diff --git a/libpsn00b/psxetc/interrupts.c b/libpsn00b/psxetc/interrupts.c index 1b5ac32..cc9d12c 100644 --- a/libpsn00b/psxetc/interrupts.c +++ b/libpsn00b/psxetc/interrupts.c @@ -53,40 +53,46 @@ static const struct JMP_BUF _isr_jmp_buf = { /* Internal IRQ and DMA handlers */ static void _global_isr(void) { - uint16_t stat = IRQ_STAT, mask = IRQ_MASK; + uint16_t stat = IRQ_STAT & IRQ_MASK; - // Clear all IRQ flags in one shot. This is not the "proper" way to do it - // but it's much faster than clearing one flag at a time. - IRQ_STAT = ~mask; + for (; stat; stat = IRQ_STAT & IRQ_MASK) { + //for (int i = 0; i < NUM_IRQ_CHANNELS; i++) { + for (int i = 0, mask = 1; stat; i++, stat >>= 1, mask <<= 1) { + if (!(stat & 1)) + continue; - //for (int i = 0; i < NUM_IRQ_CHANNELS; i++) { - for (int i = 0; stat; i++, stat >>= 1) { - if (!(stat & 1)) - continue; + // Acknowledge the current IRQ. Note that clearing all IRQ flags in one + // shot would result in hard-to-debug race conditions (been there, done + // that). + IRQ_STAT = (uint16_t) (mask ^ 0xffff); - if (_irq_handlers[i]) - _irq_handlers[i](); + if (_irq_handlers[i]) + _irq_handlers[i](); + } } ReturnFromException(); } static void _global_dma_handler(void) { - uint32_t stat = DMA_DICR; + uint32_t dicr = DMA_DICR; + uint32_t stat = (dicr >> 24) & 0x7f; + + for (; stat; dicr = DMA_DICR, stat = (dicr >> 24) & 0x7f) { + uint32_t base = dicr & 0x00ffffff; - // Clear all DMA IRQ flags in one shot (note that flags are cleared by - // writing 1 to them rather than 0). - stat &= 0x7fff0000; - DMA_DICR = stat; - stat >>= 24; + //for (int i = 0; i < NUM_DMA_CHANNELS; i++) { + for (int i = 0, mask = (1 << 24); stat; i++, stat >>= 1, mask <<= 1) { + if (!(stat & 1)) + continue; - //for (int i = 0; i < NUM_DMA_CHANNELS; i++) { - for (int i = 0; stat; i++, stat >>= 1) { - if (!(stat & 1)) - continue; + // Acknowledge the current DMA channel's IRQ. For whatever reason + // DMA IRQ flags are cleared by writing 1 to them rather than 0. + DMA_DICR = base | mask; - if (_dma_handlers[i]) - _dma_handlers[i](); + if (_dma_handlers[i]) + _dma_handlers[i](); + } } } |
