Go Down

Topic: Referencing ports directly on arduino micro (Read 120 times) previous topic - next topic

JPlanck

Today at 02:34 pm Last Edit: Today at 02:48 pm by JPlanck
Hey guys, quick question here. I'm using some time sensitive code so one of the methods I've been trying to reduce the code execution time is to reference the port and pin directly instead of using digitalwrite().

However the ports don't seem to match up with what I'm seeing on the diagrams.

According to a graphic I have of the Arduino micro pinout, digital pin 4 is port d, pin 4. And digital pin 5 is port c, pin 6. I have two MCP2515's I need to communicate with, so to drive these pins low I use an array with the information in the class definition:

byte portrefs[2];

and then initialize it in the constructor:
void MCP_CAN::init_CS(byte _CS)
{
 if (_CS == 0) return;
 SPICS = _CS;
 pinMode(SPICS, OUTPUT);
 portrefs[0] = (SPICS=4 ? PORTD : PORTC); //SPI in this case will either be pin 4 or 5, 4 is PORTD-pin4, 5 is PORTC-pin6.
 portrefs[1] = (SPICS=4 ? 4 : 6);
 MCP2515_UNSELECT();
}

I then use a macro-within-a-macro that should set those ports low or high as needed (LOW on the cs pin initializes communication with that chip):

#define CLR(x,y) (x&=(~(1<<y)))
#define SET(x,y) (x|=(1<<y))
#define MCP2515_SELECT()   CLR(portrefs[0], portrefs[1])
#define MCP2515_UNSELECT() SET(portrefs[0], portrefs[1])

However, when starting this program with the begin function, the code throws an error that the CAN chip could not initialize, as in it did not establish communications with the chip.

The only things that change between the non-working code and the working code is this double-macro referencing the array. If I revert it back to the original library with
#define MCP2515_SELECT() digitalwrite(4, LOW);
the code works fine.

Anybody know what is going wrong here? I'm a little bit out of my element going super deep into the hardware like this, but I need to speed up this code and I think it's close enough speed-wise be workable if I can succeed in reducing the execution time a bit.

aarg

Should
Code: [Select]
portrefs[1] = (SPICS=4 ? 4 : 6);

be
Code: [Select]
portrefs[1] = (SPICS==4 ? 4 : 6);
?
  ... with a transistor and a large sum of money to spend ...
Please don't PM me with technical questions. Post them in the forum.

JPlanck

:o

You're right, it should. Simple mistakes.

After fixing it, I still get the same failure to initialize CAN on pin 4 though.

aarg

:o

You're right, it should. Simple mistakes.

After fixing it, I still get the same failure to initialize CAN on pin 4 though.
Well, that could be a result of something in the rest of your code, so please post it all. In code tags.
  ... with a transistor and a large sum of money to spend ...
Please don't PM me with technical questions. Post them in the forum.

JPlanck

Well there's probably over 20 pages of code to post between my code and the libraries included/modified.

Here's a link to my code (too big to paste here):
https://docs.google.com/document/d/e/2PACX-1vRQsEtN32Lq3yiIEuH7pUzbDsQWtCmqrff0V_nKi-FVL-69s9-sWzq25x4VwcWRfkZaM-5pObTx3imT/pub


The library modified is MCP_CAN written by coryjfowler and lovee for seed studio. I've made changes in only 3 places, inlined two of the read functions (that only call other read functions with added parameters) and the stuff I showed you here.

Link to MCP_CAN libray:
https://github.com/Seeed-Studio/CAN_BUS_Shield

Really though, since it works with digitalwrite and not with the port referencing macros I feel the problem could be limited to just those lines I listed. But you're free to look through it all if it helps.

aarg

#5
Today at 04:48 pm Last Edit: Today at 04:49 pm by aarg
How can you know that your hardware connections are good? That the code is actually the problem? Have you been able to run the original working sketch on your hardware?
  ... with a transistor and a large sum of money to spend ...
Please don't PM me with technical questions. Post them in the forum.

JPlanck

Yes I have successfully run the program with the current hardware and program. I'm trying to speed it up because it is processing frames so slow that under high load it can drop some.

Robin2

Hey guys, quick question here. I'm using some time sensitive code so one of the methods I've been trying to reduce the code execution time is to reference the port and pin directly instead of using digitalwrite().
There is a digitalWriteFast library which is almost as fast as direct port manipulation and a great deal easier to use. Having just explored it for one of my own projects I suspect there are very few circumstances where it would be worth the trouble to write more directly to the ports.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

JPlanck

How much faster is it?

We're doing nearly full bus load and it's a filter/pass application so every message it receives gets processed twice, leaving about 2500 instructions per frame overhead, including SPI and serial calls.

My own code is fairly optimized to the point that I don't think I could improve it (and I have the compiler set to speed optimize, but others might be able to optimize better than myself), but the library itself is rather slow for a CAN application.

Execution speed is a critical component, and if it's just 3 clock cycles vs the 2 in the macro that would be fine, but I haven't looked into any fastwrite libraries. Do you have a link?

Whandall

Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

JPlanck

Hmm, does that same logic apply to arrays though?

In the program we are "passing" PORTD into a function by placing it into a byte array like:

byte portrefs[2];
portrefs[0] = PORTD;

And then later in the macro we reference it:
#define CLR(x,y) (x&=(~(1<<y)))
#define SET(x,y) (x|=(1<<y))
#define MCP2515_SELECT()   CLR(portrefs[0], portrefs[1])
#define MCP2515_UNSELECT() SET(portrefs[0], portrefs[1])

Since macros are not actually functions I would expect this to work, UNLESS the array storage is causing the same problem a function pass would.

Go Up