extern void *memcpy(void *ptrTo, const void *ptrFrom, size_t Size)
{
register unsigned char *ptr = (unsigned char *)ptrTo;
register unsigned char *buffer = (unsigned char *)ptrFrom;
if (Size >= SMALLEST_DMA_COPY) { // if large enough to be worthwhile
KINETIS_DMA *ptrDMA = (KINETIS_DMA *)DMA_BLOCK;
ptrDMA += DMA_MEMCPY_CHANNEL;
if (ptrDMA->DMA_DCR == 0) { // if not already in use
unsigned long ulTransfer;
while (((unsigned long)buffer) & 0x3) { // move to a long word boundary for source
*ptr++ = *buffer++;
Size--;
}
ptrDMA->DMA_DSR_BCR = DMA_DSR_BCR_DONE; // clear the DONE flag and clear errors etc.
if (((unsigned long)ptr & 0x3) != 0) { // if the destination is not also long word aligned
if ((unsigned long)ptr & 0x1) { // not short word aligned
ulTransfer = Size;
ptrDMA->DMA_DCR = (DMA_DCR_DINC | DMA_DCR_SINC | DMA_DCR_D_REQ | DMA_DCR_DSIZE_8 | DMA_DCR_SSIZE_8 | DMA_DCR_DMOD_OFF | DMA_DCR_SMOD_OFF); // set mode and protect from interrupts that could use the function in the process
}
else {
ulTransfer = (Size & ~0x1); // ensure length is suitable for short words
ptrDMA->DMA_DCR = (DMA_DCR_DINC | DMA_DCR_SINC | DMA_DCR_D_REQ | DMA_DCR_DSIZE_16 | DMA_DCR_SSIZE_16 | DMA_DCR_DMOD_OFF | DMA_DCR_SMOD_OFF); // set mode and protect from interrupts that could use the function in the process
}
}
else {
ptrDMA->DMA_DCR = (DMA_DCR_DINC | DMA_DCR_SINC | DMA_DCR_D_REQ | DMA_DCR_DSIZE_32 | DMA_DCR_SSIZE_32 | DMA_DCR_DMOD_OFF | DMA_DCR_SMOD_OFF); // set mode and protect from interrupts that could use the function in the process
ulTransfer = (Size & ~0x3); // ensure length is suitable for long words
}
ptrDMA->DMA_SAR = (unsigned long)buffer; // set address of sourse
ptrDMA->DMA_DAR = (unsigned long)ptr; // set address of destination
ptrDMA->DMA_DSR_BCR = (ulTransfer & DMA_DSR_BCR_BCR_MASK); // set transfer count (don't set DMA_DSR_BCR_DONE at the same time otherwise BCR is reset)
ptrDMA->DMA_DCR |= (DMA_DCR_START); // start DMA transfer
ptr += ulTransfer; // move the destination pointer to beyond the transfer
buffer += ulTransfer; // move the source pointer to beyond the transfer
Size -= ulTransfer; // bytes remaining
while ((ptrDMA->DMA_DSR_BCR & DMA_DSR_BCR_DONE) == 0) {} // wait until completed
while (Size--) { // complete any remaining bytes
*ptr++ = *buffer++;
}
ptrDMA->DMA_DCR = 0; // free the DMA channel for further use
return ptrTo; // return pointer to original buffer according to memcpy() declaration
}
}
// Normal memcpy() solution
//
while (Size--) {
*ptr++ = *buffer++; // copy from input buffer to output buffer
}
return ptrTo; // return pointer to original buffer according to memcpy() declaration
}