mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2025-04-16 16:06:53 +02:00
dma: fix freezes when transferring to/from IL memory
The IL memory is unavailable when the processor goes to sleep, causing any involved DMA transfer to stall. The dma_transfer_wait() normally sleeps to save battery power, but this causes the whole system to freeze and never wake up. This change lets dma_transfer_wait() decide dynamically whether to sleep or spinlock. There is no concrete improvement over dma_transfer_noint() when using IL memory, but it makes dma_transfer() fully generic. Obviously the same goes for X and Y memory.
This commit is contained in:
parent
552b9b9a43
commit
bb77e4588d
3 changed files with 16 additions and 5 deletions
|
@ -57,7 +57,7 @@ void dma_transfer(int channel, dma_size_t size, uint length,
|
||||||
void const *src, dma_address_t src_mode,
|
void const *src, dma_address_t src_mode,
|
||||||
void *dst, dma_address_t dst_mode);
|
void *dst, dma_address_t dst_mode);
|
||||||
|
|
||||||
/* dma_transfer_wait() - Wait for a transfer on channel 0 to finish
|
/* dma_transfer_wait() - Wait for a transfer to finish
|
||||||
|
|
||||||
You should call this function when you need to transfer to be complete
|
You should call this function when you need to transfer to be complete
|
||||||
before continuing execution. If you are sure that the transfer is finished,
|
before continuing execution. If you are sure that the transfer is finished,
|
||||||
|
|
|
@ -41,7 +41,7 @@ static uint32_t dma_translate(void const *address)
|
||||||
return a;
|
return a;
|
||||||
|
|
||||||
/* First additional on-chip memory area (XRAM) */
|
/* First additional on-chip memory area (XRAM) */
|
||||||
if(a >= 0xe5007000 && a < 0xE5009000)
|
if(a >= 0xe5007000 && a < 0xe5009000)
|
||||||
return a;
|
return a;
|
||||||
|
|
||||||
/* Second on-chip memory area (YRAM) */
|
/* Second on-chip memory area (YRAM) */
|
||||||
|
@ -123,8 +123,18 @@ void dma_transfer_wait(int channel)
|
||||||
channel_t *ch = dma_channel(channel);
|
channel_t *ch = dma_channel(channel);
|
||||||
if(!ch) return;
|
if(!ch) return;
|
||||||
|
|
||||||
/* Wait for the channel to be disabled by the interrupt handler */
|
/* Wait for the channel to be disabled by the interrupt handler.
|
||||||
while(ch->CHCR.DE) sleep();
|
When the source or the destination of the transfer is X, Y or IL
|
||||||
|
memory, refrain from sleeping as this also stops the transfer. */
|
||||||
|
int onchip = 0;
|
||||||
|
|
||||||
|
if(ch->SAR >= 0xe5007000 && ch->SAR < 0xe5204000) onchip = 1;
|
||||||
|
if(ch->DAR >= 0xe5007000 && ch->DAR < 0xe5204000) onchip = 1;
|
||||||
|
|
||||||
|
while(ch->CHCR.DE)
|
||||||
|
{
|
||||||
|
if(!onchip) sleep();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dma_transfer_noint(): Perform a data transfer without interruptions */
|
/* dma_transfer_noint(): Perform a data transfer without interruptions */
|
||||||
|
|
|
@ -7,6 +7,7 @@ void *dma_memset(void *dst, uint32_t l, size_t size)
|
||||||
uint32_t *IL = (void *)0xe5200000;
|
uint32_t *IL = (void *)0xe5200000;
|
||||||
for(int i = 0; i < 8; i++) IL[i] = l;
|
for(int i = 0; i < 8; i++) IL[i] = l;
|
||||||
|
|
||||||
dma_transfer_noint(1, DMA_32B, size >> 5, IL, DMA_FIXED, dst, DMA_INC);
|
dma_transfer(1, DMA_32B, size >> 5, IL, DMA_FIXED, dst, DMA_INC);
|
||||||
|
dma_transfer_wait(1);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue