> OTOH, the other way you described requires you to compile
> EVERY different version of EVERY UART routine. =A0E.g.,
> RS232_Receive, RS485_Receive, RS232_Transmit, RS485_Transmit,
> RS232_Initialize, RS485_Initialize, etc. =A0You woul dput ALL of
> these into a library (or libraries). =A0
You mean create multiple object files UART.obj, UART_RS485.obj,
UART_RS232.obj, etc from
single UART.c file and merge all of them into single lib file??
>Then, conditionally
> bind one of them to UART_Receive, another to UART_Transmit, etc.
> In that way, only one of the will be extracted from the library
> instead of "all flavors".
Please explain the procedure in detail. I don't know how to do it??
Kishore.
Reply by D Yuniskis●December 27, 20102010-12-27
On 12/27/2010 1:43 AM, kishor wrote:
> I agree you.
>
> But I am expecting some solution from you..
>
> Or instead of making .lib file should I keep using C file ???
Whether you use a C module or compile the routines into a
library is entirely up to you.
If you do it the way I suggested, you will have *one*
function for each UART action (transmit, receive, initialize,
etc.). You can chose to put these into a library if you
want. But, I suspect you will always be using *all*
of them (i.e., will you ever build a system that only
transmits and never receives? If so, then you would want
to be able to include the transmit function and NOT the
receive function. If they are in a library, then the
linker will only drag the transmit function into your
final executable if the receive is never referenced.)
If all of the functions will be used, then they can all reside in
a single C module (source file).
OTOH, the other way you described requires you to compile
EVERY different version of EVERY UART routine. E.g.,
RS232_Receive, RS485_Receive, RS232_Transmit, RS485_Transmit,
RS232_Initialize, RS485_Initialize, etc. You woul dput ALL of
these into a library (or libraries). Then, conditionally
bind one of them to UART_Receive, another to UART_Transmit, etc.
In that way, only one of the will be extracted from the library
instead of "all flavors".
Figure out how to best *write* the code (so it is understandable,
etc.). Then, figure out how to *link* it. Don't let linkage
issues govern how you *write* the code.
[standard disclaimers apply, YMMV, do not bend/fold/mutilate]
Reply by kishor●December 27, 20102010-12-27
I agree you.
But I am expecting some solution from you..
Or instead of making .lib file should I keep using C file ???
Thanks,
Kishore
Reply by D Yuniskis●December 27, 20102010-12-27
On 12/27/2010 12:04 AM, kishor wrote:
> Hi D Yuniskis,
>
> My approach to conditional code is to enable optional extra features.
>
> In case of UART features are RS485, Hardware flow control for RS232,
> etc
>
> for RS485 mode before transmitting, I need to enable the RS485
> transmit pin.
> In flow control before transmitting the data I check the CTS status.
>
> These features are deeply embedded in Serial.c.
Doesn't matter. You should look at how code that tries to
run on various platforms is written (hint: lots of #ifdef's).
The risk you run in selecting from a set of individual routines
is that any change that you later discover must be applied to
*all* of them runs the risk of:
- being incorrectly applied to *one* of them
- being hard to shoehorn in because you opted for a
different code structure in some of them
For example:
void
TxIntService()
{
/* get here when transmitter needs service */
...
/* Tx is ready for another character */
do {
/* check Tx output FIFO for data available */
if (OK != FifoStatus(TxFIFO)) {
/* shut down Tx interrupt; system will reenable
* when it decides there is something else to XMIT
*/
TxIRQ = NULL; /* yada yada yada */
break; /* yes, we have no bananas */
}
/* get character from Tx output FIFO/mbuf */
c = FifoRead(TxFIFO);
#ifdef RS232
/* examine CTS input to determine if we *can* send */
if (!CTS)
break;
#endif
#ifdef RS485
/* turn on EIA485 buffer */
BufferControl(ON);
#endif
SendCharacter(c);
} while (0); /* once around the block, Sigfried */
/* cleanup */
}
This (bogus) code fragment is intended to show that
you *probably* have a lot in common between the different
serial port configurations and how they perform specific
actions (e.g., checkiing if there is data available,
getting the next character to transmit; shutting down
the transmit IRQ when the last character has been sent;
taking / releasing mutexes, etc). If you break the
routine into N different versions, you run the risk of
forgetting one of these activities -- or, implementing
it "differently/incorrectly" -- in one or more of them.
Taken to its logical extreme, would you write N different
*programs* for your N different product configurations,
put them all into one big file and then #ifdef around
each "configuration specific section"?
> And the work around for this situation is,
>
> Writing separate functions for each features implemented with same
> function name.
> Linker will select the correct function depending on #define in header
> file.
Reply by kishor●December 27, 20102010-12-27
Hi D Yuniskis,
My approach to conditional code is to enable optional extra features.
In case of UART features are RS485, Hardware flow control for RS232,
etc
for RS485 mode before transmitting, I need to enable the RS485
transmit pin.
In flow control before transmitting the data I check the CTS status.
These features are deeply embedded in Serial.c.
And the work around for this situation is,
Writing separate functions for each features implemented with same
function name.
Linker will select the correct function depending on #define in header
file.
Kishore.
Reply by D Yuniskis●December 24, 20102010-12-24
Hi Frank,
On 12/24/2010 1:41 AM, Frank Buss wrote:
> D Yuniskis wrote:
>
>> What's to "work around"? You can either #define the symbols
>> referenced -- or not. An examination of the code (and commentary)
>> should provide hints as to what you would *like* those symbols
>> to be...
>>
>> Beyond that, there is no impact on library generation, etc.
>
> I guess he means something like different defines for different IO
> registers, depending on which CPU he is using and other things like this.
Perhaps. The question seemed unclear, to me.
("Why is there air?")
> One idea would be to refactor it, so that all #ifdefs are in the header
> files, only, and don't affect the compilation of the library. Maybe
> something like this:
>
> In the C file:
>
> static void commonUartInit()
> {
> ....
> }
>
> void initUart_at9g20()
> {
> commonUartInit();
> ....
> }
>
> void initUart_stm32()
> {
> commonUartInit();
> ....
> }
>
> In the header file:
>
> #if defined(AT9G20)
> #define initUart initUart_at9g20
> #elif defined(STM32)
> #define initUart initUart_stm32
> #else
> #error "unsupported CPU"
> #endif
... and then remembering that "initUart" is where you
(presumably) want to be.
But, you're still dealing with preprocessor directives
(#if defined() being #ifdef in an alternate form)
I think this approach would (if consistently applied)
result in more "littered" code (than burying the conditionals
within routines).
E.g., any function that talks to the UART at the hardware
level needs to be treated like this (if you are being
consistent) -- instead of folding all those issues into
one routine "conditionally".
The *advantage* this (your) approach has is that you can
write initWHATEVER() without concern for WHATEVERELSE.
OTOH, chances are that WHATEVER and WHATEVERELSE will
have similar requirements/structure.
[this *wouldn't* be the case if, for example, you were
writing "initUserInterfaceDevice()" and mapped that to
"initUART" vs. "initCRT"! In that case, there would be very
little "similar structure" to exploit and forcing all
that code into a single routine would leave you with a mess]
> Then the linker takes care that the used functions only are linked to the
> program, to keep it compact. If you have more resources, and e.g. C++ and
> templates, you could do it more general, without all the macro kludge.
This means you have to make sure the function is part of a *library*
and not a "module" (lest the rest of the module get dragged in
as well)
Reply by Frank Buss●December 24, 20102010-12-24
kishor wrote:
> Thanks for quick reply,
>
> I got the point.
> Instead of using #ifdef in function I should create two different
> functions.
> So the linker will select the functions depending on #define in
> header file.
Yes. But for small microcontroller projects, compile time doesn't matter
and if you have the source of the library, maybe just add the source code
to your projects, then you don't need to change anything. The source code
of your libraries can still be located in different directories.
But using libraries helps to separate the project in modules and makes it
more difficult to apply quick project specific hacks inside the library :-)
Another idea is to do copy-and-paste reuse. The advantage is that older
projects still works, even if you change some common used parts of the
code. This is what works best for me. Maybe doesn't work so good, if there
is more than a few programmers working on multiple projects.
--
Frank Buss, http://www.frank-buss.de
piano and more: http://www.youtube.com/user/frankbuss
Reply by kishor●December 24, 20102010-12-24
Thanks for quick reply,
I got the point.
Instead of using #ifdef in function I should create two different
functions.
So the linker will select the functions depending on #define in
header file.
Thanks,
Kishore.
Reply by Frank Buss●December 24, 20102010-12-24
D Yuniskis wrote:
> What's to "work around"? You can either #define the symbols
> referenced -- or not. An examination of the code (and commentary)
> should provide hints as to what you would *like* those symbols
> to be...
>
> Beyond that, there is no impact on library generation, etc.
I guess he means something like different defines for different IO
registers, depending on which CPU he is using and other things like this.
One idea would be to refactor it, so that all #ifdefs are in the header
files, only, and don't affect the compilation of the library. Maybe
something like this:
In the C file:
static void commonUartInit()
{
...
}
void initUart_at9g20()
{
commonUartInit();
...
}
void initUart_stm32()
{
commonUartInit();
...
}
In the header file:
#if defined(AT9G20)
#define initUart initUart_at9g20
#elif defined(STM32)
#define initUart initUart_stm32
#else
#error "unsupported CPU"
#endif
Then the linker takes care that the used functions only are linked to the
program, to keep it compact. If you have more resources, and e.g. C++ and
templates, you could do it more general, without all the macro kludge.
--
Frank Buss, http://www.frank-buss.de
piano and more: http://www.youtube.com/user/frankbuss
Reply by D Yuniskis●December 24, 20102010-12-24
On 12/24/2010 1:01 AM, kishor wrote:
> Hi friends,
>
> I have some C Source file such as Serial.c, Modbus.c, Ring_Buffer.c
> My aim is to create a .lib file in Keil uv4 for Cortex m3.
>
> Some function contains the #ifdef type conditional code's.
> How to deal with this?
>
> Please suggest any work around..
What's to "work around"? You can either #define the symbols
referenced -- or not. An examination of the code (and commentary)
should provide hints as to what you would *like* those symbols
to be...
Beyond that, there is no impact on library generation, etc.