Kenneth Wada

image
President
I am a embedded systems consultant in Silicon Valley California.

krwada

's contributions
Articles
Comments
Discussions
    • Thou didst don the pointy hat! This is how I feel when programming within the Linux Kernel. Happy April-1 Jack!

    • Hello Lundin; Yes, I think I did misunderstand what you meant. So, in your proposal, the struct definition would be hidden. How would the function call in C be implemented ... without an object that is? Would all the instances be carried in the C source file?

    • Sorry about the long delay getting back to you. When you say static analysis tools ... Do you mean lint? ... or are you referring to something like Coverity?

    • Again ... I forgot to add: You need to instance an XPTIMER object, then use it on the function with a cast. For example: XPTIMER my_xptimer01; void main (void) { . some code ... . . XPTIMER_update ((GPTIMER *)&my_xptimer01); }

    • I stated pointer to a parent. I meant to say is a pointer to the broker that 'owns' or manages the instance of a timer object.

    • Dang! I did not know that embedded.com will list the comments in latest 1st. I should have reversed my replies. I will do so next time. You will need to read my replies in reverse order. Sorry!

    • This is the beauty of unsigned arithmetic. When you do unsigned arithmetic, the carry bit is virtual. You can treat the carry bit as much as one would do using a half-adder. Here is an example using 8-bit unsigned arithmetic CURRENT_COUNT = 0xFE CAPTURE_COUNT = 0xFE ... some time later ... CURRENT_COUNT = 0x02 Now for some unsigned arithmetic: CURRENT_COUNT - CAPTURE_COUNT = 0x02 - 0xFE = 0x04 Now, if we had the carry bit it really is: CURRENT_COUNT - CAPTURE_COUNT = 0x102 - 0xFE = 0x04 In short, you do not need to worry about rollover. Now, if you do a double rollover, then you will have problems. As to atomic? Yes, the capturing of the system counter needs to be atomic in nature. Or at least, if you are using an 8-bit machine, and the counter is 32-bits, you need to make sure that the count value is correct at the time of capture. This is not so if you are using a 32-bit machine, where updates to 32-bits are generally atomic. The way to solve this problem may be as follows: 1. Disabling / re-enabling interrupts during capture ... (not so good) 2. Using a SWI (software interrupt) service to fetch the counter ... (better, but not all processors support this) 3. Capture and compare the system counter variable and use if the variable is table e.g. extern volatile unsigned long sysTickCounter; unsigned long my_captureTicks; do { my_captureTicks = sysTickCounter; } while (my_captureTicks != sysTickCounter); provided that the conditional test executes faster than sysTickCounter, then this capture / test should work.

    • "One could perhaps make the callback function pointer as an optional parameter: if it is NULL, the code will rely on polling, if it is set, it will be interrupt driven." Yes, I do this all the time. This is very similar to the "default argument" that one finds in C++. This is a very useful idea. As to nit-picking ... You are quite correct. The ISO behavior is undefined. I did the include path containing "h\includeFile.h" primarily to indicate to me that the file is to be found in the common header repository, that is local to a specific project. Again, laziness on my part. I keep forgetting where all the headers are, and invariably wind up looking in all the wrong places!

    • The danger of opaqueness in C is that there is no strict typesafe mechanisms in C as in C++. C is a bit more 'wild and wooly' when compared with the more formal C++ ... in my opinion, this gives C a more low-level feel to coding than C++. That is NOT to say that you cannot design tight C++ applications. Properly designed and written C++ constructs can and do consume few resources. C++, in my opinion, is a bit more rigorous, and safer to use in this respect.

    • As an extra note on opaqueness. Yes, I have used opaqueness on several of my C projects. Usually this is how I do it; (this appears to have met some acceptance, and not generated too many complaints). 1. Define a core enapsulation that has everything public and accesible. (this is NOT opaque) 2. Extend the core to another enapsulation by nesting the core inside the extended object, (class derivation) For example: //// parent class typedef struct GPTIMER { unsigned long lastCount; /* Last saved count for this timer */ unsigned long timeOut; /* Number of tics to timeout */ unsigned char timedOut; /* time-out status */ } GPTIMER; //// child class typedef struct XPTIMER { GPTIMER parent; /* define the parent here and make it the 1st record! */ int hold; /* when set, puts timer in hold mode */ unsigned long holdcount; /* hold dwell count to hold off this extended timer */ int alarmBit; /* some flag that is used to signal an alarm */ } XPTIMER; ///// now, on to the implementation of XPTIMER int XPTIMER_checkAlarmBit (GPTIMER *_this); /* check whether the alarm bit is set */ void XPTIMER_clearAlarmBit (GPTIMER *_this); /* clear the alarm bit */ void XPTIMER_setHoldCount (GPTIMER *_this, const unsigned long count); void XPTIMER_holdEnable (GPTIMER *_this, const int enable); void XPTIMER_update (GPTIMER *_this); /* update to refresh the alarm state */ As you can see here, the XPTIMER extensions are opaque to the user. The implementor of the XPTIMER encapsulation has hidden the details to the user / developer. Either it works properly, or it does not ... all without the risk of anyone 'fooling' around with the class extensions.