Change DDR/PORT order and add comment about intermediate state

main
Michael Hayes 13 years ago
parent 4222d1eeac
commit cd2e6f4460

@ -36,6 +36,47 @@
#include <avr/io.h>
#endif
/** AVR microcontrollers use two flip-flops per PIO stored in two
separate registers: the data direction register (DDRx) and the
port register (PORTx). The DDRx register controls the whether the
pin is an input or an output; the PORTx register determines the
output state when the pin is an output but also doubles as an
enable for a pull-up resistor when the pin is an input.
Mode: DDRx PORTx
Input, no pull-up 0 0
Input, pull-up 0 1
Output, low 1 0
Output, high 1 1
These two registers cannot be changed at the same time so a
transient intermediate state can occur if both these registers
need to be changed. This is only a concern for pins that need to
switched between being an input and an output; say for a
bidirectional communication link.
Let's consider the scenario where we change DDRx before PORTx.
If we want to reconfigure a PIO from an input with no pull-up to a
high output it will be momentarily a low output.
If we want to reconfigure a PIO from an input with pull-up to a
low output it will be momentarily a high output.
Let's consider the alternative scenario where we change DDRx after PORTx.
If we want to reconfigure a PIO from an input with no pull-up to a
high output it will be momentarily an input with a pull-up. This
is not a bad option since a high-impedance load will not notice.
If we want to reconfigure a PIO from an input with pull-up to a
low output it will be momentarily an input with no-pullup.
p.s. I am sure this subtle quirk has caused much grief to some
embedded systems engineers.
*/
/** Define port names; note not all the ports are available on some AVRs. */
@ -58,7 +99,7 @@ typedef enum pio_config_enum
#ifdef DEBUG
/* Define a PIO as a structure in terms of a port and a bit. */
/* Define PIO as a unique integer. */
#define PIO_DEFINE(PORT, PORTBIT) ((PORT) * 8 + (PORTBIT))
@ -164,13 +205,13 @@ bool pio_config_set (pio_t pio, pio_config_t config)
switch (config)
{
case PIO_OUTPUT_LOW:
PIO_DATA_ (pio) &= ~PIO_BITMASK_ (pio);
PIO_DDR_ (pio) |= PIO_BITMASK_ (pio);
PIO_DATA_ (pio) &= ~PIO_BITMASK_ (pio);
return 1;
case PIO_OUTPUT_HIGH:
PIO_DATA_ (pio) |= PIO_BITMASK_ (pio);
PIO_DDR_ (pio) |= PIO_BITMASK_ (pio);
PIO_DATA_ (pio) |= PIO_BITMASK_ (pio);
return 1;
case PIO_INPUT:
@ -265,7 +306,7 @@ bool pio_output_get (pio_t pio)
/** Set pio to desired state.
@param pio
@param state value to write pio */
@param state value to write to pio */
static inline
void pio_output_set (pio_t pio, bool state)
{

Loading…
Cancel
Save