MX Foundation 4
canbus_periodic.c
/*******************************************************************************
//
// File:
// canbus_periodic.c
//
// Copyright (c) MAX Technologies Inc. 1988-2020, All Rights Reserved.
// CONFIDENTIAL AND PROPRIETARY INFORMATION WHICH IS THE
// PROPERTY OF MAX TECHNOLOGIES INC.
//
// This demo shows how to set a basic periodic transmission with the
// scheduler.
//
// Hardware Requirements:
// - MAXT FlexMulti with CAN channel.
//
*******************************************************************************/
#include "example.h"
#define LOOPBACK
//#define LOCAL
#define BUFFER_SIZE 4096 // 4KB
uint32 ReadAcquisitionData(HMXF_BUFFER rxBuffer, MXF_CANBUS_DATAREC * rec);
/***************************************************************************************************************/
// Main
/***************************************************************************************************************/
int main(void)
{
uint32 rc;
HMXF_SERVER server;
HMXF_DEVICE device = 0;
HMXF_MODULE module = 0;
HMXF_CHANNEL channel = 0;
HMXF_BUFFER rxBuffer = 0;
HMXF_BUFFER txBuffer = 0;
MXF_CANBUS_DATAREC* rec = NULL;
HMXF_SCHED schedule;
HMXF_SCHED_MSG msg = 0;
uint32 i;
int loop = 0;
uint64 status;
// Connect to services local or remote
#ifdef LOCAL
rc = mxfServerConnect("0.0.0.0", "", "", FALSE, &server);
#else
rc = mxfServerConnect("192.168.0.1", "admin", "admin", FALSE, &server);
#endif
if (rc)
{
printf("Failed to connect; rc=0x%08x", rc);
printf("\nPress a key to terminate\n");
getchar();
return 0;
}
// Initialize the server
printf("\nStarting\n");
rc = mxfSystemInit(server);
// Get the first device handle
if (!rc)
rc = mxfSystemDeviceGet(server, 0, &device);
// Get module #12 handle (module CAN)
if (!rc)
rc = mxfDeviceModuleGet(device, 12, &module);
// Obtain channel #0 ( CAN channel)
if (!rc)
rc = mxfModuleChannelGet(module, 0, &channel);
// Set timebase to 64-bit microseconds
if (!rc)
rc = mxfSystemTimeBaseSet(server, MXF_TIMEBASE_DEVICE_USEC);
// Set bus state
if (!rc)
{
#ifdef LOOPBACK
rc = mxfCanBusStateSet(channel, MXF_CANBUS_BUS_STATE_ON_INTERNAL_LOOPBACK);
#else
rc = mxfCanBusStateSet(channel, MXF_CANBUS_BUS_STATE_ON_SELFTEST);
#endif
}
// Allocate RX acquisition buffer
if (!rc)
rc = mxfRxAcqBufferAlloc(channel, BUFFER_SIZE, &rxBuffer, NULL);
// Allocate TX Periodic Update buffer
if (!rc)
rc = mxfTxPeriodicUpdateMsgBufferAlloc(channel, 0, BUFFER_SIZE, &txBuffer, NULL);
// Allocate host buffer
if (!rc)
{
rec = (MXF_CANBUS_DATAREC*)malloc(BUFFER_SIZE);
if (!rec)
rc = MAXT_ERROR_MEM;
}
// Start the acquisition process
if (!rc)
rc = mxfRxAcqModeSet(rxBuffer, MXF_RXACQ_MODE_LINEAR);
if (!rc)
{
rc = mxfRxAcqStart(rxBuffer, MXF_RXACQ_FLAG_DEFAULT, 0, 0);
if (!rc)
printf("\nAcquisition started\n\r");
}
// Set the CAN record and create the schedule
// Create the periodic scheduler
rc = mxfTxPeriodicScheduleNew(channel, &schedule);
// Set scheduling values: Rate=500 ms (.5sec), Phase=0 us
if (!rc)
rc = mxfTxPeriodicScheduleMsgAdd(schedule, 500000LL, 0, &msg);
// Define the number of buffer for the list and link to it
if (!rc)
rc = mxfTxPeriodicScheduleBufferListAdd(msg, 1, 0, &txBuffer);
// Set record for the buffer: ID Extended 0x080A0000, DLC=8
if (!rc)
{
rec->timeTag = 0;
rec->control = 0;
rec->repeatCount = 1;
rec->errorInj = 0;
rec->dataSize = 8;
rec->id = 0x080A0000;
rec->info = MXF_CANBUS_REC_INFO_EXTENDED | 8;
for (i = 0; i<rec->dataSize; i++)
rec->data[i] = (uint8)i;
rc = mxfCanBusTxPeriodicUpdateMsgWrite(txBuffer, 1, rec);
}
// Run the scheduler
if (!rc)
{
printf("Running periodic transmission, please wait...\n\r");
// Run the schedule now
rc = mxfTxPeriodicScheduleRun(schedule);
}
// Wait 10 seconds
if (!rc)
{
do
{
mxfSleep(1000);
// Read CAN data in acquisition buffer
rc = ReadAcquisitionData(rxBuffer, rec);
if(!rc)
{
// Check Tx status
rc = mxfChannelTxStatusGet(channel, &status);
if(!rc && status)
{
if (status & MXF_TX_STATUS_OVERLOAD)
printf("Tx overload\n\r");
if (status & MXF_TX_STATUS_TIMING_LOST)
printf("Tx timing lost\n\r");
if (status & MXF_TX_STATUS_OVERFLOW)
printf("Tx overflow\n\r");
}
}
if(!rc)
{
// Check Rx status
rc = mxfChannelRxStatusGet(channel, &status);
if (!rc && status)
{
if (status & MXF_RX_STATUS_OVERFLOW)
printf("Rx overflow\n\r");
}
}
// Update record for the buffer: ID Extended 0x080A0000, DLC=8
if (!rc)
{
rec->timeTag = 0;
rec->control = 0;
rec->repeatCount = 1;
rec->errorInj = 0;
rec->dataSize = 8;
rec->id = 0x080A0000;
rec->info = MXF_CANBUS_REC_INFO_EXTENDED | 8;
for (i = 0; i<rec->dataSize; i++)
rec->data[i] = (uint8)loop;
rc = mxfCanBusTxPeriodicUpdateMsgWrite(txBuffer, 1, rec);
}
}while(!rc && (loop++ < 10));
}
if(!rc)
{
// Stop scheduler
rc = mxfTxPeriodicScheduleFree(schedule);
if (!rc)
printf("\n\rTransmission stopped\n\r");
}
// Stop and flush unread data
if (!rc)
rc = mxfRxAcqStop(rxBuffer);
if (!rc)
{
rc = mxfRxAcqClear(rxBuffer);
if (!rc)
printf("\nAcquisition stopped\n\r");
}
// Catch any previous error
if (rc)
{
char buffer[256];
rc = mxfSystemErrorStringGet(server, rc, sizeof(buffer), buffer);
printf("%s\n", buffer);
}
printf("\nTerminating\n\r");
// Free all buffers and terminate
if (rxBuffer)
mxfRxAcqBufferFree(rxBuffer);
if (txBuffer)
if (rec)
free(rec);
printf("\nPress enter to terminate\n\r");
getchar();
return rc;
}
/***************************************************************************************************************/
// ReadAcquisitionData
/***************************************************************************************************************/
uint32 ReadAcquisitionData(HMXF_BUFFER rxBuffer, MXF_CANBUS_DATAREC* rec)
{
MXF_CANBUS_DATAREC* recPtr = rec;
uint64 status, msgsCount, bytesCount;
uint64 j;
uint32 rc, byte;
// Read and display records
rc = mxfCanBusRxAcqRead(rxBuffer, 0, BUFFER_SIZE, &status, &msgsCount, &bytesCount, rec);
for (j = 0; j < msgsCount && !rc; j++)
{
printf(" %03llu: Timetag=%012llu, Size=%u", j, recPtr->timeTag, recPtr->dataSize);
if (!recPtr->control)
printf(" OK");
else
printf(" Error");
printf("\n Data=");
for (byte = 0; byte<recPtr->dataSize; byte++)
{
printf("%02X ", recPtr->data[byte]);
}
printf("\n");
rc = mxfCanBusNextDataRecordPtrGet(recPtr, &recPtr);
}
if(!rc)
{
// Check acq status
if(status & MXF_RXACQ_STATUS_OVERFLOW)
printf("Acq overflow\n\r");
if (status & MXF_RXACQ_STATUS_BUFFER_FULL)
printf("Acq buffer full\n\r");
if (status & MXF_RXACQ_STATUS_OUT_OF_RESOURCES)
printf("Acq out of resources\n\r");
}
return rc;
}
Updated 10/23/2023