[riot-devel] About function pointers

2015-02-18 Thread Oleg Hahm
Dear remodeling IoTlers!

Ludwig just made me aware that Joakim's PR for NVRAM [1] introduces function
pointers as part of the device driver struct. This made me remember that there
were already similar function pointers introduced as part of netdev.

As I was always opposed to use function pointers in that way, I could not
recall what was the reason to use them for netdev. I don't like this pseudo
object oriented C style (dev-write() and the like) because we made bad
experiences with it at my former company. While writing the whole HAL for our
firmware there using function pointers this way, made programming pretty
convenient, it turned out to become problematic speed-wise and was a nightmare
to debug.

Hence, I would like to trigger a fundamental discussion on this topic. Does
anyone has a particular opinion on the topic why function pointer based
device drivers should be a good or a bad idea? And can anyone explain to me
the need of function pointers for netdev?

Cheers,
Oleg

[1] https://github.com/RIOT-OS/RIOT/pull/2353
-- 
if (user_specified)
/* Didn't work, but the user is convinced this is the
 * place. */
linux-2.4.0-test2/drivers/parport/parport_pc.c


pgpRbu6a4LGIk.pgp
Description: PGP signature
___
devel mailing list
devel@riot-os.org
http://lists.riot-os.org/mailman/listinfo/devel


Re: [riot-devel] redbee-econotag board

2015-02-18 Thread Thomas Eichinger
Hi Ralph,

a short update:
I spent most of today’s afternoon to set up toolchain and additional tools 
again which
didn’t left much time for testing.

I can confirm the latter problem the app yielding. I will continue 
investigation tomorrow.
The first issue I couldn’t reproduce though. 

I will keep you updated on my findings.

Best, Thomas

 On 18 Feb 2015, at 14:54, Ralph Droms (rdroms) rdr...@cisco.com wrote:
 
 
 On Feb 18, 2015, at 4:18 AM 2/18/15, Thomas Eichinger 
 thomas.eichin...@fu-berlin.de wrote:
 
 Hi Ralph,
 
 first of all also welcome from my side.
 
 Regarding the RIOT support for the redbee-econotag I can remember similar
 problems which resulted from the compiler used. For this board it is 
 important
 to note that only the CodeSourcery GCC 2008q3 is supported. Could you 
 check for this?
 
 $ arm-none-eabi-gcc -v
 Using built-in specs.
 Target: arm-none-eabi
 Configured with: /scratch/julian/lite-respin/eabi/src/gcc-4.3/configure 
 --build=i686-pc-linux-gnu --host=i686-pc-linux-gnu --target=arm-none-eabi 
 --enable-threads --disable-libmudflap --disable-libssp 
 --disable-libstdcxx-pch --with-gnu-as --with-gnu-ld --enable-languages=c,c++ 
 --disable-shared --with-newlib --with-pkgversion='Sourcery G++ Lite 
 2008q3-66' --with-bugurl=https://support.codesourcery.com/GNUToolchain/ 
 --disable-nls --prefix=/opt/codesourcery --with-headers=yes 
 --with-sysroot=/opt/codesourcery/arm-none-eabi 
 --with-build-sysroot=/scratch/julian/lite-respin/eabi/install/arm-none-eabi 
 --with-gmp=/scratch/julian/lite-respin/eabi/obj/host-libs-2008q3-66-arm-none-eabi-i686-pc-linux-gnu/usr
  
 --with-mpfr=/scratch/julian/lite-respin/eabi/obj/host-libs-2008q3-66-arm-none-eabi-i686-pc-linux-gnu/usr
  --disable-libgomp --enable-poison-system-directories 
 --with-build-time-tools=/scratch/julian/lite-respin/eabi/install/arm-none-eabi/bin
  --with-build-time-tools=/scratch/julian/lite-respin/
 eabi/install/arm-none-eabi/bin
 Thread model: single
 gcc version 4.3.2 (Sourcery G++ Lite 2008q3-66) 
 
 Regarding the conditional assembly problem - this code snippet doesn't seem 
 to correctly recognize (CPU != mc1322x) (where CPU = mc1322x is set in 
 boards/redbee-econotag/Makefile.include):
 
 .if (CPU != mc1322x)
/* jump into vic interrupt */
movr0, #0xff00/* lpc23xx */
ldrr0, [r0]
addlr,pc,#4
 .else
/* mc1322x seems to lack a VIC, distinction of IRQ has to be done in SW */
ldrr0, =isr   /* mc1322x */
 .endif
 
 Running the code as distributed yields:
 
 Board initialized.
 kernel_init(): This is RIOT! (Version: 2014.12-415-g1e6e-instant-contiki)
 kernel_init(): jumping into first task...
 #!undef abort at 0x1c00a0 (0x6809490E) originating from 0x400fe8
 
 If I force assembly of the .else code, the code doesn't abort but only yields:
 
 Board initialized.
 kernel_init(): This is RIOT! (Version: 2014.12-415-g1e6e-instant-contiki)
 kernel_init(): jumping into first task...
 
 - Ralph
 
 
 I will have a more in depth look on your reported problem in the afternoon.
 
 Kind regards,
 Thomas
 
 On 17 Feb 2015, at 22:41, Ralph Droms (rdroms) rdr...@cisco.com wrote:
 
 Is redbee-econotag board code still in active development or use?
 
 I'm new to RIOT ... tried compiling the default example for 
 redbee-econotag and found an error (maybe more correctly a construct that 
 doesn't work as expected) in the conditional assembly in common.s  I put in 
 a patch but now all I get from default is:
 
 .CONNECT
 Size: 69440 bytes
 Sending /home/rdroms/RIOT/examples/default/bin/redbee-econotag/default.hex
 done sending files.
 Board initialized.
 kernel_init(): This is RIOT! (Version: 2014.12-415-g1e6e-instant-contiki)
 kernel_init(): jumping into first task...
 
 Should default work?
 
 - Ralph
 
 ___
 devel mailing list
 devel@riot-os.org
 http://lists.riot-os.org/mailman/listinfo/devel
 
 ___
 devel mailing list
 devel@riot-os.org
 http://lists.riot-os.org/mailman/listinfo/devel
 
 ___
 devel mailing list
 devel@riot-os.org
 http://lists.riot-os.org/mailman/listinfo/devel

___
devel mailing list
devel@riot-os.org
http://lists.riot-os.org/mailman/listinfo/devel


Re: [riot-devel] About function pointers

2015-02-18 Thread Ryan Kurte
Hi All,

We use this approach exhaustively (for drivers and practically everything
else) with the same result.
The struct does not even need to be declared as a const struct if it is
used in a way that implies such, though it is definitely more elegant to
declare it so.

Though I do have a preference for binding prerequisite functions as a part
of the interface, rather than hiding them in the body of the code with
macros.
As a disclaimer, I haven't actually checked the result of this particular
style of binding, which in our application does use a dereference to access
the function pointer. I will have a shot at that later on.
Our decision was that effective modularity was more critical than
performance for our driver elements (at least until we experience a
performance issue).

ie.
`
//Initialise the radio device
extern int8_t SI446x_init(struct si446x_s *device,
  transfer_data_function spi_transfer_function,
  set_pin_function set_sdn,
  get_pin_function get_cts,
  get_pin_function get_irq,
  get_pin_function get_cca);
`
Where for the purposes of this example the above are defined so:
`
typedef int8_t (*transfer_data_function)(void* context, uint8_t *data,
uint8_t size);
typedef int8_t (*set_pin_function)(void* context, uint8_t value);
typedef int8_t (*get_pin_function)(void* context);
`

This means that any dependencies are explicitly defined in the interface,
rather than hidden in the source code.
It also means that instantiating multiple devices and linking them to
different underlying communication channels becomes possible, and you can
do some quite neat testing based on that.

In my opinion this is a cleaner abstraction, and leads to clearer parallel
composition (or wiring) of modules, rather than the oft used vertical
composition.
I had a bit of a wild rant about this recently, and there is a /very/ draft
set of slides if anyone is interested.

Hope some of this is valuable,

Ryan

On 19 February 2015 at 05:28, ROUSSEL Kévin kevin.rous...@inria.fr wrote:

 Hello,

 I began to use function pointers in the 'radio_driver.h' when trying to
 create a unified model for radio drivers. I guess it went over later to the
 whole netdev effort.

 My idea then was to have a fast, predictable call chain from the MAC
 layer to the physical radio transceiver functions: most MAC protocols
 expect to run with precise delays, and a mechanism relying on message
 between threads (like 'transceiver') did not fit that need.
 The model of driver as structs containing function pointers is the one
 used in Contiki: it seemed quite a natural way to handle the problem to
 me... In their code, the needed drivers are aliased as 'NETSTACK_xxx'
 macros, then functions are called by invoking 'NETSTACK_xxx.func()'.
 I've never seen advanced dereferencing (-) nor object-oriented like
 constructs in that context.

 As P. Nikander said, since you are supposed to know your hardware at
 compile time, these pointers are actually constants that should be resolved
 at compile (linking) time -- even with GCC. Theoretically, it should be
 translated by standard indirect calls at the assembler level. Could you
 tell us more about your previous experiments? It seems quite strange to me
 that such a mechanism (that seems simple to me) could impose speed and
 debugging penalties.

 The other question is how could we implement the network stack? Using a
 mechanism like 'transceiver', that relies on message-passing between
 threads, implies that there is no predictable delay for executing network
 functions (one has to wait for the scheduler to switch to the thread(s)
 that execute(s) the feature(s) you want to use). At some levels -- like
 between MAC and PHY -- this can be a huge disadvantage.

 Is there a better way to obtain deterministic/direct API calls than using
 the struct of function pointers scheme ?...

 Regards,



 Le 18/02/2015 11:38, Oleg Hahm a écrit :

 Dear remodeling IoTlers!

 Ludwig just made me aware that Joakim's PR for NVRAM [1] introduces
 function
 pointers as part of the device driver struct. This made me remember that
 there
 were already similar function pointers introduced as part of netdev.

 As I was always opposed to use function pointers in that way, I could not
 recall what was the reason to use them for netdev. I don't like this
 pseudo
 object oriented C style (dev-write() and the like) because we made bad
 experiences with it at my former company. While writing the whole HAL for
 our
 firmware there using function pointers this way, made programming pretty
 convenient, it turned out to become problematic speed-wise and was a
 nightmare
 to debug.

 Hence, I would like to trigger a fundamental discussion on this topic.
 Does
 anyone has a particular opinion on the topic why function pointer based
 device drivers should be a good or a bad idea? And can anyone explain to
 me
 the need of 

Re: [riot-devel] About function pointers

2015-02-18 Thread Oleg Hahm
Hi Pekka,

thanks for your input.

 Of course, some care is needed to make sure that the compiler does the right
 thing.
 It is relatively easy to break the pattern.

I see your point, but actually, I don't want to build a whole system model
based on any assumption about what the compiler might optimize. Without
testing I'm pretty sure that you're right and an up-to-date version of GCC is
able to optimize static function pointers, but we don't know which weird
compilers on some esoteric hardware platform might be used for RIOT somewhere
sometime, so I rather rely on optimized C code than on optimized compilers.

Cheers,
Oleg
-- 
The four hard things in CS are cache invalidation, naming, and off-by-one
errors.


pgpuXrBOHbMyR.pgp
Description: PGP signature
___
devel mailing list
devel@riot-os.org
http://lists.riot-os.org/mailman/listinfo/devel


Re: [riot-devel] About function pointers

2015-02-18 Thread Oleg Hahm
Hi Kévin!

 I began to use function pointers in the 'radio_driver.h' when trying to
 create a unified model for radio drivers. I guess it went over later to the
 whole netdev effort.

Yes, I remember that, but why can't this be implemented in a similar way we
did for most of the peripheral drivers like SPI? Instead of calling a function
pointer, we simply pass a struct describing the low-level device (driver) that
should be used.

 My idea then was to have a fast, predictable call chain from the MAC layer
 to the physical radio transceiver functions: most MAC protocols expect to
 run with precise delays, and a mechanism relying on message between threads
 (like 'transceiver') did not fit that need.

I completely agree on the point that we need to have direct function calls for
MAC protocols (see also http://arxiv.org/abs/1502.01968).

 The model of driver as structs containing function pointers is the one used
 in Contiki: it seemed quite a natural way to handle the problem to me... In
 their code, the needed drivers are aliased as 'NETSTACK_xxx' macros, then
 functions are called by invoking 'NETSTACK_xxx.func()'.

I think it is indeed one of the two natural solutions - the other one would be
MACROing everything. I made experiences with both versions while developing on
firmware for older sensor board platforms. And both had their drawbacks. Thus,
when I started to work on what now is known as RIOT, I wanted to avoid Macros
and a function pointer based abstraction layer model as much as possible. Of
course, there are cases where either the one or the other will be the best
solution, but I think we have to make sure to check if there are no
alternative solutions that might work better on the long run.

 As P. Nikander said, since you are supposed to know your hardware at compile
 time, these pointers are actually constants that should be resolved at
 compile (linking) time -- even with GCC. Theoretically, it should be
 translated by standard indirect calls at the assembler level.

You name it: If everything is known at link time, then there is also always a
way around function pointers. As I've written in the previous mail: I'd rather
tell the compiler (or linker) how to do the stuff in an efficient way than
hoping for the toolchain being smarter than me.

 Could you tell us more about your previous experiments? It seems quite
 strange to me that such a mechanism (that seems simple to me) could impose
 speed and debugging penalties.

I cannot disclose any code here, because it was proprietary code for my old
company, but the problem was a layered one. We had a highly abstracted driver
model, similar to Linux' one with char and block devices, abstracted serial
line devices and the like. Thus, an application or any high level code
accessing low-level drivers would be de-referenced multiple times. This made
it incredible hard to debug (because you had to follow all the pointer
de-referencing) and made it almost impossible to hold some strict deadlines
for TDMA on our old MSP430F1612.

 The other question is how could we implement the network stack? Using a
 mechanism like 'transceiver', that relies on message-passing between
 threads, implies that there is no predictable delay for executing network
 functions (one has to wait for the scheduler to switch to the thread(s) that
 execute(s) the feature(s) you want to use). At some levels -- like between
 MAC and PHY -- this can be a huge disadvantage.

I think we can live with the overhead of IPC calls on all layers except the
MAC protocol. However, even message-passing has a predictable delay in RIOT -
just the concrete numbers might be to high for some low latency MAC protocols.
But again, I'm definitely not arguing against function calls for these tasks,
just wondering if function pointers are the smartest solution here. (And I'm
not saying that they're not...)

Cheers,
Oleg
-- 
printk(CPU[%d]: Giving pardon to imprisoned penguins\n, smp_processor_id());
linux-2.4.8/arch/sparc64/kernel/smp.c


pgpRheajnL991.pgp
Description: PGP signature
___
devel mailing list
devel@riot-os.org
http://lists.riot-os.org/mailman/listinfo/devel


Re: [riot-devel] About function pointers

2015-02-18 Thread Oleg Hahm
Hi Ryan!

 In my opinion this is a cleaner abstraction, and leads to clearer parallel
 composition (or wiring) of modules, rather than the oft used vertical
 composition.

So, basically you're saying that trading some performance for a cleaner design
is a good thing, is that right? I would say that this is very aligned with
RIOT's usual design goals and therefore I agree. The question is: how much
performance can we give away for this before we hit the limits? Remember, we
don't have to care only for rather powerful ARM MCUs, but also for their
little 8 and 16 bit brothers and sisters running with only a couple of MHz CPU
speed.

 I had a bit of a wild rant about this recently, and there is a /very/ draft
 set of slides if anyone is interested.

I would be interested.

Cheers,
Oleg
-- 
The bad thing about Kerberos jokes is that I can't tell them to you because I
don't trust you and I don't know your name!


pgpN0cHAjyxLj.pgp
Description: PGP signature
___
devel mailing list
devel@riot-os.org
http://lists.riot-os.org/mailman/listinfo/devel


Re: [riot-devel] redbee-econotag board

2015-02-18 Thread Ralph Droms (rdroms)

 On Feb 18, 2015, at 4:18 AM 2/18/15, Thomas Eichinger 
 thomas.eichin...@fu-berlin.de wrote:
 
 Hi Ralph,
 
 first of all also welcome from my side.
 
 Regarding the RIOT support for the redbee-econotag I can remember similar
 problems which resulted from the compiler used. For this board it is important
 to note that only the CodeSourcery GCC 2008q3 is supported. Could you 
 check for this?

$ arm-none-eabi-gcc -v
Using built-in specs.
Target: arm-none-eabi
Configured with: /scratch/julian/lite-respin/eabi/src/gcc-4.3/configure 
--build=i686-pc-linux-gnu --host=i686-pc-linux-gnu --target=arm-none-eabi 
--enable-threads --disable-libmudflap --disable-libssp --disable-libstdcxx-pch 
--with-gnu-as --with-gnu-ld --enable-languages=c,c++ --disable-shared 
--with-newlib --with-pkgversion='Sourcery G++ Lite 2008q3-66' 
--with-bugurl=https://support.codesourcery.com/GNUToolchain/ --disable-nls 
--prefix=/opt/codesourcery --with-headers=yes 
--with-sysroot=/opt/codesourcery/arm-none-eabi 
--with-build-sysroot=/scratch/julian/lite-respin/eabi/install/arm-none-eabi 
--with-gmp=/scratch/julian/lite-respin/eabi/obj/host-libs-2008q3-66-arm-none-eabi-i686-pc-linux-gnu/usr
 
--with-mpfr=/scratch/julian/lite-respin/eabi/obj/host-libs-2008q3-66-arm-none-eabi-i686-pc-linux-gnu/usr
 --disable-libgomp --enable-poison-system-directories 
--with-build-time-tools=/scratch/julian/lite-respin/eabi/install/arm-none-eabi/bin
 --with-build-time-tools=/scratch/julian/lite-respin/
 eabi/install/arm-none-eabi/bin
Thread model: single
gcc version 4.3.2 (Sourcery G++ Lite 2008q3-66) 

Regarding the conditional assembly problem - this code snippet doesn't seem to 
correctly recognize (CPU != mc1322x) (where CPU = mc1322x is set in 
boards/redbee-econotag/Makefile.include):

.if (CPU != mc1322x)
/* jump into vic interrupt */
movr0, #0xff00/* lpc23xx */
ldrr0, [r0]
addlr,pc,#4
.else
/* mc1322x seems to lack a VIC, distinction of IRQ has to be done in SW */
ldrr0, =isr   /* mc1322x */
.endif

Running the code as distributed yields:

 Board initialized.
 kernel_init(): This is RIOT! (Version: 2014.12-415-g1e6e-instant-contiki)
 kernel_init(): jumping into first task...
 #!undef abort at 0x1c00a0 (0x6809490E) originating from 0x400fe8

If I force assembly of the .else code, the code doesn't abort but only yields:

 Board initialized.
 kernel_init(): This is RIOT! (Version: 2014.12-415-g1e6e-instant-contiki)
 kernel_init(): jumping into first task...

- Ralph

 
 I will have a more in depth look on your reported problem in the afternoon.
 
 Kind regards,
 Thomas
 
 On 17 Feb 2015, at 22:41, Ralph Droms (rdroms) rdr...@cisco.com wrote:
 
 Is redbee-econotag board code still in active development or use?
 
 I'm new to RIOT ... tried compiling the default example for 
 redbee-econotag and found an error (maybe more correctly a construct that 
 doesn't work as expected) in the conditional assembly in common.s  I put in 
 a patch but now all I get from default is:
 
 .CONNECT
 Size: 69440 bytes
 Sending /home/rdroms/RIOT/examples/default/bin/redbee-econotag/default.hex
 done sending files.
 Board initialized.
 kernel_init(): This is RIOT! (Version: 2014.12-415-g1e6e-instant-contiki)
 kernel_init(): jumping into first task...
 
 Should default work?
 
 - Ralph
 
 ___
 devel mailing list
 devel@riot-os.org
 http://lists.riot-os.org/mailman/listinfo/devel
 
 ___
 devel mailing list
 devel@riot-os.org
 http://lists.riot-os.org/mailman/listinfo/devel

___
devel mailing list
devel@riot-os.org
http://lists.riot-os.org/mailman/listinfo/devel


Re: [riot-devel] About function pointers

2015-02-18 Thread ROUSSEL Kévin

Hello,

I began to use function pointers in the 'radio_driver.h' when trying to 
create a unified model for radio drivers. I guess it went over later to 
the whole netdev effort.


My idea then was to have a fast, predictable call chain from the MAC 
layer to the physical radio transceiver functions: most MAC protocols 
expect to run with precise delays, and a mechanism relying on message 
between threads (like 'transceiver') did not fit that need.
The model of driver as structs containing function pointers is the one 
used in Contiki: it seemed quite a natural way to handle the problem to 
me... In their code, the needed drivers are aliased as 'NETSTACK_xxx' 
macros, then functions are called by invoking 'NETSTACK_xxx.func()'.
I've never seen advanced dereferencing (-) nor object-oriented like 
constructs in that context.


As P. Nikander said, since you are supposed to know your hardware at 
compile time, these pointers are actually constants that should be 
resolved at compile (linking) time -- even with GCC. Theoretically, it 
should be translated by standard indirect calls at the assembler level. 
Could you tell us more about your previous experiments? It seems quite 
strange to me that such a mechanism (that seems simple to me) could 
impose speed and debugging penalties.


The other question is how could we implement the network stack? Using a 
mechanism like 'transceiver', that relies on message-passing between 
threads, implies that there is no predictable delay for executing 
network functions (one has to wait for the scheduler to switch to the 
thread(s) that execute(s) the feature(s) you want to use). At some 
levels -- like between MAC and PHY -- this can be a huge disadvantage.


Is there a better way to obtain deterministic/direct API calls than 
using the struct of function pointers scheme ?...


Regards,



Le 18/02/2015 11:38, Oleg Hahm a écrit :

Dear remodeling IoTlers!

Ludwig just made me aware that Joakim's PR for NVRAM [1] introduces function
pointers as part of the device driver struct. This made me remember that there
were already similar function pointers introduced as part of netdev.

As I was always opposed to use function pointers in that way, I could not
recall what was the reason to use them for netdev. I don't like this pseudo
object oriented C style (dev-write() and the like) because we made bad
experiences with it at my former company. While writing the whole HAL for our
firmware there using function pointers this way, made programming pretty
convenient, it turned out to become problematic speed-wise and was a nightmare
to debug.

Hence, I would like to trigger a fundamental discussion on this topic. Does
anyone has a particular opinion on the topic why function pointer based
device drivers should be a good or a bad idea? And can anyone explain to me
the need of function pointers for netdev?

Cheers,
Oleg

[1] https://github.com/RIOT-OS/RIOT/pull/2353



___
devel mailing list
devel@riot-os.org
http://lists.riot-os.org/mailman/listinfo/devel



--


 Kévin Roussel
 Doctorant, projet LAR
 Équipe MADYNES, INRIA Nancy Grand-Est / LORIA
 Tél. : +33 3 54 95 86 27
 kevin.rous...@inria.fr

___
devel mailing list
devel@riot-os.org
http://lists.riot-os.org/mailman/listinfo/devel