Skip to content
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

Closed
alexandruradovici opened this issue Mar 26, 2021 · 16 comments
Closed

Unable to disable FIFO_IRQ_PROC0 #284

alexandruradovici opened this issue Mar 26, 2021 · 16 comments
Labels
documentation Improvements or additions to documentation

Comments

@alexandruradovici
Copy link

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:

  1. the FIFO_IRQ_PROC) (15) interrupt keeps firing continuously, I tried disabling it from the NVIC, but it seems to ignore it
  2. when trying to to write to the NVIC::ISER register the value 1<<15 it hard faults, any other value works

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.

@lurch
Copy link
Contributor

lurch commented Mar 27, 2021

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.

@alexandruradovici
Copy link
Author

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?)

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.

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 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.

@lurch
Copy link
Contributor

lurch commented Mar 27, 2021

I did try disabling it by writing the ICER register.

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 🙂

@kilograham
Copy link
Contributor

kilograham commented Mar 27, 2021

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.

@kilograham kilograham added the documentation Improvements or additions to documentation label Mar 27, 2021
@lurch
Copy link
Contributor

lurch commented Mar 27, 2021

From what I understand from the datasheet, shouldn't core0 writing to the FIFO trigger core1's IRQ, i.e. 16?

EDIT:

You need to clear the status register by writing say 0xF to the register; this will clear the IRQ.

The datasheet claims that the FIFO_ST RDY and VLD fields are ReadOnly? (I'm not implying that @kilograham is wrong, it might be the datasheet that is wrong, or it might just be @alexandruradovici 's code that is wrong 🤷‍♂️ )

@kilograham
Copy link
Contributor

yes i meant core 1 sorry ... edited

@alexandruradovici
Copy link
Author

You need to clear the status register by writing say 0xF to the register; this will clear the IRQ.

I tried this now, the interrupt still fires.

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.

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.

@lurch
Copy link
Contributor

lurch commented Mar 27, 2021

@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 multicore_fifo_clear_irq() and the comment at https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/pico_multicore/include/pico/multicore.h#L134 says // Write any value to clear any interrupts, i.e. the multicore_fifo_irqs example seems to be assuming that multicore_fifo_clear_irq() clears the VLD flag?
However section 2.3.1.4. in the datasheet says "The ROE and WOF flags are cleared by writing any value to FIFO_ST, and the VLD flag is cleared by reading data from the FIFO until empty." and the register-description for FIFO_ST additionally shows that the VLD field is read-only?

So (to me) it seems like what multicore_fifo_clear_irq() is actually doing is just clearing the error flags? (which of course will clear the interrupt, if the interrupt was caused by an underflow / overflow error).

P.S. The doxygen comment for multicore_fifo_drain says "Flush any data in the outgoing FIFO" however should it say "incoming FIFO" (as it seems to be draining fifo_rd)?

@alexandruradovici

I don't think I turned on the interrupt. How would I do that?

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?

@alexandruradovici
Copy link
Author

alexandruradovici commented Mar 27, 2021

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).

@alexandruradovici
Copy link
Author

alexandruradovici commented Mar 27, 2021

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 main function:

/**
 * 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)

@lurch
Copy link
Contributor

lurch commented Mar 27, 2021

Now I start getting also IRQ 16. Shouldn't this fire only for the second core?

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? 🤷‍♂️

@alexandruradovici
Copy link
Author

alexandruradovici commented Mar 28, 2021

Now I start getting also IRQ 16. Shouldn't this fire only for the second core?

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."

I figured that this might be the problem.

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

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.

But I can't comment further on your code as I'm starting to get out of my depth wink (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?)

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:

  1. IRQ 15 stops pending as long as I read FIFO_RD and write 0xff to FIFO_ST two times
  2. IRQ 16 never stops pending, not matter what I do.

My understanding is that for processor 0 I should ignore IRQ 16. Is this right?

@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? man_shrugging

@lurch
Copy link
Contributor

lurch commented Mar 28, 2021

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.

Can't you just ignore pending-interrupts in your interrupt-handler / kernel, when you know those interrupts haven't been enabled?

IRQ 16 never stops pending, not matter what I do.

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).

@alexandruradovici
Copy link
Author

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.

Can't you just ignore pending-interrupts in your interrupt-handler / kernel, when you know those interrupts haven't been enabled?

This is what I did.

IRQ 16 never stops pending, not matter what I do.

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 makes sense, thank you.

@kilograham
Copy link
Contributor

i think this can be closed, no?

lurch added a commit to lurch/pico-sdk that referenced this issue Apr 9, 2021
@alexandruradovici
Copy link
Author

i think this can be closed, no?

Yes, I think so.

kilograham pushed a commit that referenced this issue Apr 18, 2021
Based on my observations in #284
kilograham added a commit that referenced this issue Jun 3, 2021
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

3 participants