Reply by Chris Hills February 2, 20072007-02-02
In article <45C33455.7887F4C3@yahoo.com>, CBFalconer 
<cbfalconer@yahoo.com> writes
>Chris Hills wrote: >> There are many dialects of C Most break the rules somewhere. By >> your definition there are only , I think, 6 C compilers world >> wide but they only could for a minute fraction of the "c" >> programming in the world. The vast majority do not fully implement >> ISO 9899:1999 but rather something between C95 and C99 *with >> extensions* > >Then it isn't a C compiler, by definition.
This sort of stupidity is prevalent on comp.lang.c but thankfully not on the standards panels. I am surprised to see in an embedded NG. By your definition there are only 6 C compilers and non of them in the embedded area. -- \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ \/\/\/\/\ Chris Hills Staffs England /\/\/\/\/ /\/\/ chris@phaedsys.org www.phaedsys.org \/\/\ \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
Reply by CBFalconer February 2, 20072007-02-02
Chris Hills wrote:
> Mark L Pappin <mlp@acm.org> writes >> Chris Hills <chris@phaedsys.org> writes: >>> Paul Keinanen <keinanen@sci.fi> writes >>>
... snip ...
>>> >>>> If this is supposed to be standard C, then int can not be 8 bits. >>> >>> No, this is for an embedded MCU so it can be 8 bits. >> >> Not if you want to call the language C. >> You can call it "C-like" if you want, > > You are being a pedant and pointless. > >> but for the last 17 years there >> has been an international standard defining the language called C > > I know I have been on that panel for about a decade.
Then you should know better. I suspect you are largely ignored.
> >> and one of its most fundamental features is that the type 'int' >> can hold all values between 32767 and -32767 inclusive. > > This is not correct. Type in should be at least 16 bits. Ints can > legally be any size above 16 bits. There are systems with 64 bit ints.
All of which can hold values between 32767 and -32767 as he said.
> > Also an int can be signed or unsigned. An unsigned int does not hold > negative values... > > Of course both signed and unsigned char are integer types though a > char does not have to be 8 bits. Hence the communications industry > having the type "octet" which we have suggested as a standard type > on more than one occasion.
unsigned ints are not ints. They are a different type and follow different rules, such as the use of modulo arithmetic. Which doesn't affect the statement about ints.
> >> A language with a type >> 'int' that can not hold at least this range can not be called C. > > As I said you are a pedant and pointless. The difference between > theory and practice.... > > There are many dialects of C Most break the rules somewhere. By > your definition there are only , I think, 6 C compilers world > wide but they only could for a minute fraction of the "c" > programming in the world. The vast majority do not fully implement > ISO 9899:1999 but rather something between C95 and C99 *with > extensions*
Then it isn't a C compiler, by definition. It may still be useful. The point of a standard is to allow confidence that source code will work on any system that is standards compliant. Use of extensions should be limited to clearly identified modules. -- <http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt> "A man who is right every time is not likely to do very much." -- Francis Crick, co-discover of DNA "There is nothing more amazing than stupidity in action." -- Thomas Matthews
Reply by Chris Hills February 2, 20072007-02-02
In article <m3ireledq6.fsf@Claudio.Messina>, Mark L Pappin <mlp@acm.org> 
writes
>Chris Hills <chris@phaedsys.org> writes: > >> Paul Keinanen <keinanen@sci.fi> writes >>> "Gary Pace" <xxx@yyy> wrote: >>>> - i is signed, int may be 8,16,32 (maybe 64?) bits in size >>> If this is supposed to be standard C, then int can not be 8 bits. > >> No, this is for an embedded MCU so it can be 8 bits. > >Not if you want to call the language C. >You can call it "C-like" if you want,
You are being a pedant and pointless.
> but for the last 17 years there >has been an international standard defining the language called C
I know I have been on that panel for about a decade.
>and >one of its most fundamental features is that the type 'int' can hold >all values between 32767 and -32767 inclusive.
This is not correct. Type in should be at least 16 bits. Ints can legally be any size above 16 bits. There are systems with 64 bit ints. Also an int can be signed or unsigned. An unsigned int does not hold negative values... Of course both signed and unsigned char are integer types though a char does not have to be 8 bits. Hence the communications industry having the type "octet" which we have suggested as a standard type on more than one occasion.
>A language with a type >'int' that can not hold at least this range can not be called C.
As I said you are a pedant and pointless. The difference between theory and practice.... There are many dialects of C Most break the rules somewhere. By your definition there are only , I think, 6 C compilers world wide but they only could for a minute fraction of the "c" programming in the world. The vast majority do not fully implement ISO 9899:1999 but rather something between C95 and C99 *with extensions* There are some compilers that are as compliant as most of the other c compilers out there that for reasons of hardware architecture and efficiency my have 8 bit ints. It is not common but I would not stop them being called C compilers for just that reason alone.
>The C standard _does_ allow for various extensions, and makes the >distinction between "freestanding" and "hosted" implementations (most >embedded platforms will be the former, which for instance doesn't need >to provide all or even any of the standard library) but reducing the >range of _the_ basic type in this way is just not on. >mlp
As I said all "c" compilers have extensions and restrictions on ISO9899:1999. I think only 6 fully implement the standard, all the common ones don't, ALL of the C compilers have extensions. C is like English, rarely ever used in it's pure form. -- \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ \/\/\/\/\ Chris Hills Staffs England /\/\/\/\/ /\/\/ chris@phaedsys.org www.phaedsys.org \/\/\ \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
Reply by February 1, 20072007-02-01
Chris Hills <chris@phaedsys.org> writes:

> Paul Keinanen <keinanen@sci.fi> writes >> "Gary Pace" <xxx@yyy> wrote: >>> - i is signed, int may be 8,16,32 (maybe 64?) bits in size >> If this is supposed to be standard C, then int can not be 8 bits.
> No, this is for an embedded MCU so it can be 8 bits.
Not if you want to call the language C. You can call it "C-like" if you want, but for the last 17 years there has been an international standard defining the language called C and one of its most fundamental features is that the type 'int' can hold all values between 32767 and -32767 inclusive. A language with a type 'int' that can not hold at least this range can not be called C. The C standard _does_ allow for various extensions, and makes the distinction between "freestanding" and "hosted" implementations (most embedded platforms will be the former, which for instance doesn't need to provide all or even any of the standard library) but reducing the range of _the_ basic type in this way is just not on. mlp
Reply by Chris Hills January 26, 20072007-01-26
In article <dngjr29j577keg3m5r01n4vv3mn4nap5ak@4ax.com>, Paul Keinanen 
<keinanen@sci.fi> writes
>On Thu, 25 Jan 2007 23:07:25 -0600, "Gary Pace" <xxx@yyy> wrote: > >> >>"joshc" <josh.curtz@gmail.com> wrote in message >>news:1169696689.897046.166960@l53g2000cwa.googlegroups.com... > >>> int iterative_factorial(int i) { >>> int f; >>> f = 1; >>> >>> while (i != 0) { >>> f = i * f; >>> i--; >>> } >>> return(f); >>> } >>> > >This function can not be a stand-alone ISR (with register save >preamble), since ISRs do not in general have input parameters or >return any function results, so apparently this example function is >called from some higher level interrupt service code. > >>As written the function is "unsafe" in many contexts within an embedded app >>(particularly so in an ISR where "get in and out quickly" is often important >>to maintain system timing) : >>- i is signed, int may be 8,16,32 (maybe 64?) bits in size > >If this is supposed to be standard C, then int can not be 8 bits.
No, this is for an embedded MCU so it can be 8 bits. Incidentally both signed and unsigned char are integer types. However the standard says an int is not less than 16 bits so the chars are usually used.
>Someone pointed out that the ISR could execute for a very long time. >However, in this case this would not be a critical thing for legal >values.
That is legal for that compiler on that target. ISO C has little relevance here.
>Floating point instructions should be avoided even if the instruction >set implements these instructions, since saving and restoring the >floating point control/status and actual data registers would take a >huge time.
That's true. However there is no reason to use floats in this function. Which instruction set do you mean? The compiler or the hardware? Some MCU have FPU most compilers have FP libs that either dit it internally or use the HW WFU
>While the 8087 style floating point processor (used in most x86
>On later Pentium models, the FPU stack is used as MMX data registers
The only relevant Intel part here is likely to be the 386 -- \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ \/\/\/\/\ Chris Hills Staffs England /\/\/\/\/ /\/\/ chris@phaedsys.org www.phaedsys.org \/\/\ \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
Reply by Chris Hills January 26, 20072007-01-26
In article <1169696689.897046.166960@l53g2000cwa.googlegroups.com>, 
joshc <josh.curtz@gmail.com> writes
>So during an interview for an embedded software position, I was asked >to write any function I wanted in C. I chose an iterative factorial >function like this: > >int iterative_factorial(int i) { > int f; > f = 1; > > while (i != 0) { > f = i * f; > i--; > } > return(f); >} > >I was then asked what I would have to worry about or fix to make the >function safe to use in an ISR. I really could not think of anything >wrong with this function as it seems reentrant and I don't see any >concurrency issues. Can anyone think of anything that might make this >function unsafe to use in an ISR?
The answers depend largely on the target architecture and the specific compiler you are using. -- \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ \/\/\/\/\ Chris Hills Staffs England /\/\/\/\/ /\/\/ chris@phaedsys.org www.phaedsys.org \/\/\ \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
Reply by Paul Keinanen January 26, 20072007-01-26
On Fri, 26 Jan 2007 03:08:30 -0800, David R Brooks
<davebXXX@iinet.net.au> wrote:

>Paul Keinanen wrote: >[snip] >> >> However, multiplications and divisions should be avoided in ISRs, >> especially if these are implemented in software or implemented as >> microcode with execution times several times larger than ordinary >> instructions. >> >> Floating point instructions should be avoided even if the instruction >> set implements these instructions, since saving and restoring the >> floating point control/status and actual data registers would take a >> huge time. >> >> While the 8087 style floating point processor (used in most x86 >> processors) contains an internal stack for internal values, this is >> practically useless for ISRs, since it contains only 8 slots and could >> be used to 7-8 slots already when the ISR occurs, so executing >> floating point operations in the ISR without first saving the stack >> could easily overflow the stack. >> >> On later Pentium models, the FPU stack is used as MMX data registers >> and the processor might be in MMX mode when the interrupt occurs, >> switching it to floating point mode in the ISR takes a very long time >> as well as restoring the MMX state after the interrupt execution. >> >These points are valid enough for X86 architectures. However the OP >specified an "embedded" application, so it is unlikely a Pentium would >be used (it might be, of course :)
There is a quite large number of small form factor processor boards using mobile Pentiums from Intel. There are other processors from other manufacturers running Pentium code (of course these processors can not be called Pentium due to trade mark reasons) that fit into the PC/104 board. These small boards are used frequently in various embedded applications. IMHO, the greatest problem in using x86 processors in embedded applications is the short production run, typically 1-2 years, while some products using embedded processors may be produced for years and may require support for 10-20 years.
>Many other CPUs have multiply and FP instructions that act directly on >the CPU registers, so there would be no inherent bar to using them in >interrupts. Of course, one would want to check the specs for just how >long they take.
Apart from bandwidth issues (e.g. double requires two 32 bit registers), one should also check the control register issues, for instance the rounding/truncate bit found in many processors. Are such bits readable from the hardware registers before modifying them ? Paul
Reply by January 26, 20072007-01-26
On Friday, in article
     <dngjr29j577keg3m5r01n4vv3mn4nap5ak@4ax.com> keinanen@sci.fi
     "Paul Keinanen" wrote:
>On Thu, 25 Jan 2007 23:07:25 -0600, "Gary Pace" <xxx@yyy> wrote: > >> >>"joshc" <josh.curtz@gmail.com> wrote in message >>news:1169696689.897046.166960@l53g2000cwa.googlegroups.com... > >>> int iterative_factorial(int i) { >>> int f; >>> f = 1; >>> >>> while (i != 0) { >>> f = i * f; >>> i--; >>> } >>> return(f); >>> } >>> > >This function can not be a stand-alone ISR (with register save >preamble), since ISRs do not in general have input parameters or >return any function results, so apparently this example function is >called from some higher level interrupt service code. > >>As written the function is "unsafe" in many contexts within an embedded app >>(particularly so in an ISR where "get in and out quickly" is often important >>to maintain system timing) : >>- i is signed, int may be 8,16,32 (maybe 64?) bits in size > >If this is supposed to be standard C, then int can not be 8 bits. > >Someone pointed out that the ISR could execute for a very long time. >However, in this case this would not be a critical thing for legal >values. > > 7! = 0x13B0 Legal 16 bit signed int > 8! = 0x9D80 Legal 16 bit only as unsigned > 9! = 0x58980 Does not fit into 16 bit > >12! = 0x1C8CFC00 Legal 32 bit signed int >13! = 0x17328CC00 Does not fit into 32 bits > >So for 16 bit int, at most 7 iterations would have to be performed, >while the result f fits into int and with 32 bit int, 12 iterations >are required and with 64 bit int, 20 iterations would be performed at >most. > >However, multiplications and divisions should be avoided in ISRs, >especially if these are implemented in software or implemented as >microcode with execution times several times larger than ordinary >instructions.
Well if this is to be a function returning int of 8,16,32 or even 64bits the SAFEST method is Lookup table as there are not that many values with -1, or all ones (signed/unsigned) as return value for out of range. Why bother computing an integer value that has a limited range of results everytime, for that matter it could easily be a global table in READ ONLY space on a true embedded system, depending on how many times called and if the input range is limited and checked ALWAYS elsewhere. Assuming you are not trying to do factorials of negative numbers... the function basically becomes - int iterative_factorial(int i) { return ( (i<0 &#4294967295;&#4294967295; i>MAX_INDEX) ? 0xFFFF : factorial_table[i]); } Even with 13 or more entries in the lookup table the code size will be smaller, the footprint of calls will be smaller, the execution time will be faster and deterministic. -- Paul Carpenter | paul@pcserviceselectronics.co.uk <http://www.pcserviceselectronics.co.uk/> PC Services <http://www.gnuh8.org.uk/> GNU H8 & mailing list info <http://www.badweb.org.uk/> For those web sites you hate
Reply by David R Brooks January 26, 20072007-01-26
Paul Keinanen wrote:
[snip]
> > However, multiplications and divisions should be avoided in ISRs, > especially if these are implemented in software or implemented as > microcode with execution times several times larger than ordinary > instructions. > > Floating point instructions should be avoided even if the instruction > set implements these instructions, since saving and restoring the > floating point control/status and actual data registers would take a > huge time. > > While the 8087 style floating point processor (used in most x86 > processors) contains an internal stack for internal values, this is > practically useless for ISRs, since it contains only 8 slots and could > be used to 7-8 slots already when the ISR occurs, so executing > floating point operations in the ISR without first saving the stack > could easily overflow the stack. > > On later Pentium models, the FPU stack is used as MMX data registers > and the processor might be in MMX mode when the interrupt occurs, > switching it to floating point mode in the ISR takes a very long time > as well as restoring the MMX state after the interrupt execution. >
These points are valid enough for X86 architectures. However the OP specified an "embedded" application, so it is unlikely a Pentium would be used (it might be, of course :) Many other CPUs have multiply and FP instructions that act directly on the CPU registers, so there would be no inherent bar to using them in interrupts. Of course, one would want to check the specs for just how long they take.
Reply by Paul Keinanen January 26, 20072007-01-26
On Thu, 25 Jan 2007 23:07:25 -0600, "Gary Pace" <xxx@yyy> wrote:

> >"joshc" <josh.curtz@gmail.com> wrote in message >news:1169696689.897046.166960@l53g2000cwa.googlegroups.com...
>> int iterative_factorial(int i) { >> int f; >> f = 1; >> >> while (i != 0) { >> f = i * f; >> i--; >> } >> return(f); >> } >>
This function can not be a stand-alone ISR (with register save preamble), since ISRs do not in general have input parameters or return any function results, so apparently this example function is called from some higher level interrupt service code.
>As written the function is "unsafe" in many contexts within an embedded app >(particularly so in an ISR where "get in and out quickly" is often important >to maintain system timing) : >- i is signed, int may be 8,16,32 (maybe 64?) bits in size
If this is supposed to be standard C, then int can not be 8 bits. Someone pointed out that the ISR could execute for a very long time. However, in this case this would not be a critical thing for legal values. 7! = 0x13B0 Legal 16 bit signed int 8! = 0x9D80 Legal 16 bit only as unsigned 9! = 0x58980 Does not fit into 16 bit 12! = 0x1C8CFC00 Legal 32 bit signed int 13! = 0x17328CC00 Does not fit into 32 bits So for 16 bit int, at most 7 iterations would have to be performed, while the result f fits into int and with 32 bit int, 12 iterations are required and with 64 bit int, 20 iterations would be performed at most. However, multiplications and divisions should be avoided in ISRs, especially if these are implemented in software or implemented as microcode with execution times several times larger than ordinary instructions. Floating point instructions should be avoided even if the instruction set implements these instructions, since saving and restoring the floating point control/status and actual data registers would take a huge time. While the 8087 style floating point processor (used in most x86 processors) contains an internal stack for internal values, this is practically useless for ISRs, since it contains only 8 slots and could be used to 7-8 slots already when the ISR occurs, so executing floating point operations in the ISR without first saving the stack could easily overflow the stack. On later Pentium models, the FPU stack is used as MMX data registers and the processor might be in MMX mode when the interrupt occurs, switching it to floating point mode in the ISR takes a very long time as well as restoring the MMX state after the interrupt execution. Paul