#include <stdio.h> // printf()
#include <stdlib.h> // srand(), rand()
#include <time.h> // time()
#include <string.h> // memcmp()
#include <4FM.h> // 4DSP's Application Programming Interface header
#include <malloc.h> // _aligned_malloc/free(), this is a windows specific header
#define _MEMORY_SIZE 4096 // 4096 bytes is the maximum size we can transfer without to overflow FIFOs in the ifpga interface.
// function called to free buffers, handle to the 4DSP's device and then exit the application
void exit_handler(void *buf1, void *buf2, _4FM_DeviceContext *dev_ctx)
{
// Release the instance to the hardware
if(dev_ctx!=NULL)
_4FM_CloseDevice(dev_ctx);
// Free the buffers
if(buf1!=NULL)
_aligned_free(buf1);
if(buf2!=NULL)
_aligned_free(buf2);
// Exit the application
exit(0);
}
int main(int argc, char* argv[])
{
_4FM_error_t api_status; // the variable receiving status of the API
_4FM_DeviceContext dev_ctx; // handle to the device opened
char *dma_buffer_in; // buffer used for our DMA transactions ( hardware to host )
char *dma_buffer_out; // buffer used for our DMA transactions ( host to hardware )
char devicetype[1024]; // receive the device type ( during _4FM_OpenDEviceEx() call )
int devicenumber; // receive the device number ( during _4FM_OpenDEviceEx() call )
// DMA ( Direct Memory Access ) implementation requires 4k aligned buffers in the memory.
// we allocate both buffers.
dma_buffer_in = (char *)_aligned_malloc(_MEMORY_SIZE, 4096);
dma_buffer_out = (char *)_aligned_malloc(_MEMORY_SIZE, 4096);
// Open the 4DSP hardware
api_status = _4FM_OpenDeviceEx(&dev_ctx, devicetype, &devicenumber, OPEN_MODE_FIRST_DEVICE_FOUND);
if(api_status!=_4FM_OK) {
printf("No devices found in the system, exiting...\n");
exit_handler(dma_buffer_in, dma_buffer_out, &dev_ctx);
}
printf("Found device %s at index %d\n", devicetype, devicenumber);
// Place software, firmware and hardware into a known sane state
api_status = _4FM_ResetDevice(&dev_ctx);
if(api_status!=_4FM_OK) {
printf("Could not reset, exiting...\n");
exit_handler(dma_buffer_in, dma_buffer_out, &dev_ctx);
}
// We tell the firmware to route DMA transaction between the host and FPGA B, the main FPGA
api_status = _4FM_SelectTarget(&dev_ctx, tgMainFPGA);
if(api_status!=_4FM_OK) {
printf("Could not tell the hardware to route DMA transaction to the main fpga exiting...\n");
exit_handler(dma_buffer_in, dma_buffer_out, &dev_ctx);
}
// Create random data, this data is sent to the firmware afterwards
srand((unsigned int)time(0));
for(int i = 0; i < _MEMORY_SIZE; i++)
dma_buffer_out[i] = (char)rand();
// Send the data to the hardware using direct memory address operations
api_status = _4FM_SendData(&dev_ctx, dma_buffer_out, _MEMORY_SIZE);
if(api_status!=_4FM_OK) {
printf("Could not send random data to the hardware device...\n");
exit_handler(dma_buffer_in, dma_buffer_out, &dev_ctx);
}
// Receive the data from the hardware using direct memory address operations
api_status = _4FM_ReceiveData(&dev_ctx, dma_buffer_in, _MEMORY_SIZE);
if(api_status!=_4FM_OK) {
printf("Could not receive random data from the hardware device...\n");
exit_handler(dma_buffer_in, dma_buffer_out, &dev_ctx);
}
// compare the buffer send to the hardware and the buffer received from the hardware.
// they should be equal as the hardware looped-back the data.
if(memcmp(dma_buffer_out, dma_buffer_in, _MEMORY_SIZE))
printf("Error, the data echoed by the hardware does not match the data we've sent out\n");
else
printf("Success, the data echoed by the hardware does match the data we've sent out\n");
printf("The test has finished!\n");
// Terminate properly
exit_handler(dma_buffer_in, dma_buffer_out, &dev_ctx);
}