Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quirks in audio FIFO and DMA #326

Open
alyosha-tas opened this issue Sep 1, 2023 · 7 comments
Open

Quirks in audio FIFO and DMA #326

alyosha-tas opened this issue Sep 1, 2023 · 7 comments

Comments

@alyosha-tas
Copy link

alyosha-tas commented Sep 1, 2023

I've been working on some audio FIFO tests in the style of jsmolka's suite, but quickly ran into some weird stuff. You can find the test here:

https://github.com/alyosha-tas/gba-tests/tree/master/fifo_dma

Test 1 is just testing readability of sound control reg for FIFO while power is off, nothing unexpected happens.

For test 2 though, in order for the test to pass, manual writes to FIFO while audio power is off need to fail (not add samples to FIFO.)

Additionally, FIFO DMA from fixed source in ROM needs to use all non-sequential accesses, which was unexpected, previously I had all DMA's to/from ROM automatically incrementing.

Test 3 just checks if FIFO is cleared by power off, nothing unexpected happens.

Test 4 is nearly identical to test 2 but with a few more nops in between timer reads, however the results are non-sensical. (They remain non-sensical without the nops as well.) To pass the test would require all non-sequential accesses for the first FIFO DMA and all sequential accesses for the second. I don't have an explanation for that but it works on hardware.

NanoBoyAdvance currently fails on test 2.

EDIT: Strike through comments about non-sequential accesses, they are likely incorrect. but, the cause of the observed behaviours is still unknown.

@fleroviux
Copy link
Member

Thanks for this! Looks like I had an oversight regarding the APU master enable bit in 16-bit and 32-bit IO handlers.

Regarding fixed source ROM DMA: that's odd. My impression so far was that DMA forces the first ROM access to be non-sequential and otherwise uses all sequential accesses, which can look like incrementing DMA for ROM due to the cartridge latching the address only on non-sequential access. I'll try to write some tests and see if I can find out more.

@fleroviux
Copy link
Member

This is really weird. I wrote some tests for DMA1-3 decrementing and fixed ROM source DMAs and they all seem to indicate that a single non-sequential + N sequential accesses are used. I haven't tested audio DMA specifically yet, admittedly, but I'm not sure why it would be different. The only explanation I can think of at the moment would be that since the DMA seems to run between the two timer reads maybe the access previously done on the bus or the access to be done by the CPU next affects the DMA? But I wasn't able to reproduce anything like that so far.

@alyosha-tas
Copy link
Author

I guess another explanation could be that audio DMA simply takes longer for some unknown reason and it just happens to be 6 cycles so that it looks like non-sequential timing.. Maybe there is some internal FIFO state not being captured yet?

I'll do some more testing today and see if I can come up with anything that makes sense.

@fleroviux
Copy link
Member

I have messed around with your test a bit and noticed that there appears to be a missing comparison for the tmr_read_b value around here:

        adr     r5, .tmr_read_b
        ldr     r7, [r5]
        bne     f002b
        b       t003

I have modified the code like this, which should fix that I think:

        adr     r5, .tmr_read_b
        ldr     r1, [r5]
        cmp     r7, r1
        bne     f002b
        b       t003     

But then I also had to adjust tmr_read_b to 0x0080008B to pass on hardware.

After this a couple of other observations were:

  • DMA1 seems to run twice during the second test, once before the timer reads and once in between the two timer reads
  • In NBA the first timer read is too fast by six cycles, meaning the first DMA1 already is off and the second DMA1 seems to be too slow by 7(?) cycles.

@alyosha-tas
Copy link
Author

Oh, good catch, I'll commit the fixed code.

I made a slightly modified test that uses EWRAM and still got some strange results, but only if another timer overflow happens while the FIFO DMA is still running. Perhaps this is part of the issue in the original test as well. If I ensure timer ticks happen slowly enough that they don't occur concurrently with a DMA, nothing strange happens that I can see.

@fleroviux
Copy link
Member

I have started to test FIFO DMA specifically a bit and noticed that my test sometimes seems to lock up on hardware when timer overflows happen during a FIFO DMA frequently enough. I wonder if the internal state of the DMA somehow gets messed up under certain circumstances causing it to never stop. I know this kind of thing can happen when stopping a DMA while it is starting up.

@alyosha-tas
Copy link
Author

Here's another test that doesn't rely on strange interrupting of DMAs.

https://github.com/alyosha-tas/gba-tests/tree/master/fifo_dma_2

This one tests exact FIFO DMA timing with prefetcher enabled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants