//--- // gint:dma - Direct Memory Access for efficient data transfer //--- #ifndef GINT_DMA #define GINT_DMA /* TODO: Enable DMA on fx-9860G */ #ifdef FXCG50 #include /* dma_size_t - Transfer block size */ typedef enum { /* Normal transfers of 1, 2, 4, 8, 16 or 32 bytes at a time */ DMA_1B = 0, DMA_2B = 1, DMA_4B = 2, DMA_8B = 7, DMA_16B = 3, DMA_32B = 4, /* Transfers of 16 or 32 bytes divided in two operations */ DMA_16B_DIV = 11, DMA_32B_DIV = 12, } dma_size_t; /* dma_address_t - Addressing mode for source and destination regions */ typedef enum { /* Fixed address mode: the same address is read/written at each step */ DMA_FIXED = 0, /* Increment: address is incremented by transfer size at each step */ DMA_INC = 1, /* Decrement: only allowed for 1/2/4-byte transfers */ DMA_DEC = 2, /* Fixed division mode: address is fixed even in 16/32-divide mode */ DMA_FIXEDDIV = 3, } dma_address_t; /* dma_transfer() - Start a data transfer on channel 0 This function returns just when the transfer starts. The transfer will end later on and the DMA will be stopped by an interrupt. Call dma_transfer_wait() if you need to wait for the transfer to finish. Don't start a new transfer until the current one is finished! @channel DMA channel (0..5) @size Transfer size @blocks Number of blocks (transferred memory = size * blocks) @src Source pointer, must be aligned with transfer size @src_mode Source address mode @dst Destination address, must be aligned with transfer size @dst_mode Destination address mode */ void dma_transfer(int channel, dma_size_t size, uint length, void const *src, dma_address_t src_mode, void *dst, dma_address_t dst_mode); /* dma_transfer_wait() - Wait for a transfer to finish 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, this is not necessary (the only way to know is to look at the DMA registers or record interrupts). @channel DMA channel (0..5) */ void dma_transfer_wait(int channel); /* dma_transfer_noint() - Perform a data transfer without interrupts This function performs a transfer much like dma_transfer(), but doesn't use interrupts and *actively waits* for the transfer to finish, returning when it's finished. Don't call dma_transfer_wait() after using this function. Not using interrupts is a bad design idea for a majority of programs, and is only ever needed to display panic messages inside exception handlers. */ void dma_transfer_noint(int channel, dma_size_t size, uint blocks, void const *src, dma_address_t src_mode, void *dst, dma_address_t dst_mode); //--- // DMA-based memory manipulation functions //--- /* dma_memset(): Fast 32-aligned memset This function is your typical memset(), except that the destination and size must be 32-aligned, and that the pattern is 4 bytes instead of one. It is replicated to 32 bytes then used to fill the destination area. This 4-byte fixed size may be lifted in future versions. This function cannot be used with virtualized (P0) addresses. @dst Destination address (32-aligned) @pattern 4-byte pattern to fill @dst @size Sie of destination area (32-aligned) */ void *dma_memset(void *dst, uint32_t pattern, size_t size); /* dma_memcpy(): Fast 32-aligned memcpy This function works exactly like memcpy(), but it expects 32-aligned source, destination, and size, and uses the DMA to efficiently copy. This function cannot be used with virtualized (P0) addresses. @dst Destination address (32-aligned) @dst Source addresss (32-aligned) @size Size of region (32-aligned) */ void *dma_memcpy(void * restrict dst, const void * restrict src, size_t size); #endif /* FXCG50 */ #endif /* GINT_DMA */