Open djfd opened 5 years ago
This could potentially solve without introducing any external variable hacks: https://github.com/piopawlu/simavr/commit/32112e8f86e1df551d0e3968fbc116f9bda0268d
I've got that trouble today. I decided this using ioctl
avr_ioport.h
#define AVR_IOCTL_IOPORT_GET_EXTERNAL(_name) AVR_IOCTL_DEF('i','o','e',(_name))
avr_ioport.c
/*
* Get the default IRQ values when pin is set as input
*/
if (ctl == AVR_IOCTL_IOPORT_GET_EXTERNAL(p->name)) {
avr_ioport_external_t * m = (avr_ioport_external_t*)io_param;
m->mask = p->external.pull_mask;
m->value = p->external.pull_value;
res = 0;
}
My code with buttons connected to GND:
static void ButtonSet_SetStimul(const uint8_t pButton, const bool pPressed)
{
avr_ioport_external_t ext;
avr_ioctl(MCU, AVR_IOCTL_IOPORT_GET_EXTERNAL(ButtonSet.Port[pButton].Name), &ext);
ext.mask |= (1 << ButtonSet.Port[pButton].Pin);
if(pPressed)
ext.value &= ~(1 << ButtonSet.Port[pButton].Pin);
else
ext.value |= (1 << ButtonSet.Port[pButton].Pin);
avr_ioctl(MCU, AVR_IOCTL_IOPORT_SET_EXTERNAL(ButtonSet.Port[pButton].Name), &ext);
}
static void ButtonSet_Press(const uint8_t pButton)
{
ButtonSet_SetStimul(pButton, true);
avr_raise_irq(&ButtonSet.IRQ[pButton], 0);
}
static void ButtonSet_Release(const uint8_t pButton)
{
ButtonSet_SetStimul(pButton, false);
avr_raise_irq(&ButtonSet.IRQ[pButton], 1);
}
Hi,
the situation. A port has some pins assigned as outputs, and some as inputs. Inputs have their associated pin-change interrupts enabled. So when setting just a single output pin with
we expect to (e.g. see
at-tiny-24
reference guide 12.1 IO Ports Overview, p.49):But actually, current implementation is going to update all IRQs for all port pins (even if we are changing the single one only) causing pin change interrupts occurrence for every input pin.
There is backtrace:
#0 avr_ioport_irq_notify (irq=0x55555555ae20, value=1, param=0x555555561400)
at sim/avr_ioport.c:158#1 0x00007ffff7ebb272 in avr_raise_irq_float (irq=0x55555555ae20, value=1, floating=0)
at sim/sim_irq.c:214#2 0x00007ffff7ebb303 in avr_raise_irq (irq=0x55555555ae20, value=1)
at sim/sim_irq.c:232#3 0x00007ffff7ecfc1e in avr_ioport_update_irqs (p=0x555555561400)
at sim/avr_ioport.c:61#4 0x00007ffff7ecfe36 in avr_ioport_write (avr=0x55555555cfa0, addr=59, v=195 '\303', param=0x555555561400)
at sim/avr_ioport.c:89#5 0x00007ffff7ebd020 in _avr_set_r (avr=0x55555555cfa0, r=59, v=195 '\303')
at sim/sim_core.c:196#6 0x00007ffff7ebd273 in _avr_set_ram (avr=0x55555555cfa0, addr=59, v=195 '\303')
at sim/sim_core.c:247#7 0x00007ffff7ec0a6c in avr_run_one (avr=0x55555555cfa0)
at sim/sim_core.c:1266Particularly, check the frames #7, #3. We are handling the only pin (frame 7), but iterating through all register bits (frame 3) causing the interrupts for every pin configured as input.
Their vars:
ie. we are handling bit 5, but
triggering pin change interrupt for pin6
Thanks
UPD As a workaround, until proper solution is found, I use this patch which did the trick for my usecase