Hello,

On Wed, 9 Oct 2013 13:22:37 -0700
Michael Smith <[email protected]> wrote:

> 
> On 09/10/2013, at 1:03 PM, Paul Sokolovsky <[email protected]> wrote:
> 
> >> void rcc_peripheral_enable_clock(clock_enable_reg_t
> >> clock_enable_reg, uint32_t en);
> > 
> > Would it change *that* much? There still will be a function which
> > needs to be called, do the dynamic bit manipulation and return.
> > Shouldn't it be something like:
> > 
> > peripheral_enable_clock<clock_enable_reg_t, uint32_t>() to emphasize
> > that it should be compile-time constants?
> 
> No, that's still awful. Nobody wants to care which register they're
> fiddling with, they just want the peripheral on / off.
> 
>       peripheral.clock_enable = true;

Just to get things straight, this is how you'd do it in Python or
JavaScript, and NOT how you'd do it in C++ (for the topic we discuss,
because C++ is multi-paradigm language - in different contexts, you use
different means). The misconception that it's how it's done in C++ is
the reason why people are stuck with less than ideal C APIs and spend
time trying to make them just a little bit "better".

Back to your example, even C++11 doesn't have properties, and objects in
C++ waste memory (min object size is 1). So, instead one uses types
(which encapsulate object properties) and static methods, on top of that
type-based encapsulation. So it's like the code example you deleted:

Block::clk::enable();

Any block has its clock encapsulated, which you just enable. For
example:

SPI::clk::enable();

What if there're few SPIs? Easy:

SPI<SPI0>::clk::enable();
SPI<SPI1>::clk::enable();

Where SPI0/SPI1 are opaque identifiers. Obviously, you don't need to
write it all the time like that, can instantiate specific block you
need:

typedef SPI<SPI0> myspi;
myspi::clk::enable();

Now you can pass a block to some algorithm. For example, block transfer:

BlockXfer<myspi>::xfer(mem, size);

Come up with DMA implementation of transfer algorithm?

BlockDMAXfer<myspi>::xfer(mem, size);

Want to easily switch between different transfer types depending on
development stage, product, etc.?

prod1.h:
typedef BlockXferByte<myspi> xferer;
prod2.h:
typedef BlockXferWord<myspi> xferer;
prod3.h:
typedef BlockDMAXfer<myspi> xferer;

Try to do all that in C. Tell when you gave up with #ifdef and
5-story macros which still didn't allow full component-based design with
ultimate code efficiency.

> 
> would be better if you're going to do the C++ thing. 
> 
>       periperhal_clock_enable(<peripheral identifier>,<clock state>)
> 
> if you want to stick to C (note verb-subject re-ordering to maintain
> widest-to-narrowest ordering in the function name).

Nice. One may only wonder why all C APIs aren't designed like that from
start. Then one may wonder if it's worth to change existing ones. Then
one may wonder if there's a change anyway, is it worth to stop with just
swapping words in identifiers? I spent a lot of time thinking before
"falling down" to "dreadest" C++ (hadn't used C++ for 10 years before
that, because it is "superfluous"), but in the end, I waved C bye-bye.
Just sharing.

> 
>  = Mike
> 



-- 
Best regards,
 Paul                          mailto:[email protected]

------------------------------------------------------------------------------
October Webinars: Code for Performance
Free Intel webinars can help you accelerate application performance.
Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from 
the latest Intel processors and coprocessors. See abstracts and register >
http://pubads.g.doubleclick.net/gampad/clk?id=60134071&iu=/4140/ostg.clktrk
_______________________________________________
libopencm3-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libopencm3-devel

Reply via email to