diff --git a/common/dmacopy.c b/common/dmacopy.c index 140d51d..4c8ba43 100644 --- a/common/dmacopy.c +++ b/common/dmacopy.c @@ -11,7 +11,7 @@ void __noinline memcpy32(void *dst, void *src, uint32_t size) { if(!size) return; // Cowardly avoid unaligned transfers, let memcpy() handle them. - if((size & 0x3) || (((uint32_t)dst) & 0x3) || (((uint32_t)src) & 0x3)) { + if((size < 64) || (size & 0x3) || (((uint32_t)dst) & 0x3) || (((uint32_t)src) & 0x3)) { memcpy(dst, src, size); return; } @@ -42,6 +42,47 @@ void __noinline memcpy32(void *dst, void *src, uint32_t size) { channel_config_set_write_increment(&c, false); } +void __noinline memset32(void *dst, uint8_t val, uint32_t size) { + dma_channel_config c; + uint32_t src = val; + src |= src << 8; + src |= src << 16; + + // Nothing to do! + if(!size) return; + + // Cowardly avoid unaligned transfers, let memset() handle them. + if((size < 64) || (size & 0x3) || (((uint32_t)dst) & 0x3)) { + memset(dst, val, size); + return; + } + + // 32 bit transfers. Write address increments after each + // transfer (pointing to a location in dst). + // No DREQ is selected, so the DMA transfers as fast as it can. + + // Get a free channel, panic() if there are none + if(dmacopy_channel == -1) + dmacopy_channel = dma_claim_unused_channel(true); + + c = dma_channel_get_default_config(dmacopy_channel); + channel_config_set_transfer_data_size(&c, DMA_SIZE_32); + channel_config_set_read_increment(&c, false); + channel_config_set_write_increment(&c, true); + + dma_channel_configure(dmacopy_channel, &c, dst, &src, (size >> 2), true); + + dma_channel_wait_for_finish_blocking(dmacopy_channel); + + dma_channel_abort(dmacopy_channel); + + // Deinit the DMA channel + c = dma_channel_get_default_config(dmacopy_channel); + dma_channel_configure(dmacopy_channel, &c, NULL, NULL, 0, false); + channel_config_set_read_increment(&c, false); + channel_config_set_write_increment(&c, false); +} + void __noinline dmacpy32(void *start, void *end, void *source) { uint32_t size = ((uint32_t)end) - ((uint32_t)start); diff --git a/common/dmacopy.h b/common/dmacopy.h index d0f6271..ae6d46c 100644 --- a/common/dmacopy.h +++ b/common/dmacopy.h @@ -2,3 +2,5 @@ void memcpy32(void *dst, void *src, uint32_t size); void dmacpy32(void *start, void *end, void *source); + +void __noinline memset32(void *dst, uint8_t val, uint32_t size); \ No newline at end of file