Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Topics - Richard

Pages: [1] 2
µTasker general / Finding device with DHCP IP address
« on: June 27, 2009, 04:07:15 AM »
Hi, all.

Imagine that you send a uTasker device -- e.g., an intelligent coffee maker that has a web server on port 4388 -- to your friend to install in his house.  Your friend knows almost nothing about networks, but someone has already set up an Ethernet network for him, so all he has to do is plug in the coffee pot.  He would like to see the coffee pot's web page on his PC (via the LAN), and you'd like to see the web page on your PC (via the Internet). 

What I don't understand:
1) how will your friend know what IP address was assigned to the coffee pot by his DHCP server?
2) how will you convince his router to accept traffic from you for port 4388 and forward it to the coffee pot?  I.e., how do you open port 4388 through the router's NAT?
3) Number 2 comes into play only if you already know your friend's public IP address, which is most likely one that is assigned dynamically by his ISP and subject to change.  There are solutions for this, see e.g., <>.  Some routers have a built-in update client -- the module that sends "here-I-am" to the dynamic DNS service at appropriate intervals -- but not all do.  Is there uTasker code for an update client?

Given the push to attach everything in the world to the Internet, this problem must have been addressed somewhere, but I haven't seen where.  I'd appreciate any hints.


Hi, Mark.

So far as I can tell, ucTopOfStack, defined as an unsigned char in fnInitialiseHeap(), is never actually used.  Only its address is ever referenced, here in this
Code: [Select]
while (ucPattern <= &ucTopOfStack) {                                 // this pattern is used later for Stack use monitoring
    *ucPattern++ = UNUSED_STACK_PATTERN;
Apparently, the compiler never actually allocates a location for the variable.  Indeed, it does not appear in uTasker_full.elf.xMAP.  The result is that the while loop that is supposed to fill the heap with UNUSED_STACK_PATTERN doesn't do anything.

Did I miss something?

I found this because, in my program,
Code: [Select]
pucTopOfHeap += ctOurHeap->need_this_amount;
causes pucTopOfHeap to be set to 0x20008340.  Since there is no memory there, calling fnStackFree() fails with an access error exception on an operand read.  If the while loop in fnInitialiseHeap() actually did anything, an access error would have occurred at that point, as the program was starting up.

My next question is this: can I safely reduce the value of OUR_HEAP_SIZE below the 21K it is set to and by how much?

Since I'm using CodeWarrior and use only uMalloc() and never malloc(), it looks like I can change HEAP_SIZE = 0x1000; to HEAP_SIZE = 0; in M52235EVB_FLASH.lcf.  The note in the file is a little difficult to interpret: by "This can be left as zero..." do you mean that it can be reduced to zero?  If so, it may be enough to save me without reducing OUR_HEAP_SIZE ... for now.


P.S. Thinking about your comment,
If the pattern is not being set it suggests that its address is below the top of heap (system variables plus OUR_HEAP_SIZE)
I've modified the code in fnInitialiseHeap() to be
Code: [Select]
if (pucTopOfHeap <= &ucTopOfStack) {
    while (ucPattern <= &ucTopOfStack) {                                 // this pattern is used later for Stack use monitoring
        *ucPattern++ = UNUSED_STACK_PATTERN;
else                   // not enough memory for heap!
    while (1) {}; // hang here to make the problem obvious while debugging.

NXPTM M522XX, KINETIS and i.MX RT / Handling short power failures
« on: April 21, 2009, 11:39:22 PM »
Hi, all.
    In previous projects, I've found that many power outages are so short that RAM values are reliably maintained, even though prudence dictated stopping the CPU when power dropped below a certain level.  If power was again restored within seconds, a surprisingly frequent situation, a quick check of RAM -- e.g., a checksum of a specific area --  if successful, can allow the program to resume as though nothing had happened.  This is the desired result, since going through a full restart may have unpleasant side-effects, including annoying the user.
    Unfortunately, the M5223X CW project startup code zeroes RAM before allowing any user-defined procedures to run.  This is one way to guarantee that external C variables are initialized to zero by default, as required by C semantics.  However, it prevents using my old assembly-language based technique for a silent restart after a very brief outage.
    So I've got three questions:
1) Is it possible to protect a specified part of RAM from being zeroed on power up?  And, of course, it has to be possible to specify which variables are to be put into this part of RAM.
2) Is there some other reasonable way during power up to tell that power has been down for a very short time, at most a few seconds?  If this were possible, I could simply save critical data in FLASH as power went down and restore it after short outages.
3) Is there some other way to respond to failing power that prevents erratic behavior but does not cause a full reset if power comes back quickly?

Thanks for any suggestions.
    - Richard

Maybe I'm losing my mind...

If I write

double x;
void fn0(void) {
  x = ...;

where x is a global, I'll get expected results.  But if I write

void fn0(void) {
  double x;
  x = ...;

where x is a local variable, the debugger and the compiler disagree about where x is located, so the displayed value for x in the debugger has the wrong value.  I've single stepped through the assembly code and seen what location gets put into the registers that access the variable; it's not the same as the one attributed to the variable by the debugger.

A similar problem occurs with values passed as function arguments, e.g.,

void fn1(double t) {
  ... = t...;

My code is based on uTasker SP 7  -- in particular, in the ColdFire Processor configuration panel, Parameter Passing is set to Register, Integers are 4 bytes, A6 Stack Frames are turned off, the CPU is a 52233 (so Floating Point is automatically selected to be Software), both the Code and Data Models are set to Far (32 bit).  I believe all the other choices are the usual ColdFire ones.

I'm using CodeWarrior 7.1, build 14. I've made the recommended additions and changes to use floating point variables --
1) include (and link) the following files in my project:
    fp_coldfire.a in C:\Program Files\Freescale\CodeWarrior for ColdFire V7.1\ColdFire_Support\Libraries
    C_4i_CF_RegABI_Runtime.a in C:\Program Files\Freescale\CodeWarrior for ColdFire V7.1\ColdFire_Support\Runtime
    C_4i_CF_RegABI_SZ_MSL.a in C:\Program Files\Freescale\CodeWarrior for ColdFire V7.1\ColdFire_Support\msl\MSL_C\MSL_ColdFire\Lib

2) modify ansi_prefix.CF.size.h in C:\Program Files\Freescale\CodeWarrior for ColdFire V7.1\ColdFire_Support\msl\MSL_C\MSL_ColdFire\Include by changing a couple of #defines to give

#if !((__COLDFIRE__ == __MCF5475__ || __COLDFIRE__ == __MCF5485__) && !__option(fp_library))
#define _MSL_FLOATING_POINT 1  // was 0
#undef _MSL_NO_MATH_LIB         // was define

Unlike Neil's suggestion (topic 399, message 1646), I did not change _MSL_FLOATING_POINT_IO from 0 to 1, because I'm not trying to format or print floating point numbers.

With the exception of this debugging problem, floating point code seems to work just fine with this setup.

My questions are these:
    1) has anyone else observed this problem? and
    2) is there some setting I missed that would make the debugger correctly recognize the location of local variables of type double?
and, of course,
    3) am I losing my mind?


NXPTM M522XX, KINETIS and i.MX RT / RTC initialization
« on: March 24, 2009, 07:23:15 PM »
When I tried to use the RTC, I found that the one-minute interrupt occurred every 12 seconds.  Changing the value stored in the Real Time Clock Divide Register from
when I initialized the RTC fixed the problem.

I don't understand the theory behind the problem and its solution, since the manual clearly says that the RTC gets its 1 Hz frequency by dividing the oscillator clock by a factor of RTCDF+1, but empirically, I needed the crystal frequency -- at least that's what the macro names imply.

I should point out that I'm using my own board, not one of the Freescale (Axiom) DEMO boards, and maybe the difference is to be found there.

Best regards,

Hi, all.  The 5223X has the ability to detect when the supply voltage is dropping and force an interrupt.  According to table 2.3 of the MCF52235 Data Sheet (still labeled "advance information" in revision 6!), the low voltage detect trip voltage is between 2.15 and 2.3 Volts.

I'd like to be able to save a few values in a block of internal flash between the time the low voltage interrupt occurs and power drops to a level that no longer permits reliable writing to flash.  Has anyone an idea if this is possible?  I.e., is it even possible to write to the internal flash at 2.15 Volts.  If so, how much time does it take to write one block of flash, and how long after the interrupt occurs will power still be above whatever is required to write flash?

Assume the worst case, i.e., that power fails completely while the 5223X is in its full power mode, and assume that power capacitors and resistors are as recommended by Freescale, e.g., on their demo board or Figure 5. "Suggested Connection Scheme for Power and Ground" of the MCF52235 Data Sheet. 

I guess that the first thing to do after receiving the interrupt would be to clear the Peripheral Power Management Registers (PPMRH, PPMRL) to shut down all the clocks and set all ports to be GPIO with their DDRs set to 0 (inputs) so the CPU wouldn't be sourcing more power than necessary...or is there a better way to do reduce power and still be able to write to the internal flash?

Thanks for whatever thoughts and information you may have.

    - Richard

NXPTM M522XX, KINETIS and i.MX RT / M5225X support
« on: December 05, 2008, 03:30:45 AM »
Hi, Mark.  A very small point:

In file M5223X.h (supports also M5213, M5222X) is the comment line
Code: [Select]
   13.08.2008   Add M5223X support                                       {24}but every time {24} appears, it seems to be associated with M5225X.  Since the file already accommodated the M5223X family, I suspect that the processor number in the comment is a typo.

Also, the line identifying the file near its beginning should probably have M5225X added to the "supports also" part.

    - Richard 

µTasker general / User authentication
« on: May 20, 2008, 04:47:24 AM »
Hi.  I've had a bit of trouble when I've tried to force the user to log in before accessing web pages.

To test this, I forcibly set ucHttpProperties |= WEB_AUTHENTICATE; in fnConfigureAndStartWebServer. (I'm sure there's a better permanent solution that involves setting the appropriate bit in ucServers, but for this initial test, I haven't tried to figure out the best place to do that.)

However, for reasons I don't fully understand, the routine fnWebParHandler checks to see if (ucFile == ' ') before it tries to authenticate the user.  Using SP7 and the simulator, it is apparent that ucFile has the value '0' at the time the test is made.  If I change the test in fnWebParHandler, to be if (ucFile == '0'), the user authentication appears to work as expected.

Is this the correct way to deal with user authentication for web pages, or is there something else that is more in keeping with your original intent and hence more reliable than the expedient "hack" I've created?

Best regards,

Hi, Mark.

In trying to understand parameter blocks, I seem to have run into a couple of bugs.

fnSaveNewPars(SAVE_NEW_PARAMETERS) calls (after some nesting) fnWriteLongWordFlash().  This relies on fnFlashNow().  Since it is generally not possible to execute code from FLASH when also writing to FLASH, the first time fnFlashNow() is used, it copies necessary code into RAM, using uMemcpy(), and then tries to execute the copy.

To copy more than 20 bytes (as defined by SMALLEST_DMA_COPY), uMemcpy() uses a DMA technique.  By setting breakpoints on the M52233DEMO board, I have found that in this case, the copy does not work; the relevant portion of memory contains mostly 0x00 after uMemcpy() returns.  If I set SMALLEST_DMA_COPY to some very high number, forcing a direct copy (*ptr1++ = *ptr2++;), uMemcpy() does the necessary copy and the expected code makes it into RAM.

In the process of working with this, I also tried commenting out DMA_MEMCPY_SET but defining RUN_LOOPS_IN_RAM.  This caused the compiler to complain a couple of times about an illegal constant expression.

I am using uTasker 1.3, SP6, and version 7.0 of the Codewarrior IDE, but I've tried this with version 6.4, too, and had the same results.

I am still having some difficulties understanding parameter blocks, but I'll post questions about those in the general forum when I have formulated my thoughts a little more sharply.

Best regards,

µTasker general / Internet Time Service protocol
« on: March 28, 2008, 06:09:26 AM »
Hi.  I'm back to thinking about time and putting information about the time zone into the parameter block.  In the process, I stumbled across the following information about the NIST Internet Time Service (ITS)  They will eventually no longer support the time protocol used in the uTasker code, Time Protocol (RFC-868), which uses port 37.  They say it is used by only about 1% of their users, and they want everyone to move to Network Time Protocol (RFC-1305), which uses port 123.

Starting on 14 April 2007 the server will no longer respond to requests for time in the TIME format (as defined in RFC-868). These requests are generated by a number of different programs including DATE, RDATE, and other programs that connect to the time server using tcp or udp port 37. All of the other NIST servers (except for will continue to respond to requests to either tcp or udp port 37 for time in the format specified in RFC-868.

However, this format has poor error-handling capabilities in general, and many of the client programs that use this format are poorly written and may not handle network errors properly. Therefore users are strongly encouraged to switch to the Network Time Protocol (NTP), which is more robust and provides greater accuracy. We eventually intend to phase out support for the TIME format on all servers.

Please send questions or comments regarding this issue to Judah Levine:

For my purposes, the older, RFC-868 protocol is good enough, but I'd hate to see an application fail in the field because NIST decides to pull the plug on the service, especially since they've given warning well in advance.  So, eventually [but it could be years, who knows?] we'll all be forced to use the new protocol, or at least the simplified version of NTP, suitable for most uses, specified in RFC-4330.

Has anyone worked with this?  Has anyone written a modified version of the uTasker TIME client that makes use of the newer protocol that he would be willing to share?  Is there a simple reference version available on the Internet?  All the sample code provided by NIST uses older protocols.  All the other reference code I can find spreads the details over dozens of files -- and it can't be that hard.

I shouldn't let this stop me from figuring out how to put time zone information into the parameter block, with a way for the user to update it for summer time or a change in location (probably via a web page).


µTasker general / 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.
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,

NXPTM M522XX, KINETIS and i.MX RT / Service Pack 6 and CodeWarrior 7.0
« on: February 25, 2008, 03:09:49 AM »

Has anyone succeeded in getting Service Pack 6 to run using CodeWarrior 7.0?

A couple of months ago, Freescale upgraded CodeWarrior to version 7.0 (see <>).  As is now usual, the "standard edition" is free, so I downloaded it and have been using it for my project, which is based on Mark's V1.3 SP5 code and its various patches.  It runs on the M52233DEMO board.

To remain current, I decided to switch my project over to SP6 and then ran into trouble.  To try to figure out what went wrong, I went back to the original V1.3 release, loaded SP6 over it, renamed its config_ref... to config.h and made two copies of the resultant directory structure.

I ran one copy using CW 6.4, using CFM_MCXF52233 to set the parameters of the Flash Programmer.  This appears to have been successful, because the program runs, and if I set a breakpoint at the beginning of fnApplication(), it gets to that breakpoint and halts.

I tried then to run the other copy using CW 7.0, using MCF_52233_INTFLASH.xml to set the parameters of the Flash Programmer.  This version can erase the FLASH and load the program.  However, when I start the debugger, it opens at .debug_frame + 0x00000000, and nothing I can do will convince it to take even one step into the program.  Single stepping does nothing.  If I start it running and then stop it, it's always at the first step.  If I set a breakpoint at the beginning of fnApplication(), it never gets there.

It must be possible to make SP6 run using CW 7.0.  Is there some magic I've missed?


µTasker general / Accessing registers without pointers
« on: October 26, 2007, 01:59:21 AM »
The Freescale Application Note AN2616, "Getting Started with HCS08 and CodeWarrior Using C", section 6.6, recommends defining a register via a structure, as in this example:
Code: [Select]
/*** DBGC - Debug Control Register ***/
typedef union {
  byte Byte;
  struct {
    byte RWBEN :1; /* Enable R/W for Comparator B */
    byte RWB :1; /* R/W Comparison Value for Comparator B */
    byte RWAEN :1; /* Enable R/W for Comparator A */
    byte RWA :1; /* R/W Comparison Value for Comparator A */
    byte BRKEN :1; /* Break Enable */
    byte TAG :1; /* Tag/Force Select */
    byte ARM :1; /* Arm Control */
    byte DBGEN :1; /* Debug Module Enable */
  } Bits;
extern volatile DBGCSTR _DBGC @0x00001816;
using these data types:
Code: [Select]
/* Types definition */
typedef unsigned char byte;
typedef unsigned int word;
typedef unsigned long dword;
typedef unsigned long dlong[2];

To access the bits of DBGC, you can write things like
Code: [Select]
DBGC.Bits.RWB = 1; /*Set RWB bit of DBGC */
DBGC.Bits.RWB = 0; /*Clear RWB bit of DBGC */
Note that this avoids the use of a pointer to access DBGC by telling the compiler where it is located.

This may work fine for the CodeWarrior HCS08 compiler but not for either the CodeWarrior Coldfire or the Microsoft Visual Studio 2005 compiler.  Both are unhappy about dealing with a statement like
  extern volatile DBGCSTR _DBGC @0x00001816;
which is supposed to declare that DBGC is at location 0x00001816.

How can I achieve the same effect with the CodeWarrior and the Microsoft Visual Studio compilers?  I.e., how can I tell these compilers what address to assign to a variable?


The following C code
Code: [Select]
const int a=1;
const int b=2;
const int c=a+b;
void main(){}
generates an "error C2099: initializer is not a constant" for the line const int c=a+b; when compiled with Visual C++ 2005 Express Edition (the compiler I use for simulation) but not when compiled with the Freescale CodeWarrior C compiler.
   Is this a bug of the Visual C++ compiler or a non-standard extension of the Freescale compiler?
   I know I could use various #define work arounds, but would prefer not to, for exactly the reasons that const was added to C.  Is there a good way around this?

NXPTM M522XX, KINETIS and i.MX RT / Web parameters
« on: September 26, 2007, 06:21:19 AM »
Hi. Do you have a write up of the web parameter facility of your demo software, i.e., the part of the web server that deals with "£" embedded in the html pages it serves?

Pages: [1] 2