Author Topic: fnDebugMsg and debug.c  (Read 3244 times)

Offline paulk

  • Newbie
  • *
  • Posts: 45
    • View Profile
fnDebugMsg and debug.c
« on: June 10, 2010, 04:35:41 PM »
Hi Mark,

I'm working on an embedded ethernet project and want to have a setup menu system via TELNET.  This is already done in the uTasker demo app and works well.  However, since you've used fnDebugMsg to display the menus, all of the debug messages from the other modules are coming through this interface (ie: Modbus communications messages, etc..)

What I'd like is to limit the TELNET communication to the menus only, or better yet, allow the user to set the "debug level" to define the amount of debug information they see.

However, modifying fnDebugMsg seems daunting since its in the driver.c file (which I would like to avoid changing), as well as all the instances of fnDebugMsg being used throughout the modules.

Do you have an idea of how to overcome this?  I was thinking of changing "debug.c" to "menu.c", and defining a custom print function within that file, and allow fnDebugMsg to write to the network port only if the debug level is set high enough.....

If you have a better implementation idea, please let me know.....

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3093
    • View Profile
    • uTasker
Re: fnDebugMsg and debug.c
« Reply #1 on: June 10, 2010, 05:44:10 PM »
Hi Paul

There are various methods that I can think of to achieve parts or all of what you are interested in doing. Some are quite simple and others involve larger changes.

Therefore I will start with the simplest suggestion.

As you probably know, all debug output from fnDebugMsg() is sent to the device with DebugHandle. The device can be changed by simply modifying DebugHandle. Establishing a connection via TELNET will automatically set this to the TELNET ID (actually (DebugHandle = NETWORK_HANDLE which is also the default). All debug output therefore passes via the user-supplied function:
extern QUEUE_TRANSFER fnNetworkTx(unsigned char *output_buffer, QUEUE_TRANSFER nr_of_bytes) in debug.c.

If you add a further global variable
int iOutput = 0;

You can then control which output actually gets sent and which not.
In the routine you can add something like
if (iOutput == 0) {
    return;                             // if nothing specified ignore
}
or sent to TELNET if connected



In the code area where you want output to be sent from you can set iOutput = 1; and then at the end set back to 0.
Alternatively add a cover function like
int _fnDebugMsg(CHAR *message)
{
    int iRtn;
    iOutput = 1;
    iRtn = fnDebugMsg(message);
    iOutput = 0;
    return (iRtn );
}


This does use a global variable to control it, but is probably the simplest method to get it working. Also by having different values for different outputs (like UARTs or debug levels) different outputs could be controlled too.

Regards

Mark


Offline mhoneywill

  • Full Member
  • ***
  • Posts: 173
    • View Profile
Re: fnDebugMsg and debug.c
« Reply #2 on: June 11, 2010, 11:22:21 AM »
Hi Paul,

I'd asked Mark a similar question in a personal email, below is my original email and Marks reply. It might be of help to you.



Hi Mark,

I'm adding a telnet interface to my project, using debug.c as a starting point. This all works fine.

What I would also like to do is to add a debug interface, which would be on a different TCPIP port than the standard Telnet port. Currently If I start using fnDebugMsg it will mess up my Telnet interface.

My thoughts are as follows.

1. Create fnTelnetMsg, fnTelnetDec, fnTelnetHex which are similar to the fnDebug... equivalents but use the Tenet Port.

2. Create a #define in debug.c that changes fnDebug... to fnTelnet... It may be better to do a replace the string "fnDebug" with "fnTelnet" in the code but I want to have minimal changes in the code.

3. I've just looked at the definitions of fnDebugMsg and it prints to the Network Queue rather than the a queue associated with the Telnet Port, so It may be a bit more complex than I first thought.

4. What would you suggest would be the best way to create Telnet functionality on two separate TCPIP ports, one for a Telnet interface and one for a Debug interface? would I need to duplicate the telnet.c code or could I re-use it on multiple ports?

5. If another TCPIP port is not required for debug comms I would like to be able to #define fnDebug.. as fnTelnet.. so I would have the same functionality as currently exists (both functions outputting to the same port).

6. I guess my question really relates to how to setup multiple Telnet sessions on Multiple TCPIP ports.

Cheers

Martin



Hi Martin

If the second TCP connection is on a different port it is necessary to have a second socket handler. This can of course be very similar to the present one in debug.c.

To have multiple TELNET sessions on the same TCP port the same code can be used but needs to be adapter to support multiple sessions (like in HTTP), meaning that any local variables have to be changed to arrays so that each session has its own set.

 
Assuming that you have 2 TCP TELNET (or TELNET like) connections open I would try to use the existing fnNetworkTx() method.
 

// We support the network transmit routine here
//
extern QUEUE_TRANSFER fnNetworkTx(unsigned char *output_buffer, QUEUE_TRANSFER nr_of_bytes)
{
    return (fnSendBufTCP(Telnet_socket, output_buffer, nr_of_bytes, (TCP_BUF_SEND | TCP_BUF_SEND_REPORT_COPY)));
}


All debug type outputs will be sent here if the debug handle is a -1 (the default value).
But this is user code and can be modified to send to multiple outputs (for example), like UART, USB and Telnet, or multiple Telnet type sessions.

// We support the network transmit routine here
//
extern QUEUE_TRANSFER fnNetworkTx(unsigned char *output_buffer, QUEUE_TRANSFER nr_of_bytes)
{
    fnPrint(serial_handle, output_buffer, nr_of_bytes);               // send to serial output
    return (fnSendBufTCP(Telnet_socket, output_buffer, nr_of_bytes, (TCP_BUF_SEND | TCP_BUF_SEND_REPORT_COPY))); // and TELNET
}


Since all output will pass this way it may be easiest to put a case in it:

// We support the network transmit routine here
//
extern QUEUE_TRANSFER fnNetworkTx(unsigned char *output_buffer, QUEUE_TRANSFER nr_of_bytes)
{
    switch (DebugOutput) {
    case STANDARD_OUTPUT:
    return (fnSendBufTCP(Telnet_socket, output_buffer, nr_of_bytes, (TCP_BUF_SEND | TCP_BUF_SEND_REPORT_COPY)));
    case SECOND_OUTPUT:
    return (fnSendBufTCP(Second_Telnet_socket, output_buffer, nr_of_bytes, (TCP_BUF_SEND | TCP_BUF_SEND_REPORT_COPY)));
    }
}

 
The new global variable DebugOutput  can be used to select the output for individual messages.

DebugOutput = SECOND_OUTPUT;
fnDebugMsg(“Test”);
DebugOutput = STANDARD_OUTPUT;

Possibly a macro or cover function would help too. All output which is for the standard one doesn’t need to do anything special.

Regards

Mark