Author Topic: time of day socket  (Read 8773 times)

Offline Richard

  • Newbie
  • *
  • Posts: 44
    • View Profile
time of day socket
« on: March 06, 2008, 06:15:55 AM »
Hi, Mark.

The time of day seems to drift by a couple of minutes in 24 hours, so I'd like to reset it every once in a while, maybe every ten or fifteen minutes.  In the process of looking at this, I came across the following questions:

It looks like the time of day socket, TIME_TCP_socket, is never actively released once it is opened.  Is there a built-in mechanism in uTasker for aging an unused socket into a closed state and then releasing it?  Does it rely on the remote endpoint to close the connection?  If I want to release the socket after successfully receiving the time, do I first have to do something to close the TCP connection?  If so, does it suffice to call fnTCP_close(), or do I have to "wait around" and release the socket after the close completes?

If I'm going to attempt to reconnect to a time server, I'd like to know if the TIME_TCP_socket is still available, but the routine fnGetSocketControl() is static, so I can't access it outside of tcp.c.  Is there some other way to test whether TIME_TCP_socket is still defined?  Note that, as an uninitialized external variable, it starts out life defined as 0.  From the comment at typedef USOCKET, it looks like 0 is a legal socket number.  Would it be reasonable to define UNDEFINED_SOCKET as -3 and then declare USOCKET TIME_TCP_socket = UNDEFINED_SOCKET; (making it static if appropriate)?

Then, instead of copying the existing
Code: [Select]
if ((TIME_TCP_socket = fnGetTCP_Socket(TOS_MINIMISE_DELAY, TCP_DEFAULT_TIMEOUT, fnTimeListener)) >= 0) {
  fnTCP_Connect(TIME_TCP_socket, (unsigned char *)&ucTimeServers[ucTimeServerTry++], TIME_PORT, 0, 0);
}

I could write something like

Code: [Select]
if (TIME_TCP_socket < 0) {
  ucTimeServerTry = 0;    // since we're opening a new socket, we'll start at the beginning of the list.
  TIME_TCP_socket = fnGetTCP_Socket(TOS_MINIMISE_DELAY, TCP_DEFAULT_TIMEOUT, fnTimeListener);
}
if (TIME_TCP_socket  >= 0) {
  fnTCP_Connect(TIME_TCP_socket, (unsigned char *)&ucTimeServers[ucTimeServerTry++], TIME_PORT, 0, 0);
}

Note that this would rely on whatever released TCP sockets to set TIME_TCP_socket back to UNDEFINED_SOCKET.

I noticed that fnReleaseTCP_Socket() returns either the socket number or a 0 if there is an error, but if 0 is indeed a legal socket number, shouldn't it return -1 in case of an error?   As it happens, the return value is not checked anywhere in the current software, so its value doesn't make a difference.

Sorry to bother you with this raft of questions, but my first attempts to write a simple task that wakes up every ten minutes to reset the time didn't quite work.

Best regards,
    Richard
« Last Edit: March 06, 2008, 06:22:51 AM by Richard »

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: time of day socket
« Reply #1 on: March 06, 2008, 02:46:20 PM »
Hi Richard

There are two main issues here:
- the first are the points that you make
- the second is why the clock runs off by such a lot (perhaps there is a slight error in a frequency configuration which needs to be solved?)

For the moment I will concentrate on your points since there will always be some drift - the periodicity of synchronisation is a variable.

>>Would it be reasonable to define UNDEFINED_SOCKET as -3 and then declare USOCKET TIME_TCP_socket = UNDEFINED_SOCKET;

Generally sockets are initialised with -1 to distinguish them from allocated sockets (which are always positive or zero). In the case of the time server demo the socket is uninitialised - however it is initialised immediately and will not fail due to the fact that there has been a socket reserved for it in the socket pool (see TIME_SERVER_SOCKET). It may be cleaner to initialise it as you suggest. I think that your suggestion for its value is OK, although i would possibly shift the others and use -1 as default.

If you are using the socket repeatedly I wouldn't release it. I tried the following change in the seconds event in teh demo code:
Code: [Select]
                if ((ulPresentTime & 0xf) == 0xf) {
                     fnTCP_Connect(TIME_TCP_socket, (unsigned char *)&ucTimeServers[0], TIME_PORT, 0, 0);
                }

This requests the time every 16s (for test purposes).

>>Note that this would rely on whatever released TCP sockets to set TIME_TCP_socket back to UNDEFINED_SOCKET.
Correct, but this is Ok since it is application code releasing the socket which also knows that it may want to use it again. As I said, I wouldn't release it because this only has advantages if another use is to be made of the socket and in the case of a regular function it may just as well keep it.

>>I noticed that fnReleaseTCP_Socket() returns either the socket number or a 0 if there is an error
Yes I have just seen this. There are a couple of TCP routines which do this so make distinction between an error and an existing socket difficult. I will review and try to add some more meaningful error codes.


Now back to the fact that there is drift.
If you are using the demo code it will be using a timer event to count the seconds:
                uTaskerMonoTimer( OWN_TASK, (DELAY_LIMIT)(1*SEC), E_SECOND_TICK );

If there are some functions in taking place which are blocking scheduling long enough to miss a TICK it is possible that missed TICKs will add up.
The other more mundane explanation is simply that the crystal on the board runs a bit slow.
Another possibility is that the TICK is not exact.
2 minutes in 24 hours represents about 0.14%. If the TICK timer set up is out by one it may well result in this. Some processors have periodic interrupt timers which have limited prescaler/dividers (eg teh freescale NE64) where a 34ms TICK can not be set exactly, and the best one can do is get 34.078ms TICK which obviously runs off a bit.
Since you are using the M5223X I would expect a bit better, so I checked with 60MHz PLL clock and 50ms TICK (see M5223X.c for calculations). In fact the perfect PIT divider (using 4k prescaler) is 366.2 (this is obviously rounded down to 366 or 0x16e). This tells me that in 24 hours the system TICK will in fact run fast by about 0.06% or 47seconds (if I am not mistaken).

If you need higher accuracy you could look at using the RTC in the M5223X (see http://www.utasker.com/forum/index.php?topic=35.0 ). You can configure this to gererate a 1s interrupt which is derived from the crystal directly and so will have the crystal accuracy.
Note too - there is a register called MCF_CLOCK_RTCDR
It is configured in M5223X.c:
   MCF_CLOCK_RTCDR = (OSCCLK-1);                                        // set RTC 1Hz frequency {10}
This derives the 1Hz frequency to driver the RTC. It is also possible to adjust this value to math even the inaccuracy of the crystal to tune it to be even more accurate over long periods of time - of course not taking into account aging drifts and temperate dependency (although this could even be considered...).

Thanks for the interesting feedbak - I will make some improvements as mentioned above.

Regards

Mark


Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: time of day socket
« Reply #2 on: April 18, 2008, 08:12:49 PM »
Hi Richard

I have to correct some details I stated here based on a probably error in the PIT configuration in the M5223X project.

See:
http://www.utasker.com/forum/index.php?topic=248.0

My new calculations are:
"In fact the perfect PIT divider (using 4k prescaler) is (366.2 - 1) (this is obviously rounded down to 365 or 0x16d). This tells me that in 24 hours the system TICK will in fact run fast by about 0.06% or 47seconds (if I am not mistaken)."

Without the correction the error would be slow by 3 Minutes!!

Regards

Mark