irq_set_enabled() and irq_set_mask_enabled() are exactly the same thing - except irq_set_enabled() takes an interrupt number (just one) while irq_set_mask_enabled() takes a bitmap and so can enable multiple at the same time in the rare case that is useful. So irq_set_enabled(FOO, true) is identical to irq_set_mask_enabled(1<<FOO, true). These are setting the enable in the NVIC, within a given CPU core.Code:
gpio_add_raw_irq_handler_masked() Adds a raw GPIO IRQ handler for the specified GPIOs on the current core.irq_set_mask_enabled () Enable/disable multiple interrupts on the executing core.irq_set_enabled(IO_IRQ_BANK0, true); Enable or disable a specific interrupt on the executing core.gpio_set_irq_enabled() This function sets which GPIO events cause a GPIO interrupt on the calling core.
gpio_set_irq_enabled() is setting the enable from the peripheral towards the CPU cores. The SDK is actually hiding some detail from you here: as mentioned above, there's two sets of enables in the peripheral and so you'd either expect an extra parameter to say which one, or two different functions, but because the two IRQs are each dedicated to an individual core the SDK assumes that you want to set the one that will generate interrupts to your current core. That's not an unreasonable assumption: since you absolutely have to do the NVIC initialisation on the core that will receive the interrupts, forcing you to do this initialisation there as well is OK.
gpio_add_raw_irq_handler() is actually just a shim over irq_add_shared_handler(IO_IRQ_BANK0, your_handler_fn) with some checking that you haven't registered more than one for the same GPIO number. This is compared to the gpio_set_irq_callback() which does all the demultiplexing of multiple pin interrupts for you, or irq_add_exclusive_handler(IO_IRQ_BANK0, your_handler_fn) where you get all the interrupts in one handler and have to do everything yourself. So with the _raw_ option you can have multiple handlers, but they each (might) get called for interrupts pertaining to a different GPIO pin and so need to check if their intended interrupt is actually active before doing any processing.
irq_add_exclusive_handler() is inserting the address of your handler into the interrupt vector table. This table is in RAM, and each core's NVIC has a pointer to it; so the vector table can in principle be shared between cores (both NVICs point at the same table), or separate per-core. I believe the Pico SDK sets up for one shared table - on the basis that each interrupt will normally only be enabled on one core and so there's no point in having two tables (however, that logic seems suspect for the GPIO vector).
This was my suggestion for how to do interrupts from one core to the other without using the inter-core FIFO (so not normally recommended, but maybe worthwhile here as one plausible explanation for the trouble you are having is that the Arduino framework you started from may already be using the FIFO for other purposes).Thanks. Could you give me specific code or register names?then on one core you enable that interrupt (in the peripheral's interrupt enable register) and on the other core you clear the enable in your interrupt handler - using hw_set_bits()/hw_clr_bits()
So the idea is to pick some interrupt that isn't otherwise in use, force it permanently active in the peripheral, enable it in the NVIC on the target core, and then enable it in the peripheral (from the 'causing' core) and disable it again in the peripheral in the interrupt handler in place of acknowledging it.
Now we could use the GPIO interrupt for this, but it's a bit non-standard, and it's quite likely that you will want to service real hardware GPIO interrupts as well, which would make things much more complex. So lets's pick TIMER_IRQ_3 instead.
One-time initialisation to get the interrupt active in the peripheral (execute on either core)
Code:
hw_set_bits(timer_hw->intf, (1<<3));// bit3 means timer interrupt 3
Code:
irq_set_exclusive_handler(TIMER_IRQ_3, my_handler_fn);irq_set_enabled(TIMER_IRQ_3, true);
Code:
hw_set_bits(timer_hw->inte, (1<<3));
Code:
hw_clear_bits(timer_hw->inte, (1<<3));
Statistics: Posted by arg001 — Sat Aug 10, 2024 7:08 pm