-
Notifications
You must be signed in to change notification settings - Fork 971
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unable to disable FIFO_IRQ_PROC0 #284
Comments
I've not tried this myself, but from a quick look at the datasheet it seems you need to write to NVIC ICER to disable the interrupt? (ISER is the enable register; although I dunno why re-enabling an interrupt should cause a hard fault?) EDIT: And section 2.3.1.4. of the datasheet says you can read FIFO_ST to see the reason the interrupt was fired. |
I did try disabling it by writing the ICER register. I cleared the pending register, wrote 1 << 15 to ICER and then read the pending register again. It was still signaling the interrupt.
I did this, the register returns 0b11, meaging that the RDY and VLD are set. Reading the FIFO_RD register still does not clear the interrupt. I tried reding it 100 times, once every time the interrupt fired, and always got 0. |
Sorry, from your original message it sounded like you were trying to disable the interrupt by writing to NVIC::ISER, apologies if I misunderstood. Well I'm afraid that's as far as my knowledge goes, so you'll have to wait for @kilograham or @Wren6991 to provide further assistance 🙂 |
You need to clear the status register by writing say 0xF to the register; this will clear the IRQ. I am suprised that emptying the FIFO does not clear the IRQ - will have to dig deeper on that, although it may be for consistency with other peripherals which all clear IRQs explicitly. Note, that yes, core 1 (edited) startup does write a 0 to the FIFO, so there will always be an IRQ pending on core 0. It seems like you are turning on the interrupt without actually means to use it which seems odd, but there you go. |
From what I understand from the datasheet, shouldn't core0 writing to the FIFO trigger core1's IRQ, i.e. 16? EDIT:
The datasheet claims that the FIFO_ST |
yes i meant core 1 sorry ... edited |
I tried this now, the interrupt still fires.
I don't think I turned on the interrupt. How would I do that? How can I disable it (other then from NVIC). I still don't understand why it faults when I try to write 1<<15 to ISER to unmask it. |
@kilograham There seems to be slight mismatch between what pico-examples / pico-sdk are doing, and what the RP2040 datasheet says? Or perhaps I'm just misunderstanding things? (the latter is probably the most likely scenario!) The IRQ-handlers in https://github.com/raspberrypi/pico-examples/blob/master/multicore/multicore_fifo_irqs/multicore_fifo_irqs.c#L24 use So (to me) it seems like what P.S. The doxygen comment for
I suspect that by "turn on" Graham meant the same thing you're referring to as "unmask"? Also, perhaps it's worth playing with https://github.com/raspberrypi/pico-examples/tree/master/multicore/multicore_fifo_irqs to see if that helps you see where your own code is going wrong? |
Now its getting even stranger. Now I start getting also IRQ 16. Shouldn't this fire only for the second core? Now only RDY is set, so based on the datasheet the interrupt should not fire, no? I am still not able to disable the interrupts (15 and 16). |
I did some further testing and it seems that actually while the interrupt is in fact disable, I am not able to clear the pending bit. I am running the following lines in the /**
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "pico/stdlib.h"
#include "pico/multicore.h"
#include "hardware/irq.h"
const uint LED_PIN = 25;
#pragma GCC push_options
#pragma GCC optimize ("O0")
static void led (void) {
gpio_put (LED_PIN, 1);
}
static void led2 (void) {
panic ("led 2");
}
#pragma GCC push_options
#pragma GCC optimize ("O0")
int main() {
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
volatile unsigned int *icpr = (unsigned int*)(0xe000e280);
volatile unsigned int icpr_value = *icpr;
*icpr = (unsigned int)(1 <<15);
icpr_value = *(unsigned int*)(0xe000e280);
led ();
panic ("");
// irq_set_exclusive_handler(SIO_IRQ_PROC0, led);
// irq_set_exclusive_handler(SIO_IRQ_PROC1, led2);
// irq_set_enabled (SIO_IRQ_PROC0, true);
// irq_set_enabled (SIO_IRQ_PROC1, true);
while (true) {
// gpio_put(LED_PIN, 1);
// sleep_ms(250);
// gpio_put(LED_PIN, 0);
// sleep_ms(250);
}
} After executing this, gdb shows the disassembly: 0x1000037a <+10>: bl 0x100003dc <gpio_init>
0x1000037e <+14>: movs r3, #25
0x10000380 <+16>: movs r1, #1
0x10000382 <+18>: movs r0, r3
0x10000384 <+20>: bl 0x100003c8 <gpio_set_dir>
0x10000388 <+24>: ldr r3, [pc, #32] ; (0x100003ac <main+60>)
0x1000038a <+26>: str r3, [r7, #4]
0x1000038c <+28>: ldr r3, [r7, #4]
0x1000038e <+30>: ldr r3, [r3, #0]
0x10000390 <+32>: str r3, [r7, #0]
0x10000392 <+34>: ldr r3, [r7, #4]
0x10000394 <+36>: movs r2, #128 ; 0x80
--Type <RET> for more, q to quit, c to continue without paging--
0x10000396 <+38>: lsls r2, r2, #8
=> 0x10000398 <+40>: str r2, [r3, #0]
0x1000039a <+42>: ldr r3, [pc, #16] ; (0x100003ac <main+60>)
0x1000039c <+44>: ldr r3, [r3, #0]
0x1000039e <+46>: str r3, [r7, #0]
0x100003a0 <+48>: bl 0x1000035c <led>
0x100003a4 <+52>: ldr r3, [pc, #8] ; (0x100003b0 <main+64>)
0x100003a6 <+54>: movs r0, r3
0x100003a8 <+56>: bl 0x10000464 <panic>
0x100003ac <+60>: b.n 0x100008b0 <stdio_put_string+12>
0x100003ae <+62>: b.n 0x100003b2 <main+66>
0x100003b0 <+64>: lsrs r0, r6, #10
0x100003b2 <+66>: asrs r0, r0, #32
End of assembler dump.
(gdb)
(gdb) p/t $r2
$12 = 1000000000000000
(gdb) p/x $r3
$13 = 0xe000e280
(gdb) si
0x1000039a in main ()
(gdb) si
0x1000039c in main ()
(gdb) p/x $r3
$14 = 0xe000e280
(gdb) si
0x1000039e in main ()
(gdb) p/x $r3
$15 = 0x18040
(gdb) p/t $r3
$16 = 11000000001000000 If my code is correct, this should be the value of the icpr register. It does not seem to clear the pending bit. Is it possible that I am overlooking something? EDIT: clearing IRQ 6 works (writing 1 << 6) |
All interrupts get routed to both cores. As it notes in the RP2040 datasheet: "Typically Core 0 will use IRQ15 and core 1 will use IRQ16. If the IRQs are used the other way round then it is difficult for the core that has been interrupted to correctly identify the reason for the interrupt as the core doesn’t have access to the other core’s FIFO status register." Also, you could probably get rid of some of those "ugly" hardcoded values in your code by using constants from "hardware/regs/m0plus.h" https://github.com/raspberrypi/pico-sdk/blob/develop/src/rp2040/hardware_regs/include/hardware/regs/m0plus.h But I can't comment further on your code as I'm starting to get out of my depth 😉 (Is it possible that the pending bit is still active because the interrupt has re-fired?. I'm probably not understanding what you're trying to do, but why do you care about the pending bits 15 and 16 being set if those interrupts are masked, which (I think) means that they'll not actually trigger an interrupt-handler?) @kilograham On a sidenote I see that there's no hardware_structs middle-layer between the low-level hardware_regs and the higher-level hardware_irq lib. For consistency with the rest of pico-sdk, should there be? 🤷♂️ |
I figured that this might be the problem.
Tock, the OS that I am trying to port, is written in Rust, meaning I cannot use the SDK header files. The C example is just for testing purposes, I wanted to make sure that my code is not doing something wrong, so I tested using the SDK.
Tock uses bottom-half handlers for interrupts, meaning that interrupts fire, they are flagged as pending in the interrupt handler and will be actually handled a little later in the kernel context. After the interrupt handler returns, the kernel checks the pending interrupts and executes the handlers. You are correct, the interrupt never fires as it is disabled, but the ICSR register cannot clear the pending status and this makes the kernel execute the handlers continuously. EDIT: I did some more experimenting and found out the following:
My understanding is that for processor 0 I should ignore IRQ 16. Is this right?
|
Can't you just ignore pending-interrupts in your interrupt-handler / kernel, when you know those interrupts haven't been enabled?
The way I understand it (which as I've mentioned before, may well be wrong!), is that when you set bit 16 in the ICPR register it does clear the pending interrupt, but because the "actual interrupt" (i.e. the VLD bit in core1's FIFO_ST) is still active, the interrupt immediately re-fires again. If you really wanted to clear IRQ16 I think the only way to do that would be drain core1's FIFO_RD (which you can only do from core1 itself). |
This is what I did.
This makes sense, thank you. |
i think this can be closed, no? |
Based on my observations in raspberrypi#284
Yes, I think so. |
See release notes for more descriptive details * Delete some redundant CMake parts (#240) * pio: Add 'pragma once' to generated header files (#237) * pio: allow programs with 32 instructions (#236) * Fixup incorrect doxygen for multicore_fifo_wready * Add param-validation to spin_lock_instance * Fix back-to-front description of IRQ priority in doxygen (#245) * Fix ROSC typo (#259) * Typo (#251) * Add gpio_get_out_level() accessor, and correct SIO GPIO_OUT struct ty… (#247) * Add gpio_get_out_level() accessor, and correct SIO GPIO_OUT struct type from WO to RW * Add pico_get_unique_board_id_string API (#281) * Clean up -Wconversion=error issues * move PLL reset code from clocks driver to pll driver (#110) * Don't clear PLL PWR/FBDIV after reset as unnecessary. Call out in runtime.c why USB/syscfg aren't reset. * i2c: set hold time of SDA during transmit to an appropriate value (#273) * i2c: set hold time of SDA during transmit to 2 for TCS34725 color sensor * i2c: fix issues in i2c_write_blocking_internal * i2c: rename sda_hold_count to sda_tx_hold_count * use assert rather than invalid_params_if for internal consistency checks * i2c: use a more appropriate sda tx hold time at higher baudrates * i2c: reduce 120/1e9 to the smallest possible integer numerator and denominator * Update NULL GPIO function to 0x1f (#320) * i2c: set high and low times to values that conform to the i2c specification (#314) * Make flash_do_cmd public (#269) * Fix implementation config listing in structs/i2c.h (#324) * Clarify that cache is flushed, but that function is intended for low-level metadata access during startup (#322) * Fix implementation config listing in structs/i2c.h (#325) * Fix param-validation for PIO sideset encoding (#311) * Remove MASTER_ON_HOLD bit from I2C status registers. Fix typos. (#326) * Fixing arithmetic underflow in SPI I/O loops #337 (#338) * Source code licence clarification (#340) * Updated existing Pimoroni board headers to match latest style, and added a new board (#343) * Added new pimoroni board headers * SPI Definitions for SparkFun boards (#344) * SPI Definitions for SparkFun boards * Clarify multicore_fifo doxygen (#323) Based on my observations in #284 * correct adafruit flash size for itsybitsy and qt rp2040 (#348) from 4 MB to 8 MB * Small typos (#366) * make spi_init return baud rate set (#296) * Fix path + typo in README.md (#347) * Fix path + typo in README.md * Remove incorrect path change * Remove typo * disable core 0 SIO FIFO IRQ handler during core 1 launch in case someone has already installed one (#375) * add PICO_DIVIDER_DISABLE_INTERRUPTS flag which makes PICO_DIVIDER disable interrupts around division rather than using co-operative guards to protect nested use (i.e. within IRQ/exception). Use of this flag can simplify porting of RTOSes but with a different performance profile (#372) * make all non hardware_ libraries foo add C preprocessor definition LIB_FOO=1, and remove bespoke definitions which were all undocumented anyway (#374) * Change various (confusing to user) message to be DEBUG only (#365) * add small delay to stdio_get_until to prevent starvation of USB IRQ handler due to in use mutex. build was non deterministic due to missing link wrapping of getchar (#364) * Some cmake build improvements (#376) * Change some cmake output to DEBUG level Make SDK build more consistent with other libraries (use an INTERFACE marker library for inclusion tests) Add PICO_SDK_PRE_LIST_FILES, PICO_SDK_POST_LIST_FILES build vars * fix typo * remove leftover debugging message * i2c: improve communication with i2c devices in i2c_write_blocking * Definitions for IC_TX_BUFFER_DEPTH inconsistent (fixes #335) (#381) * Add hardware_exception for setting exception handlers at runtime (#380) * add __always_inline to trivial super low level inline functions (#379) * Rework lock_core / timers (#378) * remove spurious sys/select.h include (#377) * Fixup IRQ_PRIORITY #define values (#393) * Correct doxygen for mutex_try_enter (#392) * Fix a bunch of doxygen typos (#391) * Rework ordering of cmake, so that libraries in subdirectories can add to internal lists as PICO_SDK_POST_LIST_FILES, PICO_CONFIG_HEADER_FILES etc. (#382) * Fix some hardware_library dependencies (#383) * make host pico_platform.h and binary_info.h CMakeLists.txt safe for inclusion in non SDK build (#388) * Add basic CMSIS core headers (#384) * Fix the PICO_CONFIG default value for PICO_CMSIS_RENAME_EXCEPTIONS (#399) * add timeout_us/until to mutex/sem blocking methods (#402) * Fixup divider save_restore for floating point too; improve tests (#405) * fix pico_promote_common_scope_vars (#397) * add comment about using clk_gpout0 enable bit (Fixes #413) * pioasm: prevent double inclusion for C SDK generated headers (#417) * Add missing cast to uint32_t in hw_divider_u32_quotient for host (#436) * Optional feature to get the max level that has ever been held by a queue (#444) * Fix wrong format string in alarm_pool_dump_key (#437) * Add support for Arduino Nano RP2040 Connect (#425) * Add support for Arduino Nano RP2040 Connect * Add support for at25sf128a flash * Fix function-name misspelling (#443) * Update host multicore.h to match multicore.h in rp2_common (#439) * Implement `uart_write_blocking` and `uart_read_blocking` for host (#438) * Define `__STRING` for other compilers than MSVC in the host platform.h file (#434) * Prevent warnings about some unused parameters in pico_stdio_usb when building with -Wextra (#431) * Fix warnings about some unused parameters in pico_stdio_usb * Use `__unused` for the unused parameter in tud_descriptor_configuration_cb * Remove redundant inclusions of `pico/platform.h` * Define `void operator delete[](void *p, std::size_t n)` in new_delete.cpp (#430) * queue: make data pointers const in queue_try_add and queue_add_blocking (#423) * misc interp_ fixes (#428) * some typo fixes (#408) * Prevent the literal string DEBUG from being appended to some messages in CMake < 3.15 (#433) * Add function to get the currently selected channel (#451) * Add missing board detection macros (#448) * add board detection macros for Sparkfun & RPi Pico / VGA Board * dma_channel_transfer_[from/to]_buffer_now: added const volatile to read_addr and volatile to write_addr (#449) * Change the quick-start instructions to include installation of the (#92) * added spi_get_baudrate() + some consistency changes (#395) * Allow lengthening xosc startup delay with a compile option (#457) * Add hardware_gpio accessors for Schmitt, slew rate, drive strength (fixes #290) (#464) * Add some spin lock related doxygen * Move to Tinyusb 0.10.0 (#462) * Add usb device dpram to svd file. Fixes #351 (#465) * Add PICO_PANIC_FUNCTION define to allow replacement of the default panic function (#463) * Add missing DREQ_ definitions * store actual clock frequency in clock_configure (fixes #368) * Fix hw_is_claimed, and add xxx_is_claimed APIs * Add some PIO irq helper methods * Add DMA channel IRQ status getter and clear methods * Implement the correct PIO IRQ status/clear methods (good to have methods here as the h/w interrupt registers are super confusing) * fix pico_multicore dependencies * add missing wrapper func __aeabi_f2d * Further DMA/PIO IRQ API cleanup (and review fixes) * add PICO_INT64_OPS_IN_RAM flag * fix qtpy rp2040 uart rx rev B (#466) * Move to tinyusb 0.10.1 (upstream tinyusb repo) ($467) * Add gpio_set_irqover to match inover/outover/oeover (fixes #265) (#470) Co-authored-by: Andrew Scheller <andrew.scheller@raspberrypi.com> Co-authored-by: Christian Flach <cmfcmf.flach@gmail.com> Co-authored-by: Luke Wren <wren6991@gmail.com> Co-authored-by: Earle F. Philhower, III <earlephilhower@yahoo.com> Co-authored-by: majbthrd <majbthrd@gmail.com> Co-authored-by: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Co-authored-by: Brian Cooke <bdscooke@gmail.com> Co-authored-by: Scott Shawcroft <scott@tannewt.org> Co-authored-by: Michael Stoops <spam@michaelstoops.com> Co-authored-by: ZodiusInfuser <christopher.parrott2@gmail.com> Co-authored-by: Kirk Benell <36707344+kirk-sfe@users.noreply.github.com> Co-authored-by: Ha Thach <thach@tinyusb.org> Co-authored-by: Exr0n <spotyie@gmail.com> Co-authored-by: Joni Kähärä <joni.kahara@async.fi> Co-authored-by: Rafael G. Martins <rafael@rafaelmartins.eng.br> Co-authored-by: Jonathan Reichelt Gjertsen <jonath.re@gmail.com> Co-authored-by: Martino Facchin <m.facchin@arduino.cc> Co-authored-by: Rene <reneg973@gmail.com> Co-authored-by: Brendan <2bndy5@gmail.com> Co-authored-by: geurtv <48989893+geurtv@users.noreply.github.com> Co-authored-by: ewpa <34030942+ewpa@users.noreply.github.com> Co-authored-by: Dan Halbert <halbert@halwitz.org> Co-authored-by: Liam Fraser <liam@raspberrypi.com>
I am trying to port Tock to the Raspberry Pi Pico and I am facing a strange issue regarding the FIFO interrupt.
As Tock is using only one core, I do not need the FIFO. My understanding is that the second core is stopped by the bootloader. The problems that I am facing are the following:
I am using
openocd
via a Raspberry Pi to load and debug the software. I used the same init steps as in the SDK.I think I might be missing something, but I can't figure out what. Any advice would be great.
The text was updated successfully, but these errors were encountered: