grisp / grisp-software

Toolchain and Examples for GRISP
28 stars 5 forks source link

Usage of PIO_ConfigureIt() leads to wpa_supplicant not starting #35

Closed holzingk closed 5 years ago

holzingk commented 6 years ago

In my application I try to register an interrupt. As soon as I use the function PIO_ConfigureIt() wpa_supplicant fails to start, even when the function is not called at all. So I guess that something is linked automaticly which interferes with wpa_supplicant.

Boot output looks as follows:


mkdir /tmp
mkdir /tmp/log
mkdir /home
err: Setting environment
nchdir(/media/mmcsd-0-0/)
o
erl_main: starting ...
 getcwd: /media/mmcsd-0-0
vhostname: grispapp
astarting erlang runtime
lid interfaces found
warning: no interfaces have a carrier
uhub0: 2 ports with 2 removable, self powered
Successfully initialized wpa_supplicant
ugen0.2: <Philips Semiconductors ISP1520> at usbus0
uhub1 on uhub0
uhub1: <Philips Semiconductors ISP1520, class 9/0, rev 2.00/0.00, addr 2> on usbus0
uhub1: 3 ports with 3 removable, self powered
ugen0.3: <vendor 0x0bda product 0x8176> at usbus0
rtwn0: <vendor 0x0bda product 0x8176, class 0/0, rev 2.00/2.00, addr 3> on usbus0
rtwn0: MAC/BB RTL8188CUS, RF 6052 1T1R
wlan0: Failed to initialize driver interface
wpa_supplicant returned with -1
Successfully initialized wpa_supplicant
wlan0: Failed to initialize driver interface
wpa_supplicant returned with -1
Successfully initialized wpa_supplicant
wlan0: Failed to initialize driver interface
wpa_supplicant returned with -1
Successfully initialized wpa_supplicant```
c-mauderer commented 6 years ago

Which interrupt did you try to register? Could you post the code snipped where PIO_ConfigureIt(...) is called? About when is the call done?

Background of the questions is the following: Currently the USB controller driver assumes that it has the port interrupt for itself (for performance reasons). If your registered pin is in the same bank as the USB interrupt pin, that could lead to the given problem.

sebhub commented 6 years ago

The module defining PIO_ConfigureIt() contains a system initialization item which calls PIO_SysInitializeInterrupts() during system initialization. It installs some RTEMS_INTERRUPT_UNIQUE interrupt handlers. Maybe this causes the problem. The pio_it.c should be changed to be a bit less greedy.

holzingk commented 6 years ago

I use PIO_ConfigureIt(triggerpin, &grisp_ir_handle, data);

triggerpin is a pointer to: {PIO_PC12, PIOC, ID_PIOC, PIO_INPUT, PIO_IT_FALL_EDGE}

I am writing an Erlang driver to notify Erlang about pin interrupts and I use the function in the start function. The call is not done at all, as the driver is not even started from the Erlang side. The problem occurs with lone presence of the function, so I guess it has to do with linking, and some automatic initialisation as @sebhub pointed out.

c-mauderer commented 6 years ago

Yes. The initialization that Sebastian mentioned seems more likely. In pio_it.c a RTEMS_INTERRUPT_UNIQUE is installed for all port interrupts. That will interfere with the rtems_interrupt_handler_install that is used in a (quite deeply nested) call during the USB-controller initialization here: https://github.com/grisp/rtems-libbsd/blob/grisp/freebsd/sys/dev/usb/controller/saf1761_otg_fdt.c#L246

I think there are two to three possible solutions to that:

  1. Adapting SAF1761 driver so that it uses the BSPs PIO_ConfigureIt mechanic. That will have an performance impact on all USB (and therefore WiFi) communication. But it will have the advantage that the PIO_ConfigureIt is usable for other pins on the same port (relevant ones should be JUMPER5, DIO1/AN1 (connector GPIO1), DIO2/AN2 (connector GPIO1), JUMPER3)
  2. Somehow disable the interrupt handler on PIOC and keep that interrupt exclusive for the USB. That offers a higher performance for USB but will prevent any interrupts on the listed pins. For example we could add a rtems_interrupt_handler_remove for that interrupt before the libbsd initialization.
  3. Some other ideas?
holzingk commented 6 years ago

In my case I need hardware interrupts on GPIO pins, which are scattered on PIO controllers A, C and D. So option 2. is ok for me, I just cannot have interrupts on all pins then, but I don't need that for my use case anyways.

Option 1 seems more elegant, but I cannot predict performance impact.

peerst commented 6 years ago

I'd go for Option 2 now, would be nice if trying to register a interrupt on PIOC results in a fatal error with some discernable message like "no interrupt allowed on PORTC pins"

c-mauderer commented 6 years ago

I have some other (pressing) work in the next few days so I can't guarantee when I'll find time to take a look at that.

In case you need something to try: My first idea for a workaround would be along the following line: Before the initialization of libbsd:

Basically that would mean something like that (untested):

static void dummy_isr(void *arg)
{
    /* do nothing */    
    (void) arg;
}
static void workarround_function(void)
{
    sc = rtems_interrupt_handler_install(
        PIOC_IRQn,
        "PIO C",
        RTEMS_INTERRUPT_UNIQUE | RTEMS_INTERRUPT_REPLACE,
        dummy_isr,
        NULL
    );
    assert(sc == RTEMS_SUCCESSFUL);
    sc = rtems_interrupt_handler_remove(
        PIOC_IRQn,
        dummy_isr,
        NULL
    );
    assert(sc == RTEMS_SUCCESSFUL);
}
holzingk commented 5 years ago

Thank you @c-mauderer . The mentioned workaround worked fine in my application.

Unfortunately my generic interrupt driver still is not in a state to be merged into the grisp repository.