-
Notifications
You must be signed in to change notification settings - Fork 0
DMA
It is recommended to only use DMA for large transfers, as setting up each transfer takes a lot of CPU instructions.
Initializing GeNETiCC for use with DMA is very simple(as long as your system is already supported, info on how to integrate your system here.).
First enable DMA by setting GENETICC_USE_DMA in "geneticc_config.h" to true. DMA functions will now be available to use.
Then in your setup routine, simply call geneticc_dma_init(), like this.
#include "geneticc/geneticc_master.h"
int main(void)
{
/*Setup routine*/
//Initialize DMA
geneticc_dma_init();
//DMA is now initialized.
while(1)
{
/*Main Loop*/
}
}
To disable the use of DMA, change geneticc_dma_control.enabled to false.
As of now, most DMA macros are located in "geneticc_list.h," more info here.
Keep track of what transfers have finished
It is not recommended to use the Transfer System outside of GeNETiCC's internal functions.
The transfer system is how the library schedules internal calls to the DMA engine.
Every time you make a call to a DMA Macro/Function, it will create 1 transfer, and at least 1 subtransfer.
The transfer is then registered, which lets the transfer system know its waiting to start. If there are other transfers running, it will start when they have finished, and if there are no transfers running, it will be sent to the DMA engine, 1 sub-transfer at a time in order.
When the sub-transfer has completed, the transfer will check to see if it has any more sub-transfers that are waiting. If there is, it will send the next one. When all sub-transfers have completed, if the user has registered the transfer_done user callback, it will pass the transfer to the callback, and then free/delete the transfer depending on the DMA configuration.
Currently only 1 DMA channel is supported, but multiple channels will be added in the future, to save time on configuring the DMA engine.
Transfer (geneticc_dma_transfer_t)
Sub-Transfer (geneticc_dma_subtransfer_t)
Transactions are how many times the DMA engine has to access memory to complete the transfer.
Even when calling a DMA Macro or Function, it is not guaranteed to use the DMA engine.
The DMA engine will only be used if the minimum transaction count is met.
If the transaction count is not met, it will use standard memcpy/memmove function, but you will still have a performance hit over the non DMA macros, as the transfers are still created and registered.
The minimum transaction count can be changed by editing GENETICC_DMA_MIN_TRANSACTION_COUNT in "geneticc/dma/geneticc_dma_config.h."
The transaction count is calculated by taking the transaction size (in bytes), and dividing by the beatsize.
Below GENETICC_DMA_MIN_TRANSACTION_COUNT you may have noticed 'GENETICC_DMA_SYNC_MIN_TRANSACTION_COUNT.' You can force all non DMA Macros/Functions to use DMA synchronously. In most cases DMA is slower than CPU transfers, so synchronous operation is not recommended, but is still available for the rare cases DMA is faster. To force synchronous DMA, set GENETICC_FORCE_SYNCHRONOUS_DMA which is located in "geneticc/geneticc_memory.h" to true.
Used to keep a record of the source and destination address,
typedef struct
{
list_t subtransfers; //list of geneticc_dma_subtransfer_t
ARRAY_PTR src; //Pointer to the source array
ARRAY_PTR dest; //Pointer to the destination array
size_t size; //The total size of the src array, NOT how many bytes are being transferred
unsigned int subtran_count : 8; //Sub-transfer count
unsigned int complete_count : 8; //How many sub-transfers have finished?
geneticc_dma_transfer_flags_t flags;
}geneticc_dma_transfer_t;typedef struct
{
geneticc_dma_transfer_t* parent; //Parent transfer
ARRAY_PTR src; //Source address
ARRAY_PTR dest; //Destination address
size_t size; //Transfer size
geneticc_dma_subtransfer_flags_t flags; //Status/Control Flags
}geneticc_dma_subtransfer_t;