It is currently Thu Oct 23, 2014 8:52 pm



Post new topic Reply to topic  [ 26 posts ]  Go to page Previous  1, 2, 3  Next
Author Message
 Post subject: Re: DigitalWriteFast library for Uno32?
PostPosted: Wed Feb 15, 2012 10:45 am 
Offline

Joined: Wed May 25, 2011 12:17 am
Posts: 148
So, remember this really ugly implementation of DigitalWriteFast? It relied on gcc being able to optimize away long and complex ternary statements containing constants. It was fast, but it relied on awful-looking C macros that were completely separate from the main pins_arduino.c structures, and thus subject to maintenance nightmares.

Well, it turns out that gcc will also optimize indexing into static arrays with a constant, so we can get ALMOST as fast an implementation, using the code that already exists. No maintenance nightmare, and a pretty closely parallel implementation, and no particularly ugly macros.

variants/xxx/Board_Data.c gets a slight set of modifications so that it can make either global arrays (for pins_arduino.c) or static arrays that disappear when only indexed by constants:
Code:
+#if defined(OPT_BOARD_DATA_STATIC)
+#define MAYBESTATIC static
+#else
+#define MAYBESTATIC
+#endif
 
 /* ------------------------------------------------------------ */
 /*                                     Data Tables                                                                     */
@@ -56,7 +61,7 @@
 ** the TRIS register for the port. This is used for setting the
 ** pin direction.
 */
-const uint32_t port_to_tris_PGM[] = {
+MAYBESTATIC const uint32_t port_to_tris_PGM[] = {
        NOT_A_PORT,                             //index value 0 is not used
 
 #if defined(_PORTA)
@@ -108,7 +113,7 @@
 /* This table is used to map the digital pin number to the port
 ** containing that pin.
 */
-const uint8_t digital_pin_to_port_PGM[] = {
+MAYBESTATIC const uint8_t digital_pin_to_port_PGM[] = {

And then fastio.h gets code to include the arrays, and uses inline functions that closely parallel wiring_digital.c. It even gets to include some of the sanity checking:
Code:
#define OPT_BOARD_DATA_STATIC 1
#define OPT_BOARD_DATA 1
#define OPT_BOARD_INTERNAL 1
#include <p32xxxx.h>
#include <WProgram.h>
#include <Board_Data.c>

/*
 * This looks a lot like digitalWrite, but uses the static arrays and is inline.
 * when called with constants, it should optimize down to the single instruct.
 */
static inline void _dwf(uint8_t pin, uint8_t val)
{
    p32_ioport *   iop;
    unsigned int      port;
    unsigned int      bit;

   //* Get the port number for this pin.
   if ((pin >= NUM_DIGITAL_PINS) ||
       ((port = digitalPinToPort(pin)) == NOT_A_PIN))
   {
      return;
   }

   //* Obtain pointer to the registers for this io port.
   iop = (p32_ioport *)portRegisters(port);

   //* Obtain bit mask for the specific bit for this pin.
   bit = digitalPinToBitMask(pin);

   //* Set the pin state
   if (val == LOW)
   {
      iop->lat.clr = bit;
   }
   else
   {
      iop->lat.set = bit;
   }
}


#define digitalWriteFast(P, V)  \
    if (__builtin_constant_p(P) && __builtin_constant_p(V)) {   \
   _dwf(P, V);                  \
    } else {                     \
   digitalWrite((P), (V));               \
    }

This makes me feel a lot warmer and fuzzier than the previous implementation. It ought to be MUCH easier to add to the different variants, and could have "partial" support added to the core with no impact...


Top
 Profile  
 
 Post subject: Re: DigitalWriteFast library for Uno32?
PostPosted: Tue Feb 21, 2012 10:40 pm 
Offline

Joined: Mon Aug 15, 2011 9:21 pm
Posts: 165
Location: Sweden
You're the man! :)


Top
 Profile  
 
 Post subject: Re: DigitalWriteFast library for Uno32?
PostPosted: Tue Oct 15, 2013 2:01 am 
Offline

Joined: Sat Nov 19, 2011 8:45 pm
Posts: 34
ok,
So I know this thread is old, but I'm just getting around to needing
fast i/o on the pic32 for my glcd library and all the digitalWriteFast()/digitalReadFast() stuff
annoys the !@#!@# out of me not to mention it is pain to deal with.
So let me explain further about not needing to go
down the digitalXXXFast() path again.

While I believe that a better more integrated solution should be supplied with the
IDE for a "it just works" out of the box experience, even when implementing
faster i/o by using the simple wrapper macros in a header file
like several of the FastDigital header files are doing, there is simply
no need to create a new/alternate API for the faster i/o.
The way C macro expansion works, you can use the exact name for the macro
wrapper as the name of the function it is wrapping.
This feature is specifically mentioned in the cpp
documenation. This allows you to wrap a function without the calling code
ever having to know about it.
It is one of the many subtle behaviors of cpp that often comes in handy.
I use it quite often.
So for example,
a tweak from the FastDigital.h header
works perfectly:

Code:
#define digitalWrite(P, V) \
do {                        \
    if (__builtin_constant_p(P) && __builtin_constant_p(V)) {      \
   if (V) {                     \
       *(_dpin_to_set_macro(P)) = _dpin_to_bitmask_macro(P);   \
   } else {                     \
       *(_dpin_to_clr_macro(P))  = _dpin_to_bitmask_macro(P);   \
   }                        \
    } else  digitalWrite((P), (V));               \
}while (0)


Because of the way cpp works, it does not cause macro recursion.
In the above example,
the calling code will get the macro instead of the function
and the macro can then call the real digitalWrite() when necessary.
Defined this way instead, the user simply includes the FastDigital header and does
not have to modify his code.

--- bill


Top
 Profile  
 
 Post subject: Re: DigitalWriteFast library for Uno32?
PostPosted: Thu Oct 17, 2013 1:40 am 
Offline

Joined: Mon Sep 24, 2012 3:24 pm
Posts: 73
This sounds like a great idea. So I asked a few of our run-time engineers to take a closer look.

Turns out there may be complications with PPS mapping on MX1,2 devices, and with pull-ups for Change Notification pins. These concerns might be resolvable, but there is also a third issue. A new I/O architecture is under development that is definitely not compatible with this proposal. In the interest of compatibility across board variants, I don’t think we can implement this macro in the core system.

Nevertheless, thank you for taking the time to write up a clear explanation of how it could work. That's useful info for those of us with limited C preprocessor (cpp) experience.


Top
 Profile  
 
 Post subject: Re: DigitalWriteFast library for Uno32?
PostPosted: Thu Oct 17, 2013 2:53 am 
Offline

Joined: Sat Nov 19, 2011 8:45 pm
Posts: 34
guymc wrote:
This sounds like a great idea. So I asked a few of our run-time engineers to take a closer look.

Turns out there may be complications with PPS mapping on MX1,2 devices, and with pull-ups for Change Notification pins. These concerns might be resolvable, but there is also a third issue. A new I/O architecture is under development that is definitely not compatible with this proposal. In the interest of compatibility across board variants, I don’t think we can implement this macro in the core system.

Nevertheless, thank you for taking the time to write up a clear explanation of how it could work. That's useful info for those of us with limited C preprocessor (cpp) experience.

Huh?
I'm following what you are saying.
You can wrap CPP macros on top of anything.
There should be no compatiblity issue with respect to variants
the macros just have to smart enough to deal with things.

I have a set of macros that are thousands of lines long that I use on AVR
to do raw port i/o. They automatically determine if bits are adjacent
on ports and can do multi bit i/o.

In my openGLCD library I have layers and layers of macros
that make decisions based on all kinds of information, including
board types, which in some cases has to be determined by looking
at analog to digital pin mappings from other macros down in the variant files.
(Arduino IDE does not tell you which board the code is being compiled for)

All of this is done at compile time with help from lots of cpp macros.

The key is macros need to be very high up if not on top
of the API rather than down in the middle of a design.

My suggestion is that anybody involved with defining a i/o architecture
will need to be VERY proficient at CPP.
The reason being is that as much as possible needs to be done at compile time
vs run time to get the performance up.
There will have to be trade offs between what can be done at compile time
vs run time given the API.
But often you gain significant advantages when taking of advantage of
capabilites of CPP and using smart macros.

There are also some things that can be done in C++ that can really help,
but then you can't use it in regular C code.

For me, one thing that is needed that is missing from the existing Arduino i/o
API is multi bit i/o.
i.e.
the abilty to set/read multiple i/o pins with a single API call.
This allows the underlying code to optimize the i/o to reduce the number
of register operation and dramatically speed up the i/o process.

For an example of what I'm talking about see my avrio header file:
http://code.google.com/p/mcu-io/source/browse/trunk/avr/avrio/avrio.h

--- bill


Top
 Profile  
 
 Post subject: Re: DigitalWriteFast library for Uno32?
PostPosted: Mon Oct 21, 2013 11:15 pm 
Offline

Joined: Sun May 22, 2011 6:59 am
Posts: 162
If anyone would like to combine this into a 3rd party library on github. I could include it in the next build of MPIDE.

Let me know if there is an issue getting the code into Github. I can help with that.

-Rick


Top
 Profile  
 
 Post subject: Re: DigitalWriteFast library for Uno32?
PostPosted: Tue Oct 22, 2013 12:41 am 
Offline

Joined: Sat Nov 19, 2011 8:45 pm
Posts: 34
Were you refreing to DigitalFast?
or the avrio stuff I've done?

When is the next build?

In the big picture, I still believe that the
digitalXXXfast() API is the wrong way to go.
I stronly believe that should be transparaent
to the actual user sketch code vs being a new API.

If it were to be handled as a 3rd party library, then
I believe that the user simply includes a header file,
and his existing code with no modifications,
continues to work, using the existing digitalWrite()/digitalRead() API,
but the code gets faster if certain parameters are constants.

i.e. the header file just creates wrapper macros that sit
on top of the existing API as I mentioned earlier.

The reason I ask about timing for the next release,
is that while I'm willing to do it,
I've still got a bunch of stuff on my plate to get my openGLCD library
pushed out.

As far as actual implemenation goes, there are some open items
like does the implemenation have to work for both C and C++?

Also, it would get much easier to do and maintain if there could be a
slightly different declaration in the Board_Data.c files to allow
turning on/off a static declaration so that the code could pull the data
from the actual IDE supplied pin data tables vs having to create and maintain
parallel tables in macros.

And if we are talking about going that far for integration, why not
just include it into the core code and be done with it so all sketches
benefit from the additional performance when paramters allow it?

--- bill


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 26 posts ]  Go to page Previous  1, 2, 3  Next

Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Theme designed by stylerbb.net © 2008
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
All times are UTC [ DST ]