From: FreeRTOS info on

"John Devereux" <john(a)devereux.me.uk> wrote in message
news:878wfyxlay.fsf(a)devereux.me.uk...
> Vladimir Vassilevsky <nospam(a)nowhere.com> writes:
>
>> David Brown wrote:
>>
>>
>>> What I take issue with is when people get obsessive about globals
>>> and think that it is somehow better to have functions called
>>> "SetUartTimeout" and "GetUartTimeout",
>>
>> Yes it is better.
>>
>> * Perhaps it could be necessary to add flushing the UART before
>> changing timeouts. You just have to modify one function.
>>
>> * What if there is a need to have more then one uart? How about
>> accessing N uarts?
>>
>> * What if there is a need to access the timeouts from more then one
>> thread?
>>
>> * What if there is a name conflict due to the use of the global objects?
>>
>>> doing nothing but accessing a static variable, instead of just using
>>> a globally visible variable "uartTimeout".
>>
>> I do require all access to such variables via member functions. I like
>> an overloaded function UART.Timeout() instead of separate Set.. and
>> Get.. functions.
>
> How does that work, like:
>
> timeout = UART.Timeout(GET,UART1);
>
> ...
>
> UART.Timeout(SET,10000);


My assumption was he was meaning a more directly OO approach.

// Declare two UART objects
UART uart0( 0, 'n', 8, 1 ), uart2( 1, 'n', 8, 1 );

// Send to uart 0
uart0.send( "message to send" );

// Send to uart 1
uart1.send( "another message to send" );

--
Regards,
Richard.

+ http://www.FreeRTOS.org
Designed for Microcontrollers. More than 7000 downloads per month.

+ http://www.SafeRTOS.com
Certified by T�V as meeting the requirements for safety related systems

From: David Brown on
Vladimir Vassilevsky wrote:
>
>
> David Brown wrote:
>
>
>> What I take issue with is when people get obsessive about globals and
>> think that it is somehow better to have functions called
>> "SetUartTimeout" and "GetUartTimeout",
>
> Yes it is better.
>
> * Perhaps it could be necessary to add flushing the UART before changing
> timeouts. You just have to modify one function.
>

Then you've changed the API - your UartTimeout (variable or accessor
functions) are not doing what they were doing before. It's okay to
break existing code when you make significant changes to the API.

Since you are now actually doing something when setting uartTimeout, you
have to change the global variable to a function with a slightly
different name. You need to grep through your source code that uses the
uart, and modify that source code (or just attempt a rebuild - the
compiler will tell you where the problems lie).


> * What if there is a need to have more then one uart? How about
> accessing N uarts?
>

Again, that's a big change in the functionality of the module, and
requires a big change in the API.

> * What if there is a need to access the timeouts from more then one thread?
>

If you need a module that supports multiple threads reading and/or
writing the data, then you must take that into account. If that means
that accesses must be wrapped in locks, then you don't have a simple
read-write data item, and can't use a global.

Global data is not appropriate for all uses. But when you have a
clearly defined data item that can be safely read or written (according
to whatever restrictions you have documented in the module interface),
then wrapping the data in simple accessor functions is a waste of source
code, a waste of object code, and a waste of runtime, and gives exactly
zero benefits for modularisation, encapsulation, structure, clarity,
code maintenance, or any other buzz words you like.

> * What if there is a name conflict due to the use of the global objects?
>

Now you are getting silly. "uartTimeout" has no more or less a
potential for name conflicts than "SetUartTimeout" and "GetUartTimeout".
C works with a single global namespace - use appropriate naming
conventions for your global objects (variables, functions or whatever).
If your project is too big for that, try C++ and namespaces.

>> doing nothing but accessing a static variable, instead of just using a
>> globally visible variable "uartTimeout".
>
> I do require all access to such variables via member functions. I like
> an overloaded function UART.Timeout() instead of separate Set.. and
> Get.. functions.
>
>> The global must be part of the well-defined interface,
>
> Well defined interfaces exist only in the textbooks.
>

It's easy to give clear and safe interfaces for small modules.

>> not a backdoor into the module's interior, but there is absolutely no
>> reason to pretend that having the global variable is somehow "riskier"
>> or "unclear", or harder to use or change.
>
> As the project grow large, is gets much harder to maintain the code
> which is controlled by the global variables.
>

This is comp.arch.embedded - a great many of the projects here do not
grow "large" because they are for small systems. The code is small
enough that is not a big problem to keep track of modules and their
interfaces, and that includes global variables. On the other hand, the
waste of runtime and code space caused by unnecessary accessor functions
/can/ be significant.

For large projects, there are different balances - then there is much
more reason to avoid global variables. But it is still a minor detail -
finding a good way to specify your interfaces and keep your structure
clean is more important.


To take another example, suppose you have a module that collects samples
from somewhere and puts it in an array dataSamples[]. Should that only
be accessible through a function "int GetDataSample(int n)" ? That
would make a summation function very slow. Should you have a
"CopyDataSamples(int * dest, int n)" to let users have a local copy?
Again, it's slow, and a waste of data space. Perhaps just "const int *
AccessDataSamples(void)" to return a pointer to the data - it's fast,
but loses the compile-time checking you get with simple clear access to
the raw global data.


From: ChrisQ on
David Brown wrote:

>
> I agree 100% about encapsulation (at least, I agree about it as an ideal
> - sometimes you have to compromise in practice). What I take issue with
> is when people get obsessive about globals and think that it is somehow
> better to have functions called "SetUartTimeout" and "GetUartTimeout",
> doing nothing but accessing a static variable,

<...>

I guess you would take issue with a lot of my code then, because it uses
a lot of that type of construct to hide internals and there are no
globals other than const data at all in systems designed here. Within
modules, all vars and const data is declared static, so it doesn't get
exported to the linker. If you accept that all computing is just data
movement and processing, the interfaces between modules become the
defining nodes of system design.

A typical example might be timer pool support which needs only a system
interrupt tick timer call to function. The programming interface
consists of a group of functions to do stuff like request, cancel,
check, refresh timer etc and all you get back from or provide to the
interface is a U8 timer handle or a status. There is also a callback
facility on timeout, though this is only for short code sections as it
runs in interrupt context. The whole point of it is that it's a proven
library module that I never have to rewrite, can take it to any project,
compile it and it just works.

That's probably a simple and unfair example, as it's easy to fully
encapsulate, but the same process is used for ports, where a more or
less standard driver module abstracts the hardware into a port id and
bit which are defined for the project in a project_defs file. If fast
access is needed to a port, a special driver is written for that
function alone and all hardware references are again abstracted out as
far as possible.

The similar process is used for comms, which is usually built as an
upper and lower layer. Upper layer has the app call interface, lower
layer interrupt handler. The two are connected by queues in both
directions. At this level, a call interface structure contains all the
data and references for a uart and it's queues and this structure is
shared between the layers. In this way, the code becomes completely
reentrant and one set of upper level code and queue functions is shared
across all uarts. On some projects with 4 or more comms channels, this
save a lot of code space even though it's larger than it would normally
be for a single uart channel. Only the interrupt handlers are uart
specific and this is because it's more efficient in terms of interrupt
handler times.

A lot of the ideas for this came from classic os design and while you
might argue that it's inappropriate for small systems, it's surprising
how usefull it is at any level. There's quite a bit more effort up front
to start with, but the payback is not on this project but on the next
one and so on. You find that there are fewer bugs and a lot of stuff
works the first time because you think systems design, not programs. On
subsequent projects, you find that a lot of the code is reusable without
change and all you have to write is the application layer, or part of
it. Over time, you build up functionality to the point where you hardly
ever need to look at stuff like the standard c lib, (which has all the
wrong types anyway) and you thus have complete visibility of all the code...

Regards,

Chris
From: ChrisQ on
FreeRTOS info wrote:
>

> My assumption was he was meaning a more directly OO approach.
>
> // Declare two UART objects
> UART uart0( 0, 'n', 8, 1 ), uart2( 1, 'n', 8, 1 );
>
> // Send to uart 0
> uart0.send( "message to send" );
>
> // Send to uart 1
> uart1.send( "another message to send" );
>

Not quite that ideal as yet. The timer pool deals in timer objects with
handles, but the uart driver is not so ideal. At present, the
programming interface consists of a structure pointer containing
everything related to that uart, one item of which is a function code.
It's not ideal and needs to be developed further into a more oo call
interface.

The most recent project using this set of code had a 4 way rs485 link,
with custom protocol, so there are more layers on top of the basic
driver to handle line turnaround (port driver), protocol deframing and
ack / nack or data responses. The gory structure details become hidden
by these. There's also an aux port module used for terminal interface
layered on top of the uart driver which provides putchar, getchar,
string io and conversion functions. it's called curses.c, as a nod
elsewhere :-). There's no rtos, just a simple state machine and multiple
interrupt sources to schedule everything.

It oo stuff needs more development, but clients don't pay you for this
sort of thing and it has to be done incrementally as time allows. I
guess the aim is to have a universal embedded function library,
eventually. The code may not be quite as efficient as individual hand
coded stuff, but could be very beneficial in many other ways...

Regards,

Chris
From: David Brown on
ChrisQ wrote:
> David Brown wrote:
>
>>
>> I agree 100% about encapsulation (at least, I agree about it as an
>> ideal - sometimes you have to compromise in practice). What I take
>> issue with is when people get obsessive about globals and think that
>> it is somehow better to have functions called "SetUartTimeout" and
>> "GetUartTimeout", doing nothing but accessing a static variable,
>
> <...>
>
> I guess you would take issue with a lot of my code then, because it uses

As I said (paraphrased) in another post, if you have a development
method that works better for you to produce clear, maintainable and
efficient code, then that trumps any individual rules or recommendations.

> a lot of that type of construct to hide internals and there are no
> globals other than const data at all in systems designed here. Within
> modules, all vars and const data is declared static, so it doesn't get
> exported to the linker. If you accept that all computing is just data
> movement and processing, the interfaces between modules become the
> defining nodes of system design.
>
> A typical example might be timer pool support which needs only a system
> interrupt tick timer call to function. The programming interface
> consists of a group of functions to do stuff like request, cancel,
> check, refresh timer etc and all you get back from or provide to the
> interface is a U8 timer handle or a status. There is also a callback
> facility on timeout, though this is only for short code sections as it
> runs in interrupt context. The whole point of it is that it's a proven
> library module that I never have to rewrite, can take it to any project,
> compile it and it just works.
>
> That's probably a simple and unfair example, as it's easy to fully
> encapsulate, but the same process is used for ports, where a more or
> less standard driver module abstracts the hardware into a port id and
> bit which are defined for the project in a project_defs file. If fast
> access is needed to a port, a special driver is written for that
> function alone and all hardware references are again abstracted out as
> far as possible.
>

What you have here is a typical trade-off between writing re-usable code
and writing specific code. The re-usable code takes longer to develop
and test the first time, but will save overall if it is used on many
projects. But it comes with a run-time and code space cost.

> The similar process is used for comms, which is usually built as an
> upper and lower layer. Upper layer has the app call interface, lower
> layer interrupt handler. The two are connected by queues in both
> directions. At this level, a call interface structure contains all the
> data and references for a uart and it's queues and this structure is
> shared between the layers. In this way, the code becomes completely
> reentrant and one set of upper level code and queue functions is shared
> across all uarts. On some projects with 4 or more comms channels, this
> save a lot of code space even though it's larger than it would normally
> be for a single uart channel. Only the interrupt handlers are uart
> specific and this is because it's more efficient in terms of interrupt
> handler times.
>
> A lot of the ideas for this came from classic os design and while you
> might argue that it's inappropriate for small systems, it's surprising
> how usefull it is at any level. There's quite a bit more effort up front
> to start with, but the payback is not on this project but on the next
> one and so on. You find that there are fewer bugs and a lot of stuff
> works the first time because you think systems design, not programs. On
> subsequent projects, you find that a lot of the code is reusable without
> change and all you have to write is the application layer, or part of
> it. Over time, you build up functionality to the point where you hardly
> ever need to look at stuff like the standard c lib, (which has all the
> wrong types anyway) and you thus have complete visibility of all the
> code...
>

This all sounds like a good way to produce reusable libraries of code.
But there is absolutely nothing here to suggest that global data is a
problem. If I understand you correctly, you've just hidden it within
your "call interface structures". The effect is really just a matter
of making your access to global data a little more formalised and
consistent, as well as tidying the data inside neat structs rather than
in a loser pile. Application code has access to these structs - it
#include's headers that define the structs, and it has instantiations of
them. It can therefore access the data directly if it wants.