Skip to content

Commit

Permalink
Add a configuration option (CONFIG_PULL_UPS in Makefile.common) for
Browse files Browse the repository at this point in the history
building without GPIO pull-up support.  Applications can supply their own.
  • Loading branch information
ga committed Feb 27, 2022
1 parent 3e739ea commit ef0e7a5
Show file tree
Hide file tree
Showing 8 changed files with 37 additions and 3 deletions.
4 changes: 4 additions & 0 deletions Makefile.common
Expand Up @@ -43,6 +43,10 @@ CFLAGS += -O2 -Wall -Wextra -Wno-unused-parameter \
-Wno-unused-result -Wno-missing-field-initializers \
-Wno-sign-compare
CFLAGS += -g
# Add feature defines that are also used throughout.

CFLAGS += -DCONFIG_PULL_UPS=1

CORE_CFLAGS = -DAVR_CORE=1

ifeq (${shell uname}, Darwin)
Expand Down
4 changes: 4 additions & 0 deletions simavr/sim/avr/avr_mcu_section.h
Expand Up @@ -62,7 +62,9 @@ enum {
AVR_MMCU_TAG_VCD_TRACE,
AVR_MMCU_TAG_VCD_PORTPIN,
AVR_MMCU_TAG_VCD_IRQ,
#ifdef CONFIG_PULL_UPS
AVR_MMCU_TAG_PORT_EXTERNAL_PULL,
#endif
};

enum {
Expand Down Expand Up @@ -185,6 +187,7 @@ struct avr_mmcu_vcd_trace_t {
.len = sizeof(void *),\
.what = (void*)_register, \
}
#ifdef CONFIG_PULL_UPS
/*!
* Allows the firmware to hint simavr as to wether there are external
* pullups/down on PORT pins. It helps if the firmware uses "open drain"
Expand All @@ -198,6 +201,7 @@ struct avr_mmcu_vcd_trace_t {
(((unsigned long)((_port)&0xff) << 16) | \
((unsigned long)((_mask)&0xff) << 8) | \
((_val)&0xff)));
#endif
/*!
* Add this port/pin to the VCD file. The syntax uses the name of the
* port as a character, and not a pointer to a register.
Expand Down
6 changes: 6 additions & 0 deletions simavr/sim/avr_ioport.c
Expand Up @@ -70,13 +70,17 @@ avr_ioport_update_irqs(
for (int i = 0; i < 8; i++) {
if (ddr & (1 << i))
avr_raise_irq(p->io.irq + i, (avr->data[p->r_port] >> i) & 1);
#ifdef CONFIG_PULL_UPS
else if (p->external.pull_mask & (1 << i))
avr_raise_irq(p->io.irq + i, (p->external.pull_value >> i) & 1);
else if ((avr->data[p->r_port] >> i) & 1)
avr_raise_irq(p->io.irq + i, 1);
#endif
}
uint8_t pin = (avr->data[p->r_pin] & ~ddr) | (avr->data[p->r_port] & ddr);
#ifdef CONFIG_PULL_UPS
pin = (pin & ~p->external.pull_mask) | p->external.pull_value;
#endif
avr_raise_irq(p->io.irq + IOPORT_IRQ_PIN_ALL, pin);

// if IRQs are registered on the PORT register (for example, VCD dumps) send
Expand Down Expand Up @@ -270,6 +274,7 @@ avr_ioport_ioctl(
*((avr_ioport_state_t*)io_param) = state;
res = 0;
}
#ifdef CONFIG_PULL_UPS
/*
* Set the default IRQ values when pin is set as input
*/
Expand All @@ -279,6 +284,7 @@ avr_ioport_ioctl(
p->external.pull_value = m->value;
res = 0;
}
#endif
}
}

Expand Down
4 changes: 4 additions & 0 deletions simavr/sim/avr_ioport.h
Expand Up @@ -72,6 +72,7 @@ typedef struct avr_ioport_state_t {
// add port name (uppercase) to get the port state
#define AVR_IOCTL_IOPORT_GETSTATE(_name) AVR_IOCTL_DEF('i','o','s',(_name))

#ifdef CONFIG_PULL_UPS
/*
* ioctl used to set default port state when set as input.
*
Expand All @@ -83,6 +84,7 @@ typedef struct avr_ioport_external_t {

// add port name (uppercase) to set default input pin IRQ values
#define AVR_IOCTL_IOPORT_SET_EXTERNAL(_name) AVR_IOCTL_DEF('i','o','p',(_name))
#endif

/**
* pin structure
Expand Down Expand Up @@ -112,6 +114,7 @@ typedef struct avr_ioport_t {
uint8_t mask;
int8_t shift;

#ifdef CONFIG_PULL_UPS
// This represent the default IRQ value when
// the port is set as input.
// If the mask is not set, no output value is sent
Expand All @@ -120,6 +123,7 @@ typedef struct avr_ioport_t {
struct {
uint8_t pull_mask, pull_value;
} external;
#endif
} avr_ioport_t;

void avr_ioport_init(avr_t * avr, avr_ioport_t * port);
Expand Down
4 changes: 4 additions & 0 deletions simavr/sim/sim_elf.c
Expand Up @@ -170,6 +170,7 @@ avr_load_firmware(
memcpy(avr->fuse, firmware->fuse, firmware->fusesize);
if (firmware->lockbits)
avr->lockbits = firmware->lockbits[0];
#ifdef CONFIG_PULL_UPS
// load the default pull up/down values for ports
for (int i = 0; i < 8 && firmware->external_state[i].port; i++) {
avr_ioport_external_t e = {
Expand All @@ -179,6 +180,7 @@ avr_load_firmware(
};
avr_ioctl(avr, AVR_IOCTL_IOPORT_SET_EXTERNAL(e.name), &e);
}
#endif
avr_set_command_register(avr, firmware->command_register_addr);
avr_set_console_register(avr, firmware->console_register_addr);

Expand Down Expand Up @@ -299,6 +301,7 @@ elf_parse_mmcu_section(
firmware->aref =
src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
break;
#ifdef CONFIG_PULL_UPS
case AVR_MMCU_TAG_PORT_EXTERNAL_PULL: {
for (int i = 0; i < 8; i++)
if (!firmware->external_state[i].port) {
Expand All @@ -315,6 +318,7 @@ elf_parse_mmcu_section(
break;
}
} break;
#endif
case AVR_MMCU_TAG_VCD_PORTPIN:
case AVR_MMCU_TAG_VCD_IRQ:
case AVR_MMCU_TAG_VCD_TRACE: {
Expand Down
2 changes: 2 additions & 0 deletions simavr/sim/sim_elf.h
Expand Up @@ -56,10 +56,12 @@ typedef struct elf_firmware_t {
char name[64];
} trace[32];

#ifdef CONFIG_PULL_UPS
struct {
char port;
uint8_t mask, value;
} external_state[8];
#endif

// register to listen to for commands from the firmware
uint16_t command_register_addr;
Expand Down
2 changes: 1 addition & 1 deletion tests/atmega168_ioport.c
Expand Up @@ -66,7 +66,7 @@ int main()

/* This should say P<70 - pullups and direct output give 0xF0
* but the caller sees that and turns off bit 7 input,
* overriding that pullup.
* overriding that pullup. With pullups disabled: P<30.
*/

printf("P<%02X ", PIND);
Expand Down
14 changes: 12 additions & 2 deletions tests/test_atmega168_ioport.c
Expand Up @@ -92,15 +92,25 @@ static void reg_read(struct avr_irq_t *irq, uint32_t value, void *param)
/* This string should be sent by the firmware. */

static const char *expected =
#ifdef CONFIG_PULL_UPS
"P<2A P<70 F<01 I<E0 P<E0 J<03 J<00 P<E8 | K | ";
#else
"P<2A P<30 F<01 I<20 P<20 J<03 J<00 P<28 | K | ";
#endif

/* This string is expected in variable log. */

static const char *log_expected =
"d-0F P-00 o-0A P-0A I-0A 5-01 o-09 P-29 d-3C 5-00 P-09 o-F0 5-01 P-F0 "
"I-70 " // Interrupts off testing.
"d-0F P-00 o-0A P-0A I-0A 5-01 o-09 P-29 d-3C 5-00 P-09 o-F0 5-01 "
#ifdef CONFIG_PULL_UPS
"P-F0 I-70 " // Interrupts off testing.
"o-E0 P-E0 I-E0 I-E0 " // External interrupt test.
"d-03 o-01 P-E1 o-03 P-E3 o-00 P-E8 I-E8 "; // Pin change interrupt test.
#else
"P-30 I-30 " // Interrupts off testing.
"o-E0 P-20 I-20 I-20 " // External interrupt test.
"d-03 o-01 P-21 o-03 P-23 o-00 P-28 I-28 "; // Pin change interrupt test.
#endif


int main(int argc, char **argv) {
Expand Down

0 comments on commit ef0e7a5

Please sign in to comment.