Common Support Functions

The file Common.c contains a collection of useful common support functions:

Application Start-up and Clean-up Framework

  • void AppInit (uint32_t dsp_clock)
    Application Initialization Code
    Put all your initialization code into this central function. To make the CPrintf() function work as well in your initialization code called from here CPrintf_select_output() should be moved here too.
  • void AppCleanup (void)
    Application Clean-up Code at exit
    This function is called from PrintExitCode() during exit to clean up running processes like interrupts and DMA, flush opened files, close handles



Use AppInit() as the first step in your main program:

//******************************************************************************
//
// @brief Main application
// @param not used
// @return never
//
//******************************************************************************
void main (void)
{
//**************************************************************************
// locals
//**************************************************************************
// -
//**************************************************************************
// initialize application
//**************************************************************************
AppInit (dsp_clock);
...




Application Exit

  • void PrintExitCode ( void )
    Print descriptive exit code. This function is called automatically on exit and uses global exit string for printing a certain message. Use function prg_exit(string) instead of exit() to see the descriptive exit message.
  • prg_exit(string)
    Macro to log file name, line number and to set error string and exit application



The prg_exit() macro logs the file name and the line number and calls exit(). During exit function PrintExitCode() is executed. Depending on fatal errors like BUFFEROVERFLOW_ERROR GPIO's can be set or exit messages can be printed on a terminal containing file name and line number to identify the exit reason and position.

void InitializeFAT ( void )
{
...
if ( dFatAddDrive(RAM_DRIVE, INIT_RAM_DISC, 0) )
{
prg_exit ("error adding device. exiting...");
} // if

Will print in case of an error:

EXIT: DSPCommander.c line 203: error adding device. exiting...




Application Heap monitoring

  • size_t GetFreeHeapSize (void)
    This function determines the largest free heap block
  • void memmap (size_t heap_mem_size)
    This function is useful to show memory fragmentation and to detect memory leaks.



When the Common Support Functions Framework is used, GetFreeHeapSize() is called from AppInit() to get the initial configured heap size. Use global variable initial_heap_size to compare current available heap size to initial configured heap size. Macro ASSERT_HEAP() can be used to test for sufficient heap before a malloc() fails.

int main ( void )
{
//****************************************************************************
// locals
//****************************************************************************
...
//****************************************************************************
// initialize application. AppInit() MUST be called before any other function
//****************************************************************************
AppInit (dsp_clock);
//****************************************************************************
// select output device for CPrintf
// possible settings:
// CPRINTF_UART_OUTPUT -> output to UART
// CPRINTF_CCS_OUTPUT -> output to CCS
// CPRINTF_UART_OUTPUT | CPRINTF_CCS_OUTPUT -> output to UART and CCS
//****************************************************************************
// CPrintf_select_output (CPRINTF_UART_OUTPUT); // UART output
//****************************************************************************
// print a start up message
//****************************************************************************
//****************************************************************************
// perform HEAP check; at least 0x10000 bytes required for this app
//****************************************************************************
...


Function memmap() prints the current dynamic memory map on the activated CPrintf device. Repetitive calls may discover memory leaks.

Example memmap() outpout:

>> Used:1 size:264 addr:b0040000
>> Used:0 size:96 addr:b0040110
>> Used:1 size:384 addr:b0040178
>> Used:0 size:112 addr:b0040300
>> Used:1 size:128 addr:b0040378
>> Used:0 size:112 addr:b0040400
>> Used:1 size:512 addr:b0040478
>> Used:0 size:112 addr:b0040680
>> Used:1 size:128 addr:b00406f8
>> Used:0 size:112 addr:b0040780
>> Used:1 size:512 addr:b00407f8
>> Used:0 size:112 addr:b0040a00
>> Used:1 size:256 addr:b0040a78
>> Used:0 size:112 addr:b0040b80
>> Used:1 size:128 addr:b0040bf8
>> Used:0 size:112 addr:b0040c80
>> Used:1 size:1536 addr:b0040cf8
>> Used:0 size:60664 addr:b0041300
fr_nm:9 fr_sp:f068 fr_mx:ecf8 us_nm:9 us_sp:f08 us_mx:600 ovr:90

This memory map shows 9 free blocks (fr_nm), 0xf068 free memory (fr_sp) and the largest free block size of 0xecf8 (fr_mx).




Network Error Code/Event Handling

  • void net_print_error ( int32_t error_code, tpMessageLogFxn pLog )
    Print descriptive human readable message for network errors/events.
  • int32_t net_recv_event_handler (SOCKET *so, tpMessageLogFxn pLog)
    handle net_recv() and receive callback events



Use net_print_error() e.g. after net_recv() function call to signal a connection status change:

if (net_recv (tcp_server, tcp_rx, BUFFERSIZE))
{
switch (socket-> error_code & SO_ERROR_MASK)
{
//**************************************************************
// new data is available
//**************************************************************
break;
//**************************************************************
// event: connection established
//**************************************************************
//**************************************************************
// event: connection closed
//**************************************************************
//**************************************************************
// event: connection reset
//**************************************************************
default:
//**************************************************************
// else print error
//**************************************************************
net_print_error (socket-> error_code, printf);
break;
}
}



Use net_recv_event_handler() immediately after net_recv() function calls or within callback functions to handle events properly and to determine the received data length.
E.g.: usage after net_recv():

//**************************************************************************
// check for events and new data waiting in buffer
//**************************************************************************
if (net_recv (tcp_server, tcp_rx, sizeof(tcp_rx)))
{
//**********************************************************************
// check events
// if NULL is passed as pLog parameter, no message is printed to output
// use net_recv_event_handler() to determine the data length waiting
// in the receive buffer
//**********************************************************************
data_length = net_recv_event_handler (tcp_server, CPrintf); // with messages
// data_length = net_recv_event_handler (tcp_server, NULL); // without messages
}
if (data_length)
{
CPrintf ("received %d data elements\r\n", data_length);
//**********************************************************************
// new data available, process buffer
//**********************************************************************
// ...
data_length = 0;
}


E.g.: usage in a callback function:

int32_t tcp_call_back (SOCKET *so, void *data, uint32_t len, uint32_t ec)
{
//**************************************************************************
// locals
//**************************************************************************
int32_t data_length; // net_recv_event_handler() return parameter
//**************************************************************************
// suppress unused parameter warning
//**************************************************************************
UNREFERENCED_PARAMETER(data); // not used here, data is discarded
UNREFERENCED_PARAMETER(ec); // handled in net_recv_event_handler()
UNREFERENCED_PARAMETER(len); // len is ignored, data_len is used instead
//**************************************************************************
// Check events
// If NULL is passed as pLog parameter (recommended for use in callback functions),
// no message is printed to output.
// Use net_recv_event_handler() to determine the data length waiting in the
// receive buffer
//**************************************************************************
// data_length = net_recv_event_handler (so, CPrintf); // with messages
data_length = net_recv_event_handler (so, NULL); // without messages
//**************************************************************************
// net_recv_event_handler() returns the amount of data waiting in the buffer
//**************************************************************************
if (data_length)
{
// CPrintf ("received %d bytes\r\n", data_length);
//**********************************************************************
// TCP packet received
// process data
// here:discard data, count packets to send answer in main
//**********************************************************************
}
//**************************************************************************
// return true, if message processed
//**************************************************************************
return (SOCKET_CB_OK);
}



Use net_send_event_handler() immediately after net_send() function calls to detect fatal errors during a send process. A send process calling this handler must be terminated, if a fatal error was detected (return value 1). In case of a return value 0 the calling process may continue sending further data or wait for completion (TCP only).

//**************************************************************************
// @important note:
// net_send() must not be called while errors are pending
//**************************************************************************
if ( socket-> error_code == SO_NO_ERROR )
{
net_send_return = net_send (socket, data, (uint16_t)send_length>>socket-> data_shift);
} // if
else
{
net_send_return = NET_SEND_PENDING;
}
//**************************************************************************
// handle event conditions:
// some events must be monitored to detect connection or link loss
//**************************************************************************
if (net_send_event_handler (socket, CPrintf, net_send_return))
{
//**********************************************************************
// a fatal error was detected, terminate this function immediately
//**********************************************************************
return (0L);
}
if ( (socket-> proto == IPT_TCP) && (tcp_get_state (socket) != TCP_ESTABLISHED ) )
{
//**********************************************************************
// sending TCP data if not established makes no sense
//**********************************************************************
return (0L);
}




Application Link Status Function



Also a global variable is defined that reflects the current link status:

//******************************************************************************
// link
//******************************************************************************

Use this status in your application to wait for a valid link

while (_link == 0)
{
}

or to prevent a message from being sent without a link

//******************************************************************************
// send time stamp to PC
//******************************************************************************
if (_link)
{
net_send (udp_socket, // socket
udp_data, // data to send
10); // length of data
}
Warning
_link is only valid when the link-status callback function link_status() is used