µTasker Forum

µTasker Forum => µTasker general => Topic started by: echel0n on February 26, 2009, 08:34:30 PM

Title: Newbie's firsttime with uTasker
Post by: echel0n on February 26, 2009, 08:34:30 PM
Having a hard time with this uTasker and stripping out the unwanted demo apps.

What I'm trying to accomplish is seperating all serial and ethernet code from application.c to there own files such as serial.c and network.c and then bridge them together so data that comes in from uart1 goes out via ethernet to a server app running on my pc then takes the data from the server app in via ethernet and echo's it back out via uart1.

Sounds simple but so far it's becoming rather problematic.

Any idea's or already done source code for me to work with would be appreciated....

Thanks.
Title: Re: Newbie's firsttime with uTasker
Post by: mark on February 26, 2009, 09:36:58 PM
Hi

The uTasker project is a demo project which contains pretty much everything required as base for most general projects. It is however still just an example and in some cases it may be required to start with a fresh sheet. In this case it is advisable to add a fresh project and start there rather than weeding out the bits from the demo which are not required. How to start a fresh project is explained in http://www.utasker.com/docs/uTasker/uTaskerV1.3_user_guide.PDF (from page 2) and you may like to take this root.

What you want to do is make an Ethernet<->RS232 converter. This is not included as part of the demo project. The main reason was due to the fact that it is not as simple as it first seems and there would be a risk of the uTasker project migrating to an Ethernet<->RS232 project rather than remaining a general tool.

The following shows an example of a product which was realised using the uTasker: http://www.xmodus.ch/sm_lan.html

In fact the difficulty is not in the basic operation, such as transferring Ethernet received frames to UART and the reverse - this is very easy. But, the complications start when flow control is considered. That is, what to do when the remote side's UART is blocked due to flow control (assuming UART - but other interfaces or internal processing can lead to the same effect)? This then causes the remote side to have to store the received data until its buffers fill. Then this progresses through the TCP/IP part (windowing) back to the local part, so the flow control finally works its way back to the local UART too, which can't clear input data since the remote TCP socket has closed its window.

All of the support to do this is however present in the package but it does require a bit more work than originally expected before it all works correctly under all circumstances. In fact the result can however still be very efficient, using very small amounts of memory (FLASH and SRAM). The 32k SRAM based SAM7X128 used in the example managed to achieve better file transfer throughput than another product on the market based on an ARM9 with 16Meg SDRAM...

So how to start?

Well I would in fact first stay with the demo project - at least for the first steps - and do a quick tests as follows:

1) Establish a TELNET connection (since the Telnet socket type is the one to use) - ensure USE_TELNET is enabled in the demo project.

2) In application.c add the following line (ensure SERIAL_INTERFACE is enabled):
...
        while ((Length = fnRead( SerialPortID, ucInputMessage, MEDIUM_MESSAGE)) != 0) {
            fnWrite(NETWORK_HANDLE, ucInputMessage, Length); // <--- send all UART input to TCP (TELNET connection)
...


This will already achieve UART -> Ethernet

3) In fnTELNETListener() in debug.c add the following line
...
    case TCP_EVENT_DATA:
        fnWrite(SerialPortID, ucIp_Data, usPortLen); // <----- send all TCP/IP input to the UART
...


This will then achieve Ethernet -> UART

However, as mentioned earlier, there is quite a lot involved to make this into a complete project for a real product. But once the data starts flowing it does make it more fun to work on;-)

Good luck.

Regards

Mark

Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on February 26, 2009, 10:56:45 PM
This project will not require any sort of flow control, just rx and tx.
Data comes into arm7 from another device and then I process the data and depending on what it is I either send it out via ethernet or send it back out via uart1.

Also the data that comes into the arm7 via uart1 is formated in such a way that I can tell exactly how many bytes I'm to expect so I can do a forever loop till X number of bytes arrive and then exit the loop and continue with processing.

Anyways you've shed some light on what I was wondering about.

Now my next question is:
Do I even need application.c file at all ?
Do I need fnApplication function ?
Title: Re: Newbie's firsttime with uTasker
Post by: mark on February 26, 2009, 11:30:45 PM
Hi

Basically you don't need any of the files in the utaskerV1.3 application directory. However it is handy to have the application task (application.c) even if stripped out since it is coordinating the start up of most of the system:

1) It is reading user parameters (and also subroutines controlling the reading of the network parameters for the Ethernet task). See uParameterSystem details in http://www.utasker.com/docs/uTasker/uTaskerFileSystem_3.PDF

2) It is starting some other tasks, like the debug task which is configuring Telnet.

3) It is starting HTTP and FTP servers.

4) It is configuring ports.

5) It is configuring the UART and it is also handling UART reception.

Since you will be using the UART, whos configuration is also a user parameter from the parameter block in FLASH, you may like to keep this part. You can simply add your reception in the read loop:
while ((Length = fnRead( SerialPortID, ucInputMessage, MEDIUM_MESSAGE)) != 0) {
....
}


See the following for using the serial interface(s): http://www.utasker.com/forum/index.php?topic=54.msg220#msg220


Generally the application (every project will have a central management part which could be designated the "application") will be realised as a task similar to the one in application.c. Other tasks can perform more dedicated jobs to keep everything modular. Depending on the project itself, the application can be a high level overviewing function or it may also do lots of nitty-gritty work (too). Therefore I would suggest keeping this file/task because it helps coordinate a project centrally.


Regards

Mark


Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on February 26, 2009, 11:45:07 PM
Then I suppose what I'll do then is move serial into serial.c and ethernet into network.c and strip that code away from application.c but leave anything that would be used to say initiate those 2
Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on February 27, 2009, 01:03:33 AM
Any reason why I can't set hardware breakpoints in crossworks with this ?
I go set a breakpoint but after I build + debug it puts a question mark in the breakpoint saying no code present ????
Title: Re: Newbie's firsttime with uTasker
Post by: mark on February 27, 2009, 01:18:25 AM
Hi

I think that you are using the LPC23XX. Generally this works well with Crossworks - just check that you have chosen a target with debug information (not a release one).

Also it is advisable to disable the watchdog (it is enabled in the uTasker project by default) since the watchdog can cause big problems when debugging. See http://www.utasker.com/forum/index.php?topic=521.msg2223#msg2223
Note that, if the watchdog has been enabled, only a power down cycle will disable it - so even after building with no watchdog (or using the input disable method) don't forget to cycle the power to really stop it.

Regards

Mark
Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on February 27, 2009, 01:27:41 AM
Where would I define this WATCHDOG_DISABLE ???
Title: Re: Newbie's firsttime with uTasker
Post by: mark on February 27, 2009, 01:40:57 AM
Hi

See the link http://www.utasker.com/forum/index.php?topic=521.msg2223#msg2223
WATCHDOG_DISABLE() is in app_hw_lpc23xx.h
Set it to
WATCHDOG_DISABLE() 1
to completely disable it.

Or else by pull the defined port input to '0' to disable it during a debug session.
The exact input depends on the board being used. I think that you use the Olimex (#define OLIMEX_LPC2378_STK should be set in config.h) and this means that it is port0 bit 18 (Button 2). You can keep the button pressed when the board starts and then the watchdog will not be enabled.

Regards

Mark

PS Signing off for tonight. Good luck...
Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on February 27, 2009, 01:50:44 AM
Ok that didn't resolve the issue.

My problem is those blue arrows where you normally would set hardware breakpoints via clicking with your mouse are NOT present in my serial.c but are present in application.c thus I'm unable to set breakpoints hardware-wise to do any debugging.

Why would this be ?
Title: Re: Newbie's firsttime with uTasker
Post by: mark on February 27, 2009, 02:18:20 AM
Hi

This sounds as though you have no code in the file. Check the map to see whether you find your routines. Maybe they are not being called as you expect and the linker is thus not binding the code into the target file.

Is serial.c content defined as a task? It it in the task list? If not there will be no code calling it and so it will be dumped by the linker.

Also try testing with VisualStudio (you can also test UARTs and Ethernet) since there are no target-level debugging difficulties involved. When it works there you can generally load to the board and run...

Regards

Mark
Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on February 27, 2009, 02:45:42 AM
Yup it's defined as a task perfectly along with code in the serial.c file is present.
Not sure whats gone wrong with it.
Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on February 27, 2009, 02:44:24 PM
Ok from what I can tell this is ONLY happening when creating new files.

I created test.c and copied some code from applicaiton.c into test.c then started debugging to find I was unable to set breakpoints with this new code in test.c yet the very same code in application.c was able to have breakpoints applied to it.

whats the reason for this ?
Title: Re: Newbie's firsttime with uTasker
Post by: mark on February 27, 2009, 02:58:19 PM
Hi

Have you correctly added your new file to the Rowley project? Check that its attributes are not set to 'exclude from build'.
Also are you sure that it is really being compiled? Type some extra things in the file so that it is invalid code and check that the compiler really gives an error due to this.

Regards

Mark
Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on February 27, 2009, 03:06:27 PM
It's not being excluded from build and I added something to it that I know would throw a compile error and it did throw the error so I'm slightly confused as to whats wrong.
Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on February 27, 2009, 03:10:30 PM
Ok Now I've gone as far as to extracting the uTasker source files and service pack files from scratch again into a new folder and not touching a single file.
What I've done is add a new file called test.c with some source code in it, maybe about 10 lines of code.

I've compiled it fine but when debugging I get no breakpoints in ONLY that file.

Any clues ?
Title: Re: Newbie's firsttime with uTasker
Post by: mark on February 27, 2009, 03:13:24 PM
Hi

Yes, me too.

Did you check that the code was really appearing in the map file? (confirming that it is being linked in correctly)

It it possible that the code is there but somehow the attributes for the new file in the project is to generate it without debug information?

Do you have Rowley support to ask them if they known what is happening?

Regards

Mark

Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on February 27, 2009, 03:20:19 PM
Yes I can see it in the MAP file and it's being linked in perfectly.

This doesn't make any sense to me why it would do this to me.

Now keep in mind I'm creating test.c and NO test.h so I don't know if that would be the culprit.
Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on February 27, 2009, 03:25:18 PM
Ok just created test.h and no diffrence. I just don't understand what the reasoning behind this would be.
Title: Re: Newbie's firsttime with uTasker
Post by: mark on February 27, 2009, 03:30:09 PM
Hi

I just did the following.

1) using Rowley Crossworks 1.7 Build 16 I opened the standard uTasker V1.3 project for SAM7X
2) I created a new file called test.c in Rowley. I placed it in the Applications\uTaskerV1.3 folder
3) I added this content:

static int iTest = 0;
extern void fnTest(void)
{
    iTest++;
}

4) In application.c task I added two calls to the new routine fntest()
fntest();
fntest();


5) In test.c I put a break point at the line:
   iTest++;

6) I then downloaded to RAM (using Thumb RAM debug) target) after building the project.

7) The break point was hit twice, as expected and the local variable incremented to2, as expected.
The following is the screen shot. It shows the break point and a second blue arrow.

Can you repeat this step by step to see whether it is really different at your end?

Regards

Mark

PS. Note that this was the SAM7x project. I will repeat with the LPC23XX project and the Olimex board
Title: Re: Newbie's firsttime with uTasker
Post by: mark on February 27, 2009, 03:43:13 PM
Hi

Now I have results from the same test on the LPC2378-STK. This time I worked with the FLASH DEBUG target.

I did get the blue arrows and I could put a break point in the routine. It stopped there correctly and I could step normally.

However, when working from FLASH you have only one HW break point. If you try to set a second, when there is already one somewhere else you will see the question mark. By hovering the mouse over it it will inform that the break point could not be set due to lack of HW break points.

I have attached my Rowley project file (as just tested) as reference.

Regards

Mark

Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on February 27, 2009, 03:49:03 PM
I belieave I've located the problem.

For whatever reason crossworks was reporting there was no issues with the build and made it appear as if things compiled perfectly.
It was clearly misleading me as I extracted a fresh copy of uTasker and created a file called test.c then created a task for it in TaskConfig.h then re-compiled and debugged. All the blue arrows were present.

For whatever reason before it would do this but like I said I heavily modified application.c and stripped out ALOT of code and moved all the serial routines from there to serial.c.

I'm gonna try this again but keep a closer eye on it this time.

Thanks and I'll let you know how my progress makes.

BTW if I have to create serial.h cause I have to move code from application.h into would I include serial.h in config.h ?
Title: Re: Newbie's firsttime with uTasker
Post by: mark on February 27, 2009, 04:01:13 PM
Hi

If you need only serial.h in the single file you can just add it there.

If you find that you need to share it between several files it is simplest to add it in your config.h - there is already a list of includes in it, so add it to the list.

Note that all files should include config.h so that they all have everything needed for the uTasker resources. Generally this single include is all that is needed.

Good luck

regards

Mark

Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on February 27, 2009, 05:10:17 PM
Ok the problem is back again but this time I've not modified application.c and only touched TaskConfig.h to add my task in then created a new file and added the following code:

Code: [Select]
#include "config.h"

#define OWN_TASK             TASK_IKS_CLIENT

#define INITIALISATION       0
#define ACTIVE               1

QUEUE_HANDLE SerialPortID;
static unsigned char ucSerialInput[RX_BUFFER_SIZE];                  // static buffer for collecting UART data

static char fnReadIrd(unsigned char * buf)
{
  unsigned char ucInputMessage;                  // reserve space for receiving messages
  int a = 0;

  if (fnRead(SerialPortID, &ucInputMessage, 1) != 0) {
    return -1;
  }

  if (ucInputMessage != 0x21) {
    return -1;
  }
  buf[0] = ucInputMessage;

  while (fnRead(SerialPortID, &ucInputMessage, 1) != 0);
    buf[1] = ucInputMessage;
  while (fnRead(SerialPortID, &ucInputMessage, 1) != 0);
    buf[2] = ucInputMessage;

  for (a = 0; a < buf[2] + 1; ++a)
  {
      while (fnRead(SerialPortID, &ucInputMessage, 1) != 0);
      {
          buf[3 + a] = ucInputMessage;
      }
  }

  return buf[2] + 4;
}

extern void fnIKSClient(TTASKTABLE *ptrTaskTable)
{
  static int iSerialRxLenth = 0;                                       // length of collected UART data
  static int iTaskState = INITIALISATION;

  QUEUE_HANDLE        PortIDInternal = ptrTaskTable->TaskID;           // queue ID for task input
 
  if (INITIALISATION == iTaskState) {                                  // configure interfaces on initialisation
      fnSetNewSerialMode(FOR_I_O);
      iTaskState = ACTIVE;
  }

  // Wait for RX Data from receiver
  while ((iSerialRxLenth = fnReadIrd(ucSerialInput)) == -1);
}

Give it a try and tell me if you get breakpoints or not please ...
Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on February 27, 2009, 06:57:19 PM
Mark have you tried and got same issue now as I do ?
Title: Re: Newbie's firsttime with uTasker
Post by: mark on February 27, 2009, 09:21:42 PM
Hi

I just tried it and it looks good here (see screen shot). I can set break points and step - all the blue arrows are there.

I added four lines to TaskConfig.h:

...
#define TASK_IKS_CLIENT         'I'
...
extern void fnIKSClient(TTASKTABLE *ptrTaskTable);
...
TASK_IKS_CLIENT,
...
  { "I",       fnIKSClient,  MEDIUM_QUE,  (DELAY_LIMIT)(0.20 * SEC), 0, UTASKER_STOP},
...


After the 200ms delay the task started.

However (after doing the first test) I changed the code since it causes problems when data is really received. You need to remember that the uTasker OS is state event driven and you can't wait for characters in a task. I have re-written it and tested it in the simulator so that it does (more of less - maybe there is a length slightly off somewhere) that which you want it to do.

These are the changes:
1. In application.c I added #undef SERIAL_INTERFACE to remove all serial port control from there.
2. I moved the serial interface configuration to your file.
3. I added a simple state-even machine to handle the searching for the sync character 0x21. Then it collects the content and informs that it is ready for further handling when its length corresponds to buf[2] length details. In addition I added a length check to reject frames which have a bad format  so that they don't overrun the input buffer.

Regards

Mark

Code: [Select]
#include "config.h"

#define OWN_TASK             TASK_IKS_CLIENT

#define INITIALISATION       0
#define ACTIVE               1


QUEUE_HANDLE SerialPortID = 0;

static CHAR 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 + 3);                     // 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 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
        // 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 TEST_MSG_MODE
    tInterfaceParameters.usConfig |= (MSG_MODE);
        #if defined (TEST_MSG_CNT_MODE) && defined (SUPPORT_MSG_CNT)
    tInterfaceParameters.usConfig |= (MSG_MODE_RX_CNT);
        #endif
    tInterfaceParameters.usConfig &= ~USE_XON_OFF;
    tInterfaceParameters.ucMessageTerminator = '\r';
    #endif
    #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
        if (tInterfaceParameters.usConfig & RTS_CTS) {                   // {8}
            fnDriver( SerialPortID, (MODIFY_INTERRUPT | ENABLE_CTS_CHANGE), 0 ); // activate CTS interrupt when working with HW flow control (this returns also the present control line states)
            fnDriver( SerialPortID, (MODIFY_CONTROL | SET_RTS), 0 );     // activate RTS line when working with HW flow control
        }
    }
    return SerialPortID;
}




Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on February 28, 2009, 08:36:28 PM
Ok I've done exactly as you've instructed and here's the outcome.

#1. Function fnReadIRD has no breakpoints and says no code present.
#2. Function fnIKSClient has no breakpoints and says no code present.
#3. Function fnSetNewSerialMode has breakpoints.

I just don't understand whats happening here.

Any idea's ?
Title: Re: Newbie's firsttime with uTasker
Post by: mark on February 28, 2009, 10:02:03 PM
Hi

This would be consistent with the task content never being called from anywhere else in the code. The routine fnSetNewSerialMode() is called from debug.c so it is (also) getting linked correctly.

Try calling fnIKSClient() directly from application.c or even from within fnSetNewSerialMode() . Just pass a null-pointer as parameter.

If the task code is then present it means that the linker is recognizing that it is needed (being linked in) and would conform that the linker is otherwise leaving it out. [Note that the code will actually crash when fnIKSClient() is called directly  but at least it will allow the test to be made].

Please post you TaskConfig.h file so that I can check that you are really adding in your task correctly to the task table (this is the only logical explanation for it to be otherwise missing).

Regards

Mark
Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on February 28, 2009, 10:24:29 PM
Ok calling fnIKSClient(0) from application.c fixes the issue so it must be something with TaskConfig.h

Here's the code contained in TaskConfig.h

Code: [Select]
   /********************************************************************
   Mark Butcher      Bsc (Hons) MPhil MIEE

   M.J.Butcher Consulting
   Obere Bahnhofstrasse 13, 5507 Mellingen

   www.uTasker.com      Skype: M_J_Butcher

   ---------------------------------------------------------------------
   File:        TaskConfig.h
   Project:     Single Chip Embedded Internet
   ---------------------------------------------------------------------
   Copyright (C) M.J.Butcher Consulting 2004..2008
   *********************************************************************

   28.04.2007 Add SNMP task
   13.05.2007 Add PPP task

*/


/******************************** The tasks used in the system ********************************************/
/* Warning - each task must use a unique letter equivalent to the start of its task name                  */
#define TASK_WATCHDOG           'W'                                      // watchdog task
#define TASK_ETHERNET           'E'                                      // ethernet task
#define TASK_ARP                'A'                                      // ARP task
#define TASK_TCP                'T'                                      // TCP task
#define TASK_BOOTP              'B'                                      // Bootp task
#define TASK_DHCP               'D'                                      // DHCP task
#define TASK_DNS                'd'                                      // DNS task
#define TASK_POP3               'P'                                      // POP 3 task
#define TASK_PPP                'U'                                      // PPP task
#define TASK_SMTP               'S'                                      // SMTP task
#define TASK_FTP                'F'                                      // FTP task
#define TASK_TFTP               't'                                      // TFTP task
#define TASK_APPLICATION        'a'                                      // application task
#define TASK_CAN_SIM            'c'                                      // CAN simulator task
#define TASK_DEBUG              'm'                                      // debugger (maintenance) task
#define TASK_TIMER              'p'                                      // timer task for global timer use
#define TASK_LCD                'L'                                      // application LCD task
#define TASK_KEY                'K'                                      // keyboard scanning task
#define TASK_NETWORK_INDICATOR  'N'                                      // task displaying network activity
#define TASK_DATA_SOCKET        's'                                      // task handling data socket
#define TASK_ICMP               'i'                                      // this is a pseudotask for sending ping results
#define TASK_LOW_POWER          'l'                                      // Task supporting power saving
#define TASK_SNMP               'M'                                      // snMp protocol task
#define TASK_IKS_CLIENT         'I'

#undef  OWN_TASK

#ifdef LAN_REPORT_ACTIVITY
   #define INTERRUPT_TASK_PHY         TASK_NETWORK_INDICATOR             // This task is woken on PHY changes (set 0 for none)
#endif
#define UNETWORK_MASTER               TASK_APPLICATION                   // This task is worken on uNetwork error events
#define INTERRUPT_TASK_LAN_EXCEPTIONS TASK_NETWORK_INDICATOR             // This task is woken on Ethernet exceptions (set 0 for none)
#define INTERRUPT_TASK_SERIAL_CONTROL TASK_APPLICATION                   // This task is woken on general serial control line changes (set 0 for none)
#define CAN_ERROR_TASK                TASK_APPLICATION                   // This task is woken on CAN errors

extern void fnTaskWatchdog(TTASKTABLE *);
extern void fnApplication(TTASKTABLE *);
extern void fnDebug(TTASKTABLE *);
extern void fnTaskEthernet(TTASKTABLE *);
extern void fnTaskArp(TTASKTABLE *);
extern void fnTaskTCP(TTASKTABLE *);
extern void fnDHCP(TTASKTABLE *);
extern void fnBootp(TTASKTABLE *);
extern void fnDNS(TTASKTABLE *);
extern void fnPOP3(TTASKTABLE *);
extern void fnSmtp(TTASKTABLE *);
extern void fnTftp(TTASKTABLE *);
extern void fnLCD(TTASKTABLE *);
extern void fnADC(TTASKTABLE *);
extern void fnKey(TTASKTABLE *);
extern void fnTimer(TTASKTABLE *);
extern void fnNetworkIndicator(TTASKTABLE *);
extern void fnLowPower(TTASKTABLE *);
extern void fnSNMP(TTASKTABLE *);
extern void fnPPP(TTASKTABLE *);
extern void fnIKSClient(TTASKTABLE *ptrTaskTable);


/************ uTasker task table is defined here but only used by the hardware module initiates the system ***********/

#define DEFAULT_NODE_NUMBER    1                                         // we use one fixed node in the system

#ifdef SUPPORT_DISTRIBUTED_NODES
    extern const unsigned char ucNodeMac[MAX_NETWORK_NODES][MAC_LENGTH];
#endif

#ifdef OPSYS_CONFIG                                                      // this is only set in the hardware module

CONFIG_LIMIT OurConfigNr = DEFAULT_NODE_NUMBER;                          // in single node system this can be initialised with a fixed value

#ifdef SUPPORT_DISTRIBUTED_NODES
    NETWORK_LIMIT OurNetworkNumber = 0;                                  // this value must be set (to non-zero) on startup individually for each node in the network

    const unsigned char ucNodeMac[MAX_NETWORK_NODES][MAC_LENGTH] = {
        {0,0,0,0,0,1},                                                   // MAC address of nodes in the system
        {0,0,0,0,0,2}
    };
#endif

const HEAP_NEEDS ctOurHeap[] = {
    {DEFAULT_NODE_NUMBER, OUR_HEAP_SIZE},                                // our node requires this amount of heap space
    {0}                                                                  // end
};


const UTASK_TASK ctNodes[] = {                                           // we use a single fixed configuration (single node)
  DEFAULT_NODE_NUMBER,                                                   // configuration our single node

  TASK_WATCHDOG,                                                         // watchdog task
#ifdef USE_IP
  TASK_ARP,                                                              // ARP task
#endif
#ifdef ETH_INTERFACE
  TASK_ETHERNET,                                                         // ethernet task
#endif
#ifdef USE_TCP
  TASK_TCP,                                                              // TCP task
#endif
  TASK_APPLICATION,                                                      // application task
  TASK_DEBUG,                                                            // maintenance task
#ifdef USE_BOOTP
  TASK_BOOTP,                                                            // Bootp task
#endif
#ifdef USE_DHCP
  TASK_DHCP,                                                             // DHCP task
#endif
#ifdef USE_DNS
  TASK_DNS,                                                              // DNS task
#endif
#ifdef USE_POP3
  TASK_POP3,                                                             // POP 3 task
#endif
#ifdef USE_SMTP
  TASK_SMTP,                                                             // POP 3 task
#endif
#ifdef USE_FTP
  TASK_FTP,                                                              // FTP task
#endif
#ifdef USE_TFTP
  TASK_TFTP,                                                             // TFTP task
#endif
#ifdef SUPPORT_LCD
  TASK_LCD,                                                              // LCD task
#endif
#ifdef USE_SNMP
  TASK_SNMP,                                                             // SNMP task
#endif
#ifdef SUPPORT_ADC
  TASK_ADC,                                                              // ADC task
#endif
#ifdef USE_PPP
  TASK_PPP,                                                              // PPP task
#endif
#ifdef SUPPORT_KEY_SCAN
  TASK_KEY,                                                              // Key scan task
#endif
#ifdef GLOBAL_TIMER_TASK
  TASK_TIMER,                                                            // Gobal Timer Task
#endif
  TASK_NETWORK_INDICATOR,                                                // network activity indicator task
  TASK_DATA_SOCKET,                                                      // data socket task
#ifdef SUPPORT_LOW_POWER
  TASK_LOW_POWER,                                                        // Low power task
#endif
  TASK_IKS_CLIENT,
  0,                                                                     // end of single configuration

  // insert more node configurations here if required
  0                                                                      // end of configuration list
};


const UTASKTABLEINIT ctTaskTable[] = {
  // task name,  task routine,   input queue size, start delay, period, initial task state
#ifdef _HW_SAM7X
  { "Wdog",      fnTaskWatchdog, NO_QUE,   (DELAY_LIMIT)( 0.2 * SEC ), (DELAY_LIMIT)( 0.2 * SEC ),  UTASKER_STOP},    // watchdog task (Note SAM7X is not allowed to start watchdog immediately since it also checks for too fast triggering!!)
#else
  { "Wdog",      fnTaskWatchdog, NO_QUE,   0, (DELAY_LIMIT)( 0.2 * SEC ),  UTASKER_GO},      // watchdog task (runs immediately and then periodically)
#endif
#ifdef USE_IP    // Warning - start ARP task before Ethernet. If Ethernet messages are received before ARP tabelle is ready there would be an error..
  { "ARP",       fnTaskArp,      MEDIUM_QUE, (DELAY_LIMIT)(0.05 * SEC), 0, UTASKER_STOP},  // ARP task check periodically state of ARP table
#endif
#ifdef ETH_INTERFACE
  { "Eth",       fnTaskEthernet, (HEADER_LENGTH * 12),  (DELAY_LIMIT)(0.05 * SEC), 0, UTASKER_STOP}, // ethernet task - runs automatically
#endif
#ifdef USE_TCP
  { "TCP",       fnTaskTCP,      MEDIUM_QUE,  (DELAY_LIMIT)(0.10 * SEC), 0, UTASKER_STOP}, // TCP task checks periodically state of session timeouts (controlled by task itself)
#endif
  { "app",       fnApplication,  MEDIUM_QUE,  (DELAY_LIMIT)(0.10 * SEC), 0, UTASKER_STOP}, // Application - start after Ethernet to be sure we have Ethernet handle
#ifdef USE_BOOTP
  { "BOOTP",     fnBootp,        SMALL_QUEUE, (DELAY_LIMIT)(0.10 * SEC), 0, UTASKER_STOP}, //
#endif
#ifdef USE_DHCP
  { "DHCP",      fnDHCP,         SMALL_QUEUE, (DELAY_LIMIT)(NO_DELAY_RESERVE_MONO), 0, UTASKER_STOP}, // delay only for timer queue space
#endif
#ifdef USE_DNS
  { "dNS",       fnDNS,          SMALL_QUEUE, (DELAY_LIMIT)(0.05 * SEC), 0, UTASKER_STOP}, // start before application calls a search
#endif
#ifdef USE_POP3
  { "POP",       fnPOP3,         SMALL_QUEUE, (DELAY_LIMIT)(0.10 * SEC), 0, UTASKER_STOP}, //
#endif
#ifdef USE_SMTP
  { "SMTP",      fnSmtp,         SMALL_QUEUE, (DELAY_LIMIT)(NO_DELAY_RESERVE_MONO), 0, UTASKER_STOP},  //
#endif
#ifdef USE_TFTP
  { "tFTP",      fnTftp,         SMALL_QUEUE, (DELAY_LIMIT)(NO_DELAY_RESERVE_MONO), 0, UTASKER_STOP},  //
#endif
#ifdef USE_SNMP
  { "MsnMp",     fnSNMP,         SMALL_QUEUE, (DELAY_LIMIT)(NO_DELAY_RESERVE_MONO), 0, UTASKER_STOP},  //
#endif
#ifdef USE_PPP
  { "Uart_ppp",  fnPPP,          SMALL_QUEUE, (DELAY_LIMIT)(NO_DELAY_RESERVE_MONO), 0, UTASKER_STOP},  //
#endif
#ifdef SUPPORT_LCD
  { "LCD",       fnLCD,          MEDIUM_QUE,  (DELAY_LIMIT)(NO_DELAY_RESERVE_MONO), 0, UTASKER_STOP},  //
#endif
#ifdef SUPPORT_ADC
  { "cDA",       fnADC,          NO_QUE,      (DELAY_LIMIT)(2.0 * SEC), (DELAY_LIMIT)(0.05 * SEC), UTASKER_STOP},  //
#endif
#ifdef SUPPORT_KEY_SCAN
  { "Key",       fnKey,          NO_QUE,      (DELAY_LIMIT)(0.1 * SEC), (DELAY_LIMIT)(0.1 * SEC), UTASKER_STOP},  //
#endif
#ifdef GLOBAL_TIMER_TASK
  { "period",    fnTimer,        SMALL_QUEUE, (DELAY_LIMIT)(NO_DELAY_RESERVE_MONO), 0, UTASKER_STOP},   //
#endif
#ifdef USE_MAINTENANCE
  { "maintenace",fnDebug,        SMALL_QUEUE, (DELAY_LIMIT)(NO_DELAY_RESERVE_MONO), 0, UTASKER_STOP}, // Task used for debug messages (started by application)
#endif
#ifdef LAN_REPORT_ACTIVITY
  { "NetInd", fnNetworkIndicator,LARGE_QUE,   (DELAY_LIMIT)(NO_DELAY_RESERVE_MONO), 0, UTASKER_STOP}, // Network activity task
#endif
#ifdef SUPPORT_LOW_POWER
  { "lowPower", fnLowPower,      NO_QUE,      0, 0, UTASKER_GO},         // Low power task
#endif
  { "I",       fnIKSClient,  MEDIUM_QUE,  (DELAY_LIMIT)(0.20 * SEC), 0, UTASKER_STOP},
  { 0 }
};
#endif                                                                   // end of task configuration
Title: Re: Newbie's firsttime with uTasker
Post by: mark on February 28, 2009, 11:11:21 PM
Hi

When I use this TaskConfig.h but don't add the test file with fnIKSClient() in it the code doesn't build since the task fnIKSClient() is missing (this is of course what is expected and verifies that the linker is seeing that fnIKSClient() is required).
I so nothing wrong with your configuration.

Before putting this down to Gremlins in the system I have two (possibly) final ideas:


Last but one thought... your TaskConfig.h is fine and works here. Is it possible that you are editing a TaskConfig.h file which is not actually the one used by the project? This would then indeed be a logical explanation as to why the file is not being linked. Make a small change in the file and see whether the project is rebuilt when compiled (a change in the 'real' TaskConfig.h should cause all files to be rebuilt. If you get no rebuild after a change it would mean that it doesn't see it as a project file with dependency.

Last thought... Also try a project rebuild (rather than just compile - it is also sometimes known as a clean) to ensure that the files actually using the TaskConfig.h content are being compiled with its new content. I have seen cases where object files have (somehow) received newer dates than source files (a data in the future) and the make file never re-compiles because it thinks that the output is newer (nasty problems can arise until it is noticed). A rebuild will cause all object files to be deleted and then everything to be recompiled, resulting in a correction of any such corrupted projects.

Good luck

Regards

Mark
Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on March 02, 2009, 01:50:51 AM
Well I've tried everything and so far the only way I see this working is to call fnIKSClient() from application.c
How might I go about doing this properly since it's a task that needs to be executed.
Title: Re: Newbie's firsttime with uTasker
Post by: mark on March 02, 2009, 01:45:31 PM
Hi

Try adding a dummy call to fnIKSClient() from application.c, but somewhere where it is never actually called.

Eg:

int iDoCall = 0;  // global variable
...

if (iDoCall != 0) {
    fnIKSClient(0);
}


You have to trick the compiler/linker into not removing the call - the global variable will usually do it.

As you have already found, as long as fnIKSClient() is called form application.c its code is present and you can also debug in it. This should be enough to assure that.

The question is whether it is then scheduled correctly - eg. started after 200ms. This you will see when debugging. If it doesn't, it still means that it is not 'really' in your TaskConfig.h - which is the only logical explanation that I can think of, but why is beyond me.
If it does, it means that you have discovered a real problem with the GNU compiler since it is refusing to acknowledge the presence of your task code.

Make this last test and if the trick still doesn't work please zip your complete project (exactly as it is) and send it to me (Mark@uTasker.com). I will then open it exactly as you have it and attempt to explain what is happening.

Regards

Mark

Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on March 02, 2009, 08:47:52 PM
Ok I've emailed my source code.
Just extract it into the application folder.

The trick worked to allow me to debug the code but my task was never called.
Title: Re: Newbie's firsttime with uTasker
Post by: mark on March 02, 2009, 10:22:26 PM
Hi

I am sorry but I have bad news.

I extracted the folder that you had compressed to the Applications\uTaskerV1.3 folder and then opened it in Rowely Crossworks.
Since the project didn't have paths to the debug code (since it was moved to another PC) I had to rebuild it.

Then I downloaded and set a break point in your task and it arrived there and I could step normally. See the screen shot below:

The only thing that didn't work as expected is that the task never exists. Instead it has optimised a loop away into a forever loop (which didn't occur in the simulator) so I am looking at why this should be the case (obviously something to do with the GCC optimiser).

My feeling is that when you compile the TaskConfig.h is still not being used correctly by the build because that's the only reason why the task's code would be missing in the debugger when not forced in by a dummy call and also why it wouldn't be scheduled.

I would try deleting the complete content of Applications\uTaskerV1.3\IKSClient\Rowley_LPC23XX\THUMB Flash Release so that it is impossible for something not be be compiled.
Also from Rowley try disassembling the individual file (Click on IKSClient.c in the project explorer - right click and Disassemble: I get three main disassemble block of lengths 0x82, 0x8e and 0x3e - does this correspond to what you see.
Then try the command "pre-process". It shows you all includes being used, the values inserted and will also show which code is being compiled and which not.

I will ask someone at Rowley to take a quick look to see whether there is an explanation for this. It is obvously not the code and not the Rowley project settings but rather something local to your PC, but this is the mystery which I just can't solve at the moment.

Regards

Mark
Title: Re: Newbie's firsttime with uTasker
Post by: mark on March 02, 2009, 10:29:40 PM
Hi

Although not the real topic of the thread, the forever loop is due to a mismatch between the return value from fnReadIrd() and the length iSerialRxLenth

If static CHAR fnReadIrd(unsigned char * buf) is changed to static int fnReadIrd(unsigned char * buf) it is OK.

regards

Mark
Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on March 02, 2009, 11:29:45 PM
Ok here's what I got when I disassemble
Code: [Select]
section .text

section .data

section .bss

section .text.fnSetNewSerialMode
  <fnSetNewSerialMode>:
  <fnIKSClient>:
   B570       push {r4-r6, lr}
   B084       sub sp, #0x010
   466D       mov r5, sp
   2301       movs r3, #0x01
   722B       strb r3, [r5, #0x08]
   4B1B       ldr r3, [pc, #0x06C]
   681A       ldr r2, [r3, #0x00]
   1C93       adds r3, r2, #0x2
   7FDB       ldrb r3, [r3, #0x1F]
   72EB       strb r3, [r5, #0x0B]
   2380       movs r3, #0x80
   015B       lsls r3, r3, #0x05
   80EB       strh r3, [r5, #0x06]
   2640       movs r6, #0x40
   2349       movs r3, #0x49
   732B       strb r3, [r5, #0x0C]
   80AE       strh r6, [r5, #0x04]
   1C13       adds r3, r2, #0x0
   334B       adds r3, #0x4B
   781B       ldrb r3, [r3, #0x00]
   736B       strb r3, [r5, #0x0D]
   1C13       adds r3, r2, #0x0
   334C       adds r3, #0x4C
   781B       ldrb r3, [r3, #0x00]
   73AB       strb r3, [r5, #0x0E]
   0601       lsls r1, r0, #0x18
   8B93       ldrh r3, [r2, #0x1C]
   0E09       lsrs r1, r1, #0x18
   2000       movs r0, #0x00
   466A       mov r2, sp
   802B       strh r3, [r5, #0x00]
   F7FFFFFE   bl 0x0000003E
   4C0E       ldr r4, [pc, #0x038]
   7020       strb r0, [r4, #0x00]
   2800       cmp r0, #0x00
   D010       beq 0x0000006C
   2105       movs r1, #0x05
   2200       movs r2, #0x00
   F7FFFFFE   bl 0x0000004E
   882B       ldrh r3, [r5, #0x00]
   4233       tst r3, r6
   D009       beq 0x0000006C
   4909       ldr r1, [pc, #0x024]
   2200       movs r2, #0x00
   7820       ldrb r0, [r4, #0x00]
   F7FFFFFE   bl 0x0000005E
   7820       ldrb r0, [r4, #0x00]
   2181       movs r1, #0x81
   2200       movs r2, #0x00
   F7FFFFFE   bl 0x00000068
   4B03       ldr r3, [pc, #0x00C]
   7818       ldrb r0, [r3, #0x00]
   B004       add sp, #0x010
   BC70       pop {r4-r6}
   BC02       pop {r1}
   4708       bx r1
   0000       lsls r0, r0, #0x00
   0000       lsls r0, r0, #0x00
   0000       lsls r0, r0, #0x00
   0000       lsls r0, r0, #0x00
   0404       lsls r4, r0, #0x10
   0000       lsls r0, r0, #0x00

section .text.fnIKSClient
  <fnSetNewSerialMode>:
  <fnIKSClient>:
   B510       push {r4, lr}
   4C1E       ldr r4, [pc, #0x078]
   7823       ldrb r3, [r4, #0x00]
   B081       sub sp, #0x004
   2B00       cmp r3, #0x00
   D125       bne 0x00000058
   2003       movs r0, #0x03
   F7FFFFFE   bl 0x0000000E
   7020       strb r0, [r4, #0x00]
   E020       b 0x00000058
   491A       ldr r1, [pc, #0x068]
   680A       ldr r2, [r1, #0x00]
   2A00       cmp r2, #0x00
   D107       bne 0x0000002E
   7822       ldrb r2, [r4, #0x00]
   2A21       cmp r2, #0x21
   D119       bne 0x00000058
   2301       movs r3, #0x01
   600B       str r3, [r1, #0x00]
   4B16       ldr r3, [pc, #0x058]
   701A       strb r2, [r3, #0x00]
   E014       b 0x00000058
   2A3F       cmp r2, #0x3F
   DD04       ble 0x0000003C
   4A15       ldr r2, [pc, #0x054]
   2300       movs r3, #0x00
   6013       str r3, [r2, #0x00]
   600B       str r3, [r1, #0x00]
   E00D       b 0x00000058
   7824       ldrb r4, [r4, #0x00]
   4B11       ldr r3, [pc, #0x044]
   1C50       adds r0, r2, #0x1
   54D4       strb r4, [r2, r3]
   6008       str r0, [r1, #0x00]
   2803       cmp r0, #0x03
   D102       bne 0x00000050
   4A0F       ldr r2, [pc, #0x03C]
   1CE3       adds r3, r4, #0x3
   6013       str r3, [r2, #0x00]
   4B0D       ldr r3, [pc, #0x034]
   681B       ldr r3, [r3, #0x00]
   4298       cmp r0, r3
   D00A       beq 0x0000006E
   4B08       ldr r3, [pc, #0x020]
   466C       mov r4, sp
   3403       adds r4, #0x03
   7818       ldrb r0, [r3, #0x00]
   1C21       adds r1, r4, #0x0
   2201       movs r2, #0x01
   F7FFFFFE   bl 0x00000064
   2800       cmp r0, #0x00
   D1D4       bne 0x00000016
   E001       b 0x00000072
   3001       adds r0, #0x01
   D1F2       bne 0x00000058
   B001       add sp, #0x004
   BC10       pop {r4}
   BC01       pop {r0}
   4700       bx r0
   0000       lsls r0, r0, #0x00
   0000       lsls r0, r0, #0x00
   0000       lsls r0, r0, #0x00
   0000       lsls r0, r0, #0x00
   0000       lsls r0, r0, #0x00
   0000       lsls r0, r0, #0x00
   0000       lsls r0, r0, #0x00
   0000       lsls r0, r0, #0x00
   0000       lsls r0, r0, #0x00

section .bss.SerialPortID
  <fnSetNewSerialMode>:
  <fnIKSClient>:
   000C       lsls r4, r1, #0x00

section .bss.ucSerialInput.2174
  <fnSetNewSerialMode>:
  <fnIKSClient>:
   000C       lsls r4, r1, #0x00
   0000       lsls r0, r0, #0x00
   FFFFFFFF   undefined opcode
   0001       lsls r1, r0, #0x00
   7C01       ldrb r1, [r0, #0x10]
   0C0E       lsrs r6, r1, #0x10
   000D       lsls r5, r1, #0x00
   0024       lsls r4, r4, #0x00
   0000       lsls r0, r0, #0x00
   0000       lsls r0, r0, #0x00
   0000       lsls r0, r0, #0x00
   0000       lsls r0, r0, #0x00
   0000       lsls r0, r0, #0x00
   0084       lsls r4, r0, #0x02
   0000       lsls r0, r0, #0x00
   0204       lsls r4, r0, #0x08
   0000       lsls r0, r0, #0x00
   0E00       lsrs r0, r0, #0x18
   8410       strh r0, [r2, #0x20]
   8504       strh r4, [r0, #0x28]
   8603       strh r3, [r0, #0x30]
   8E02       ldrh r2, [r0, #0x30]
   0401       lsls r1, r0, #0x10
   0002       lsls r2, r0, #0x00
   0000       lsls r0, r0, #0x00
   200E       movs r0, #0x0E
   0000       lsls r0, r0, #0x00
   0020       lsls r0, r4, #0x00
   0000       lsls r0, r0, #0x00
   0000       lsls r0, r0, #0x00
   0000       lsls r0, r0, #0x00

section .bss.iExpectedbytes.2153
  <fnSetNewSerialMode>:
  <fnIKSClient>:
   000C       lsls r4, r1, #0x00
   0000       lsls r0, r0, #0x00

section .bss.iRxReceived.2152
  <fnSetNewSerialMode>:
  <fnIKSClient>:
   000C       lsls r4, r1, #0x00
   0000       lsls r0, r0, #0x00

Still I'm unable to set breakpoints
Title: Re: Newbie's firsttime with uTasker
Post by: mark on March 03, 2009, 12:30:22 AM
Hi

This is identical to mine. Compiling is good.

I have sent you the map file (per email) generated when I build. Perhaps you can see a difference in the content.

I have asked Rowley to take a look. At the moment I am out of ideas apart from to try working in a different PC to see whether there is a change.

Regards

Mark

Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on March 03, 2009, 01:06:07 AM
ok I've gone as far as to install crossworks on my laptop and try it there and it was a no go.
i'm starting to wonder if it's my utasker source ?
Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on March 03, 2009, 01:16:01 AM
Ok I got it to work but the way I did it is completly messed up.
I re-extracted the utasker along with service pack 3 and instead of copying the folder to a new folder to start a new project I just decided to edit it as is.

It worked!!!

So then I re-opened my older IKS project we've been messing with and it works now as well.

Why is this ?
Title: Re: Newbie's firsttime with uTasker
Post by: mark on March 03, 2009, 02:37:40 AM
Hi

I am pleased that it has started to work but can't explain what was going on.
That the project which was not working also suddenly started is a further mystery. [Perhaps someone else can think of an explanation]

I hope that it at least continues working from now.

And, that you can finally start doing some real work - hopefully you can make up some lost time using the features in the project...

Also don't forget to try the uTasker simulator since this can save most real development time and also avoids a lot of work on the target.

Regards

Mark

Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on March 03, 2009, 03:05:52 AM
Let me explain what I did.

I extracted a fresh copy of utasker and utasker sp3

I then opened up taskconfig.h inside of the utaskerv1.3 folder and added in my iksclient task and then I also created a new file called iksclient.c and added in my own code.

I then debugged/compiled and it worked perfectly.

So after doing so I reloaded my old project located under folder iksclient and it started working as well.

So for some reason the changed I made to file TaskConfig.h in folder utaskerv1.3 reflected on what I was compiling in folder iksclient which should have been a seperate project folder all together with it's own taskconfig.h file but it would appear that when modifying taskconfig.h contained under iksclient folder it would do simply nothing.

any reason for this ? perchance it's a path or file setup incorrectly in utasker ?
Title: Re: Newbie's firsttime with uTasker
Post by: mark on March 03, 2009, 03:24:07 AM
Hi

Each application folder contains its own:
- config.h
- TaskConfig.h
- Types.h and
- app_hw_xxxx.h

In Rowley Crossworks there is a setting: Preprocessor Options -> User Include Directories
This path is set to ..\\..\\..\\Applications\\uTaskerV1.3 in the demo project.

When a new project folder is created but this include path not modified to suit, it is probable that some files will be using includes from the demo project. I expect this is the problem that you had. In fact, I don't think that the project corrected itself but rather you had compiled a configuration using a modified TaskConfig.h in the demo which is then being used for the new project setting too.

If even in doubt about which includes are being used, it is always a good idea to intentionally add an error to the file and recompile. If the build works it means that the compiler didn't see the error and is therefore working with a different file!

Therefore I think that this now does explain the problem. I didn't see it because I replaced the uTaskerV1.3 content in my tests with your code since I didn't realise that you had copied the project directory.

I will rework the "uTasker - First Steps for new Users" document so that this point is made clear to avoid similar difficulties.

regards

Mark





Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on March 03, 2009, 03:39:09 AM
Now with that being finally solved and outta the way I seem to have some issue with my code.

In function fnReadIRD() where it says "if (ucInputMessage != 0x21) {" it never seems to equal 0x21

Now the device that sends the data to my ARM7 via uart1 has all it's packets start with 21 so I'm lost why it's not working with uTasker but the same code in the past has worked with other tasking projects ...

Any idea's ?
Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on March 03, 2009, 04:13:28 AM
Ok by running the simulator I'm finding the first value it gets is "33" which is the DEC equiv to "21" in hex.
Why would it be in DEC and not in HEX ? Is this something to do with fnRead ?
Title: Re: Newbie's firsttime with uTasker
Post by: mark on March 03, 2009, 01:32:04 PM
Hi

fnRead() doesn't change content in any way.

Check that your settings for the interface speed, parity etc. match correctly.
Also try by sending to a normal terminal emulator to see the data that is being received - 0x21 is '!' and so is visible. 0x33 is '3' - so you can verify.

If you are saying that it is displaying 33 dec, this is identical to 0x21 hex (the debugger can be set to display hex or dec) so would in fact be correct.

I just simulated your code and sent 0x21 (33) by typing in '!' from a terminal emulator connected to the UART. The task was woken and the receiver synchronised (0x21 or 33 was put to buf[0]):

      if (iRxReceived == 0) {                                            // searching for sync byte
          if (ucInputMessage != 0x21) {
              continue;                                                  // still not found sync byte
          }
          iRxReceived = 1;                                               // synchronised
          buf[0] = ucInputMessage;


Therefore it looks to be good.
Please check again - I am sure that there are no problems with the UARTs but more a misunderstanding somewhere.

Regards

Mark
Title: Re: Newbie's firsttime with uTasker
Post by: echel0n 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
Title: Re: Newbie's firsttime with uTasker
Post by: mark 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



Title: Re: Newbie's firsttime with uTasker
Post by: echel0n 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 ?
Title: Re: Newbie's firsttime with uTasker
Post by: mark 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



Title: Re: Newbie's firsttime with uTasker
Post by: echel0n 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.
Title: Re: Newbie's firsttime with uTasker
Post by: mark 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


Title: Re: Newbie's firsttime with uTasker
Post by: echel0n 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.

??
Title: Re: Newbie's firsttime with uTasker
Post by: mark 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
Title: Re: Newbie's firsttime with uTasker
Post by: echel0n 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
    }
Title: Re: Newbie's firsttime with uTasker
Post by: mark 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

Title: Re: Newbie's firsttime with uTasker
Post by: echel0n 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;
}
Title: Re: Newbie's firsttime with uTasker
Post by: echel0n 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)
Title: Re: Newbie's firsttime with uTasker
Post by: mark 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

Title: Re: Newbie's firsttime with uTasker
Post by: echel0n 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
}
Title: Re: Newbie's firsttime with uTasker
Post by: mark 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
Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on March 05, 2009, 01:32:16 AM
Ok here's a update on all the code I have so far.
It appears to send data but once it gets to the 2nd time around it gives a exception error in vb.net

Code: [Select]
#include "config.h"
#include "IKSClient.h"

#define OWN_TASK TASK_IKS_CLIENT

#define INITIALISATION       0
#define ACTIVE               1

// TCP Settings
int connected = 0;
int busy = 0;
#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;
static TCP_MESSAGE IKSData;

// Serial Port Settings
int iSerialRxLenth = 0;
static unsigned char ucSerialInput[RX_BUFFER_SIZE];
QUEUE_HANDLE SerialPortID = 0;

static int fnIKSListener(USOCKET Socket, unsigned char ucEvent, unsigned char *ucIp_Data, unsigned short usPortLen)
{
    switch (ucEvent) {
case TCP_EVENT_CONNECTED:
connected = 1;
memcpy(IKSData.ucTCP_Message,ucSerialInput,iSerialRxLenth);
if(fnSendTCP(iks_client_socket, (unsigned char *)&IKSData.tTCP_Header, iSerialRxLenth, TCP_FLAG_PUSH) > 0)
return APP_SENT_DATA;
break;
    case TCP_EVENT_ARP_RESOLUTION_FAILED:
        break;
case TCP_EVENT_REGENERATE:
memcpy(IKSData.ucTCP_Message,ucSerialInput,iSerialRxLenth);
if(fnSendTCP(iks_client_socket, (unsigned char *)&IKSData.tTCP_Header, iSerialRxLenth, TCP_FLAG_PUSH) > 0)
return APP_SENT_DATA;
break;
    case TCP_EVENT_DATA:
busy = 0;
        break;
    case TCP_EVENT_CLOSE:
    case TCP_EVENT_CLOSED:
connected = 0;
        break;
case TCP_EVENT_ACK:
connected = 1;
uTaskerStateChange(OWN_TASK, UTASKER_ACTIVATE);
break;
    case TCP_EVENT_ABORT:
fnTCP_Connect(iks_client_socket, iks_server_ip, IKS_SERVER_PORT, 0, 0);
        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)
{
    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;
} else {
fnSendTCP(iks_client_socket, (unsigned char *)&IKSData.tTCP_Header, iSerialRxLenth, TCP_FLAG_PUSH);
connected = 3;
}
break;
}
    // 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;
}

BTW I appreciate all the time and effort your putting into this for me and others.
Thanks!!!
Title: Re: Newbie's firsttime with uTasker
Post by: mark on March 05, 2009, 02:49:36 AM
Hi

I see a few more things.

1) There is no need to do a memcpy(IKSData.ucTCP_Message,ucSerialInput,iSerialRxLenth); in the listener. The data is already in the IKSData.ucTCP_Message.

2) In the project we use uMemcpy() rather than memcpy(). uMempy() allows better debugging in the simulator (you can't step into memcpy() to check pointer values). Also it can (depending on processor type used) be accelerated by using DMA.

3) I don't know the length of the messages you are receiving but I think that the crash will be due to a buffer overflow. I think that
iRxReceived = iExpectedbytes = 0;                          // go back to sync hunt mode
must also be performed when the message has been completely received, as well as
              return iExpectedbytes;                                     // inform of the frame length so that it can be processed
otherwise following characters are not put to the start of the buffer - and also the sync hunting doesn't re-start. I don't actually see the crash reason but this should be much easier to find in the simulator than on the target since the simulator has very powerful debugging support (actually VS and not the simulator itself).

When you get an exception you should see lots of information - which line it is at, variable contents etc., which should help solve any such (quite normal software development issues...) quite easily.

Final note:
In fact you can save the ucSerialInput[] buffer in the code since you also have the static TCP_MESSAGE IKSData; Since no more UART rx data is being put into it during tcp transmission (until ACK confirmation) the next time you actually read UART data in, the IKSData.ucTCP_Message is free. This means that you can in fact read UART data directly into IKSData.ucTCP_Message. This saves a buffer and also a uMemcpy(), resulting in even more efficiency of memory and speed.

Good luck.

Regards

Mark
Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on March 05, 2009, 03:18:01 AM
Ok i'm now able to send and receive the data and send it out of my uart but I notice that it's all running rather slow like it doesn't try and get the next request from the uart after I send my response I got from ethernet out via the uart.

Anyway to rectify this to go quicker ?
Title: Re: Newbie's firsttime with uTasker
Post by: mark on March 05, 2009, 03:40:56 AM
Hi

You will need to look at the TCP flow (using WireShark) and also the pause periods on the UART (oscilloscope) to see what is really going on.

Here are a couple of notes:

1) When sending TCP data to a PC you will generally not get an ACK for about 150ms. This is due to the PC's TCP/IP stack performing Delayed- Ack operation. See more details here: http://www.utasker.com/forum/index.php?topic=396.0
To overcome this, either the PC program must disable Delayed- Ack operation or else it needs to be overcome by performing TCP windowing. This is automatically done when using a buffered TCP socket but is not that with a simple TCP socket (best use a buffered socket if this is what you are seeing and TCP speed in the PC direction is to be maximised.

2) When testing with the simulator, the throughput may be a little slower due to its polling operation. To see whether this is the case, try reducing the TICK to 20 or even 10ms. I don't expect that this will be the problem but when sending fast data that needs fast reaction it can help a bit. Also check the performance on the target to see whether there is a difference here or not.

In config.h

#ifdef _WINDOWS
    #define TICK_RESOLUTION      20  // increase tick rate to speed up simulator reaction time
#else
    #define TICK_RESOLUTION      50 // no need to speed up on teh target since it is purely interrupt driven
#endif


Beware that going below about 10ms on XP or Vista PC will cause it to start going slower again due to the increasing TICK overhead for Windows...!!


3) I didn't understand exactly in which path the delay is but you should find that the reaction time between the ACK being received and the task reading its UART input again (on the target) is only a few us. In the simulator it may be up to the TICK interval value. You also didn't quantify what you mean by slow. Is this in the us, ms or seconds range? I wouldn't expect the simulator delay to be that noticeable. The Ethernet part of the simulator is a bit different and doesn't poll. Its though-put is usually a bit higher than on the target since the PCs processor and its support hardware is rather fast in comparison.

Regards

Mark

Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on March 05, 2009, 04:23:05 AM
Ok let me explain my self a little better on whats really slow.

I can send the data to the server and get a response back right away it's the time after that I wait for it to process the next request from the uart thats slow.
See the device that is sending requests to my ARM7 device responds right away but if not answered right away it'll timeout so what needs to happen is after the response comes back from the server and gets sent out via the uart to my other device the task needs to restart and get data from the uart again right away.
Title: Re: Newbie's firsttime with uTasker
Post by: echel0n on March 05, 2009, 05:19:54 AM
Ok i've changed the following code and things seemed to have sped up a bit but it's like it comes in bursts but just isn't a steady enough speed to keep communication with my device going.

Code: [Select]
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

iRxReceived = iExpectedbytes = 0;
    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
}

Not sure if I placed the iRxReceived = iExpectedbytes = 0; in the correct place but it seems to work better now.

Now I'm not sure if buffered TCP would work since the device needs to make a request and then get a response before it can make another request or it'll just timeout and go back to the very first request it made.
Title: Re: Newbie's firsttime with uTasker
Post by: mark on March 05, 2009, 01:09:52 PM
Hi

I don't think the reset of iRxReceived and iExpectedbytes is in a good place. It will trash any UART messages not received in a single block.
Try the following position.

          if (iRxReceived == iExpectedbytes) {                    // the complete message has now been collected
              int iRtn = iExpectedbytes;
              iRxReceived = iExpectedbytes = 0;                   // reset counter and start searching for next frame synch
              return iRtn ;                                                      // inform of the frame length so that it can be processed
          }


I expect that (from your explanation) the UART reception is missing messages (due to the fact that the buffer counters are not being handled correctly). Then there is a timeout (and I assume repeat from the device or PC sending to the UART) which is then synchronised to. Probably the repetitions are seen as delays.

You didn't say whether you are presently working with the simulator only, the target only or both.
As explained before the simulator may have slight delays in the order or 10ms but the target should only have delays in the order of us. I do work a lot with such protocols (eg. MODBUS running on multiple UARTs and multiple TCP sessions) using both simulator and target. There is a slight difference in maximum speed but it is still fast. Any sluggishness will almost certainly be due to the code so this must be analysed and corrected where necessary.

Regards

Mark