Jermone, See some suggestions below. Brendan --- In lpc2000@yahoogroups.com, jk jlkj <njad2002@...> wrote: > > Hi Firends, > > The other day i was reading a message in this group, about writing code which does not use any of the compiler specific extended keywords like __arm, __nested, __irq etc. The main point about any of these extensions is that they are compiler and/or system specific. This means if you ever have to change environments (i.e. either compiler or target) you almost certainly have to change them. This (a) generates extra work and (b) introduces scope for new bugs to be introduced and (c) adds to ongoing maintenance task, as two (or more) versions must be maintained. None of this is an issue if all you're doing is something quick and dirty. A second issue with compiler extensions is that they tend to be the area where most compiler's have problems/bugs. > Does any one have any sample code or any documentation or articles on how this can be done. I'm not aware of any: it's an issue that tends to be driven more by practical experience. I'd be very interested in seeing some though. > Because, i think that this is an important step towards writing code that is not compiler specific and would compile with very little or no changes between compilers. It is perfectly possible to achieve on processors such as ARM etc. (next to impossible though on very low-end 8-bit micros such as PICs etc., where there are more extensions and restrictions than compatibility to standard 'C'). The techniques we use include: - As a starting point for 'C' code: stick to standard 'C'. Don't use any extensions such as special keywords, pragmas, in-line assembler etc., if you can avoid them (which you almost certainly can) - When accessing hardware, you can do it from 'C', but make sure you don't use non-portable features such as bit-fields. For a read or write to a 32-bit register you can type cast the hardware address to a "volatile int *" (or better yet define a type in a master include file with something like "uint32" as an unsigned 32-bit integer) - We don't use any standard libraries (printf and the like), preferring to write our own. This is more to simplify maintenance than anything else - we use very few such functions. It avoids having to find and/or port libraries for multiple platforms. - You will find that some things just can't be done from 'C'. Our preference is to code these in assembler in separate source files, as it eases maintenance. > > I think that such code would definitely require a little bit of assembly language. > > What i would like to know and do is > a. List down all the compiler specfic instructions which are very commonly used. > b. Write code which would replace these compiler specific intructions. > > Well the (a) part of my job seems to be easier, so i am listing down the commonly used IAR ewarm compiler specific instructions here . > > __irq, __fiq, __arm, __thumb, __nested, __swi > > For the (b) part of my question i would need some serious help from some of the experts in this group. By help i do not expect any one to give me the entire code. All i need is some guidance and hints, i will try and compile the code. However, if some one has already done this exercise, then please share it with us. For the LPC, the only assembler we have is as follows. All other code is standard 'C', including all low-level device drivers. As a matter of good practice, we code the hardware-specific parts of the device drivers to be as small as possible, and separate from the main body of the code, using well defined APIs. - Vector table and startup code. The startup code in our case initializes the stack pointers, sets the mode to supervisor with interrupts off and jumps to 'C'. I believe I posted a version of this a while ago here. You can zero out the uninitialized data and copy in the initialized data as part of this: equally, you can do this from `C' (though do it near the start, obviously). - IRQ interrupt dispatch, that enables nested interrupts. There were a couple of examples of this posted here recently. This can be written so that the main body of the interrupt handler can be a standard `C' function (no need for special keywords). - A few miscellaneous functions: a pair of functions to disable and re-enable interrupts, and maybe one other to enable them in the first place (called at the end of the initialization code). We don't use software interrupts. Whether a source file is compiled as ARM or Thumb mode can be controlled from the build environment (either part of an IDE or makefile): the actual code can be agnostic as to how it's compiled. Using this approach, we have applications that take up maybe 100kbytes of code space, all of it standard `C' except for a handful of assembler functions. The main body of code gets compiled with five different compilers on about six or seven distinct platforms, without any changes. Moving to a new compiler takes a couple of days at worst (to generate build system for it), a couple of hours at best. Moving to a new platform takes a couple of weeks to code up the platform specific stuff. A few other points I'd make: Although we have a particular requirement for portability, we have found that even if we didn't, these techniques have advantages, in terms of training (by using standard features only, there's less to learn), code quality (no reliance on frequently poorly documented features, avoidance of bug-prone compiler features), maintenance (easier to understand something that's standardized), flexibility (not tied into a particular compiler vendor) etc. Even if you don't think portability is an issue for you today, changing requirements will often make it an issue for you. I tried to make this point recently in an exchange on in-line assembler, and failed. Having said all of the above, there will be occasions where it's just handy to use a compiler extension (for example, where some feature just isn't available otherwise: someone gave an example of accessing special DSP instructions on a DSP recently). Finally, all this is based on our own experience: clearly there are alternative approaches. I'm not really interested in debating the merits of this or any alternative approach to death: simply to present a number of well-known techniques that I have found very useful and effective, and hope that others can learn from our experience. I hope you find the above of some use. Brendan P.S. apologies for not providing direct references to code examples, but the search facility on this site is woeful, and I'm out of time. > > Regards, > Jerome
Message
Re: Compiller neutral code
2006-04-18 by brendanmurphy37
Attachments
- No local attachments were found for this message.