Step 4: Add Application Code to the Project

Last modified by Microchip on 2026/06/29 11:08

This example application on the PIC32CM LS00 Curiosity Nano+ Touch Evaluation Kit board demonstrates two separate projects, one for CPU-driven transfer and another for Direct Memory Access (DMA)-driven transfer. Add the appropriate application code for each project accordingly.

Information

Tip: Press the CTRL key and left click on the SYS_Initialize function. The click will open the implementation for the SYS_Initialize function.

Application Code for CPU-Driven Transfer

Add the following application code to the generated project for CPU-driven transfer.

Open the main.c source file in the non-secure project. Include the <stdio.h> and <string.h> header file, and then define TRANSFER_SIZE as 1024. Next, create two arrays named srcBuffer and dstBuffer and declare timeStamp as an external volatile variable.

Code:

#include <stdio.h>
#include
<string.h>

#define TRANSFER_SIZE 1024
char srcBuffer[TRANSFER_SIZE] = {};
char dstBuffer[TRANSFER_SIZE] = {};
volatile uint32_t timeStamp = 0;

Non-secure main.c setup

TRANSFER_SIZE specifies the number of bytes to transfer (1024B). srcBuffer and dstBuffer are the source and destination arrays for data transfer. timeStamp is a volatile variable used to record timing information, such as the number of cycles taken for the transfer.

After calling SYS_Initialize(NULL); in the main() function, the srcBuffer[] (source buffer) is initialized with known 8-bit values to ensure transfer accuracy.

Code:

for(uint32_t i = 0; i < TRANSFER_SIZE; i++)
    {
        srcBuffer[i] = (uint8_t)i;    
    }

srcBuffer[] initialized

After initializing the source buffer, a message is printed using printf to indicate the start of the CPU memory transfer demonstration. The SysTick timer is started with the SYSTICK_TimerStart(); function, and the initial timestamp is captured using SYSTICK_TimerCounterGet(); to measure execution time. The CPU then copies data from srcBuffer to dstBuffer byte by byte using a manual for loop. After the transfer is complete, the SysTick timer is read again, and the elapsed time is calculated to determine the total duration of the CPU-based memory transfer.

Code:

    printf("\n\r\t\t CPU Memory Transfer DEMO\t\t");

    SYSTICK_TimerStart();
    timeStamp = SYSTICK_TimerCounterGet();

   for(uint32_t i = 0; i < TRANSFER_SIZE; i++)
    {
        dstBuffer[i] = srcBuffer[i];
    }

    timeStamp = timeStamp - SYSTICK_TimerCounterGet();

printed message

After completing the CPU-based memory copy, the strncmp() function is used to compare srcBuffer and dstBuffer over TRANSFER_SIZE bytes to verify data integrity. If the buffers match, a success message is printed; otherwise, a data mismatch message is displayed. The total number of SysTick cycles, stored in timeStamp, is then printed to indicate the execution time of the CPU transfer.

Code:

    if(strncmp(srcBuffer, dstBuffer, TRANSFER_SIZE) == 0)
    {
        printf("\n\r CPU Memory Transfer Successful with Data Match\n\r");
    }
   else
    {
        printf("\n\r CPU Memory Transfer Data Mismatch !!!\n\r");
    }
    printf("\n\r No of Transfer Cycles for Last Transfer --> %lu", timeStamp);

compare srcBuffer and dstBuffer

Information

Note: After adding the above code for the CPU-driven project, proceed to build, program and observe the output.


Application Code for DMA-Driven Transfer

Add the following application code to the generated project for DMA-driven transfer.

For the DMA-driven transfer project, after including the header files, define TRANSFER_SIZE as 1024. Then, declare two arrays, srcBuffer and dstBuffer, each with a size of TRANSFER_SIZE. Next, declare a volatile bool variable named completeStatus and a volatile uint32_t variable named timeStamp to track the completion status and timing information, respectively.

Code:

#define TRANSFER_SIZE 1024

char srcBuffer[TRANSFER_SIZE] = {};
char dstBuffer[TRANSFER_SIZE] = {};
volatile bool completeStatus = false;
volatile uint32_t timeStamp = 0;

Variable declarations for the DMA transfer example

In the main.c file, inside the int main() function and after the SYS_Initialize() call, add the DMAC_ChannelCallbackRegister() function to register APP_Callback for DMA Channel 0. This allows the CPU to be automatically notified when the DMA transfer is complete, eliminating the need for polling. Then, use the SYSTICK_TimerStart() function to start the SysTick timer and measure the execution time of the DMA transfer.

Code:

 DMAC_ChannelCallbackRegister(DMAC_CHANNEL_0, APP_Callback, 0);

 SYSTICK_TimerStart();

int main() function

Add the APP_Callback function after the extern variable declarations. The APP_Callback() function is automatically executed when a DMA transfer event occurs, as registered with the DMA controller. It calculates the total DMA transfer time using the SysTick timer and sets the completeStatus flag upon successful completion.

Code:

void APP_Callback(DMAC_TRANSFER_EVENT status, uintptr_t context)
{
     timeStamp = timeStamp - SYSTICK_TimerCounterGet();
    if(status == DMAC_TRANSFER_EVENT_COMPLETE)
     {
          completeStatus = true;
     }
}

APP_Callback implementation

After starting the SysTick timer, the srcBuffer is initialized with test data using a for loop, and a message is printed with printf to indicate the start of the DMA transfer demonstration. The current timer value is stored in timeStamp, and the DMAC_ChannelTransfer() function is called to initiate the memory transfer from srcBuffer to dstBuffer using DMA Channel 0.

Code:

for(uint32_t i = 0; i < TRANSFER_SIZE; i++)
    {
        srcBuffer[i] = (uint8_t)i;    
    }
    printf("\n\r\t\t DMAC Memory Transfer DEMO\t\t");
    timeStamp = SYSTICK_TimerCounterGet();
    DMAC_ChannelTransfer(DMAC_CHANNEL_0, &srcBuffer, &dstBuffer, TRANSFER_SIZE);

DMA transfer initialization

Inside the while loop, the code checks the completeStatus flag to determine if the DMA transfer has finished. Once the transfer is complete, it verifies the data by comparing srcBuffer and dstBuffer using strncmp, prints the transfer result, and displays the total transfer cycles measured using the SysTick timer.

Code:

if(completeStatus == true)
    {
        completeStatus = false;
       if(strncmp(srcBuffer, dstBuffer, TRANSFER_SIZE) == 0)
        {
            printf("\n\r DMAC Memory Transfer Successful with Data Match\n\r");
        }
       else
        {
            printf("\n\r DMAC Memory Transfer Data Mismatch !!!\n\r");
        }
        printf("\n\r No of Transfer for Last Transfer --> %lu", timeStamp);
   }

completeStatus flag check

Information

Note: Once the application code for the DMA-driven transfer demonstration is added, proceed to build, program and observe the output.

Back to Top