Author Topic: Newbie's firsttime with uTasker  (Read 41180 times)

Offline echel0n

  • Newbie
  • *
  • Posts: 37
    • View Profile
Re: Newbie's firsttime with uTasker
« Reply #45 on: March 03, 2009, 08:25:07 PM »
Ok I'm running the simulator and when it gets to where it looks for '0x21' in ucInputMessage it actually has 33 which is the dec equiv to hex 0x21 ....
This causes problems as I need to see it in hex and NOT dec

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3162
    • View Profile
    • uTasker
Re: Newbie's firsttime with uTasker
« Reply #46 on: March 03, 2009, 09:26:54 PM »
Hi

I assume you are using VisualStudio C++ 2009 for the simulation (others are similar, if not identical).

How values are displayed is your own choice. If they are being displayed as decimal values and you prefer hexadecimal, change the setting as follows:
- In the "Locals" window [Menu Debug | Windows | Local, if not already displayed] click on a variable to set the context to that windows.
- Now right mouse click and set "Hexadecimal Display"
- If you want to view in decimal again (is useful for looking at IP addresses, for example), just repeat and disable "Hexadecimal Display"

Regards

Mark




Offline echel0n

  • Newbie
  • *
  • Posts: 37
    • View Profile
Re: Newbie's firsttime with uTasker
« Reply #47 on: March 03, 2009, 09:48:13 PM »
So is it safe to say that ucInputMessage will contain hex when ran off the arm7 devel board instead of the simulator ?

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3162
    • View Profile
    • uTasker
Re: Newbie's firsttime with uTasker
« Reply #48 on: March 03, 2009, 10:18:24 PM »
Hi

There is no different between dec and hex. In the simulator it is stored exactly the same way as on the ARM target. The target will neither store in hex or decimal - it will actually store physically in binary. But there is no difference - this can also be interpreted as hex or dec too.

The only reason why you are seeing it as dec is because the debugger is displaying it like that.
There is no difference - it is only the way that it is interpreted for human readability.

For example, your variable with 0x21 is in fact stored as b00100001 in an 8 bit byte. (Note that it is also never actually stored as hex either since hex is only an interpretation, as is dec - it is always stored as binary bits. This is the only physical storage that is possible).

This b00100001 never changes but can be viewed as hex 21 or decimal 33 or oct 41 (or a variety of others in other numbering systems are used).

As an experiment:
Start the Windows calculator and switch it to Binary mode. Input a binary number. Now select Hex, Dec or Oct and binary again. The value is not changed by doing this (there is no right or wrong) - it is simply displayed differently.

Regards

Mark




Offline echel0n

  • Newbie
  • *
  • Posts: 37
    • View Profile
Re: Newbie's firsttime with uTasker
« Reply #49 on: March 03, 2009, 11:54:50 PM »
Ok I understand what your saying and I did change vb.net to show hex instead of dec and now ucInputMessage shows the correct data and 0x21 gets matched but that doesn't explain why when testing via crossworks debugging that 0x21 was never matched nor was there any data ever put into ucInputMessage as far as I could tell.

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3162
    • View Profile
    • uTasker
Re: Newbie's firsttime with uTasker
« Reply #50 on: March 04, 2009, 12:33:38 AM »
Hi

I just loaded your code to my Olimex board.
I connect to UART1 (the connector in the center of the board) with a straight cable to a PC running a Terminal Emulator (TeraTermPro) configured for 115'200 Baud, 8 bit, no parity.

With a break point at the line
           iRxReceived = 1;
I send some characters. It doesn't break until I send '!', when it does break. This is 0x21.

Therefore it does (also) work on the hardware.
Check that you are testing in a similar manner. Verify the Baud rate since you have set it to 115k.

However, be careful that you haven't saved parameters to FLASH  (eg. when testing the demo project) which are configuring the UART to a different Baud rate. To ensure that this is not the case, either debug the UART configuration to see the speed being set or else increment the parameter version number so that the code will not recognise any previously saved configuration. (PARAMETER_BLOCK_VERSION in application.h).

Note that when the Baud rate doesn't match you will still get reception but the value will be incorrect.

Regards

Mark



Offline echel0n

  • Newbie
  • *
  • Posts: 37
    • View Profile
Re: Newbie's firsttime with uTasker
« Reply #51 on: March 04, 2009, 05:57:24 PM »
Is there anything I should know about using the simulator and sending TCP data to my server on my pc cause no matter what I try it doesn't seem to ever send the data but I'm fairly sure the code is correct in my uTasker project.

??

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3162
    • View Profile
    • uTasker
Re: Newbie's firsttime with uTasker
« Reply #52 on: March 04, 2009, 06:16:32 PM »
Hi

- Have you selected the PC NIC and can you ping the simulator? This will verify that it basically works.

- Check what is happening with WireShark. It may be that a configuration is not correct for your network or it may be that the PC is blocking with its Firewall. In the recording you can see whether there are no responses or whether the PC is responding with RST (this means that it doesn't have a port listening on the TCP port or that its firewall may be shooting down an attempted connection).

Regards

Mark

Offline echel0n

  • Newbie
  • *
  • Posts: 37
    • View Profile
Re: Newbie's firsttime with uTasker
« Reply #53 on: March 04, 2009, 06:44:41 PM »
Ok it seems to be doing better now, I can actually ping it and I see my server saying utasker connected to it but still got issues.

This happens when utasker trys to connect to my pc server.
30   125.501740   192.168.1.69   192.168.1.65   TCP   irdmi > 49744 [RST, ACK] Seq=1 Ack=1 Win=0 [TCP CHECKSUM INCORRECT] Len=0

This happens when my utasker sends data to my pc server.
35   154.460465   192.168.1.65   192.168.1.69   TCP   [TCP Port numbers reused] 49744 > irdmi [SYN] Seq=0 Win=1460 Len=0 MSS=1460
36   154.460537   192.168.1.69   192.168.1.65   TCP   irdmi > 49744 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1460
37   154.461381   192.168.1.65   192.168.1.69   TCP   49744 > irdmi [ACK] Seq=1 Ack=1 Win=1460 Len=0

The length of the packet we are trying to send should be 5

Here's my tcp code.
Code: [Select]
    while ((iSerialRxLenth = fnReadIrd(ucSerialInput)) != -1) {             // collect the data until ready
if ((iks_client_socket = fnGetTCP_Socket(TOS_MINIMISE_DELAY, TCP_DEFAULT_TIMEOUT, fnIKSListener)) >= 0) {
fnTCP_Connect(iks_client_socket, iks_server_ip, IKS_SERVER_PORT, 0, 0);
}

memcpy(IKSData.ucTCP_Message,ucSerialInput,iSerialRxLenth);
fnSendTCP(iks_client_socket, (unsigned char *)&IKSData, iSerialRxLenth, TCP_FLAG_PUSH);
        // data ready
        // handle it here
    }

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3162
    • View Profile
    • uTasker
Re: Newbie's firsttime with uTasker
« Reply #54 on: March 04, 2009, 06:50:53 PM »
Hi

35..37 is a normal connection. This is find.

30 is a reset from the server. I don't know why - was it due to a previous frame or a timeout?

I don't see where data is being sent.

regards

Mark


Offline echel0n

  • Newbie
  • *
  • Posts: 37
    • View Profile
Re: Newbie's firsttime with uTasker
« Reply #55 on: March 04, 2009, 07:13:35 PM »
Checksum: 0x83f1 [incorrect, should be 0x3791 (maybe caused by "TCP checksum offload"?)]

Thats what I got for 30 in wireshark.

Here's my revised code
Code: [Select]
#include "config.h"
#include "IKSClient.h"

#define OWN_TASK TASK_IKS_CLIENT

#define INITIALISATION       0
#define ACTIVE               1

// TCP Settings
#define IKS_SERVER_PORT      8000
static USOCKET iks_client_socket;
static unsigned char iks_server_ip[IPV4_LENGTH] = {192, 168, 1, 69};

#define MAX_DATA_LEN 100
typedef struct stTCP_MESSAGE
{
    TCP_HEADER     tTCP_Header;                    // reserve header space
    unsigned char  ucTCP_Message[MAX_DATA_LEN];    // data payload space
} TCP_MESSAGE;

// Serial Port Settings
QUEUE_HANDLE SerialPortID = 0;

static int fnIKSListener(USOCKET Socket, unsigned char ucEvent, unsigned char *ucIp_Data, unsigned short usPortLen)
{
    switch (ucEvent) {
    case TCP_EVENT_ARP_RESOLUTION_FAILED:
        break;
    case TCP_EVENT_DATA:                                                 // a time server sends the time in seconds from 0:0:0 1900 and terminates
        //ulPresentTime = *ucIp_Data++;
        //uTaskerMonoTimer( OWN_TASK, (DELAY_LIMIT)(1*SEC), E_SECOND_TICK );
        break;
    case TCP_EVENT_CLOSE:
    case TCP_EVENT_CLOSED:
        break;
        // If remote server closed before we received the time, try next
    case TCP_EVENT_ABORT:                                              // no connection was established
        //if (ucTimeServerTry < NUMBER_OF_TIME_SERVERS) {
        //    fnTCP_Connect(TIME_TCP_socket, (unsigned char *)&ucTimeServers[ucTimeServerTry++], TIME_PORT, 0, 0); // {15} ucTimeServerTry incremented after use and not before
        //}
        break;

    }
    return APP_ACCEPT;
}

static int fnReadIrd(unsigned char * buf)
{
    static int iRxReceived = 0;                                          // the number of byte received (until now)
    static int iExpectedbytes = 0;
    unsigned char ucInputMessage;                                        // reserve space for receiving messages

    while (fnRead(SerialPortID, &ucInputMessage, 1) != 0) {              // read each presently available input byte
if (iRxReceived == 0) {                                            // searching for sync byte
          if (ucInputMessage != 0x21) {
              continue;                                                  // still not found sync byte
          }
          iRxReceived = 1;                                               // synchronised
          buf[0] = ucInputMessage;
      }
      else {
          if (iRxReceived >= RX_BUFFER_SIZE) {                           // protect buffer overrun on invalid frames
              iRxReceived = iExpectedbytes = 0;                          // go back to sync hunt mode
              continue;
          }
          buf[iRxReceived++] = ucInputMessage;                           // collect message content
          if (iRxReceived == 3) {                                        // the expected length is now known
              iExpectedbytes = (ucInputMessage + 4);                     // note the expected length
          }
          if (iRxReceived == iExpectedbytes) {                           // the complete message has now been collected
              return iExpectedbytes;                                     // inform of the frame length so that it can be processed
          }
      }

    }
    return -1;                                                           // frame not yet ready
}

// This task is started once to initialise the interface and then for each received character
//
extern void fnIKSClient(TTASKTABLE *ptrTaskTable)
{
static TCP_MESSAGE IKSData;
    static unsigned char ucSerialInput[RX_BUFFER_SIZE];                  // static buffer for collecting UART data
    QUEUE_HANDLE        PortIDInternal = ptrTaskTable->TaskID;           // queue ID for task input
    int iSerialRxLenth = 0;                                              // length of collected UART data

    if (!SerialPortID) {                                                 // configure interfaces on initialisation
        SerialPortID = fnSetNewSerialMode(FOR_I_O);
    }

    while ((iSerialRxLenth = fnReadIrd(ucSerialInput)) != -1) {             // collect the data until ready
if ((iks_client_socket = fnGetTCP_Socket(TOS_MINIMISE_DELAY, TCP_DEFAULT_TIMEOUT, fnIKSListener)) >= 0) {
fnTCP_Connect(iks_client_socket, iks_server_ip, IKS_SERVER_PORT, 0, 0);
}

memcpy(IKSData.ucTCP_Message,ucSerialInput,iSerialRxLenth);
if(fnSendTCP(iks_client_socket, (unsigned char *)&IKSData.tTCP_Header, iSerialRxLenth, TCP_FLAG_PUSH) >0) {
//successfull
}
        // data ready
        // handle it here
    }
    // else quit - we return on further input
}



// After changes, we set up the new serial configuration
// (moved from application.c to here) - in application.s #undef SERIAL_INTERFACE added to remove its control of the serial interface
extern QUEUE_HANDLE fnSetNewSerialMode(unsigned char ucDriverMode)
{
    TTYTABLE tInterfaceParameters;                                       // table for passing information to driver
    tInterfaceParameters.Channel = DEMO_UART;                            // set UART channel for serial use
    tInterfaceParameters.ucSpeed = temp_pars->temp_parameters.ucSerialSpeed; // baud rate
    tInterfaceParameters.Rx_tx_sizes.RxQueueSize = RX_BUFFER_SIZE;       // input buffer size
    tInterfaceParameters.Rx_tx_sizes.TxQueueSize = TX_BUFFER_SIZE;       // output buffer size
    tInterfaceParameters.Task_to_wake = OWN_TASK;                        // wake self when messages have been received
    #ifdef SUPPORT_FLOW_HIGH_LOW
    tInterfaceParameters.ucFlowHighWater = temp_pars->temp_parameters.ucFlowHigh;// set the flow control high and low water levels in %
    tInterfaceParameters.ucFlowLowWater = temp_pars->temp_parameters.ucFlowLow;
    #endif
    tInterfaceParameters.usConfig = temp_pars->temp_parameters.usSerialMode;
    #ifdef SERIAL_SUPPORT_DMA
    tInterfaceParameters.ucDMAConfig = UART_TX_DMA;                      // activate DMA on transmission
    #endif
    if ((SerialPortID = fnOpen( TYPE_TTY, ucDriverMode, &tInterfaceParameters )) != 0) { // open or change the channel with defined configurations (initially inactive)
       fnDriver( SerialPortID, ( TX_ON | RX_ON ), 0 );                  // enable rx and tx
    }
    return SerialPortID;
}

Offline echel0n

  • Newbie
  • *
  • Posts: 37
    • View Profile
Re: Newbie's firsttime with uTasker
« Reply #56 on: March 04, 2009, 07:40:11 PM »
Ok via wireshark I see my data being sent but the packet length is set to 1 insteaf of 5 ....
This doesn't make sense.

Transmission Control Protocol, Src Port: 49744 (49744), Dst Port: irdmi (8000), Seq: 0, Len: 1
Options: (4 bytes)
Data (1 byte)
« Last Edit: March 04, 2009, 07:52:36 PM by echel0n »

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3162
    • View Profile
    • uTasker
Re: Newbie's firsttime with uTasker
« Reply #57 on: March 04, 2009, 08:59:10 PM »
Hi

1) TCP checksum incorrect. This is typical of Wireshark (and its predecessor Ethereal). It says this most of the time but it is not correct - it can therefore be ignored.

2) There are a few problems with the code that you have:
a) You are changing the socket each time you want to send data. This is not correct. A socket should only be obtained once and used for all further transactions (also after a close). I suggest putting iks_client_socket = fnGetTCP_Socket(TOS_MINIMISE_DELAY, TCP_DEFAULT_TIMEOUT, fnIKSListener); in the initialisation so that it is obtained when the code starts and then is always valid.
b) You are also opening a new connection on each data packet to be transferred. This is also incorrect. fnTCP_Connect(iks_client_socket, iks_server_ip, IKS_SERVER_PORT, 0, 0); should only be called if you don't yet have a connection. Once connected you can keep the connection open and simply send data.
c) You are not waiting for the connection to open before sending the data. An open may take a short time to complete. In the best case the three-way handshake [SYN, SYN + ACK, ACK sequence] has to be performed (the TCP_EVENT_CONNECTED in the listener signals that it is ready and the first packet can be sent there. In the meantime you will have to back up the data until it has been sent (and subsequently until it has acknowledged).
Often ARP will also first have to resolve the destination MAC address, which requires a bit longer (this is handled by the TCP task so you don't need to do anything actively).
d) Since you are using a simple TCP socket you also have to ensure that no second packet is sent until the first has been acknowledged. This means that you must handle the TCP_EVENT_REGENERATE event to repeat any data which was lost in transmission. And, you need to handle the TCP_EVENT_ACK to know that transmission was successful: in this case you can then discard the backup of the first packet and send any waiting data.

3) Please study the guide here: http://www.utasker.com/forum/index.php?topic=25.0
This explains most details. Also how to use a buffered TCP socket (this means that you don't need to handle the buffering and any regeneration yourself - this is easier but needs extra memory). Remember the example I showed at the beginning?
fnWrite(NETWORK_HANDLE, ucInputMessage, Length);
This could be used (or a direct fnSendBufTCP() call) if the socket is of buffered type. The decision is between RAM use, absolute control and simplicity. The simple TCP socket is in fact the most difficult to control but allows maximum control.


Regards

Mark


Offline echel0n

  • Newbie
  • *
  • Posts: 37
    • View Profile
Re: Newbie's firsttime with uTasker
« Reply #58 on: March 05, 2009, 12:27:54 AM »
Will this work ???

Code: [Select]
extern void fnIKSClient(TTASKTABLE *ptrTaskTable)
{
    QUEUE_HANDLE        PortIDInternal = ptrTaskTable->TaskID;           // queue ID for task input

    if (!SerialPortID) {                                                 // configure interfaces on initialisation
        SerialPortID = fnSetNewSerialMode(FOR_I_O);
    }

while((iks_client_socket = fnGetTCP_Socket(TOS_MINIMISE_DELAY, TCP_DEFAULT_TIMEOUT, fnIKSListener)) < 0);

    while ((iSerialRxLenth = fnReadIrd(ucSerialInput)) != -1) {             // collect the data until ready
if(!connected){
fnTCP_Connect(iks_client_socket, iks_server_ip, IKS_SERVER_PORT, 0, 0);
}

//memcpy(IKSData.ucTCP_Message,ucSerialInput,iSerialRxLenth);
//fnSendTCP(iks_client_socket, (unsigned char *)&IKSData.tTCP_Header, iSerialRxLenth, TCP_FLAG_PUSH);
// Wait for data to be sent


        // data ready
        // handle it here
    }
    // else quit - we return on further input
}

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3162
    • View Profile
    • uTasker
Re: Newbie's firsttime with uTasker
« Reply #59 on: March 05, 2009, 12:55:34 AM »
Hi

I think that the following has chances:

Code: [Select]
extern void fnIKSClient(TTASKTABLE *ptrTaskTable)
{
    QUEUE_HANDLE        PortIDInternal = ptrTaskTable->TaskID;           // queue ID for task input

    if (!SerialPortID) {                                                 // configure interfaces on initialisation
        SerialPortID = fnSetNewSerialMode(FOR_I_O);
        iks_client_socket = fnGetTCP_Socket(TOS_MINIMISE_DELAY, TCP_DEFAULT_TIMEOUT, fnIKSListener))
    }
    if (connected >= 2) {  // TCP transmission is busy so wait - queue all UART rx data in UART buffer in the meantime
        return;
    }

    while ((iSerialRxLenth = fnReadIrd(ucSerialInput)) != -1) {             // collect the data until ready
memcpy(IKSData.ucTCP_Message, ucSerialInput, iSerialRxLenth);
if (!connected){
                    fnTCP_Connect(iks_client_socket, iks_server_ip, IKS_SERVER_PORT, 0, 0);
                    connected = 2;                                                  // waiting for connection
}
                else {
                    fnSendTCP(iks_client_socket, (unsigned char *)&IKSData.tTCP_Header, iSerialRxLenth, TCP_FLAG_PUSH);
                   connected = 3;                                                  // sending
                }
            break;
    }
    // else quit - we return on further input
}

1) I put the get socket in the initialisation - it will never fail as long as you have added a TCP socket to the TCP socket pool for it.
2) When connected is 0 it establishes the connection to the server.
3) data is always backed up so that it can be sent on the connected event in the listener
4) when connected and the not waiting on an ACK TCP data can be sent immediately.
5) I put a break after either requesting connection or sending data so that no more input is read. connected is set to 3 to indicate that data is being sent. In the listener, this should be set back to 1 when the ACK to is received.
6) Note that the UART receiver is not read when the ACK has not yet been received (when connected is >= 2). This means that the UART buffer is queuing any additional data received in the meantime (the size of the queue is adjustable when the UART is opened). This has the advantage that you don't have to read and store multiple waiting messages when the TCP connection is slow or error prone - the UART buffer does this work automatically.
7) Finally you must ensure that the rx UART buffer is checked when the listener receives an ACK and sets connected back to 1. Do this by calling uTaskerStateChange(OWN_TASK, UTASKER_ACTIVATE);. This will make the task run once so it can check and read any messages which are already waiting the UART input and immediately start sending them.
Of course the values 1, 2 and 3 can be given meaningful defined names to make the code more understandably.
8 ) Since you have essentially solved the message backup by copying it to IKSData.ucTCP_Message (which of course has to be static memory) you can simply resend this if the regenerate event is received in the listener.

I think that this may be a real solution for you (unless I have overlooked something) since it then solves all problems (connection, repetition and queuing). Maybe there are some thought to be made about handling serious errors, closes and communication breakdowns but the rest is probably there.

Regards

Mark
« Last Edit: March 05, 2009, 01:00:02 AM by mark »