#161597 - simonjhall - Wed Aug 06, 2008 10:55 pm
I think I'm missing something here!
I'm using
as my DMA function. As far as I can see, there's no blocking going on here. However here's what I'm doing:
I don't care what the data is doing, I don't care that they overlap, and I only vaguely care about the size.
That magic number I'm print before and after is the vcount register. Only the vertical blank interrupt is on. The ARM7 is idle.
If I comment out DMAs #2, 3 & 4 my vcount advances by one, my vblank count doesn't increase. This is what I'd expect, as what I'm measuring is the set-up time of a DMA. If I uncomment DMA #2 the time between the two gaps is still 0 vblanks and the vcount has increased to 152. That's quite a long time! If I make it so that they don't overlap I get the exact same result.
If I change the first function call to be to dmaCopyHalfWords (which blocks at the end) the amount of time is the same!
If I change it back to the asynchronous version and uncomment the remaining two DMAs (so all four are apparently running asynchronously) the vcount increases to 190. If I make the first three synchronous and the final one asynchronous, vcount ends up at 191.
I've tried sticking other timing mechanisms around this code (eg timers) and I can verify this result...it looks like as soon as you try and schedule a DMA (whether it's asynchronous or not) but another one is already running it'll block when it's issued. It will literally wait for any pending DMA transfers to finish before a new one can be issued! I think the DMA system has a one-element deep queue and if you try and write another one, it'll block the CPU.
Can anyone else please verify this?
_________________
Big thanks to everyone who donated for Quake2
I'm using
Code: |
static inline void dmaCopyHalfWordsAsynch(uint8 channel, const void* src, void* dest, uint32 size) {
DMA_SRC(channel) = (uint32)src; DMA_DEST(channel) = (uint32)dest; DMA_CR(channel) = DMA_COPY_HALFWORDS | (size>>1); } |
Code: |
printf("before %d\n", *(volatile unsigned short *)0x4000006);
dmaCopyHalfWordsAsynch(0, (void *)0x2750000, (void *)0x2770000, 5 * 1024); dmaCopyHalfWordsAsynch(1, (void *)0x2750000, (void *)0x2770000, 5 * 1024); dmaCopyHalfWordsAsynch(2, (void *)0x2750000, (void *)0x2770000, 5 * 1024); dmaCopyHalfWordsAsynch(3, (void *)0x2750000, (void *)0x2770000, 5 * 1024); printf("after %d\n", *(volatile unsigned short *)0x4000006); |
That magic number I'm print before and after is the vcount register. Only the vertical blank interrupt is on. The ARM7 is idle.
If I comment out DMAs #2, 3 & 4 my vcount advances by one, my vblank count doesn't increase. This is what I'd expect, as what I'm measuring is the set-up time of a DMA. If I uncomment DMA #2 the time between the two gaps is still 0 vblanks and the vcount has increased to 152. That's quite a long time! If I make it so that they don't overlap I get the exact same result.
If I change the first function call to be to dmaCopyHalfWords (which blocks at the end) the amount of time is the same!
If I change it back to the asynchronous version and uncomment the remaining two DMAs (so all four are apparently running asynchronously) the vcount increases to 190. If I make the first three synchronous and the final one asynchronous, vcount ends up at 191.
I've tried sticking other timing mechanisms around this code (eg timers) and I can verify this result...it looks like as soon as you try and schedule a DMA (whether it's asynchronous or not) but another one is already running it'll block when it's issued. It will literally wait for any pending DMA transfers to finish before a new one can be issued! I think the DMA system has a one-element deep queue and if you try and write another one, it'll block the CPU.
Can anyone else please verify this?
_________________
Big thanks to everyone who donated for Quake2