16
\$\begingroup\$

I have a full time job as a firmware engineer. I've recently been given a task to review GPIO configurations and change the settings as needed. I found a few pins that were incorrectly configured so naturally I reconfigured them, however I was told I did it in the wrong order. Here is what I'm talking about:

Before:
GPIO1.direction = INPUT;

After:
GPIO1.direction = OUTPUT;
GPIO1.value = 0;

However during the code review I've been told that I need to change the order of initialization to the following:

GPIO1.value = 0;
GPIO1.direction = OUTPUT;

In other words set the value first and then set direction of the pin. I've also been told that this is how it needs to be on the modern processors because they use two registers, one for input and one for output, however old processors use only one register, so the order of operations wouldn't matter.
(Note: Modern = ARM Cortex M3 and above, Old = Intel 8051)

I asked for a better explanation at work, but I couldn't get a good answer. That's why I decided to ask here.

So here are my questions:

  1. Why does the order of initialization matter on the new processors?
  2. Why does the order of initialization not matter on the old processors?
  3. What two registers are they talking about in the modern processors?
  4. What single register are they talking about on the old processors?

If someone could provide some sort of a diagram, that would be even better.

\$\endgroup\$
  • 1
    \$\begingroup\$ "Modern" and "Old" processors is far too vague to give a useful answer to. Different architectures have different register settings; without knowing which ones you're talking about there's no way to intelligently comment on them. \$\endgroup\$ – Nick Johnson Jul 16 '15 at 15:48
  • \$\begingroup\$ @IgnacioVazquez-Abrams No, not really. There were very experienced engineers in the room who said that you will have glitches on the line if it is done my way. \$\endgroup\$ – flashburn Jul 16 '15 at 15:49
  • \$\begingroup\$ @NickJohnson Modern = ARM Cortex M4 and above, Old = Intel 8051. \$\endgroup\$ – flashburn Jul 16 '15 at 15:50
  • \$\begingroup\$ @BrianDrummond LOL. Very nice explanation. But what about the old processors, 8051 for example. Why this doesn't matter for them? \$\endgroup\$ – flashburn Jul 16 '15 at 15:57
  • 2
    \$\begingroup\$ Q4 would be easier to answer with a datasheet link. \$\endgroup\$ – pjc50 Jul 16 '15 at 15:59
22
\$\begingroup\$

The original 8051 used so-called pseudo-bidirectional output ports (open-drain with pullups), so there was really no port direction setting.

Of course for modern true bidirectional output ports it's better to have a known value set before enabling the port pin for output, because otherwise you could have a transient on the output that could do something undesirable.

See my answer here, for example.

Edit: Here is the I/O pin structure for a (relatively) modern CMOS microcontroller:

enter image description here

TRIS (TRIState) is called DDR (Data Direction Register) in many other micros. In this case, if the TRIS latch output is high then both transistors are 'off', but the port can still be read.

Here is a slightly more complex I/O pin structure for a newer Microchip micro.

enter image description here

Again, the TRIS latch disables the output. This one includes a LAT latch that helps avoid read-modify-write issues. On the PIC series you should write to the LAT register only (and read from the PORT register).

Here is the original 8051 and CMOS 8051 classic I/O port pin internal circuitry (from this source):

enter image description here

There's a bit of extra complexity in that there is a speed-up transistor in parallel with the pull-up that is briefly turned on to overcome external capacitance. As you can see, there is no TRIS/DDR control at all. The pull-up MOSFETs used in normal operation are 'weak'- they are small enough (low Idss) that an external output connected to the pin can pull the pseudo-bidirectional port line low.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the explanation. I haven't worked with hardware in a while so I have hard time understanding the explanation from a description. Would you mind providing images? Say how would a pin configuration hardware would look on a modern processor vs how it looks on 8051? I would really appreciate it. \$\endgroup\$ – flashburn Jul 16 '15 at 16:07
  • \$\begingroup\$ What do you mean by hardware? The internal GPIO circuitry of the chip? \$\endgroup\$ – Spehro Pefhany Jul 16 '15 at 16:08
  • \$\begingroup\$ That's correct. Some sort of diagram would be really helpful. \$\endgroup\$ – flashburn Jul 16 '15 at 16:08
16
\$\begingroup\$

If you set the direction first, the pin will briefly be configured to output whatever its current output value is. If you set the value first, this won't happen.

So, doing it the way you've been recommended avoids glitches on the output, which could range from harmless to catastrophic, depending on what the pin is connected to.

\$\endgroup\$
  • \$\begingroup\$ Thanks. So what about the old processors, why this doesn't matter for them? Old = Intel 8051 \$\endgroup\$ – flashburn Jul 16 '15 at 15:52
  • \$\begingroup\$ I'm not familiar with the 8051. Based on what your colleagues said, if the same register configures both direction and value, it won't matter because the compiler will optimize the two writes into one. \$\endgroup\$ – Nick Johnson Jul 16 '15 at 15:54
  • 2
    \$\begingroup\$ it would probably still be a good habit to do it this "new" way for old processors also for reason above. Different orocessors may have different requirements, different vendors may give better suggestion than others,and different companies/employers/teams may have different policies about such details. \$\endgroup\$ – billt Jul 16 '15 at 16:02
  • 2
    \$\begingroup\$ indeed... always assume the DIO is connected to the orbiting laser of doom ;) \$\endgroup\$ – Michael Jul 16 '15 at 18:45
4
\$\begingroup\$

Assuming the default direction is an input (i.e. High-Z, which is making sense as we don't want the MCU to force any value on the lines connected), this order of setting up the port is preferable but not necessary. It is in fact necessary when your application requires that on the startup the value of the port won't be, say 1. Then you will set the value to 0 and then change the direction. In this case you avoid the possible momentary "glitch" between the setting the direction and the value, which might result in a spike on that pin. And it is true for all of the processors having such a logic, not only the new ones.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.