Squashed 'third_party/pico-sdk/' changes from 2062372d20..2e6142b15b
2e6142b15b SDK 1.4.0 release
5e9a5e827b Add Pico W and lwIP support
77c04e458c revert TinyUSB update (#889)
bc5d1b8485 Add channel_config_set_high_priority (#888)
85dbbfdf4d Update TinyUSB to commit 39069cf4b to pick up recent RP2040 fixes (#886)
e7267f99fe Fix GPIO # callback parameter (#880)
4c49427bf3 Fix auto_init_recursive_mutex definition for C++ (#875)
33818dd0bd Increase PLL min VCO from 400MHz to 750MHz for improved stability across operating conditions (#869)
8f09099757 sem_acquire has no reason to do a notify! (#857)
9644399993 Suppress new GCC 12 warning (#842)
b3c56e7169 Add stderr support and remove 1us timeout for timeouts of 0us (#858)
7858601a58 stdio_usb improvements (#871)
0bdd463898 Add DatanoiseTV DSP Board. (#866)
7daa20ce4c Add board definition for the RP2040 Stamp Round Carrier (#837)
705b5cedcd Wrap realloc() call with malloc_mutex in multicore (#864)
bdd9746635 Don't copy .data for NO_FLASH binaries, as it's loaded in-place (#859)
babc4a1794 Remove 'default=none' from PICO_CONFIG lines (#865)
6c19d20aa5 Fix up filename displayed by extract_config.py when an invalid attribute is found (#853)
672e48e9e9 Add sem_try_acquire(). Fixes #846 (#856)
ef47dfeeaf Add new GPIO APIs for adding shared GPIO handlers, and improve docs (#850)
6389927cf9 Add some optional header includes, to make per-target changes to config easier (#851)
d3dcbb8292 Add new user_irq claim APIs to make it easier for independent code using them to interoperate (#854)
f3c446ae14 move get_core_num() into platform.h (#852)
4e4cf11d9b Start SDK 1.3.2 development
426e46126b SDK 1.3.1 release
ebc601f71f Re-merge SDK1.3.0 history back into SDK1.3.1
1e6c122fc9 gate inclusion of pico.h in binary info, so as not to break picotool builds (#836)
7880405292 Doxygen typo (#835)
530204ec0c Small tweak to busy_wait_at_least_cycles doxygen (#834)
ea79d29cd6 Merge non-squashed history of 1.3.0 release back in to master
b2ad632c24 Minor additions to PIO documentation (#831)
658a21b946 Update rtc_set_datetime docs to point out that the written value may not be immediately visible (#832)
e44d2c0010 Add busy_wait_at_least_cycles method (#830)
43a5593e8f Pass PIOASM_EXTRA_SOURCE_FILES to Pioasm sub-cmake and add OUTPUT_FORMAT option (fixes #827) (#828)
792813926d Make pioasm accept windows CRLF input (#829)
159d552150 Fix bug in irq_remove_shared_handler and add test #823 (#825)
3a3d5fe6c4 Small IRQ doxygen tweaks (#824)
5e22c09660 convert unlikely panic to hard_assert to not waste space for string (#826)
4e62c26a2c Add documentation to dma_channel_abort regarding errata RP2040-E13 (#816)
5a927792ef Suppress false GCC 11 warning on TinyUSB (#819)
60a6fea534 Fix list management in stdio_set_driver_enabled so drivers can be freely added and removed (#822)
04c68c554b cleanup pico_stdlib_test. add actual check for __builtin bitops (#821)
0d2591e1f1 Pad all but last sector in flash binary to write whole of sector (#800)
81bdcb6681 print build type during CMake config; remove spurious call to pico_is_toplevel_project() (#818)
9c616da1e5 fix bug in pico_float_test (#817)
f260477802 Adapt assembler syntax to eliminate Clang errors. (LLVM 14.0.0) (#798)
e1c5fd34e4 PLL setup check bug (#796) (#806)
5d422deed1 Add extra info about address_range defined values (#652)
0c501c246a Add wiznet_w5100s_evb_pico support (#666)
259da19660 Include structs/iobank0.h from hardware/gpio.h (#733) (#807)
5325008956 Added board definition for upcoming Pimoroni motor driver (#795)
510ca47c92 Additional PWM validation and small tidy-up (#801)
d5121dc880 Removed unnecessary ifdefs from Pimoroni boards (#802)
3c450011da Additional param-validation for PIO (#805)
6149b9e4ec Add board definition for Seeed Xiao RP2040 (#691)
8554fc4ea1 Add is_at_the_end_of_time() method (#784)
01290c4cb3 Added int_frac function for configuring PWM (#768)
8d43364cfb Small typos (#776)
1c9f72ba1c Small edits to the Doxygen mainpage and update the RPi logo (#778)
76c1830aeb Add gpio_deinit (#793)
c66a2c1c3b Remove implicit grouping for PIO defines (#779)
e4a2aa7262 Fix typo in binary_info description (#788)
fc86203f49 comment typo (#794)
6619a2d329 Typo (#799)
5a427fbf1f irq_add_shared_handler assertion fix #724 (#747)
bb5a2a3906 Added definition for Badger RP2040 board (#735)
8291f1013a add #ifdef guards to vgaboard.h to allow user overrides (#746)
e90f831756 add board definition of eetree gamekit rp2040 (#732)
541f93541c improve comment (#658)
17d53af105 Allow 252-byte binaries to be checksummed (#764)
1896b1491b fix __ctzdi2 for values with non-zero low 32 bits (fixes #765) (#766)
3d45276423 Added board definition for upcoming Pimoroni servo driver (#769)
d35083b3f7 Fix typo in SIO register description (#770)
38b26b5d65 pico_sdk_import: don't recurse git submodules (#772)
d54104a1e5 fix when PICO_NO_BINARY_INFO is set (#693)
bc3484e793 Mark __aeabi_lmul section as allocatable and executable (#722)
b7e82b638a Fix function-names reported by hardware_pwm_test (#736)
bf9848eaf9 Updated DMA CTRL_TRIG.CHAIN_TO reset values (#743)
ae7ef546a6 Fix typo in Doxygen comment (#731)
b3cf3e8f6f Correct comment in time.h (#715)
25a3b36793 Fix assert in adc_set_round_robin() (#698)
96afce8ece Add board definition for Adafruit Macropad (#684)
5bcf4ed83a Clarify header-comments about pico_enable_stdio_ CMake-functions (#705)
e379f6764b Add board definition for RP2040 Stamp and Carrier (#696)
91462e430a Add `__attribute__((noreturn))` to `_exit` (#707)
d831eff5a2 fix pioasm python output (#694) (#695)
215f77b836 Moves the #if guards to before the comments (#690)
0f67a6c00c Add board definition for Adafruit KB2040 (#676)
add120e4f6 add missing change to dma.h from __force_inline fix (#680)
386e2a7bc6 Added Tiny2040 2MB (#672)
0562089fab fixup __forceinline for cpp code and add kitchen_sink cpp test (#670)
269332dc21 rename pybstick26_rp2040.h to garatronic_pybstick26_rp2040.h (#675)
a8fa19a74d pio_set_irqn_source_mask_enabled() sets wrong irq (#655)
699838d153 Start SDK 1.3.1 development (#648)
60c5a929cc Remove <b> from mutex doxygen due to PDF generation bug
d0af70bd77 fix __packed attribute for MSVC (#646)
da476610e2 allow override of XOSC_MHZ (#644)
d7358e4ed8 update generated struct headers to fix collision (#641)
ccccff8450 Add pybstick26_rp2040 support (#636)
d0c7642369 Update ADC ENOB comment to match (measured) value in RP2040 datasheet (#643)
cc1e2e8758 Small typo in kitchen_sink (#642)
e4d6ff9ecd Small PICO_PLATFORM=host fixes (#639)
97eec951b1 Another .org -> .com fix (#638)
fba9c8ce4d change SDK version to 1.3.0 (#628)
da7c39bc23 Fix some of the (simpler) errors reported by the doxygen command (#617)
b04a09110f revert additional assertion check which breaks used of hw_alias macro outside of functions (#635)
5641cd0a4a __aeabi_memset* were switching the wrong arguments (#634)
68555c9751 Added some waveshare boards definition (#619)
e5110dfce1 add docs for pio_instructions.h (#624)
3604a6fa13 add CONTRIBUTING.md (#626)
e850214938 Platform updates (#611)
723dfd04ff add more/better documentation to pico/multicore (#620)
05418b4e71 fix minor bug in add_repeating_timer_us, and add some comments (#621)
83cd1da1ef fix build if TinyUSB not present (#631)
0ccd0db163 Update to TinyUSB 0.12.0 (#622)
22b0d5d2ed Update links in Doxygen pages from .org to .com (#625)
3c72e753b6 Split recursive mutex into their own functions (was Reduce performance hit of recursive mutex) (#495)
9320d192c3 add watchdog_enable_caused_reboot (minor compatibility issue) (#594)
68571ad33e Hardware struct regeneration (#613)
a0450d0133 Updated reg_headers and SVD (#612)
3c94bc8137 Change _watchdog_enable to trigger immediate reboot when no delay set (#561)
f808b5f2dc Add DREQ methods for PWM/SPI/UART/I2C (#603)
2f2e62968d Use auto-generated hardware/structs/ headers (based off SVD) SVD errors fixed.
a793222331 add template PR - very polite (#596)
ec4036181f tweak info message for TinyUSB support (#590)
db47fba48d respect OUTPUT_NAME target property when generating supplemental files (#592)
a0d4bdf731 fix pico_set_printf_implementation(TARGET compiler) (#593)
d50e743e0e make type punning of floating point/int in float_math and double_math use union to avoid warnings (#600)
30673fb6d0 move inline assembly constant out into C code so it doesn't get out of range in a large function (#602)
e76d5a9008 add dma_timer related methods (#604)
9f1c37318b add irq_get_priority method - improve efficiency of irq_init_priorities (#609)
4c9ba3e8ad USB: Fix description of Length 0 in dpram_regs. Fixes #541 (#608)
ace97f3387 More accurate register access-types and reset-values (#601)
0fa58ed219 Adding/propage macros/signature typedefs for ROM functions. Make rom_func_lookup non-flash safe for flash functions (#586)
0a32023aac fix arg parsing segfault (#595)
13be546dc3 pico_stdio improvements (#598)
12017a07ab SPINLOCK regs are RW. (#599)
9319ab11d9 Add xip window alias macros (#566) (#585)
62854f5eff shrink max-page-size for linker to more sensible 4096 by default (#587)
13ed99df0d split out usb_reset_interface header into its own library for consumption by picotool or others (#589)
0fdf543126 Missing extern C in datetime.h #581 (#584)
3c53029c24 Fix some typos (#517)
ce0db40223 adafruit_feather_rp2040: Fix default I2C instance (#526)
a119b5bd9f Fix semihosting_putc (#530)
eb42ecfaa5 Added definitions for some upcoming Pimoroni LED driver boards (#535)
cd4e53a202 Use W25Q080 second stage loader for Nano RP2040 Connect (#537)
f63a14e9ee Change PWM_CH1_DIV_INT_LSB to PWM_CH0_DIV_INT_LSB (#560)
2214468b51 Add Adafruit Trinkey QT2040 board (#525)
e12713d70b pio_assembler: typo fix (#538)
e6b8c7b64e bugfix: "WO" registers should be listed in the SVD as write-only, not read-write (#544)
1d0dcc8177 pico_time: Fix alarm_pool_dump_key format string (#557)
46d8597d35 Add hardware_divider to pico_divider dependencies (#571)
d7feac1495 Fix syntax error in cmake when using custom stage2 (#580)
ca232e9404 Add Melopero Shake RP2040 Board header file (#565)
c08136b696 Move ret_dzero to the same section as it get used (#513)
672d18a6f0 Fix default PICO_BOARD value (#536)
2622e9bc29 Enable UART RX timeout IRQ, as well as RX IRQ, so that individual characters can be received.
9a586371db Add doxygen clarifying PWM behaviour when enabled/disabled, and advice for controlling the pin state when disabled (#521)
a6a436b1fe use PUBLIC for pio headers on any target except INTERFACE library
7e90980118 Add explanatory note on 7-bit I2C addresses (#520)
ae6e574f53 Improve wording of comments in irq.h (#509)
ccc0ba5649 elf2uf2: correctly parse ELF files where the program header is not directly following the file header
5e05469373 bug in sleep_until on host mode for macOS (#502)
dc4342f0f6 Update usb regs to fix https://github.com/raspberrypi/pico-feedback/issues/172
35b4965054 make sure PICO_DEFAULT_BOOT_STAGE2_FILE is defined in parent CMake file (#491)
e02c6b327d Allow one of float/double to have 'none' impl but not the other - previously caused a link error
f4ab723eb5 compile failure with PICO_STDOUT_MUTEX=0
529d7087eb fix operatore precedence of */ vs +- in pioasm
cefe5c5b2a Better support for PICO_DISABLE_SHARED_IRQ_HANDLERS (#496)
edcb65c916 Enable I2C FIFO full hold in slave mode (stretch clock when RX full), fixes #456 (#494)
f16ccfa1ff Small comment typos
44feae4caf set DIVISOR for each use of h/w divider
61b7cbdc54 Using ' inline __always_inline' also for GNUC 7. (#484)
21bbaf3ca6 remove -Winline (#481)
4328b2c75f fix pioasm python output (#479)
1f1c6162cd Header info string updates for PIO DBG_PADx and XOSC STARTUP (#478)
979045dc12 removed CMSIS from SDK doxygen
d42e6a9d10 include pico.h so that uint is defined (#475)
654b66693f start 1.3.0 development
git-subtree-dir: third_party/pico-sdk
git-subtree-split: 2e6142b15b8a75c1227dd3edbe839193b2bf9041
Signed-off-by: Ravago Jones <ravagojones@gmail.com>
Change-Id: I7d5ab3e7e797e8e956d3a651b600448157ab0608
diff --git a/.gitmodules b/.gitmodules
index 4846c9c..a37debe 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,9 @@
[submodule "tinyusb"]
path = lib/tinyusb
url = https://github.com/hathach/tinyusb.git
+[submodule "lib/cyw43-driver"]
+ path = lib/cyw43-driver
+ url = https://github.com/georgerobotics/cyw43-driver.git
+[submodule "lib/lwip"]
+ path = lib/lwip
+ url = https://github.com/lwip-tcpip/lwip.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0ab4c31..e79d04a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9,6 +9,7 @@
project(pico_sdk C CXX ASM)
+ message("Build type is ${CMAKE_BUILD_TYPE}")
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
if (PICO_DEOPTIMIZED_DEBUG)
message("Using fully de-optimized debug build (set PICO_DEOPTIMIZED_DEBUG=0 to optimize)")
diff --git a/README.md b/README.md
index db6cef6..26084ca 100644
--- a/README.md
+++ b/README.md
@@ -110,6 +110,24 @@
```
+ * Or by cloning the SDK locally, but without copying `pico_sdk_import.cmake`:
+ 1. `git clone` this Raspberry Pi Pico SDK repository
+ 2. Setup a `CMakeLists.txt` like:
+
+ ```cmake
+ cmake_minimum_required(VERSION 3.13)
+
+ # initialize the SDK directly
+ include(/path/to/pico-sdk/pico_sdk_init.cmake)
+
+ project(my_project)
+
+ # initialize the Raspberry Pi Pico SDK
+ pico_sdk_init()
+
+ # rest of your project
+
+ ```
1. Write your code (see [pico-examples](https://github.com/raspberrypi/pico-examples) or the [Raspberry Pi Pico C/C++ SDK](https://rptl.io/pico-c-sdk) documentation for more information)
About the simplest you can do is a single source file (e.g. hello_world.c)
diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in
index cc133f8..5dc4be7 100644
--- a/docs/Doxyfile.in
+++ b/docs/Doxyfile.in
@@ -60,4 +60,5 @@
__time_critical_func(x) \
__not_in_flash(x)= \
__no_inline_not_in_flash(x)= \
- __attribute__(x)=
+ __attribute__(x)= \
+ DOXYGEN_GENERATION=
diff --git a/docs/header.html b/docs/header.html
index 32bb7eb..72332ff 100644
--- a/docs/header.html
+++ b/docs/header.html
@@ -54,7 +54,7 @@
<div class="navigation-footer">
<img src="logo-mobile.svg" alt="Raspberry Pi">
- <a href="https://www.raspberrypi.com/" target="_blank">By Raspberry Pi (Trading) Ltd</a>
+ <a href="https://www.raspberrypi.com/" target="_blank">By Raspberry Pi Ltd</a>
</div>
<!-- <div class="search">
<form>
diff --git a/docs/index.h b/docs/index.h
index c7ef735..a334fc3 100644
--- a/docs/index.h
+++ b/docs/index.h
@@ -56,6 +56,13 @@
* \defgroup tinyusb_host tinyusb_host
* @}
*
+ * \defgroup networking Networking Libraries
+ * Functions for implementing networking
+ * @{
+ * \defgroup pico_lwip pico_lwip
+ * \defgroup pico_cyw43_arch pico_cyw43_arch
+ * @}
+ *
* \defgroup runtime Runtime Infrastructure
* Libraries that are used to provide efficient implementation of certain
* language level and C library functions, as well as CMake INTERFACE libraries
diff --git a/docs/logo-mobile.svg b/docs/logo-mobile.svg
index 27192be..fb97dd1 100644
--- a/docs/logo-mobile.svg
+++ b/docs/logo-mobile.svg
@@ -1,17 +1,29 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="570" height="720">
- <path d="m 158.375,1.65625 c -3.6193,0.1123192 -7.51715,1.4493266 -11.9375,4.9375 C 135.61054,2.4174496 125.11041,0.9665612 115.71875,9.46875 101.22489,7.5879922 96.508461,11.469494 92.9375,16 89.754953,15.934135 69.118652,12.72793 59.65625,26.84375 35.874602,24.030329 28.359472,40.831625 36.875,56.5 c -4.856911,7.518955 -9.889503,14.947226 1.46875,29.28125 -4.018006,7.983514 -1.527431,16.64403 7.9375,27.125 -2.497857,11.2226 2.412077,19.14086 11.21875,25.3125 -1.64709,15.35756 14.083505,24.28743 18.78125,27.46875 1.803677,8.94868 5.56291,17.3927 23.53125,22.0625 2.96323,13.3361 13.76206,15.63906 24.21875,18.4375 -34.561929,20.08954 -64.20067,46.52266 -64,111.375 l -5.0625,9.03125 C 15.337882,350.69604 -20.316547,428.16001 35.4375,491.125 c 3.641871,19.70838 9.749589,33.86396 15.1875,49.53125 8.133834,63.13058 61.21763,92.69161 75.21875,96.1875 20.51653,15.62812 42.36818,30.45672 71.9375,40.84375 27.87515,28.74946 58.07388,39.7064 88.4375,39.6875 0.44515,-2.8e-4 0.89853,0.005 1.34375,0 30.36363,0.0189 60.56235,-10.93804 88.4375,-39.6875 29.56932,-10.38703 51.42097,-25.21563 71.9375,-40.84375 14.00112,-3.49589 67.08492,-33.05692 75.21875,-96.1875 5.43791,-15.66729 11.54562,-29.82287 15.1875,-49.53125 55.75404,-62.96499 20.09961,-140.42896 -19.53125,-164.53125 L 513.75,317.5625 c 0.20067,-64.85234 -29.43807,-91.28546 -64,-111.375 10.45669,-2.79844 21.25552,-5.1014 24.21875,-18.4375 17.96834,-4.6698 21.72758,-13.11382 23.53125,-22.0625 4.69775,-3.18132 20.42834,-12.11119 18.78125,-27.46875 8.80668,-6.17164 13.71661,-14.0899 11.21875,-25.3125 9.46494,-10.48097 11.9555,-19.141487 7.9375,-27.125 C 546.79575,71.447226 541.76316,64.018955 536.90625,56.5 545.42178,40.831625 537.90665,24.030329 514.125,26.84375 504.6626,12.72793 484.0263,15.934135 480.84375,16 477.27279,11.469494 472.55636,7.587992 458.0625,9.46875 448.67084,0.96656132 438.17071,2.41745 427.34375,6.59375 414.48455,-3.5536631 405.97149,4.580454 396.25,7.65625 380.67615,2.568472 377.11698,9.5371578 369.46875,12.375 352.4935,8.7869238 347.33315,16.598532 339.1875,24.84375 l -9.46875,-0.1875 c -25.61054,15.093115 -38.33378,45.825501 -42.84375,61.625 -4.51206,-15.801979 -17.20647,-46.534542 -42.8125,-61.625 l -9.46875,0.1875 C 226.4481,16.598532 221.28775,8.7869235 204.3125,12.375 196.66427,9.5371583 193.1051,2.5684729 177.53125,7.65625 c -6.37973,-2.0184911 -12.24667,-6.2144276 -19.15625,-6 z" style="fill:#000000" />
- <path d="m 107.39184,68.055583 c 67.94767,35.031357 107.44689,63.368967 129.08717,87.504467 -11.08235,44.41759 -68.89638,46.44464 -90.03559,45.19858 4.32842,-2.01474 7.93988,-4.42778 9.22051,-8.13574 -5.30449,-3.76981 -24.11289,-0.39719 -37.24363,-7.77416 5.04407,-1.04499 7.40348,-2.06302 9.76289,-5.78542 -12.40571,-3.9567 -25.76862,-7.36642 -33.627746,-13.92116 4.241253,0.0524 8.201156,0.9488 13.740366,-2.89271 -11.111694,-5.98819 -22.969108,-10.73351 -32.18139,-19.88738 5.745213,-0.14063 11.939452,-0.0568 13.740371,-2.16953 -10.17044,-6.30068 -18.751242,-13.30787 -25.853592,-20.97215 8.039979,0.97052 11.435284,0.13478 13.378782,-1.26556 -7.687795,-7.87419 -17.417559,-14.52319 -22.056911,-24.22644 5.969606,2.057484 11.431249,2.84506 15.36752,-0.180795 -2.612365,-5.893453 -13.805413,-9.369618 -20.248967,-23.141676 6.284359,0.609377 12.949606,1.371108 14.282753,0 C 61.802068,58.517346 56.796919,51.835885 51.887978,44.913906 65.338021,44.714177 85.715734,44.966253 84.792549,43.82914 l -8.31654,-8.497335 c 13.137617,-3.537241 26.580651,0.568164 36.339661,3.615887 4.38186,-3.457681 -0.0776,-7.82998 -5.42383,-12.294015 11.16496,1.490646 21.25382,4.057389 30.37345,7.593362 4.87238,-4.399329 -3.16389,-8.798658 -7.05098,-13.197987 17.24936,3.272568 24.55716,7.87068 31.81981,12.47481 5.26935,-5.050799 0.30166,-9.343299 -3.2543,-13.740371 13.00566,4.817048 19.70478,11.035551 26.75756,17.175463 2.39119,-3.227053 6.07494,-5.592408 1.62715,-13.378781 9.23416,5.322725 16.18926,11.59506 21.33374,18.621817 5.71336,-3.637941 3.40387,-8.613023 3.43509,-13.197987 9.59665,7.806516 15.68687,16.11395 23.14168,24.226443 1.50169,-1.093437 2.81661,-4.80171 3.97747,-10.666867 22.89539,22.211815 55.24591,78.158241 8.31654,100.340861 C 207.95028,109.95728 160.25292,86.016909 107.39184,68.055583 z" style="fill:#75a928" />
- <path d="M 467.92487,68.055583 C 399.9772,103.08694 360.47798,131.42455 338.8377,155.56005 c 11.08235,44.41759 68.89638,46.44464 90.03559,45.19858 -4.32842,-2.01474 -7.93988,-4.42778 -9.22051,-8.13574 5.30449,-3.76981 24.11289,-0.39719 37.24363,-7.77416 -5.04407,-1.04499 -7.40348,-2.06302 -9.76289,-5.78542 12.40571,-3.9567 25.76862,-7.36642 33.62775,-13.92116 -4.24126,0.0524 -8.20116,0.9488 -13.74037,-2.89271 11.11169,-5.98819 22.96911,-10.73351 32.18139,-19.88738 -5.74521,-0.14063 -11.93945,-0.0568 -13.74037,-2.16953 10.17044,-6.30068 18.75124,-13.30787 25.85359,-20.97215 -8.03998,0.97052 -11.43528,0.13478 -13.37878,-1.26556 7.68779,-7.87419 17.41756,-14.52319 22.05691,-24.22644 -5.96961,2.057484 -11.43125,2.84506 -15.36752,-0.180795 2.61237,-5.893453 13.80541,-9.369618 20.24897,-23.141676 -6.28436,0.609377 -12.94961,1.371108 -14.28276,0 2.92231,-11.888563 7.92746,-18.570024 12.8364,-25.492003 -13.45004,-0.199729 -33.82775,0.05235 -32.90457,-1.084766 l 8.31654,-8.497335 c -13.13762,-3.537241 -26.58065,0.568164 -36.33966,3.615887 -4.38186,-3.457681 0.0776,-7.82998 5.42383,-12.294015 -11.16496,1.490646 -21.25382,4.057389 -30.37345,7.593362 -4.87238,-4.399329 3.16389,-8.798658 7.05098,-13.197987 -17.24936,3.272568 -24.55716,7.87068 -31.81981,12.47481 -5.26935,-5.050799 -0.30166,-9.343299 3.2543,-13.740371 -13.00566,4.817048 -19.70478,11.035551 -26.75756,17.175463 -2.39119,-3.227053 -6.07494,-5.592408 -1.62715,-13.378781 -9.23416,5.322725 -16.18926,11.59506 -21.33374,18.621817 -5.71336,-3.637941 -3.40387,-8.613023 -3.43509,-13.197987 -9.59665,7.806516 -15.68687,16.11395 -23.14168,24.226443 -1.50169,-1.093437 -2.81661,-4.80171 -3.97747,-10.666867 -22.89539,22.211815 -55.24591,78.158241 -8.31654,100.340861 39.91877,-32.94716 87.61613,-56.887531 140.47721,-74.848857 z" style="fill:#75a928" />
- <path d="m 365.2046,521.84937 a 71.956154,66.532318 0 1 1 -143.91231,0 71.956154,66.532318 0 1 1 143.91231,0 z" transform="matrix(1.131107,0,0,1.1280497,-43.139135,-68.310983)" style="fill:#bc1142" />
- <path d="m 262.84091,276.64774 a 61.875,28.125 0 1 1 -123.75,0 61.875,28.125 0 1 1 123.75,0 z" transform="matrix(0.76741684,-1.1613112,2.171115,1.4224368,-560.88858,217.68859)" style="fill:#bc1142" />
- <path d="m 262.84091,276.64774 a 61.875,28.125 0 1 1 -123.75,0 61.875,28.125 0 1 1 123.75,0 z" transform="matrix(-0.76741684,-1.1613112,-2.171115,1.4224368,1134.8288,213.68859)" style="fill:#bc1142" />
- <path d="M 72.910253,342.0878 C 109.32447,332.33088 85.201845,492.72431 55.576871,479.56357 22.990103,453.35089 12.493801,376.58814 72.910253,342.0878 z" style="fill:#bc1142" />
- <path d="m 493.67828,340.0878 c -36.41422,-9.75692 -12.2916,150.63651 17.33338,137.47577 32.58677,-26.21268 43.08307,-102.97543 -17.33338,-137.47577 z" style="fill:#bc1142" />
- <path d="m 369.97158,220.6534 c 62.83486,-10.61013 115.11594,26.72229 113.01138,94.85796 -2.06693,26.12112 -136.15872,-90.96907 -113.01138,-94.85796 z" style="fill:#bc1142" />
- <path d="M 196.35975,218.6534 C 133.52489,208.04327 81.24381,245.37569 83.34837,313.51136 85.4153,339.63248 219.50709,222.54229 196.35975,218.6534 z" style="fill:#bc1142" />
- <path d="m 286.61932,202.75568 c -37.50259,-0.97548 -73.49548,27.83418 -73.58158,44.54443 -0.10462,20.30426 29.6512,41.09266 73.83726,41.62035 45.12305,0.32321 73.91561,-16.64049 74.0611,-37.59409 0.16484,-23.73996 -41.03879,-48.93744 -74.31678,-48.57069 z" style="fill:#bc1142" />
- <path d="m 288.90937,619.11675 c 32.69744,-1.42711 76.57083,10.53196 76.6568,26.39598 0.5427,15.4052 -39.78969,50.21055 -78.82634,49.53765 -40.42729,1.74391 -80.06908,-33.11559 -79.54951,-45.19859 -0.60506,-17.71593 49.226,-31.54796 81.71905,-30.73504 z" style="fill:#bc1142" />
- <path d="m 168.13874,525.10369 c 23.2791,28.04573 33.89066,77.31899 14.46355,91.84353 -18.37917,11.08784 -63.01228,6.52162 -94.736237,-39.05157 -21.395052,-38.24168 -18.637584,-77.15663 -3.615887,-88.58924 22.464424,-13.68429 57.173424,4.79902 83.888574,35.79728 z" style="fill:#bc1142" />
- <path d="m 405.0209,516.21177 c -25.18682,29.50165 -39.21227,83.30951 -20.83785,100.6428 17.56828,13.46361 64.7292,11.58162 99.56566,-36.75574 25.29599,-32.46471 16.82013,-86.68225 2.37077,-101.07511 -21.46408,-16.60213 -52.27691,4.64489 -81.09858,37.18805 z" style="fill:#bc1142" />
+<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="50mm" height="50mm" viewBox="0 0 141.73228 141.73228">
+ <defs>
+ <style>
+ .cls-1 {
+ fill: #46af4b;
+ }
+
+ .cls-2 {
+ fill: #cd2355;
+ }
+ </style>
+ </defs>
+ <g>
+ <path d="M120.397,80.45865c-.56815-5.90742-3.22385-11.16309-6.995-13.93267a17.27379,17.27379,0,0,0-3.24656-6.31353,19.36966,19.36966,0,0,0-6.892-13.02018,7.27722,7.27722,0,0,0,1.59572-1.944c4.57759-2.04455,7.80508-6.33776,8.1794-9.53072a12.5259,12.5259,0,0,0,3.95675-8.20484,7.846,7.846,0,0,0-.69989-3.69357,7.01847,7.01847,0,0,0,1.82922-7.2442c-1.36677-3.95887-6.15514-6.52856-12.58679-6.80113A10.13626,10.13626,0,0,0,98.52937,7.374a16.203,16.203,0,0,0-3.78352.46578,8.61261,8.61261,0,0,0-3.719-.75319,14.555,14.555,0,0,0-7.0952,1.934,6.5202,6.5202,0,0,0-.85646-.05542c-3.193-.0003-6.38471,2.19991-8.00284,3.51125a24.2642,24.2642,0,0,0-4.2063,4.38226,24.27017,24.27017,0,0,0-4.206-4.38195c-1.61814-1.31135-4.80988-3.51126-8.00254-3.51156a6.525,6.525,0,0,0-.85677.05542,14.55806,14.55806,0,0,0-7.09489-1.934,8.614,8.614,0,0,0-3.71931.75319A16.201,16.201,0,0,0,43.203,7.374a10.13676,10.13676,0,0,0-7.00858,2.39979c-6.432.27257-11.22033,2.84226-12.5871,6.80143a7.018,7.018,0,0,0,1.82922,7.2439A7.84794,7.84794,0,0,0,24.737,27.513a12.52529,12.52529,0,0,0,3.95675,8.20454c.37432,3.19326,3.60181,7.48617,8.1794,9.53072a7.27538,7.27538,0,0,0,1.59542,1.944,19.37028,19.37028,0,0,0-6.89168,13.02018A17.27118,17.27118,0,0,0,28.33031,66.526c-3.77111,2.76958-6.42681,8.02525-6.99495,13.93236-.56482,5.87168,1.046,11.35328,4.32471,14.82547a20.99222,20.99222,0,0,0,3.56516,8.18667,21.30368,21.30368,0,0,0,5.378,12.42629,22.01533,22.01533,0,0,0,11.859,7.04734,28.71359,28.71359,0,0,0,9.48469,5.87137A20.881,20.881,0,0,0,70.866,134.64567a20.8833,20.8833,0,0,0,14.91936-5.83019,28.72034,28.72034,0,0,0,9.48469-5.87137,22.01559,22.01559,0,0,0,11.85873-7.04734,21.3036,21.3036,0,0,0,5.378-12.426,20.98659,20.98659,0,0,0,3.56517-8.187C119.35068,91.81162,120.96155,86.33,120.397,80.45865Z"/>
+ <path class="cls-1" d="M82.88834,15.64565a.50715.50715,0,0,1,.64431.53875c-.16085,1.517.75688,1.32594.97375,1.05634,2.38917-2.97065,4.91974-3.64653,7.18552-3.447a.5073.5073,0,0,1,.347.81808c-.90026,1.33535.06917,1.58923.42806,1.34935,3.67706-2.299,7.18462-2.30316,8.53087-1.33751a.50652.50652,0,0,1,.03017.78741c-1.36075,1.15928-.599,1.73636-.11843,1.56042,3.73308-1.31743,8.88679-.15193,10.68462,1.36809a.511.511,0,0,1,.01278.77323,10.12618,10.12618,0,0,0-3.89825,6.80014c-.10141.89409,1.38228.706,2.00839.54492a.50694.50694,0,0,1,.63161.47341c.05646,2.14911-1.97606,4.51144-5.00017,6.53158-.405.27055-.34746.91972.57694.94363a.50088.50088,0,0,1,.43014.75445c-1.0784,2.00172-2.545,3.88636-7.54009,5.18055a.51181.51181,0,0,0-.07052.96565.48972.48972,0,0,1,.15941.86532c-4.97342,4.27273-17.58014,2.58829-19.18036-4.603a.50477.50477,0,0,1,.09069-.4114A47.92158,47.92158,0,0,1,100.721,21.25148a.3975.3975,0,0,0-.19687-.76539,34.186,34.186,0,0,0-22.704,13.68742.512.512,0,0,1-.65061.14752C69.08866,30.14885,75.72444,17.82948,82.88834,15.64565Z"/>
+ <path class="cls-1" d="M35.37668,35.161a.50084.50084,0,0,1,.43005-.75445c.92449-.02391.982-.67308.57694-.94363-3.02411-2.02014-5.05663-4.38247-5.00007-6.53158a.5069.5069,0,0,1,.6316-.47341c.626.16108,2.10971.34917,2.0083-.54492a10.126,10.126,0,0,0-3.89816-6.80014.51094.51094,0,0,1,.0127-.77323c1.79782-1.52,6.95154-2.68552,10.6847-1.36809.48048.17594,1.24223-.40114-.11843-1.56042a.50652.50652,0,0,1,.03008-.78741c1.34634-.96565,4.85381-.96146,8.53087,1.33751.3589.23988,1.32833-.014.42815-1.34935a.5073.5073,0,0,1,.34692-.81808c2.26588-.19954,4.79644.47634,7.18561,3.447.21678.2696,1.13461.46062.97375-1.05634a.50711.50711,0,0,1,.64422-.53875c7.164,2.18383,13.79977,14.5032,5.71877,18.67538a.512.512,0,0,1-.65061-.14752A34.18579,34.18579,0,0,0,41.20821,20.48609a.3975.3975,0,0,0-.19688.76539,47.92145,47.92145,0,0,1,20.90622,15.9066.50472.50472,0,0,1,.0906.4114c-1.60022,7.19128-14.20694,8.87572-19.18035,4.603a.48975.48975,0,0,1,.15941-.86532.51183.51183,0,0,0-.07043-.96565C37.92166,39.04731,36.455,37.16267,35.37668,35.161Z"/>
+ <path class="cls-2" d="M102.70391,57.14512c2.07215,5.51262.45788,8.1631-4.45781,5.35681a35.23186,35.23186,0,0,1-10.324-8.6538c-3.70264-4.39923-1.29618-6.3588,4.53643-5.30214A15.74307,15.74307,0,0,1,102.70391,57.14512Z"/>
+ <path class="cls-2" d="M80.656,50.9434c7.02971,5.84278-1.02445,9.97893-9.78984,9.97893s-16.81947-4.13615-9.78976-9.97893a15.62992,15.62992,0,0,1,19.5796,0Z"/>
+ <path class="cls-2" d="M39.02843,57.14512A15.74294,15.74294,0,0,1,49.27372,48.546c5.83261-1.05666,8.23916.90291,4.53644,5.30214a35.232,35.232,0,0,1-10.324,8.6538C38.57056,65.30822,36.95628,62.65774,39.02843,57.14512Z"/>
+ <path class="cls-2" d="M28.86006,87.77634a15.73764,15.73764,0,0,1,1.16828-13.39206c2.59721-4.419,5.21118-4.2431,6.24869-.49944a23.47909,23.47909,0,0,1-1.35309,15.47529C33.00057,93.18313,30.595,91.89119,28.86006,87.77634Z"/>
+ <path class="cls-2" d="M47.58848,116.39963A15.64491,15.64491,0,0,1,35.82,102.43657C36.79507,79.749,69.49268,120.26554,47.58848,116.39963Z"/>
+ <path class="cls-2" d="M48.254,88.14263c-5.48323-3.16572-6.9343-10.91794-3.24093-17.31507s11.13243-9.01664,16.61566-5.85087c5.48323,3.16572,6.9343,10.918,3.24094,17.31507S53.73709,91.3084,48.254,88.14263Z"/>
+ <path class="cls-2" d="M80.0159,125.05829a15.6584,15.6584,0,0,1-18.29955,0c-5.43318-3.75194.03278-8.06894,9.14978-8.06894S85.44917,121.30635,80.0159,125.05829Z"/>
+ <ellipse class="cls-2" cx="70.86613" cy="100.39562" rx="12.72753" ry="10.90937"/>
+ <path class="cls-2" d="M76.86255,82.29176c-3.69336-6.39709-2.24229-14.14935,3.24094-17.31507,5.48323-3.16577,12.9223-.54622,16.61567,5.85087s2.24229,14.14935-3.24094,17.31507C87.99516,91.3084,80.55592,88.68885,76.86255,82.29176Z"/>
+ <path class="cls-2" d="M94.14377,116.39963c-21.9042,3.86591,10.79341-36.65066,11.7686-13.96306A15.64488,15.64488,0,0,1,94.14377,116.39963Z"/>
+ <path class="cls-2" d="M112.87229,87.77634c-1.73505,4.11485-4.14061,5.40679-6.064,1.58379a23.47913,23.47913,0,0,1-1.353-15.47529c1.03742-3.74366,3.65139-3.9196,6.2486.49944A15.73769,15.73769,0,0,1,112.87229,87.77634Z"/>
+ </g>
</svg>
diff --git a/docs/mainpage.md b/docs/mainpage.md
index e79fb90..c79b587 100644
--- a/docs/mainpage.md
+++ b/docs/mainpage.md
@@ -1,30 +1,28 @@
# Raspberry Pi Pico SDK
-The Raspberry Pi Pico SDK (Software Development Kit), henceforth SDK, provides the headers, libraries and build system necessary to write programs for the RP2040 based devices such as the Raspberry Pi Pico in C, C++ or assembly language. The SDK is designed to provide an API and programming environment that is familiar both to non-embedded C developers and embedded C developers alike.
+The Raspberry Pi Pico SDK (Software Development Kit), henceforth SDK, provides the headers, libraries and build system necessary to write programs for RP2040-based devices such as the Raspberry Pi Pico in C, C++ or assembly language. The SDK is designed to provide an API (Application Programming Interface) and programming environment that is familiar both to non-embedded C developers and embedded C developers alike.
-A single program runs on the device at a time with a conventional main() method. Standard C/C++ libraries are supported along with APIs for accessing the RP2040’s hardware, including DMA, IRQs, and the wide variety fixed function peripherals and PIO (Programmable IO).
+A single program runs on the device at a time with a conventional `main()` method. Standard C/C++ libraries are supported along with APIs for accessing the RP2040’s hardware, including DMA, IRQs, and the wide variety of fixed-function peripherals and PIO (Programmable IO).
-Additionally the SDK provides higher level libraries for dealing with timers, USB, synchronization and multi-core programming, along with additional high level functionality built using PIO such as audio. The SDK can be used to build anything from simple applications, full fledged runtime environments such as MicroPython, to low level software such as the RP2040’s on chip bootrom itself.
+Additionally the SDK provides higher-level libraries for dealing with timers, USB, synchronization and multi-core programming, along with additional high-level functionality built using PIO, such as audio. The SDK can be used to build anything from simple applications, or full-fledged runtime environments such as MicroPython, to low-level software such as the RP2040’s on-chip bootrom itself.
This documentation is generated from the SDK source tree using Doxygen. It provides basic information on the APIs used for each library, but does not provide usage information. Please refer to the Databooks for usage and more technical information.
## SDK Design
-The RP2040 is a powerful chip, however it is an embedded environment, so both RAM, and program space are at premium. Additionally the trade offs between performance and other factors (e.g. edge case error handling, runtime vs compile time configuration) are necessarily much more visible to the developer than they might be on other higher level platforms.
+The RP2040 is a powerful chip, however it is an embedded environment, so both RAM and program space are at premium. Additionally the trade-offs between performance and other factors (e.g. edge-case error handling, runtime vs compile-time configuration) are necessarily much more visible to the developer than they might be on other higher-level platforms.
-The intention within the SDK has been for features to just work out of the box, with sensible defaults, but also to give the developer as much control and power as possible (if they want it) to fine tune every aspect of the application they are building and the libraries used.
+The intention within the SDK has been for features to just work out of the box, with sensible defaults, but also to give the developer as much control and power as possible (if they want it) to fine-tune every aspect of the application they are building and the libraries used.
## The Build System
-The SDK uses CMake to manage the build. CMake is widely supported by IDEs (Integrated Development Environments), and allows a simple specification of the build (via CMakeLists.txt files), from which CMake can generate a build system (for use by `make`, `ninja` or other build tools) customized for the platform and by any configuration variables the developer chooses for a list of configuration variables).
+The SDK uses CMake to manage the build. CMake is widely supported by IDEs (Integrated Development Environments), and allows a simple specification of the build (via `CMakeLists.txt` files), from which CMake can generate a build system (for use by `make`, `ninja` or other build tools) customized for the platform and by any configuration variables the developer chooses.
-Apart from being a widely used build system for C/C++ development, CMake is fundamental to the way the SDK is structured, and how applications are configured and built.
+Apart from being a widely-used build system for C/C++ development, CMake is fundamental to the way the SDK is structured, and how applications are configured and built.
-The SDK builds an executable which is bare metal, i.e. it includes the entirety of the code needed to run on the device (other than floating point and other optimized code contained in the bootrom within the RP2040).
+The SDK builds an executable which is bare-metal, i.e. it includes the entirety of the code needed to run on the device (other than floating-point and other optimized code contained in the bootrom within the RP2040).
## Examples
-
This SDK documentation contains a number of example code fragments. An index of these examples can be found [here](@ref examples_page). These examples, and any other source code included in this documentation, is Copyright © 2020 Raspberry Pi (Trading) Ltd. and licensed under the [3-Clause BSD](https://opensource.org/licenses/BSD-3-Clause) license.
-
diff --git a/external/pico_sdk_import.cmake b/external/pico_sdk_import.cmake
index 28efe9e..65f8a6f 100644
--- a/external/pico_sdk_import.cmake
+++ b/external/pico_sdk_import.cmake
@@ -29,11 +29,22 @@
if (PICO_SDK_FETCH_FROM_GIT_PATH)
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
endif ()
- FetchContent_Declare(
- pico_sdk
- GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
- GIT_TAG master
- )
+ # GIT_SUBMODULES_RECURSE was added in 3.17
+ if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0")
+ FetchContent_Declare(
+ pico_sdk
+ GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
+ GIT_TAG master
+ GIT_SUBMODULES_RECURSE FALSE
+ )
+ else ()
+ FetchContent_Declare(
+ pico_sdk
+ GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
+ GIT_TAG master
+ )
+ endif ()
+
if (NOT pico_sdk)
message("Downloading Raspberry Pi Pico SDK")
FetchContent_Populate(pico_sdk)
diff --git a/lib/cyw43-driver b/lib/cyw43-driver
new file mode 160000
index 0000000..195dfcc
--- /dev/null
+++ b/lib/cyw43-driver
@@ -0,0 +1 @@
+Subproject commit 195dfcc10bb6f379e3dea45147590db2203d3c7b
diff --git a/lib/lwip b/lib/lwip
new file mode 160000
index 0000000..239918c
--- /dev/null
+++ b/lib/lwip
@@ -0,0 +1 @@
+Subproject commit 239918ccc173cb2c2a62f41a40fd893f57faf1d6
diff --git a/pico_sdk_init.cmake b/pico_sdk_init.cmake
index f6b6f81..5153e2b 100644
--- a/pico_sdk_init.cmake
+++ b/pico_sdk_init.cmake
@@ -53,7 +53,6 @@
message(WARNING "pico_sdk_init() should be called after the project is created (and languages added)")
endif()
add_subdirectory(${PICO_SDK_PATH} pico-sdk)
- pico_is_top_level_project(ISTOP)
endmacro()
macro(add_sub_list_dirs var)
diff --git a/pico_sdk_version.cmake b/pico_sdk_version.cmake
index 1605f56..f00759a 100644
--- a/pico_sdk_version.cmake
+++ b/pico_sdk_version.cmake
@@ -3,7 +3,7 @@
set(PICO_SDK_VERSION_MAJOR 1)
# PICO_BUILD_DEFINE: PICO_SDK_VERSION_MINOR, SDK minor version number, type=int, group=pico_base
# PICO_CONFIG: PICO_SDK_VERSION_MINOR, SDK minor version number, type=int, group=pico_base
-set(PICO_SDK_VERSION_MINOR 3)
+set(PICO_SDK_VERSION_MINOR 4)
# PICO_BUILD_DEFINE: PICO_SDK_VERSION_REVISION, SDK version revision, type=int, group=pico_base
# PICO_CONFIG: PICO_SDK_VERSION_REVISION, SDK version revision, type=int, group=pico_base
set(PICO_SDK_VERSION_REVISION 0)
diff --git a/src/boards/include/boards/adafruit_kb2040.h b/src/boards/include/boards/adafruit_kb2040.h
new file mode 100644
index 0000000..9353082
--- /dev/null
+++ b/src/boards/include/boards/adafruit_kb2040.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+
+#ifndef _BOARDS_ADAFRUIT_KB2040_H
+#define _BOARDS_ADAFRUIT_KB2040_H
+
+// For board detection
+#define ADAFRUIT_KB2040
+
+// On some samples, the xosc can take longer to stabilize than is usual
+#ifndef PICO_XOSC_STARTUP_DELAY_MULTIPLIER
+#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64
+#endif
+
+//------------- UART -------------//
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART 0
+#endif
+
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN 0
+#endif
+
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN 1
+#endif
+
+//------------- LED -------------//
+#ifndef PICO_DEFAULT_WS2812_PIN
+#define PICO_DEFAULT_WS2812_PIN 17
+#endif
+
+//------------- I2C -------------//
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 0
+#endif
+
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 12
+#endif
+
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 13
+#endif
+
+//------------- SPI -------------//
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 0
+#endif
+
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 19
+#endif
+
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 20
+#endif
+
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 18
+#endif
+
+//------------- FLASH -------------//
+
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024)
+#endif
+
+// All boards have B1 RP2040
+#ifndef PICO_RP2040_B0_SUPPORTED
+#define PICO_RP2040_B0_SUPPORTED 0
+#endif
+
+#endif
diff --git a/src/boards/include/boards/adafruit_macropad_rp2040.h b/src/boards/include/boards/adafruit_macropad_rp2040.h
new file mode 100644
index 0000000..3c0c525
--- /dev/null
+++ b/src/boards/include/boards/adafruit_macropad_rp2040.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+
+#ifndef _BOARDS_ADAFRUIT_MACROPAD_RP2040_H
+#define _BOARDS_ADAFRUIT_MACROPAD_RP2040_H
+
+// For board detection
+#define ADAFRUIT_MACROPAD_RP2040
+
+// On some samples, the xosc can take longer to stabilize than is usual
+#ifndef PICO_XOSC_STARTUP_DELAY_MULTIPLIER
+#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64
+#endif
+
+// --- BOARD SPECIFIC ---
+#ifndef ADAFRUIT_MACROPAD_KEY1_PIN
+#define ADAFRUIT_MACROPAD_KEY1_PIN 1
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_KEY2_PIN
+#define ADAFRUIT_MACROPAD_KEY2_PIN 2
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_KEY3_PIN
+#define ADAFRUIT_MACROPAD_KEY3_PIN 3
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_KEY4_PIN
+#define ADAFRUIT_MACROPAD_KEY4_PIN 4
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_KEY5_PIN
+#define ADAFRUIT_MACROPAD_KEY5_PIN 5
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_KEY6_PIN
+#define ADAFRUIT_MACROPAD_KEY6_PIN 6
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_KEY7_PIN
+#define ADAFRUIT_MACROPAD_KEY7_PIN 7
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_KEY8_PIN
+#define ADAFRUIT_MACROPAD_KEY8_PIN 8
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_KEY9_PIN
+#define ADAFRUIT_MACROPAD_KEY9_PIN 9
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_KEY10_PIN
+#define ADAFRUIT_MACROPAD_KEY10_PIN 10
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_KEY11_PIN
+#define ADAFRUIT_MACROPAD_KEY11_PIN 11
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_KEY12_PIN
+#define ADAFRUIT_MACROPAD_KEY12_PIN 12
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_LED_PIN
+#define ADAFRUIT_MACROPAD_LED_PIN 13
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_SPEAKER_ENABLE_PIN
+#define ADAFRUIT_MACROPAD_SPEAKER_ENABLE_PIN 14
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_SPEAKER_PIN
+#define ADAFRUIT_MACROPAD_SPEAKER_PIN 16
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_BUTTON_PIN
+#define ADAFRUIT_MACROPAD_BUTTON_PIN 0
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_ROTA_PIN
+#define ADAFRUIT_MACROPAD_ROTA_PIN 17
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_ROTB_PIN
+#define ADAFRUIT_MACROPAD_ROTB_PIN 18
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_NEOPIXEL_PIN
+#define ADAFRUIT_MACROPAD_NEOPIXEL_PIN 19
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_DISPLAY_OLED_CS_PIN
+#define ADAFRUIT_MACROPAD_DISPLAY_OLED_CS_PIN 22
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_DISPLAY_OLED_RESET_PIN
+#define ADAFRUIT_MACROPAD_DISPLAY_OLED_RESET_PIN 23
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_DISPLAY_OLED_DC_PIN
+#define ADAFRUIT_MACROPAD_DISPLAY_OLED_DC_PIN 24
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_DISPLAY_SCK_PIN
+#define ADAFRUIT_MACROPAD_DISPLAY_SCK_PIN 26
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_DISPLAY_MOSI_PIN
+#define ADAFRUIT_MACROPAD_DISPLAY_MOSI_PIN 27
+#endif
+
+#ifndef ADAFRUIT_MACROPAD_DISPLAY_MISO_PIN
+#define ADAFRUIT_MACROPAD_DISPLAY_MISO_PIN 28
+#endif
+
+// no PICO_DEFAULT_UART
+
+//------------- LED -------------//
+#ifndef PICO_DEFAULT_LED_PIN
+#define PICO_DEFAULT_LED_PIN ADAFRUIT_MACROPAD_LED_PIN
+#endif
+
+#ifndef PICO_DEFAULT_WS2812_PIN
+#define PICO_DEFAULT_WS2812_PIN ADAFRUIT_MACROPAD_NEOPIXEL_PIN
+#endif
+
+//------------- I2C -------------//
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 0
+#endif
+
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 20
+#endif
+
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 21
+#endif
+
+//------------- SPI -------------//
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 1
+#endif
+
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 27
+#endif
+
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 28
+#endif
+
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 26
+#endif
+
+//------------- FLASH -------------//
+
+// Use slower generic flash access
+#define PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 4
+#endif
+
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024)
+#endif
+
+// All boards have B1 RP2040
+#ifndef PICO_FLOAT_SUPPORT_ROM_V1
+#define PICO_FLOAT_SUPPORT_ROM_V1 0
+#endif
+
+#ifndef PICO_DOUBLE_SUPPORT_ROM_V1
+#define PICO_DOUBLE_SUPPORT_ROM_V1 0
+#endif
+
+#endif
diff --git a/src/boards/include/boards/datanoisetv_rp2040_dsp.h b/src/boards/include/boards/datanoisetv_rp2040_dsp.h
new file mode 100644
index 0000000..49a357b
--- /dev/null
+++ b/src/boards/include/boards/datanoisetv_rp2040_dsp.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+//
+//------------------------------------------------------------------------------------------
+// Board definition for the DatanoiseTV RP2040 DSP Board
+//
+// This header may be included by other board headers as "boards/datanoisetv_rp2040_dsp.h"
+
+#ifndef _BOARDS_DATANOISETV_RP2040_DSP_H
+#define _BOARDS_DATANOISETV_RP2040_DSP_H
+
+// For board detection
+#define DATANOISETV_RP2040_DSP
+
+// --- I2C ---
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 0
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 24
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 25
+#endif
+
+// -- FLASH --
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
+#endif
+
+#ifndef PICO_RP2040_B0_SUPPORTED
+#define PICO_RP2040_B0_SUPPORTED 0
+#endif
+
+
+// --- I2S ---
+#ifndef PICO_AUDIO_I2S_DATA_PIN
+#define PICO_AUDIO_I2S_DATA_PIN 16
+#endif
+#ifndef PICO_AUDIO_I2S_CLOCK_PIN_BASE
+#define PICO_AUDIO_I2S_CLOCK_PIN_BASE 17
+#endif
+
+#include "boards/pico.h"
+
+#endif
diff --git a/src/boards/include/boards/eetree_gamekit_rp2040.h b/src/boards/include/boards/eetree_gamekit_rp2040.h
new file mode 100644
index 0000000..f007147
--- /dev/null
+++ b/src/boards/include/boards/eetree_gamekit_rp2040.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+
+#ifndef _BOARDS_EETREE_GAMEKIT_RP2040_H
+#define _BOARDS_EETREE_GAMEKIT_RP2040_H
+
+// For board detection
+#define EETREE_GAMEKIT_RP2040
+
+// --- UART ---
+// no PICO_DEFAULT_UART
+// no PICO_DEFAULT_UART_TX_PIN
+// no PICO_DEFAULT_UART_RX_PIN
+
+// --- LED ---
+#ifndef PICO_DEFAULT_LED_PIN
+ #define PICO_DEFAULT_LED_PIN 4
+#endif
+// no PICO_DEFAULT_WS2812_PIN
+
+// --- I2C ---
+#ifndef PICO_DEFAULT_I2C
+ #define PICO_DEFAULT_I2C 1
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+ #define PICO_DEFAULT_I2C_SDA_PIN 10
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+ #define PICO_DEFAULT_I2C_SCL_PIN 11
+#endif
+
+// --- SPI ---
+// no PICO_DEFAULT_SPI
+// no PICO_DEFAULT_SPI_SCK_PIN
+// no PICO_DEFAULT_SPI_TX_PIN
+// no PICO_DEFAULT_SPI_RX_PIN
+// no PICO_DEFAULT_SPI_CSN_PIN
+
+// --- LCD ---
+#ifndef EETREE_RP2040_LCD_SPI
+ #define EETREE_RP2040_LCD_SPI 0
+#endif
+#ifndef EETREE_RP2040_LCD_DC_PIN
+ #define EETREE_RP2040_LCD_DC_PIN 1
+#endif
+#ifndef EETREE_RP2040_LCD_SCLK_PIN
+ #define EETREE_RP2040_LCD_SCLK_PIN 2
+#endif
+#ifndef EETREE_RP2040_LCD_TX_PIN
+ #define EETREE_RP2040_LCD_TX_PIN 3
+#endif
+#ifndef EETREE_RP2040_LCD_RST_PIN
+ #define EETREE_RP2040_LCD_RST_PIN 0
+#endif
+// no EETREE_RP2040_LCD_CS_PIN
+
+// --- FLASH ---
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+#ifndef PICO_FLASH_SPI_CLKDIV
+ #define PICO_FLASH_SPI_CLKDIV 2
+#endif
+#ifndef PICO_FLASH_SIZE_BYTES
+ #define PICO_FLASH_SIZE_BYTES (2 * 1024 * 1024)
+#endif
+
+// All boards have B1 RP2040
+#ifndef PICO_RP2040_B0_SUPPORTED
+ #define PICO_RP2040_B0_SUPPORTED 0
+#endif
+
+#endif // _BOARDS_EETREE_GAMEKIT_RP2040_H
diff --git a/src/boards/include/boards/pybstick26_rp2040.h b/src/boards/include/boards/garatronic_pybstick26_rp2040.h
similarity index 90%
rename from src/boards/include/boards/pybstick26_rp2040.h
rename to src/boards/include/boards/garatronic_pybstick26_rp2040.h
index 8a9ca41..d1c0298 100644
--- a/src/boards/include/boards/pybstick26_rp2040.h
+++ b/src/boards/include/boards/garatronic_pybstick26_rp2040.h
@@ -9,11 +9,11 @@
// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
// -----------------------------------------------------
-#ifndef _BOARDS_PYBSTICK26_RP2040_H
-#define _BOARDS_PYBSTICK26_RP2040_H
+#ifndef _BOARDS_GARATRONIC_PYBSTICK26_RP2040_H
+#define _BOARDS_GARATRONIC_PYBSTICK26_RP2040_H
// For board detection
-#define PYBSTICK26_RP2040
+#define GARATRONIC_PYBSTICK26_RP2040
// --- UART ---
#ifndef PICO_DEFAULT_UART
@@ -82,4 +82,4 @@
#endif
#endif
-// of #define _BOARDS_PYBSTICK26_RP2040_H
+// of #define _BOARDS_GARATRONIC_PYBSTICK26_RP2040_H
diff --git a/src/boards/include/boards/pico_w.h b/src/boards/include/boards/pico_w.h
new file mode 100644
index 0000000..b4a8bd7
--- /dev/null
+++ b/src/boards/include/boards/pico_w.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+
+// This header may be included by other board headers as "boards/pico.h"
+
+#ifndef _BOARDS_PICO_W_H
+#define _BOARDS_PICO_W_H
+
+// For board detection
+#define RASPBERRYPI_PICO_W
+
+// --- UART ---
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART 0
+#endif
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN 0
+#endif
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN 1
+#endif
+
+// --- LED ---
+// no PICO_DEFAULT_LED_PIN - LED is on Wireless chip
+// no PICO_DEFAULT_WS2812_PIN
+
+// --- I2C ---
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 0
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 4
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 5
+#endif
+
+// --- SPI ---
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 0
+#endif
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 18
+#endif
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 19
+#endif
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 16
+#endif
+#ifndef PICO_DEFAULT_SPI_CSN_PIN
+#define PICO_DEFAULT_SPI_CSN_PIN 17
+#endif
+
+// --- FLASH ---
+
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (2 * 1024 * 1024)
+#endif
+
+// note the SMSP mode pin is on WL_GPIO1
+// #define PICO_SMPS_MODE_PIN
+
+#ifndef PICO_RP2040_B0_SUPPORTED
+#define PICO_RP2040_B0_SUPPORTED 0
+#endif
+
+#ifndef PICO_RP2040_B1_SUPPORTED
+#define PICO_RP2040_B1_SUPPORTED 0
+#endif
+
+#ifndef CYW43_PIN_WL_HOST_WAKE
+#define CYW43_PIN_WL_HOST_WAKE 24
+#endif
+
+#ifndef CYW43_PIN_WL_REG_ON
+#define CYW43_PIN_WL_REG_ON 23
+#endif
+
+#ifndef CYW43_WL_GPIO_COUNT
+#define CYW43_WL_GPIO_COUNT 3
+#endif
+
+#ifndef CYW43_WL_GPIO_LED_PIN
+#define CYW43_WL_GPIO_LED_PIN 0
+#endif
+
+#endif
diff --git a/src/boards/include/boards/pimoroni_badger2040.h b/src/boards/include/boards/pimoroni_badger2040.h
new file mode 100644
index 0000000..0749450
--- /dev/null
+++ b/src/boards/include/boards/pimoroni_badger2040.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+
+#ifndef _BOARDS_PIMORONI_BADGER2040_H
+#define _BOARDS_PIMORONI_BADGER2040_H
+
+// For board detection
+#define PIMORONI_BADGER2040
+
+// --- BOARD SPECIFIC ---
+#define BADGER2040_UART 0
+#define BADGER2040_TX_PIN 0
+#define BADGER2040_RX_PIN 1
+
+#define BADGER2040_I2C 0
+#define BADGER2040_INT_PIN 3
+#define BADGER2040_SDA_PIN 4
+#define BADGER2040_SCL_PIN 5
+
+#define BADGER2040_3V3_EN_PIN 10
+
+#define BADGER2040_SW_DOWN_PIN 11
+#define BADGER2040_SW_A_PIN 12
+#define BADGER2040_SW_B_PIN 13
+#define BADGER2040_SW_C_PIN 14
+#define BADGER2040_SW_UP_PIN 15
+
+#define BADGER2040_INKY_SPI 0
+#define BADGER2040_INKY_MISO_PIN 16
+#define BADGER2040_INKY_CSN_PIN 17
+#define BADGER2040_INKY_SCK_PIN 18
+#define BADGER2040_INKY_MOSI_PIN 19
+#define BADGER2040_INKY_DC_PIN 20
+#define BADGER2040_INKY_RESET_PIN 21
+#define BADGER2040_INKY_BUSY_PIN 26
+
+#define BADGER2040_USER_SW_PIN 23
+#define BADGER2040_USER_LED_PIN 25
+
+#define BADGER2040_VBUS_DETECT_PIN 24
+#define BADGER2040_VREF_POWER_PIN 27
+#define BADGER2040_1V2_REF_PIN 28
+#define BADGER2040_BAT_SENSE_PIN 29
+
+// --- UART ---
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART BADGER2040_UART
+#endif
+
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN BADGER2040_TX_PIN
+#endif
+
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN BADGER2040_RX_PIN
+#endif
+
+// --- LED ---
+#ifndef PICO_DEFAULT_LED_PIN
+#define PICO_DEFAULT_LED_PIN BADGER2040_USER_LED_PIN
+#endif
+// no PICO_DEFAULT_WS2812_PIN
+
+// --- I2C ---
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C BADGER2040_I2C
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN BADGER2040_SDA_PIN
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN BADGER2040_SCL_PIN
+#endif
+
+// --- SPI ---
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI BADGER2040_INKY_SPI
+#endif
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN BADGER2040_INKY_SCK_PIN
+#endif
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN BADGER2040_INKY_MOSI_PIN
+#endif
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN BADGER2040_INKY_MISO_PIN
+#endif
+#ifndef PICO_DEFAULT_SPI_CSN_PIN
+#define PICO_DEFAULT_SPI_CSN_PIN BADGER2040_INKY_CSN_PIN
+#endif
+
+// --- FLASH ---
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (2 * 1024 * 1024)
+#endif
+
+// All boards have B1 RP2040
+#ifndef PICO_RP2040_B0_SUPPORTED
+#define PICO_RP2040_B0_SUPPORTED 0
+#endif
+
+#endif
diff --git a/src/boards/include/boards/pimoroni_interstate75.h b/src/boards/include/boards/pimoroni_interstate75.h
index e2621b0..5b5bf06 100644
--- a/src/boards/include/boards/pimoroni_interstate75.h
+++ b/src/boards/include/boards/pimoroni_interstate75.h
@@ -16,117 +16,42 @@
#define PIMORONI_INTERSTATE75
// --- BOARD SPECIFIC ---
-#ifndef INTERSTATE75_R0_PIN
#define INTERSTATE75_R0_PIN 0
-#endif
-
-#ifndef INTERSTATE75_G0_PIN
#define INTERSTATE75_G0_PIN 1
-#endif
-
-#ifndef INTERSTATE75_B0_PIN
#define INTERSTATE75_B0_PIN 2
-#endif
-
-#ifndef INTERSTATE75_R1_PIN
#define INTERSTATE75_R1_PIN 3
-#endif
-
-#ifndef INTERSTATE75_G1_PIN
#define INTERSTATE75_G1_PIN 4
-#endif
-
-#ifndef INTERSTATE75_B1_PIN
#define INTERSTATE75_B1_PIN 5
-#endif
-#ifndef INTERSTATE75_ROW_A_PIN
#define INTERSTATE75_ROW_A_PIN 6
-#endif
-
-#ifndef INTERSTATE75_ROW_B_PIN
#define INTERSTATE75_ROW_B_PIN 7
-#endif
-
-#ifndef INTERSTATE75_ROW_C_PIN
#define INTERSTATE75_ROW_C_PIN 8
-#endif
-
-#ifndef INTERSTATE75_ROW_D_PIN
#define INTERSTATE75_ROW_D_PIN 9
-#endif
-
-#ifndef INTERSTATE75_ROW_E_PIN
#define INTERSTATE75_ROW_E_PIN 10
-#endif
-#ifndef INTERSTATE75_CLK_PIN
#define INTERSTATE75_CLK_PIN 11
-#endif
-
-#ifndef INTERSTATE75_LAT_PIN
#define INTERSTATE75_LAT_PIN 12
-#endif
-
-#ifndef INTERSTATE75_OE_PIN
#define INTERSTATE75_OE_PIN 13
-#endif
-#ifndef INTERSTATE75_SW_A_PIN
#define INTERSTATE75_SW_A_PIN 14
-#endif
-#ifndef INTERSTATE75_LED_R_PIN
#define INTERSTATE75_LED_R_PIN 16
-#endif
-
-#ifndef INTERSTATE75_LED_G_PIN
#define INTERSTATE75_LED_G_PIN 17
-#endif
-
-#ifndef INTERSTATE75_LED_B_PIN
#define INTERSTATE75_LED_B_PIN 18
-#endif
-#ifndef INTERSTATE75_I2C
#define INTERSTATE75_I2C 0
-#endif
-
-#ifndef INTERSTATE75_INT_PIN
#define INTERSTATE75_INT_PIN 19
-#endif
-
-#ifndef INTERSTATE75_SDA_PIN
#define INTERSTATE75_SDA_PIN 20
-#endif
-
-#ifndef INTERSTATE75_SCL_PIN
#define INTERSTATE75_SCL_PIN 21
-#endif
-#ifndef INTERSTATE75_USER_SW_PIN
#define INTERSTATE75_USER_SW_PIN 23
-#endif
-#ifndef INTERSTATE75_A0_PIN
#define INTERSTATE75_A0_PIN 26
-#endif
-
-#ifndef INTERSTATE75_A1_PIN
#define INTERSTATE75_A1_PIN 27
-#endif
-
-#ifndef INTERSTATE75_A2_PIN
#define INTERSTATE75_A2_PIN 28
-#endif
-
-#ifndef INTERSTATE75_NUM_ADC_PINS
#define INTERSTATE75_NUM_ADC_PINS 3
-#endif
-#ifndef INTERSTATE75_CURRENT_SENSE_PIN
#define INTERSTATE75_CURRENT_SENSE_PIN 29
-#endif
// --- UART ---
// no PICO_DEFAULT_UART
diff --git a/src/boards/include/boards/pimoroni_keybow2040.h b/src/boards/include/boards/pimoroni_keybow2040.h
index 43772e8..baf0c40 100644
--- a/src/boards/include/boards/pimoroni_keybow2040.h
+++ b/src/boards/include/boards/pimoroni_keybow2040.h
@@ -16,89 +16,30 @@
#define PIMORONI_KEYBOW2040
// --- BOARD SPECIFIC ---
-#ifndef KEYBOW2040_I2C_SDA_PIN
#define KEYBOW2040_I2C_SDA_PIN 4
-#endif
-
-#ifndef KEYBOW2040_I2C_SCL_PIN
#define KEYBOW2040_I2C_SCL_PIN 5
-#endif
-
-#ifndef KEYBOW2040_I2C_INT_PIN
#define KEYBOW2040_I2C_INT_PIN 3
-#endif
-#ifndef KEYBOW2040_USER_SW_PIN
#define KEYBOW2040_USER_SW_PIN 23
-#endif
-#ifndef KEYBOW2040_SW0_PIN
#define KEYBOW2040_SW0_PIN 21
-#endif
-
-#ifndef KEYBOW2040_SW1_PIN
#define KEYBOW2040_SW1_PIN 20
-#endif
-
-#ifndef KEYBOW2040_SW2_PIN
#define KEYBOW2040_SW2_PIN 19
-#endif
-
-#ifndef KEYBOW2040_SW3_PIN
#define KEYBOW2040_SW3_PIN 18
-#endif
-
-#ifndef KEYBOW2040_SW4_PIN
#define KEYBOW2040_SW4_PIN 17
-#endif
-
-#ifndef KEYBOW2040_SW5_PIN
#define KEYBOW2040_SW5_PIN 16
-#endif
-
-#ifndef KEYBOW2040_SW6_PIN
#define KEYBOW2040_SW6_PIN 15
-#endif
-
-#ifndef KEYBOW2040_SW7_PIN
#define KEYBOW2040_SW7_PIN 14
-#endif
-
-#ifndef KEYBOW2040_SW8_PIN
#define KEYBOW2040_SW8_PIN 13
-#endif
-
-#ifndef KEYBOW2040_SW9_PIN
#define KEYBOW2040_SW9_PIN 12
-#endif
-
-#ifndef KEYBOW2040_SW10_PIN
#define KEYBOW2040_SW10_PIN 11
-#endif
-
-#ifndef KEYBOW2040_SW11_PIN
#define KEYBOW2040_SW11_PIN 10
-#endif
-
-#ifndef KEYBOW2040_SW12_PIN
#define KEYBOW2040_SW12_PIN 9
-#endif
-
-#ifndef KEYBOW2040_SW13_PIN
#define KEYBOW2040_SW13_PIN 8
-#endif
-
-#ifndef KEYBOW2040_SW14_PIN
#define KEYBOW2040_SW14_PIN 7
-#endif
-
-#ifndef KEYBOW2040_SW15_PIN
#define KEYBOW2040_SW15_PIN 6
-#endif
-#ifndef KEYBOW2040_NUM_SWITCHES_PINS
#define KEYBOW2040_NUM_SWITCHES_PINS 16
-#endif
// --- UART ---
#ifndef PICO_DEFAULT_UART
diff --git a/src/boards/include/boards/pimoroni_motor2040.h b/src/boards/include/boards/pimoroni_motor2040.h
new file mode 100644
index 0000000..00fd91a
--- /dev/null
+++ b/src/boards/include/boards/pimoroni_motor2040.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+
+#ifndef _BOARDS_PIMORONI_MOTOR2040_H
+#define _BOARDS_PIMORONI_MOTOR2040_H
+
+// For board detection
+#define PIMORONI_MOTOR2040
+
+#ifndef MOTOR2040_USE_DISTANCE_SENSOR
+// default to 0, if not explicitly set
+#define MOTOR2040_USE_DISTANCE_SENSOR 0
+#endif
+
+// --- BOARD SPECIFIC ---
+#define MOTOR2040_MOTOR_A_P_PIN 4
+#define MOTOR2040_MOTOR_A_N_PIN 5
+#define MOTOR2040_MOTOR_B_P_PIN 6
+#define MOTOR2040_MOTOR_B_N_PIN 7
+#define MOTOR2040_MOTOR_C_P_PIN 8
+#define MOTOR2040_MOTOR_C_N_PIN 9
+#define MOTOR2040_MOTOR_D_P_PIN 10
+#define MOTOR2040_MOTOR_D_N_PIN 11
+#define MOTOR2040_NUM_MOTORS 4
+
+#define MOTOR2040_ENCODER_A_A_PIN 0
+#define MOTOR2040_ENCODER_A_B_PIN 1
+#define MOTOR2040_ENCODER_B_A_PIN 2
+#define MOTOR2040_ENCODER_B_B_PIN 3
+#define MOTOR2040_ENCODER_C_A_PIN 12
+#define MOTOR2040_ENCODER_C_B_PIN 13
+#define MOTOR2040_ENCODER_D_A_PIN 14
+#define MOTOR2040_ENCODER_D_B_PIN 15
+#define MOTOR2040_NUM_ENCODERS 4
+
+#if MOTOR2040_USE_DISTANCE_SENSOR
+#define MOTOR2040_TRIG_PIN 16
+#define MOTOR2040_ECHO_PIN 17
+#else
+#define MOTOR2040_UART 0
+#define MOTOR2040_TX_PIN 16
+#define MOTOR2040_RX_PIN 17
+#endif
+
+#define MOTOR2040_LED_DATA_PIN 18
+#define MOTOR2040_NUM_LEDS 1
+
+#define MOTOR2040_I2C 0
+#define MOTOR2040_INT_PIN 19
+#define MOTOR2040_SDA_PIN 20
+#define MOTOR2040_SCL_PIN 21
+
+#define MOTOR2040_USER_SW_PIN 23
+
+#define MOTOR2040_A0_PIN 26
+#define MOTOR2040_A1_PIN 27
+#define MOTOR2040_A2_PIN 28
+#define MOTOR2040_NUM_ADC_PINS 3
+
+#define MOTOR2040_SHARED_ADC_PIN 29
+#define MOTOR2040_ADC_ADDR_0_PIN 22
+#define MOTOR2040_ADC_ADDR_1_PIN 24
+#define MOTOR2040_ADC_ADDR_2_PIN 25
+
+#define MOTOR2040_CURRENT_SENSE_A_ADDR 0b000
+#define MOTOR2040_CURRENT_SENSE_B_ADDR 0b001
+#define MOTOR2040_CURRENT_SENSE_C_ADDR 0b010
+#define MOTOR2040_CURRENT_SENSE_D_ADDR 0b011
+#define MOTOR2040_VOLTAGE_SENSE_ADDR 0b100
+#define MOTOR2040_FAULT_SENSE_ADDR 0b101
+#define MOTOR2040_SENSOR_1_ADDR 0b110
+#define MOTOR2040_SENSOR_2_ADDR 0b111
+#define MOTOR2040_NUM_SENSORS 2
+
+// --- UART ---
+#if MOTOR2040_USE_DISTANCE_SENSOR
+// no PICO_DEFAULT_UART
+#else
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART MOTOR2040_UART
+#endif
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN MOTOR2040_TX_PIN
+#endif
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN MOTOR2040_RX_PIN
+#endif
+#endif
+
+// --- LED ---
+// no PICO_DEFAULT_LED_PIN
+#ifndef PICO_DEFAULT_WS2812_PIN
+#define PICO_DEFAULT_WS2812_PIN MOTOR2040_LED_DATA_PIN
+#endif
+
+// --- I2C ---
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C MOTOR2040_I2C
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN MOTOR2040_SDA_PIN
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN MOTOR2040_SCL_PIN
+#endif
+
+// --- SPI ---
+// no PICO_DEFAULT_SPI
+// no PICO_DEFAULT_SPI_SCK_PIN
+// no PICO_DEFAULT_SPI_TX_PIN
+// no PICO_DEFAULT_SPI_RX_PIN
+// no PICO_DEFAULT_SPI_CSN_PIN
+
+// --- FLASH ---
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (2 * 1024 * 1024)
+#endif
+
+// All boards have B1 RP2040
+#ifndef PICO_RP2040_B0_SUPPORTED
+#define PICO_RP2040_B0_SUPPORTED 0
+#endif
+
+#endif
diff --git a/src/boards/include/boards/pimoroni_picolipo_16mb.h b/src/boards/include/boards/pimoroni_picolipo_16mb.h
index 338977b..dfad767 100644
--- a/src/boards/include/boards/pimoroni_picolipo_16mb.h
+++ b/src/boards/include/boards/pimoroni_picolipo_16mb.h
@@ -16,17 +16,9 @@
#define PIMORONI_PICOLIPO_16MB
// --- BOARD SPECIFIC ---
-#ifndef PICOLIPO_USER_SW_PIN
#define PICOLIPO_USER_SW_PIN 23
-#endif
-
-#ifndef PICOLIPO_VBUS_DETECT_PIN
#define PICOLIPO_VBUS_DETECT_PIN 24
-#endif
-
-#ifndef PICOLIPO_BAT_SENSE_PIN
#define PICOLIPO_BAT_SENSE_PIN 29
-#endif
// --- UART ---
#ifndef PICO_DEFAULT_UART
diff --git a/src/boards/include/boards/pimoroni_picolipo_4mb.h b/src/boards/include/boards/pimoroni_picolipo_4mb.h
index 871ed83..aea767d 100644
--- a/src/boards/include/boards/pimoroni_picolipo_4mb.h
+++ b/src/boards/include/boards/pimoroni_picolipo_4mb.h
@@ -16,17 +16,9 @@
#define PIMORONI_PICOLIPO_4MB
// --- BOARD SPECIFIC ---
-#ifndef PICOLIPO_USER_SW_PIN
#define PICOLIPO_USER_SW_PIN 23
-#endif
-
-#ifndef PICOLIPO_VBUS_DETECT_PIN
#define PICOLIPO_VBUS_DETECT_PIN 24
-#endif
-
-#ifndef PICOLIPO_BAT_SENSE_PIN
#define PICOLIPO_BAT_SENSE_PIN 29
-#endif
// --- UART ---
#ifndef PICO_DEFAULT_UART
diff --git a/src/boards/include/boards/pimoroni_picosystem.h b/src/boards/include/boards/pimoroni_picosystem.h
index 1e7c80e..0717b05 100644
--- a/src/boards/include/boards/pimoroni_picosystem.h
+++ b/src/boards/include/boards/pimoroni_picosystem.h
@@ -16,97 +16,35 @@
#define PIMORONI_PICOSYSTEM
// --- BOARD SPECIFIC ---
-#ifndef PICOSYSTEM_VBUS_DETECT_PIN
#define PICOSYSTEM_VBUS_DETECT_PIN 2
-#endif
-#ifndef PICOSYSTEM_LCD_SPI
#define PICOSYSTEM_LCD_SPI 0
-#endif
-
-#ifndef PICOSYSTEM_LCD_RESET_PIN
#define PICOSYSTEM_LCD_RESET_PIN 4
-#endif
-
-#ifndef PICOSYSTEM_LCD_CSN_PIN
#define PICOSYSTEM_LCD_CSN_PIN 5
-#endif
-
-#ifndef PICOSYSTEM_LCD_SCLK_PIN
#define PICOSYSTEM_LCD_SCLK_PIN 6
-#endif
-
-#ifndef PICOSYSTEM_LCD_MOSI_PIN
#define PICOSYSTEM_LCD_MOSI_PIN 7
-#endif
-
-#ifndef PICOSYSTEM_LCD_VSYNC_PIN
#define PICOSYSTEM_LCD_VSYNC_PIN 8
-#endif
-
-#ifndef PICOSYSTEM_LCD_DC_PIN
#define PICOSYSTEM_LCD_DC_PIN 9
-#endif
-#ifndef PICOSYSTEM_AUDIO_PIN
#define PICOSYSTEM_AUDIO_PIN 11
-#endif
-#ifndef PICOSYSTEM_BACKLIGHT_PIN
#define PICOSYSTEM_BACKLIGHT_PIN 12
-#endif
-#ifndef PICOSYSTEM_LED_G_PIN
#define PICOSYSTEM_LED_G_PIN 13
-#endif
-
-#ifndef PICOSYSTEM_LED_R_PIN
#define PICOSYSTEM_LED_R_PIN 14
-#endif
-
-#ifndef PICOSYSTEM_LED_B_PIN
#define PICOSYSTEM_LED_B_PIN 15
-#endif
-#ifndef PICOSYSTEM_SW_Y_PIN
#define PICOSYSTEM_SW_Y_PIN 16
-#endif
-
-#ifndef PICOSYSTEM_SW_X_PIN
#define PICOSYSTEM_SW_X_PIN 17
-#endif
-
-#ifndef PICOSYSTEM_SW_A_PIN
#define PICOSYSTEM_SW_A_PIN 18
-#endif
-
-#ifndef PICOSYSTEM_SW_B_PIN
#define PICOSYSTEM_SW_B_PIN 19
-#endif
-
-#ifndef PICOSYSTEM_SW_DOWN_PIN
#define PICOSYSTEM_SW_DOWN_PIN 20
-#endif
-
-#ifndef PICOSYSTEM_SW_RIGHT_PIN
#define PICOSYSTEM_SW_RIGHT_PIN 21
-#endif
-
-#ifndef PICOSYSTEM_SW_LEFT_PIN
#define PICOSYSTEM_SW_LEFT_PIN 22
-#endif
-
-#ifndef PICOSYSTEM_SW_UP_PIN
#define PICOSYSTEM_SW_UP_PIN 23
-#endif
-#ifndef PICOSYSTEM_CHARGE_STAT_PIN
#define PICOSYSTEM_CHARGE_STAT_PIN 24
-#endif
-
-#ifndef PICOSYSTEM_BAT_SENSE_PIN
#define PICOSYSTEM_BAT_SENSE_PIN 26
-#endif
// --- UART ---
#ifndef PICO_DEFAULT_UART
diff --git a/src/boards/include/boards/pimoroni_plasma2040.h b/src/boards/include/boards/pimoroni_plasma2040.h
index 226aaf5..2cdb4c5 100644
--- a/src/boards/include/boards/pimoroni_plasma2040.h
+++ b/src/boards/include/boards/pimoroni_plasma2040.h
@@ -16,73 +16,29 @@
#define PIMORONI_PLASMA2040
// --- BOARD SPECIFIC ---
-#ifndef PLASMA2040_SW_A_PIN
#define PLASMA2040_SW_A_PIN 12
-#endif
-
-#ifndef PLASMA2040_SW_B_PIN
#define PLASMA2040_SW_B_PIN 13
-#endif
-#ifndef PLASMA2040_CLK_PIN
#define PLASMA2040_CLK_PIN 14
-#endif
-
-#ifndef PLASMA2040_DATA_PIN
#define PLASMA2040_DATA_PIN 15
-#endif
-#ifndef PLASMA2040_LED_R_PIN
#define PLASMA2040_LED_R_PIN 16
-#endif
-
-#ifndef PLASMA2040_LED_G_PIN
#define PLASMA2040_LED_G_PIN 17
-#endif
-
-#ifndef PLASMA2040_LED_B_PIN
#define PLASMA2040_LED_B_PIN 18
-#endif
-#ifndef PLASMA2040_I2C
#define PLASMA2040_I2C 0
-#endif
-
-#ifndef PLASMA2040_INT_PIN
#define PLASMA2040_INT_PIN 19
-#endif
-
-#ifndef PLASMA2040_SDA_PIN
#define PLASMA2040_SDA_PIN 20
-#endif
-
-#ifndef PLASMA2040_SCL_PIN
#define PLASMA2040_SCL_PIN 21
-#endif
-#ifndef PLASMA2040_USER_SW_PIN
#define PLASMA2040_USER_SW_PIN 23
-#endif
-#ifndef PLASMA2040_A0_PIN
#define PLASMA2040_A0_PIN 26
-#endif
-
-#ifndef PLASMA2040_A1_PIN
#define PLASMA2040_A1_PIN 27
-#endif
-
-#ifndef PLASMA2040_A2_PIN
#define PLASMA2040_A2_PIN 28
-#endif
-
-#ifndef PLASMA2040_NUM_ADC_PINS
#define PLASMA2040_NUM_ADC_PINS 3
-#endif
-#ifndef PLASMA2040_CURRENT_SENSE_PIN
#define PLASMA2040_CURRENT_SENSE_PIN 29
-#endif
// --- UART ---
// no PICO_DEFAULT_UART
diff --git a/src/boards/include/boards/pimoroni_servo2040.h b/src/boards/include/boards/pimoroni_servo2040.h
new file mode 100644
index 0000000..17fd76f
--- /dev/null
+++ b/src/boards/include/boards/pimoroni_servo2040.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+
+#ifndef _BOARDS_PIMORONI_SERVO2040_H
+#define _BOARDS_PIMORONI_SERVO2040_H
+
+// For board detection
+#define PIMORONI_SERVO2040
+
+// --- BOARD SPECIFIC ---
+#define SERVO2040_SERVO_1_PIN 0
+#define SERVO2040_SERVO_2_PIN 1
+#define SERVO2040_SERVO_3_PIN 2
+#define SERVO2040_SERVO_4_PIN 3
+#define SERVO2040_SERVO_5_PIN 4
+#define SERVO2040_SERVO_6_PIN 5
+#define SERVO2040_SERVO_7_PIN 6
+#define SERVO2040_SERVO_8_PIN 7
+#define SERVO2040_SERVO_9_PIN 8
+#define SERVO2040_SERVO_10_PIN 9
+#define SERVO2040_SERVO_11_PIN 10
+#define SERVO2040_SERVO_12_PIN 11
+#define SERVO2040_SERVO_13_PIN 12
+#define SERVO2040_SERVO_14_PIN 13
+#define SERVO2040_SERVO_15_PIN 14
+#define SERVO2040_SERVO_16_PIN 15
+#define SERVO2040_SERVO_17_PIN 16
+#define SERVO2040_SERVO_18_PIN 17
+#define SERVO2040_NUM_SERVOS 18
+
+#define SERVO2040_LED_DATA_PIN 18
+#define SERVO2040_NUM_LEDS 6
+
+#define SERVO2040_I2C 0
+#define SERVO2040_INT_PIN 19
+#define SERVO2040_SDA_PIN 20
+#define SERVO2040_SCL_PIN 21
+
+#define SERVO2040_USER_SW_PIN 23
+
+#define SERVO2040_A0_PIN 26
+#define SERVO2040_A1_PIN 27
+#define SERVO2040_A2_PIN 28
+#define SERVO2040_NUM_ADC_PINS 3
+
+#define SERVO2040_SHARED_ADC_PIN 29
+#define SERVO2040_ADC_ADDR_0_PIN 22
+#define SERVO2040_ADC_ADDR_1_PIN 24
+#define SERVO2040_ADC_ADDR_2_PIN 25
+
+#define SERVO2040_SENSOR_1_ADDR 0b000
+#define SERVO2040_SENSOR_2_ADDR 0b001
+#define SERVO2040_SENSOR_3_ADDR 0b010
+#define SERVO2040_SENSOR_4_ADDR 0b011
+#define SERVO2040_SENSOR_5_ADDR 0b100
+#define SERVO2040_SENSOR_6_ADDR 0b101
+#define SERVO2040_VOLTAGE_SENSE_ADDR 0b110
+#define SERVO2040_CURRENT_SENSE_ADDR 0b111
+#define SERVO2040_NUM_SENSORS 6
+
+// --- UART ---
+// no PICO_DEFAULT_UART
+// no PICO_DEFAULT_UART_TX_PIN
+// no PICO_DEFAULT_UART_RX_PIN
+
+// --- LED ---
+// no PICO_DEFAULT_LED_PIN
+#ifndef PICO_DEFAULT_WS2812_PIN
+#define PICO_DEFAULT_WS2812_PIN SERVO2040_LED_DATA_PIN
+#endif
+
+// --- I2C ---
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C SERVO2040_I2C
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN SERVO2040_SDA_PIN
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN SERVO2040_SCL_PIN
+#endif
+
+// --- SPI ---
+// no PICO_DEFAULT_SPI
+// no PICO_DEFAULT_SPI_SCK_PIN
+// no PICO_DEFAULT_SPI_TX_PIN
+// no PICO_DEFAULT_SPI_RX_PIN
+// no PICO_DEFAULT_SPI_CSN_PIN
+
+// --- FLASH ---
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (2 * 1024 * 1024)
+#endif
+
+// All boards have B1 RP2040
+#ifndef PICO_RP2040_B0_SUPPORTED
+#define PICO_RP2040_B0_SUPPORTED 0
+#endif
+
+#endif
diff --git a/src/boards/include/boards/pimoroni_tiny2040.h b/src/boards/include/boards/pimoroni_tiny2040.h
index 51d17f6..f407008 100644
--- a/src/boards/include/boards/pimoroni_tiny2040.h
+++ b/src/boards/include/boards/pimoroni_tiny2040.h
@@ -14,47 +14,22 @@
// For board detection
#define PIMORONI_TINY2040
+#define PIMORONI_TINY2040_8MB
// --- BOARD SPECIFIC ---
-#ifndef TINY2040_LED_R_PIN
#define TINY2040_LED_R_PIN 18
-#endif
-
-#ifndef TINY2040_LED_G_PIN
#define TINY2040_LED_G_PIN 19
-#endif
-
-#ifndef TINY2040_LED_B_PIN
#define TINY2040_LED_B_PIN 20
-#endif
-#ifndef TINY2040_USER_SW_PIN
#define TINY2040_USER_SW_PIN 23
-#endif
-#ifndef TINY2040_A0_PIN
#define TINY2040_A0_PIN 26
-#endif
-
-#ifndef TINY2040_A1_PIN
#define TINY2040_A1_PIN 27
-#endif
-
-#ifndef TINY2040_A2_PIN
#define TINY2040_A2_PIN 28
-#endif
-
-#ifndef TINY2040_A3_PIN
#define TINY2040_A3_PIN 29
-#endif
-#ifndef TINY2040_NUM_IO_PINS
#define TINY2040_NUM_IO_PINS 8
-#endif
-
-#ifndef TINY2040_NUM_ADC_PINS
#define TINY2040_NUM_ADC_PINS 4
-#endif
// --- UART ---
#ifndef PICO_DEFAULT_UART
diff --git a/src/boards/include/boards/pimoroni_tiny2040_2mb.h b/src/boards/include/boards/pimoroni_tiny2040_2mb.h
new file mode 100644
index 0000000..e32d370
--- /dev/null
+++ b/src/boards/include/boards/pimoroni_tiny2040_2mb.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+
+#ifndef _BOARDS_PIMORONI_TINY2040_2MB_H
+#define _BOARDS_PIMORONI_TINY2040_2MB_H
+
+// For board detection
+#define PIMORONI_TINY2040
+#define PIMORONI_TINY2040_2MB
+
+// --- BOARD SPECIFIC ---
+#define TINY2040_LED_R_PIN 18
+#define TINY2040_LED_G_PIN 19
+#define TINY2040_LED_B_PIN 20
+
+#define TINY2040_USER_SW_PIN 23
+
+#define TINY2040_A0_PIN 26
+#define TINY2040_A1_PIN 27
+#define TINY2040_A2_PIN 28
+#define TINY2040_A3_PIN 29
+
+#define TINY2040_NUM_IO_PINS 8
+#define TINY2040_NUM_ADC_PINS 4
+
+// --- UART ---
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART 0
+#endif
+
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN 0
+#endif
+
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN 1
+#endif
+
+// --- LED ---
+// Included so basic examples will work, and set it to the green LED
+#ifndef PICO_DEFAULT_LED_PIN
+#define PICO_DEFAULT_LED_PIN TINY2040_LED_G_PIN
+#endif
+// no PICO_DEFAULT_WS2812_PIN
+
+#ifndef PICO_DEFAULT_LED_PIN_INVERTED
+#define PICO_DEFAULT_LED_PIN_INVERTED 1
+#endif
+
+// --- I2C ---
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 1
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 2
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 3
+#endif
+
+// --- SPI ---
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 0
+#endif
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 6
+#endif
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 7
+#endif
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 4
+#endif
+#ifndef PICO_DEFAULT_SPI_CSN_PIN
+#define PICO_DEFAULT_SPI_CSN_PIN 5
+#endif
+
+// --- FLASH ---
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (2 * 1024 * 1024)
+#endif
+
+// All boards have B1 RP2040
+#ifndef PICO_RP2040_B0_SUPPORTED
+#define PICO_RP2040_B0_SUPPORTED 0
+#endif
+
+#endif
diff --git a/src/boards/include/boards/seeed_xiao_rp2040.h b/src/boards/include/boards/seeed_xiao_rp2040.h
new file mode 100644
index 0000000..2fd3687
--- /dev/null
+++ b/src/boards/include/boards/seeed_xiao_rp2040.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+
+#ifndef _BOARDS_SEEED_XIAO_RP2040_H
+#define _BOARDS_SEEED_XIAO_RP2040_H
+
+// For board detection
+#define SEEED_XIAO_RP2040
+
+// On some samples, the xosc can take longer to stabilize than is usual
+#ifndef PICO_XOSC_STARTUP_DELAY_MULTIPLIER
+#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64
+#endif
+
+//------------- UART -------------//
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART 0
+#endif
+
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN 0
+#endif
+
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN 1
+#endif
+
+//------------- LED -------------//
+#ifndef PICO_DEFAULT_LED_PIN
+#define PICO_DEFAULT_LED_PIN 25
+#endif
+
+#ifndef PICO_DEFAULT_LED_PIN_INVERTED
+#define PICO_DEFAULT_LED_PIN_INVERTED 1
+#endif
+
+#ifndef PICO_DEFAULT_WS2812_PIN
+#define PICO_DEFAULT_WS2812_PIN 12
+#endif
+
+#ifndef PICO_DEFAULT_WS2812_POWER_PIN
+#define PICO_DEFAULT_WS2812_POWER_PIN 11
+#endif
+
+//------------- I2C -------------//
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 1
+#endif
+
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 6
+#endif
+
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 7
+#endif
+
+//------------- SPI -------------//
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 0
+#endif
+
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 3
+#endif
+
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 4
+#endif
+
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 2
+#endif
+
+//------------- FLASH -------------//
+
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (2 * 1024 * 1024)
+#endif
+
+// All boards have B1 RP2040
+#ifndef PICO_RP2040_B0_SUPPORTED
+#define PICO_RP2040_B0_SUPPORTED 0
+#endif
+
+#endif
diff --git a/src/boards/include/boards/solderparty_rp2040_stamp.h b/src/boards/include/boards/solderparty_rp2040_stamp.h
new file mode 100644
index 0000000..fb3c5b9
--- /dev/null
+++ b/src/boards/include/boards/solderparty_rp2040_stamp.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+//
+//------------------------------------------------------------------------------------------
+// Board definition for the Solder Party RP2040 Stamp
+//
+// This header may be included by other board headers as "boards/solderparty_rp2040_stamp.h"
+
+#ifndef _BOARDS_SOLDERPARTY_RP2040_STAMP_H
+#define _BOARDS_SOLDERPARTY_RP2040_STAMP_H
+
+// For board detection
+#define SOLDERPARTY_RP2040_STAMP
+
+// --- UART ---
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART 0
+#endif
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN 0
+#endif
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN 1
+#endif
+
+// --- Neopixel ---
+#ifndef PICO_DEFAULT_WS2812_PIN
+#define PICO_DEFAULT_WS2812_PIN 21
+#endif
+
+// --- I2C ---
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 0
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 4
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 5
+#endif
+
+// --- SPI ---
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 0
+#endif
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 18
+#endif
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 19
+#endif
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 16
+#endif
+#ifndef PICO_DEFAULT_SPI_CSN_PIN
+#define PICO_DEFAULT_SPI_CSN_PIN 17
+#endif
+
+// --- FLASH ---
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024)
+#endif
+
+// All production boards have B1 RP2040
+#ifndef PICO_RP2040_B0_SUPPORTED
+#define PICO_RP2040_B0_SUPPORTED 0
+#endif
+
+#endif
diff --git a/src/boards/include/boards/solderparty_rp2040_stamp_carrier.h b/src/boards/include/boards/solderparty_rp2040_stamp_carrier.h
new file mode 100644
index 0000000..aac45f4
--- /dev/null
+++ b/src/boards/include/boards/solderparty_rp2040_stamp_carrier.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+//
+//------------------------------------------------------------------------------------------
+// Board definition for the Solder Party RP2040 Stamp Carrier
+//
+// This header may be included by other board headers as "boards/solderparty_rp2040_stamp_carrier.h"
+
+#ifndef _BOARDS_SOLDERPARTY_RP2040_STAMP_CARRIER_H
+#define _BOARDS_SOLDERPARTY_RP2040_STAMP_CARRIER_H
+
+// For board detection
+#define SOLDERPARTY_RP2040_STAMP_CARRIER
+
+#ifndef PICO_DEFAULT_LED_PIN
+#define PICO_DEFAULT_LED_PIN 20
+#endif
+
+#include "solderparty_rp2040_stamp.h"
+
+#endif
diff --git a/src/boards/include/boards/solderparty_rp2040_stamp_round_carrier.h b/src/boards/include/boards/solderparty_rp2040_stamp_round_carrier.h
new file mode 100644
index 0000000..bb9d335
--- /dev/null
+++ b/src/boards/include/boards/solderparty_rp2040_stamp_round_carrier.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+//
+//------------------------------------------------------------------------------------------
+// Board definition for the Solder Party RP2040 Stamp Round Carrier
+//
+// This header may be included by other board headers as "boards/solderparty_rp2040_stamp_round_carrier.h"
+
+#ifndef _BOARDS_SOLDERPARTY_RP2040_STAMP_ROUND_CARRIER_H
+#define _BOARDS_SOLDERPARTY_RP2040_STAMP_ROUND_CARRIER_H
+
+// For board detection
+#define SOLDERPARTY_RP2040_STAMP_ROUND_CARRIER
+
+// --- User LED ---
+#ifndef PICO_DEFAULT_LED_PIN
+#define PICO_DEFAULT_LED_PIN 25
+#endif
+
+// --- UART ---
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART 0
+#endif
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN 16
+#endif
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN 17
+#endif
+
+// --- Neopixel Ring ---
+#ifndef PICO_DEFAULT_WS2812_PIN
+#define PICO_DEFAULT_WS2812_PIN 24
+#endif
+
+// --- On-Stamp Neopixel ---
+#ifndef SOLDERPARTY_RP2040_STAMP_WS2812_PIN
+#define SOLDERPARTY_RP2040_STAMP_WS2812_PIN 21
+#endif
+
+// --- I2C ---
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 0
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 0
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 1
+#endif
+
+// --- SPI ---
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 1
+#endif
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 10
+#endif
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 11
+#endif
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 8
+#endif
+#ifndef PICO_DEFAULT_SPI_CSN_PIN
+#define PICO_DEFAULT_SPI_CSN_PIN 9
+#endif
+
+#include "solderparty_rp2040_stamp.h"
+
+#endif
diff --git a/src/boards/include/boards/vgaboard.h b/src/boards/include/boards/vgaboard.h
index f0b6f0e..dd4bf6c 100644
--- a/src/boards/include/boards/vgaboard.h
+++ b/src/boards/include/boards/vgaboard.h
@@ -53,12 +53,25 @@
#define PICO_DEFAULT_UART_RX_PIN 21
#endif
+#ifndef PICO_SCANVIDEO_COLOR_PIN_BASE
#define PICO_SCANVIDEO_COLOR_PIN_BASE VGABOARD_VGA_COLOR_PIN_BASE
-#define PICO_SCANVIDEO_SYNC_PIN_BASE VGABOARD_VGA_SYNC_PIN_BASE
+#endif
+#ifndef PICO_SCANVIDEO_SYNC_PIN_BASE
+#define PICO_SCANVIDEO_SYNC_PIN_BASE VGABOARD_VGA_SYNC_PIN_BASE
+#endif
+
+#ifndef PICO_SD_CLK_PIN
#define PICO_SD_CLK_PIN VGABOARD_SD_CLK_PIN
+#endif
+
+#ifndef PICO_SD_CMD_PIN
#define PICO_SD_CMD_PIN VGABOARD_SD_CMD_PIN
+#endif
+
+#ifndef PICO_SD_DAT0_PIN
#define PICO_SD_DAT0_PIN VGABOARD_SD_DAT0_PIN
+#endif
// 1 or 4
#ifndef PICO_SD_DAT_PIN_COUNT
@@ -66,13 +79,24 @@
#endif
// 1 or -1
+#ifndef PICO_SD_DAT_PIN_INCREMENT
#define PICO_SD_DAT_PIN_INCREMENT 1
+#endif
+#ifndef PICO_AUDIO_I2S_DATA_PIN
#define PICO_AUDIO_I2S_DATA_PIN VGABOARD_I2S_DIN_PIN
+#endif
+#ifndef PICO_AUDIO_I2S_CLOCK_PIN_BASE
#define PICO_AUDIO_I2S_CLOCK_PIN_BASE VGABOARD_I2S_BCK_PIN
+#endif
+#ifndef PICO_AUDIO_PWM_L_PIN
#define PICO_AUDIO_PWM_L_PIN VGABOARD_PWM_L_PIN
+#endif
+
+#ifndef PICO_AUDIO_PWM_R_PIN
#define PICO_AUDIO_PWM_R_PIN VGABOARD_PWM_R_PIN
+#endif
#define PICO_VGA_BOARD
diff --git a/src/boards/include/boards/wiznet_w5100s_evb_pico.h b/src/boards/include/boards/wiznet_w5100s_evb_pico.h
new file mode 100644
index 0000000..585f1d1
--- /dev/null
+++ b/src/boards/include/boards/wiznet_w5100s_evb_pico.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+
+
+
+#ifndef _BOARDS_WIZNET_W5100S_EVB_PICO_H
+#define _BOARDS_WIZNET_W5100S_EVB_PICO_H
+
+// For board detection
+#define WIZNET_W5100S_EVB_PICO
+
+// --- BOARD SPECIFIC ---
+#ifndef W5100S_EVB_PICO_INTN_PIN
+#define W5100S_EVB_PICO_INTN_PIN 21
+#endif
+
+#ifndef W5100S_EVB_PICO_RSTN_PIN
+#define W5100S_EVB_PICO_RSTN_PIN 20
+#endif
+
+#ifndef W5100S_EVB_PICO_A0_PIN
+#define W5100S_EVB_PICO_A0_PIN 26
+#endif
+#ifndef W5100S_EVB_PICO_A1_PIN
+#define W5100S_EVB_PICO_A1_PIN 27
+#endif
+#ifndef W5100S_EVB_PICO_A2_PIN
+#define W5100S_EVB_PICO_A2_PIN 28
+#endif
+
+// --- LED ---
+#ifndef PICO_DEFAULT_LED_PIN
+#define PICO_DEFAULT_LED_PIN 25
+#endif
+
+// --- UART ---
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART 0
+#endif
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN 0
+#endif
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN 1
+#endif
+
+
+// --- I2C ---
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 0
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 4
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 5
+#endif
+
+// --- SPI ---
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 0
+#endif
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 18
+#endif
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 19
+#endif
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 16
+#endif
+#ifndef PICO_DEFAULT_SPI_CSN_PIN
+#define PICO_DEFAULT_SPI_CSN_PIN 17
+#endif
+
+// --- FLASH ---
+
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (2 * 1024 * 1024)
+#endif
+
+// Drive high to force power supply into PWM mode (lower ripple on 3V3 at light loads)
+#define PICO_SMPS_MODE_PIN 23
+
+#ifndef PICO_RP2040_B0_SUPPORTED
+#define PICO_RP2040_B0_SUPPORTED 0
+#endif
+
+#endif
diff --git a/src/boards/pico_w.cmake b/src/boards/pico_w.cmake
new file mode 100644
index 0000000..15b901d
--- /dev/null
+++ b/src/boards/pico_w.cmake
@@ -0,0 +1,2 @@
+set(PICO_CYW43_SUPPORTED "1" CACHE INTERNAL "Try to add support for PICO_CYW43")
+include(${CMAKE_CURRENT_LIST_DIR}/generic_board.cmake)
diff --git a/src/common/pico_base/include/pico.h b/src/common/pico_base/include/pico.h
index 1b73651..784566e 100644
--- a/src/common/pico_base/include/pico.h
+++ b/src/common/pico_base/include/pico.h
@@ -16,9 +16,18 @@
* This header may be included by assembly code
*/
+#define __PICO_STRING(x) #x
+#define __PICO_XSTRING(x) __PICO_STRING(x)
+
#include "pico/types.h"
#include "pico/version.h"
+
+// PICO_CONFIG: PICO_CONFIG_HEADER, unquoted path to header include in place of the default pico/config.h which may be desirable for build systems which can't easily generate the config_autogen header, group=pico_base
+#ifdef PICO_CONFIG_HEADER
+#include __PICO_XSTRING(PICO_CONFIG_HEADER)
+#else
#include "pico/config.h"
+#endif
#include "pico/platform.h"
#include "pico/error.h"
diff --git a/src/common/pico_base/include/pico/config.h b/src/common/pico_base/include/pico/config.h
index 8d69269..10a9c6a 100644
--- a/src/common/pico_base/include/pico/config.h
+++ b/src/common/pico_base/include/pico/config.h
@@ -18,4 +18,9 @@
#include "pico/config_autogen.h"
-#endif
\ No newline at end of file
+// PICO_CONFIG: PICO_CONFIG_RTOS_ADAPTER_HEADER, unquoted path to header include in the default pico/config.h for RTOS integration defines that must be included in all sources, group=pico_base
+#ifdef PICO_CONFIG_RTOS_ADAPTER_HEADER
+#include __PICO_XSTRING(PICO_CONFIG_RTOS_ADAPTER_HEADER)
+#endif
+
+#endif
diff --git a/src/common/pico_base/include/pico/error.h b/src/common/pico_base/include/pico/error.h
index fadb45e..a5cbc39 100644
--- a/src/common/pico_base/include/pico/error.h
+++ b/src/common/pico_base/include/pico/error.h
@@ -10,14 +10,18 @@
#ifndef __ASSEMBLER__
/*!
- * Common return codes from pico_sdk methods that return a status
+ * \brief Common return codes from pico_sdk methods that return a status
+ * \ingroup pico_base
*/
-enum {
+enum pico_error_codes {
PICO_OK = 0,
PICO_ERROR_NONE = 0,
PICO_ERROR_TIMEOUT = -1,
PICO_ERROR_GENERIC = -2,
PICO_ERROR_NO_DATA = -3,
+ PICO_ERROR_NOT_PERMITTED = -4,
+ PICO_ERROR_INVALID_ARG = -5,
+ PICO_ERROR_IO = -6,
};
#endif // !__ASSEMBLER__
diff --git a/src/common/pico_binary_info/include/pico/binary_info.h b/src/common/pico_binary_info/include/pico/binary_info.h
index 77b1c08..b5c08e7 100644
--- a/src/common/pico_binary_info/include/pico/binary_info.h
+++ b/src/common/pico_binary_info/include/pico/binary_info.h
@@ -25,7 +25,5 @@
#if !PICO_ON_DEVICE && !defined(PICO_NO_BINARY_INFO)
#define PICO_NO_BINARY_INFO 1
#endif
-#if !PICO_NO_BINARY_INFO
#include "pico/binary_info/code.h"
#endif
-#endif
diff --git a/src/common/pico_binary_info/include/pico/binary_info/code.h b/src/common/pico_binary_info/include/pico/binary_info/code.h
index e87a2cd..9478477 100644
--- a/src/common/pico_binary_info/include/pico/binary_info/code.h
+++ b/src/common/pico_binary_info/include/pico/binary_info/code.h
@@ -7,7 +7,12 @@
#ifndef _PICO_BINARY_INFO_CODE_H
#define _PICO_BINARY_INFO_CODE_H
+// pico.h is not available when PICO_NO_BINARY_INFO=1 is used for builds outside of the SDK (e.g. picotool)
+// and only needed anyway (because of macro definitions) in PICO_NO_BINARY_INFO=0 builds
+#if !PICO_NO_BINARY_INFO
#include "pico.h"
+#endif
+
#include "pico/binary_info/structure.h"
#if !PICO_NO_BINARY_INFO
@@ -131,7 +136,7 @@
#define bi_pin_range_with_func(plo, phi, func) __bi_encoded_pins_with_func(BI_PINS_ENCODING_RANGE | ((func << 3)) | ((plo) << 7) | ((phi) << 12))
#define bi_pin_mask_with_name(pmask, label) __bi_pins_with_name((pmask), (label))
-// names are sperated by | ... i.e. "name1|name2|name3"
+// names are separated by | ... i.e. "name1|name2|name3"
#define bi_pin_mask_with_names(pmask, label) __bi_pins_with_name((pmask), (label))
#define bi_1pin_with_name(p0, name) bi_pin_mask_with_name(1u << (p0), name)
#define bi_2pins_with_names(p0, name0, p1, name1) bi_pin_mask_with_names((1u << (p0)) | (1u << (p1)), name0 "|" name1)
diff --git a/src/common/pico_sync/include/pico/mutex.h b/src/common/pico_sync/include/pico/mutex.h
index e834dc5..ca93760 100644
--- a/src/common/pico_sync/include/pico/mutex.h
+++ b/src/common/pico_sync/include/pico/mutex.h
@@ -289,7 +289,7 @@
*
* But the initialization of the mutex is performed automatically during runtime initialization
*/
-#define auto_init_recursive_mutex(name) static __attribute__((section(".mutex_array"))) recursive_mutex_t name = { .core.spin_lock = (spin_lock_t *)1 /* marker for runtime_init */ }
+#define auto_init_recursive_mutex(name) static __attribute__((section(".mutex_array"))) recursive_mutex_t name = { .core = { .spin_lock = (spin_lock_t *)1 /* marker for runtime_init */ }, .owner = 0, .enter_count = 0 }
#ifdef __cplusplus
}
diff --git a/src/common/pico_sync/include/pico/sem.h b/src/common/pico_sync/include/pico/sem.h
index 6244e32..f9f724b 100644
--- a/src/common/pico_sync/include/pico/sem.h
+++ b/src/common/pico_sync/include/pico/sem.h
@@ -122,6 +122,17 @@
*/
bool sem_acquire_block_until(semaphore_t *sem, absolute_time_t until);
+/*! \brief Attempt to acquire a permit from a semaphore without blocking
+ * \ingroup sem
+ *
+ * This function will return false without blocking if no permits are
+ * available, otherwise it will acquire a permit and return true.
+ *
+ * \param sem Pointer to semaphore structure
+ * \return true if permit was acquired.
+ */
+bool sem_try_acquire(semaphore_t *sem);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/common/pico_sync/sem.c b/src/common/pico_sync/sem.c
index 06b4946..ec49fdb 100644
--- a/src/common/pico_sync/sem.c
+++ b/src/common/pico_sync/sem.c
@@ -23,7 +23,7 @@
uint32_t save = spin_lock_blocking(sem->core.spin_lock);
if (sem->permits > 0) {
sem->permits--;
- lock_internal_spin_unlock_with_notify(&sem->core, save);
+ spin_unlock(sem->core.spin_lock, save);
break;
}
lock_internal_spin_unlock_with_wait(&sem->core, save);
@@ -43,7 +43,7 @@
uint32_t save = spin_lock_blocking(sem->core.spin_lock);
if (sem->permits > 0) {
sem->permits--;
- lock_internal_spin_unlock_with_notify(&sem->core, save);
+ spin_unlock(sem->core.spin_lock, save);
return true;
}
if (lock_internal_spin_unlock_with_best_effort_wait_or_timeout(&sem->core, save, until)) {
@@ -52,6 +52,17 @@
} while (true);
}
+bool __time_critical_func(sem_try_acquire)(semaphore_t *sem) {
+ uint32_t save = spin_lock_blocking(sem->core.spin_lock);
+ if (sem->permits > 0) {
+ sem->permits--;
+ spin_unlock(sem->core.spin_lock, save);
+ return true;
+ }
+ spin_unlock(sem->core.spin_lock, save);
+ return false;
+}
+
// todo this should really have a blocking variant for when permits are maxed out
bool __time_critical_func(sem_release)(semaphore_t *sem) {
uint32_t save = spin_lock_blocking(sem->core.spin_lock);
diff --git a/src/common/pico_time/include/pico/time.h b/src/common/pico_time/include/pico/time.h
index c00b7a8..0fde00f 100644
--- a/src/common/pico_time/include/pico/time.h
+++ b/src/common/pico_time/include/pico/time.h
@@ -76,7 +76,7 @@
* \ingroup timestamp
* \brief Convert a timestamp into a number of milliseconds since boot.
* \param t an absolute_time_t value to convert
- * \return the number of microseconds since boot represented by t
+ * \return the number of milliseconds since boot represented by t
* \sa to_us_since_boot()
*/
static inline uint32_t to_ms_since_boot(absolute_time_t t) {
@@ -162,6 +162,16 @@
*/
extern const absolute_time_t at_the_end_of_time;
+/*! \brief Determine if the given timestamp is "at_the_end_of_time"
+ * \ingroup timestamp
+ * \param t the timestamp
+ * \return true if the timestamp is at_the_end_of_time
+ * \sa at_the_end_of_time
+ */
+static inline bool is_at_the_end_of_time(absolute_time_t t) {
+ return to_us_since_boot(t) == to_us_since_boot(at_the_end_of_time);
+}
+
/*! \brief The timestamp representing a null timestamp
* \ingroup timestamp
*/
diff --git a/src/common/pico_util/include/pico/util/pheap.h b/src/common/pico_util/include/pico/util/pheap.h
index 25351b4..5dc5133 100644
--- a/src/common/pico_util/include/pico/util/pheap.h
+++ b/src/common/pico_util/include/pico/util/pheap.h
@@ -24,13 +24,12 @@
* Pairing Heap Implementation
* \ingroup pico_util
*
- * pheap defines a simple pairing heap. the implementation simply tracks array indexes, it is up to
+ * pheap defines a simple pairing heap. The implementation simply tracks array indexes, it is up to
* the user to provide storage for heap entries and a comparison function.
*
- * NOTE: this class is not safe for concurrent usage. It should be externally protected. Furthermore
+ * NOTE: This class is not safe for concurrent usage. It should be externally protected. Furthermore
* if used concurrently, the caller needs to protect around their use of the returned id.
- * for example, ph_remove_and_free_head returns the id of an element that is no longer in the heap.
- *
+ * For example, ph_remove_and_free_head returns the id of an element that is no longer in the heap.
* The user can still use this to look at the data in their companion array, however obviously further operations
* on the heap may cause them to overwrite that data as the id may be reused on subsequent operations
*
diff --git a/src/common/pico_util/include/pico/util/queue.h b/src/common/pico_util/include/pico/util/queue.h
index 097578a..eb71e36 100644
--- a/src/common/pico_util/include/pico/util/queue.h
+++ b/src/common/pico_util/include/pico/util/queue.h
@@ -101,6 +101,7 @@
return level;
}
+#if PICO_QUEUE_MAX_LEVEL
/*! \brief Returns the highest level reached by the specified queue since it was created
* or since the max level was reset
* \ingroup queue
@@ -108,18 +109,17 @@
* \param q Pointer to a queue_t structure, used as a handle
* \return Maximum level of the queue
*/
-#if PICO_QUEUE_MAX_LEVEL
static inline uint queue_get_max_level(queue_t *q) {
return q->max_level;
}
#endif
+#if PICO_QUEUE_MAX_LEVEL
/*! \brief Reset the highest level reached of the specified queue.
* \ingroup queue
*
* \param q Pointer to a queue_t structure, used as a handle
*/
-#if PICO_QUEUE_MAX_LEVEL
static inline void queue_reset_max_level(queue_t *q) {
uint32_t save = spin_lock_blocking(q->core.spin_lock);
q->max_level = queue_get_level_unsafe(q);
diff --git a/src/host/hardware_sync/include/hardware/sync.h b/src/host/hardware_sync/include/hardware/sync.h
index a27ea01..58426f5 100644
--- a/src/host/hardware_sync/include/hardware/sync.h
+++ b/src/host/hardware_sync/include/hardware/sync.h
@@ -86,8 +86,6 @@
void spin_unlock(spin_lock_t *lock, uint32_t saved_irq);
-uint get_core_num();
-
spin_lock_t *spin_lock_init(uint lock_num);
void clear_spin_locks(void);
diff --git a/src/host/pico_platform/include/pico/platform.h b/src/host/pico_platform/include/pico/platform.h
index 27e5c08..b5e8137 100644
--- a/src/host/pico_platform/include/pico/platform.h
+++ b/src/host/pico_platform/include/pico/platform.h
@@ -22,7 +22,7 @@
#define __not_in_flash(group)
#define __not_in_flash_func(func) func
-#define __no_inline_not_in_flash_func(func)
+#define __no_inline_not_in_flash_func(func) func
#define __in_flash(group)
#define __scratch_x(group)
#define __scratch_y(group)
@@ -139,6 +139,9 @@
static inline void __compiler_memory_barrier(void) {
}
+
+uint get_core_num();
+
#ifdef __cplusplus
}
#endif
diff --git a/src/rp2040/hardware_regs/include/hardware/platform_defs.h b/src/rp2040/hardware_regs/include/hardware/platform_defs.h
index 08c7159..21f77ca 100644
--- a/src/rp2040/hardware_regs/include/hardware/platform_defs.h
+++ b/src/rp2040/hardware_regs/include/hardware/platform_defs.h
@@ -21,6 +21,7 @@
#define NUM_DMA_CHANNELS _u(12)
#define NUM_DMA_TIMERS _u(4)
#define NUM_IRQS _u(32)
+#define NUM_USER_IRQS _u(6)
#define NUM_PIOS _u(2)
#define NUM_PIO_STATE_MACHINES _u(4)
#define NUM_PWM_SLICES _u(8)
diff --git a/src/rp2040/hardware_regs/include/hardware/regs/dma.h b/src/rp2040/hardware_regs/include/hardware/regs/dma.h
index 042c3c1..1b69346 100644
--- a/src/rp2040/hardware_regs/include/hardware/regs/dma.h
+++ b/src/rp2040/hardware_regs/include/hardware/regs/dma.h
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
+ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -183,7 +183,6 @@
// Description : When this channel completes, it will trigger the channel
// indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this
// channel)_.
-// Reset value is equal to channel number (0).
#define DMA_CH0_CTRL_TRIG_CHAIN_TO_RESET _u(0x0)
#define DMA_CH0_CTRL_TRIG_CHAIN_TO_BITS _u(0x00007800)
#define DMA_CH0_CTRL_TRIG_CHAIN_TO_MSB _u(14)
@@ -457,7 +456,7 @@
// Description : DMA Channel 1 Control and Status
#define DMA_CH1_CTRL_TRIG_OFFSET _u(0x0000004c)
#define DMA_CH1_CTRL_TRIG_BITS _u(0xe1ffffff)
-#define DMA_CH1_CTRL_TRIG_RESET _u(0x00000800)
+#define DMA_CH1_CTRL_TRIG_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : DMA_CH1_CTRL_TRIG_AHB_ERROR
// Description : Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel
@@ -572,8 +571,7 @@
// Description : When this channel completes, it will trigger the channel
// indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this
// channel)_.
-// Reset value is equal to channel number (1).
-#define DMA_CH1_CTRL_TRIG_CHAIN_TO_RESET _u(0x1)
+#define DMA_CH1_CTRL_TRIG_CHAIN_TO_RESET _u(0x0)
#define DMA_CH1_CTRL_TRIG_CHAIN_TO_BITS _u(0x00007800)
#define DMA_CH1_CTRL_TRIG_CHAIN_TO_MSB _u(14)
#define DMA_CH1_CTRL_TRIG_CHAIN_TO_LSB _u(11)
@@ -846,7 +844,7 @@
// Description : DMA Channel 2 Control and Status
#define DMA_CH2_CTRL_TRIG_OFFSET _u(0x0000008c)
#define DMA_CH2_CTRL_TRIG_BITS _u(0xe1ffffff)
-#define DMA_CH2_CTRL_TRIG_RESET _u(0x00001000)
+#define DMA_CH2_CTRL_TRIG_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : DMA_CH2_CTRL_TRIG_AHB_ERROR
// Description : Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel
@@ -961,8 +959,7 @@
// Description : When this channel completes, it will trigger the channel
// indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this
// channel)_.
-// Reset value is equal to channel number (2).
-#define DMA_CH2_CTRL_TRIG_CHAIN_TO_RESET _u(0x2)
+#define DMA_CH2_CTRL_TRIG_CHAIN_TO_RESET _u(0x0)
#define DMA_CH2_CTRL_TRIG_CHAIN_TO_BITS _u(0x00007800)
#define DMA_CH2_CTRL_TRIG_CHAIN_TO_MSB _u(14)
#define DMA_CH2_CTRL_TRIG_CHAIN_TO_LSB _u(11)
@@ -1235,7 +1232,7 @@
// Description : DMA Channel 3 Control and Status
#define DMA_CH3_CTRL_TRIG_OFFSET _u(0x000000cc)
#define DMA_CH3_CTRL_TRIG_BITS _u(0xe1ffffff)
-#define DMA_CH3_CTRL_TRIG_RESET _u(0x00001800)
+#define DMA_CH3_CTRL_TRIG_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : DMA_CH3_CTRL_TRIG_AHB_ERROR
// Description : Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel
@@ -1350,8 +1347,7 @@
// Description : When this channel completes, it will trigger the channel
// indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this
// channel)_.
-// Reset value is equal to channel number (3).
-#define DMA_CH3_CTRL_TRIG_CHAIN_TO_RESET _u(0x3)
+#define DMA_CH3_CTRL_TRIG_CHAIN_TO_RESET _u(0x0)
#define DMA_CH3_CTRL_TRIG_CHAIN_TO_BITS _u(0x00007800)
#define DMA_CH3_CTRL_TRIG_CHAIN_TO_MSB _u(14)
#define DMA_CH3_CTRL_TRIG_CHAIN_TO_LSB _u(11)
@@ -1624,7 +1620,7 @@
// Description : DMA Channel 4 Control and Status
#define DMA_CH4_CTRL_TRIG_OFFSET _u(0x0000010c)
#define DMA_CH4_CTRL_TRIG_BITS _u(0xe1ffffff)
-#define DMA_CH4_CTRL_TRIG_RESET _u(0x00002000)
+#define DMA_CH4_CTRL_TRIG_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : DMA_CH4_CTRL_TRIG_AHB_ERROR
// Description : Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel
@@ -1739,8 +1735,7 @@
// Description : When this channel completes, it will trigger the channel
// indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this
// channel)_.
-// Reset value is equal to channel number (4).
-#define DMA_CH4_CTRL_TRIG_CHAIN_TO_RESET _u(0x4)
+#define DMA_CH4_CTRL_TRIG_CHAIN_TO_RESET _u(0x0)
#define DMA_CH4_CTRL_TRIG_CHAIN_TO_BITS _u(0x00007800)
#define DMA_CH4_CTRL_TRIG_CHAIN_TO_MSB _u(14)
#define DMA_CH4_CTRL_TRIG_CHAIN_TO_LSB _u(11)
@@ -2013,7 +2008,7 @@
// Description : DMA Channel 5 Control and Status
#define DMA_CH5_CTRL_TRIG_OFFSET _u(0x0000014c)
#define DMA_CH5_CTRL_TRIG_BITS _u(0xe1ffffff)
-#define DMA_CH5_CTRL_TRIG_RESET _u(0x00002800)
+#define DMA_CH5_CTRL_TRIG_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : DMA_CH5_CTRL_TRIG_AHB_ERROR
// Description : Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel
@@ -2128,8 +2123,7 @@
// Description : When this channel completes, it will trigger the channel
// indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this
// channel)_.
-// Reset value is equal to channel number (5).
-#define DMA_CH5_CTRL_TRIG_CHAIN_TO_RESET _u(0x5)
+#define DMA_CH5_CTRL_TRIG_CHAIN_TO_RESET _u(0x0)
#define DMA_CH5_CTRL_TRIG_CHAIN_TO_BITS _u(0x00007800)
#define DMA_CH5_CTRL_TRIG_CHAIN_TO_MSB _u(14)
#define DMA_CH5_CTRL_TRIG_CHAIN_TO_LSB _u(11)
@@ -2402,7 +2396,7 @@
// Description : DMA Channel 6 Control and Status
#define DMA_CH6_CTRL_TRIG_OFFSET _u(0x0000018c)
#define DMA_CH6_CTRL_TRIG_BITS _u(0xe1ffffff)
-#define DMA_CH6_CTRL_TRIG_RESET _u(0x00003000)
+#define DMA_CH6_CTRL_TRIG_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : DMA_CH6_CTRL_TRIG_AHB_ERROR
// Description : Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel
@@ -2517,8 +2511,7 @@
// Description : When this channel completes, it will trigger the channel
// indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this
// channel)_.
-// Reset value is equal to channel number (6).
-#define DMA_CH6_CTRL_TRIG_CHAIN_TO_RESET _u(0x6)
+#define DMA_CH6_CTRL_TRIG_CHAIN_TO_RESET _u(0x0)
#define DMA_CH6_CTRL_TRIG_CHAIN_TO_BITS _u(0x00007800)
#define DMA_CH6_CTRL_TRIG_CHAIN_TO_MSB _u(14)
#define DMA_CH6_CTRL_TRIG_CHAIN_TO_LSB _u(11)
@@ -2791,7 +2784,7 @@
// Description : DMA Channel 7 Control and Status
#define DMA_CH7_CTRL_TRIG_OFFSET _u(0x000001cc)
#define DMA_CH7_CTRL_TRIG_BITS _u(0xe1ffffff)
-#define DMA_CH7_CTRL_TRIG_RESET _u(0x00003800)
+#define DMA_CH7_CTRL_TRIG_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : DMA_CH7_CTRL_TRIG_AHB_ERROR
// Description : Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel
@@ -2906,8 +2899,7 @@
// Description : When this channel completes, it will trigger the channel
// indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this
// channel)_.
-// Reset value is equal to channel number (7).
-#define DMA_CH7_CTRL_TRIG_CHAIN_TO_RESET _u(0x7)
+#define DMA_CH7_CTRL_TRIG_CHAIN_TO_RESET _u(0x0)
#define DMA_CH7_CTRL_TRIG_CHAIN_TO_BITS _u(0x00007800)
#define DMA_CH7_CTRL_TRIG_CHAIN_TO_MSB _u(14)
#define DMA_CH7_CTRL_TRIG_CHAIN_TO_LSB _u(11)
@@ -3180,7 +3172,7 @@
// Description : DMA Channel 8 Control and Status
#define DMA_CH8_CTRL_TRIG_OFFSET _u(0x0000020c)
#define DMA_CH8_CTRL_TRIG_BITS _u(0xe1ffffff)
-#define DMA_CH8_CTRL_TRIG_RESET _u(0x00004000)
+#define DMA_CH8_CTRL_TRIG_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : DMA_CH8_CTRL_TRIG_AHB_ERROR
// Description : Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel
@@ -3295,8 +3287,7 @@
// Description : When this channel completes, it will trigger the channel
// indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this
// channel)_.
-// Reset value is equal to channel number (8).
-#define DMA_CH8_CTRL_TRIG_CHAIN_TO_RESET _u(0x8)
+#define DMA_CH8_CTRL_TRIG_CHAIN_TO_RESET _u(0x0)
#define DMA_CH8_CTRL_TRIG_CHAIN_TO_BITS _u(0x00007800)
#define DMA_CH8_CTRL_TRIG_CHAIN_TO_MSB _u(14)
#define DMA_CH8_CTRL_TRIG_CHAIN_TO_LSB _u(11)
@@ -3569,7 +3560,7 @@
// Description : DMA Channel 9 Control and Status
#define DMA_CH9_CTRL_TRIG_OFFSET _u(0x0000024c)
#define DMA_CH9_CTRL_TRIG_BITS _u(0xe1ffffff)
-#define DMA_CH9_CTRL_TRIG_RESET _u(0x00004800)
+#define DMA_CH9_CTRL_TRIG_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : DMA_CH9_CTRL_TRIG_AHB_ERROR
// Description : Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel
@@ -3684,8 +3675,7 @@
// Description : When this channel completes, it will trigger the channel
// indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this
// channel)_.
-// Reset value is equal to channel number (9).
-#define DMA_CH9_CTRL_TRIG_CHAIN_TO_RESET _u(0x9)
+#define DMA_CH9_CTRL_TRIG_CHAIN_TO_RESET _u(0x0)
#define DMA_CH9_CTRL_TRIG_CHAIN_TO_BITS _u(0x00007800)
#define DMA_CH9_CTRL_TRIG_CHAIN_TO_MSB _u(14)
#define DMA_CH9_CTRL_TRIG_CHAIN_TO_LSB _u(11)
@@ -3958,7 +3948,7 @@
// Description : DMA Channel 10 Control and Status
#define DMA_CH10_CTRL_TRIG_OFFSET _u(0x0000028c)
#define DMA_CH10_CTRL_TRIG_BITS _u(0xe1ffffff)
-#define DMA_CH10_CTRL_TRIG_RESET _u(0x00005000)
+#define DMA_CH10_CTRL_TRIG_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : DMA_CH10_CTRL_TRIG_AHB_ERROR
// Description : Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel
@@ -4073,8 +4063,7 @@
// Description : When this channel completes, it will trigger the channel
// indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this
// channel)_.
-// Reset value is equal to channel number (10).
-#define DMA_CH10_CTRL_TRIG_CHAIN_TO_RESET _u(0xa)
+#define DMA_CH10_CTRL_TRIG_CHAIN_TO_RESET _u(0x0)
#define DMA_CH10_CTRL_TRIG_CHAIN_TO_BITS _u(0x00007800)
#define DMA_CH10_CTRL_TRIG_CHAIN_TO_MSB _u(14)
#define DMA_CH10_CTRL_TRIG_CHAIN_TO_LSB _u(11)
@@ -4347,7 +4336,7 @@
// Description : DMA Channel 11 Control and Status
#define DMA_CH11_CTRL_TRIG_OFFSET _u(0x000002cc)
#define DMA_CH11_CTRL_TRIG_BITS _u(0xe1ffffff)
-#define DMA_CH11_CTRL_TRIG_RESET _u(0x00005800)
+#define DMA_CH11_CTRL_TRIG_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : DMA_CH11_CTRL_TRIG_AHB_ERROR
// Description : Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel
@@ -4462,8 +4451,7 @@
// Description : When this channel completes, it will trigger the channel
// indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this
// channel)_.
-// Reset value is equal to channel number (11).
-#define DMA_CH11_CTRL_TRIG_CHAIN_TO_RESET _u(0xb)
+#define DMA_CH11_CTRL_TRIG_CHAIN_TO_RESET _u(0x0)
#define DMA_CH11_CTRL_TRIG_CHAIN_TO_BITS _u(0x00007800)
#define DMA_CH11_CTRL_TRIG_CHAIN_TO_MSB _u(14)
#define DMA_CH11_CTRL_TRIG_CHAIN_TO_LSB _u(11)
diff --git a/src/rp2040/hardware_regs/include/hardware/regs/pll.h b/src/rp2040/hardware_regs/include/hardware/regs/pll.h
index a0f5ad0..9dba689 100644
--- a/src/rp2040/hardware_regs/include/hardware/regs/pll.h
+++ b/src/rp2040/hardware_regs/include/hardware/regs/pll.h
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
+ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -17,7 +17,7 @@
// GENERAL CONSTRAINTS:
// Reference clock frequency min=5MHz, max=800MHz
// Feedback divider min=16, max=320
-// VCO frequency min=400MHz, max=1600MHz
+// VCO frequency min=750MHz, max=1600MHz
#define PLL_CS_OFFSET _u(0x00000000)
#define PLL_CS_BITS _u(0x8000013f)
#define PLL_CS_RESET _u(0x00000001)
diff --git a/src/rp2040/hardware_regs/include/hardware/regs/sio.h b/src/rp2040/hardware_regs/include/hardware/regs/sio.h
index f641533..8d4a4ac 100644
--- a/src/rp2040/hardware_regs/include/hardware/regs/sio.h
+++ b/src/rp2040/hardware_regs/include/hardware/regs/sio.h
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
+ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -344,7 +344,7 @@
// q`.
// Any operand write starts a new calculation. The results appear
// in QUOTIENT, REMAINDER.
-// UDIVIDEND/SDIVIDEND are aliases of the same internal register.
+// UDIVISOR/SDIVISOR are aliases of the same internal register.
// The U alias starts an
// unsigned calculation, and the S alias starts a signed
// calculation.
diff --git a/src/rp2040/hardware_regs/rp2040.svd b/src/rp2040/hardware_regs/rp2040.svd
index 52da2c0..3849776 100644
--- a/src/rp2040/hardware_regs/rp2040.svd
+++ b/src/rp2040/hardware_regs/rp2040.svd
@@ -22367,7 +22367,7 @@
GENERAL CONSTRAINTS:\n
Reference clock frequency min=5MHz, max=800MHz\n
Feedback divider min=16, max=320\n
- VCO frequency min=400MHz, max=1600MHz</description>
+ VCO frequency min=750MHz, max=1600MHz</description>
<fields>
<field>
<access>read-only</access>
@@ -29754,8 +29754,7 @@
<field>
<access>read-write</access>
<bitRange>[14:11]</bitRange>
- <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.\n
- Reset value is equal to channel number (0).</description>
+ <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.</description>
<name>CHAIN_TO</name>
</field>
<field>
@@ -30039,8 +30038,7 @@
<field>
<access>read-write</access>
<bitRange>[14:11]</bitRange>
- <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.\n
- Reset value is equal to channel number (1).</description>
+ <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.</description>
<name>CHAIN_TO</name>
</field>
<field>
@@ -30113,7 +30111,7 @@
</field>
</fields>
<name>CH1_CTRL_TRIG</name>
- <resetValue>0x00000800</resetValue>
+ <resetValue>0x00000000</resetValue>
</register>
<register>
<access>read-write</access>
@@ -30324,8 +30322,7 @@
<field>
<access>read-write</access>
<bitRange>[14:11]</bitRange>
- <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.\n
- Reset value is equal to channel number (2).</description>
+ <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.</description>
<name>CHAIN_TO</name>
</field>
<field>
@@ -30398,7 +30395,7 @@
</field>
</fields>
<name>CH2_CTRL_TRIG</name>
- <resetValue>0x00001000</resetValue>
+ <resetValue>0x00000000</resetValue>
</register>
<register>
<access>read-write</access>
@@ -30609,8 +30606,7 @@
<field>
<access>read-write</access>
<bitRange>[14:11]</bitRange>
- <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.\n
- Reset value is equal to channel number (3).</description>
+ <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.</description>
<name>CHAIN_TO</name>
</field>
<field>
@@ -30683,7 +30679,7 @@
</field>
</fields>
<name>CH3_CTRL_TRIG</name>
- <resetValue>0x00001800</resetValue>
+ <resetValue>0x00000000</resetValue>
</register>
<register>
<access>read-write</access>
@@ -30894,8 +30890,7 @@
<field>
<access>read-write</access>
<bitRange>[14:11]</bitRange>
- <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.\n
- Reset value is equal to channel number (4).</description>
+ <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.</description>
<name>CHAIN_TO</name>
</field>
<field>
@@ -30968,7 +30963,7 @@
</field>
</fields>
<name>CH4_CTRL_TRIG</name>
- <resetValue>0x00002000</resetValue>
+ <resetValue>0x00000000</resetValue>
</register>
<register>
<access>read-write</access>
@@ -31179,8 +31174,7 @@
<field>
<access>read-write</access>
<bitRange>[14:11]</bitRange>
- <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.\n
- Reset value is equal to channel number (5).</description>
+ <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.</description>
<name>CHAIN_TO</name>
</field>
<field>
@@ -31253,7 +31247,7 @@
</field>
</fields>
<name>CH5_CTRL_TRIG</name>
- <resetValue>0x00002800</resetValue>
+ <resetValue>0x00000000</resetValue>
</register>
<register>
<access>read-write</access>
@@ -31464,8 +31458,7 @@
<field>
<access>read-write</access>
<bitRange>[14:11]</bitRange>
- <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.\n
- Reset value is equal to channel number (6).</description>
+ <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.</description>
<name>CHAIN_TO</name>
</field>
<field>
@@ -31538,7 +31531,7 @@
</field>
</fields>
<name>CH6_CTRL_TRIG</name>
- <resetValue>0x00003000</resetValue>
+ <resetValue>0x00000000</resetValue>
</register>
<register>
<access>read-write</access>
@@ -31749,8 +31742,7 @@
<field>
<access>read-write</access>
<bitRange>[14:11]</bitRange>
- <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.\n
- Reset value is equal to channel number (7).</description>
+ <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.</description>
<name>CHAIN_TO</name>
</field>
<field>
@@ -31823,7 +31815,7 @@
</field>
</fields>
<name>CH7_CTRL_TRIG</name>
- <resetValue>0x00003800</resetValue>
+ <resetValue>0x00000000</resetValue>
</register>
<register>
<access>read-write</access>
@@ -32034,8 +32026,7 @@
<field>
<access>read-write</access>
<bitRange>[14:11]</bitRange>
- <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.\n
- Reset value is equal to channel number (8).</description>
+ <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.</description>
<name>CHAIN_TO</name>
</field>
<field>
@@ -32108,7 +32099,7 @@
</field>
</fields>
<name>CH8_CTRL_TRIG</name>
- <resetValue>0x00004000</resetValue>
+ <resetValue>0x00000000</resetValue>
</register>
<register>
<access>read-write</access>
@@ -32319,8 +32310,7 @@
<field>
<access>read-write</access>
<bitRange>[14:11]</bitRange>
- <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.\n
- Reset value is equal to channel number (9).</description>
+ <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.</description>
<name>CHAIN_TO</name>
</field>
<field>
@@ -32393,7 +32383,7 @@
</field>
</fields>
<name>CH9_CTRL_TRIG</name>
- <resetValue>0x00004800</resetValue>
+ <resetValue>0x00000000</resetValue>
</register>
<register>
<access>read-write</access>
@@ -32604,8 +32594,7 @@
<field>
<access>read-write</access>
<bitRange>[14:11]</bitRange>
- <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.\n
- Reset value is equal to channel number (10).</description>
+ <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.</description>
<name>CHAIN_TO</name>
</field>
<field>
@@ -32678,7 +32667,7 @@
</field>
</fields>
<name>CH10_CTRL_TRIG</name>
- <resetValue>0x00005000</resetValue>
+ <resetValue>0x00000000</resetValue>
</register>
<register>
<access>read-write</access>
@@ -32889,8 +32878,7 @@
<field>
<access>read-write</access>
<bitRange>[14:11]</bitRange>
- <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.\n
- Reset value is equal to channel number (11).</description>
+ <description>When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_.</description>
<name>CHAIN_TO</name>
</field>
<field>
@@ -32963,7 +32951,7 @@
</field>
</fields>
<name>CH11_CTRL_TRIG</name>
- <resetValue>0x00005800</resetValue>
+ <resetValue>0x00000000</resetValue>
</register>
<register>
<access>read-write</access>
@@ -44521,7 +44509,7 @@
<description>Divider unsigned divisor\n
Write to the DIVISOR operand of the divider, i.e. the q in `p / q`.\n
Any operand write starts a new calculation. The results appear in QUOTIENT, REMAINDER.\n
- UDIVIDEND/SDIVIDEND are aliases of the same internal register. The U alias starts an\n
+ UDIVISOR/SDIVISOR are aliases of the same internal register. The U alias starts an\n
unsigned calculation, and the S alias starts a signed calculation.</description>
<name>DIV_UDIVISOR</name>
<resetValue>0x00000000</resetValue>
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/adc.h b/src/rp2040/hardware_structs/include/hardware/structs/adc.h
index c47e9d4..016137c 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/adc.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/adc.h
@@ -86,6 +86,6 @@
io_ro_32 ints;
} adc_hw_t;
-#define adc_hw ((adc_hw_t *const)ADC_BASE)
+#define adc_hw ((adc_hw_t *)ADC_BASE)
#endif
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/bus_ctrl.h b/src/rp2040/hardware_structs/include/hardware/structs/bus_ctrl.h
index 81118a8..d4e819e 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/bus_ctrl.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/bus_ctrl.h
@@ -72,6 +72,6 @@
bus_ctrl_perf_hw_t counter[4];
} bus_ctrl_hw_t;
-#define bus_ctrl_hw ((bus_ctrl_hw_t *const)BUSCTRL_BASE)
+#define bus_ctrl_hw ((bus_ctrl_hw_t *)BUSCTRL_BASE)
#endif
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/clocks.h b/src/rp2040/hardware_structs/include/hardware/structs/clocks.h
index a245dbd..0d27da5 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/clocks.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/clocks.h
@@ -319,7 +319,7 @@
io_ro_32 ints;
} clocks_hw_t;
-#define clocks_hw ((clocks_hw_t *const)CLOCKS_BASE)
+#define clocks_hw ((clocks_hw_t *)CLOCKS_BASE)
static_assert( CLK_COUNT == 10, "");
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/dma.h b/src/rp2040/hardware_structs/include/hardware/structs/dma.h
index 0d20641..4281ddf 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/dma.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/dma.h
@@ -194,8 +194,8 @@
} ch[NUM_DMA_CHANNELS];
} dma_debug_hw_t;
-#define dma_hw ((dma_hw_t *const)DMA_BASE)
-#define dma_debug_hw ((dma_debug_hw_t *const)(DMA_BASE + DMA_CH0_DBG_CTDREQ_OFFSET))
+#define dma_hw ((dma_hw_t *)DMA_BASE)
+#define dma_debug_hw ((dma_debug_hw_t *)(DMA_BASE + DMA_CH0_DBG_CTDREQ_OFFSET))
static_assert( NUM_DMA_TIMERS == 4, "");
static_assert( NUM_DMA_CHANNELS == 12, "");
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/i2c.h b/src/rp2040/hardware_structs/include/hardware/structs/i2c.h
index 43d6086..397ad9a 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/i2c.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/i2c.h
@@ -327,7 +327,7 @@
io_ro_32 comp_type;
} i2c_hw_t;
-#define i2c0_hw ((i2c_hw_t *const)I2C0_BASE)
-#define i2c1_hw ((i2c_hw_t *const)I2C1_BASE)
+#define i2c0_hw ((i2c_hw_t *)I2C0_BASE)
+#define i2c1_hw ((i2c_hw_t *)I2C1_BASE)
#endif
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/iobank0.h b/src/rp2040/hardware_structs/include/hardware/structs/iobank0.h
index aae74b2..04b3f4d 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/iobank0.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/iobank0.h
@@ -208,7 +208,7 @@
io_irq_ctrl_hw_t dormant_wake_irq_ctrl;
} iobank0_hw_t;
-#define iobank0_hw ((iobank0_hw_t *const)IO_BANK0_BASE)
+#define iobank0_hw ((iobank0_hw_t *)IO_BANK0_BASE)
/// \end::iobank0_hw[]
static_assert( NUM_BANK0_GPIOS == 30, "");
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/ioqspi.h b/src/rp2040/hardware_structs/include/hardware/structs/ioqspi.h
index 2992bfe..70ba09e 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/ioqspi.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/ioqspi.h
@@ -167,7 +167,7 @@
io_qspi_ctrl_hw_t dormant_wake_qspi_ctrl;
} ioqspi_hw_t;
-#define ioqspi_hw ((ioqspi_hw_t *const)IO_QSPI_BASE)
+#define ioqspi_hw ((ioqspi_hw_t *)IO_QSPI_BASE)
static_assert( NUM_QSPI_GPIOS == 6, "");
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/mpu.h b/src/rp2040/hardware_structs/include/hardware/structs/mpu.h
index e647220..09fb644 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/mpu.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/mpu.h
@@ -56,6 +56,6 @@
io_rw_32 rasr;
} mpu_hw_t;
-#define mpu_hw ((mpu_hw_t *const)(PPB_BASE + M0PLUS_MPU_TYPE_OFFSET))
+#define mpu_hw ((mpu_hw_t *)(PPB_BASE + M0PLUS_MPU_TYPE_OFFSET))
#endif
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/pads_qspi.h b/src/rp2040/hardware_structs/include/hardware/structs/pads_qspi.h
index 8036cd9..5c9d90f 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/pads_qspi.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/pads_qspi.h
@@ -40,7 +40,7 @@
io_rw_32 io[NUM_QSPI_GPIOS]; // 6
} pads_qspi_hw_t;
-#define pads_qspi_hw ((pads_qspi_hw_t *const)PADS_QSPI_BASE)
+#define pads_qspi_hw ((pads_qspi_hw_t *)PADS_QSPI_BASE)
static_assert( NUM_QSPI_GPIOS == 6, "");
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/padsbank0.h b/src/rp2040/hardware_structs/include/hardware/structs/padsbank0.h
index 2c067fa..fbb6052 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/padsbank0.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/padsbank0.h
@@ -40,7 +40,7 @@
io_rw_32 io[NUM_BANK0_GPIOS]; // 30
} padsbank0_hw_t;
-#define padsbank0_hw ((padsbank0_hw_t *const)PADS_BANK0_BASE)
+#define padsbank0_hw ((padsbank0_hw_t *)PADS_BANK0_BASE)
static_assert( NUM_BANK0_GPIOS == 30, "");
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/pio.h b/src/rp2040/hardware_structs/include/hardware/structs/pio.h
index 515e4d1..6a3126a 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/pio.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/pio.h
@@ -275,8 +275,8 @@
io_ro_32 ints1;
} pio_hw_t;
-#define pio0_hw ((pio_hw_t *const)PIO0_BASE)
-#define pio1_hw ((pio_hw_t *const)PIO1_BASE)
+#define pio0_hw ((pio_hw_t *)PIO0_BASE)
+#define pio1_hw ((pio_hw_t *)PIO1_BASE)
static_assert( NUM_PIO_STATE_MACHINES == 4, "");
static_assert( PIO_INSTRUCTION_COUNT == 32, "");
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/pll.h b/src/rp2040/hardware_structs/include/hardware/structs/pll.h
index 5a506e3..5633ad9 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/pll.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/pll.h
@@ -49,8 +49,8 @@
io_rw_32 prim;
} pll_hw_t;
-#define pll_sys_hw ((pll_hw_t *const)PLL_SYS_BASE)
-#define pll_usb_hw ((pll_hw_t *const)PLL_USB_BASE)
+#define pll_sys_hw ((pll_hw_t *)PLL_SYS_BASE)
+#define pll_usb_hw ((pll_hw_t *)PLL_USB_BASE)
/// \end::pll_hw[]
#endif
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/psm.h b/src/rp2040/hardware_structs/include/hardware/structs/psm.h
index cdfb2e3..3b9e65e 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/psm.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/psm.h
@@ -106,6 +106,6 @@
io_ro_32 done;
} psm_hw_t;
-#define psm_hw ((psm_hw_t *const)PSM_BASE)
+#define psm_hw ((psm_hw_t *)PSM_BASE)
#endif
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/pwm.h b/src/rp2040/hardware_structs/include/hardware/structs/pwm.h
index fd9a75c..f62c6d7 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/pwm.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/pwm.h
@@ -119,7 +119,7 @@
io_ro_32 ints;
} pwm_hw_t;
-#define pwm_hw ((pwm_hw_t *const)PWM_BASE)
+#define pwm_hw ((pwm_hw_t *)PWM_BASE)
static_assert( NUM_PWM_SLICES == 8, "");
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/resets.h b/src/rp2040/hardware_structs/include/hardware/structs/resets.h
index bc1c10c..c27337c 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/resets.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/resets.h
@@ -110,7 +110,7 @@
io_ro_32 reset_done;
} resets_hw_t;
-#define resets_hw ((resets_hw_t *const)RESETS_BASE)
+#define resets_hw ((resets_hw_t *)RESETS_BASE)
/// \end::resets_hw[]
#endif
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/rosc.h b/src/rp2040/hardware_structs/include/hardware/structs/rosc.h
index 114c602..86fa042 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/rosc.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/rosc.h
@@ -81,6 +81,6 @@
io_rw_32 count;
} rosc_hw_t;
-#define rosc_hw ((rosc_hw_t *const)ROSC_BASE)
+#define rosc_hw ((rosc_hw_t *)ROSC_BASE)
#endif
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/rtc.h b/src/rp2040/hardware_structs/include/hardware/structs/rtc.h
index 794a0e0..ccdb326 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/rtc.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/rtc.h
@@ -109,6 +109,6 @@
io_ro_32 ints;
} rtc_hw_t;
-#define rtc_hw ((rtc_hw_t *const)RTC_BASE)
+#define rtc_hw ((rtc_hw_t *)RTC_BASE)
#endif
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/scb.h b/src/rp2040/hardware_structs/include/hardware/structs/scb.h
index 42569c7..3214414 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/scb.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/scb.h
@@ -64,6 +64,6 @@
io_rw_32 scr;
} armv6m_scb_t;
-#define scb_hw ((armv6m_scb_t *const)(PPB_BASE + M0PLUS_CPUID_OFFSET))
+#define scb_hw ((armv6m_scb_t *)(PPB_BASE + M0PLUS_CPUID_OFFSET))
#endif
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/sio.h b/src/rp2040/hardware_structs/include/hardware/structs/sio.h
index 00b7e7e..251dd30 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/sio.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/sio.h
@@ -171,6 +171,6 @@
interp_hw_t interp[2];
} sio_hw_t;
-#define sio_hw ((sio_hw_t *const)SIO_BASE)
+#define sio_hw ((sio_hw_t *)SIO_BASE)
#endif
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/spi.h b/src/rp2040/hardware_structs/include/hardware/structs/spi.h
index f7fffb8..08243c0 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/spi.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/spi.h
@@ -94,7 +94,7 @@
io_rw_32 dmacr;
} spi_hw_t;
-#define spi0_hw ((spi_hw_t *const)SPI0_BASE)
-#define spi1_hw ((spi_hw_t *const)SPI1_BASE)
+#define spi0_hw ((spi_hw_t *)SPI0_BASE)
+#define spi1_hw ((spi_hw_t *)SPI1_BASE)
#endif
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/ssi.h b/src/rp2040/hardware_structs/include/hardware/structs/ssi.h
index 0ab18be..639bd64 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/ssi.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/ssi.h
@@ -205,6 +205,6 @@
io_rw_32 txd_drive_edge;
} ssi_hw_t;
-#define ssi_hw ((ssi_hw_t *const)XIP_SSI_BASE)
+#define ssi_hw ((ssi_hw_t *)XIP_SSI_BASE)
#endif
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/syscfg.h b/src/rp2040/hardware_structs/include/hardware/structs/syscfg.h
index 52218fb..e890521 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/syscfg.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/syscfg.h
@@ -72,6 +72,6 @@
io_rw_32 mempowerdown;
} syscfg_hw_t;
-#define syscfg_hw ((syscfg_hw_t *const)SYSCFG_BASE)
+#define syscfg_hw ((syscfg_hw_t *)SYSCFG_BASE)
#endif
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/systick.h b/src/rp2040/hardware_structs/include/hardware/structs/systick.h
index a859fea..b57a740 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/systick.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/systick.h
@@ -47,6 +47,6 @@
io_ro_32 calib;
} systick_hw_t;
-#define systick_hw ((systick_hw_t *const)(PPB_BASE + M0PLUS_SYST_CSR_OFFSET))
+#define systick_hw ((systick_hw_t *)(PPB_BASE + M0PLUS_SYST_CSR_OFFSET))
#endif
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/timer.h b/src/rp2040/hardware_structs/include/hardware/structs/timer.h
index c7c7066..7622f13 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/timer.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/timer.h
@@ -100,7 +100,7 @@
io_ro_32 ints;
} timer_hw_t;
-#define timer_hw ((timer_hw_t *const)TIMER_BASE)
+#define timer_hw ((timer_hw_t *)TIMER_BASE)
static_assert( NUM_TIMERS == 4, "");
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/uart.h b/src/rp2040/hardware_structs/include/hardware/structs/uart.h
index 09af33e..4912824 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/uart.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/uart.h
@@ -171,7 +171,7 @@
io_rw_32 dmacr;
} uart_hw_t;
-#define uart0_hw ((uart_hw_t *const)UART0_BASE)
-#define uart1_hw ((uart_hw_t *const)UART1_BASE)
+#define uart0_hw ((uart_hw_t *)UART0_BASE)
+#define uart1_hw ((uart_hw_t *)UART1_BASE)
#endif
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/usb.h b/src/rp2040/hardware_structs/include/hardware/structs/usb.h
index c9455d0..d5d74df 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/usb.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/usb.h
@@ -568,7 +568,7 @@
io_ro_32 ints;
} usb_hw_t;
-#define usb_hw ((usb_hw_t *const)USBCTRL_REGS_BASE)
+#define usb_hw ((usb_hw_t *)USBCTRL_REGS_BASE)
#define usb_dpram ((usb_device_dpram_t *)USBCTRL_DPRAM_BASE)
#define usbh_dpram ((usb_host_dpram_t *)USBCTRL_DPRAM_BASE)
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/vreg_and_chip_reset.h b/src/rp2040/hardware_structs/include/hardware/structs/vreg_and_chip_reset.h
index 554d9e4..edfc498 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/vreg_and_chip_reset.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/vreg_and_chip_reset.h
@@ -44,6 +44,6 @@
io_rw_32 chip_reset;
} vreg_and_chip_reset_hw_t;
-#define vreg_and_chip_reset_hw ((vreg_and_chip_reset_hw_t *const)VREG_AND_CHIP_RESET_BASE)
+#define vreg_and_chip_reset_hw ((vreg_and_chip_reset_hw_t *)VREG_AND_CHIP_RESET_BASE)
#endif
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/watchdog.h b/src/rp2040/hardware_structs/include/hardware/structs/watchdog.h
index 9579700..5071cf5 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/watchdog.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/watchdog.h
@@ -57,6 +57,6 @@
io_rw_32 tick;
} watchdog_hw_t;
-#define watchdog_hw ((watchdog_hw_t *const)WATCHDOG_BASE)
+#define watchdog_hw ((watchdog_hw_t *)WATCHDOG_BASE)
#endif
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/xip_ctrl.h b/src/rp2040/hardware_structs/include/hardware/structs/xip_ctrl.h
index 21885e8..84e92b4 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/xip_ctrl.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/xip_ctrl.h
@@ -63,7 +63,7 @@
io_ro_32 stream_fifo;
} xip_ctrl_hw_t;
-#define xip_ctrl_hw ((xip_ctrl_hw_t *const)XIP_CTRL_BASE)
+#define xip_ctrl_hw ((xip_ctrl_hw_t *)XIP_CTRL_BASE)
#define XIP_STAT_FIFO_FULL XIP_STAT_FIFO_FULL_BITS
#define XIP_STAT_FIFO_EMPTY XIP_STAT_FIFO_EMPTY_BITS
diff --git a/src/rp2040/hardware_structs/include/hardware/structs/xosc.h b/src/rp2040/hardware_structs/include/hardware/structs/xosc.h
index 0ff4db4..d327aa9 100644
--- a/src/rp2040/hardware_structs/include/hardware/structs/xosc.h
+++ b/src/rp2040/hardware_structs/include/hardware/structs/xosc.h
@@ -54,7 +54,7 @@
io_rw_32 count;
} xosc_hw_t;
-#define xosc_hw ((xosc_hw_t *const)XOSC_BASE)
+#define xosc_hw ((xosc_hw_t *)XOSC_BASE)
/// \end::xosc_hw[]
#endif
diff --git a/src/rp2_common/CMakeLists.txt b/src/rp2_common/CMakeLists.txt
index 4ca55be..0d0f9b9 100644
--- a/src/rp2_common/CMakeLists.txt
+++ b/src/rp2_common/CMakeLists.txt
@@ -58,6 +58,10 @@
pico_add_subdirectory(tinyusb)
pico_add_subdirectory(pico_stdio_usb)
+ pico_add_subdirectory(cyw43_driver)
+ pico_add_subdirectory(pico_lwip)
+ pico_add_subdirectory(pico_cyw43_arch)
+
pico_add_subdirectory(pico_stdlib)
pico_add_subdirectory(pico_cxx_options)
diff --git a/src/rp2_common/boot_stage2/pad_checksum b/src/rp2_common/boot_stage2/pad_checksum
index 356227d..d301756 100755
--- a/src/rp2_common/boot_stage2/pad_checksum
+++ b/src/rp2_common/boot_stage2/pad_checksum
@@ -31,7 +31,7 @@
except:
sys.exit("Could not open input file '{}'".format(args.ifile))
-if len(idata) >= args.pad - 4:
+if len(idata) > args.pad - 4:
sys.exit("Input file size ({} bytes) too large for final size ({} bytes)".format(len(idata), args.pad))
idata_padded = idata + bytes(args.pad - 4 - len(idata))
diff --git a/src/rp2_common/cyw43_driver/CMakeLists.txt b/src/rp2_common/cyw43_driver/CMakeLists.txt
new file mode 100644
index 0000000..8951df4
--- /dev/null
+++ b/src/rp2_common/cyw43_driver/CMakeLists.txt
@@ -0,0 +1,81 @@
+if (DEFINED ENV{PICO_CYW43_DRIVER_PATH} AND (NOT PICO_CYW43_DRIVER_PATH))
+ set(PICO_CYW43_DRIVER_PATH $ENV{PICO_CYW43_DRIVER_PATH})
+ message("Using PICO_CYW43_DRIVER_PATH from environment ('${PICO_CYW43_DRIVER_PATH}')")
+endif()
+
+set(CYW43_DRIVER_TEST_FILE "src/cyw43.h")
+
+if (NOT PICO_CYW43_DRIVER_PATH)
+ set(PICO_CYW43_DRIVER_PATH ${PICO_SDK_PATH}/lib/cyw43-driver)
+ if (PICO_CYW43_SUPPORTED AND NOT EXISTS ${PICO_CYW43_DRIVER_PATH}/${CYW43_DRIVER_TEST_FILE})
+ message(WARNING "cyw43-driver submodule has not been initialized; Pico W wireless support will be unavailable
+hint: try 'git submodule update --init' from your SDK directory (${PICO_SDK_PATH}).")
+ endif()
+elseif (NOT EXISTS ${PICO_CYW43_DRIVER_PATH}/${CYW43_DRIVER_TEST_FILE})
+ message(WARNING "PICO_CYW43_DRIVER_PATH specified but content not present.")
+endif()
+
+if (EXISTS ${PICO_CYW43_DRIVER_PATH}/${CYW43_DRIVER_TEST_FILE})
+ message("cyw43-driver available at ${PICO_CYW43_DRIVER_PATH}")
+
+ pico_register_common_scope_var(PICO_CYW43_DRIVER_PATH)
+
+ # base driver without our bus
+ add_library(cyw43_driver_base INTERFACE)
+ target_sources(cyw43_driver_base INTERFACE
+ ${PICO_CYW43_DRIVER_PATH}/src/cyw43_ll.c
+ ${PICO_CYW43_DRIVER_PATH}/src/cyw43_stats.c
+ ${PICO_CYW43_DRIVER_PATH}/src/cyw43_lwip.c
+ ${PICO_CYW43_DRIVER_PATH}/src/cyw43_ctrl.c
+ )
+ target_include_directories(cyw43_driver_base INTERFACE
+ ${PICO_CYW43_DRIVER_PATH}/src
+ ${PICO_CYW43_DRIVER_PATH}/firmware
+ )
+
+ # Build the driver for cyw43 for pico w
+
+ # Firmware stuff
+ set(CYW43_FIRMWARE_BIN 43439A0-7.95.49.00.combined)
+ string(REGEX REPLACE [\\\.\-] _ CYW43_FIRMWARE_BIN_ ${CYW43_FIRMWARE_BIN})
+ string(REGEX MATCH [^_]+_?[^_]*_?[^_]*_?[^_]*_?[^_]* CYW43_FIRMWARE_PRETTY ${CYW43_FIRMWARE_BIN_})
+ set(CYW43_FIRMWARE_PRETTY fw_${CYW43_FIRMWARE_PRETTY})
+ set(RESOURCE_SECNAME .big_const)
+ set(RESOURCE_SECFLAGS contents,alloc,load,readonly,data)
+ set(CYW43_FIRMWARE_OBJ ${CMAKE_CURRENT_BINARY_DIR}/cyw43_resource.o)
+
+ add_custom_target(cyw43_firmware_package DEPENDS ${CYW43_FIRMWARE_OBJ})
+
+ # cyw43_resource.o contains the WiFi and BT firmware as a binary blob
+ add_custom_command(
+ OUTPUT ${CYW43_FIRMWARE_OBJ}
+ DEPENDS ${PICO_CYW43_DRIVER_PATH}/firmware/${CYW43_FIRMWARE_BIN}
+ WORKING_DIRECTORY ${PICO_CYW43_DRIVER_PATH}/firmware
+ COMMAND ${CMAKE_OBJCOPY} -I binary -O elf32-littlearm -B arm
+ --readonly-text
+ --rename-section .data=${RESOURCE_SECNAME},${RESOURCE_SECFLAGS}
+ --redefine-sym _binary_${CYW43_FIRMWARE_BIN_}_start=${CYW43_FIRMWARE_PRETTY}_start
+ --redefine-sym _binary_${CYW43_FIRMWARE_BIN_}_end=${CYW43_FIRMWARE_PRETTY}_end
+ --redefine-sym _binary_${CYW43_FIRMWARE_BIN_}_size=${CYW43_FIRMWARE_PRETTY}_size
+ ${CYW43_FIRMWARE_BIN} ${CYW43_FIRMWARE_OBJ}
+ )
+
+ add_library(cyw43_driver_picow INTERFACE)
+ target_sources(cyw43_driver_picow INTERFACE
+ ${CMAKE_CURRENT_LIST_DIR}/cyw43_bus_pio_spi.c
+ )
+ pico_generate_pio_header(cyw43_driver_picow ${CMAKE_CURRENT_LIST_DIR}/cyw43_bus_pio_spi.pio)
+ add_dependencies(cyw43_driver_picow INTERFACE cyw43_firmware_package)
+ target_link_libraries(cyw43_driver_picow INTERFACE
+ ${CYW43_FIRMWARE_OBJ}
+ )
+ target_link_libraries(cyw43_driver_picow INTERFACE
+ cyw43_driver_base
+ pico_stdlib
+ hardware_pio
+ hardware_dma
+ hardware_exception
+ )
+
+ pico_promote_common_scope_vars()
+endif()
diff --git a/src/rp2_common/cyw43_driver/cyw43_bus_pio_spi.c b/src/rp2_common/cyw43_driver/cyw43_bus_pio_spi.c
new file mode 100644
index 0000000..0fd17f4
--- /dev/null
+++ b/src/rp2_common/cyw43_driver/cyw43_bus_pio_spi.c
@@ -0,0 +1,545 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "pico/stdlib.h"
+#include "hardware/gpio.h"
+#include "hardware/pio.h"
+#include "hardware/clocks.h"
+#include "hardware/structs/iobank0.h"
+#include "hardware/sync.h"
+#include "hardware/dma.h"
+#include "cyw43_bus_pio_spi.pio.h"
+#include "cyw43.h"
+#include "cyw43_internal.h"
+#include "cyw43_spi.h"
+#include "cyw43_debug_pins.h"
+
+#if CYW43_SPI_PIO
+#define WL_REG_ON 23
+#define DATA_OUT_PIN 24u
+#define DATA_IN_PIN 24u
+#define IRQ_PIN 24u
+// #define MONITOR_PIN 3u
+#define CLOCK_PIN 29u
+#define CS_PIN 25u
+#define IRQ_SAMPLE_DELAY_NS 100
+
+#define SPI_PROGRAM_NAME spi_gap01_sample0
+#define SPI_PROGRAM_FUNC __CONCAT(SPI_PROGRAM_NAME, _program)
+#define SPI_PROGRAM_GET_DEFAULT_CONFIG_FUNC __CONCAT(SPI_PROGRAM_NAME, _program_get_default_config)
+#define SPI_OFFSET_END __CONCAT(SPI_PROGRAM_NAME, _offset_end)
+#define SPI_OFFSET_LP1_END __CONCAT(SPI_PROGRAM_NAME, _offset_lp1_end)
+
+#define CLOCK_DIV 2
+#define CLOCK_DIV_MINOR 0
+#define PADS_DRIVE_STRENGTH PADS_BANK0_GPIO0_DRIVE_VALUE_12MA
+
+#if !CYW43_USE_SPI
+#error CYW43_USE_SPI should be true
+#endif
+
+#ifndef NDEBUG
+//#define ENABLE_SPI_DUMPING 1
+#endif
+
+// Set to 1 to enable
+#if ENABLE_SPI_DUMPING //NDEBUG
+#if 0
+#define DUMP_SPI_TRANSACTIONS(A) A
+#else
+static bool enable_spi_packet_dumping; // set to true to dump
+#define DUMP_SPI_TRANSACTIONS(A) if (enable_spi_packet_dumping) {A}
+#endif
+
+static uint32_t counter = 0;
+#else
+#define DUMP_SPI_TRANSACTIONS(A)
+#endif
+
+//#define SWAP32(A) ((((A) & 0xff000000U) >> 8) | (((A) & 0xff0000U) << 8) | (((A) & 0xff00U) >> 8) | (((A) & 0xffU) << 8))
+__force_inline static uint32_t __swap16x2(uint32_t a) {
+ __asm ("rev16 %0, %0" : "+l" (a) : : );
+ return a;
+}
+#define SWAP32(a) __swap16x2(a)
+
+#ifndef CYW43_SPI_PIO_PREFERRED_PIO
+#define CYW43_SPI_PIO_PREFERRED_PIO 1
+#endif
+static_assert(CYW43_SPI_PIO_PREFERRED_PIO >=0 && CYW43_SPI_PIO_PREFERRED_PIO < NUM_PIOS, "");
+
+typedef struct {
+ pio_hw_t *pio;
+ uint8_t pio_func_sel;
+ int8_t pio_offset;
+ int8_t pio_sm;
+ int8_t dma_out;
+ int8_t dma_in;
+} bus_data_t;
+
+static bus_data_t bus_data_instance;
+
+int cyw43_spi_init(cyw43_int_t *self) {
+ // Only does something if CYW43_LOGIC_DEBUG=1
+ logic_debug_init();
+
+ static_assert(NUM_PIOS == 2, "");
+
+ pio_hw_t *pios[2] = {pio0, pio1};
+ uint pio_index = CYW43_SPI_PIO_PREFERRED_PIO;
+ // Check we can add the program
+ if (!pio_can_add_program(pios[pio_index], &SPI_PROGRAM_FUNC)) {
+ pio_index ^= 1;
+ if (!pio_can_add_program(pios[pio_index], &SPI_PROGRAM_FUNC)) {
+ return CYW43_FAIL_FAST_CHECK(-CYW43_EIO);
+ }
+ }
+ assert(!self->bus_data);
+ self->bus_data = &bus_data_instance;
+ bus_data_t *bus_data = (bus_data_t *)self->bus_data;
+ bus_data->pio = pios[pio_index];
+ bus_data->dma_in = -1;
+ bus_data->dma_out = -1;
+
+ static_assert(GPIO_FUNC_PIO1 == GPIO_FUNC_PIO0 + 1, "");
+ bus_data->pio_func_sel = GPIO_FUNC_PIO0 + pio_index;
+ bus_data->pio_sm = (int8_t)pio_claim_unused_sm(bus_data->pio, false);
+ if (bus_data->pio_sm < 0) {
+ cyw43_spi_deinit(self);
+ return CYW43_FAIL_FAST_CHECK(-CYW43_EIO);
+ }
+
+ bus_data->pio_offset = pio_add_program(bus_data->pio, &SPI_PROGRAM_FUNC);
+ pio_sm_config config = SPI_PROGRAM_GET_DEFAULT_CONFIG_FUNC(bus_data->pio_offset);
+
+ sm_config_set_clkdiv_int_frac(&config, CLOCK_DIV, CLOCK_DIV_MINOR);
+ hw_write_masked(&padsbank0_hw->io[CLOCK_PIN],
+ (uint)PADS_DRIVE_STRENGTH << PADS_BANK0_GPIO0_DRIVE_LSB,
+ PADS_BANK0_GPIO0_DRIVE_BITS
+ );
+ hw_write_masked(&padsbank0_hw->io[CLOCK_PIN],
+ (uint)1 << PADS_BANK0_GPIO0_SLEWFAST_LSB,
+ PADS_BANK0_GPIO0_SLEWFAST_BITS
+ );
+
+ sm_config_set_out_pins(&config, DATA_OUT_PIN, 1);
+ sm_config_set_in_pins(&config, DATA_IN_PIN);
+ sm_config_set_set_pins(&config, DATA_OUT_PIN, 1);
+ sm_config_set_sideset(&config, 1, false, false);
+ sm_config_set_sideset_pins(&config, CLOCK_PIN);
+ sm_config_set_in_shift(&config, false, true, 32);
+ sm_config_set_out_shift(&config, false, true, 32);
+ hw_set_bits(&bus_data->pio->input_sync_bypass, 1u << DATA_IN_PIN);
+ pio_sm_set_config(bus_data->pio, bus_data->pio_sm, &config);
+ pio_sm_set_consecutive_pindirs(bus_data->pio, bus_data->pio_sm, CLOCK_PIN, 1, true);
+ gpio_set_function(DATA_OUT_PIN, bus_data->pio_func_sel);
+ gpio_set_function(CLOCK_PIN, bus_data->pio_func_sel);
+
+ // Set data pin to pull down and schmitt
+ gpio_set_pulls(DATA_IN_PIN, false, true);
+ gpio_set_input_hysteresis_enabled(DATA_IN_PIN, true);
+
+ pio_sm_exec(bus_data->pio, bus_data->pio_sm, pio_encode_set(pio_pins, 1));
+
+ bus_data->dma_out = (int8_t) dma_claim_unused_channel(false);
+ bus_data->dma_in = (int8_t) dma_claim_unused_channel(false);
+ if (bus_data->dma_out < 0 || bus_data->dma_in < 0) {
+ cyw43_spi_deinit(self);
+ return CYW43_FAIL_FAST_CHECK(-CYW43_EIO);
+ }
+ return 0;
+}
+
+void cyw43_spi_deinit(cyw43_int_t *self) {
+ if (self->bus_data) {
+ bus_data_t *bus_data = (bus_data_t *)self->bus_data;
+ if (bus_data->pio_sm >= 0) {
+ if (bus_data->pio_offset != -1)
+ pio_remove_program(bus_data->pio, &SPI_PROGRAM_FUNC, bus_data->pio_offset);
+ pio_sm_unclaim(bus_data->pio, bus_data->pio_sm);
+ }
+ if (bus_data->dma_out >= 0) {
+ dma_channel_unclaim(bus_data->dma_out);
+ bus_data->dma_out = -1;
+ }
+ if (bus_data->dma_in >= 0) {
+ dma_channel_unclaim(bus_data->dma_in);
+ bus_data->dma_in = -1;
+ }
+ self->bus_data = NULL;
+ }
+}
+
+static void cs_set(bool value) {
+ gpio_put(CS_PIN, value);
+}
+
+static __noinline void ns_delay(uint32_t ns) {
+ // cycles = ns * clk_sys_hz / 1,000,000,000
+ uint32_t cycles = ns * (clock_get_hz(clk_sys) >> 16u) / (1000000000u >> 16u);
+ busy_wait_at_least_cycles(cycles);
+}
+
+static void start_spi_comms(cyw43_int_t *self) {
+ bus_data_t *bus_data = (bus_data_t *)self->bus_data;
+ // Pull CS low
+ cs_set(false);
+ gpio_set_function(DATA_OUT_PIN, bus_data->pio_func_sel);
+}
+
+// we need to atomically de-assert CS and enable IRQ
+static void stop_spi_comms(void) {
+ // from this point a positive edge will cause an IRQ to be pending
+ cs_set(true);
+
+ // we need to wait a bit in case the irq line is incorrectly high
+ ns_delay(IRQ_SAMPLE_DELAY_NS);
+}
+
+#if ENABLE_SPI_DUMPING
+static void dump_bytes(const uint8_t *bptr, uint32_t len) {
+ unsigned int i = 0;
+
+ for (i = 0; i < len;) {
+ if ((i & 0x0f) == 0) {
+ printf("\n");
+ } else if ((i & 0x07) == 0) {
+ printf(" ");
+ }
+ printf("%02x ", bptr[i++]);
+ }
+ printf("\n");
+}
+#endif
+
+int cyw43_spi_transfer(cyw43_int_t *self, const uint8_t *tx, size_t tx_length, uint8_t *rx,
+ size_t rx_length) {
+
+ if ((tx == NULL) && (rx == NULL)) {
+ return CYW43_FAIL_FAST_CHECK(-CYW43_EINVAL);
+ }
+
+ bus_data_t *bus_data = (bus_data_t *)self->bus_data;
+ start_spi_comms(self);
+ if (rx != NULL) {
+ if (tx == NULL) {
+ tx = rx;
+ assert(tx_length && tx_length < rx_length);
+ }
+ DUMP_SPI_TRANSACTIONS(
+ printf("[%lu] bus TX/RX %u bytes rx %u:", counter++, tx_length, rx_length);
+ dump_bytes(tx, tx_length);
+ )
+ assert(!(tx_length & 3));
+ assert(!(((uintptr_t)tx) & 3));
+ assert(!(((uintptr_t)rx) & 3));
+ assert(!(rx_length & 3));
+
+ pio_sm_set_enabled(bus_data->pio, bus_data->pio_sm, false);
+ pio_sm_set_wrap(bus_data->pio, bus_data->pio_sm, bus_data->pio_offset, bus_data->pio_offset + SPI_OFFSET_END - 1);
+ pio_sm_clear_fifos(bus_data->pio, bus_data->pio_sm);
+ pio_sm_set_pindirs_with_mask(bus_data->pio, bus_data->pio_sm, 1u << DATA_OUT_PIN, 1u << DATA_OUT_PIN);
+ pio_sm_restart(bus_data->pio, bus_data->pio_sm);
+ pio_sm_clkdiv_restart(bus_data->pio, bus_data->pio_sm);
+ pio_sm_put(bus_data->pio, bus_data->pio_sm, tx_length * 8 - 1);
+ pio_sm_exec(bus_data->pio, bus_data->pio_sm, pio_encode_out(pio_x, 32));
+ pio_sm_put(bus_data->pio, bus_data->pio_sm, (rx_length - tx_length) * 8 - 1);
+ pio_sm_exec(bus_data->pio, bus_data->pio_sm, pio_encode_out(pio_y, 32));
+ pio_sm_exec(bus_data->pio, bus_data->pio_sm, pio_encode_jmp(bus_data->pio_offset));
+ dma_channel_abort(bus_data->dma_out);
+ dma_channel_abort(bus_data->dma_in);
+
+ dma_channel_config out_config = dma_channel_get_default_config(bus_data->dma_out);
+ channel_config_set_bswap(&out_config, true);
+ channel_config_set_dreq(&out_config, pio_get_dreq(bus_data->pio, 0, true));
+
+ dma_channel_configure(bus_data->dma_out, &out_config, &bus_data->pio->txf[0], tx, tx_length / 4, true);
+
+ dma_channel_config in_config = dma_channel_get_default_config(bus_data->dma_in);
+ channel_config_set_bswap(&in_config, true);
+ channel_config_set_dreq(&in_config, pio_get_dreq(bus_data->pio, 0, false));
+ channel_config_set_write_increment(&in_config, true);
+ channel_config_set_read_increment(&in_config, false);
+ dma_channel_configure(bus_data->dma_in, &in_config, rx + tx_length, &bus_data->pio->rxf[0], rx_length / 4 - tx_length / 4, true);
+
+ pio_sm_set_enabled(bus_data->pio, bus_data->pio_sm, true);
+ __compiler_memory_barrier();
+
+ dma_channel_wait_for_finish_blocking(bus_data->dma_out);
+ dma_channel_wait_for_finish_blocking(bus_data->dma_in);
+
+ __compiler_memory_barrier();
+ memset(rx, 0, tx_length); // make sure we don't have garbage in what would have been returned data if using real SPI
+ } else if (tx != NULL) {
+ DUMP_SPI_TRANSACTIONS(
+ printf("[%lu] bus TX only %u bytes:", counter++, tx_length);
+ dump_bytes(tx, tx_length);
+ )
+ assert(!(((uintptr_t)tx) & 3));
+ assert(!(tx_length & 3));
+ pio_sm_set_enabled(bus_data->pio, bus_data->pio_sm, false);
+ pio_sm_set_wrap(bus_data->pio, bus_data->pio_sm, bus_data->pio_offset, bus_data->pio_offset + SPI_OFFSET_LP1_END - 1);
+ pio_sm_clear_fifos(bus_data->pio, bus_data->pio_sm);
+ pio_sm_set_pindirs_with_mask(bus_data->pio, bus_data->pio_sm, 1u << DATA_OUT_PIN, 1u << DATA_OUT_PIN);
+ pio_sm_restart(bus_data->pio, bus_data->pio_sm);
+ pio_sm_clkdiv_restart(bus_data->pio, bus_data->pio_sm);
+ pio_sm_put(bus_data->pio, bus_data->pio_sm, tx_length * 8 - 1);
+ pio_sm_exec(bus_data->pio, bus_data->pio_sm, pio_encode_out(pio_x, 32));
+ pio_sm_put(bus_data->pio, bus_data->pio_sm, 0);
+ pio_sm_exec(bus_data->pio, bus_data->pio_sm, pio_encode_out(pio_y, 32));
+ pio_sm_exec(bus_data->pio, bus_data->pio_sm, pio_encode_jmp(bus_data->pio_offset));
+ dma_channel_abort(bus_data->dma_out);
+
+ dma_channel_config out_config = dma_channel_get_default_config(bus_data->dma_out);
+ channel_config_set_bswap(&out_config, true);
+ channel_config_set_dreq(&out_config, pio_get_dreq(bus_data->pio, 0, true));
+
+ dma_channel_configure(bus_data->dma_out, &out_config, &bus_data->pio->txf[0], tx, tx_length / 4, true);
+
+ bus_data->pio->fdebug = 1u << PIO_FDEBUG_TXSTALL_LSB;
+ pio_sm_set_enabled(bus_data->pio, 0, true);
+ while (!(bus_data->pio->fdebug & (1u << PIO_FDEBUG_TXSTALL_LSB))) {
+ tight_loop_contents(); // todo timeout
+ }
+ __compiler_memory_barrier();
+ pio_sm_set_enabled(bus_data->pio, bus_data->pio_sm, false);
+ pio_sm_set_consecutive_pindirs(bus_data->pio, bus_data->pio_sm, DATA_IN_PIN, 1, false);
+ } else if (rx != NULL) { /* currently do one at a time */
+ DUMP_SPI_TRANSACTIONS(
+ printf("[%lu] bus TX %u bytes:", counter++, rx_length);
+ dump_bytes(rx, rx_length);
+ )
+ panic_unsupported();
+ }
+ pio_sm_exec(bus_data->pio, bus_data->pio_sm, pio_encode_mov(pio_pins, pio_null)); // for next time we turn output on
+
+ stop_spi_comms();
+ DUMP_SPI_TRANSACTIONS(
+ printf("RXed:");
+ dump_bytes(rx, rx_length);
+ printf("\n");
+ )
+
+ return 0;
+}
+
+// Initialise our gpios
+void cyw43_spi_gpio_setup(void) {
+ // Setup WL_REG_ON (23)
+ gpio_init(WL_REG_ON);
+ gpio_set_dir(WL_REG_ON, GPIO_OUT);
+ gpio_pull_up(WL_REG_ON);
+
+ // Setup DO, DI and IRQ (24)
+ gpio_init(DATA_OUT_PIN);
+ gpio_set_dir(DATA_OUT_PIN, GPIO_OUT);
+ gpio_put(DATA_OUT_PIN, false);
+
+ // Setup CS (25)
+ gpio_init(CS_PIN);
+ gpio_set_dir(CS_PIN, GPIO_OUT);
+ gpio_put(CS_PIN, true);
+}
+
+// Reset wifi chip
+void cyw43_spi_reset(void) {
+ gpio_put(WL_REG_ON, false); // off
+ sleep_ms(20);
+ gpio_put(WL_REG_ON, true); // on
+ sleep_ms(250);
+
+ // Setup IRQ (24) - also used for DO, DI
+ gpio_init(IRQ_PIN);
+ gpio_set_dir(IRQ_PIN, GPIO_IN);
+}
+
+static inline uint32_t make_cmd(bool write, bool inc, uint32_t fn, uint32_t addr, uint32_t sz) {
+ return write << 31 | inc << 30 | fn << 28 | (addr & 0x1ffff) << 11 | sz;
+}
+
+#if CYW43_VERBOSE_DEBUG
+static const char *func_name(int fn) {
+ switch (fn)
+ {
+ case BUS_FUNCTION:
+ return "BUS_FUNCTION";
+ case BACKPLANE_FUNCTION:
+ return "BACKPLANE_FUNCTION";
+ case WLAN_FUNCTION:
+ return "WLAN_FUNCTION";
+ default:
+ return "UNKNOWN";
+ }
+}
+#endif
+
+uint32_t read_reg_u32_swap(cyw43_int_t *self, uint32_t fn, uint32_t reg) {
+ uint32_t buf[2] = {0};
+ assert(fn != BACKPLANE_FUNCTION);
+ buf[0] = SWAP32(make_cmd(false, true, fn, reg, 4));
+ int ret = cyw43_spi_transfer(self, NULL, 4, (uint8_t *)buf, 8);
+ if (ret != 0) {
+ return ret;
+ }
+ return SWAP32(buf[1]);
+}
+
+static inline uint32_t _cyw43_read_reg(cyw43_int_t *self, uint32_t fn, uint32_t reg, uint size) {
+ // Padding plus max read size of 32 bits + another 4?
+ static_assert(WHD_BUS_SPI_BACKPLANE_READ_PADD_SIZE % 4 == 0, "");
+ uint32_t buf32[WHD_BUS_SPI_BACKPLANE_READ_PADD_SIZE/4 + 1 + 1];
+ uint8_t *buf = (uint8_t *)buf32;
+ const uint32_t padding = (fn == BACKPLANE_FUNCTION) ? WHD_BUS_SPI_BACKPLANE_READ_PADD_SIZE : 0; // Add response delay
+ buf32[0] = make_cmd(false, true, fn, reg, size + padding);
+
+ if (fn == BACKPLANE_FUNCTION) {
+ logic_debug_set(pin_BACKPLANE_READ, 1);
+ }
+ int ret = cyw43_spi_transfer(self, NULL, 4, buf, 8 + padding);
+ if (fn == BACKPLANE_FUNCTION) {
+ logic_debug_set(pin_BACKPLANE_READ, 0);
+ }
+
+ if (ret != 0) {
+ return ret;
+ }
+ uint32_t result = buf32[padding > 0 ? 2 : 1];
+ CYW43_VDEBUG("cyw43_read_reg_u%d %s 0x%lx=0x%lx\n", size * 8, func_name(fn), reg, result);
+ return result;
+}
+
+uint32_t cyw43_read_reg_u32(cyw43_int_t *self, uint32_t fn, uint32_t reg) {
+ return _cyw43_read_reg(self, fn, reg, 4);
+}
+
+int cyw43_read_reg_u16(cyw43_int_t *self, uint32_t fn, uint32_t reg) {
+ return _cyw43_read_reg(self, fn, reg, 2);
+}
+
+int cyw43_read_reg_u8(cyw43_int_t *self, uint32_t fn, uint32_t reg) {
+ return _cyw43_read_reg(self, fn, reg, 1);
+}
+
+// This is only used to switch the word order on boot
+int write_reg_u32_swap(cyw43_int_t *self, uint32_t fn, uint32_t reg, uint32_t val) {
+ uint32_t buf[2];
+ // Boots up in little endian so command needs swapping too
+ buf[0] = SWAP32(make_cmd(true, true, fn, reg, 4));
+ buf[1] = SWAP32(val);
+ int ret = cyw43_spi_transfer(self, (uint8_t *)buf, 8, NULL, 0);
+ CYW43_VDEBUG("write_reg_u32_swap %s 0x%lx=0x%lx\n", func_name(fn), reg, val);
+ return ret;
+}
+
+static inline int _cyw43_write_reg(cyw43_int_t *self, uint32_t fn, uint32_t reg, uint32_t val, uint size) {
+ uint32_t buf[2];
+ buf[0] = make_cmd(true, true, fn, reg, size);
+ buf[1] = val;
+ if (fn == BACKPLANE_FUNCTION) {
+ // In case of f1 overflow
+ self->last_size = 8;
+ self->last_header[0] = buf[0];
+ self->last_header[1] = buf[1];
+ self->last_backplane_window = self->cur_backplane_window;
+ }
+
+ if (fn == BACKPLANE_FUNCTION) {
+ logic_debug_set(pin_BACKPLANE_WRITE, 1);
+ }
+
+ int ret = cyw43_spi_transfer(self, (uint8_t *)buf, 8, NULL, 0);
+
+ if (fn == BACKPLANE_FUNCTION) {
+ logic_debug_set(pin_BACKPLANE_WRITE, 0);
+ }
+
+ CYW43_VDEBUG("cyw43_write_reg_u%d %s 0x%lx=0x%lx\n", size * 8, func_name(fn), reg, val);
+ return ret;
+}
+
+int cyw43_write_reg_u32(cyw43_int_t *self, uint32_t fn, uint32_t reg, uint32_t val) {
+ return _cyw43_write_reg(self, fn, reg, val, 4);
+}
+
+int cyw43_write_reg_u16(cyw43_int_t *self, uint32_t fn, uint32_t reg, uint16_t val) {
+ return _cyw43_write_reg(self, fn, reg, val, 2);
+}
+
+int cyw43_write_reg_u8(cyw43_int_t *self, uint32_t fn, uint32_t reg, uint32_t val) {
+ return _cyw43_write_reg(self, fn, reg, val, 1);
+}
+
+#if MAX_BLOCK_SIZE > 0x7f8
+#error Block size is wrong for SPI
+#endif
+
+// Assumes we're reading into spid_buf
+int cyw43_read_bytes(cyw43_int_t *self, uint32_t fn, uint32_t addr, size_t len, uint8_t *buf) {
+ assert(fn != BACKPLANE_FUNCTION || (len <= 64 && (addr + len) <= 0x8000));
+ const uint32_t padding = (fn == BACKPLANE_FUNCTION) ? 4 : 0; // Add response delay
+ size_t aligned_len = (len + 3) & ~3;
+ assert(aligned_len > 0 && aligned_len <= 0x7f8);
+ self->spi_header[padding > 0 ? 0 : 1] = make_cmd(false, true, fn, addr, len + padding);
+ if (fn == WLAN_FUNCTION) {
+ logic_debug_set(pin_WIFI_RX, 1);
+ }
+ int ret = cyw43_spi_transfer(self, NULL, 4, (uint8_t *)&self->spi_header[padding > 0 ? 0 : 1], aligned_len + 4 + padding);
+ if (fn == WLAN_FUNCTION) {
+ logic_debug_set(pin_WIFI_RX, 0);
+ }
+ if (ret != 0) {
+ printf("cyw43_read_bytes error %d", ret);
+ return ret;
+ }
+ if (buf != self->spid_buf) { // avoid a copy in the usual case just to add the header
+ memcpy(buf, self->spid_buf, len);
+ }
+ return 0;
+}
+
+// See whd_bus_spi_transfer_bytes
+// Note, uses spid_buf if src isn't using it already
+// Apart from firmware download this appears to only be used for wlan functions?
+int cyw43_write_bytes(cyw43_int_t *self, uint32_t fn, uint32_t addr, size_t len, const uint8_t *src) {
+ assert(fn != BACKPLANE_FUNCTION || (len <= 64 && (addr + len) <= 0x8000));
+ size_t aligned_len = (len + 3) & ~3u;
+ assert(aligned_len > 0 && aligned_len <= 0x7f8);
+ if (fn == WLAN_FUNCTION) {
+ // Wait for FIFO to be ready to accept data
+ int f2_ready_attempts = 1000;
+ while (f2_ready_attempts-- > 0) {
+ uint32_t bus_status = cyw43_read_reg_u32(self, BUS_FUNCTION, SPI_STATUS_REGISTER);
+ if (bus_status & STATUS_F2_RX_READY) {
+ logic_debug_set(pin_F2_RX_READY_WAIT, 0);
+ break;
+ } else {
+ logic_debug_set(pin_F2_RX_READY_WAIT, 1);
+ }
+ }
+ if (f2_ready_attempts <= 0) {
+ printf("F2 not ready\n");
+ return CYW43_FAIL_FAST_CHECK(-CYW43_EIO);
+ }
+ }
+ if (src == self->spid_buf) { // avoid a copy in the usual case just to add the header
+ self->spi_header[1] = make_cmd(true, true, fn, addr, len);
+ logic_debug_set(pin_WIFI_TX, 1);
+ int res = cyw43_spi_transfer(self, (uint8_t *)&self->spi_header[1], aligned_len + 4, NULL, 0);
+ logic_debug_set(pin_WIFI_TX, 0);
+ return res;
+ } else {
+ // todo: would be nice to get rid of this. Only used for firmware download?
+ assert(src < self->spid_buf || src >= (self->spid_buf + sizeof(self->spid_buf)));
+ self->spi_header[1] = make_cmd(true, true, fn, addr, len);
+ memcpy(self->spid_buf, src, len);
+ return cyw43_spi_transfer(self, (uint8_t *)&self->spi_header[1], aligned_len + 4, NULL, 0);
+ }
+}
+#endif
diff --git a/src/rp2_common/cyw43_driver/cyw43_bus_pio_spi.pio b/src/rp2_common/cyw43_driver/cyw43_bus_pio_spi.pio
new file mode 100644
index 0000000..ea0d195
--- /dev/null
+++ b/src/rp2_common/cyw43_driver/cyw43_bus_pio_spi.pio
@@ -0,0 +1,61 @@
+;
+; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+;
+; SPDX-License-Identifier: BSD-3-Clause
+;
+
+.program spi_gap0_sample1
+.side_set 1
+
+; always transmit multiple of 32 bytes
+lp: out pins, 1 side 0
+ jmp x-- lp side 1
+public lp1_end:
+ set pindirs, 0 side 0
+lp2:
+ in pins, 1 side 1
+ jmp y-- lp2 side 0
+public end:
+
+.program spi_gap01_sample0
+.side_set 1
+
+; always transmit multiple of 32 bytes
+lp: out pins, 1 side 0
+ jmp x-- lp side 1
+public lp1_end:
+ set pindirs, 0 side 0
+ nop side 1
+lp2:
+ in pins, 1 side 0
+ jmp y-- lp2 side 1
+public end:
+
+.program spi_gap010_sample1
+.side_set 1
+
+; always transmit multiple of 32 bytes
+lp: out pins, 1 side 0
+ jmp x-- lp side 1
+public lp1_end:
+ set pindirs, 0 side 0
+ nop side 1
+ nop side 0
+lp2:
+ in pins, 1 side 1
+ jmp y-- lp2 side 0
+public end:
+
+.program spi_gap0_sample1_regular
+.side_set 1
+
+; always transmit multiple of 32 bytes
+lp: out pins, 1 side 0
+ jmp x-- lp side 1
+public lp1_end:
+ set pindirs, 0 side 0
+lp2:
+ in pins, 1 side 1
+ jmp y-- lp2 side 0
+public end:
+
diff --git a/src/rp2_common/hardware_adc/include/hardware/adc.h b/src/rp2_common/hardware_adc/include/hardware/adc.h
index be82025..b8987ee 100644
--- a/src/rp2_common/hardware_adc/include/hardware/adc.h
+++ b/src/rp2_common/hardware_adc/include/hardware/adc.h
@@ -106,7 +106,7 @@
* \param input_mask A bit pattern indicating which of the 5 inputs are to be sampled. Write a value of 0 to disable round robin sampling.
*/
static inline void adc_set_round_robin(uint input_mask) {
- invalid_params_if(ADC, input_mask & ~ADC_CS_RROBIN_BITS);
+ valid_params_if(ADC, input_mask < (1 << NUM_ADC_CHANNELS));
hw_write_masked(&adc_hw->cs, input_mask << ADC_CS_RROBIN_LSB, ADC_CS_RROBIN_BITS);
}
diff --git a/src/rp2_common/hardware_clocks/clocks.c b/src/rp2_common/hardware_clocks/clocks.c
index f51331a..9ba51f0 100644
--- a/src/rp2_common/hardware_clocks/clocks.c
+++ b/src/rp2_common/hardware_clocks/clocks.c
@@ -148,13 +148,13 @@
/// \tag::pll_settings[]
// Configure PLLs
// REF FBDIV VCO POSTDIV
- // PLL SYS: 12 / 1 = 12MHz * 125 = 1500MHZ / 6 / 2 = 125MHz
- // PLL USB: 12 / 1 = 12MHz * 40 = 480 MHz / 5 / 2 = 48MHz
+ // PLL SYS: 12 / 1 = 12MHz * 125 = 1500MHz / 6 / 2 = 125MHz
+ // PLL USB: 12 / 1 = 12MHz * 100 = 1200MHz / 5 / 5 = 48MHz
/// \end::pll_settings[]
/// \tag::pll_init[]
pll_init(pll_sys, 1, 1500 * MHZ, 6, 2);
- pll_init(pll_usb, 1, 480 * MHZ, 5, 2);
+ pll_init(pll_usb, 1, 1200 * MHZ, 5, 5);
/// \end::pll_init[]
// Configure clocks
diff --git a/src/rp2_common/hardware_clocks/scripts/vcocalc.py b/src/rp2_common/hardware_clocks/scripts/vcocalc.py
index 4d90146..5d143b3 100755
--- a/src/rp2_common/hardware_clocks/scripts/vcocalc.py
+++ b/src/rp2_common/hardware_clocks/scripts/vcocalc.py
@@ -5,7 +5,7 @@
parser = argparse.ArgumentParser(description="PLL parameter calculator")
parser.add_argument("--input", "-i", default=12, help="Input (reference) frequency. Default 12 MHz", type=float)
parser.add_argument("--vco-max", default=1600, help="Override maximum VCO frequency. Default 1600 MHz", type=float)
-parser.add_argument("--vco-min", default=400, help="Override minimum VCO frequency. Default 400 MHz", type=float)
+parser.add_argument("--vco-min", default=750, help="Override minimum VCO frequency. Default 750 MHz", type=float)
parser.add_argument("--low-vco", "-l", action="store_true", help="Use a lower VCO frequency when possible. This reduces power consumption, at the cost of increased jitter")
parser.add_argument("output", help="Output frequency in MHz.", type=float)
args = parser.parse_args()
diff --git a/src/rp2_common/hardware_dma/dma.c b/src/rp2_common/hardware_dma/dma.c
index 90fde06..f142b53 100644
--- a/src/rp2_common/hardware_dma/dma.c
+++ b/src/rp2_common/hardware_dma/dma.c
@@ -36,6 +36,12 @@
hw_claim_clear((uint8_t *) &_claimed, channel);
}
+void dma_unclaim_mask(uint32_t mask) {
+ for(uint i = 0; mask; i++, mask >>= 1u) {
+ if (mask & 1u) dma_channel_unclaim(i);
+ }
+}
+
int dma_claim_unused_channel(bool required) {
return hw_claim_unused_from_range((uint8_t*)&_claimed, required, 0, NUM_DMA_CHANNELS-1, "No DMA channels are available");
}
diff --git a/src/rp2_common/hardware_dma/include/hardware/dma.h b/src/rp2_common/hardware_dma/include/hardware/dma.h
index 7c9406f..ec73564 100644
--- a/src/rp2_common/hardware_dma/include/hardware/dma.h
+++ b/src/rp2_common/hardware_dma/include/hardware/dma.h
@@ -88,12 +88,17 @@
/*! \brief Mark a dma channel as no longer used
* \ingroup hardware_dma
*
- * Method for cooperative claiming of hardware.
- *
* \param channel the dma channel to release
*/
void dma_channel_unclaim(uint channel);
+/*! \brief Mark multiple dma channels as no longer used
+ * \ingroup hardware_dma
+ *
+ * \param channel_mask Bitfield of all channels to unclaim (bit 0 == channel 0, bit 1 == channel 1 etc)
+ */
+void dma_unclaim_mask(uint32_t channel_mask);
+
/*! \brief Claim a free dma channel
* \ingroup hardware_dma
*
@@ -118,7 +123,6 @@
*
* A DMA channel needs to be configured, these functions provide handy helpers to set up configuration
* structures. See \ref dma_channel_config
- *
*/
/*! \brief Enumeration of available DMA channel transfer sizes.
@@ -136,10 +140,10 @@
uint32_t ctrl;
} dma_channel_config;
-/*! \brief Set DMA channel read increment
+/*! \brief Set DMA channel read increment in a channel configuration object
* \ingroup channel_config
*
- * \param c Pointer to channel configuration data
+ * \param c Pointer to channel configuration object
* \param incr True to enable read address increments, if false, each read will be from the same address
* Usually disabled for peripheral to memory transfers
*/
@@ -147,10 +151,10 @@
c->ctrl = incr ? (c->ctrl | DMA_CH0_CTRL_TRIG_INCR_READ_BITS) : (c->ctrl & ~DMA_CH0_CTRL_TRIG_INCR_READ_BITS);
}
-/*! \brief Set DMA channel write increment
+/*! \brief Set DMA channel write increment in a channel configuration object
* \ingroup channel_config
*
- * \param c Pointer to channel configuration data
+ * \param c Pointer to channel configuration object
* \param incr True to enable write address increments, if false, each write will be to the same address
* Usually disabled for memory to peripheral transfers
* Usually disabled for memory to peripheral transfers
@@ -159,7 +163,7 @@
c->ctrl = incr ? (c->ctrl | DMA_CH0_CTRL_TRIG_INCR_WRITE_BITS) : (c->ctrl & ~DMA_CH0_CTRL_TRIG_INCR_WRITE_BITS);
}
-/*! \brief Select a transfer request signal
+/*! \brief Select a transfer request signal in a channel configuration object
* \ingroup channel_config
*
* The channel uses the transfer request signal to pace its data transfer rate.
@@ -179,13 +183,13 @@
c->ctrl = (c->ctrl & ~DMA_CH0_CTRL_TRIG_TREQ_SEL_BITS) | (dreq << DMA_CH0_CTRL_TRIG_TREQ_SEL_LSB);
}
-/*! \brief Set DMA channel completion channel
+/*! \brief Set DMA channel chain_to channel in a channel configuration object
* \ingroup channel_config
*
* When this channel completes, it will trigger the channel indicated by chain_to. Disable by
* setting chain_to to itself (the same channel)
*
- * \param c Pointer to channel configuration data
+ * \param c Pointer to channel configuration object
* \param chain_to Channel to trigger when this channel completes.
*/
static inline void channel_config_set_chain_to(dma_channel_config *c, uint chain_to) {
@@ -193,13 +197,13 @@
c->ctrl = (c->ctrl & ~DMA_CH0_CTRL_TRIG_CHAIN_TO_BITS) | (chain_to << DMA_CH0_CTRL_TRIG_CHAIN_TO_LSB);
}
-/*! \brief Set the size of each DMA bus transfer
+/*! \brief Set the size of each DMA bus transfer in a channel configuration object
* \ingroup channel_config
*
* Set the size of each bus transfer (byte/halfword/word). The read and write addresses
* advance by the specific amount (1/2/4 bytes) with each transfer.
*
- * \param c Pointer to channel configuration data
+ * \param c Pointer to channel configuration object
* \param size See enum for possible values.
*/
static inline void channel_config_set_transfer_data_size(dma_channel_config *c, enum dma_channel_transfer_size size) {
@@ -207,7 +211,7 @@
c->ctrl = (c->ctrl & ~DMA_CH0_CTRL_TRIG_DATA_SIZE_BITS) | (((uint)size) << DMA_CH0_CTRL_TRIG_DATA_SIZE_LSB);
}
-/*! \brief Set address wrapping parameters
+/*! \brief Set address wrapping parameters in a channel configuration object
* \ingroup channel_config
*
* Size of address wrap region. If 0, don’t wrap. For values n > 0, only the lower n bits of the address
@@ -217,7 +221,7 @@
*
* 0x0 -> No wrapping.
*
- * \param c Pointer to channel configuration data
+ * \param c Pointer to channel configuration object
* \param write True to apply to write addresses, false to apply to read addresses
* \param size_bits 0 to disable wrapping. Otherwise the size in bits of the changing part of the address.
* Effectively wraps the address on a (1 << size_bits) byte boundary.
@@ -229,27 +233,27 @@
(write ? DMA_CH0_CTRL_TRIG_RING_SEL_BITS : 0);
}
-/*! \brief Set DMA byte swapping
+/*! \brief Set DMA byte swapping config in a channel configuration object
* \ingroup channel_config
*
* No effect for byte data, for halfword data, the two bytes of each halfword are
* swapped. For word data, the four bytes of each word are swapped to reverse their order.
*
- * \param c Pointer to channel configuration data
+ * \param c Pointer to channel configuration object
* \param bswap True to enable byte swapping
*/
static inline void channel_config_set_bswap(dma_channel_config *c, bool bswap) {
c->ctrl = bswap ? (c->ctrl | DMA_CH0_CTRL_TRIG_BSWAP_BITS) : (c->ctrl & ~DMA_CH0_CTRL_TRIG_BSWAP_BITS);
}
-/*! \brief Set IRQ quiet mode
+/*! \brief Set IRQ quiet mode in a channel configuration object
* \ingroup channel_config
*
* In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead,
* an IRQ is raised when NULL is written to a trigger register, indicating the end of a control
* block chain.
*
- * \param c Pointer to channel configuration data
+ * \param c Pointer to channel configuration object
* \param irq_quiet True to enable quiet mode, false to disable.
*/
static inline void channel_config_set_irq_quiet(dma_channel_config *c, bool irq_quiet) {
@@ -257,13 +261,31 @@
}
/*!
- * \brief Enable/Disable the DMA channel
+ * \brief Set the channel priority in a channel configuration object
+ * \ingroup channel_config
+ *
+ * When true, gives a channel preferential treatment in issue scheduling: in each scheduling round,
+ * all high priority channels are considered first, and then only a single low
+ * priority channel, before returning to the high priority channels.
+ *
+ * This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed.
+ * If the DMA is not saturated then a low priority channel will see no loss of throughput.
+ *
+ * \param c Pointer to channel configuration object
+ * \param high_priority True to enable high priority
+ */
+static inline void channel_config_set_high_priority(dma_channel_config *c, bool high_priority) {
+ c->ctrl = high_priority ? (c->ctrl | DMA_CH0_CTRL_TRIG_HIGH_PRIORITY_BITS) : (c->ctrl & ~DMA_CH0_CTRL_TRIG_HIGH_PRIORITY_BITS);
+}
+
+/*!
+ * \brief Enable/Disable the DMA channel in a channel configuration object
* \ingroup channel_config
*
* When false, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will
* remain high if already high)
*
- * \param c Pointer to channel configuration data
+ * \param c Pointer to channel configuration object
* \param enable True to enable the DMA channel. When enabled, the channel will respond to triggering events, and start transferring data.
*
*/
@@ -271,12 +293,12 @@
c->ctrl = enable ? (c->ctrl | DMA_CH0_CTRL_TRIG_EN_BITS) : (c->ctrl & ~DMA_CH0_CTRL_TRIG_EN_BITS);
}
-/*! \brief Enable access to channel by sniff hardware.
+/*! \brief Enable access to channel by sniff hardware in a channel configuration object
* \ingroup channel_config
*
* Sniff HW must be enabled and have this channel selected.
*
- * \param c Pointer to channel configuration data
+ * \param c Pointer to channel configuration object
* \param sniff_enable True to enable the Sniff HW access to this DMA channel.
*/
static inline void channel_config_set_sniff_enable(dma_channel_config *c, bool sniff_enable) {
@@ -297,6 +319,7 @@
* Ring | write=false, size=0 (i.e. off)
* Byte Swap | false
* Quiet IRQs | false
+ * High Priority | false
* Channel Enable | true
* Sniff Enable | false
*
@@ -315,6 +338,7 @@
channel_config_set_irq_quiet(&c, false);
channel_config_set_enable(&c, true);
channel_config_set_sniff_enable(&c, false);
+ channel_config_set_high_priority( &c, false);
return c;
}
@@ -473,6 +497,32 @@
*
* Function will only return once the DMA has stopped.
*
+ * Note that due to errata RP2040-E13, aborting a channel which has transfers
+ * in-flight (i.e. an individual read has taken place but the corresponding write has not), the ABORT
+ * status bit will clear prematurely, and subsequently the in-flight
+ * transfers will trigger a completion interrupt once they complete.
+ *
+ * The effect of this is that you \em may see a spurious completion interrupt
+ * on the channel as a result of calling this method.
+ *
+ * The calling code should be sure to ignore a completion IRQ as a result of this method. This may
+ * not require any additional work, as aborting a channel which may be about to complete, when you have a completion
+ * IRQ handler registered, is inherently race-prone, and so code is likely needed to disambiguate the two occurrences.
+ *
+ * If that is not the case, but you do have a channel completion IRQ handler registered, you can simply
+ * disable/re-enable the IRQ around the call to this method as shown by this code fragment (using DMA IRQ0).
+ *
+ * \code
+ * // disable the channel on IRQ0
+ * dma_channel_set_irq0_enabled(channel, false);
+ * // abort the channel
+ * dma_channel_abort(channel);
+ * // clear the spurious IRQ (if there was one)
+ * dma_channel_acknowledge_irq0(channel);
+ * // re-enable the channel on IRQ0
+ * dma_channel_set_irq0_enabled(channel, true);
+ *\endcode
+ *
* \param channel DMA channel
*/
static inline void dma_channel_abort(uint channel) {
@@ -480,7 +530,7 @@
dma_hw->abort = 1u << channel;
// Bit will go 0 once channel has reached safe state
// (i.e. any in-flight transfers have retired)
- while (dma_hw->abort & (1ul << channel)) tight_loop_contents();
+ while (dma_hw->ch[channel].ctrl_trig & DMA_CH0_CTRL_TRIG_BUSY_BITS) tight_loop_contents();
}
/*! \brief Enable single DMA channel's interrupt via DMA_IRQ_0
diff --git a/src/rp2_common/hardware_gpio/CMakeLists.txt b/src/rp2_common/hardware_gpio/CMakeLists.txt
index 1bfb078..97a9355 100644
--- a/src/rp2_common/hardware_gpio/CMakeLists.txt
+++ b/src/rp2_common/hardware_gpio/CMakeLists.txt
@@ -1 +1,2 @@
-pico_simple_hardware_target(gpio)
\ No newline at end of file
+pico_simple_hardware_target(gpio)
+target_link_libraries(hardware_gpio INTERFACE hardware_irq)
\ No newline at end of file
diff --git a/src/rp2_common/hardware_gpio/gpio.c b/src/rp2_common/hardware_gpio/gpio.c
index 2816b97..6e4261f 100644
--- a/src/rp2_common/hardware_gpio/gpio.c
+++ b/src/rp2_common/hardware_gpio/gpio.c
@@ -14,11 +14,13 @@
#include "pico/binary_info.h"
#endif
-static gpio_irq_callback_t _callbacks[NUM_CORES];
+static gpio_irq_callback_t callbacks[NUM_CORES];
+// a 1 bit means the IRQ is handled by a raw IRQ handler
+static uint32_t raw_irq_mask[NUM_CORES];
// Get the raw value from the pin, bypassing any muxing or overrides.
int gpio_get_pad(uint gpio) {
- invalid_params_if(GPIO, gpio >= NUM_BANK0_GPIOS);
+ check_gpio_param(gpio);
hw_set_bits(&padsbank0_hw->io[gpio], PADS_BANK0_GPIO0_IE_BITS);
return (iobank0_hw->io[gpio].status & IO_BANK0_GPIO0_STATUS_INFROMPAD_BITS)
>> IO_BANK0_GPIO0_STATUS_INFROMPAD_LSB;
@@ -28,7 +30,7 @@
// Select function for this GPIO, and ensure input/output are enabled at the pad.
// This also clears the input/output/irq override bits.
void gpio_set_function(uint gpio, enum gpio_function fn) {
- invalid_params_if(GPIO, gpio >= NUM_BANK0_GPIOS);
+ check_gpio_param(gpio);
invalid_params_if(GPIO, ((uint32_t)fn << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB) & ~IO_BANK0_GPIO0_CTRL_FUNCSEL_BITS);
// Set input enable on, output disable off
hw_write_masked(&padsbank0_hw->io[gpio],
@@ -42,14 +44,14 @@
/// \end::gpio_set_function[]
enum gpio_function gpio_get_function(uint gpio) {
- invalid_params_if(GPIO, gpio >= NUM_BANK0_GPIOS);
+ check_gpio_param(gpio);
return (enum gpio_function) ((iobank0_hw->io[gpio].ctrl & IO_BANK0_GPIO0_CTRL_FUNCSEL_BITS) >> IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB);
}
// Note that, on RP2040, setting both pulls enables a "bus keep" function,
// i.e. weak pull to whatever is current high/low state of GPIO.
void gpio_set_pulls(uint gpio, bool up, bool down) {
- invalid_params_if(GPIO, gpio >= NUM_BANK0_GPIOS);
+ check_gpio_param(gpio);
hw_write_masked(
&padsbank0_hw->io[gpio],
(bool_to_bit(up) << PADS_BANK0_GPIO0_PUE_LSB) | (bool_to_bit(down) << PADS_BANK0_GPIO0_PDE_LSB),
@@ -59,7 +61,7 @@
// Direct override for per-GPIO IRQ signal
void gpio_set_irqover(uint gpio, uint value) {
- invalid_params_if(GPIO, gpio >= NUM_BANK0_GPIOS);
+ check_gpio_param(gpio);
hw_write_masked(&iobank0_hw->io[gpio].ctrl,
value << IO_BANK0_GPIO0_CTRL_IRQOVER_LSB,
IO_BANK0_GPIO0_CTRL_IRQOVER_BITS
@@ -68,7 +70,7 @@
// Direct overrides for pad controls
void gpio_set_inover(uint gpio, uint value) {
- invalid_params_if(GPIO, gpio >= NUM_BANK0_GPIOS);
+ check_gpio_param(gpio);
hw_write_masked(&iobank0_hw->io[gpio].ctrl,
value << IO_BANK0_GPIO0_CTRL_INOVER_LSB,
IO_BANK0_GPIO0_CTRL_INOVER_BITS
@@ -76,7 +78,7 @@
}
void gpio_set_outover(uint gpio, uint value) {
- invalid_params_if(GPIO, gpio >= NUM_BANK0_GPIOS);
+ check_gpio_param(gpio);
hw_write_masked(&iobank0_hw->io[gpio].ctrl,
value << IO_BANK0_GPIO0_CTRL_OUTOVER_LSB,
IO_BANK0_GPIO0_CTRL_OUTOVER_BITS
@@ -84,7 +86,7 @@
}
void gpio_set_oeover(uint gpio, uint value) {
- invalid_params_if(GPIO, gpio >= NUM_BANK0_GPIOS);
+ check_gpio_param(gpio);
hw_write_masked(&iobank0_hw->io[gpio].ctrl,
value << IO_BANK0_GPIO0_CTRL_OEOVER_LSB,
IO_BANK0_GPIO0_CTRL_OEOVER_BITS
@@ -92,7 +94,7 @@
}
void gpio_set_input_hysteresis_enabled(uint gpio, bool enabled) {
- invalid_params_if(GPIO, gpio >= NUM_BANK0_GPIOS);
+ check_gpio_param(gpio);
if (enabled)
hw_set_bits(&padsbank0_hw->io[gpio], PADS_BANK0_GPIO0_SCHMITT_BITS);
else
@@ -101,12 +103,12 @@
bool gpio_is_input_hysteresis_enabled(uint gpio) {
- invalid_params_if(GPIO, gpio >= NUM_BANK0_GPIOS);
+ check_gpio_param(gpio);
return (padsbank0_hw->io[gpio] & PADS_BANK0_GPIO0_SCHMITT_BITS) != 0;
}
void gpio_set_slew_rate(uint gpio, enum gpio_slew_rate slew) {
- invalid_params_if(GPIO, gpio >= NUM_BANK0_GPIOS);
+ check_gpio_param(gpio);
hw_write_masked(&padsbank0_hw->io[gpio],
(uint)slew << PADS_BANK0_GPIO0_SLEWFAST_LSB,
PADS_BANK0_GPIO0_SLEWFAST_BITS
@@ -114,7 +116,7 @@
}
enum gpio_slew_rate gpio_get_slew_rate(uint gpio) {
- invalid_params_if(GPIO, gpio >= NUM_BANK0_GPIOS);
+ check_gpio_param(gpio);
return (enum gpio_slew_rate)((padsbank0_hw->io[gpio]
& PADS_BANK0_GPIO0_SLEWFAST_BITS)
>> PADS_BANK0_GPIO0_SLEWFAST_LSB);
@@ -124,7 +126,7 @@
// Enum encoding should match hardware encoding on RP2040
static_assert(PADS_BANK0_GPIO0_DRIVE_VALUE_8MA == GPIO_DRIVE_STRENGTH_8MA, "");
void gpio_set_drive_strength(uint gpio, enum gpio_drive_strength drive) {
- invalid_params_if(GPIO, gpio >= NUM_BANK0_GPIOS);
+ check_gpio_param(gpio);
hw_write_masked(&padsbank0_hw->io[gpio],
(uint)drive << PADS_BANK0_GPIO0_DRIVE_LSB,
PADS_BANK0_GPIO0_DRIVE_BITS
@@ -132,25 +134,28 @@
}
enum gpio_drive_strength gpio_get_drive_strength(uint gpio) {
- invalid_params_if(GPIO, gpio >= NUM_BANK0_GPIOS);
+ check_gpio_param(gpio);
return (enum gpio_drive_strength)((padsbank0_hw->io[gpio]
& PADS_BANK0_GPIO0_DRIVE_BITS)
>> PADS_BANK0_GPIO0_DRIVE_LSB);
}
-static void gpio_irq_handler(void) {
- io_irq_ctrl_hw_t *irq_ctrl_base = get_core_num() ?
- &iobank0_hw->proc1_irq_ctrl : &iobank0_hw->proc0_irq_ctrl;
- for (uint gpio = 0; gpio < NUM_BANK0_GPIOS; gpio++) {
- io_ro_32 *status_reg = &irq_ctrl_base->ints[gpio / 8];
- uint events = (*status_reg >> 4 * (gpio % 8)) & 0xf;
- if (events) {
- // TODO: If both cores care about this event then the second core won't get the irq?
- gpio_acknowledge_irq(gpio, events);
- gpio_irq_callback_t callback = _callbacks[get_core_num()];
- if (callback) {
- callback(gpio, events);
+static void gpio_default_irq_handler(void) {
+ uint core = get_core_num();
+ gpio_irq_callback_t callback = callbacks[core];
+ io_irq_ctrl_hw_t *irq_ctrl_base = core ? &iobank0_hw->proc1_irq_ctrl : &iobank0_hw->proc0_irq_ctrl;
+ for (uint gpio = 0; gpio < NUM_BANK0_GPIOS; gpio+=8) {
+ uint32_t events8 = irq_ctrl_base->ints[gpio >> 3u];
+ // note we assume events8 is 0 for non-existent GPIO
+ for(uint i=gpio;events8 && i<gpio+8;i++) {
+ uint32_t events = events8 & 0xfu;
+ if (events && !(raw_irq_mask[core] & (1u << i))) {
+ gpio_acknowledge_irq(i, events);
+ if (callback) {
+ callback(i, events);
+ }
}
+ events8 >>= 4;
}
}
}
@@ -178,21 +183,48 @@
void gpio_set_irq_enabled_with_callback(uint gpio, uint32_t events, bool enabled, gpio_irq_callback_t callback) {
gpio_set_irq_enabled(gpio, events, enabled);
+ gpio_set_irq_callback(callback);
+ if (enabled) irq_set_enabled(IO_IRQ_BANK0, true);
+}
- // TODO: Do we want to support a callback per GPIO pin?
- // Install IRQ handler
- _callbacks[get_core_num()] = callback;
- irq_set_exclusive_handler(IO_IRQ_BANK0, gpio_irq_handler);
- irq_set_enabled(IO_IRQ_BANK0, true);
+void gpio_set_irq_callback(gpio_irq_callback_t callback) {
+ uint core = get_core_num();
+ if (callbacks[core]) {
+ if (!callback) {
+ irq_remove_handler(IO_IRQ_BANK0, gpio_default_irq_handler);
+ }
+ callbacks[core] = callback;
+ } else if (callback) {
+ callbacks[core] = callback;
+ irq_add_shared_handler(IO_IRQ_BANK0, gpio_default_irq_handler, GPIO_IRQ_CALLBACK_ORDER_PRIORITY);
+ }
+}
+
+void gpio_add_raw_irq_handler_with_order_priority_masked(uint gpio_mask, irq_handler_t handler, uint8_t order_priority) {
+ hard_assert(!(raw_irq_mask[get_core_num()] & gpio_mask)); // should not add multiple handlers for the same event
+ raw_irq_mask[get_core_num()] |= gpio_mask;
+ irq_add_shared_handler(IO_IRQ_BANK0, handler, order_priority);
+}
+
+void gpio_add_raw_irq_handler_masked(uint gpio_mask, irq_handler_t handler) {
+ gpio_add_raw_irq_handler_with_order_priority_masked(gpio_mask, handler, GPIO_RAW_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
+}
+
+void gpio_remove_raw_irq_handler_masked(uint gpio_mask, irq_handler_t handler) {
+ assert(raw_irq_mask[get_core_num()] & gpio_mask); // should not remove handlers that are not added
+ irq_remove_handler(IO_IRQ_BANK0, handler);
+ raw_irq_mask[get_core_num()] &= ~gpio_mask;
}
void gpio_set_dormant_irq_enabled(uint gpio, uint32_t events, bool enabled) {
+ check_gpio_param(gpio);
io_irq_ctrl_hw_t *irq_ctrl_base = &iobank0_hw->dormant_wake_irq_ctrl;
_gpio_set_irq_enabled(gpio, events, enabled, irq_ctrl_base);
}
void gpio_acknowledge_irq(uint gpio, uint32_t events) {
- iobank0_hw->intr[gpio / 8] = events << 4 * (gpio % 8);
+ check_gpio_param(gpio);
+ iobank0_hw->intr[gpio / 8] = events << (4 * (gpio % 8));
}
#define DEBUG_PIN_MASK (((1u << PICO_DEBUG_PIN_COUNT)-1) << PICO_DEBUG_PIN_BASE)
@@ -217,8 +249,12 @@
gpio_set_function(gpio, GPIO_FUNC_SIO);
}
+void gpio_deinit(uint gpio) {
+ gpio_set_function(gpio, GPIO_FUNC_NULL);
+}
+
void gpio_init_mask(uint gpio_mask) {
- for(uint i=0;i<32;i++) {
+ for(uint i=0;i<NUM_BANK0_GPIOS;i++) {
if (gpio_mask & 1) {
gpio_init(i);
}
diff --git a/src/rp2_common/hardware_gpio/include/hardware/gpio.h b/src/rp2_common/hardware_gpio/include/hardware/gpio.h
index 7037e85..09a9b96 100644
--- a/src/rp2_common/hardware_gpio/include/hardware/gpio.h
+++ b/src/rp2_common/hardware_gpio/include/hardware/gpio.h
@@ -10,6 +10,8 @@
#include "pico.h"
#include "hardware/structs/sio.h"
#include "hardware/structs/padsbank0.h"
+#include "hardware/structs/iobank0.h"
+#include "hardware/irq.h"
#ifdef __cplusplus
extern "C" {
@@ -102,7 +104,7 @@
#define GPIO_OUT 1
#define GPIO_IN 0
-/*! \brief GPIO Interrupt level definitions
+/*! \brief GPIO Interrupt level definitions (GPIO events)
* \ingroup hardware_gpio
* \brief GPIO Interrupt levels
*
@@ -128,10 +130,11 @@
* \ingroup hardware_gpio
*
* \param gpio Which GPIO caused this interrupt
- * \param events Which events caused this interrupt. See \ref gpio_set_irq_enabled for details.
+ * \param event_mask Which events caused this interrupt. See \ref gpio_irq_level for details.
* \sa gpio_set_irq_enabled_with_callback()
+ * \sa gpio_set_irq_callback()
*/
-typedef void (*gpio_irq_callback_t)(uint gpio, uint32_t events);
+typedef void (*gpio_irq_callback_t)(uint gpio, uint32_t event_mask);
enum gpio_override {
GPIO_OVERRIDE_NORMAL = 0, ///< peripheral signal selected via \ref gpio_set_function
@@ -165,6 +168,10 @@
GPIO_DRIVE_STRENGTH_12MA = 3 ///< 12 mA nominal drive strength
};
+static inline void check_gpio_param(__unused uint gpio) {
+ invalid_params_if(GPIO, gpio >= NUM_BANK0_GPIOS);
+}
+
// ----------------------------------------------------------------------------
// Pad Controls + IO Muxing
// ----------------------------------------------------------------------------
@@ -346,63 +353,288 @@
*/
enum gpio_drive_strength gpio_get_drive_strength(uint gpio);
-/*! \brief Enable or disable interrupts for specified GPIO
+/*! \brief Enable or disable specific interrupt events for specified GPIO
* \ingroup hardware_gpio
*
- * \note The IO IRQs are independent per-processor. This configures IRQs for
+ * This function sets which GPIO events cause a GPIO interrupt on the calling core. See
+ * \ref gpio_set_irq_callback, \ref gpio_set_irq_enabled_with_callback and
+ * \ref gpio_add_raw_irq_handler to set up a GPIO interrupt handler to handle the events.
+ *
+ * \note The IO IRQs are independent per-processor. This configures the interrupt events for
* the processor that calls the function.
*
* \param gpio GPIO number
- * \param events Which events will cause an interrupt
+ * \param event_mask Which events will cause an interrupt
* \param enabled Enable or disable flag
*
- * Events is a bitmask of the following:
+ * Events is a bitmask of the following \ref gpio_irq_level values:
*
- * bit | interrupt
- * ----|----------
- * 0 | Low level
- * 1 | High level
- * 2 | Edge low
- * 3 | Edge high
+ * bit | constant | interrupt
+ * ----|----------------------------------------------------------
+ * 0 | GPIO_IRQ_LEVEL_LOW | Continuously while level is low
+ * 1 | GPIO_IRQ_LEVEL_HIGH | Continuously while level is high
+ * 2 | GPIO_IRQ_EDGE_FALL | On each transition from high to low
+ * 3 | GPIO_IRQ_EDGE_RISE | On each transition from low to high
+ *
+ * which are specified in \ref gpio_irq_level
*/
-void gpio_set_irq_enabled(uint gpio, uint32_t events, bool enabled);
+void gpio_set_irq_enabled(uint gpio, uint32_t event_mask, bool enabled);
-/*! \brief Enable interrupts for specified GPIO
+// PICO_CONFIG: GPIO_IRQ_CALLBACK_ORDER_PRIORITY, the irq priority order of the default IRQ callback, min=0, max=255, default=PICO_SHARED_IRQ_HANDLER_LOWEST_ORDER_PRIORITY, group=hardware_gpio
+#ifndef GPIO_IRQ_CALLBACK_ORDER_PRIORITY
+#define GPIO_IRQ_CALLBACK_ORDER_PRIORITY PICO_SHARED_IRQ_HANDLER_LOWEST_ORDER_PRIORITY
+#endif
+
+// PICO_CONFIG: GPIO_RAW_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY, the irq priority order of raw IRQ handlers if the priortiy is not specified, min=0, max=255, default=PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY, group=hardware_gpio
+#ifndef GPIO_RAW_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY
+#define GPIO_RAW_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY
+#endif
+
+/*! \brief Set the generic callback used for GPIO IRQ events for the current core
* \ingroup hardware_gpio
*
- * \note The IO IRQs are independent per-processor. This configures IRQs for
+ * This function sets the callback used for all GPIO IRQs on the current core that are not explicitly
+ * hooked via \ref gpio_add_raw_irq_handler or other gpio_add_raw_irq_handler_ functions.
+ *
+ * This function is called with the GPIO number and event mask for each of the (not explicitly hooked)
+ * GPIOs that have events enabled and that are pending (see \ref gpio_get_irq_event_mask).
+ *
+ * \note The IO IRQs are independent per-processor. This function affects
* the processor that calls the function.
*
- * \param gpio GPIO number
- * \param events Which events will cause an interrupt. See \ref gpio_set_irq_enabled for details.
- * \param enabled Enable or disable flag
- * \param callback user function to call on GPIO irq. Note only one of these can be set per processor.
- *
- * \note Currently the GPIO parameter is ignored, and this callback will be called for any enabled GPIO IRQ on any pin.
- *
+ * \param callback default user function to call on GPIO irq. Note only one of these can be set per processor.
*/
-void gpio_set_irq_enabled_with_callback(uint gpio, uint32_t events, bool enabled, gpio_irq_callback_t callback);
+void gpio_set_irq_callback(gpio_irq_callback_t callback);
-/*! \brief Enable dormant wake up interrupt for specified GPIO
+/*! \brief Convenience function which performs multiple GPIO IRQ related initializations
+ * \ingroup hardware_gpio
+ *
+ * This method is a slightly eclectic mix of initialization, that:
+ *
+ * \li Updates whether the specified events for the specified GPIO causes an interrupt on the calling core based
+ * on the enable flag.
+ *
+ * \li Sets the callback handler for the calling core to callback (or clears the handler if the callback is NULL).
+ *
+ * \li Enables GPIO IRQs on the current core if enabled is true.
+ *
+ * This method is commonly used to perform a one time setup, and following that any additional IRQs/events are enabled
+ * via \ref gpio_set_irq_enabled. All GPIOs/events added in this way on the same core share the same callback; for multiple
+ * independent handlers for different GPIOs you should use \ref gpio_add_raw_irq_handler and related functions.
+ *
+ * This method is equivalent to:
+ *
+ * \code{.c}
+ * gpio_set_irq_enabled(gpio, event_mask, enabled);
+ * gpio_set_irq_callback(callback);
+ * if (enabled) irq_set_enabled(IO_IRQ_BANK0, true);
+ * \endcode
+ *
+ * \note The IO IRQs are independent per-processor. This method affects only the processor that calls the function.
+ *
+ * \param gpio GPIO number
+ * \param event_mask Which events will cause an interrupt. See \ref gpio_irq_level for details.
+ * \param enabled Enable or disable flag
+ * \param callback user function to call on GPIO irq. if NULL, the callback is removed
+ */
+void gpio_set_irq_enabled_with_callback(uint gpio, uint32_t event_mask, bool enabled, gpio_irq_callback_t callback);
+
+/*! \brief Enable dormant wake up interrupt for specified GPIO and events
* \ingroup hardware_gpio
*
* This configures IRQs to restart the XOSC or ROSC when they are
* disabled in dormant mode
*
* \param gpio GPIO number
- * \param events Which events will cause an interrupt. See \ref gpio_set_irq_enabled for details.
+ * \param event_mask Which events will cause an interrupt. See \ref gpio_irq_level for details.
* \param enabled Enable/disable flag
*/
-void gpio_set_dormant_irq_enabled(uint gpio, uint32_t events, bool enabled);
+void gpio_set_dormant_irq_enabled(uint gpio, uint32_t event_mask, bool enabled);
-/*! \brief Acknowledge a GPIO interrupt
+/*! \brief Return the current interrupt status (pending events) for the given GPIO
* \ingroup hardware_gpio
*
* \param gpio GPIO number
- * \param events Bitmask of events to clear. See \ref gpio_set_irq_enabled for details.
- *
+ * \return Bitmask of events that are currently pending for the GPIO. See \ref gpio_irq_level for details.
+ * \sa gpio_acknowledge_irq
*/
-void gpio_acknowledge_irq(uint gpio, uint32_t events);
+static inline uint32_t gpio_get_irq_event_mask(uint gpio) {
+ check_gpio_param(gpio);
+ io_irq_ctrl_hw_t *irq_ctrl_base = get_core_num() ?
+ &iobank0_hw->proc1_irq_ctrl : &iobank0_hw->proc0_irq_ctrl;
+ io_ro_32 *status_reg = &irq_ctrl_base->ints[gpio >> 3u];
+ return (*status_reg >> (4 * (gpio & 7u))) & 0xfu;
+}
+
+/*! \brief Acknowledge a GPIO interrupt for the specified events on the calling core
+ * \ingroup hardware_gpio
+ *
+ * \note This may be called with a mask of any of valid bits specified in \ref gpio_irq_level, however
+ * it has no effect on \a level sensitive interrupts which remain pending while the GPIO is at the specified
+ * level. When handling \a level sensitive interrupts, you should generally disable the interrupt (see
+ * \ref gpio_set_irq_enabled) and then set it up again later once the GPIO level has changed (or to catch
+ * the opposite level).
+ *
+ * \param gpio GPIO number
+ * \param events Bitmask of events to clear. See \ref gpio_set_irq_enabled for details.
+ *
+ * \note For callbacks set with \ref gpio_set_irq_enabled_with_callback, or \ref gpio_set_irq_callback,this function is called automatically.
+ * \param event_mask Bitmask of events to clear. See \ref gpio_irq_level for details.
+ */
+void gpio_acknowledge_irq(uint gpio, uint32_t event_mask);
+
+/*! \brief Adds a raw GPIO IRQ handler for the specified GPIOs on the current core
+ * \ingroup hardware_gpio
+ *
+ * In addition to the default mechanism of a single GPIO IRQ event callback per core (see \ref gpio_set_irq_callback),
+ * it is possible to add explicit GPIO IRQ handlers which are called independent of the default callback. The order
+ * relative to the default callback can be controlled via the order_priority parameter (the default callback has the priority
+ * \ref GPIO_IRQ_CALLBACK_ORDER_PRIORITY which defaults to the lowest priority with the intention of it running last).
+ *
+ * This method adds such an explicit GPIO IRQ handler, and disables the "default" callback for the specified GPIOs.
+ *
+ * \note Multiple raw handlers should not be added for the same GPIOs, and this method will assert if you attempt to.
+ *
+ * A raw handler should check for whichever GPIOs and events it handles, and acknowledge them itself; it might look something like:
+ *
+ * \code{.c}
+ * void my_irq_handler(void) {
+ * if (gpio_get_irq_event_mask(my_gpio_num) & my_gpio_event_mask) {
+ * gpio_acknowledge_irq(my_gpio_num, my_gpio_event_mask);
+ * // handle the IRQ
+ * }
+ * if (gpio_get_irq_event_mask(my_gpio_num2) & my_gpio_event_mask2) {
+ * gpio_acknowledge_irq(my_gpio_num2, my_gpio_event_mask2);
+ * // handle the IRQ
+ * }
+ * }
+ * \endcode
+ *
+ * @param gpio_mask a bit mask of the GPIO numbers that will no longer be passed to the default callback for this core
+ * @param handler the handler to add to the list of GPIO IRQ handlers for this core
+ * @param order_priority the priority order to determine the relative position of the handler in the list of GPIO IRQ handlers for this core.
+ */
+void gpio_add_raw_irq_handler_with_order_priority_masked(uint gpio_mask, irq_handler_t handler, uint8_t order_priority);
+
+/*! \brief Adds a raw GPIO IRQ handler for a specific GPIO on the current core
+ * \ingroup hardware_gpio
+ *
+ * In addition to the default mechanism of a single GPIO IRQ event callback per core (see \ref gpio_set_irq_callback),
+ * it is possible to add explicit GPIO IRQ handlers which are called independent of the default callback. The order
+ * relative to the default callback can be controlled via the order_priority parameter(the default callback has the priority
+ * \ref GPIO_IRQ_CALLBACK_ORDER_PRIORITY which defaults to the lowest priority with the intention of it running last).
+ *
+ * This method adds such a callback, and disables the "default" callback for the specified GPIO.
+ *
+ * \note Multiple raw handlers should not be added for the same GPIO, and this method will assert if you attempt to.
+ *
+ * A raw handler should check for whichever GPIOs and events it handles, and acknowledge them itself; it might look something like:
+ *
+ * \code{.c}
+ * void my_irq_handler(void) {
+ * if (gpio_get_irq_event_mask(my_gpio_num) & my_gpio_event_mask) {
+ * gpio_acknowledge_irq(my_gpio_num, my_gpio_event_mask);
+ * // handle the IRQ
+ * }
+ * }
+ * \endcode
+ *
+ * @param gpio the GPIO number that will no longer be passed to the default callback for this core
+ * @param handler the handler to add to the list of GPIO IRQ handlers for this core
+ * @param order_priority the priority order to determine the relative position of the handler in the list of GPIO IRQ handlers for this core.
+ */
+static inline void gpio_add_raw_irq_handler_with_order_priority(uint gpio, irq_handler_t handler, uint8_t order_priority) {
+ check_gpio_param(gpio);
+ gpio_add_raw_irq_handler_with_order_priority_masked(1u << gpio, handler, order_priority);
+}
+
+/*! \brief Adds a raw GPIO IRQ handler for the specified GPIOs on the current core
+ * \ingroup hardware_gpio
+ *
+ * In addition to the default mechanism of a single GPIO IRQ event callback per core (see \ref gpio_set_irq_callback),
+ * it is possible to add explicit GPIO IRQ handlers which are called independent of the default event callback.
+ *
+ * This method adds such a callback, and disables the "default" callback for the specified GPIOs.
+ *
+ * \note Multiple raw handlers should not be added for the same GPIOs, and this method will assert if you attempt to.
+ *
+ * A raw handler should check for whichever GPIOs and events it handles, and acknowledge them itself; it might look something like:
+ *
+ * \code{.c}
+ * void my_irq_handler(void) {
+ * if (gpio_get_irq_event_mask(my_gpio_num) & my_gpio_event_mask) {
+ * gpio_acknowledge_irq(my_gpio_num, my_gpio_event_mask);
+ * // handle the IRQ
+ * }
+ * if (gpio_get_irq_event_mask(my_gpio_num2) & my_gpio_event_mask2) {
+ * gpio_acknowledge_irq(my_gpio_num2, my_gpio_event_mask2);
+ * // handle the IRQ
+ * }
+ * }
+ * \endcode
+ *
+ * @param gpio_mask a bit mask of the GPIO numbers that will no longer be passed to the default callback for this core
+ * @param handler the handler to add to the list of GPIO IRQ handlers for this core
+ */
+void gpio_add_raw_irq_handler_masked(uint gpio_mask, irq_handler_t handler);
+
+/*! \brief Adds a raw GPIO IRQ handler for a specific GPIO on the current core
+ * \ingroup hardware_gpio
+ *
+ * In addition to the default mechanism of a single GPIO IRQ event callback per core (see \ref gpio_set_irq_callback),
+ * it is possible to add explicit GPIO IRQ handlers which are called independent of the default event callback.
+ *
+ * This method adds such a callback, and disables the "default" callback for the specified GPIO.
+ *
+ * \note Multiple raw handlers should not be added for the same GPIO, and this method will assert if you attempt to.
+ *
+ * A raw handler should check for whichever GPIOs and events it handles, and acknowledge them itself; it might look something like:
+ *
+ * \code{.c}
+ * void my_irq_handler(void) {
+ * if (gpio_get_irq_event_mask(my_gpio_num) & my_gpio_event_mask) {
+ * gpio_acknowledge_irq(my_gpio_num, my_gpio_event_mask);
+ * // handle the IRQ
+ * }
+ * }
+ * \endcode
+ *
+ * @param gpio the GPIO number that will no longer be passed to the default callback for this core
+ * @param handler the handler to add to the list of GPIO IRQ handlers for this core
+ */
+static inline void gpio_add_raw_irq_handler(uint gpio, irq_handler_t handler) {
+ check_gpio_param(gpio);
+ gpio_add_raw_irq_handler_masked(1u << gpio, handler);
+}
+
+/*! \brief Removes a raw GPIO IRQ handler for the specified GPIOs on the current core
+ * \ingroup hardware_gpio
+ *
+ * In addition to the default mechanism of a single GPIO IRQ event callback per core (see \ref gpio_set_irq_callback),
+ * it is possible to add explicit GPIO IRQ handlers which are called independent of the default event callback.
+ *
+ * This method removes such a callback, and enables the "default" callback for the specified GPIOs.
+ *
+ * @param gpio_mask a bit mask of the GPIO numbers that will now be passed to the default callback for this core
+ * @param handler the handler to remove from the list of GPIO IRQ handlers for this core
+ */
+void gpio_remove_raw_irq_handler_masked(uint gpio_mask, irq_handler_t handler);
+
+/*! \brief Removes a raw GPIO IRQ handler for the specified GPIO on the current core
+ * \ingroup hardware_gpio
+ *
+ * In addition to the default mechanism of a single GPIO IRQ event callback per core (see \ref gpio_set_irq_callback),
+ * it is possible to add explicit GPIO IRQ handlers which are called independent of the default event callback.
+ *
+ * This method removes such a callback, and enables the "default" callback for the specified GPIO.
+ *
+ * @param gpio the GPIO number that will now be passed to the default callback for this core
+ * @param handler the handler to remove from the list of GPIO IRQ handlers for this core
+ */
+static inline void gpio_remove_raw_irq_handler(uint gpio, irq_handler_t handler) {
+ check_gpio_param(gpio);
+ gpio_remove_raw_irq_handler_masked(1u << gpio, handler);
+}
/*! \brief Initialise a GPIO for (enabled I/O and set func to GPIO_FUNC_SIO)
* \ingroup hardware_gpio
@@ -414,6 +646,13 @@
*/
void gpio_init(uint gpio);
+/*! \brief Resets a GPIO back to the NULL function, i.e. disables it.
+ * \ingroup hardware_gpio
+ *
+ * \param gpio GPIO number
+ */
+void gpio_deinit(uint gpio);
+
/*! \brief Initialise multiple GPIOs (enabled I/O and set func to GPIO_FUNC_SIO)
* \ingroup hardware_gpio
*
diff --git a/src/rp2_common/hardware_i2c/include/hardware/i2c.h b/src/rp2_common/hardware_i2c/include/hardware/i2c.h
index 23ff8f1..202ec02 100644
--- a/src/rp2_common/hardware_i2c/include/hardware/i2c.h
+++ b/src/rp2_common/hardware_i2c/include/hardware/i2c.h
@@ -89,7 +89,7 @@
* master.
*
* The I2C bus frequency is set as close as possible to requested, and
- * the return actual rate set is returned
+ * the actual rate set is returned
*
* \param i2c Either \ref i2c0 or \ref i2c1
* \param baudrate Baudrate in Hz (e.g. 100kHz is 100000)
diff --git a/src/rp2_common/hardware_irq/include/hardware/irq.h b/src/rp2_common/hardware_irq/include/hardware/irq.h
index 424a497..66679fe 100644
--- a/src/rp2_common/hardware_irq/include/hardware/irq.h
+++ b/src/rp2_common/hardware_irq/include/hardware/irq.h
@@ -103,6 +103,9 @@
#define PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY 0x80
#endif
+#define PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY 0xff
+#define PICO_SHARED_IRQ_HANDLER_LOWEST_ORDER_PRIORITY 0x00
+
// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_IRQ, Enable/disable assertions in the IRQ module, type=bool, default=0, group=hardware_irq
#ifndef PARAM_ASSERTIONS_ENABLED_IRQ
#define PARAM_ASSERTIONS_ENABLED_IRQ 0
@@ -126,7 +129,7 @@
/*! \brief Set specified interrupt's priority
* \ingroup hardware_irq
*
- * \param num Interrupt number
+ * \param num Interrupt number \ref interrupt_nums
* \param hardware_priority Priority to set.
* Numerically-lower values indicate a higher priority. Hardware priorities
* range from 0 (highest priority) to 255 (lowest priority) though only the
@@ -147,7 +150,7 @@
* initialized to PICO_DEFAULT_IRQ_PRIORITY by the SDK runtime at startup.
* PICO_DEFAULT_IRQ_PRIORITY defaults to 0x80
*
- * \param num Interrupt number
+ * \param num Interrupt number \ref interrupt_nums
* \return the IRQ priority
*/
uint irq_get_priority(uint num);
@@ -171,7 +174,7 @@
/*! \brief Enable/disable multiple interrupts on the executing core
* \ingroup hardware_irq
*
- * \param mask 32-bit mask with one bits set for the interrupts to enable/disable
+ * \param mask 32-bit mask with one bits set for the interrupts to enable/disable \ref interrupt_nums
* \param enabled true to enable the interrupts, false to disable them.
*/
void irq_set_mask_enabled(uint32_t mask, bool enabled);
@@ -216,7 +219,7 @@
* the (total across all IRQs on both cores) maximum (configurable via PICO_MAX_SHARED_IRQ_HANDLERS) number of shared handlers
* would be exceeded.
*
- * \param num Interrupt number
+ * \param num Interrupt number \ref interrupt_nums
* \param handler The handler to set. See \ref irq_handler_t
* \param order_priority The order priority controls the order that handlers for the same IRQ number on the core are called.
* The shared irq handlers for an interrupt are all called when an IRQ fires, however the order of the calls is based
@@ -224,6 +227,9 @@
* rule of thumb is to use PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY if you don't much care, as it is in the middle of
* the priority range by default.
*
+ * \note The order_priority uses \em higher values for higher priorities which is the \em opposite of the CPU interrupt priorities passed
+ * to irq_set_priority() which use lower values for higher priorities.
+ *
* \see irq_set_exclusive_handler()
*/
void irq_add_shared_handler(uint num, irq_handler_t handler, uint8_t order_priority);
@@ -246,6 +252,14 @@
*/
void irq_remove_handler(uint num, irq_handler_t handler);
+/*! \brief Determine if the current handler for the given number is shared
+ * \ingroup hardware_irq
+ *
+ * \param num Interrupt number \ref interrupt_nums
+ * \param return true if the specified IRQ has a shared handler
+ */
+bool irq_has_shared_handler(uint num);
+
/*! \brief Get the current IRQ handler for the specified IRQ from the currently installed hardware vector table (VTOR)
* of the execution core
* \ingroup hardware_irq
@@ -258,6 +272,10 @@
/*! \brief Clear a specific interrupt on the executing core
* \ingroup hardware_irq
*
+ * This method is only useful for "software" IRQs that are not connected to hardware (i.e. IRQs 26-31)
+ * as the the NVIC always reflects the current state of the IRQ state of the hardware for hardware IRQs, and clearing
+ * of the IRQ state of the hardware is performed via the hardware's registers instead.
+ *
* \param int_num Interrupt number \ref interrupt_nums
*/
static inline void irq_clear(uint int_num) {
@@ -279,6 +297,69 @@
* \note This is an internal method and user should generally not call it.
*/
void irq_init_priorities(void);
+
+/*! \brief Claim ownership of a user IRQ on the calling core
+ * \ingroup hardware_irq
+ *
+ * User IRQs are numbered 26-31 and are not connected to any hardware, but can be triggered by \ref irq_set_pending.
+ *
+ * \note User IRQs are a core local feature; they cannot be used to communicate between cores. Therfore all functions
+ * dealing with Uer IRQs affect only the calling core
+ *
+ * This method explicitly claims ownership of a user IRQ, so other code can know it is being used.
+ *
+ * \param irq_num the user IRQ to claim
+ */
+void user_irq_claim(uint irq_num);
+
+/*! \brief Mark a user IRQ as no longer used on the calling core
+ * \ingroup hardware_irq
+ *
+ * User IRQs are numbered 26-31 and are not connected to any hardware, but can be triggered by \ref irq_set_pending.
+ *
+ * \note User IRQs are a core local feature; they cannot be used to communicate between cores. Therfore all functions
+ * dealing with Uer IRQs affect only the calling core
+ *
+ * This method explicitly releases ownership of a user IRQ, so other code can know it is free to use.
+ *
+ * \note it is customary to have disabled the irq and removed the handler prior to calling this method.
+ *
+ * \param irq_num the irq irq_num to unclaim
+ */
+void user_irq_unclaim(uint irq_num);
+
+/*! \brief Claim ownership of a free user IRQ on the calling core
+ * \ingroup hardware_irq
+ *
+ * User IRQs are numbered 26-31 and are not connected to any hardware, but can be triggered by \ref irq_set_pending.
+ *
+ * \note User IRQs are a core local feature; they cannot be used to communicate between cores. Therfore all functions
+ * dealing with Uer IRQs affect only the calling core
+ *
+ * This method explicitly claims ownership of an unused user IRQ if there is one, so other code can know it is being used.
+ *
+ * \param required if true the function will panic if none are available
+ * \return the user IRQ number or -1 if required was false, and none were free
+ */
+int user_irq_claim_unused(bool required);
+
+/*
+*! \brief Check if a user IRQ is in use on the calling core
+ * \ingroup hardware_irq
+ *
+ * User IRQs are numbered 26-31 and are not connected to any hardware, but can be triggered by \ref irq_set_pending.
+ *
+ * \note User IRQs are a core local feature; they cannot be used to communicate between cores. Therfore all functions
+ * dealing with Uer IRQs affect only the calling core
+ *
+ * \param irq_num the irq irq_num
+ * \return true if the irq_num is claimed, false otherwise
+ * \sa user_irq_claim
+ * \sa user_irq_unclaim
+ * \sa user_irq_claim_unused
+ */
+bool user_irq_is_claimed(uint irq_num);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/rp2_common/hardware_irq/irq.c b/src/rp2_common/hardware_irq/irq.c
index 211f6d0..251cdf7 100644
--- a/src/rp2_common/hardware_irq/irq.c
+++ b/src/rp2_common/hardware_irq/irq.c
@@ -8,12 +8,15 @@
#include "hardware/regs/m0plus.h"
#include "hardware/platform_defs.h"
#include "hardware/structs/scb.h"
+#include "hardware/claim.h"
#include "pico/mutex.h"
#include "pico/assert.h"
extern void __unhandled_user_irq(void);
+static uint8_t user_irq_claimed[NUM_CORES];
+
static inline irq_handler_t *get_vtable(void) {
return (irq_handler_t *) scb_hw->vtor;
}
@@ -92,10 +95,21 @@
static inline bool is_shared_irq_raw_handler(irq_handler_t raw_handler) {
return (uintptr_t)raw_handler - (uintptr_t)irq_handler_chain_slots < sizeof(irq_handler_chain_slots);
}
+
+bool irq_has_shared_handler(uint irq_num) {
+ check_irq_param(irq_num);
+ irq_handler_t handler = irq_get_vtable_handler(irq_num);
+ return handler && is_shared_irq_raw_handler(handler);
+}
+
#else
#define is_shared_irq_raw_handler(h) false
+bool irq_has_shared_handler(uint irq_num) {
+ return false;
+}
#endif
+
irq_handler_t irq_get_vtable_handler(uint num) {
check_irq_param(num);
return get_vtable()[16 + num];
@@ -135,9 +149,9 @@
static uint16_t make_branch(uint16_t *from, void *to) {
uint32_t ui_from = (uint32_t)from;
uint32_t ui_to = (uint32_t)to;
- uint32_t delta = (ui_to - ui_from - 4) / 2;
- assert(!(delta >> 11u));
- return (uint16_t)(0xe000 | (delta & 0x7ff));
+ int32_t delta = (int32_t)(ui_to - ui_from - 4);
+ assert(delta >= -2048 && delta <= 2046 && !(delta & 1));
+ return (uint16_t)(0xe000 | ((delta >> 1) & 0x7ff));
}
static void insert_branch_and_link(uint16_t *from, void *to) {
@@ -287,7 +301,6 @@
struct irq_handler_chain_slot *prev_slot = NULL;
struct irq_handler_chain_slot *existing_vtable_slot = remove_thumb_bit(vtable_handler);
struct irq_handler_chain_slot *to_free_slot = existing_vtable_slot;
- int8_t to_free_slot_index = get_slot_index(to_free_slot);
while (to_free_slot->handler != handler) {
prev_slot = to_free_slot;
if (to_free_slot->link < 0) break;
@@ -325,7 +338,7 @@
}
// add slot back to free list
to_free_slot->link = irq_hander_chain_free_slot_head;
- irq_hander_chain_free_slot_head = to_free_slot_index;
+ irq_hander_chain_free_slot_head = get_slot_index(to_free_slot);
} else {
// since we are the last slot we know that our inst3 hasn't executed yet, so we change
// it to bl to irq_handler_chain_remove_tail which will remove the slot.
@@ -411,3 +424,31 @@
}
#endif
}
+
+#define FIRST_USER_IRQ (NUM_IRQS - NUM_USER_IRQS)
+
+static uint get_user_irq_claim_index(uint irq_num) {
+ invalid_params_if(IRQ, irq_num < FIRST_USER_IRQ || irq_num >= NUM_IRQS);
+ // we count backwards from the last, to match the existing hard coded uses of user IRQs in the SDK which were previously using 31
+ static_assert(NUM_IRQS - FIRST_USER_IRQ <= 8, ""); // we only use a single byte's worth of claim bits today.
+ return NUM_IRQS - irq_num - 1u;
+}
+
+void user_irq_claim(uint irq_num) {
+ hw_claim_or_assert(&user_irq_claimed[get_core_num()], get_user_irq_claim_index(irq_num), "User IRQ is already claimed");
+}
+
+void user_irq_unclaim(uint irq_num) {
+ hw_claim_clear(&user_irq_claimed[get_core_num()], get_user_irq_claim_index(irq_num));
+}
+
+int user_irq_claim_unused(bool required) {
+ int bit = hw_claim_unused_from_range(&user_irq_claimed[get_core_num()], required, 0, NUM_USER_IRQS - 1, "No user IRQs are available");
+ if (bit >= 0) bit = (int)NUM_IRQS - bit - 1;
+ return bit;
+}
+
+bool user_irq_is_claimed(uint irq_num) {
+ return hw_is_claimed(&user_irq_claimed[get_core_num()], get_user_irq_claim_index(irq_num));
+}
+
diff --git a/src/rp2_common/hardware_irq/irq_handler_chain.S b/src/rp2_common/hardware_irq/irq_handler_chain.S
index 7d7be7d..ca15292 100644
--- a/src/rp2_common/hardware_irq/irq_handler_chain.S
+++ b/src/rp2_common/hardware_irq/irq_handler_chain.S
@@ -54,17 +54,18 @@
.endr
irq_handler_chain_first_slot:
- push {lr}
- ldr r0, [r1, #4]
- adds r1, #1
- mov lr, r1
- bx r0
+ push {lr} // Save EXC_RETURN token, so `pop {pc}` will return from interrupt
+ ldr r0, [r1, #4] // Get `handler` field of irq_handler_chain_slot
+ adds r1, #1 // r1 points to `inst3` field of slot struct. Set Thumb bit on r1,
+ mov lr, r1 // and copy to lr, so `inst3` is executed on return from handler
+ bx r0 // Enter handler
+
irq_handler_chain_remove_tail:
- mov r0, lr
- subs r0, #9
+ mov r0, lr // Get start of struct. This function was called by a bl at offset +4,
+ subs r0, #9 // so lr points to offset +8. Note also lr has its Thumb bit set!
ldr r1, =irq_add_tail_to_free_list
blx r1
- pop {pc}
+ pop {pc} // Top of stack is EXC_RETURN
#endif
diff --git a/src/rp2_common/hardware_pio/include/hardware/pio.h b/src/rp2_common/hardware_pio/include/hardware/pio.h
index d2377ac..e42c60f 100644
--- a/src/rp2_common/hardware_pio/include/hardware/pio.h
+++ b/src/rp2_common/hardware_pio/include/hardware/pio.h
@@ -73,20 +73,16 @@
* e.g. pio_gpio_init(pio0, 5)
*
* \ingroup hardware_pio
- * @{
*/
#define pio0 pio0_hw
-/** @} */
/** Identifier for the second (PIO 1) hardware PIO instance (for use in PIO functions).
*
* e.g. pio_gpio_init(pio1, 5)
*
* \ingroup hardware_pio
- * @{
*/
#define pio1 pio1_hw
-/** @} */
/** \brief PIO state machine configuration
* \defgroup sm_config sm_config
@@ -99,6 +95,9 @@
/** \brief PIO Configuration structure
* \ingroup sm_config
+ *
+ * This structure is an in-memory representation of the configuration that can be applied to a PIO
+ * state machine later using pio_sm_set_config() or pio_sm_init().
*/
typedef struct {
uint32_t clkdiv;
@@ -157,7 +156,7 @@
/*! \brief Set the 'in' pins in a state machine configuration
* \ingroup sm_config
*
- * Can overlap with the 'out', ''set' and 'sideset' pins
+ * Can overlap with the 'out', 'set' and 'sideset' pins
*
* \param c Pointer to the configuration structure to modify
* \param in_base 0-31 First pin to use as input
@@ -215,6 +214,7 @@
* \sa sm_config_set_clkdiv()
*/
static inline void sm_config_set_clkdiv_int_frac(pio_sm_config *c, uint16_t div_int, uint8_t div_frac) {
+ invalid_params_if(PIO, div_int == 0 && div_frac != 0);
c->clkdiv =
(((uint)div_frac) << PIO_SM0_CLKDIV_FRAC_LSB) |
(((uint)div_int) << PIO_SM0_CLKDIV_INT_LSB);
@@ -374,8 +374,8 @@
* Side Set Pins (base) | 0
* Side Set | disabled
* Wrap | wrap=31, wrap_to=0
- * In Shift | shift_direction=right, autopush=false, push_thrshold=32
- * Out Shift | shift_direction=right, autopull=false, pull_thrshold=32
+ * In Shift | shift_direction=right, autopush=false, push_threshold=32
+ * Out Shift | shift_direction=right, autopull=false, pull_threshold=32
* Jmp Pin | 0
* Out Special | sticky=false, has_enable_pin=false, enable_pin_index=0
* Mov Status | status_sel=STATUS_TX_LESSTHAN, n=0
@@ -790,9 +790,9 @@
static inline void pio_set_irqn_source_mask_enabled(PIO pio, uint irq_index, uint32_t source_mask, bool enabled) {
invalid_params_if(PIO, irq_index > 1);
if (irq_index) {
- pio_set_irq0_source_mask_enabled(pio, source_mask, enabled);
- } else {
pio_set_irq1_source_mask_enabled(pio, source_mask, enabled);
+ } else {
+ pio_set_irq0_source_mask_enabled(pio, source_mask, enabled);
}
}
@@ -905,7 +905,7 @@
}
/*! \brief Set the current 'out' pins for a state machine
- * \ingroup sm_config
+ * \ingroup hardware_pio
*
* Can overlap with the 'in', 'set' and 'sideset' pins
*
@@ -926,7 +926,7 @@
/*! \brief Set the current 'set' pins for a state machine
- * \ingroup sm_config
+ * \ingroup hardware_pio
*
* Can overlap with the 'in', 'out' and 'sideset' pins
*
@@ -946,9 +946,9 @@
}
/*! \brief Set the current 'in' pins for a state machine
- * \ingroup sm_config
+ * \ingroup hardware_pio
*
- * Can overlap with the 'out', ''set' and 'sideset' pins
+ * Can overlap with the 'out', 'set' and 'sideset' pins
*
* \param pio The PIO instance; either \ref pio0 or \ref pio1
* \param sm State machine index (0..3)
@@ -963,7 +963,7 @@
}
/*! \brief Set the current 'sideset' pins for a state machine
- * \ingroup sm_config
+ * \ingroup hardware_pio
*
* Can overlap with the 'in', 'out' and 'set' pins
*
@@ -1155,6 +1155,7 @@
static inline void pio_sm_set_clkdiv_int_frac(PIO pio, uint sm, uint16_t div_int, uint8_t div_frac) {
check_pio_param(pio);
check_sm_param(sm);
+ invalid_params_if(PIO, div_int == 0 && div_frac != 0);
pio->sm[sm].clkdiv =
(((uint)div_frac) << PIO_SM0_CLKDIV_FRAC_LSB) |
(((uint)div_int) << PIO_SM0_CLKDIV_INT_LSB);
diff --git a/src/rp2_common/hardware_pll/include/hardware/pll.h b/src/rp2_common/hardware_pll/include/hardware/pll.h
index ee0c3ae..0466504 100644
--- a/src/rp2_common/hardware_pll/include/hardware/pll.h
+++ b/src/rp2_common/hardware_pll/include/hardware/pll.h
@@ -31,6 +31,14 @@
#define pll_sys pll_sys_hw
#define pll_usb pll_usb_hw
+#ifndef PICO_PLL_VCO_MIN_FREQ_MHZ
+#define PICO_PLL_VCO_MIN_FREQ_MHZ 750
+#endif
+
+#ifndef PICO_PLL_VCO_MAX_FREQ_MHZ
+#define PICO_PLL_VCO_MAX_FREQ_MHZ 1600
+#endif
+
/*! \brief Initialise specified PLL.
* \ingroup hardware_pll
* \param pll pll_sys or pll_usb
diff --git a/src/rp2_common/hardware_pll/pll.c b/src/rp2_common/hardware_pll/pll.c
index 6cc6184..e152b84 100644
--- a/src/rp2_common/hardware_pll/pll.c
+++ b/src/rp2_common/hardware_pll/pll.c
@@ -13,6 +13,9 @@
void pll_init(PLL pll, uint refdiv, uint vco_freq, uint post_div1, uint post_div2) {
uint32_t ref_mhz = XOSC_MHZ / refdiv;
+ // Check vco freq is in an acceptable range
+ assert(vco_freq >= (PICO_PLL_VCO_MIN_FREQ_MHZ * MHZ) && vco_freq <= (PICO_PLL_VCO_MAX_FREQ_MHZ * MHZ));
+
// What are we multiplying the reference clock by to get the vco freq
// (The regs are called div, because you divide the vco output and compare it to the refclk)
uint32_t fbdiv = vco_freq / (ref_mhz * MHZ);
@@ -41,7 +44,7 @@
if ((pll->cs & PLL_CS_LOCK_BITS) &&
(refdiv == (pll->cs & PLL_CS_REFDIV_BITS)) &&
(fbdiv == (pll->fbdiv_int & PLL_FBDIV_INT_BITS)) &&
- (pdiv == (pll->prim & (PLL_PRIM_POSTDIV1_BITS & PLL_PRIM_POSTDIV2_BITS)))) {
+ (pdiv == (pll->prim & (PLL_PRIM_POSTDIV1_BITS | PLL_PRIM_POSTDIV2_BITS)))) {
// do not disrupt PLL that is already correctly configured and operating
return;
}
diff --git a/src/rp2_common/hardware_pwm/include/hardware/pwm.h b/src/rp2_common/hardware_pwm/include/hardware/pwm.h
index 634375e..839b8f0 100644
--- a/src/rp2_common/hardware_pwm/include/hardware/pwm.h
+++ b/src/rp2_common/hardware_pwm/include/hardware/pwm.h
@@ -106,7 +106,7 @@
| (bool_to_bit(phase_correct) << PWM_CH0_CSR_PH_CORRECT_LSB);
}
-/** \brief Set clock divider in a PWM configuration
+/** \brief Set PWM clock divider in a PWM configuration
* \ingroup hardware_pwm
*
* \param c PWM configuration struct to modify
@@ -117,9 +117,27 @@
* before passing them on to the PWM counter.
*/
static inline void pwm_config_set_clkdiv(pwm_config *c, float div) {
+ valid_params_if(PWM, div >= 1.f && div < 256.f);
c->div = (uint32_t)(div * (float)(1u << PWM_CH0_DIV_INT_LSB));
}
+/** \brief Set PWM clock divider in a PWM configuration using an 8:4 fractional value
+ * \ingroup hardware_pwm
+ *
+ * \param c PWM configuration struct to modify
+ * \param integer 8 bit integer part of the clock divider. Must be greater than or equal to 1.
+ * \param fract 4 bit fractional part of the clock divider
+ *
+ * If the divide mode is free-running, the PWM counter runs at clk_sys / div.
+ * Otherwise, the divider reduces the rate of events seen on the B pin input (level or edge)
+ * before passing them on to the PWM counter.
+ */
+static inline void pwm_config_set_clkdiv_int_frac(pwm_config *c, uint8_t integer, uint8_t fract) {
+ valid_params_if(PWM, integer >= 1);
+ valid_params_if(PWM, fract < 16);
+ c->div = (((uint)integer) << PWM_CH0_DIV_INT_LSB) | (((uint)fract) << PWM_CH0_DIV_FRAC_LSB);
+}
+
/** \brief Set PWM clock divider in a PWM configuration
* \ingroup hardware_pwm
*
@@ -131,7 +149,8 @@
* before passing them on to the PWM counter.
*/
static inline void pwm_config_set_clkdiv_int(pwm_config *c, uint div) {
- c->div = div << PWM_CH0_DIV_INT_LSB;
+ valid_params_if(PWM, div >= 1 && div < 256);
+ pwm_config_set_clkdiv_int_frac(c, (uint8_t)div, 0);
}
/** \brief Set PWM counting mode in a PWM configuration
@@ -376,6 +395,7 @@
*/
static inline void pwm_set_clkdiv_int_frac(uint slice_num, uint8_t integer, uint8_t fract) {
check_slice_num_param(slice_num);
+ valid_params_if(PWM, integer >= 1);
valid_params_if(PWM, fract < 16);
pwm_hw->slice[slice_num].div = (((uint)integer) << PWM_CH0_DIV_INT_LSB) | (((uint)fract) << PWM_CH0_DIV_FRAC_LSB);
}
diff --git a/src/rp2_common/hardware_rtc/include/hardware/rtc.h b/src/rp2_common/hardware_rtc/include/hardware/rtc.h
index 8757e36..2a72a8e 100644
--- a/src/rp2_common/hardware_rtc/include/hardware/rtc.h
+++ b/src/rp2_common/hardware_rtc/include/hardware/rtc.h
@@ -47,6 +47,10 @@
/*! \brief Set the RTC to the specified time
* \ingroup hardware_rtc
*
+ * \note Note that after setting the RTC date and time, a subsequent read of the values (e.g. via rtc_get_datetime()) may not
+ * reflect the new setting until up to three cycles of the potentially-much-slower RTC clock domain have passed. This represents a period
+ * of 64 microseconds with the default RTC clock configuration.
+ *
* \param t Pointer to a \ref datetime_t structure contains time to set
* \return true if set, false if the passed in datetime was invalid.
*/
diff --git a/src/rp2_common/hardware_rtc/rtc.c b/src/rp2_common/hardware_rtc/rtc.c
index 5429acd..be9250f 100644
--- a/src/rp2_common/hardware_rtc/rtc.c
+++ b/src/rp2_common/hardware_rtc/rtc.c
@@ -65,13 +65,13 @@
}
// Write to setup registers
- rtc_hw->setup_0 = (((uint)t->year) << RTC_SETUP_0_YEAR_LSB ) |
- (((uint)t->month) << RTC_SETUP_0_MONTH_LSB) |
- (((uint)t->day) << RTC_SETUP_0_DAY_LSB);
- rtc_hw->setup_1 = (((uint)t->dotw) << RTC_SETUP_1_DOTW_LSB) |
- (((uint)t->hour) << RTC_SETUP_1_HOUR_LSB) |
- (((uint)t->min) << RTC_SETUP_1_MIN_LSB) |
- (((uint)t->sec) << RTC_SETUP_1_SEC_LSB);
+ rtc_hw->setup_0 = (((uint32_t)t->year) << RTC_SETUP_0_YEAR_LSB ) |
+ (((uint32_t)t->month) << RTC_SETUP_0_MONTH_LSB) |
+ (((uint32_t)t->day) << RTC_SETUP_0_DAY_LSB);
+ rtc_hw->setup_1 = (((uint32_t)t->dotw) << RTC_SETUP_1_DOTW_LSB) |
+ (((uint32_t)t->hour) << RTC_SETUP_1_HOUR_LSB) |
+ (((uint32_t)t->min) << RTC_SETUP_1_MIN_LSB) |
+ (((uint32_t)t->sec) << RTC_SETUP_1_SEC_LSB);
// Load setup values into rtc clock domain
rtc_hw->ctrl = RTC_CTRL_LOAD_BITS;
@@ -95,13 +95,13 @@
uint32_t rtc_0 = rtc_hw->rtc_0;
uint32_t rtc_1 = rtc_hw->rtc_1;
- t->dotw = (rtc_0 & RTC_RTC_0_DOTW_BITS ) >> RTC_RTC_0_DOTW_LSB;
- t->hour = (rtc_0 & RTC_RTC_0_HOUR_BITS ) >> RTC_RTC_0_HOUR_LSB;
- t->min = (rtc_0 & RTC_RTC_0_MIN_BITS ) >> RTC_RTC_0_MIN_LSB;
- t->sec = (rtc_0 & RTC_RTC_0_SEC_BITS ) >> RTC_RTC_0_SEC_LSB;
- t->year = (rtc_1 & RTC_RTC_1_YEAR_BITS ) >> RTC_RTC_1_YEAR_LSB;
- t->month = (rtc_1 & RTC_RTC_1_MONTH_BITS) >> RTC_RTC_1_MONTH_LSB;
- t->day = (rtc_1 & RTC_RTC_1_DAY_BITS ) >> RTC_RTC_1_DAY_LSB;
+ t->dotw = (int8_t) ((rtc_0 & RTC_RTC_0_DOTW_BITS ) >> RTC_RTC_0_DOTW_LSB);
+ t->hour = (int8_t) ((rtc_0 & RTC_RTC_0_HOUR_BITS ) >> RTC_RTC_0_HOUR_LSB);
+ t->min = (int8_t) ((rtc_0 & RTC_RTC_0_MIN_BITS ) >> RTC_RTC_0_MIN_LSB);
+ t->sec = (int8_t) ((rtc_0 & RTC_RTC_0_SEC_BITS ) >> RTC_RTC_0_SEC_LSB);
+ t->year = (int16_t) ((rtc_1 & RTC_RTC_1_YEAR_BITS ) >> RTC_RTC_1_YEAR_LSB);
+ t->month = (int8_t) ((rtc_1 & RTC_RTC_1_MONTH_BITS) >> RTC_RTC_1_MONTH_LSB);
+ t->day = (int8_t) ((rtc_1 & RTC_RTC_1_DAY_BITS ) >> RTC_RTC_1_DAY_LSB);
return true;
}
@@ -148,13 +148,13 @@
rtc_disable_alarm();
// Only add to setup if it isn't -1
- rtc_hw->irq_setup_0 = ((t->year < 0) ? 0 : (((uint)t->year) << RTC_IRQ_SETUP_0_YEAR_LSB )) |
- ((t->month < 0) ? 0 : (((uint)t->month) << RTC_IRQ_SETUP_0_MONTH_LSB)) |
- ((t->day < 0) ? 0 : (((uint)t->day) << RTC_IRQ_SETUP_0_DAY_LSB ));
- rtc_hw->irq_setup_1 = ((t->dotw < 0) ? 0 : (((uint)t->dotw) << RTC_IRQ_SETUP_1_DOTW_LSB)) |
- ((t->hour < 0) ? 0 : (((uint)t->hour) << RTC_IRQ_SETUP_1_HOUR_LSB)) |
- ((t->min < 0) ? 0 : (((uint)t->min) << RTC_IRQ_SETUP_1_MIN_LSB )) |
- ((t->sec < 0) ? 0 : (((uint)t->sec) << RTC_IRQ_SETUP_1_SEC_LSB ));
+ rtc_hw->irq_setup_0 = ((t->year < 0) ? 0 : (((uint32_t)t->year) << RTC_IRQ_SETUP_0_YEAR_LSB )) |
+ ((t->month < 0) ? 0 : (((uint32_t)t->month) << RTC_IRQ_SETUP_0_MONTH_LSB)) |
+ ((t->day < 0) ? 0 : (((uint32_t)t->day) << RTC_IRQ_SETUP_0_DAY_LSB ));
+ rtc_hw->irq_setup_1 = ((t->dotw < 0) ? 0 : (((uint32_t)t->dotw) << RTC_IRQ_SETUP_1_DOTW_LSB)) |
+ ((t->hour < 0) ? 0 : (((uint32_t)t->hour) << RTC_IRQ_SETUP_1_HOUR_LSB)) |
+ ((t->min < 0) ? 0 : (((uint32_t)t->min) << RTC_IRQ_SETUP_1_MIN_LSB )) |
+ ((t->sec < 0) ? 0 : (((uint32_t)t->sec) << RTC_IRQ_SETUP_1_SEC_LSB ));
// Set the match enable bits for things we care about
if (t->year >= 0) hw_set_bits(&rtc_hw->irq_setup_0, RTC_IRQ_SETUP_0_YEAR_ENA_BITS);
diff --git a/src/rp2_common/hardware_spi/include/hardware/spi.h b/src/rp2_common/hardware_spi/include/hardware/spi.h
index e8dc952..8e27533 100644
--- a/src/rp2_common/hardware_spi/include/hardware/spi.h
+++ b/src/rp2_common/hardware_spi/include/hardware/spi.h
@@ -53,7 +53,7 @@
*
* \ingroup hardware_spi
*/
-#define spi0 ((spi_inst_t * const)spi0_hw)
+#define spi0 ((spi_inst_t *)spi0_hw)
/** Identifier for the second (SPI 1) hardware SPI instance (for use in SPI functions).
*
@@ -61,7 +61,7 @@
*
* \ingroup hardware_spi
*/
-#define spi1 ((spi_inst_t * const)spi1_hw)
+#define spi1 ((spi_inst_t *)spi1_hw)
#if !defined(PICO_DEFAULT_SPI_INSTANCE) && defined(PICO_DEFAULT_SPI)
#define PICO_DEFAULT_SPI_INSTANCE (__CONCAT(spi,PICO_DEFAULT_SPI))
diff --git a/src/rp2_common/hardware_sync/include/hardware/sync.h b/src/rp2_common/hardware_sync/include/hardware/sync.h
index 8f91d55..eee675e 100644
--- a/src/rp2_common/hardware_sync/include/hardware/sync.h
+++ b/src/rp2_common/hardware_sync/include/hardware/sync.h
@@ -304,15 +304,6 @@
restore_interrupts(saved_irq);
}
-/*! \brief Get the current core number
- * \ingroup hardware_sync
- *
- * \return The core number the call was made from
- */
-__force_inline static uint get_core_num(void) {
- return (*(uint32_t *) (SIO_BASE + SIO_CPUID_OFFSET));
-}
-
/*! \brief Initialise a spin lock
* \ingroup hardware_sync
*
diff --git a/src/rp2_common/hardware_uart/include/hardware/uart.h b/src/rp2_common/hardware_uart/include/hardware/uart.h
index bce0d2f..0309e59 100644
--- a/src/rp2_common/hardware_uart/include/hardware/uart.h
+++ b/src/rp2_common/hardware_uart/include/hardware/uart.h
@@ -78,8 +78,8 @@
* \ingroup hardware_uart
* @{
*/
-#define uart0 ((uart_inst_t * const)uart0_hw) ///< Identifier for UART instance 0
-#define uart1 ((uart_inst_t * const)uart1_hw) ///< Identifier for UART instance 1
+#define uart0 ((uart_inst_t *)uart0_hw) ///< Identifier for UART instance 0
+#define uart1 ((uart_inst_t *)uart1_hw) ///< Identifier for UART instance 1
/** @} */
diff --git a/src/rp2_common/hardware_watchdog/include/hardware/watchdog.h b/src/rp2_common/hardware_watchdog/include/hardware/watchdog.h
index 747838b..7ce89ff 100644
--- a/src/rp2_common/hardware_watchdog/include/hardware/watchdog.h
+++ b/src/rp2_common/hardware_watchdog/include/hardware/watchdog.h
@@ -97,7 +97,7 @@
* This would not be present if a watchdog reset is initiated by \ref watchdog_reboot or by the RP2040 bootrom
* (e.g. dragging a UF2 onto the RPI-RP2 drive).
*
- * @return true If the watchdog timer or a watchdog force caused (see \reg watchdog_caused_reboot) the last reboot
+ * @return true If the watchdog timer or a watchdog force caused (see \ref watchdog_caused_reboot) the last reboot
* and the watchdog reboot happened after \ref watchdog_enable was called
* @return false If there has been no watchdog reboot since the last power on reset, or the watchdog reboot was not caused
* by a watchdog timeout after \ref watchdog_enable was called.
diff --git a/src/rp2_common/pico_bit_ops/bit_ops_aeabi.S b/src/rp2_common/pico_bit_ops/bit_ops_aeabi.S
index eba839e..7b83edb 100644
--- a/src/rp2_common/pico_bit_ops/bit_ops_aeabi.S
+++ b/src/rp2_common/pico_bit_ops/bit_ops_aeabi.S
@@ -85,7 +85,7 @@
ldr r3, =aeabi_bits_funcs
ldr r3, [r3, #CTZ32]
cmp r0, #0
- bne 1f
+ beq 1f
bx r3
1:
push {lr}
diff --git a/src/rp2_common/pico_bootrom/bootrom.c b/src/rp2_common/pico_bootrom/bootrom.c
index af7d091..5def61a 100644
--- a/src/rp2_common/pico_bootrom/bootrom.c
+++ b/src/rp2_common/pico_bootrom/bootrom.c
@@ -12,9 +12,6 @@
// Returns the 32 bit pointer into the ROM if found or NULL otherwise.
typedef void *(*rom_table_lookup_fn)(uint16_t *table, uint32_t code);
-// Convert a 16 bit pointer stored at the given rom address into a 32 bit pointer
-#define rom_hword_as_ptr(rom_address) (void *)(uintptr_t)(*(uint16_t *)rom_address)
-
void *rom_func_lookup(uint32_t code) {
return rom_func_lookup_inline(code);
}
diff --git a/src/rp2_common/pico_bootrom/include/pico/bootrom.h b/src/rp2_common/pico_bootrom/include/pico/bootrom.h
index e557893..4484568 100644
--- a/src/rp2_common/pico_bootrom/include/pico/bootrom.h
+++ b/src/rp2_common/pico_bootrom/include/pico/bootrom.h
@@ -116,8 +116,18 @@
// Returns the 32 bit pointer into the ROM if found or NULL otherwise.
typedef void *(*rom_table_lookup_fn)(uint16_t *table, uint32_t code);
+#if defined(__GNUC__) && (__GNUC__ >= 12)
// Convert a 16 bit pointer stored at the given rom address into a 32 bit pointer
-#define rom_hword_as_ptr(rom_address) (void *)(uintptr_t)(*(uint16_t *)rom_address)
+static inline void *rom_hword_as_ptr(uint16_t rom_address) {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warray-bounds"
+ return (void *)(uintptr_t)*(uint16_t *)(uintptr_t)rom_address;
+#pragma GCC diagnostic pop
+}
+#else
+// Convert a 16 bit pointer stored at the given rom address into a 32 bit pointer
+#define rom_hword_as_ptr(rom_address) (void *)(uintptr_t)(*(uint16_t *)(uintptr_t)(rom_address))
+#endif
/*!
* \brief Lookup a bootrom function by code. This method is forceably inlined into the caller for FLASH/RAM sensitive code usage
diff --git a/src/rp2_common/pico_cyw43_arch/CMakeLists.txt b/src/rp2_common/pico_cyw43_arch/CMakeLists.txt
new file mode 100644
index 0000000..ede03f1
--- /dev/null
+++ b/src/rp2_common/pico_cyw43_arch/CMakeLists.txt
@@ -0,0 +1,66 @@
+if (PICO_CYW43_SUPPORTED) # set by BOARD=pico-w
+ if (TARGET cyw43_driver_picow)
+ message("Enabling build support for Pico W wireless.")
+
+ pico_add_impl_library(pico_cyw43_arch)
+ target_sources(pico_cyw43_arch INTERFACE
+ ${CMAKE_CURRENT_LIST_DIR}/cyw43_arch.c
+ ${CMAKE_CURRENT_LIST_DIR}/cyw43_arch_poll.c
+ ${CMAKE_CURRENT_LIST_DIR}/cyw43_arch_threadsafe_background.c
+ ${CMAKE_CURRENT_LIST_DIR}/cyw43_arch_freertos.c
+ )
+
+ target_include_directories(pico_cyw43_arch INTERFACE
+ ${CMAKE_CURRENT_LIST_DIR}/include)
+
+ target_link_libraries(pico_cyw43_arch INTERFACE
+ pico_unique_id
+ cyw43_driver_picow)
+
+ if (NOT TARGET pico_lwip)
+ message(WARNING "lwIP is not available; Full Pico W wireless support will be unavailable too")
+ else()
+ add_library(pico_cyw43_arch_lwip_poll INTERFACE)
+ target_link_libraries(pico_cyw43_arch_lwip_poll INTERFACE
+ pico_cyw43_arch
+ pico_lwip
+ pico_lwip_nosys)
+ target_compile_definitions(pico_cyw43_arch_lwip_poll INTERFACE
+ CYW43_LWIP=1
+ PICO_CYW43_ARCH_POLL=1
+ )
+
+ add_library(pico_cyw43_arch_lwip_threadsafe_background INTERFACE)
+ target_link_libraries(pico_cyw43_arch_lwip_threadsafe_background INTERFACE
+ pico_cyw43_arch
+ pico_lwip
+ pico_lwip_nosys)
+ target_compile_definitions(pico_cyw43_arch_lwip_threadsafe_background INTERFACE
+ CYW43_LWIP=1
+ PICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1
+ )
+
+ add_library(pico_cyw43_arch_lwip_sys_freertos INTERFACE)
+ target_link_libraries(pico_cyw43_arch_lwip_sys_freertos INTERFACE
+ pico_cyw43_arch
+ pico_lwip
+ pico_lwip_contrib_freertos)
+ target_compile_definitions(pico_cyw43_arch_lwip_sys_freertos INTERFACE
+ CYW43_LWIP=1
+ LWIP_PROVIDE_ERRNO=1
+ PICO_CYW43_ARCH_FREERTOS=1
+ )
+ endif()
+
+ add_library(pico_cyw43_arch_none INTERFACE)
+ target_link_libraries(pico_cyw43_arch_none INTERFACE pico_cyw43_arch)
+ target_compile_definitions(pico_cyw43_arch_none INTERFACE
+ CYW43_LWIP=0
+ PICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1 # none still uses threadsafe_background to make gpio use easy
+ )
+ endif()
+endif()
+
+if (PICO_CYW43_DRIVER_PATH AND EXISTS "${PICO_CYW43_DRIVER_PATH}")
+ pico_add_doxygen(${PICO_CYW43_DRIVER_PATH}/src)
+endif()
\ No newline at end of file
diff --git a/src/rp2_common/pico_cyw43_arch/cyw43_arch.c b/src/rp2_common/pico_cyw43_arch/cyw43_arch.c
new file mode 100644
index 0000000..c328d6e
--- /dev/null
+++ b/src/rp2_common/pico_cyw43_arch/cyw43_arch.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "pico/unique_id.h"
+#include "cyw43.h"
+#include "pico/cyw43_arch.h"
+#include "cyw43_ll.h"
+#include "cyw43_stats.h"
+
+#if CYW43_ARCH_DEBUG_ENABLED
+#define CYW43_ARCH_DEBUG(...) printf(__VA_ARGS__)
+#else
+#define CYW43_ARCH_DEBUG(...) ((void)0)
+#endif
+
+static uint32_t country_code = PICO_CYW43_ARCH_DEFAULT_COUNTRY_CODE;
+
+void cyw43_arch_enable_sta_mode() {
+ assert(cyw43_is_initialized(&cyw43_state));
+ cyw43_wifi_set_up(&cyw43_state, CYW43_ITF_STA, true, cyw43_arch_get_country_code());
+}
+
+void cyw43_arch_enable_ap_mode(const char *ssid, const char *password, uint32_t auth) {
+ assert(cyw43_is_initialized(&cyw43_state));
+ cyw43_wifi_ap_set_ssid(&cyw43_state, strlen(ssid), (const uint8_t *) ssid);
+ if (password) {
+ cyw43_wifi_ap_set_password(&cyw43_state, strlen(password), (const uint8_t *) password);
+ cyw43_wifi_ap_set_auth(&cyw43_state, auth);
+ } else {
+ cyw43_wifi_ap_set_auth(&cyw43_state, CYW43_AUTH_OPEN);
+ }
+ cyw43_wifi_set_up(&cyw43_state, CYW43_ITF_AP, true, cyw43_arch_get_country_code());
+}
+
+#if CYW43_ARCH_DEBUG_ENABLED
+// Return a string for the wireless state
+static const char* status_name(int status)
+{
+ switch (status) {
+ case CYW43_LINK_DOWN:
+ return "link down";
+ case CYW43_LINK_JOIN:
+ return "joining";
+ case CYW43_LINK_NOIP:
+ return "no ip";
+ case CYW43_LINK_UP:
+ return "link up";
+ case CYW43_LINK_FAIL:
+ return "link fail";
+ case CYW43_LINK_NONET:
+ return "network fail";
+ case CYW43_LINK_BADAUTH:
+ return "bad auth";
+ }
+ return "unknown";
+}
+#endif
+
+int cyw43_arch_wifi_connect_async(const char *ssid, const char *pw, uint32_t auth) {
+ if (!pw) auth = CYW43_AUTH_OPEN;
+ // Connect to wireless
+ return cyw43_wifi_join(&cyw43_state, strlen(ssid), (const uint8_t *)ssid, pw ? strlen(pw) : 0, (const uint8_t *)pw, auth, NULL, CYW43_ITF_STA);
+}
+
+// Connect to wireless, return with success when an IP address has been assigned
+int cyw43_arch_wifi_connect_until(const char *ssid, const char *pw, uint32_t auth, absolute_time_t until) {
+ int err = cyw43_arch_wifi_connect_async(ssid, pw, auth);
+ if (err) return err;
+
+ int status = CYW43_LINK_UP + 1;
+ while(status >= 0 && status != CYW43_LINK_UP) {
+ int new_status = cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA);
+ if (new_status != status) {
+ status = new_status;
+ CYW43_ARCH_DEBUG("connect status: %s\n", status_name(status));
+ }
+ // in case polling is required
+ cyw43_arch_poll();
+ best_effort_wfe_or_timeout(until);
+ if (time_reached(until)) {
+ return PICO_ERROR_TIMEOUT;
+ }
+ }
+ return status == CYW43_LINK_UP ? 0 : status;
+}
+
+int cyw43_arch_wifi_connect_blocking(const char *ssid, const char *pw, uint32_t auth) {
+ return cyw43_arch_wifi_connect_until(ssid, pw, auth, at_the_end_of_time);
+}
+
+int cyw43_arch_wifi_connect_timeout_ms(const char *ssid, const char *pw, uint32_t auth, uint32_t timeout_ms) {
+ return cyw43_arch_wifi_connect_until(ssid, pw, auth, make_timeout_time_ms(timeout_ms));
+}
+
+// todo maybe add an #ifdef in cyw43_driver
+uint32_t storage_read_blocks(__unused uint8_t *dest, __unused uint32_t block_num, __unused uint32_t num_blocks) {
+ // shouldn't be used
+ panic_unsupported();
+}
+
+// Generate a mac address if one is not set in otp
+void cyw43_hal_generate_laa_mac(__unused int idx, uint8_t buf[6]) {
+ CYW43_DEBUG("Warning. No mac in otp. Generating mac from board id\n");
+ pico_unique_board_id_t board_id;
+ pico_get_unique_board_id(&board_id);
+ memcpy(buf, &board_id.id[2], 6);
+ buf[0] &= (uint8_t)~0x1; // unicast
+ buf[0] |= 0x2; // locally administered
+}
+
+// Return mac address
+void cyw43_hal_get_mac(__unused int idx, uint8_t buf[6]) {
+ // The mac should come from cyw43 otp.
+ // This is loaded into the state after the driver is initialised
+ // cyw43_hal_generate_laa_mac is called by the driver to generate a mac if otp is not set
+ memcpy(buf, cyw43_state.mac, 6);
+}
+
+uint32_t cyw43_arch_get_country_code(void) {
+ return country_code;
+}
+
+int cyw43_arch_init_with_country(uint32_t country) {
+ country_code = country;
+ return cyw43_arch_init();
+}
+
+void cyw43_arch_gpio_put(uint wl_gpio, bool value) {
+ invalid_params_if(CYW43_ARCH, wl_gpio >= CYW43_WL_GPIO_COUNT);
+ cyw43_gpio_set(&cyw43_state, (int)wl_gpio, value);
+}
+
+bool cyw43_arch_gpio_get(uint wl_gpio) {
+ invalid_params_if(CYW43_ARCH, wl_gpio >= CYW43_WL_GPIO_COUNT);
+ bool value = false;
+ cyw43_gpio_get(&cyw43_state, (int)wl_gpio, &value);
+ return value;
+}
diff --git a/src/rp2_common/pico_cyw43_arch/cyw43_arch_freertos.c b/src/rp2_common/pico_cyw43_arch/cyw43_arch_freertos.c
new file mode 100644
index 0000000..88dde6e
--- /dev/null
+++ b/src/rp2_common/pico_cyw43_arch/cyw43_arch_freertos.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdio.h>
+
+#include "pico/cyw43_arch.h"
+
+#include "hardware/gpio.h"
+#include "hardware/irq.h"
+#include "hardware/sync.h"
+
+#include "cyw43_stats.h"
+
+#if CYW43_LWIP
+#include <lwip/tcpip.h>
+#endif
+
+#if PICO_CYW43_ARCH_FREERTOS
+
+// FreeRTOS includes
+#include "FreeRTOS.h"
+#include "timers.h"
+#include "semphr.h"
+
+#if NO_SYS
+#error example_cyw43_arch_frertos_sys requires NO_SYS=0
+#endif
+
+#ifndef CYW43_TASK_PRIORITY
+#define CYW43_TASK_PRIORITY ( tskIDLE_PRIORITY + 4)
+#endif
+
+#ifndef CYW43_SLEEP_CHECK_MS
+#define CYW43_SLEEP_CHECK_MS 50 // How often to run lwip callback
+#endif
+
+#define CYW43_GPIO_IRQ_HANDLER_PRIORITY 0x40
+
+static void signal_cyw43_task(void);
+
+#if !LWIP_TCPIP_CORE_LOCKING_INPUT
+static SemaphoreHandle_t cyw43_mutex;
+#endif
+static TimerHandle_t timer_handle;
+static TaskHandle_t cyw43_task_handle;
+static volatile bool cyw43_task_should_exit;
+static SemaphoreHandle_t cyw43_worker_ran_sem;
+static uint8_t cyw43_core_num;
+
+// Called in low priority pendsv interrupt only to do lwip processing and check cyw43 sleep
+static void periodic_worker(__unused TimerHandle_t handle)
+{
+#if CYW43_USE_STATS
+ static uint32_t counter;
+ if (counter++ % (30000 / LWIP_SYS_CHECK_MS) == 0) {
+ cyw43_dump_stats();
+ }
+#endif
+
+ CYW43_STAT_INC(LWIP_RUN_COUNT);
+ if (cyw43_poll) {
+ if (cyw43_sleep > 0) {
+ if (--cyw43_sleep == 0) {
+ signal_cyw43_task();
+ }
+ }
+ }
+}
+
+void cyw43_await_background_or_timeout_us(uint32_t timeout_us) {
+ // if we are called from within an IRQ, then don't wait (we are only ever called in a polling loop)
+ assert(!portCHECK_IF_IN_ISR());
+ xSemaphoreTake(cyw43_worker_ran_sem, pdMS_TO_TICKS(timeout_us / 1000));
+}
+
+// GPIO interrupt handler to tell us there's cyw43 has work to do
+static void gpio_irq_handler(void)
+{
+ uint32_t events = gpio_get_irq_event_mask(CYW43_PIN_WL_HOST_WAKE);
+ if (events & GPIO_IRQ_LEVEL_HIGH) {
+ // As we use a high level interrupt, it will go off forever until it's serviced
+ // So disable the interrupt until this is done. It's re-enabled again by CYW43_POST_POLL_HOOK
+ // which is called at the end of cyw43_poll_func
+ gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, false);
+ signal_cyw43_task();
+ CYW43_STAT_INC(IRQ_COUNT);
+ }
+}
+
+// Low priority interrupt handler to perform background processing
+static void cyw43_task(__unused void *param) {
+ do {
+ ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
+ if (cyw43_task_should_exit) break;
+ cyw43_thread_enter();
+ if (cyw43_poll) cyw43_poll();
+ cyw43_thread_exit();
+ xSemaphoreGive(cyw43_worker_ran_sem);
+ __sev(); // it is possible regular code is waiting on a WFE on the other core
+ } while (true);
+}
+
+static void tcpip_init_done(void *param) {
+ xSemaphoreGive((SemaphoreHandle_t)param);
+}
+
+int cyw43_arch_init(void) {
+ cyw43_core_num = get_core_num();
+#if configUSE_CORE_AFFINITY && configNUM_CORES > 1
+ TaskHandle_t task_handle = xTaskGetCurrentTaskHandle();
+ UBaseType_t affinity = vTaskCoreAffinityGet(task_handle);
+ // we must bind the main task to one core during init
+ vTaskCoreAffinitySet(task_handle, 1 << portGET_CORE_ID());
+#endif
+#if !LWIP_TCPIP_CORE_LOCKING_INPUT
+ cyw43_mutex = xSemaphoreCreateRecursiveMutex();
+#endif
+ cyw43_init(&cyw43_state);
+ cyw43_worker_ran_sem = xSemaphoreCreateBinary();
+
+#if CYW43_LWIP
+ SemaphoreHandle_t init_sem = xSemaphoreCreateBinary();
+ tcpip_init(tcpip_init_done, init_sem);
+ xSemaphoreTake(init_sem, portMAX_DELAY);
+#endif
+
+ timer_handle = xTimerCreate( "cyw43_sleep_timer", // Just a text name, not used by the kernel.
+ pdMS_TO_TICKS(CYW43_SLEEP_CHECK_MS),
+ pdTRUE, // The timers will auto-reload themselves when they expire.
+ NULL,
+ periodic_worker);
+
+ if (!timer_handle) {
+ return PICO_ERROR_GENERIC;
+ }
+
+ gpio_add_raw_irq_handler_with_order_priority(IO_IRQ_BANK0, gpio_irq_handler, CYW43_GPIO_IRQ_HANDLER_PRIORITY);
+ gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, true);
+ irq_set_enabled(IO_IRQ_BANK0, true);
+
+ cyw43_task_should_exit = false;
+ xTaskCreate(cyw43_task, "CYW43 Worker", configMINIMAL_STACK_SIZE, NULL, CYW43_TASK_PRIORITY, &cyw43_task_handle);
+#if configUSE_CORE_AFFINITY && configNUM_CORES > 1
+ // the cyw43 task mus tbe on the same core so it can restore IRQs
+ vTaskCoreAffinitySet(cyw43_task_handle, 1 << portGET_CORE_ID());
+#endif
+
+#if configUSE_CORE_AFFINITY && configNUM_CORES > 1
+ vTaskCoreAffinitySet(task_handle, affinity);
+#endif
+
+ return PICO_OK;
+}
+
+void cyw43_arch_deinit(void) {
+ assert(cyw43_core_num == get_core_num());
+ if (timer_handle) {
+ xTimerDelete(timer_handle, 0);
+ timer_handle = 0;
+ }
+ if (cyw43_task_handle) {
+ cyw43_task_should_exit = true;
+ signal_cyw43_task();
+ }
+ gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, false);
+ gpio_remove_raw_irq_handler(IO_IRQ_BANK0, gpio_irq_handler);
+}
+
+void cyw43_post_poll_hook(void) {
+ assert(cyw43_core_num == get_core_num());
+ gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, true);
+}
+
+// This is called in the gpio and low_prio_irq interrupts and on either core
+static void signal_cyw43_task(void) {
+ if (cyw43_task_handle) {
+ if (portCHECK_IF_IN_ISR()) {
+ vTaskNotifyGiveFromISR(cyw43_task_handle, NULL);
+ } else {
+ xTaskNotifyGive(cyw43_task_handle);
+ }
+ }
+}
+
+void cyw43_schedule_internal_poll_dispatch(void (*func)(void)) {
+ assert(func == cyw43_poll);
+ signal_cyw43_task();
+}
+
+static int nesting;
+// Prevent background processing in pensv and access by the other core
+// These methods are called in pensv context and on either core
+// They can be called recursively
+void cyw43_thread_enter(void) {
+ // Lock the other core and stop low_prio_irq running
+ assert(!portCHECK_IF_IN_ISR());
+#if LWIP_TCPIP_CORE_LOCKING_INPUT
+ // we must share their mutex otherwise we can get deadlocks with two different recursive mutexes
+ LOCK_TCPIP_CORE();
+#else
+ xSemaphoreTakeRecursive(cyw43_mutex, portMAX_DELAY);
+#endif
+ nesting++;
+}
+
+#ifndef NDEBUG
+void cyw43_thread_lock_check(void) {
+ // Lock the other core and stop low_prio_irq running
+#if LWIP_TCPIP_CORE_LOCKING_INPUT
+ assert(xSemaphoreGetMutexHolder(lock_tcpip_core.mut) == xTaskGetCurrentTaskHandle());
+#else
+ assert(xSemaphoreGetMutexHolder(cyw43_mutex) == xTaskGetCurrentTaskHandle());
+#endif
+}
+#endif
+
+// Re-enable background processing
+void cyw43_thread_exit(void) {
+ // Run low_prio_irq if needed
+ --nesting;
+#if LWIP_TCPIP_CORE_LOCKING_INPUT
+ // we must share their mutex otherwise we can get deadlocks with two different recursive mutexes
+ UNLOCK_TCPIP_CORE();
+#else
+ xSemaphoreGiveRecursive(cyw43_mutex);
+#endif
+
+ if (!nesting && cyw43_task_handle != xTaskGetCurrentTaskHandle())
+ signal_cyw43_task();
+}
+
+void cyw43_delay_ms(uint32_t ms) {
+ assert(!portCHECK_IF_IN_ISR());
+ vTaskDelay(pdMS_TO_TICKS(ms));
+}
+
+void cyw43_delay_us(uint32_t us) {
+ if (us >= 1000) {
+ cyw43_delay_ms(us / 1000);
+ } else {
+ vTaskDelay(1);
+ }
+}
+
+void cyw43_arch_poll() {
+}
+
+#endif
\ No newline at end of file
diff --git a/src/rp2_common/pico_cyw43_arch/cyw43_arch_poll.c b/src/rp2_common/pico_cyw43_arch/cyw43_arch_poll.c
new file mode 100644
index 0000000..e71f86a
--- /dev/null
+++ b/src/rp2_common/pico_cyw43_arch/cyw43_arch_poll.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdio.h>
+#include "hardware/gpio.h"
+#include "hardware/irq.h"
+#include "pico/sem.h"
+#include "pico/cyw43_arch.h"
+#include "cyw43_stats.h"
+
+#if PICO_CYW43_ARCH_POLL
+#include <lwip/init.h>
+#include "lwip/timeouts.h"
+
+#if CYW43_LWIP && !NO_SYS
+#error PICO_CYW43_ARCH_POLL requires lwIP NO_SYS=1
+#endif
+
+#define CYW43_GPIO_IRQ_HANDLER_PRIORITY 0x40
+
+#ifndef NDEBUG
+uint8_t cyw43_core_num;
+#endif
+
+bool cyw43_poll_required;
+
+// GPIO interrupt handler to tell us there's cyw43 has work to do
+static void gpio_irq_handler(void)
+{
+ uint32_t events = gpio_get_irq_event_mask(CYW43_PIN_WL_HOST_WAKE);
+ if (events & GPIO_IRQ_LEVEL_HIGH) {
+ // As we use a high level interrupt, it will go off forever until it's serviced
+ // So disable the interrupt until this is done. It's re-enabled again by CYW43_POST_POLL_HOOK
+ // which is called at the end of cyw43_poll_func
+ gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, false);
+ // also clear the force bit which we use to programmatically cause this handler to fire (on the right core)
+ io_irq_ctrl_hw_t *irq_ctrl_base = get_core_num() ?
+ &iobank0_hw->proc1_irq_ctrl : &iobank0_hw->proc0_irq_ctrl;
+ hw_clear_bits(&irq_ctrl_base->intf[CYW43_PIN_WL_HOST_WAKE/8], GPIO_IRQ_LEVEL_HIGH << (4 * (CYW43_PIN_WL_HOST_WAKE & 7)));
+ cyw43_schedule_internal_poll_dispatch(cyw43_poll);
+ CYW43_STAT_INC(IRQ_COUNT);
+ }
+}
+
+void cyw43_post_poll_hook(void) {
+ gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, true);
+}
+
+int cyw43_arch_init(void) {
+#ifndef NDEBUG
+ cyw43_core_num = (uint8_t)get_core_num();
+#endif
+ cyw43_init(&cyw43_state);
+ static bool done_lwip_init;
+ if (!done_lwip_init) {
+ lwip_init();
+ done_lwip_init = true;
+ }
+ gpio_add_raw_irq_handler_with_order_priority(IO_IRQ_BANK0, gpio_irq_handler, CYW43_GPIO_IRQ_HANDLER_PRIORITY);
+ gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, true);
+ irq_set_enabled(IO_IRQ_BANK0, true);
+ return 0;
+}
+
+void cyw43_arch_deinit(void) {
+ gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, false);
+ gpio_remove_raw_irq_handler(IO_IRQ_BANK0, gpio_irq_handler);
+ cyw43_deinit(&cyw43_state);
+}
+
+
+void cyw43_schedule_internal_poll_dispatch(__unused void (*func)(void)) {
+ cyw43_poll_required = true;
+}
+
+void cyw43_arch_poll(void)
+{
+ CYW43_STAT_INC(LWIP_RUN_COUNT);
+ sys_check_timeouts();
+ if (cyw43_poll) {
+ if (cyw43_sleep > 0) {
+ // todo check this; but we don't want to advance too quickly
+ static absolute_time_t last_poll_time;
+ absolute_time_t current = get_absolute_time();
+ if (absolute_time_diff_us(last_poll_time, current) > 1000) {
+ if (--cyw43_sleep == 0) {
+ cyw43_poll_required = 1;
+ }
+ last_poll_time = current;
+ }
+ }
+ // todo graham i removed this because otherwise polling can do nothing during connect.
+ // in the polling only case, the caller is responsible for throttling how often they call anyway.
+ // The alternative would be to have the call to this function from the init set the poll_required flag first
+// if (cyw43_poll_required) {
+ cyw43_poll();
+// cyw43_poll_required = false;
+// }
+ }
+}
+
+#ifndef NDEBUG
+void cyw43_thread_check() {
+ if (__get_current_exception() || get_core_num() != cyw43_core_num) {
+ panic("cyw43_thread_lock_check failed");
+ }
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/src/rp2_common/pico_cyw43_arch/cyw43_arch_threadsafe_background.c b/src/rp2_common/pico_cyw43_arch/cyw43_arch_threadsafe_background.c
new file mode 100644
index 0000000..a3dde74
--- /dev/null
+++ b/src/rp2_common/pico_cyw43_arch/cyw43_arch_threadsafe_background.c
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdio.h>
+
+#include "pico/cyw43_arch.h"
+#include "pico/mutex.h"
+#include "pico/sem.h"
+
+#include "hardware/gpio.h"
+#include "hardware/irq.h"
+
+#include "cyw43_stats.h"
+
+#if CYW43_LWIP
+#include <lwip/init.h>
+#include "lwip/timeouts.h"
+#endif
+
+// note same code
+#if PICO_CYW43_ARCH_THREADSAFE_BACKGROUND
+
+#if PICO_CYW43_ARCH_THREADSAFE_BACKGROUND && CYW43_LWIP && !NO_SYS
+#error PICO_CYW43_ARCH_THREADSAFE_BACKGROUND requires lwIP NO_SYS=1
+#endif
+#if PICO_CYW43_ARCH_THREADSAFE_BACKGROUND && CYW43_LWIP && MEM_LIBC_MALLOC
+#error MEM_LIBC_MALLOC is incompatible with PICO_CYW43_ARCH_THREADSAFE_BACKGROUND
+#endif
+// todo right now we are now always doing a cyw43_dispatch along with a lwip one when hopping cores in low_prio_irq_schedule_dispatch
+
+#ifndef CYW43_SLEEP_CHECK_MS
+#define CYW43_SLEEP_CHECK_MS 50 // How often to run lwip callback
+#endif
+static alarm_id_t periodic_alarm = -1;
+
+static inline uint recursive_mutex_enter_count(recursive_mutex_t *mutex) {
+ return mutex->enter_count;
+}
+
+static inline lock_owner_id_t recursive_mutex_owner(recursive_mutex_t *mutex) {
+ return mutex->owner;
+}
+
+#define CYW43_GPIO_IRQ_HANDLER_PRIORITY 0x40
+
+enum {
+ CYW43_DISPATCH_SLOT_CYW43 = 0,
+ CYW43_DISPATCH_SLOT_ADAPTER,
+ CYW43_DISPATCH_SLOT_ENUM_COUNT
+};
+#ifndef CYW43_DISPATCH_SLOT_COUNT
+#define CYW43_DISPATCH_SLOT_COUNT CYW43_DISPATCH_SLOT_ENUM_COUNT
+#endif
+
+typedef void (*low_prio_irq_dispatch_t)(void);
+static void low_prio_irq_schedule_dispatch(size_t slot, low_prio_irq_dispatch_t f);
+
+static uint8_t cyw43_core_num;
+#ifndef NDEBUG
+static bool in_low_priority_irq;
+#endif
+static uint8_t low_priority_irq_num;
+static bool low_priority_irq_missed;
+static low_prio_irq_dispatch_t low_priority_irq_dispatch_slots[CYW43_DISPATCH_SLOT_COUNT];
+static recursive_mutex_t cyw43_mutex;
+semaphore_t cyw43_irq_sem;
+
+// Called in low priority pendsv interrupt only to do lwip processing and check cyw43 sleep
+static void periodic_worker(void)
+{
+#if CYW43_USE_STATS
+ static uint32_t counter;
+ if (counter++ % (30000 / LWIP_SYS_CHECK_MS) == 0) {
+ cyw43_dump_stats();
+ }
+#endif
+
+ CYW43_STAT_INC(LWIP_RUN_COUNT);
+#if CYW43_LWIP
+ sys_check_timeouts();
+#endif
+ if (cyw43_poll) {
+ if (cyw43_sleep > 0) {
+ if (--cyw43_sleep == 0) {
+ low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_CYW43, cyw43_poll);
+ }
+ }
+ }
+}
+
+// Regular callback to get lwip to check for timeouts
+static int64_t periodic_alarm_handler(__unused alarm_id_t id, __unused void *user_data)
+{
+ // Do lwip processing in low priority pendsv interrupt
+ low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_ADAPTER, periodic_worker);
+ return CYW43_SLEEP_CHECK_MS * 1000;
+}
+
+void cyw43_await_background_or_timeout_us(uint32_t timeout_us) {
+ // if we are called from within an IRQ, then don't wait (we are only ever called in a polling loop)
+ if (!__get_current_exception()) {
+ sem_acquire_timeout_us(&cyw43_irq_sem, timeout_us);
+ }
+}
+
+// GPIO interrupt handler to tell us there's cyw43 has work to do
+static void gpio_irq_handler(void)
+{
+ uint32_t events = gpio_get_irq_event_mask(CYW43_PIN_WL_HOST_WAKE);
+ if (events & GPIO_IRQ_LEVEL_HIGH) {
+ // As we use a high level interrupt, it will go off forever until it's serviced
+ // So disable the interrupt until this is done. It's re-enabled again by CYW43_POST_POLL_HOOK
+ // which is called at the end of cyw43_poll_func
+ gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, false);
+ // also clear the force bit which we use to progratically cause this handler to fire (on the right core)
+ io_irq_ctrl_hw_t *irq_ctrl_base = get_core_num() ?
+ &iobank0_hw->proc1_irq_ctrl : &iobank0_hw->proc0_irq_ctrl;
+ hw_clear_bits(&irq_ctrl_base->intf[CYW43_PIN_WL_HOST_WAKE/8], GPIO_IRQ_LEVEL_HIGH << (4 * (CYW43_PIN_WL_HOST_WAKE & 7)));
+ low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_CYW43, cyw43_poll);
+ CYW43_STAT_INC(IRQ_COUNT);
+ }
+}
+
+// Low priority interrupt handler to perform background processing
+static void low_priority_irq_handler(void) {
+ assert(cyw43_core_num == get_core_num());
+ if (recursive_mutex_try_enter(&cyw43_mutex, NULL)) {
+ if (recursive_mutex_enter_count(&cyw43_mutex) != 1) {
+ low_priority_irq_missed = true;
+ CYW43_STAT_INC(PENDSV_DISABLED_COUNT);
+ } else {
+ CYW43_STAT_INC(PENDSV_RUN_COUNT);
+#ifndef NDEBUG
+ in_low_priority_irq = true;
+#endif
+ for (size_t i = 0; i < count_of(low_priority_irq_dispatch_slots); i++) {
+ if (low_priority_irq_dispatch_slots[i] != NULL) {
+ low_prio_irq_dispatch_t f = low_priority_irq_dispatch_slots[i];
+ low_priority_irq_dispatch_slots[i] = NULL;
+ f();
+ }
+ }
+#ifndef NDEBUG
+ in_low_priority_irq = false;
+#endif
+ }
+ recursive_mutex_exit(&cyw43_mutex);
+ } else {
+ CYW43_STAT_INC(PENDSV_DISABLED_COUNT);
+ low_priority_irq_missed = true;
+ }
+ sem_release(&cyw43_irq_sem);
+}
+
+static bool low_prio_irq_init(uint8_t priority) {
+ assert(get_core_num() == cyw43_core_num);
+ int irq = user_irq_claim_unused(false);
+ if (irq < 0) return false;
+ low_priority_irq_num = (uint8_t) irq;
+ irq_set_exclusive_handler(low_priority_irq_num, low_priority_irq_handler);
+ irq_set_enabled(low_priority_irq_num, true);
+ irq_set_priority(low_priority_irq_num, priority);
+ return true;
+}
+
+static void low_prio_irq_deinit(void) {
+ if (low_priority_irq_num > 0) {
+ irq_set_enabled(low_priority_irq_num, false);
+ irq_remove_handler(low_priority_irq_num, low_priority_irq_handler);
+ user_irq_unclaim(low_priority_irq_num);
+ low_priority_irq_num = 0;
+ }
+}
+
+int cyw43_arch_init(void) {
+ cyw43_core_num = get_core_num();
+ recursive_mutex_init(&cyw43_mutex);
+ cyw43_init(&cyw43_state);
+ sem_init(&cyw43_irq_sem, 0, 1);
+
+ // Start regular lwip callback to handle timeouts
+ periodic_alarm = add_alarm_in_us(CYW43_SLEEP_CHECK_MS * 1000, periodic_alarm_handler, NULL, true);
+ if (periodic_alarm < 0) {
+ return PICO_ERROR_GENERIC;
+ }
+
+ gpio_add_raw_irq_handler_with_order_priority(IO_IRQ_BANK0, gpio_irq_handler, CYW43_GPIO_IRQ_HANDLER_PRIORITY);
+ gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, true);
+ irq_set_enabled(IO_IRQ_BANK0, true);
+
+#if CYW43_LWIP
+ lwip_init();
+#endif
+ // start low priority handler (no background work is done before this)
+ bool ok = low_prio_irq_init(PICO_LOWEST_IRQ_PRIORITY);
+ if (!ok) {
+ cyw43_arch_deinit();
+ return PICO_ERROR_GENERIC;
+ }
+ return PICO_OK;
+}
+
+void cyw43_arch_deinit(void) {
+ if (periodic_alarm >= 0) {
+ cancel_alarm(periodic_alarm);
+ periodic_alarm = -1;
+ }
+ gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, false);
+ gpio_remove_raw_irq_handler(IO_IRQ_BANK0, gpio_irq_handler);
+ low_prio_irq_deinit();
+}
+
+void cyw43_post_poll_hook(void) {
+ gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, true);
+}
+
+// This is called in the gpio and low_prio_irq interrupts and on either core
+static void low_prio_irq_schedule_dispatch(size_t slot, low_prio_irq_dispatch_t f) {
+ assert(slot < count_of(low_priority_irq_dispatch_slots));
+ low_priority_irq_dispatch_slots[slot] = f;
+ if (cyw43_core_num == get_core_num()) {
+ //on same core, can dispatch directly
+ irq_set_pending(low_priority_irq_num);
+ } else {
+ // on wrong core, so force via GPIO IRQ which itself calls this method for the CYW43 slot.
+ // since the CYW43 slot always uses the same function, this is fine with the addition of an
+ // extra (but harmless) CYW43 slot call when another SLOT is invoked.
+ // We could do better, but would have to track why the IRQ was called.
+ io_irq_ctrl_hw_t *irq_ctrl_base = cyw43_core_num ?
+ &iobank0_hw->proc1_irq_ctrl : &iobank0_hw->proc0_irq_ctrl;
+ hw_set_bits(&irq_ctrl_base->intf[CYW43_PIN_WL_HOST_WAKE/8], GPIO_IRQ_LEVEL_HIGH << (4 * (CYW43_PIN_WL_HOST_WAKE & 7)));
+ }
+}
+
+void cyw43_schedule_internal_poll_dispatch(void (*func)(void)) {
+ low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_CYW43, func);
+}
+
+// Prevent background processing in pensv and access by the other core
+// These methods are called in pensv context and on either core
+// They can be called recursively
+void cyw43_thread_enter(void) {
+ // Lock the other core and stop low_prio_irq running
+ recursive_mutex_enter_blocking(&cyw43_mutex);
+}
+
+#ifndef NDEBUG
+void cyw43_thread_lock_check(void) {
+ // Lock the other core and stop low_prio_irq running
+ if (recursive_mutex_enter_count(&cyw43_mutex) < 1 || recursive_mutex_owner(&cyw43_mutex) != lock_get_caller_owner_id()) {
+ panic("cyw43_thread_lock_check failed");
+ }
+}
+#endif
+
+// Re-enable background processing
+void cyw43_thread_exit(void) {
+ // Run low_prio_irq if needed
+ if (1 == recursive_mutex_enter_count(&cyw43_mutex)) {
+ // note the outer release of the mutex is not via cyw43_exit in the low_priority_irq case (it is a direct mutex exit)
+ assert(!in_low_priority_irq);
+// if (low_priority_irq_missed) {
+// low_priority_irq_missed = false;
+ if (low_priority_irq_dispatch_slots[CYW43_DISPATCH_SLOT_CYW43]) {
+ low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_CYW43, cyw43_poll);
+ }
+// }
+ }
+ recursive_mutex_exit(&cyw43_mutex);
+}
+
+
+static void cyw43_delay_until(absolute_time_t until) {
+ // sleep can be called in IRQs, so there's not much we can do there
+ if (__get_current_exception()) {
+ busy_wait_until(until);
+ } else {
+ sleep_until(until);
+ }
+}
+
+void cyw43_delay_ms(uint32_t ms) {
+ cyw43_delay_until(make_timeout_time_ms(ms));
+}
+
+void cyw43_delay_us(uint32_t us) {
+ cyw43_delay_until(make_timeout_time_us(us));
+}
+
+void cyw43_arch_poll() {
+ // should not be necessary
+// if (cyw43_poll) {
+// low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_CYW43, cyw43_poll);
+// }
+}
+
+#if !CYW43_LWIP
+static void no_lwip_fail() {
+ panic("You cannot use IP with pico_cyw43_arch_none");
+}
+void cyw43_cb_tcpip_init(cyw43_t *self, int itf) {
+}
+void cyw43_cb_tcpip_deinit(cyw43_t *self, int itf) {
+}
+void cyw43_cb_tcpip_set_link_up(cyw43_t *self, int itf) {
+ no_lwip_fail();
+}
+void cyw43_cb_tcpip_set_link_down(cyw43_t *self, int itf) {
+ no_lwip_fail();
+}
+void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf) {
+ no_lwip_fail();
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/src/rp2_common/pico_cyw43_arch/include/cyw43_configport.h b/src/rp2_common/pico_cyw43_arch/include/cyw43_configport.h
new file mode 100644
index 0000000..7827c81
--- /dev/null
+++ b/src/rp2_common/pico_cyw43_arch/include/cyw43_configport.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+// This header is included by cyw43_driver to setup its environment
+
+#ifndef _CYW43_CONFIGPORT_H
+#define _CYW43_CONFIGPORT_H
+
+#include "pico.h"
+
+#ifdef PICO_CYW43_ARCH_HEADER
+#include __XSTRING(PICO_CYW43_ARCH_HEADER)
+#else
+#if PICO_CYW43_ARCH_POLL
+#include "pico/cyw43_arch/arch_poll.h"
+#elif PICO_CYW43_ARCH_THREADSAFE_BACKGROUND
+#include "pico/cyw43_arch/arch_threadsafe_background.h"
+#elif PICO_CYW43_ARCH_FREERTOS
+#include "pico/cyw43_arch/arch_freertos.h"
+#else
+#error must specify support pico_cyw43_arch architecture type or set PICO_CYW43_ARCH_HEADER
+#endif
+#endif
+
+#ifndef CYW43_HOST_NAME
+#define CYW43_HOST_NAME "PicoW"
+#endif
+
+#ifndef CYW43_GPIO
+#define CYW43_GPIO 1
+#endif
+
+#ifndef CYW43_LOGIC_DEBUG
+#define CYW43_LOGIC_DEBUG 0
+#endif
+
+#ifndef CYW43_USE_OTP_MAC
+#define CYW43_USE_OTP_MAC 1
+#endif
+
+#ifndef CYW43_NO_NETUTILS
+#define CYW43_NO_NETUTILS 1
+#endif
+
+#ifndef CYW43_IOCTL_TIMEOUT_US
+#define CYW43_IOCTL_TIMEOUT_US 1000000
+#endif
+
+#ifndef CYW43_USE_STATS
+#define CYW43_USE_STATS 0
+#endif
+
+// todo should this be user settable?
+#ifndef CYW43_HAL_MAC_WLAN0
+#define CYW43_HAL_MAC_WLAN0 0
+#endif
+
+#ifndef STATIC
+#define STATIC static
+#endif
+
+#ifndef CYW43_USE_SPI
+#define CYW43_USE_SPI 1
+#endif
+
+#ifndef CYW43_SPI_PIO
+#define CYW43_SPI_PIO 1
+#endif
+
+#endif
\ No newline at end of file
diff --git a/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch.h b/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch.h
new file mode 100644
index 0000000..8d6a628
--- /dev/null
+++ b/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch.h
@@ -0,0 +1,328 @@
+/*
+ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _PICO_CYW43_ARCH_H
+#define _PICO_CYW43_ARCH_H
+
+#include "pico.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "cyw43.h"
+#include "cyw43_country.h"
+
+/**
+ * \defgroup cyw43_driver cyw43_driver
+ * \ingroup pico_cyw43_arch
+ * \brief Driver used for Pico W wireless
+*/
+
+/**
+ * \defgroup cyw43_ll cyw43_ll
+ * \ingroup cyw43_driver
+ * \brief Low Level CYW43 driver interface
+*/
+
+/** \file pico/cyw43_arch.h
+ * \defgroup pico_cyw43_arch pico_cyw43_arch
+ *
+ * Architecture for integrating the CYW43 driver (for the wireless on Pico W) and lwIP (for TCP/IP stack) into the SDK. It is also necessary for accessing the on-board LED on Pico W
+ *
+ * Both the low level \c cyw43_driver and the lwIP stack require periodic servicing, and have limitations
+ * on whether they can be called from multiple cores/threads.
+ *
+ * \c pico_cyw43_arch attempts to abstract these complications into several behavioral groups:
+ *
+ * * \em 'poll' - This not multi-core/IRQ safe, and requires the user to call \ref cyw43_arch_poll periodically from their main loop
+ * * \em 'thread_safe_background' - This is multi-core/thread/task safe, and maintenance of the driver and TCP/IP stack is handled automatically in the background
+ *
+ * As of right now, lwIP is the only supported TCP/IP stack, however the use of \c pico_cyw43_arch is intended to be independent of
+ * the particular TCP/IP stack used (and possibly Bluetooth stack used) in the future. For this reason, the integration of lwIP
+ * is handled in the base (\c pico_cyw43_arch) library based on the #define \ref CYW43_LWIP used by the \c cyw43_driver.
+ *
+ * Whilst you can use the \c pico_cyw43_arch library directly and specify \ref CYW$#_LWIP (and other defines) yourself, several
+ * other libraries are made available to the build which aggregate the defines and other dependencies for you:
+ *
+ * * \b pico_cyw43_arch_lwip_poll - For using the RAW lwIP API (in `NO_SYS=1` mode) without any background processing or multi-core/thread safety.
+ *
+ * The user must call \ref pico_cyw43_poll periodically from their main loop.
+ *
+ * This wrapper library:
+ * - Sets \c CYW43_LWIP=1 to enable lwIP support in \c pico_cyw43_arch and \c cyw43_driver.
+ * - Sets \c PICO_CYW43_ARCH_POLL=1 to select the polling behavior.
+ * - Adds the \c pico_lwip as a dependency to pull in lwIP.
+ *
+ * * \b pico_cyw43_arch_lwip_threadsafe_background - For using the RAW lwIP API (in `NO_SYS=1` mode) with multi-core/thread safety, and automatic servicing of the \c cyw43_driver and
+ * lwIP in background.
+ *
+ * Calls into the \c cyw43_driver high level API (cyw43.h) may be made from either core or from lwIP callbacks, however calls into lwIP (which
+ * is not thread-safe) other than those made from lwIP callbacks, must be bracketed with \ref cyw43_arch_lwip_begin and \ref cyw43_arch_lwip_end. It is fine to bracket
+ * calls made from within lwIP callbacks too; you just don't have to.
+ *
+ * \note lwIP callbacks happen in a (low priority) IRQ context (similar to an alarm callback), so care should be taken when interacting
+ * with other code.
+ *
+ * This wrapper library:
+ * - Sets \c CYW43_LWIP=1 to enable lwIP support in \c pico_cyw43_arch and \c cyw43_driver
+ * - Sets \c PICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1 to select the thread-safe/non-polling behavior.
+ * - Adds the pico_lwip as a dependency to pull in lwIP.
+ *
+ *
+ * This library \em can also be used under the RP2040 port of FreeRTOS with lwIP in `NO_SYS=1` mode (allowing you to call \c cyw43_driver APIs
+ * from any task, and to call lwIP from lwIP callbacks, or from any task if you bracket the calls with \ref cyw43_arch_lwip_begin and \ref cyw43_arch_lwip_end. Again, you should be
+ * careful about what you do in lwIP callbacks, as you cannot call most FreeRTOS APIs from within an IRQ context. Unless you have good reason, you should probably
+ * use the full FreeRTOS integration (with `NO_SYS=0`) provided by \c pico_cyw43_arch_lwip_sys_freertos.
+ *
+ * * \b pico_cyw43_arch_lwip_sys_freertos - For using the full lwIP API including blocking sockets in OS (`NO_SYS=0`) mode, along with with multi-core/task/thread safety, and automatic servicing of the \c cyw43_driver and
+ * the lwIP stack.
+ *
+ * This wrapper library:
+ * - Sets \c CYW43_LWIP=1 to enable lwIP support in \c pico_cyw43_arch and \c cyw43_driver.
+ * - Sets \c PICO_CYW43_ARCH_FREERTOS=1 to select the NO_SYS=0 lwip/FreeRTOS integration
+ * - Sets \c LWIP_PROVIDE_ERRNO=1 to provide error numbers needed for compilation without an OS
+ * - Adds the \c pico_lwip as a dependency to pull in lwIP.
+ * - Adds the lwIP/FreeRTOS code from lwip-contrib (in the contrib directory of lwIP)
+ *
+ * Calls into the \c cyw43_driver high level API (cyw43.h) may be made from any task or from lwIP callbacks, but not from IRQs. Calls into the lwIP RAW API (which is not thread safe)
+ * must be bracketed with \ref cyw43_arch_lwip_begin and \ref cyw43_arch_lwip_end. It is fine to bracket calls made from within lwIP callbacks too; you just don't have to.
+ *
+ * \note this wrapper library requires you to link FreeRTOS functionality with your application yourself.
+ *
+ * * \b pico_cyw43_arch_none - If you do not need the TCP/IP stack but wish to use the on-board LED.
+ *
+ * This wrapper library:
+ * - Sets \c CYW43_LWIP=0 to disable lwIP support in \c pico_cyw43_arch and \c cyw43_driver
+ */
+
+// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_CYW43_ARCH, Enable/disable assertions in the pico_cyw43_arch module, type=bool, default=0, group=pico_cyw43_arch
+#ifndef PARAM_ASSERTIONS_ENABLED_CYW43_ARCH
+#define PARAM_ASSERTIONS_ENABLED_CYW43_ARCH 0
+#endif
+
+// PICO_CONFIG: CYW43_ARCH_DEBUG_ENABLED, Enable/disable some debugging output in the pico_cyw43_arch module, type=bool, default=1 in debug builds, group=pico_cyw43_arch
+#ifndef CYW43_ARCH_DEBUG_ENABLED
+#ifndef NDEBUG
+#define CYW43_ARCH_DEBUG_ENABLED 1
+#else
+#define CYW43_ARCH_DEBUG_ENABLED 0
+#endif
+#endif
+
+// PICO_CONFIG: PICO_CYW43_ARCH_DEFAULT_COUNTRY_CODE, Default country code for the cyw43 wireless driver, default=CYW43_COUNTRY_WORLDWIDE, group=pico_cyw43_arch
+#ifndef PICO_CYW43_ARCH_DEFAULT_COUNTRY_CODE
+#define PICO_CYW43_ARCH_DEFAULT_COUNTRY_CODE CYW43_COUNTRY_WORLDWIDE
+#endif
+
+/*!
+ * \brief Initialize the CYW43 architecture
+ * \ingroup pico_cyw43_arch
+ *
+ * This method initializes the `cyw43_driver` code and initializes the lwIP stack (if it
+ * was enabled at build time). This method must be called prior to using any other \c pico_cyw43_arch,
+ * \cyw43_driver or lwIP functions.
+ *
+ * \note this method initializes wireless with a country code of \c PICO_CYW43_ARCH_DEFAULT_COUNTRY_CODE
+ * which defaults to \c CYW43_COUNTRY_WORLDWIDE. Worldwide settings may not give the best performance; consider
+ * setting PICO_CYW43_ARCH_DEFAULT_COUNTRY_CODE to a different value or calling \ref cyw43_arch_init_with_country
+ * \return 0 if the initialization is successful, an error code otherwise \see pico_error_codes
+ */
+int cyw43_arch_init(void);
+
+/*!
+ * \brief Initialize the CYW43 architecture for use in a specific country
+ * \ingroup pico_cyw43_arch
+ *
+ * This method initializes the `cyw43_driver` code and initializes the lwIP stack (if it
+ * was enabled at build time). This method must be called prior to using any other \c pico_cyw43_arch,
+ * \cyw43_driver or lwIP functions.
+ *
+ * \param country the country code to use (see \ref CYW43_COUNTRY_)
+ * \return 0 if the initialization is successful, an error code otherwise \see pico_error_codes
+ */
+int cyw43_arch_init_with_country(uint32_t country);
+
+/*!
+ * \brief Enables Wi-Fi STA (Station) mode.
+ * \ingroup pico_cyw43_arch
+ *
+ * This enables the Wi-Fi in \emStation mode such that connections can be made to other Wi-Fi Access Points
+ */
+void cyw43_arch_enable_sta_mode(void);
+
+/*!
+ * \brief Enables Wi-Fi AP (Access point) mode.
+ * \ingroup pico_cyw43_arch
+ *
+ * This enables the Wi-Fi in \em Access \em Point mode such that connections can be made to the device by other Wi-Fi clients
+ * \param ssid the name for the access point
+ * \param password the password to use or NULL for no password.
+ * \param auth the authorization type to use when the password is enabled. Values are \ref CYW43_AUTH_WPA_TKIP_PSK,
+ * \ref CYW43_AUTH_WPA2_AES_PSK, or \ref CYW43_AUTH_WPA2_MIXED_PSK (see \ref CYW43_AUTH_)
+ */
+void cyw43_arch_enable_ap_mode(const char *ssid, const char *password, uint32_t auth);
+
+/*!
+ * \brief De-initialize the CYW43 architecture
+ * \ingroup pico_cyw43_arch
+ *
+ * This method de-initializes the `cyw43_driver` code and de-initializes the lwIP stack (if it
+ * was enabled at build time). Note this method should always be called from the same core (or RTOS
+ * task, depending on the environment) as \ref cyw43_arch_init.
+ */
+void cyw43_arch_deinit(void);
+
+/*!
+ * \brief Attempt to connect to a wireless access point, blocking until the network is joined or a failure is detected.
+ * \ingroup pico_cyw43_arch
+ *
+ * \param ssid the network name to connect to
+ * \param password the network password or NULL if there is no password required
+ * \param auth the authorization type to use when the password is enabled. Values are \ref CYW43_AUTH_WPA_TKIP_PSK,
+ * \ref CYW43_AUTH_WPA2_AES_PSK, or \ref CYW43_AUTH_WPA2_MIXED_PSK (see \ref CYW43_AUTH_)
+ *
+ * \return 0 if the initialization is successful, an error code otherwise \see pico_error_codes
+ */
+int cyw43_arch_wifi_connect_blocking(const char *ssid, const char *pw, uint32_t auth);
+
+/*!
+ * \brief Attempt to connect to a wireless access point, blocking until the network is joined, a failure is detected or a timeout occurs
+ * \ingroup pico_cyw43_arch
+ *
+ * \param ssid the network name to connect to
+ * \param password the network password or NULL if there is no password required
+ * \param auth the authorization type to use when the password is enabled. Values are \ref CYW43_AUTH_WPA_TKIP_PSK,
+ * \ref CYW43_AUTH_WPA2_AES_PSK, or \ref CYW43_AUTH_WPA2_MIXED_PSK (see \ref CYW43_AUTH_)
+ *
+ * \return 0 if the initialization is successful, an error code otherwise \see pico_error_codes
+ */
+int cyw43_arch_wifi_connect_timeout_ms(const char *ssid, const char *pw, uint32_t auth, uint32_t timeout);
+
+/*!
+ * \brief Start attempting to connect to a wireless access point
+ * \ingroup pico_cyw43_arch
+ *
+ * This method tells the CYW43 driver to start connecting to an access point. You should subsequently check the
+ * status by calling \ref cyw43_wifi_link_status.
+ *
+ * \param ssid the network name to connect to
+ * \param password the network password or NULL if there is no password required
+ * \param auth the authorization type to use when the password is enabled. Values are \ref CYW43_AUTH_WPA_TKIP_PSK,
+ * \ref CYW43_AUTH_WPA2_AES_PSK, or \ref CYW43_AUTH_WPA2_MIXED_PSK (see \ref CYW43_AUTH_)
+ *
+ * \return 0 if the scan was started successfully, an error code otherwise \see pico_error_codes
+ */
+int cyw43_arch_wifi_connect_async(const char *ssid, const char *pw, uint32_t auth);
+
+/*!
+ * \brief Return the country code used to initialize cyw43_arch
+ * \ingroup pico_cyw43_arch
+ *
+ * \return the country code (see \ref CYW43_COUNTRY_)
+ */
+uint32_t cyw43_arch_get_country_code(void);
+
+/*!
+ * \brief Set a GPIO pin on the wireless chip to a given value
+ * \ingroup pico_cyw43_arch
+ * \note this method does not check for errors setting the GPIO. You can use the lower level \ref cyw43_gpio_set instead if you wish
+ * to check for errors.
+ *
+ * \param wl_gpio the GPIO number on the wireless chip
+ * \param value true to set the GPIO, false to clear it.
+ */
+void cyw43_arch_gpio_put(uint wl_gpio, bool value);
+
+/*!
+ * \brief Read the value of a GPIO pin on the wireless chip
+ * \ingroup pico_cyw43_arch
+ * \note this method does not check for errors setting the GPIO. You can use the lower level \ref cyw43_gpio_get instead if you wish
+ * to check for errors.
+ *
+ * \param wl_gpio the GPIO number on the wireless chip
+ * \return true if the GPIO is high, false otherwise
+ */
+bool cyw43_arch_gpio_get(uint wl_gpio);
+
+/*!
+ * \brief Perform any processing required by the \c cyw43_driver or the TCP/IP stack
+ * \ingroup pico_cyw43_arch
+ *
+ * This method must be called periodically from the main loop when using a
+ * \em polling style \c pico_cyw43_arch (e.g. \c pico_cyw43_arch_lwip_poll ). It
+ * may be called in other styles, but it is unnecessary to do so.
+ */
+void cyw43_arch_poll(void);
+
+/*!
+ * \fn cyw43_arch_lwip_begin
+ * \brief Acquire any locks required to call into lwIP
+ * \ingroup pico_cyw43_arch
+ *
+ * The lwIP API is not thread safe. You should surround calls into the lwIP API
+ * with calls to this method and \ref cyw43_arch_lwip_end. Note these calls are not
+ * necessary (but harmless) when you are calling back into the lwIP API from an lwIP callback.
+ * If you are using single-core polling only (pico_cyw43_arch_poll) then these calls are no-ops
+ * anyway it is good practice to call them anyway where they are necessary.
+ *
+ * \sa cyw43_arch_lwip_end
+ * \sa cyw43_arch_lwip_protect
+ */
+
+/*!
+ * \fn void cyw43_arch_lwip_end(void)
+ * \brief Release any locks required for calling into lwIP
+ * \ingroup pico_cyw43_arch
+ *
+ * The lwIP API is not thread safe. You should surround calls into the lwIP API
+ * with calls to \ref cyw43_arch_lwip_begin and this method. Note these calls are not
+ * necessary (but harmless) when you are calling back into the lwIP API from an lwIP callback.
+ * If you are using single-core polling only (pico_cyw43_arch_poll) then these calls are no-ops
+ * anyway it is good practice to call them anyway where they are necessary.
+ *
+ * \sa cyw43_arch_lwip_begin
+ * \sa cyw43_arch_lwip_protect
+ */
+
+/*!
+ * \fn int cyw43_arch_lwip_protect(int (*func)(void *param), void *param)
+ * \brief sad Release any locks required for calling into lwIP
+ * \ingroup pico_cyw43_arch
+ *
+ * The lwIP API is not thread safe. You can use this method to wrap a function
+ * with any locking required to call into the lwIP API. If you are using
+ * single-core polling only (pico_cyw43_arch_poll) then there are no
+ * locks to required, but it is still good practice to use this function.
+ *
+ * \param func the function ta call with any required locks held
+ * \param param parameter to pass to \c func
+ * \return the return value from \c func
+ * \sa cyw43_arch_lwip_begin
+ * \sa cyw43_arch_lwip_end
+ */
+
+/*!
+ * \fn void cyw43_arch_lwip_check(void)
+ * \brief Checks the caller has any locks required for calling into lwIP
+ * \ingroup pico_cyw43_arch
+ *
+ * The lwIP API is not thread safe. You should surround calls into the lwIP API
+ * with calls to \ref cyw43_arch_lwip_begin and this method. Note these calls are not
+ * necessary (but harmless) when you are calling back into the lwIP API from an lwIP callback.
+ *
+ * This method will assert in debug mode, if the above conditions are not met (i.e. it is not safe to
+ * call into the lwIP API)
+ *
+ * \sa cyw43_arch_lwip_begin
+ * \sa cyw43_arch_lwip_protect
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch/arch_common.h b/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch/arch_common.h
new file mode 100644
index 0000000..3cd5aa9
--- /dev/null
+++ b/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch/arch_common.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _PICO_CYW43_ARCH_ARCH_COMMON_H
+#define _PICO_CYW43_ARCH_ARCH_COMMON_H
+
+#include "pico.h"
+#include "pico/time.h"
+#include "hardware/gpio.h"
+#include "pico/error.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Note, these are negated, because cyw43_driver negates them before returning!
+#define CYW43_EPERM (-PICO_ERROR_NOT_PERMITTED) // Operation not permitted
+#define CYW43_EIO (-PICO_ERROR_IO) // I/O error
+#define CYW43_EINVAL (-PICO_ERROR_INVALID_ARG) // Invalid argument
+#define CYW43_ETIMEDOUT (-PICO_ERROR_TIMEOUT) // Connection timed out
+
+#define CYW43_NUM_GPIOS CYW43_WL_GPIO_COUNT
+
+#define cyw43_hal_pin_obj_t uint
+
+// get the number of elements in a fixed-size array
+#define CYW43_ARRAY_SIZE(a) count_of(a)
+
+static inline uint32_t cyw43_hal_ticks_us(void) {
+ return time_us_32();
+}
+
+static inline uint32_t cyw43_hal_ticks_ms(void) {
+ return to_ms_since_boot(get_absolute_time());
+}
+
+static inline int cyw43_hal_pin_read(cyw43_hal_pin_obj_t pin) {
+ return gpio_get(pin);
+}
+
+static inline void cyw43_hal_pin_low(cyw43_hal_pin_obj_t pin) {
+ gpio_clr_mask(1 << pin);
+}
+
+static inline void cyw43_hal_pin_high(cyw43_hal_pin_obj_t pin) {
+ gpio_set_mask(1 << pin);
+}
+
+#define CYW43_HAL_PIN_MODE_INPUT (GPIO_IN)
+#define CYW43_HAL_PIN_MODE_OUTPUT (GPIO_OUT)
+
+#define CYW43_HAL_PIN_PULL_NONE (0)
+#define CYW43_HAL_PIN_PULL_UP (1)
+#define CYW43_HAL_PIN_PULL_DOWN (2)
+
+static inline void cyw43_hal_pin_config(cyw43_hal_pin_obj_t pin, uint32_t mode, uint32_t pull, __unused uint32_t alt) {
+ assert((mode == CYW43_HAL_PIN_MODE_INPUT || mode == CYW43_HAL_PIN_MODE_OUTPUT) && alt == 0);
+ gpio_set_dir(pin, mode);
+ gpio_set_pulls(pin, pull == CYW43_HAL_PIN_PULL_UP, pull == CYW43_HAL_PIN_PULL_DOWN);
+}
+
+void cyw43_hal_get_mac(int idx, uint8_t buf[6]);
+
+void cyw43_hal_generate_laa_mac(int idx, uint8_t buf[6]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch/arch_freertos.h b/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch/arch_freertos.h
new file mode 100644
index 0000000..342a85c
--- /dev/null
+++ b/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch/arch_freertos.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _EXAMPLE_CYW43_ARCH_ARCH_FREERTOS_SYS_H
+#define _EXAMPLE_CYW43_ARCH_ARCH_FREERTOS_SYS_H
+
+#include "pico/cyw43_arch/arch_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void cyw43_thread_enter(void);
+void cyw43_thread_exit(void);
+
+#define CYW43_THREAD_ENTER cyw43_thread_enter();
+#define CYW43_THREAD_EXIT cyw43_thread_exit();
+#ifndef NDEBUG
+void cyw43_thread_lock_check(void);
+#define cyw43_arch_lwip_check() cyw43_thread_lock_check()
+#define CYW43_THREAD_LOCK_CHECK cyw43_arch_lwip_check();
+#else
+#define cyw43_arch_lwip_check() ((void)0)
+#define CYW43_THREAD_LOCK_CHECK
+#endif
+
+void cyw43_await_background_or_timeout_us(uint32_t timeout_us);
+// todo not 100% sure about the timeouts here; MP uses __WFI which will always wakeup periodically
+#define CYW43_SDPCM_SEND_COMMON_WAIT cyw43_await_background_or_timeout_us(1000);
+#define CYW43_DO_IOCTL_WAIT cyw43_await_background_or_timeout_us(1000);
+
+void cyw43_delay_ms(uint32_t ms);
+void cyw43_delay_us(uint32_t us);
+
+void cyw43_schedule_internal_poll_dispatch(void (*func)(void));
+
+void cyw43_post_poll_hook(void);
+#define CYW43_POST_POLL_HOOK cyw43_post_poll_hook();
+
+static inline void cyw43_arch_lwip_begin(void) {
+ cyw43_thread_enter();
+}
+static inline void cyw43_arch_lwip_end(void) {
+ cyw43_thread_exit();
+}
+
+static inline int cyw43_arch_lwip_protect(int (*func)(void *param), void *param) {
+ cyw43_arch_lwip_begin();
+ int rc = func(param);
+ cyw43_arch_lwip_end();
+ return rc;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch/arch_poll.h b/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch/arch_poll.h
new file mode 100644
index 0000000..bfaea7f
--- /dev/null
+++ b/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch/arch_poll.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _PICO_CYW43_ARCH_ARCH_POLL_H
+#define _PICO_CYW43_ARCH_ARCH_POLL_H
+
+#include "pico/cyw43_arch/arch_common.h"
+
+#include <assert.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CYW43_THREAD_ENTER
+#define CYW43_THREAD_EXIT
+#ifndef NDEBUG
+
+void cyw43_thread_check(void);
+
+#define cyw43_arch_lwip_check() cyw43_thread_check()
+#define CYW43_THREAD_LOCK_CHECK cyw43_arch_lwip_check();
+#else
+#define cyw43_arch_lwip_check() ((void)0)
+#define CYW43_THREAD_LOCK_CHECK
+#endif
+
+#define CYW43_SDPCM_SEND_COMMON_WAIT cyw43_poll_required = true;
+#define CYW43_DO_IOCTL_WAIT cyw43_poll_required = true;
+
+#define cyw43_delay_ms sleep_ms
+#define cyw43_delay_us sleep_us
+
+void cyw43_schedule_internal_poll_dispatch(void (*func)(void));
+
+void cyw43_post_poll_hook(void);
+
+extern bool cyw43_poll_required;
+
+#define CYW43_POST_POLL_HOOK cyw43_post_poll_hook();
+#endif
+
+#ifndef DOXYGEN_GENERATION // multiple definitions in separate headers seems to confused doxygen
+#define cyw43_arch_lwip_begin() ((void)0)
+#define cyw43_arch_lwip_end() ((void)0)
+
+static inline int cyw43_arch_lwip_protect(int (*func)(void *param), void *param) {
+ return func(param);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch/arch_threadsafe_background.h b/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch/arch_threadsafe_background.h
new file mode 100644
index 0000000..713fcc1
--- /dev/null
+++ b/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch/arch_threadsafe_background.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _PICO_CYW43_ARCH_ARCH_THREADSAFE_BACKGROUND_H
+#define _PICO_CYW43_ARCH_ARCH_THREADSAFE_BACKGROUND_H
+
+#include "pico/cyw43_arch/arch_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void cyw43_thread_enter(void);
+
+void cyw43_thread_exit(void);
+
+#define CYW43_THREAD_ENTER cyw43_thread_enter();
+#define CYW43_THREAD_EXIT cyw43_thread_exit();
+#ifndef NDEBUG
+
+void cyw43_thread_lock_check(void);
+
+#define cyw43_arch_lwip_check() cyw43_thread_lock_check()
+#define CYW43_THREAD_LOCK_CHECK cyw43_arch_lwip_check();
+#else
+#define cyw43_arch_lwip_check() ((void)0)
+#define CYW43_THREAD_LOCK_CHECK
+#endif
+
+void cyw43_await_background_or_timeout_us(uint32_t timeout_us);
+// todo not 100% sure about the timeouts here; MP uses __WFI which will always wakeup periodically
+#define CYW43_SDPCM_SEND_COMMON_WAIT cyw43_await_background_or_timeout_us(1000);
+#define CYW43_DO_IOCTL_WAIT cyw43_await_background_or_timeout_us(1000);
+
+void cyw43_delay_ms(uint32_t ms);
+
+void cyw43_delay_us(uint32_t us);
+
+void cyw43_schedule_internal_poll_dispatch(void (*func)(void));
+
+void cyw43_post_poll_hook(void);
+
+#define CYW43_POST_POLL_HOOK cyw43_post_poll_hook();
+
+static inline void cyw43_arch_lwip_begin(void) {
+ cyw43_thread_enter();
+}
+
+static inline void cyw43_arch_lwip_end(void) {
+ cyw43_thread_exit();
+}
+
+static inline int cyw43_arch_lwip_protect(int (*func)(void *param), void *param) {
+ cyw43_arch_lwip_begin();
+ int rc = func(param);
+ cyw43_arch_lwip_end();
+ return rc;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/src/rp2_common/pico_divider/divider.S b/src/rp2_common/pico_divider/divider.S
index 234c1a4..ba42662 100644
--- a/src/rp2_common/pico_divider/divider.S
+++ b/src/rp2_common/pico_divider/divider.S
@@ -103,7 +103,7 @@
regular_func divmod_s32s32
#if !PICO_DIVIDER_DISABLE_INTERRUPTS
// to support IRQ usage (or context switch) we must save/restore divider state around call if state is dirty
- ldr r2, =(SIO_BASE)
+ ldr r2, =SIO_BASE
ldr r3, [r2, #SIO_DIV_CSR_OFFSET]
lsrs r3, #SIO_DIV_CSR_DIRTY_SHIFT_FOR_CARRY
bcs divmod_s32s32_savestate
@@ -114,7 +114,7 @@
// are the hardware_divider functions that can be used instead anyway
regular_func divmod_s32s32_unsafe
// to avoid worrying about IRQs (or context switches), simply disable interrupts around call
- ldr r2, =(SIO_BASE)
+ ldr r2, =SIO_BASE
mrs r3, PRIMASK
cpsid i
#endif /* !PICO_DIVIDER_DISABLE_INTERRUPTS */
@@ -167,7 +167,7 @@
wrapper_func __aeabi_uidivmod
#if !PICO_DIVIDER_DISABLE_INTERRUPTS
// to support IRQ usage (or context switch) we must save/restore divider state around call if state is dirty
- ldr r2, =(SIO_BASE)
+ ldr r2, =SIO_BASE
ldr r3, [r2, #SIO_DIV_CSR_OFFSET]
lsrs r3, #SIO_DIV_CSR_DIRTY_SHIFT_FOR_CARRY
bcs divmod_u32u32_savestate
@@ -178,7 +178,7 @@
// are the hardware_divider functions that can be used instead anyway
regular_func divmod_u32u32_unsafe
// to avoid worrying about IRQs (or context switches), simply disable interrupts around call
- ldr r2, =(SIO_BASE)
+ ldr r2, =SIO_BASE
mrs r3, PRIMASK
cpsid i
#endif /* !PICO_DIVIDER_DISABLE_INTERRUPTS */
@@ -227,7 +227,7 @@
#if !PICO_DIVIDER_DISABLE_INTERRUPTS
// to support IRQ usage (or context switch) we must save/restore divider state around call if state is dirty
mov ip, r2
- ldr r2, =(SIO_BASE)
+ ldr r2, =SIO_BASE
ldr r2, [r2, #SIO_DIV_CSR_OFFSET]
lsrs r2, #SIO_DIV_CSR_DIRTY_SHIFT_FOR_CARRY
mov r2, ip
@@ -255,7 +255,7 @@
#if !PICO_DIVIDER_DISABLE_INTERRUPTS
// to support IRQ usage (or context switch) we must save/restore divider state around call if state is dirty
mov ip, r2
- ldr r2, =(SIO_BASE)
+ ldr r2, =SIO_BASE
ldr r2, [r2, #SIO_DIV_CSR_OFFSET]
lsrs r2, #SIO_DIV_CSR_DIRTY_SHIFT_FOR_CARRY
mov r2, ip
@@ -278,7 +278,7 @@
.macro dneg lo,hi
mvns \hi,\hi
- rsbs \lo,#0
+ negs \lo,\lo
bne l\@_1
adds \hi,#1
l\@_1:
@@ -352,7 +352,7 @@
cmp r2,#0
beq 2f @ x==0?
mov r12,r7
- ldr r7,=#SIO_BASE
+ ldr r7,=SIO_BASE
str r0,[r7,#SIO_DIV_UDIVIDEND_OFFSET]
str r2,[r7,#SIO_DIV_UDIVISOR_OFFSET]
movs r1,#0
@@ -367,7 +367,7 @@
cmp r0,#0 @ y==0?
beq 3f @ then pass 0 to __aeabi_ldiv0
udiv0:
- ldr r0,=#0xffffffff
+ ldr r0,=0xffffffff
movs r1,r0 @ pass 2^64-1 to __aeabi_ldiv0
3:
push {r14}
@@ -402,7 +402,7 @@
cmp r2,#0
beq udiv0 @ x==0? exit as with y!=0 case above
push {r7}
- ldr r7,=#SIO_BASE
+ ldr r7,=SIO_BASE
str r1,[r7,#SIO_DIV_UDIVIDEND_OFFSET]
str r2,[r7,#SIO_DIV_UDIVISOR_OFFSET]
wait_div 4
@@ -464,9 +464,9 @@
lsrs r4,r2,#15
adds r4,#1 @ x1=(x0>>15)+1; 2^16<x1<=2^17
- ldr r7,=#SIO_BASE
+ ldr r7,=SIO_BASE
str r4,[r7,#SIO_DIV_UDIVISOR_OFFSET]
- ldr r4,=#0xffffffff
+ ldr r4,=0xffffffff
str r4,[r7,#SIO_DIV_UDIVIDEND_OFFSET]
lsrs r6,r1,#16
uxth r3,r2 @ x0l
@@ -687,9 +687,9 @@
adcs r4,r4
adds r4,#1 @ x1=(ui32)(x0>>31)+1; // 2^16<x1<=2^17
- ldr r7,=#SIO_BASE
+ ldr r7,=SIO_BASE
str r4,[r7,#SIO_DIV_UDIVISOR_OFFSET]
- ldr r4,=#0xffffffff
+ ldr r4,=0xffffffff
str r4,[r7,#SIO_DIV_UDIVIDEND_OFFSET]
lsrs r6,r1,#16
wait_div 1
@@ -821,7 +821,7 @@
adds r5,r3,#1
beq 1f
- ldr r7,=#SIO_BASE
+ ldr r7,=SIO_BASE
str r5,[r7,#SIO_DIV_UDIVISOR_OFFSET]
str r1,[r7,#SIO_DIV_UDIVIDEND_OFFSET]
wait_div 0
diff --git a/src/rp2_common/pico_double/double_aeabi.S b/src/rp2_common/pico_double/double_aeabi.S
index 0c59738..04cf22c 100644
--- a/src/rp2_common/pico_double/double_aeabi.S
+++ b/src/rp2_common/pico_double/double_aeabi.S
@@ -290,7 +290,7 @@
wrapper_func __aeabi_cdcmpeq
push {r0-r7,r14}
__aeabi_dfcmple_guts:
- ldr r7,=#0x7ff @ flush NaNs and denormals
+ ldr r7,=0x7ff @ flush NaNs and denormals
lsls r4,r1,#1
lsrs r4,#21
beq 1f
@@ -450,7 +450,7 @@
lsls r2, r4
lsls r0, r2, #20
lsrs r2, #12
- ldr r1,=#1055
+ ldr r1,=1055
subs r1, r4
lsls r1, #20
orrs r1, r3
@@ -552,7 +552,7 @@
cmp r1, #0
bmi 1f
movs r2, #0
- rsbs r0, #0
+ negs r0, r0
sbcs r2, r1
mov r1, r2
pop {pc}
diff --git a/src/rp2_common/pico_double/double_v1_rom_shim.S b/src/rp2_common/pico_double/double_v1_rom_shim.S
index 7a14ca4..6dac28a 100644
--- a/src/rp2_common/pico_double/double_v1_rom_shim.S
+++ b/src/rp2_common/pico_double/double_v1_rom_shim.S
@@ -144,7 +144,7 @@
lsls \re,#21
bcc l\@_1 @ skip on positive
mvns \rb,\rb @ negate mantissa
- rsbs \ra,#0
+ negs \ra,\ra
bcc l\@_1
adds \rb,#1
l\@_1:
@@ -218,7 +218,7 @@
mvns r1,r1 @ negate mantissa
mvns r0,r0
movs r2,#0
- rsbs r4,#0
+ negs r4,r4
adcs r0,r2
adcs r1,r2
1:
@@ -263,7 +263,7 @@
da_7:
@ here exponent overflow: return signed infinity
lsls r1,r3,#31
- ldr r3,=#0x7ff00000
+ ldr r3,=0x7ff00000
orrs r1,r3
b 1f
da_6:
@@ -524,7 +524,7 @@
adcs r1,r1
subs r3,#1 @ correct exponent
1:
- ldr r6,=#0x3ff
+ ldr r6,=0x3ff
subs r3,r6 @ correct for exponent bias
lsls r6,#1 @ 0x7fe
cmp r3,r6
@@ -811,7 +811,7 @@
muls r3,r0 @ zL*xH Q73
subs r4,r3
mul32_32_64 r2,r0, r2,r3, r5,r6,r7,r2,r3 @ xL*zL
- rsbs r2,#0 @ borrow from low half?
+ negs r2,r2 @ borrow from low half?
sbcs r4,r3 @ y-xz Q73 (remainder bits 52..73)
cmp r4,#0
@@ -830,9 +830,9 @@
mov r2,r12
lsls r7,r2,#31 @ result sign
asrs r2,#2 @ result exponent
- ldr r3,=#0x3fd
+ ldr r3,=0x3fd
adds r2,r3
- ldr r3,=#0x7fe
+ ldr r3,=0x7fe
cmp r2,r3
bhs dd_3 @ over- or underflow?
lsls r2,#20
@@ -936,7 +936,7 @@
b dq_4
dq_3:
- ldr r1,=#0x7ff
+ ldr r1,=0x7ff
lsls r1,#20 @ return +Inf
dq_4:
movs r0,#0
@@ -949,7 +949,7 @@
bcs dq_0 @ negative?
lsrs r2,#21 @ extract exponent
subs r2,#1
- ldr r3,=#0x7fe
+ ldr r3,=0x7fe
cmp r2,r3
bhs dq_2 @ catches 0 and +Inf
push {r4-r7,r14}
@@ -968,8 +968,8 @@
@ here
@ r0:r1 y mantissa Q52 [1,4)
@ r12 result exponent
-
- adr r4,drsqrtapp-8 @ first eight table entries are never accessed because of the mantissa's leading 1
+.equ drsqrtapp_minus_8, (drsqrtapp-8)
+ adr r4,drsqrtapp_minus_8 @ first eight table entries are never accessed because of the mantissa's leading 1
lsrs r2,r1,#17 @ y Q3
ldrb r2,[r4,r2] @ initial approximation to reciprocal square root a0 Q8
lsrs r3,r1,#4 @ first Newton-Raphson iteration
@@ -1100,7 +1100,7 @@
adds r2,r3 @ r1:r2 a5^2 Q106
lsls r0,#22 @ y Q84
- rsbs r1,#0
+ negs r1,r1
sbcs r0,r2 @ remainder y-a5^2
bmi 1f @ y<a5^2: no need to increment a5
movs r3,#0
@@ -1290,7 +1290,8 @@
bx r14
.weak d2fix_a // weak because it exists in float code too
-regular_func d2fix_a
+.thumb_func
+d2fix_a:
@ here
@ r0:r1 two's complement mantissa
@ r2 unbaised exponent
@@ -1304,7 +1305,7 @@
movs r4,r0
lsls r1,r2
lsls r0,r2
- rsbs r2,#0
+ negs r2,r2
adds r2,#32 @ complementary shift
lsrs r4,r2
orrs r1,r4
@@ -1319,7 +1320,7 @@
bmi 1f @ long shift?
mov r4,r1
lsls r4,r2
- rsbs r2,#0
+ negs r2,r2
adds r2,#32 @ complementary shift
asrs r1,r2
lsrs r0,r2
@@ -1331,7 +1332,7 @@
asrs r1,#31 @ shift down 32 places
adds r2,#32
bmi 1f @ very long shift?
- rsbs r2,#0
+ negs r2,r2
adds r2,#32
asrs r0,r2
pop {r4,r15}
@@ -1344,7 +1345,7 @@
regular_func double2float_shim
lsls r2,r1,#1
lsrs r2,#21 @ exponent
- ldr r3,=#0x3ff-0x7f
+ ldr r3,=0x3ff-0x7f
subs r2,r3 @ fix exponent bias
ble 1f @ underflow or zero
cmp r2,#0xff
@@ -1432,7 +1433,7 @@
sbcs r1,r3
uf2d:
push {r4,r5,r14}
- ldr r4,=#0x432
+ ldr r4,=0x432
subs r2,r4,r2 @ form biased exponent
@ here
@ r0:r1 unnormalised mantissa
@@ -1455,7 +1456,7 @@
lsrs r4,r1,#21
bcc 5b
4:
- ldr r4,=#0x7fe
+ ldr r4,=0x7fe
cmp r2,r4
bhs 6f @ over/underflow? return signed zero/infinity
7:
@@ -1506,7 +1507,7 @@
double_section dunpacks
regular_func dunpacks
mdunpacks r0,r1,r2,r3,r4
- ldr r3,=#0x3ff
+ ldr r3,=0x3ff
subs r2,r3 @ exponent without offset
bx r14
@@ -1572,7 +1573,7 @@
lsrs r3,r0,#24
orrs r1,r3
lsls r0,#8 @ r0:r1 Q60, to be shifted down -r2 places
- rsbs r3,r2,#0
+ negs r3,r2
adds r2,#32 @ shift down in r3, complementary shift in r2
bmi 1f @ long shift?
2:
@@ -1663,13 +1664,13 @@
bl dreduce
movs r4,#0
- ldr r5,=#0x9df04dbb @ this value compensates for the non-unity scaling of the CORDIC rotations
- ldr r6,=#0x36f656c5
+ ldr r5,=0x9df04dbb @ this value compensates for the non-unity scaling of the CORDIC rotations
+ ldr r6,=0x36f656c5
lsls r2,#31
bcc 1f
@ quadrant 2 or 3
mvns r6,r6
- rsbs r5,r5,#0
+ negs r5,r5
adcs r6,r4
1:
lsls r2,#1
@@ -1757,7 +1758,7 @@
@ r2:r3 x
push {r4-r7,r14}
bl push_r8_r11
- ldr r5,=#0x7ff00000
+ ldr r5,=0x7ff00000
movs r4,r1
ands r4,r5 @ y==0?
beq 1f
@@ -1786,7 +1787,7 @@
eors r3,r5
eors r1,r5
bmi 1f @ quadrant offset=+2 if y was positive
- rsbs r6,#0 @ quadrant offset=-2 if y was negative
+ negs r6,r6 @ quadrant offset=-2 if y was negative
1:
@ now in quadrant 0 or 3
adds r7,r1,r5 @ r7=-r1
@@ -1895,8 +1896,8 @@
cmp r6,#0
beq 1f
- ldr r4,=#0x885A308D @ π/2 Q61
- ldr r5,=#0x3243F6A8
+ ldr r4,=0x885A308D @ π/2 Q61
+ ldr r5,=0x3243F6A8
bpl 2f
mvns r4,r4 @ negative quadrant offset
mvns r5,r5
@@ -1959,8 +1960,8 @@
bl dreduce
cmp r1,#0
bge 1f
- ldr r4,=#0xF473DE6B
- ldr r5,=#0x2C5C85FD @ ln2 Q62
+ ldr r4,=0xF473DE6B
+ ldr r5,=0x2C5C85FD @ ln2 Q62
adds r0,r4
adcs r1,r5
subs r2,#1
@@ -1979,7 +1980,7 @@
sbcs r1,r5
bmi 1f
- rsbs r6,r7,#0
+ negs r6,r7
adds r6,#32 @ complementary shift
movs r5,r3
asrs r5,r7
@@ -2015,7 +2016,7 @@
adcs r1,r3
pop {r2}
- rsbs r2,#0
+ negs r2,r2
adds r2,#62
bl fix642double_shim @ in principle we can pack faster than this because we know the exponent
pop {r4-r7,r15}
@@ -2046,7 +2047,7 @@
movs r3,#0 @ y=0 Q62
3:
- rsbs r6,r7,#0
+ negs r6,r7
adds r6,#32 @ complementary shift
movs r5,r1
asrs r5,r7
@@ -2086,8 +2087,8 @@
@ here:
@ r2:r3 ln m/2 = ln m - ln2 Q62
@ r7 unbiased exponent
-
- adr r4,dreddata1+4
+.equ dreddata1_plus_4, (dreddata1+4)
+ adr r4,dreddata1_plus_4
ldmia r4,{r0,r1,r4}
adds r7,#1
muls r0,r7 @ Q62
@@ -2128,12 +2129,12 @@
pop {r4-r7,r15}
5:
- ldr r1,=#0xfff00000
+ ldr r1,=0xfff00000
movs r0,#0
pop {r4-r7,r15}
6:
- ldr r1,=#0x7ff00000
+ ldr r1,=0x7ff00000
movs r0,#0
pop {r4-r7,r15}
diff --git a/src/rp2_common/pico_fix/rp2040_usb_device_enumeration/rp2040_usb_device_enumeration.c b/src/rp2_common/pico_fix/rp2040_usb_device_enumeration/rp2040_usb_device_enumeration.c
index e1073ca..503cd12 100644
--- a/src/rp2_common/pico_fix/rp2040_usb_device_enumeration/rp2040_usb_device_enumeration.c
+++ b/src/rp2_common/pico_fix/rp2040_usb_device_enumeration/rp2040_usb_device_enumeration.c
@@ -17,12 +17,12 @@
#define LS_K 0b10
#define LS_SE1 0b11
+#if PICO_RP2040_B0_SUPPORTED || PICO_RP2040_B1_SUPPORTED
static void hw_enumeration_fix_wait_se0(void);
static void hw_enumeration_fix_force_ls_j(void);
static void hw_enumeration_fix_finish(void);
void rp2040_usb_device_enumeration_fix(void) {
-#if PICO_RP2040_B0_SUPPORTED || PICO_RP2040_B1_SUPPORTED
// Actually check for B0/B1 h/w
if (rp2040_chip_version() == 1) {
// After coming out of reset, the hardware expects 800us of LS_J (linestate J) time
@@ -36,7 +36,6 @@
// Wait SE0 phase will call force ls_j phase which will call finish phase
hw_enumeration_fix_wait_se0();
}
-#endif
}
static inline uint8_t hw_line_state(void) {
@@ -90,9 +89,7 @@
// DM must be 0 for this to work. This is true if it is selected
// to any other function. fn 8 on this pin is only for debug so shouldn't
// be selected
- if (gpio_get_function(dm) == 8) {
- panic("Not expecting DM to be function 8");
- }
+ hard_assert(gpio_get_function(dm) != 8);
// Before changing any pin state, take a copy of the current gpio control register
gpio_ctrl_prev = iobank0_hw->io[dp].ctrl;
@@ -148,3 +145,9 @@
// Restore the pad ctrl value
padsbank0_hw->io[dp] = pad_ctrl_prev;
}
+
+#else
+void rp2040_usb_device_enumeration_fix(void) {
+ // nothing to do
+}
+#endif
\ No newline at end of file
diff --git a/src/rp2_common/pico_float/float_aeabi.S b/src/rp2_common/pico_float/float_aeabi.S
index db393df..cb6f95f 100644
--- a/src/rp2_common/pico_float/float_aeabi.S
+++ b/src/rp2_common/pico_float/float_aeabi.S
@@ -378,7 +378,7 @@
lsrs r1, r0, #31
lsls r1, #31
bpl 1f
- rsbs r0, #0
+ negs r0, r0
1:
cmp r0, #0
beq 7f
@@ -392,7 +392,7 @@
pop {r1, r2}
lsls r1, r0
subs r0, #158
- rsbs r0, #0
+ negs r0, r0
adds r1,#0x80 @ rounding
bcs 5f @ tripped carry? then have leading 1 in C as required (and result is even so can ignore sticky bits)
@@ -459,7 +459,7 @@
bl __aeabi_f2uiz
cmp r0, #0
bmi 1f
- rsbs r0, #0
+ negs r0, r0
pop {pc}
1:
movs r0, #128
@@ -534,7 +534,7 @@
cmp r1, #0
bmi 1f
movs r2, #0
- rsbs r0, #0
+ negs r0, r0
sbcs r2, r1
mov r1, r2
pop {pc}
diff --git a/src/rp2_common/pico_float/float_v1_rom_shim.S b/src/rp2_common/pico_float/float_v1_rom_shim.S
index d7541a4..50df612 100644
--- a/src/rp2_common/pico_float/float_v1_rom_shim.S
+++ b/src/rp2_common/pico_float/float_v1_rom_shim.S
@@ -100,7 +100,7 @@
movs r5,r0
movs r0,r1
4:
- rsbs r2,#0
+ negs r2,r2
adds r2,#32+29
// bl packx
@@ -132,7 +132,7 @@
bmi 2f @ force y to 0 proper, so result will be zero
subs r4,r2,r3 @ calculate shift
bge 1f @ ex>=ey?
- rsbs r4,#0 @ make shift positive
+ negs r4,r4 @ make shift positive
asrs r0,r4
cmp r4,#28
blo 3f
@@ -159,8 +159,8 @@
ldr r3, =0x2cfc @ &pi_q29, circular coefficients
cmp r0,#0 @ x negative
bge 5f
- rsbs r0,#0 @ rotate to 1st/4th quadrants
- rsbs r1,#0
+ negs r0,r0 @ rotate to 1st/4th quadrants
+ negs r1,r1
ldr r2,[r3] @ pi Q29
5:
movs r4,#1 @ m=1
@@ -272,7 +272,7 @@
movs r4,r0
lsls r1,r2
lsls r0,r2
- rsbs r2,#0
+ negs r2,r2
adds r2,#32 @ complementary shift
lsrs r4,r2
orrs r1,r4
@@ -287,7 +287,7 @@
bmi 1f @ long shift?
mov r4,r1
lsls r4,r2
- rsbs r2,#0
+ negs r2,r2
adds r2,#32 @ complementary shift
asrs r1,r2
lsrs r0,r2
@@ -299,7 +299,7 @@
asrs r1,#31 @ shift down 32 places
adds r2,#32
bmi 1f @ very long shift?
- rsbs r2,#0
+ negs r2,r2
adds r2,#32
asrs r0,r2
pop {r4,r15}
@@ -329,7 +329,7 @@
cmp r2,#0xff @ Inf?
beq 2f
lsrs r1,#4 @ exponent and top 20 bits of mantissa
- ldr r2,=#(0x3ff-0x7f)<<20 @ difference in exponent offsets
+ ldr r2,=(0x3ff-0x7f)<<20 @ difference in exponent offsets
adds r1,r2
orrs r1,r3
lsls r0,#29 @ bottom 3 bits of mantissa
@@ -340,7 +340,7 @@
movs r0,#0
bx r14
2:
- ldr r1,=#0x7ff00000 @ return signed infinity
+ ldr r1,=0x7ff00000 @ return signed infinity
adds r1,r3
b 3b
diff --git a/src/rp2_common/pico_int64_ops/pico_int64_ops_aeabi.S b/src/rp2_common/pico_int64_ops/pico_int64_ops_aeabi.S
index 0dbc67c..114a1aa 100644
--- a/src/rp2_common/pico_int64_ops/pico_int64_ops_aeabi.S
+++ b/src/rp2_common/pico_int64_ops/pico_int64_ops_aeabi.S
@@ -10,11 +10,16 @@
#include "pico/asm_helper.S"
+.macro int64_section name
#if PICO_INT64_OPS_IN_RAM
-.section RAM_SECTION_NAME(__aeabi_lmul)
+.section RAM_SECTION_NAME(\name), "ax"
#else
-.section SECTION_NAME(__aeabi_lmul)
+.section SECTION_NAME(\name), "ax"
#endif
+.endm
+
+int64_section __aeabi_lmul
+
wrapper_func __aeabi_lmul
muls r1, r2
muls r3, r0
@@ -41,4 +46,3 @@
adcs r1, r2
add r1, r12
bx lr
-
diff --git a/src/rp2_common/pico_lwip/CMakeLists.txt b/src/rp2_common/pico_lwip/CMakeLists.txt
new file mode 100644
index 0000000..7b1a8a7
--- /dev/null
+++ b/src/rp2_common/pico_lwip/CMakeLists.txt
@@ -0,0 +1,278 @@
+if (DEFINED ENV{PICO_LWIP_PATH} AND (NOT PICO_LWIP_PATH))
+ set(PICO_LWIP_PATH $ENV{PICO_LWIP_PATH})
+ message("Using PICO_LWIP_PATH from environment ('${PICO_LWIP_PATH}')")
+endif ()
+
+set(LWIP_TEST_PATH "src/Filelists.cmake")
+if (NOT PICO_LWIP_PATH)
+ set(PICO_LWIP_PATH ${PROJECT_SOURCE_DIR}/lib/lwip)
+# if (NOT EXISTS ${PICO_LWIP_PATH}/${LWIP_TEST_PATH})
+# message(WARNING "LWIP submodule has not been initialized; Pico W wireless support will be unavailable
+#hint: try 'git submodule update --init' from your SDK directory (${PICO_SDK_PATH}).")
+# endif()
+elseif (NOT EXISTS ${PICO_LWIP_PATH}/${LWIP_TEST_PATH})
+ message(WARNING "PICO_LWIP_PATH specified but content not present.")
+endif()
+
+if (EXISTS ${PICO_LWIP_PATH}/${LWIP_TEST_PATH})
+ message("lwIP available at ${PICO_LWIP_PATH}")
+
+ # argh... wanted to use this, but they dump stuff into the source tree, which breaks parallel builds
+ #set(LWIP_DIR ${PICO_LWIP_PATH})
+ #include(${PICO_LWIP_PATH}/src/Filelists.cmake)
+
+ pico_register_common_scope_var(PICO_LWIP_PATH)
+
+ # The minimum set of files needed for lwIP.
+ add_library(pico_lwip_core INTERFACE)
+ target_sources(pico_lwip_core INTERFACE
+ ${PICO_LWIP_PATH}/src/core/init.c
+ ${PICO_LWIP_PATH}/src/core/def.c
+ ${PICO_LWIP_PATH}/src/core/dns.c
+ ${PICO_LWIP_PATH}/src/core/inet_chksum.c
+ ${PICO_LWIP_PATH}/src/core/ip.c
+ ${PICO_LWIP_PATH}/src/core/mem.c
+ ${PICO_LWIP_PATH}/src/core/memp.c
+ ${PICO_LWIP_PATH}/src/core/netif.c
+ ${PICO_LWIP_PATH}/src/core/pbuf.c
+ ${PICO_LWIP_PATH}/src/core/raw.c
+ ${PICO_LWIP_PATH}/src/core/stats.c
+ ${PICO_LWIP_PATH}/src/core/sys.c
+ ${PICO_LWIP_PATH}/src/core/altcp.c
+ ${PICO_LWIP_PATH}/src/core/altcp_alloc.c
+ ${PICO_LWIP_PATH}/src/core/altcp_tcp.c
+ ${PICO_LWIP_PATH}/src/core/tcp.c
+ ${PICO_LWIP_PATH}/src/core/tcp_in.c
+ ${PICO_LWIP_PATH}/src/core/tcp_out.c
+ ${PICO_LWIP_PATH}/src/core/timeouts.c
+ ${PICO_LWIP_PATH}/src/core/udp.c
+ ${CMAKE_CURRENT_LIST_DIR}/random.c
+ )
+ target_include_directories(pico_lwip_core INTERFACE
+ ${PICO_LWIP_PATH}/src/include)
+
+ add_library(pico_lwip_core4 INTERFACE)
+ target_sources(pico_lwip_core4 INTERFACE
+ ${PICO_LWIP_PATH}/src/core/ipv4/acd.c
+ ${PICO_LWIP_PATH}/src/core/ipv4/autoip.c
+ ${PICO_LWIP_PATH}/src/core/ipv4/dhcp.c
+ ${PICO_LWIP_PATH}/src/core/ipv4/etharp.c
+ ${PICO_LWIP_PATH}/src/core/ipv4/icmp.c
+ ${PICO_LWIP_PATH}/src/core/ipv4/igmp.c
+ ${PICO_LWIP_PATH}/src/core/ipv4/ip4_frag.c
+ ${PICO_LWIP_PATH}/src/core/ipv4/ip4.c
+ ${PICO_LWIP_PATH}/src/core/ipv4/ip4_addr.c
+ )
+
+ add_library(pico_lwip_core6 INTERFACE)
+ target_sources(pico_lwip_core6 INTERFACE
+ ${PICO_LWIP_PATH}/src/core/ipv6/dhcp6.c
+ ${PICO_LWIP_PATH}/src/core/ipv6/ethip6.c
+ ${PICO_LWIP_PATH}/src/core/ipv6/icmp6.c
+ ${PICO_LWIP_PATH}/src/core/ipv6/inet6.c
+ ${PICO_LWIP_PATH}/src/core/ipv6/ip6.c
+ ${PICO_LWIP_PATH}/src/core/ipv6/ip6_addr.c
+ ${PICO_LWIP_PATH}/src/core/ipv6/ip6_frag.c
+ ${PICO_LWIP_PATH}/src/core/ipv6/mld6.c
+ ${PICO_LWIP_PATH}/src/core/ipv6/nd6.c
+ )
+
+ # APIFILES: The files which implement the sequential and socket APIs.
+ add_library(pico_lwip_api INTERFACE)
+ target_sources(pico_lwip_api INTERFACE
+ ${PICO_LWIP_PATH}/src/api/api_lib.c
+ ${PICO_LWIP_PATH}/src/api/api_msg.c
+ ${PICO_LWIP_PATH}/src/api/err.c
+ ${PICO_LWIP_PATH}/src/api/if_api.c
+ ${PICO_LWIP_PATH}/src/api/netbuf.c
+ ${PICO_LWIP_PATH}/src/api/netdb.c
+ ${PICO_LWIP_PATH}/src/api/netifapi.c
+ ${PICO_LWIP_PATH}/src/api/sockets.c
+ ${PICO_LWIP_PATH}/src/api/tcpip.c
+ )
+
+ # Files implementing various generic network interface functions
+ add_library(pico_lwip_netif INTERFACE)
+ target_sources(pico_lwip_netif INTERFACE
+ ${PICO_LWIP_PATH}/src/netif/ethernet.c
+ ${PICO_LWIP_PATH}/src/netif/bridgeif.c
+ ${PICO_LWIP_PATH}/src/netif/bridgeif_fdb.c
+ ${PICO_LWIP_PATH}/src/netif/slipif.c
+ )
+
+ # 6LoWPAN
+ add_library(pico_lwip_sixlowpan INTERFACE)
+ target_sources(pico_lwip_sixlowpan INTERFACE
+ ${PICO_LWIP_PATH}/src/netif/lowpan6_common.c
+ ${PICO_LWIP_PATH}/src/netif/lowpan6.c
+ ${PICO_LWIP_PATH}/src/netif/lowpan6_ble.c
+ ${PICO_LWIP_PATH}/src/netif/zepif.c
+ )
+
+ # PPP
+ add_library(pico_lwip_ppp INTERFACE)
+ target_sources(pico_lwip_ppp INTERFACE
+ ${PICO_LWIP_PATH}/src/netif/ppp/auth.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/ccp.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/chap-md5.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/chap_ms.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/chap-new.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/demand.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/eap.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/ecp.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/eui64.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/fsm.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/ipcp.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/ipv6cp.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/lcp.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/magic.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/mppe.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/multilink.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/ppp.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/pppapi.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/pppcrypt.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/pppoe.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/pppol2tp.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/pppos.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/upap.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/utils.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/vj.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/polarssl/arc4.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/polarssl/des.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/polarssl/md4.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/polarssl/md5.c
+ ${PICO_LWIP_PATH}/src/netif/ppp/polarssl/sha1.c
+ )
+
+ # SNMPv3 agent
+ add_library(pico_lwip_snmp INTERFACE)
+ target_sources(pico_lwip_snmp INTERFACE
+ ${PICO_LWIP_PATH}/src/apps/snmp/snmp_asn1.c
+ ${PICO_LWIP_PATH}/src/apps/snmp/snmp_core.c
+ ${PICO_LWIP_PATH}/src/apps/snmp/snmp_mib2.c
+ ${PICO_LWIP_PATH}/src/apps/snmp/snmp_mib2_icmp.c
+ ${PICO_LWIP_PATH}/src/apps/snmp/snmp_mib2_interfaces.c
+ ${PICO_LWIP_PATH}/src/apps/snmp/snmp_mib2_ip.c
+ ${PICO_LWIP_PATH}/src/apps/snmp/snmp_mib2_snmp.c
+ ${PICO_LWIP_PATH}/src/apps/snmp/snmp_mib2_system.c
+ ${PICO_LWIP_PATH}/src/apps/snmp/snmp_mib2_tcp.c
+ ${PICO_LWIP_PATH}/src/apps/snmp/snmp_mib2_udp.c
+ ${PICO_LWIP_PATH}/src/apps/snmp/snmp_snmpv2_framework.c
+ ${PICO_LWIP_PATH}/src/apps/snmp/snmp_snmpv2_usm.c
+ ${PICO_LWIP_PATH}/src/apps/snmp/snmp_msg.c
+ ${PICO_LWIP_PATH}/src/apps/snmp/snmpv3.c
+ ${PICO_LWIP_PATH}/src/apps/snmp/snmp_netconn.c
+ ${PICO_LWIP_PATH}/src/apps/snmp/snmp_pbuf_stream.c
+ ${PICO_LWIP_PATH}/src/apps/snmp/snmp_raw.c
+ ${PICO_LWIP_PATH}/src/apps/snmp/snmp_scalar.c
+ ${PICO_LWIP_PATH}/src/apps/snmp/snmp_table.c
+ ${PICO_LWIP_PATH}/src/apps/snmp/snmp_threadsync.c
+ ${PICO_LWIP_PATH}/src/apps/snmp/snmp_traps.c
+ )
+
+ # HTTP server + client
+ add_library(pico_lwip_http INTERFACE)
+ target_sources(pico_lwip_http INTERFACE
+ ${PICO_LWIP_PATH}/src/apps/http/altcp_proxyconnect.c
+ ${PICO_LWIP_PATH}/src/apps/http/fs.c
+ ${PICO_LWIP_PATH}/src/apps/http/http_client.c
+ ${PICO_LWIP_PATH}/src/apps/http/httpd.c
+ )
+
+ # MAKEFSDATA HTTP server host utility
+ add_library(pico_lwip_makefsdata INTERFACE)
+ target_sources(pico_lwip_makefsdata INTERFACE
+ ${PICO_LWIP_PATH}/src/apps/http/makefsdata/makefsdata.c
+ )
+
+ # iperf
+ add_library(pico_lwip_iperf INTERFACE)
+ target_sources(pico_lwip_iperf INTERFACE
+ ${PICO_LWIP_PATH}/src/apps/lwiperf/lwiperf.c
+ )
+
+ # SMTP client
+ add_library(pico_lwip_smtp INTERFACE)
+ target_sources(pico_lwip_smtp INTERFACE
+ ${PICO_LWIP_PATH}/src/apps/smtp/smtp.c
+ )
+
+ # SNTP client
+ add_library(pico_lwip_sntp INTERFACE)
+ target_sources(pico_lwip_sntp INTERFACE
+ ${PICO_LWIP_PATH}/src/apps/sntp/sntp.c
+ )
+
+ # MDNS responder
+ add_library(pico_lwip_mdns INTERFACE)
+ target_sources(pico_lwip_mdns INTERFACE
+ ${PICO_LWIP_PATH}/src/apps/mdns/mdns.c
+ ${PICO_LWIP_PATH}/src/apps/mdns/mdns_out.c
+ ${PICO_LWIP_PATH}/src/apps/mdns/mdns_domain.c
+ )
+
+ # NetBIOS name server
+ add_library(pico_lwip_netbios INTERFACE)
+ target_sources(pico_lwip_netbios INTERFACE
+ ${PICO_LWIP_PATH}/src/apps/netbiosns/netbiosns.c
+ )
+
+ # TFTP server files
+ add_library(pico_lwip_tftp INTERFACE)
+ target_sources(pico_lwip_tftp INTERFACE
+ ${PICO_LWIP_PATH}/src/apps/tftp/tftp.c
+ )
+
+ # MQTT client files
+ add_library(pico_lwip_mbedtls INTERFACE)
+ target_sources(pico_lwip_mbedtls INTERFACE
+ ${PICO_LWIP_PATH}/src/apps/altcp_tls/altcp_tls_mbedtls.c
+ ${PICO_LWIP_PATH}/src/apps/altcp_tls/altcp_tls_mbedtls_mem.c
+ ${PICO_LWIP_PATH}/src/apps/snmp/snmpv3_mbedtls.c
+ )
+
+
+ # All LWIP files without apps
+ add_library(pico_lwip INTERFACE)
+ target_link_libraries(pico_lwip INTERFACE
+ pico_lwip_core
+ pico_lwip_core4
+ pico_lwip_core6
+ pico_lwip_api
+ pico_lwip_netif
+ pico_lwip_sixlowpan
+ pico_lwip_ppp
+ )
+
+ # our arch/cc.h
+ add_library(pico_lwip_arch INTERFACE)
+ target_include_directories(pico_lwip_arch INTERFACE
+ ${CMAKE_CURRENT_LIST_DIR}/include)
+
+ # our nosys impl
+ add_library(pico_lwip_nosys INTERFACE)
+ target_sources(pico_lwip_nosys INTERFACE
+ ${CMAKE_CURRENT_LIST_DIR}/nosys.c
+ )
+ target_link_libraries(pico_lwip_nosys INTERFACE
+ pico_lwip_arch)
+
+
+ if (NOT PICO_LWIP_CONTRIB_PATH)
+ set(PICO_LWIP_CONTRIB_PATH ${PICO_LWIP_PATH}/contrib)
+ endif()
+ pico_register_common_scope_var(PICO_LWIP_CONTRIB_PATH)
+
+ # Make lwip_contrib_freertos library, with the FreeRTOS/lwIP code from lwip-contrib
+ add_library(pico_lwip_contrib_freertos INTERFACE)
+ target_sources(pico_lwip_contrib_freertos INTERFACE
+ ${PICO_LWIP_CONTRIB_PATH}/ports/freertos/sys_arch.c
+ )
+ target_include_directories(pico_lwip_contrib_freertos INTERFACE
+ ${PICO_LWIP_CONTRIB_PATH}/ports/freertos/include
+ )
+ target_link_libraries(pico_lwip_contrib_freertos INTERFACE
+ pico_lwip_arch)
+
+ pico_promote_common_scope_vars()
+endif()
diff --git a/src/rp2_common/pico_lwip/doc.h b/src/rp2_common/pico_lwip/doc.h
new file mode 100644
index 0000000..ede60b6
--- /dev/null
+++ b/src/rp2_common/pico_lwip/doc.h
@@ -0,0 +1,44 @@
+/**
+ * \defgroup pico_lwip pico_lwip
+ * \brief Wrapper libraries for <a href="https://savannah.nongnu.org/projects/lwip/lwIP">lwIP</a>
+ *
+ * The following libraries are provided that contain the equivalent lwIP functionality groups:
+ *
+ * * \c \b pico_lwip_core -
+ * * \c \b pico_lwip_core4 -
+ * * \c \b pico_lwip_core6 -
+ * * \c \b pico_lwip_netif -
+ * * \c \b pico_lwip_sixlowpan -
+ * * \c \b pico_lwip_ppp -
+ * * \c \b pico_lwip_api -
+ *
+ * The following libraries are provided that contain the equivalent lwIP application support:
+ *
+ * * \c \b pico_lwip_snmp -
+ * * \c \b pico_lwip_http -
+ * * \c \b pico_lwip_makefsdata -
+ * * \c \b pico_lwip_iperf -
+ * * \c \b pico_lwip_smtp -
+ * * \c \b pico_lwip_sntp -
+ * * \c \b pico_lwip_mdns -
+ * * \c \b pico_lwip_netbios -
+ * * \c \b pico_lwip_tftp -
+ * * \c \b pico_lwip_mbedtls -
+ *
+ * The SDK Provides a common set of functionality in \c \p pico_lwip which aggregates:
+ *
+ * * \c \b pico_lwip_core -
+ * * \c \b pico_lwip_core4 -
+ * * \c \b pico_lwip_core6 -
+ * * \c \b pico_lwip_netif -
+ * * \c \b pico_lwip_sixlowpan -
+ * * \c \b pico_lwip_ppp -
+ *
+ * The following additional libraries are provided:
+ *
+ * * \c \b pico_lwip - Aggregates the lwIP RAW API: \c \b pico_lwip_core, \c \b pico_lwip_core4, \c \b pico_lwip_core6, \c \b pico_lwip_api, \c \b pico_lwip_netif, \c \b pico_lwip_sixlowpan and \c \b pico_lwip_ppp. It does
+ * not include \c \b pico_lwip_api, which requires NO_SYS=0. You should include the latter separately if you want it.
+ *
+ * * \c \b pico_lwip_arch - lwIP required compiler adapters. This is not included in \c \b pico_lwip in case you wish to replace them.
+ * * \c \b pico_lwip_nosys - basic stub functions for NO_SYS mode.
+ */
diff --git a/src/rp2_common/pico_lwip/include/arch/cc.h b/src/rp2_common/pico_lwip/include/arch/cc.h
new file mode 100644
index 0000000..447e4d2
--- /dev/null
+++ b/src/rp2_common/pico_lwip/include/arch/cc.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+#ifndef __CC_H__
+#define __CC_H__
+
+#if NO_SYS
+// todo really we should just not allow SYS_LIGHTWEIGHT_PROT for nosys mode (it doesn't do anything anyway)
+typedef int sys_prot_t;
+#endif
+
+/* define compiler specific symbols */
+#if defined (__ICCARM__)
+
+#define PACK_STRUCT_BEGIN
+#define PACK_STRUCT_STRUCT
+#define PACK_STRUCT_END
+#define PACK_STRUCT_FIELD(x) x
+#define PACK_STRUCT_USE_INCLUDES
+
+#elif defined (__CC_ARM)
+
+#define PACK_STRUCT_BEGIN __packed
+#define PACK_STRUCT_STRUCT
+#define PACK_STRUCT_END
+#define PACK_STRUCT_FIELD(x) x
+
+#elif defined (__GNUC__)
+
+#define PACK_STRUCT_BEGIN
+#define PACK_STRUCT_STRUCT __attribute__ ((__packed__))
+#define PACK_STRUCT_END
+#define PACK_STRUCT_FIELD(x) x
+
+#elif defined (__TASKING__)
+
+#define PACK_STRUCT_BEGIN
+#define PACK_STRUCT_STRUCT
+#define PACK_STRUCT_END
+#define PACK_STRUCT_FIELD(x) x
+
+#endif
+
+#define LWIP_PLATFORM_ASSERT(x) do { if(!(x)) while(1); } while(0)
+
+unsigned int pico_lwip_rand(void);
+#ifndef LWIP_RAND
+// Use ROSC based random number generation, more for the fact that rand() may not be seeded, than anything else
+#define LWIP_RAND pico_lwip_rand
+#endif
+#endif /* __CC_H__ */
diff --git a/src/rp2_common/pico_lwip/nosys.c b/src/rp2_common/pico_lwip/nosys.c
new file mode 100644
index 0000000..4e7605d
--- /dev/null
+++ b/src/rp2_common/pico_lwip/nosys.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "lwip/init.h"
+#include "pico/time.h"
+
+#if NO_SYS
+/* lwip has provision for using a mutex, when applicable */
+sys_prot_t sys_arch_protect(void) {
+ return 0;
+}
+
+void sys_arch_unprotect(sys_prot_t pval) {
+ (void) pval;
+}
+
+/* lwip needs a millisecond time source, and the TinyUSB board support code has one available */
+uint32_t sys_now(void) {
+ return to_ms_since_boot(get_absolute_time());
+}
+
+#endif
+
diff --git a/src/rp2_common/pico_lwip/random.c b/src/rp2_common/pico_lwip/random.c
new file mode 100644
index 0000000..2c4cdf8
--- /dev/null
+++ b/src/rp2_common/pico_lwip/random.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "pico.h"
+#include "hardware/structs/rosc.h"
+
+static uint8_t pico_lwip_random_byte(int cycles) {
+ static uint8_t byte;
+ assert(cycles >= 8);
+ assert(rosc_hw->status & ROSC_STATUS_ENABLED_BITS);
+ for(int i=0;i<cycles;i++) {
+ // picked a fairly arbitrary polynomial of 0x35u - this doesn't have to be crazily uniform.
+ byte = ((byte << 1) | rosc_hw->randombit) ^ (byte & 0x80u ? 0x35u : 0);
+ // delay a little because the random bit is a little slow
+ busy_wait_at_least_cycles(30);
+ }
+ return byte;
+}
+
+unsigned int pico_lwip_rand(void) {
+ uint32_t value = 0;
+ for (int i = 0; i < 4; i++) {
+ value = (value << 8u) | pico_lwip_random_byte(32);
+ }
+ return value;
+}
\ No newline at end of file
diff --git a/src/rp2_common/pico_malloc/CMakeLists.txt b/src/rp2_common/pico_malloc/CMakeLists.txt
index deeb30f..57ac267 100644
--- a/src/rp2_common/pico_malloc/CMakeLists.txt
+++ b/src/rp2_common/pico_malloc/CMakeLists.txt
@@ -10,6 +10,7 @@
pico_wrap_function(pico_malloc malloc)
pico_wrap_function(pico_malloc calloc)
+ pico_wrap_function(pico_malloc realloc)
pico_wrap_function(pico_malloc free)
target_link_libraries(pico_malloc INTERFACE pico_sync)
diff --git a/src/rp2_common/pico_malloc/pico_malloc.c b/src/rp2_common/pico_malloc/pico_malloc.c
index 4928a8e..a053986 100644
--- a/src/rp2_common/pico_malloc/pico_malloc.c
+++ b/src/rp2_common/pico_malloc/pico_malloc.c
@@ -16,6 +16,7 @@
extern void *__real_malloc(size_t size);
extern void *__real_calloc(size_t count, size_t size);
+extern void *__real_realloc(void *mem, size_t size);
extern void __real_free(void *mem);
extern char __StackLimit; /* Set by linker. */
@@ -62,6 +63,23 @@
return rc;
}
+void *__wrap_realloc(void *mem, size_t size) {
+#if PICO_USE_MALLOC_MUTEX
+ mutex_enter_blocking(&malloc_mutex);
+#endif
+ void *rc = __real_realloc(mem, size);
+#if PICO_USE_MALLOC_MUTEX
+ mutex_exit(&malloc_mutex);
+#endif
+#if PICO_DEBUG_MALLOC
+ if (!rc || ((uint8_t *)rc) + size > (uint8_t*)PICO_DEBUG_MALLOC_LOW_WATER) {
+ printf("realloc %p %d->%p\n", mem, (uint) size, rc);
+ }
+#endif
+ check_alloc(rc, size);
+ return rc;
+}
+
void __wrap_free(void *mem) {
#if PICO_USE_MALLOC_MUTEX
mutex_enter_blocking(&malloc_mutex);
diff --git a/src/rp2_common/pico_platform/include/pico/platform.h b/src/rp2_common/pico_platform/include/pico/platform.h
index ee1d360..1d9e1bc 100644
--- a/src/rp2_common/pico_platform/include/pico/platform.h
+++ b/src/rp2_common/pico_platform/include/pico/platform.h
@@ -17,6 +17,8 @@
*/
#include "hardware/platform_defs.h"
+#include "hardware/regs/addressmap.h"
+#include "hardware/regs/sio.h"
// Marker for builds targeting the RP2040
#define PICO_RP2040 1
@@ -233,7 +235,7 @@
* int __force_inline my_function(int x) {
*
*/
-#if defined(__GNUC__) && __GNUC__ <= 7
+#if defined(__GNUC__) && (__GNUC__ <= 6 || (__GNUC__ == 7 && (__GNUC_MINOR__ < 3 || !defined(__cplusplus))))
#define __force_inline inline __always_inline
#else
#define __force_inline __always_inline
@@ -334,13 +336,16 @@
* @return the RP2040 rom version number (1 for RP2040-B0, 2 for RP2040-B1, 3 for RP2040-B2)
*/
static inline uint8_t rp2040_rom_version(void) {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warray-bounds"
return *(uint8_t*)0x13;
+#pragma GCC diagnostic pop
}
/*! \brief No-op function for the body of tight loops
* \ingroup pico_platform
*
- * Np-op function intended to be called by any tight hardware polling loop. Using this ubiquitously
+ * No-op function intended to be called by any tight hardware polling loop. Using this ubiquitously
* makes it much easier to find tight loops, but also in the future \#ifdef-ed support for lockup
* debugging might be added
*/
@@ -400,6 +405,38 @@
}
#endif
+/*! \brief Helper method to busy-wait for at least the given number of cycles
+ * \ingroup pico_platform
+ *
+ * This method is useful for introducing very short delays.
+ *
+ * This method busy-waits in a tight loop for the given number of system clock cycles. The total wait time is only accurate to within 2 cycles,
+ * and this method uses a loop counter rather than a hardware timer, so the method will always take longer than expected if an
+ * interrupt is handled on the calling core during the busy-wait; you can of course disable interrupts to prevent this.
+ *
+ * You can use \ref clock_get_hz(clk_sys) to determine the number of clock cycles per second if you want to convert an actual
+ * time duration to a number of cycles.
+ *
+ * \param minimum_cycles the minimum number of system clock cycles to delay for
+ */
+static inline void busy_wait_at_least_cycles(uint32_t minimum_cycles) {
+ __asm volatile (
+ ".syntax unified\n"
+ "1: subs %0, #3\n"
+ "bcs 1b\n"
+ : "+r" (minimum_cycles) : : "memory"
+ );
+}
+
+/*! \brief Get the current core number
+ * \ingroup pico_platform
+ *
+ * \return The core number the call was made from
+ */
+__force_inline static uint get_core_num(void) {
+ return (*(uint32_t *) (SIO_BASE + SIO_CPUID_OFFSET));
+}
+
#else // __ASSEMBLER__
#define WRAPPER_FUNC_NAME(x) __wrap_##x
diff --git a/src/rp2_common/pico_runtime/runtime.c b/src/rp2_common/pico_runtime/runtime.c
index 575e23e..70dd3bb 100644
--- a/src/rp2_common/pico_runtime/runtime.c
+++ b/src/rp2_common/pico_runtime/runtime.c
@@ -175,7 +175,7 @@
}
-void _exit(__unused int status) {
+void __attribute__((noreturn)) _exit(__unused int status) {
#if PICO_ENTER_USB_BOOT_ON_EXIT
reset_usb_boot(0,0);
#else
diff --git a/src/rp2_common/pico_standard_link/crt0.S b/src/rp2_common/pico_standard_link/crt0.S
index f57ddfd..b2992f6 100644
--- a/src/rp2_common/pico_standard_link/crt0.S
+++ b/src/rp2_common/pico_standard_link/crt0.S
@@ -225,6 +225,9 @@
cmp r0, #0
bne hold_non_core0_in_bootrom
+ // In a NO_FLASH binary, don't perform .data copy, since it's loaded
+ // in-place by the SRAM load. Still need to clear .bss
+#if !PICO_NO_FLASH
adr r4, data_cpy_table
// assume there is at least one entry
@@ -235,6 +238,7 @@
bl data_cpy
b 1b
2:
+#endif
// Zero out the BSS
ldr r1, =__bss_start__
@@ -266,6 +270,7 @@
bkpt #0
b 1b
+#if !PICO_NO_FLASH
data_cpy_loop:
ldm r1!, {r0}
stm r2!, {r0}
@@ -273,6 +278,10 @@
cmp r2, r3
blo data_cpy_loop
bx lr
+#endif
+
+// Note the data copy table is still included for NO_FLASH builds, even though
+// we skip the copy, because it is listed in binary info
.align 2
data_cpy_table:
diff --git a/src/rp2_common/pico_stdio/stdio.c b/src/rp2_common/pico_stdio/stdio.c
index b457b8a..52a1c0c 100644
--- a/src/rp2_common/pico_stdio/stdio.c
+++ b/src/rp2_common/pico_stdio/stdio.c
@@ -29,6 +29,10 @@
#include "pico/stdio_semihosting.h"
#endif
+#define STDIO_HANDLE_STDIN 0
+#define STDIO_HANDLE_STDOUT 1
+#define STDIO_HANDLE_STDERR 2
+
static stdio_driver_t *drivers;
static stdio_driver_t *filter;
@@ -131,11 +135,13 @@
}
}
}
+ if (time_reached(until)) {
+ return PICO_ERROR_TIMEOUT;
+ }
// we sleep here in case the in_chars methods acquire mutexes or disable IRQs and
// potentially starve out what they are waiting on (have seen this with USB)
busy_wait_us(1);
- } while (!time_reached(until));
- return PICO_ERROR_TIMEOUT;
+ } while (true);
}
int WRAPPER_FUNC(putchar)(int c) {
@@ -165,14 +171,14 @@
}
int _read(int handle, char *buffer, int length) {
- if (handle == 0) {
+ if (handle == STDIO_HANDLE_STDIN) {
return stdio_get_until(buffer, length, at_the_end_of_time);
}
return -1;
}
int _write(int handle, char *buffer, int length) {
- if (handle == 1) {
+ if (handle == STDIO_HANDLE_STDOUT || handle == STDIO_HANDLE_STDERR) {
stdio_put_string(buffer, length, false, false);
return length;
}
@@ -180,20 +186,19 @@
}
void stdio_set_driver_enabled(stdio_driver_t *driver, bool enable) {
- stdio_driver_t *prev = drivers;
- for (stdio_driver_t *d = drivers; d; d = d->next) {
- if (d == driver) {
+ stdio_driver_t **prev = &drivers;
+ while (*prev) {
+ if (*prev == driver) {
if (!enable) {
- prev->next = d->next;
+ *prev = driver->next;
driver->next = NULL;
}
return;
}
- prev = d;
+ prev = &(*prev)->next;
}
if (enable) {
- if (prev) prev->next = driver;
- else drivers = driver;
+ *prev = driver;
}
}
diff --git a/src/rp2_common/pico_stdio_semihosting/include/pico/stdio_semihosting.h b/src/rp2_common/pico_stdio_semihosting/include/pico/stdio_semihosting.h
index 3304368..ca66417 100644
--- a/src/rp2_common/pico_stdio_semihosting/include/pico/stdio_semihosting.h
+++ b/src/rp2_common/pico_stdio_semihosting/include/pico/stdio_semihosting.h
@@ -13,7 +13,7 @@
* \defgroup pico_stdio_semihosting pico_stdio_semihosting
* \ingroup pico_stdio
*
- * Linking this library or calling `pico_enable_stdio_semihosting(TARGET)` in the CMake (which
+ * Linking this library or calling `pico_enable_stdio_semihosting(TARGET ENABLED)` in the CMake (which
* achieves the same thing) will add semihosting to the drivers used for standard output
*/
diff --git a/src/rp2_common/pico_stdio_uart/include/pico/stdio_uart.h b/src/rp2_common/pico_stdio_uart/include/pico/stdio_uart.h
index 5afe910..9e5ac53 100644
--- a/src/rp2_common/pico_stdio_uart/include/pico/stdio_uart.h
+++ b/src/rp2_common/pico_stdio_uart/include/pico/stdio_uart.h
@@ -14,8 +14,8 @@
* \defgroup pico_stdio_uart pico_stdio_uart
* \ingroup pico_stdio
*
- * Linking this library or calling `pico_enable_stdio_uart(TARGET)` in the CMake (which
- * achieves the same thing) will add UART to the drivers used for standard output
+ * Linking this library or calling `pico_enable_stdio_uart(TARGET ENABLED)` in the CMake (which
+ * achieves the same thing) will add UART to the drivers used for standard input/output
*/
// PICO_CONFIG: PICO_STDIO_UART_DEFAULT_CRLF, Default state of CR/LF translation for UART output, type=bool, default=PICO_STDIO_DEFAULT_CRLF, group=pico_stdio_uart
diff --git a/src/rp2_common/pico_stdio_usb/include/pico/stdio_usb.h b/src/rp2_common/pico_stdio_usb/include/pico/stdio_usb.h
index 2aeb647..8ac8244 100644
--- a/src/rp2_common/pico_stdio_usb/include/pico/stdio_usb.h
+++ b/src/rp2_common/pico_stdio_usb/include/pico/stdio_usb.h
@@ -13,8 +13,8 @@
* \defgroup pico_stdio_usb pico_stdio_usb
* \ingroup pico_stdio
*
- * Linking this library or calling `pico_enable_stdio_usb(TARGET)` in the CMake (which
- * achieves the same thing) will add USB CDC to the drivers used for standard output
+ * Linking this library or calling `pico_enable_stdio_usb(TARGET ENABLED)` in the CMake (which
+ * achieves the same thing) will add USB CDC to the drivers used for standard input/output
*
* Note this library is a developer convenience. It is not applicable in all cases; for one it takes full control of the USB device precluding your
* use of the USB in device or host mode. For this reason, this library will automatically disengage if you try to using it alongside \ref tinyusb_device or
@@ -39,9 +39,9 @@
#define PICO_STDIO_USB_TASK_INTERVAL_US 1000
#endif
-// PICO_CONFIG: PICO_STDIO_USB_LOW_PRIORITY_IRQ, low priority (non hardware) IRQ number to claim for tud_task() background execution, default=31, advanced=true, group=pico_stdio_usb
+// PICO_CONFIG: PICO_STDIO_USB_LOW_PRIORITY_IRQ, Explicit User IRQ number to claim for tud_task() background execution instead of letting the implementation pick a free one dynamically (deprecated), advanced=true, group=pico_stdio_usb
#ifndef PICO_STDIO_USB_LOW_PRIORITY_IRQ
-#define PICO_STDIO_USB_LOW_PRIORITY_IRQ 31
+// this variable is no longer set by default (one is claimed dynamically), but will be respected if specified
#endif
// PICO_CONFIG: PICO_STDIO_USB_ENABLE_RESET_VIA_BAUD_RATE, Enable/disable resetting into BOOTSEL mode if the host sets the baud rate to a magic value (PICO_STDIO_USB_RESET_MAGIC_BAUD_RATE), type=bool, default=1, group=pico_stdio_usb
diff --git a/src/rp2_common/pico_stdio_usb/include/tusb_config.h b/src/rp2_common/pico_stdio_usb/include/tusb_config.h
index c0a2843..c0d2ed3 100644
--- a/src/rp2_common/pico_stdio_usb/include/tusb_config.h
+++ b/src/rp2_common/pico_stdio_usb/include/tusb_config.h
@@ -29,6 +29,7 @@
#include "pico/stdio_usb.h"
+#if !defined(LIB_TINYUSB_HOST) && !defined(LIB_TINYUSB_DEVICE)
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE)
#define CFG_TUD_CDC (1)
@@ -38,3 +39,5 @@
// We use a vendor specific interface but with our own driver
#define CFG_TUD_VENDOR (0)
#endif
+
+#endif
diff --git a/src/rp2_common/pico_stdio_usb/reset_interface.c b/src/rp2_common/pico_stdio_usb/reset_interface.c
index 06dce86..cc25177 100644
--- a/src/rp2_common/pico_stdio_usb/reset_interface.c
+++ b/src/rp2_common/pico_stdio_usb/reset_interface.c
@@ -7,6 +7,8 @@
#include "pico/bootrom.h"
+#if !defined(LIB_TINYUSB_HOST) && !defined(LIB_TINYUSB_DEVICE)
+
#if PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE && !(PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_BOOTSEL || PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_FLASH_BOOT)
#warning PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE has been selected but neither PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_BOOTSEL nor PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_FLASH_BOOT have been selected.
#endif
@@ -110,3 +112,4 @@
}
#endif
+#endif
\ No newline at end of file
diff --git a/src/rp2_common/pico_stdio_usb/stdio_usb.c b/src/rp2_common/pico_stdio_usb/stdio_usb.c
index 913d606..cd2e2c9 100644
--- a/src/rp2_common/pico_stdio_usb/stdio_usb.c
+++ b/src/rp2_common/pico_stdio_usb/stdio_usb.c
@@ -4,17 +4,33 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-#if !defined(LIB_TINYUSB_HOST) && !defined(LIB_TINYUSB_DEVICE)
+#ifndef LIB_TINYUSB_HOST
#include "tusb.h"
+#include "pico/stdio_usb.h"
+// these may not be set if the user is providing tud support (i.e. LIB_TINYUSB_DEVICE is 1 because
+// the user linked in tinyusb_device) but they haven't selected CDC
+#if (CFG_TUD_ENABLED | TUSB_OPT_DEVICE_ENABLED) && CFG_TUD_CDC
+
+#include "pico/binary_info.h"
#include "pico/time.h"
#include "pico/stdio/driver.h"
-#include "pico/binary_info.h"
#include "pico/mutex.h"
#include "hardware/irq.h"
-static_assert(PICO_STDIO_USB_LOW_PRIORITY_IRQ > RTC_IRQ, ""); // note RTC_IRQ is currently the last one
static mutex_t stdio_usb_mutex;
+#ifndef NDEBUG
+static uint8_t stdio_usb_core_num;
+#endif
+
+// when tinyusb_device is explicitly linked we do no background tud processing
+#if !LIB_TINYUSB_DEVICE
+#ifdef PICO_STDIO_USB_LOW_PRIORITY_IRQ
+static_assert(PICO_STDIO_USB_LOW_PRIORITY_IRQ >= NUM_IRQS - NUM_USER_IRQS, "");
+#define low_priority_irq_num PICO_STDIO_USB_LOW_PRIORITY_IRQ
+#else
+static uint8_t low_priority_irq_num;
+#endif
static void low_priority_worker_irq(void) {
// if the mutex is already owned, then we are in user code
@@ -26,10 +42,16 @@
}
}
+static void usb_irq(void) {
+ irq_set_pending(low_priority_irq_num);
+}
+
static int64_t timer_task(__unused alarm_id_t id, __unused void *user_data) {
- irq_set_pending(PICO_STDIO_USB_LOW_PRIORITY_IRQ);
+ assert(stdio_usb_core_num == get_core_num()); // if this fails, you have initialized stdio_usb on the wrong core
+ irq_set_pending(low_priority_irq_num);
return PICO_STDIO_USB_TASK_INTERVAL_US;
}
+#endif
static void stdio_usb_out_chars(const char *buf, int length) {
static uint64_t last_avail_time;
@@ -89,18 +111,38 @@
};
bool stdio_usb_init(void) {
+#ifndef NDEBUG
+ stdio_usb_core_num = (uint8_t)get_core_num();
+#endif
#if !PICO_NO_BI_STDIO_USB
bi_decl_if_func_used(bi_program_feature("USB stdin / stdout"));
#endif
- // initialize TinyUSB
+#if !defined(LIB_TINYUSB_DEVICE)
+ // initialize TinyUSB, as user hasn't explicitly linked it
tusb_init();
-
- irq_set_exclusive_handler(PICO_STDIO_USB_LOW_PRIORITY_IRQ, low_priority_worker_irq);
- irq_set_enabled(PICO_STDIO_USB_LOW_PRIORITY_IRQ, true);
+#else
+ assert(tud_inited()); // we expect the caller to have initialized if they are using TinyUSB
+#endif
mutex_init(&stdio_usb_mutex);
- bool rc = add_alarm_in_us(PICO_STDIO_USB_TASK_INTERVAL_US, timer_task, NULL, true);
+ bool rc = true;
+#if !LIB_TINYUSB_DEVICE
+#ifdef PICO_STDIO_USB_LOW_PRIORITY_IRQ
+ user_irq_claim(PICO_STDIO_USB_LOW_PRIORITY_IRQ);
+#else
+ low_priority_irq_num = (uint8_t) user_irq_claim_unused(true);
+#endif
+ irq_set_exclusive_handler(low_priority_irq_num, low_priority_worker_irq);
+ irq_set_enabled(low_priority_irq_num, true);
+
+ if (irq_has_shared_handler(USBCTRL_IRQ)) {
+ // we can use a shared handler to notice when there may be work to do
+ irq_add_shared_handler(USBCTRL_IRQ, usb_irq, PICO_SHARED_IRQ_HANDLER_LOWEST_ORDER_PRIORITY);
+ } else {
+ rc = add_alarm_in_us(PICO_STDIO_USB_TASK_INTERVAL_US, timer_task, NULL, true);
+ }
+#endif
if (rc) {
stdio_set_driver_enabled(&stdio_usb, true);
#if PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS
@@ -127,9 +169,15 @@
return tud_cdc_connected();
}
#else
-#include "pico/stdio_usb.h"
-#warning stdio USB was configured, but is being disabled as TinyUSB is explicitly linked
+#warning stdio USB was configured along with user use of TinyUSB device mode, but CDC is not enabled
bool stdio_usb_init(void) {
return false;
}
-#endif
+#endif // CFG_TUD_ENABLED && CFG_TUD_CDC
+#else
+#warning stdio USB was configured, but is being disabled as TinyUSB host is explicitly linked
+bool stdio_usb_init(void) {
+ return false;
+}
+#endif // !LIB_TINYUSB_HOST
+
diff --git a/src/rp2_common/pico_stdlib/stdlib.c b/src/rp2_common/pico_stdlib/stdlib.c
index 7c9854e..159095c 100644
--- a/src/rp2_common/pico_stdlib/stdlib.c
+++ b/src/rp2_common/pico_stdlib/stdlib.c
@@ -73,7 +73,7 @@
uint crystal_freq_khz = clock_get_hz(clk_ref) / 1000;
for (uint fbdiv = 320; fbdiv >= 16; fbdiv--) {
uint vco = fbdiv * crystal_freq_khz;
- if (vco < 400000 || vco > 1600000) continue;
+ if (vco < PICO_PLL_VCO_MIN_FREQ_MHZ * 1000 || vco > PICO_PLL_VCO_MAX_FREQ_MHZ * 1000) continue;
for (uint postdiv1 = 7; postdiv1 >= 1; postdiv1--) {
for (uint postdiv2 = postdiv1; postdiv2 >= 1; postdiv2--) {
uint out = vco / (postdiv1 * postdiv2);
diff --git a/src/rp2_common/tinyusb/CMakeLists.txt b/src/rp2_common/tinyusb/CMakeLists.txt
index 80a6e78..8978788 100644
--- a/src/rp2_common/tinyusb/CMakeLists.txt
+++ b/src/rp2_common/tinyusb/CMakeLists.txt
@@ -45,5 +45,14 @@
pico_add_impl_library(tinyusb_board)
target_link_libraries(tinyusb_board INTERFACE tinyusb_bsp)
+ # Override suppress_tinyusb_warnings to add suppression of (falsely) reported GCC 11.2 warnings
+ function(suppress_tinyusb_warnings)
+ _suppress_tinyusb_warnings()
+ set_source_files_properties(
+ ${PICO_TINYUSB_PATH}/src/portable/raspberrypi/rp2040/rp2040_usb.c
+ PROPERTIES
+ COMPILE_FLAGS "-Wno-stringop-overflow -Wno-array-bounds")
+ endfunction()
+
pico_promote_common_scope_vars()
endif()
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 7ed2a00..a61388a 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -6,6 +6,8 @@
if (PICO_ON_DEVICE)
add_subdirectory(pico_float_test)
add_subdirectory(kitchen_sink)
+ add_subdirectory(hardware_irq_test)
add_subdirectory(hardware_pwm_test)
add_subdirectory(cmsis_test)
-endif()
\ No newline at end of file
+ add_subdirectory(pico_sem_test)
+endif()
diff --git a/test/hardware_irq_test/CMakeLists.txt b/test/hardware_irq_test/CMakeLists.txt
new file mode 100644
index 0000000..90ef50a
--- /dev/null
+++ b/test/hardware_irq_test/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_executable(hardware_irq_test hardware_irq_test.c)
+
+target_link_libraries(hardware_irq_test PRIVATE pico_test hardware_irq hardware_dma)
+pico_add_extra_outputs(hardware_irq_test)
\ No newline at end of file
diff --git a/test/hardware_irq_test/hardware_irq_test.c b/test/hardware_irq_test/hardware_irq_test.c
new file mode 100644
index 0000000..ed46a32
--- /dev/null
+++ b/test/hardware_irq_test/hardware_irq_test.c
@@ -0,0 +1,282 @@
+/**
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include "pico/stdlib.h"
+#include "pico/test.h"
+#include "pico/time.h"
+#include "hardware/irq.h"
+#include "hardware/dma.h"
+#include "hardware/structs/scb.h"
+
+PICOTEST_MODULE_NAME("IRQ", "IRQ Handler test");
+
+extern void __unhandled_user_irq(void);
+
+static bool remove_handler1_in_dma;
+static bool remove_handler2_in_dma;
+static bool remove_handler3_in_dma;
+static dma_channel_config config;
+
+#define MAX_FIRE_COUNT 4
+static int fire_count;
+static int fired[MAX_FIRE_COUNT];
+
+static uint32_t dma_to = 0;
+static uint32_t dma_from = 0xaaaa5555;
+
+int record_fire(int which) {
+ PICOTEST_CHECK(fire_count < MAX_FIRE_COUNT, "too many firings");
+ fired[fire_count++] = which;
+ return 0;
+}
+
+void __isr handler1(void) {
+ record_fire(1);
+ dma_channel_acknowledge_irq0(0);
+ if (remove_handler1_in_dma) {
+ irq_remove_handler(DMA_IRQ_0, handler1);
+ remove_handler1_in_dma = false;
+ }
+}
+
+void __isr handler2(void) {
+ record_fire(2);
+ dma_channel_acknowledge_irq0(0);
+ if (remove_handler2_in_dma) {
+ irq_remove_handler(DMA_IRQ_0, handler2);
+ remove_handler2_in_dma = false;
+ }
+}
+
+void __isr handler3(void) {
+ record_fire(3);
+ dma_channel_acknowledge_irq0(0);
+ if (remove_handler3_in_dma) {
+ irq_remove_handler(DMA_IRQ_0, handler3);
+ remove_handler3_in_dma = false;
+ }
+}
+
+static inline irq_handler_t *get_vtable(void) {
+ return (irq_handler_t *) scb_hw->vtor;
+}
+
+int dma_check(int expected, ...) {
+ if (expected == 0) {
+ // doing the DMA if there are no IRQ handlers will cause a hard fault, so we just check we are pointing at the handler which does this.
+ PICOTEST_CHECK_AND_ABORT(get_vtable()[16 + DMA_IRQ_0] == __unhandled_user_irq, "Expected there to be no IRQ handlers");
+ return 0;
+ }
+ fire_count = 0;
+ dma_channel_configure(0, &config, &dma_to, &dma_from, 1, true);
+ sleep_ms(100);
+ va_list args;
+ va_start(args, expected);
+ bool ok = expected == fire_count;
+ for(int i=0;ok && i<expected;i++) {
+ if (fired[i] != va_arg(args, int)) {
+ ok = false;
+ break;
+ }
+ }
+ va_end(args);
+ if (!ok) {
+ PICOTEST_CHECK(ok, "DMA handlers were not called in the order expected");
+ printf(" EXPECTED handlers: ");
+ va_start(args, expected);
+ for(int i=0;i<expected;i++) {
+ if (i) printf(", ");
+ printf("%d", va_arg(args, int));
+ }
+ printf("\n");
+ va_end(args);
+ printf(" CALLED handlers: ");
+ for(int i=0;i<fire_count;i++) {
+ if (i) printf(", ");
+ printf("%d", fired[i]);
+ }
+ printf("\n");
+ return -1;
+ }
+ return 0;
+}
+
+int main() {
+ stdio_init_all();
+
+ PICOTEST_START();
+ config = dma_channel_get_default_config(0);
+ dma_channel_set_irq0_enabled(0, true);
+ irq_set_enabled(DMA_IRQ_0, true);
+
+ // part I, just add/remove two handlers
+ PICOTEST_START_SECTION("I: Add handler1 default priority");
+ irq_add_shared_handler(DMA_IRQ_0, handler1, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
+ dma_check(1, 1);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("I: Add handler2 default priority");
+ irq_add_shared_handler(DMA_IRQ_0, handler2, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
+ dma_check(2, 2, 1);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("I: Remove handler1");
+ irq_remove_handler(DMA_IRQ_0, handler1);
+ dma_check(1, 2);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("I: Remove handler2");
+ irq_remove_handler(DMA_IRQ_0, handler2);
+ dma_check(0);
+ PICOTEST_END_SECTION();
+
+ // part II, add/remove three handlers including one in the middle
+
+ PICOTEST_START_SECTION("II: Add handler3 default priority");
+ irq_add_shared_handler(DMA_IRQ_0, handler3, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
+ dma_check(1, 3);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("II: Add handler2 default priority");
+ irq_add_shared_handler(DMA_IRQ_0, handler2, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
+ dma_check(2, 2, 3);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("II: Add handler1 default priority");
+ irq_add_shared_handler(DMA_IRQ_0, handler1, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
+ dma_check(3, 1, 2, 3);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("II: Remove handler2");
+ irq_remove_handler(DMA_IRQ_0, handler2);
+ dma_check(2, 1, 3);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("II: Remove handler3");
+ irq_remove_handler(DMA_IRQ_0, handler3);
+ dma_check(1, 1);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("II: Remove handler1");
+ irq_remove_handler(DMA_IRQ_0, handler1);
+ dma_check(0);
+ PICOTEST_END_SECTION();
+
+ // part III, the same as part II, but removing the handlers during the IRQ
+
+ PICOTEST_START_SECTION("III: Add handler3 default priority");
+ irq_add_shared_handler(DMA_IRQ_0, handler3, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
+ dma_check(1, 3);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("III: Add handler2 default priority");
+ irq_add_shared_handler(DMA_IRQ_0, handler2, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
+ dma_check(2, 2, 3);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("III: Add handler1 default priority");
+ irq_add_shared_handler(DMA_IRQ_0, handler1, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
+ dma_check(3, 1, 2, 3);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("III: Remove handler2");
+ remove_handler2_in_dma = true;
+ // note that this is the defined behavior, that any handlers after the removed handler are not called. the
+ // reasoning is that the same IRQ will immediately be re-entered, as we have missed clearing an interrupt (in whichever
+ // handlers were not called), and we will call any remaining handlers then. Because each IRQ handler is clearing the same
+ // interrupt handler in our case, this does not happen.
+ dma_check(2, 1, 2);
+ // but we call again to check
+ dma_check(2, 1, 3);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("III: Remove handler3");
+ remove_handler3_in_dma = true;
+ // note that this is the defined behavior, that any handlers after the removed handler are not called. the
+ // reasoning is that the same IRQ will immediately be re-entered, as we have missed clearing an interrupt (in whichever
+ // handlers were not called), and we will call any remaining handlers then. Because each IRQ handler is clearing the same
+ // interrupt handler in our case, this does not happen.
+ dma_check(2, 1, 3);
+ // but we call again to check
+ dma_check(1, 1);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("III: Remove handler3");
+ remove_handler1_in_dma = true;
+ // note that this is the defined behavior, that any handlers after the removed handler are not called. the
+ // reasoning is that the same IRQ will immediately be re-entered, as we have missed clearing an interrupt (in whichever
+ // handlers were not called), and we will call any remaining handlers then. Because each IRQ handler is clearing the same
+ // interrupt handler in our case, this does not happen.
+ dma_check(1, 1);
+ // but we call again to check
+ dma_check(0);
+ PICOTEST_END_SECTION();
+
+ // part IV, checking priorities
+ PICOTEST_START_SECTION("IV: Add handler1 high priority");
+ irq_add_shared_handler(DMA_IRQ_0, handler1, PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY);
+ dma_check(1, 1);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("IV: Add handler2 normal priority");
+ irq_add_shared_handler(DMA_IRQ_0, handler2, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
+ dma_check(2, 1, 2);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("IV: Add handler3 lowest priority");
+ irq_add_shared_handler(DMA_IRQ_0, handler3, PICO_SHARED_IRQ_HANDLER_LOWEST_ORDER_PRIORITY);
+ dma_check(3, 1, 2, 3);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("IV: Remove handler3");
+ irq_remove_handler(DMA_IRQ_0, handler3);
+ dma_check(2, 1, 2);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("IV: Add handler3 normal priority");
+ irq_add_shared_handler(DMA_IRQ_0, handler3, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
+ dma_check(3, 1, 3, 2);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("IV: Remove handler2");
+ irq_remove_handler(DMA_IRQ_0, handler2);
+ dma_check(2, 1, 3);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("IV: Add handler2 normal priority - 2");
+ irq_add_shared_handler(DMA_IRQ_0, handler2, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY - 2);
+ dma_check(3, 1, 3, 2);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("IV: Remove handler1");
+ irq_remove_handler(DMA_IRQ_0, handler1);
+ dma_check(2, 3, 2);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("IV: Add handler1 normal priority - 1");
+ irq_add_shared_handler(DMA_IRQ_0, handler1, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY - 1);
+ dma_check(3, 3, 1, 2);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("IV: Remove handler2 again");
+ irq_remove_handler(DMA_IRQ_0, handler2);
+ dma_check(2, 3, 1);
+
+ PICOTEST_END_SECTION();
+ PICOTEST_START_SECTION("IV: Remove handler3 again");
+ irq_remove_handler(DMA_IRQ_0, handler3);
+ dma_check(1, 1);
+ PICOTEST_END_SECTION();
+
+ PICOTEST_START_SECTION("IV: Remove handler1 again");
+ irq_remove_handler(DMA_IRQ_0, handler1);
+ dma_check(0);
+ PICOTEST_END_SECTION();
+ PICOTEST_END_TEST();
+}
+
diff --git a/test/hardware_pwm_test/hardware_pwm_test.c b/test/hardware_pwm_test/hardware_pwm_test.c
index ecd2c4d..aa5d5bb 100644
--- a/test/hardware_pwm_test/hardware_pwm_test.c
+++ b/test/hardware_pwm_test/hardware_pwm_test.c
@@ -82,25 +82,25 @@
pwm_set_both_levels(pwm, v + 1, v);
PICOTEST_CHECK_CHANNEL(pwm, slice->cc == (((v) << PWM_CH0_CC_B_LSB) | ((v + 1) << PWM_CH0_CC_A_LSB)),
- "pwm_set_compare() failed to set register");
+ "pwm_set_both_levels() failed to set register");
float divider = 100.5;
int i = (int16_t) divider;
int f = (int8_t) ((divider - i) * 16);
pwm_set_clkdiv(pwm, divider);
- PICOTEST_CHECK_CHANNEL(pwm, slice->div == (i << 4 | f), "pwm_set_divider_fract() failed to set register");
+ PICOTEST_CHECK_CHANNEL(pwm, slice->div == (i << 4 | f), "pwm_set_clkdiv() failed to set register");
i++;
pwm_set_clkdiv_int_frac(pwm, i, f);
PICOTEST_CHECK_CHANNEL(pwm, slice->div == (i << 4 | f),
- "pwm_set_divider_int_fract() failed to set register");
+ "pwm_set_clkdiv_int_frac() failed to set register");
int c = 1234;
pwm_set_counter(pwm, c);
- PICOTEST_CHECK_CHANNEL(pwm, slice->ctr == c, "pwm_set_count() failed to set register");
+ PICOTEST_CHECK_CHANNEL(pwm, slice->ctr == c, "pwm_set_counter() failed to set register");
int cc = pwm_get_counter(pwm);
- PICOTEST_CHECK_CHANNEL(pwm, slice->ctr == cc && cc == c, "pwm_get_count() failed to get register");
+ PICOTEST_CHECK_CHANNEL(pwm, slice->ctr == cc && cc == c, "pwm_get_counter() failed to get register");
pwm_set_output_polarity(pwm, false, false);
PICOTEST_CHECK_CHANNEL(pwm,
@@ -120,15 +120,15 @@
"pwm_set_output_polarity() (T/T)");
pwm_set_phase_correct(pwm, true);
- PICOTEST_CHECK_CHANNEL(pwm, (slice->csr & PWM_CH0_CSR_PH_CORRECT_BITS), "pwm_set_phase_correction(T)");
+ PICOTEST_CHECK_CHANNEL(pwm, (slice->csr & PWM_CH0_CSR_PH_CORRECT_BITS), "pwm_set_phase_correct(T)");
pwm_set_phase_correct(pwm, false);
- PICOTEST_CHECK_CHANNEL(pwm, !(slice->csr & PWM_CH0_CSR_PH_CORRECT_BITS), "pwm_set_phase_correction(F)");
+ PICOTEST_CHECK_CHANNEL(pwm, !(slice->csr & PWM_CH0_CSR_PH_CORRECT_BITS), "pwm_set_phase_correct(F)");
for (int m = PWM_DIV_FREE_RUNNING; m <= PWM_DIV_B_FALLING; m++) {
pwm_set_clkdiv_mode(pwm, m);
PICOTEST_CHECK_CHANNEL(pwm, ((slice->csr & PWM_CH0_CSR_DIVMODE_BITS) >> PWM_CH0_CSR_DIVMODE_LSB) == m,
- "pwm_set_divider_mode");
+ "pwm_set_clkdiv_mode");
}
}
PICOTEST_END_SECTION();
diff --git a/test/kitchen_sink/CMakeLists.txt b/test/kitchen_sink/CMakeLists.txt
index 024d42c..a201991 100644
--- a/test/kitchen_sink/CMakeLists.txt
+++ b/test/kitchen_sink/CMakeLists.txt
@@ -1,7 +1,4 @@
add_library(kitchen_sink_libs INTERFACE)
-target_sources(kitchen_sink_libs INTERFACE
- ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c
-)
target_link_libraries(kitchen_sink_libs INTERFACE
hardware_adc
hardware_clocks
@@ -44,11 +41,6 @@
pico_unique_id
pico_util
)
-# todo this is full of warnings atm
-#if (TARGET tinyusb_device)
-# target_include_directories(kitchen_sink_libs INTERFACE ${CMAKE_CURRENT_LIST_DIR})
-# target_link_libraries(kitchen_sink_libs INTERFACE tinyusb_device)
-#endif()
add_library(kitchen_sink_options INTERFACE)
@@ -66,7 +58,7 @@
-Wcast-qual
-Wfloat-equal
-Wmissing-format-attribute
- -Wconversion
+ #-Wconversion
-Wsign-compare
$<$<COMPILE_LANGUAGE:C>:-Wstrict-prototypes>
@@ -91,30 +83,63 @@
PICO_AUDIO_DMA_IRQ=1
)
-add_executable(kitchen_sink)
+add_executable(kitchen_sink ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c)
target_link_libraries(kitchen_sink kitchen_sink_libs kitchen_sink_options)
pico_set_program_name(kitchen_sink "Wombat tentacles")
pico_add_extra_outputs(kitchen_sink)
-add_executable(kitchen_sink_extra_stdio)
+add_executable(kitchen_sink_extra_stdio ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c)
if (COMMAND suppress_tinyusb_warnings)
# Explicitly suppress warnings in TinyUSB files which have them (this has to be done
# from the project that uses them per CMake "feature"). Note the function comes from
# TinyUSB itself, so we have to guard against TinyUSB not being present with the above if
suppress_tinyusb_warnings()
endif()
+if (TARGET pico_lwip)
+ set_source_files_properties(
+ ${PICO_LWIP_PATH}/src/core/ipv4/ip4_frag.c
+ PROPERTIES
+ COMPILE_FLAGS "-Wno-null-dereference")
+
+endif()
target_link_libraries(kitchen_sink_extra_stdio kitchen_sink_libs kitchen_sink_options)
pico_add_extra_outputs(kitchen_sink_extra_stdio)
pico_enable_stdio_usb(kitchen_sink_extra_stdio 1)
pico_enable_stdio_semihosting(kitchen_sink_extra_stdio 1)
-add_executable(kitchen_sink_copy_to_ram)
+add_executable(kitchen_sink_copy_to_ram ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c)
pico_set_binary_type(kitchen_sink_copy_to_ram copy_to_ram)
target_link_libraries(kitchen_sink_copy_to_ram kitchen_sink_libs kitchen_sink_options)
pico_add_extra_outputs(kitchen_sink_copy_to_ram)
-add_executable(kitchen_sink_no_flash)
+add_executable(kitchen_sink_no_flash ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c)
pico_set_binary_type(kitchen_sink_no_flash no_flash)
target_link_libraries(kitchen_sink_no_flash kitchen_sink_libs kitchen_sink_options)
pico_add_extra_outputs(kitchen_sink_no_flash)
+add_executable(kitchen_sink_cpp ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_cpp.cpp)
+target_link_libraries(kitchen_sink_cpp kitchen_sink_libs kitchen_sink_options)
+pico_set_program_name(kitchen_sink_cpp "Wombat tentacles CPP")
+pico_add_extra_outputs(kitchen_sink_cpp)
+
+if (TARGET pico_cyw43_arch)
+ # for lwipopts.h
+ add_executable(kitchen_sink_lwip_poll ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c)
+ target_link_libraries(kitchen_sink_lwip_poll kitchen_sink_libs kitchen_sink_options)
+ pico_add_extra_outputs(kitchen_sink_lwip_poll)
+ target_link_libraries(kitchen_sink_lwip_poll
+ pico_cyw43_arch_lwip_poll)
+ # for lwipopts.h
+ target_include_directories(kitchen_sink_lwip_poll PRIVATE
+ ${CMAKE_CURRENT_LIST_DIR})
+
+ add_executable(kitchen_sink_lwip_background ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c)
+ target_link_libraries(kitchen_sink_lwip_background kitchen_sink_libs kitchen_sink_options)
+ pico_add_extra_outputs(kitchen_sink_lwip_background)
+ target_link_libraries(kitchen_sink_lwip_background
+ pico_cyw43_arch_lwip_threadsafe_background)
+ # for lwipopts.h
+ target_include_directories(kitchen_sink_lwip_background PRIVATE
+ ${CMAKE_CURRENT_LIST_DIR})
+
+endif()
diff --git a/test/kitchen_sink/kitchen_sink.c b/test/kitchen_sink/kitchen_sink.c
index 57d4ef7..a49654d 100644
--- a/test/kitchen_sink/kitchen_sink.c
+++ b/test/kitchen_sink/kitchen_sink.c
@@ -47,6 +47,9 @@
#include "pico/sync.h"
#include "pico/time.h"
#include "pico/unique_id.h"
+#if LIB_PICO_CYW43_ARCH
+#include "pico/cyw43_arch.h"
+#endif
#include "hardware/structs/adc.h"
#include "hardware/structs/bus_ctrl.h"
@@ -97,7 +100,7 @@
uint32_t dma_to = 0;
uint32_t dma_from = 0xaaaa5555;
-void spiggle(void) {
+void __noinline spiggle(void) {
dma_channel_config c = dma_channel_get_default_config(1);
channel_config_set_bswap(&c, true);
channel_config_set_transfer_data_size(&c, DMA_SIZE_16);
@@ -106,57 +109,27 @@
dma_channel_transfer_from_buffer_now(1, foo, 23);
}
-void __isr dma_handler_a(void) {
- printf("HELLO A\n");
- if (dma_hw->ints1 & 1) {
- dma_hw->ints1 = 1;
- printf("A WINS DMA_TO %08x\n", (uint) dma_to);
- irq_remove_handler(DMA_IRQ_1, dma_handler_a);
- }
+__force_inline int something_inlined(int x) {
+ return x * 2;
}
-void __isr dma_handler_b(void) {
- printf("HELLO B\n");
- if (dma_hw->ints1 & 1) {
- dma_hw->ints1 = 1;
- printf("B WINS DMA_TO %08x\n", (uint) dma_to);
-// irq_remove_handler(DMA_IRQ_1, dma_handler_b);
- }
-}
-
-//#pragma GCC pop_options
+auto_init_mutex(mutex);
+auto_init_recursive_mutex(recursive_mutex);
int main(void) {
spiggle();
stdio_init_all();
- printf("HI %d\n", (int)time_us_32());
+ printf("HI %d\n", something_inlined((int)time_us_32()));
puts("Hello Everything!");
puts("Hello Everything2!");
- irq_add_shared_handler(DMA_IRQ_1, dma_handler_a, 0x80);
- irq_add_shared_handler(DMA_IRQ_1, dma_handler_b, 0xC0);
-
- dma_channel_config config = dma_channel_get_default_config(0);
-// set_exclusive_irq_handler(DMA_IRQ_1, dma_handler_a);
- dma_channel_set_irq1_enabled(0, true);
- irq_set_enabled(DMA_IRQ_1, true);
- dma_channel_configure(0, &config, &dma_to, &dma_from, 1, true);
- dma_channel_set_config(0, &config, false);
-
- // note this loop expects to cause a breakpoint!!
- for (int i = 0; i < 20; i++) {
- puts("sleepy");
- sleep_ms(1000);
- dma_channel_configure(0, &config, &dma_to, &dma_from, 1, true);
- if (i==3) {
- irq_remove_handler(DMA_IRQ_1, dma_handler_a);
- }
- if (i==2) {
- irq_remove_handler(DMA_IRQ_1, dma_handler_b);
- }
- }
+ hard_assert(mutex_try_enter(&mutex, NULL));
+ hard_assert(!mutex_try_enter(&mutex, NULL));
+ hard_assert(recursive_mutex_try_enter(&recursive_mutex, NULL));
+ hard_assert(recursive_mutex_try_enter(&recursive_mutex, NULL));
// this should compile as we are Cortex M0+
__asm volatile("SVC #3");
+
}
diff --git a/test/kitchen_sink/kitchen_sink_cpp.cpp b/test/kitchen_sink/kitchen_sink_cpp.cpp
new file mode 100644
index 0000000..1b4fe5a
--- /dev/null
+++ b/test/kitchen_sink/kitchen_sink_cpp.cpp
@@ -0,0 +1 @@
+#include "kitchen_sink.c"
\ No newline at end of file
diff --git a/test/kitchen_sink/lwipopts.h b/test/kitchen_sink/lwipopts.h
new file mode 100644
index 0000000..58b704a
--- /dev/null
+++ b/test/kitchen_sink/lwipopts.h
@@ -0,0 +1,14 @@
+#ifndef _LWIPOPTS_H
+#define _LWIPOPTS_H
+
+// dummy lwip opts to allow compilation
+
+#define NO_SYS 1
+#define LWIP_DHCP 1
+#define LWIP_RAW 1
+#define LWIP_NETIF_HOSTNAME 1
+#define LWIP_NETIF_STATUS_CALLBACK 1
+#define LWIP_DNS 1
+#define LWIP_SOCKET 0
+#define LWIP_NETCONN 0
+#endif
\ No newline at end of file
diff --git a/test/pico_float_test/pico_float_test.c b/test/pico_float_test/pico_float_test.c
index 5da23d2..73dfbc3 100644
--- a/test/pico_float_test/pico_float_test.c
+++ b/test/pico_float_test/pico_float_test.c
@@ -403,7 +403,7 @@
printf("FMODF %10.18f\n", check_close2(fmodf, x, 3.0f));
sincosf(x, &s, &c);
printf("SINCOS %10.18f %10.18f\n", s, c);
- if (s != sin(x) || c != cos(x)) {
+ if (s != sinf(x) || c != cosf(x)) {
printf("SINCOS mismatch\n");
fail = true;
}
diff --git a/test/pico_sem_test/CMakeLists.txt b/test/pico_sem_test/CMakeLists.txt
new file mode 100644
index 0000000..786963c
--- /dev/null
+++ b/test/pico_sem_test/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_executable(pico_sem_test pico_sem_test.c)
+
+target_link_libraries(pico_sem_test PRIVATE pico_test pico_sync)
+pico_add_extra_outputs(pico_sem_test)
diff --git a/test/pico_sem_test/pico_sem_test.c b/test/pico_sem_test/pico_sem_test.c
new file mode 100644
index 0000000..8647c19
--- /dev/null
+++ b/test/pico_sem_test/pico_sem_test.c
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdio.h>
+
+#include "pico/sem.h"
+#include "pico/test.h"
+#include "pico/stdio.h"
+
+PICOTEST_MODULE_NAME("SEM", "semaphore test");
+
+int main() {
+ semaphore_t sem;
+
+ stdio_init_all();
+ sem_init(&sem, 1, 1);
+
+ PICOTEST_START();
+
+ PICOTEST_START_SECTION("sem_try_acquire");
+ PICOTEST_CHECK(sem_try_acquire(&sem), "available permit not acquired");
+ PICOTEST_CHECK(!sem_try_acquire(&sem), "success with no permits");
+ PICOTEST_END_SECTION();
+
+ PICOTEST_END_TEST();
+}
diff --git a/test/pico_stdlib_test/pico_stdlib_test.c b/test/pico_stdlib_test/pico_stdlib_test.c
index 0adef83..ef955c1 100644
--- a/test/pico_stdlib_test/pico_stdlib_test.c
+++ b/test/pico_stdlib_test/pico_stdlib_test.c
@@ -8,11 +8,67 @@
#include <inttypes.h>
#include "pico/stdlib.h"
#include "pico/bit_ops.h"
+#include <stdlib.h>
+
+void test_builtin_bitops() {
+ int32_t x = 0;
+ for (uint32_t i = 0; i < 10000; i++) {
+ uint32_t vals32[] = {
+ i,
+ 1u << (i & 31u),
+ i * 12355821u,
+ };
+ uint64_t vals64[] = {
+ i,
+ 1ull << (i & 63u),
+ i * 12345678123125ull,
+ };
+ for(int j=0; j<count_of(vals32); j++) {
+ x += __builtin_popcount(vals32[j]);
+ x += __builtin_popcountl(vals32[j]);
+ x += (int32_t)__rev(vals32[j]);
+#if !PICO_ON_DEVICE
+ // the following functions are undefined on host mode, but on RP2040 we return 32
+ if (vals32[j]) {
+ x += __builtin_clz(vals32[j]);
+ x += __builtin_ctz(vals32[j]);
+ } else {
+ x += 64;
+ }
+#else
+ x += __builtin_clz(vals32[j]);
+ x += __builtin_ctz(vals32[j]);
+ // check l variants are the same
+ if (__builtin_clz(vals32[j]) != __builtin_clzl(vals32[j])) x += 17;
+ if (__builtin_ctz(vals32[j]) != __builtin_ctzl(vals32[j])) x += 23;
+#endif
+ }
+ for(int j=0; j<count_of(vals64); j++) {
+ x += __builtin_popcountll(vals64[j]);
+ x += (int32_t)__revll(vals64[j]);
+#if !PICO_ON_DEVICE
+ // the following functions are undefined on host mode, but on RP2040 we return 64
+ if (!vals64[j]) {
+ x += 128;
+ continue;
+ }
+#endif
+ x += __builtin_clzll(vals64[j]);
+ x += __builtin_ctzll(vals64[j]);
+ }
+ }
+ printf("Count is %d\n", (int)x);
+ int32_t expected = 1475508680;
+ if (x != expected) {
+ printf("FAILED (expected count %d\n", (int) expected);
+ exit(1);
+ }
+}
int main() {
setup_default_uart();
- puts("Hellox, worlxxcd!");
+ puts("Hellox, world!");
printf("Hello world %d\n", 2);
#if PICO_NO_HARDWARE
puts("This is native");
@@ -29,6 +85,8 @@
(unsigned long long) __revll(xl));
}
+ test_builtin_bitops();
+
for (int i = 0; i < 8; i++) {
sleep_ms(500);
printf( "%" PRIu64 "\n", to_us_since_boot(get_absolute_time()));
@@ -42,138 +100,3 @@
}
puts("DONE");
}
-
-void test1() {
- uint32_t x = 0;
- for (int i = 0; i < 1000; i++) {
- x += __builtin_popcount(i);
- x += __builtin_popcountl(i);
- x += __builtin_popcountll(i * 1234567ll);
- x += __builtin_clz(i);
- x += __builtin_clzl(i);
- x += __builtin_clzll(i * 1234567ll);
- x += __builtin_ctz(i);
- x += __builtin_ctzl(i);
- x += __builtin_ctzll(i * 1234567ll);
- }
- if (x > 12345677) {
- puts("ok");
- }
-}
-
-#if 0
-struct event {
-
-};
-
-// something might be asyncrhonous.. it communicates the result via the event
-void do_something(struct event *e, int a, unsigned int b, char *c) {
- if (a == b) puts(c);
-}
-
-int32_t event_result_timeout_ms(struct event *e, int32_t timeout_ms);
-int32_t event_result_timeout_us(struct event *e, int32_t timeout_us);
-bool is_event_done(struct event *e);
-// asserts if not done
-int32_t event_result(struct event *e);
-void event_set_callback(struct event *e, void (*callback)(struct event *e));
-void init_multi_event(struct event *target, struct event **events, uint event_count);
-
-#define timeout_ms_result(f, timeout) ({ \
- struct event __event; \
- struct event *event = &__event; \
- (f); \
- event_result_timeout_ms(event, timeout); \
- })
-
-#define blocking_result(f) timeout_ms_result(f, -1)
-#define on_complete(f, cb) ({ \
- static struct event __event; \
- struct event *event = &__event; \
- (f); \
- event_set_callback(event, my_callback); \
- })
-
-void test2() {
- // just playing with blocking syntax
- struct event e;
- do_something(&e, 1, 1, "Hello");
- uint32_t result = event_result_timeout_ms(&e, -1);
-}
-
-void test3() {
- uint32_t result = blocking_result(do_something(event, 1, 1, "Hello"));
-}
-
-void test4() {
- struct event e;
- do_something(&e, 1, 1, "Hello");
- // this would poll (down to hardware if there is no asynchronous mechanism)
- while (!is_event_done(&e)) {
- puts("waiting");
- }
- int32_t result = event_result(&e);
-}
-
-void my_callback(struct event *event) {
- puts("Its done");
- int32_t result = event_result(event);
-}
-
-void test5() {
- static struct event e;
- do_something(&e, 1, 1, "Hello");
- event_set_callback(&e, my_callback);
-}
-
-void test6() {
- on_complete(do_something(event, 1, 1, "Hello"), my_callback);
-}
-
-static struct event e1;
-static struct event e2;
-static struct event *events[2] = {&e1, &e2};
-static struct event multi;
-
-void test7() {
- init_multi_event(&multi,events, count_of(events));
- do_something(&e1, 1, 1, "Hello");
- do_something(&e2, 1, 3, "Hello");
- // something like this
-}
-
-struct dimpl {
- uint8_t type;
-};
-
-struct doodad {
- struct dimpl *type;
- uint32_t param;
-};
-
-struct dimpl indefinite_waiter = {
- .type = 1
-};
-
-extern struct dimpl INDEFINITE_WAIT;
-
-struct dimpl ms_waiter = {
- .type = 1
-};
-
-struct doodad blocking_with_timeout_ms(uint32_t ms) {
- struct doodad rc = {
- .type = &ms_waiter,
- .param = ms
- };
- return rc;
-}
-
-struct result {
-
-};
-
-struct result my_api_call(int arg, float x, struct doodad behavior) {
-
-}
-#endif
\ No newline at end of file
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index f66f9d0..59bf09f 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -4,9 +4,18 @@
find_package(Pioasm REQUIRED)
endfunction()
+# PICO_DEFAULT_PIOASM_OUTPUT_FORMAT, default output format used by pioasm when using pico_generate_pio_header, default=c-sdk, group=build
function(pico_generate_pio_header TARGET PIO)
_pico_init_pioasm()
- cmake_parse_arguments(pico_generate_pio_header "" "OUTPUT_DIR" "" ${ARGN} )
+ cmake_parse_arguments(pico_generate_pio_header "" "OUTPUT_FORMAT;OUTPUT_DIR" "" ${ARGN} )
+
+ if (pico_generate_pio_header_OUTPUT_FORMAT)
+ set(OUTPUT_FORMAT "${pico_generate_pio_header_OUTPUT_FORMAT}")
+ elseif(DEFINED PICO_DEFAULT_PIOASM_OUTPUT_FORMAT)
+ set(OUTPUT_FORMAT "${PICO_DEFAULT_PIOASM_OUTPUT_FORMAT}")
+ else()
+ set(OUTPUT_FORMAT "c-sdk")
+ endif()
if (pico_generate_pio_header_OUTPUT_DIR)
get_filename_component(HEADER_DIR ${pico_generate_pio_header_OUTPUT_DIR} ABSOLUTE)
@@ -23,7 +32,7 @@
add_custom_command(OUTPUT ${HEADER}
DEPENDS ${PIO}
- COMMAND Pioasm -o c-sdk ${PIO} ${HEADER}
+ COMMAND Pioasm -o ${OUTPUT_FORMAT} ${PIO} ${HEADER}
)
add_dependencies(${TARGET} ${HEADER_GEN_TARGET})
get_target_property(target_type ${TARGET} TYPE)
diff --git a/tools/FindPioasm.cmake b/tools/FindPioasm.cmake
index 91b9021..0cc9fe4 100644
--- a/tools/FindPioasm.cmake
+++ b/tools/FindPioasm.cmake
@@ -29,6 +29,7 @@
BINARY_DIR ${PIOASM_BINARY_DIR}
BUILD_ALWAYS 1 # force dependency checking
INSTALL_COMMAND ""
+ CMAKE_CACHE_ARGS "-DPIOASM_EXTRA_SOURCE_FILES:STRING=${PIOASM_EXTRA_SOURCE_FILES}"
)
endif()
diff --git a/tools/elf2uf2/main.cpp b/tools/elf2uf2/main.cpp
index 2c0ddcd..77e67c7 100644
--- a/tools/elf2uf2/main.cpp
+++ b/tools/elf2uf2/main.cpp
@@ -6,6 +6,7 @@
#include <cstdio>
#include <map>
+#include <set>
#include <vector>
#include <cstring>
#include <cstdarg>
@@ -21,6 +22,8 @@
#define ERROR_READ_FAILED -4
#define ERROR_WRITE_FAILED -5
+#define FLASH_SECTOR_ERASE_SIZE 4096u
+
static char error_msg[512];
static bool verbose;
@@ -59,14 +62,16 @@
typedef std::vector<address_range> address_ranges;
-#define MAIN_RAM_START 0x20000000u
-#define MAIN_RAM_END 0x20042000u
-#define FLASH_START 0x10000000u
+#define MAIN_RAM_START 0x20000000u // same as SRAM_BASE in addressmap.h
+#define MAIN_RAM_END 0x20042000u // same as SRAM_END in addressmap.h
+#define FLASH_START 0x10000000u // same as XIP_MAIN_BASE in addressmap.h
#define FLASH_END 0x15000000u
-#define XIP_SRAM_START 0x15000000u
-#define XIP_SRAM_END 0x15004000u
-#define MAIN_RAM_BANKED_START 0x21000000u
+#define XIP_SRAM_START 0x15000000u // same as XIP_SRAM_BASE in addressmap.h
+#define XIP_SRAM_END 0x15004000u // same as XIP_SRAM_END in addressmap.h
+#define MAIN_RAM_BANKED_START 0x21000000u // same as SRAM0_BASE in addressmap.h
#define MAIN_RAM_BANKED_END 0x21040000u
+#define ROM_START 0x00000000u // same as ROM_BASE in addressmap.h
+#define ROM_END 0x00004000u
const address_ranges rp2040_address_ranges_flash {
address_range(FLASH_START, FLASH_END, address_range::type::CONTENTS),
@@ -77,7 +82,7 @@
const address_ranges rp2040_address_ranges_ram {
address_range(MAIN_RAM_START, MAIN_RAM_END, address_range::type::CONTENTS),
address_range(XIP_SRAM_START, XIP_SRAM_END, address_range::type::CONTENTS),
- address_range(0x00000000u, 0x00004000u, address_range::type::IGNORE) // for now we ignore the bootrom if present
+ address_range(ROM_START, ROM_END, address_range::type::IGNORE) // for now we ignore the bootrom if present
};
struct page_fragment {
@@ -293,6 +298,28 @@
MAIN_RAM_START, sp);
}
#endif
+ } else {
+ // Fill in empty dummy uf2 pages to align the binary to flash sectors (except for the last sector which we don't
+ // need to pad, and choose not to to avoid making all SDK UF2s bigger)
+ // That workaround is required because the bootrom uses the block number for erase sector calculations:
+ // https://github.com/raspberrypi/pico-bootrom/blob/c09c7f08550e8a36fc38dc74f8873b9576de99eb/bootrom/virtual_disk.c#L205
+
+ std::set<uint32_t> touched_sectors;
+ for (auto& page_entry : pages) {
+ uint32_t sector = page_entry.first / FLASH_SECTOR_ERASE_SIZE;
+ touched_sectors.insert(sector);
+ }
+
+ uint32_t last_page = pages.rbegin()->first;
+ for (uint32_t sector : touched_sectors) {
+ for (uint32_t page = sector * FLASH_SECTOR_ERASE_SIZE; page < (sector + 1) * FLASH_SECTOR_ERASE_SIZE; page += PAGE_SIZE) {
+ if (page < last_page) {
+ // Create a dummy page, if it does not exist yet. note that all present pages are first
+ // zeroed before they are filled with any contents, so a dummy page will be all zeros.
+ auto &dummy = pages[page];
+ }
+ }
+ }
}
uf2_block block;
block.magic_start0 = UF2_MAGIC_START0;
@@ -306,7 +333,8 @@
block.target_addr = page_entry.first;
block.block_no = page_num++;
if (verbose) {
- printf("Page %d / %d %08x\n", block.block_no, block.num_blocks, block.target_addr);
+ printf("Page %d / %d %08x%s\n", block.block_no, block.num_blocks, block.target_addr,
+ page_entry.second.empty() ? " (padding)": "");
}
memset(block.data, 0, sizeof(block.data));
rc = realize_page(in, page_entry.second, block.data, sizeof(block.data));
diff --git a/tools/extract_configs.py b/tools/extract_configs.py
index e45ae7c..0c6942a 100755
--- a/tools/extract_configs.py
+++ b/tools/extract_configs.py
@@ -38,7 +38,7 @@
-def ValidateAttrs(config_attrs):
+def ValidateAttrs(config_attrs, file_path, linenum):
_type = config_attrs.get('type', 'int')
# Validate attrs
@@ -192,26 +192,31 @@
if val in all_defines:
resolved_defines[d] = all_defines[val]
-for config_name in all_configs:
+for config_name, config_obj in all_configs.items():
+ file_path = os.path.join(scandir, config_obj['filename'])
+ linenum = config_obj['line_number']
- ValidateAttrs(all_configs[config_name]['attrs'])
+ ValidateAttrs(config_obj['attrs'], file_path, linenum)
# Check that default values match up
- if 'default' in all_configs[config_name]['attrs']:
+ if 'default' in config_obj['attrs']:
+ config_default = config_obj['attrs']['default']
if config_name in all_defines:
- if all_configs[config_name]['attrs']['default'] not in all_defines[config_name] and (config_name not in resolved_defines or all_configs[config_name]['attrs']['default'] not in resolved_defines[config_name]):
- if '/' in all_configs[config_name]['attrs']['default'] or ' ' in all_configs[config_name]['attrs']['default']:
+ defines_obj = all_defines[config_name]
+ if config_default not in defines_obj and (config_name not in resolved_defines or config_default not in resolved_defines[config_name]):
+ if '/' in config_default or ' ' in config_default:
continue
# There _may_ be multiple matching defines, but arbitrarily display just one in the error message
- first_define_value = list(all_defines[config_name].keys())[0]
- raise Exception('Found {} at {}:{} with a default of {}, but #define says {} (at {}:{})'.format(config_name, os.path.join(scandir, all_configs[config_name]['filename']), all_configs[config_name]['line_number'], all_configs[config_name]['attrs']['default'], first_define_value, all_defines[config_name][first_define_value][0], all_defines[config_name][first_define_value][1]))
+ first_define_value = list(defines_obj.keys())[0]
+ first_define_file_path, first_define_linenum = defines_obj[first_define_value]
+ raise Exception('Found {} at {}:{} with a default of {}, but #define says {} (at {}:{})'.format(config_name, file_path, linenum, config_default, first_define_value, first_define_file_path, first_define_linenum))
else:
- raise Exception('Found {} at {}:{} with a default of {}, but no matching #define found'.format(config_name, os.path.join(scandir, all_configs[config_name]['filename']), all_configs[config_name]['line_number'], all_configs[config_name]['attrs']['default']))
+ raise Exception('Found {} at {}:{} with a default of {}, but no matching #define found'.format(config_name, file_path, linenum, config_default))
with open(outfile, 'w', newline='') as csvfile:
fieldnames = ('name', 'location', 'description', 'type') + tuple(sorted(all_attrs - set(['type'])))
writer = csv.DictWriter(csvfile, fieldnames=fieldnames, extrasaction='ignore', dialect='excel-tab')
writer.writeheader()
- for config_name in sorted(all_configs):
- writer.writerow({'name': config_name, 'location': '{}:{}'.format(all_configs[config_name]['filename'], all_configs[config_name]['line_number']), 'description': all_configs[config_name]['description'], **all_configs[config_name]['attrs']})
+ for config_name, config_obj in sorted(all_configs.items()):
+ writer.writerow({'name': config_name, 'location': '{}:{}'.format(config_obj['filename'], config_obj['line_number']), 'description': config_obj['description'], **config_obj['attrs']})
diff --git a/tools/pioasm/gen/lexer.cpp b/tools/pioasm/gen/lexer.cpp
index 5de6626..6277a7a 100644
--- a/tools/pioasm/gen/lexer.cpp
+++ b/tools/pioasm/gen/lexer.cpp
@@ -424,7 +424,7 @@
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static const flex_int16_t yy_accept[263] =
+static const flex_int16_t yy_accept[266] =
{ 0,
0, 0, 7, 7, 11, 11, 0, 0, 96, 94,
1, 2, 40, 94, 37, 28, 29, 34, 30, 23,
@@ -432,49 +432,49 @@
92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
92, 73, 74, 92, 26, 27, 38, 36, 41, 94,
7, 4, 5, 7, 11, 8, 12, 10, 19, 14,
- 20, 21, 16, 16, 15, 1, 2, 39, 0, 0,
- 31, 50, 50, 50, 50, 50, 50, 50, 22, 93,
- 89, 0, 0, 24, 93, 92, 92, 92, 92, 92,
- 92, 53, 92, 92, 92, 92, 92, 92, 92, 92,
+ 20, 14, 21, 16, 16, 15, 1, 2, 39, 0,
+ 0, 31, 50, 50, 50, 50, 50, 50, 50, 22,
+ 93, 89, 0, 0, 24, 93, 92, 92, 92, 92,
+ 92, 92, 53, 92, 92, 92, 92, 92, 92, 92,
- 92, 92, 75, 92, 92, 92, 92, 92, 92, 92,
- 92, 0, 7, 4, 5, 6, 11, 8, 12, 9,
- 19, 14, 20, 0, 13, 16, 19, 19, 0, 3,
- 0, 50, 50, 50, 50, 50, 50, 50, 50, 91,
- 90, 92, 92, 92, 92, 92, 92, 58, 77, 51,
- 57, 92, 60, 92, 92, 87, 63, 78, 54, 67,
- 92, 92, 92, 84, 59, 92, 92, 92, 92, 0,
- 18, 17, 50, 50, 50, 50, 50, 50, 50, 92,
- 92, 76, 68, 92, 92, 92, 92, 71, 92, 69,
- 92, 70, 92, 56, 55, 64, 92, 52, 88, 0,
+ 92, 92, 92, 75, 92, 92, 92, 92, 92, 92,
+ 92, 92, 0, 7, 4, 5, 6, 11, 8, 12,
+ 9, 19, 14, 20, 14, 0, 13, 16, 19, 19,
+ 0, 3, 0, 50, 50, 50, 50, 50, 50, 50,
+ 50, 91, 90, 92, 92, 92, 92, 92, 92, 58,
+ 77, 51, 57, 92, 60, 92, 92, 87, 63, 78,
+ 54, 67, 92, 92, 92, 84, 59, 92, 92, 92,
+ 92, 0, 6, 18, 17, 50, 50, 50, 50, 50,
+ 50, 50, 92, 92, 76, 68, 92, 92, 92, 92,
+ 71, 92, 69, 92, 70, 92, 56, 55, 64, 92,
- 50, 50, 50, 50, 50, 45, 44, 80, 85, 92,
- 92, 92, 92, 92, 92, 92, 92, 92, 92, 0,
- 50, 50, 50, 50, 50, 50, 92, 82, 92, 86,
- 92, 92, 61, 92, 92, 79, 32, 46, 50, 48,
- 50, 50, 50, 83, 81, 92, 72, 65, 92, 50,
- 42, 50, 50, 62, 66, 49, 47, 50, 50, 50,
- 43, 0
+ 52, 88, 0, 50, 50, 50, 50, 50, 45, 44,
+ 80, 85, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 0, 50, 50, 50, 50, 50, 50, 92,
+ 82, 92, 86, 92, 92, 61, 92, 92, 79, 32,
+ 46, 50, 48, 50, 50, 50, 83, 81, 92, 72,
+ 65, 92, 50, 42, 50, 50, 62, 66, 49, 47,
+ 50, 50, 50, 43, 0
} ;
static const YY_CHAR yy_ec[256] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 4, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 2, 4, 5, 1, 1, 6, 7, 1, 8,
- 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
- 18, 18, 18, 18, 18, 18, 18, 19, 20, 1,
- 21, 1, 1, 1, 22, 23, 24, 25, 26, 27,
- 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
- 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 1, 49, 50, 51, 1, 52, 53, 54, 55,
+ 1, 2, 5, 6, 1, 1, 7, 8, 1, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 19, 19, 19, 19, 19, 19, 19, 20, 21, 1,
+ 22, 1, 1, 1, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 1, 50, 51, 52, 1, 53, 54, 55, 56,
- 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
- 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
- 76, 77, 78, 79, 80, 81, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 82, 1, 1, 1, 1,
+ 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ 77, 78, 79, 80, 81, 82, 1, 1, 1, 1,
1, 1, 1, 1, 1, 83, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 84, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -483,173 +483,178 @@
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 84, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 85, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1
} ;
-static const YY_CHAR yy_meta[85] =
+static const YY_CHAR yy_meta[86] =
{ 0,
- 1, 2, 3, 1, 2, 4, 1, 1, 1, 5,
- 1, 1, 1, 1, 1, 6, 6, 6, 1, 1,
- 2, 7, 7, 7, 7, 7, 7, 8, 8, 8,
+ 1, 2, 3, 1, 1, 2, 4, 1, 1, 1,
+ 5, 1, 1, 1, 1, 1, 6, 6, 6, 1,
+ 1, 2, 7, 7, 7, 7, 7, 7, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 1, 1, 1,
- 8, 7, 7, 7, 7, 7, 7, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 1, 1,
+ 1, 8, 7, 7, 7, 7, 7, 7, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 1, 1, 1,
- 1, 1, 1, 1
+ 8, 8, 8, 8, 8, 8, 8, 8, 1, 1,
+ 1, 1, 1, 1, 1
} ;
-static const flex_int16_t yy_base[276] =
+static const flex_int16_t yy_base[279] =
{ 0,
- 0, 0, 83, 85, 90, 92, 94, 101, 516, 605,
- 513, 511, 492, 510, 605, 605, 605, 605, 605, 605,
- 498, 88, 99, 118, 113, 490, 0, 0, 57, 74,
- 63, 79, 113, 92, 91, 103, 107, 143, 124, 135,
- 137, 0, 0, 134, 605, 605, 605, 605, 605, 420,
- 0, 499, 497, 419, 0, 496, 494, 481, 0, 493,
- 491, 488, 182, 170, 605, 399, 364, 605, 103, 131,
- 605, 0, 138, 144, 145, 153, 171, 168, 605, 0,
- 194, 200, 0, 605, 0, 0, 166, 182, 187, 188,
- 193, 0, 183, 184, 187, 182, 203, 195, 203, 189,
+ 0, 0, 84, 90, 96, 99, 102, 109, 540, 644,
+ 112, 536, 516, 121, 644, 644, 644, 644, 644, 644,
+ 523, 96, 79, 126, 121, 516, 0, 0, 83, 84,
+ 83, 94, 125, 111, 112, 114, 132, 161, 127, 151,
+ 132, 0, 0, 131, 644, 644, 644, 644, 644, 452,
+ 0, 195, 531, 452, 0, 205, 529, 391, 0, 209,
+ 401, 213, 393, 201, 209, 644, 227, 310, 644, 228,
+ 231, 644, 0, 167, 183, 170, 174, 190, 201, 644,
+ 0, 231, 118, 0, 644, 0, 0, 200, 212, 215,
+ 212, 218, 0, 213, 213, 216, 212, 236, 223, 231,
- 194, 195, 0, 204, 238, 209, 203, 220, 224, 222,
- 223, 283, 0, 363, 361, 0, 0, 360, 355, 605,
- 0, 355, 353, 308, 285, 263, 248, 293, 265, 266,
- 281, 0, 246, 249, 263, 258, 270, 257, 275, 269,
- 0, 274, 277, 276, 266, 270, 263, 0, 0, 0,
- 0, 273, 0, 285, 279, 0, 291, 296, 0, 313,
- 298, 300, 310, 0, 0, 314, 300, 313, 319, 205,
- 271, 370, 330, 344, 345, 346, 349, 351, 340, 346,
- 340, 0, 0, 343, 348, 346, 359, 0, 355, 0,
- 368, 0, 369, 0, 0, 380, 358, 0, 0, 159,
+ 217, 221, 220, 0, 227, 261, 230, 224, 244, 255,
+ 248, 257, 214, 0, 297, 277, 301, 0, 310, 262,
+ 644, 0, 314, 198, 315, 171, 168, 303, 172, 316,
+ 322, 326, 327, 0, 278, 287, 306, 301, 319, 306,
+ 324, 331, 0, 325, 328, 327, 317, 320, 313, 0,
+ 0, 0, 0, 323, 0, 335, 325, 0, 329, 334,
+ 0, 337, 328, 330, 335, 0, 0, 339, 337, 341,
+ 360, 84, 396, 385, 411, 379, 382, 383, 385, 388,
+ 390, 379, 385, 379, 0, 0, 382, 387, 385, 392,
+ 0, 387, 0, 394, 0, 395, 0, 0, 391, 388,
- 378, 117, 384, 376, 72, 0, 50, 0, 0, 375,
- 384, 394, 391, 398, 395, 411, 410, 397, 398, 15,
- 413, 404, 406, 420, 409, 410, 406, 0, 421, 0,
- 432, 415, 0, 415, 431, 0, 605, 0, 421, 0,
- 425, 434, 439, 0, 0, 440, 0, 0, 433, 434,
- 0, 435, 438, 0, 0, 0, 0, 450, 454, 451,
- 0, 605, 522, 530, 538, 546, 548, 556, 559, 567,
- 575, 583, 591, 594, 597
+ 0, 0, 73, 397, 90, 426, 418, 57, 0, 44,
+ 0, 0, 417, 426, 445, 429, 436, 433, 449, 448,
+ 435, 436, 5, 451, 442, 444, 458, 441, 441, 437,
+ 0, 452, 0, 463, 450, 0, 450, 466, 0, 644,
+ 0, 456, 0, 460, 469, 474, 0, 0, 464, 0,
+ 0, 457, 475, 0, 476, 479, 0, 0, 0, 0,
+ 491, 503, 489, 0, 644, 561, 569, 577, 585, 587,
+ 595, 598, 606, 614, 622, 630, 633, 636
} ;
-static const flex_int16_t yy_def[276] =
+static const flex_int16_t yy_def[279] =
{ 0,
- 262, 1, 263, 263, 264, 264, 265, 265, 262, 262,
- 262, 262, 262, 266, 262, 262, 262, 262, 262, 262,
- 262, 267, 262, 262, 262, 262, 268, 269, 269, 269,
- 269, 269, 269, 269, 269, 269, 269, 269, 269, 269,
- 269, 269, 269, 269, 262, 262, 262, 262, 262, 262,
- 270, 270, 262, 270, 271, 271, 262, 262, 272, 262,
- 262, 273, 272, 272, 262, 262, 262, 262, 266, 266,
- 262, 274, 274, 274, 274, 274, 274, 274, 262, 268,
- 262, 262, 275, 262, 268, 269, 269, 269, 269, 269,
- 269, 269, 269, 269, 269, 269, 269, 269, 269, 269,
+ 265, 1, 266, 266, 267, 267, 268, 268, 265, 265,
+ 265, 265, 265, 269, 265, 265, 265, 265, 265, 265,
+ 265, 270, 265, 265, 265, 265, 271, 272, 272, 272,
+ 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
+ 272, 272, 272, 272, 265, 265, 265, 265, 265, 265,
+ 273, 273, 265, 273, 274, 274, 265, 265, 275, 265,
+ 265, 275, 276, 275, 275, 265, 265, 265, 265, 269,
+ 269, 265, 277, 277, 277, 277, 277, 277, 277, 265,
+ 271, 265, 265, 278, 265, 271, 272, 272, 272, 272,
+ 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
- 269, 269, 269, 269, 269, 269, 269, 269, 269, 269,
- 269, 262, 270, 270, 262, 270, 271, 271, 262, 262,
- 272, 262, 262, 273, 273, 272, 272, 272, 266, 266,
- 266, 274, 274, 274, 274, 274, 274, 274, 274, 262,
- 275, 269, 269, 269, 269, 269, 269, 269, 269, 269,
- 269, 269, 269, 269, 269, 269, 269, 269, 269, 269,
- 269, 269, 269, 269, 269, 269, 269, 269, 269, 262,
- 272, 272, 274, 274, 274, 274, 274, 274, 274, 269,
- 269, 269, 269, 269, 269, 269, 269, 269, 269, 269,
- 269, 269, 269, 269, 269, 269, 269, 269, 269, 262,
+ 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
+ 272, 272, 265, 273, 273, 265, 273, 274, 274, 265,
+ 265, 275, 265, 265, 275, 276, 276, 275, 275, 275,
+ 269, 269, 269, 277, 277, 277, 277, 277, 277, 277,
+ 277, 265, 278, 272, 272, 272, 272, 272, 272, 272,
+ 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
+ 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
+ 272, 265, 273, 275, 275, 277, 277, 277, 277, 277,
+ 277, 277, 272, 272, 272, 272, 272, 272, 272, 272,
+ 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
- 274, 274, 274, 274, 274, 274, 274, 269, 269, 269,
- 269, 269, 269, 269, 269, 269, 269, 269, 269, 262,
- 274, 274, 274, 274, 274, 274, 269, 269, 269, 269,
- 269, 269, 269, 269, 269, 269, 262, 274, 274, 274,
- 274, 274, 274, 269, 269, 269, 269, 269, 269, 274,
- 274, 274, 274, 269, 269, 274, 274, 274, 274, 274,
- 274, 0, 262, 262, 262, 262, 262, 262, 262, 262,
- 262, 262, 262, 262, 262
+ 272, 272, 265, 277, 277, 277, 277, 277, 277, 277,
+ 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
+ 272, 272, 265, 277, 277, 277, 277, 277, 277, 272,
+ 272, 272, 272, 272, 272, 272, 272, 272, 272, 265,
+ 277, 277, 277, 277, 277, 277, 272, 272, 272, 272,
+ 272, 272, 277, 277, 277, 277, 272, 272, 277, 277,
+ 277, 277, 277, 277, 0, 265, 265, 265, 265, 265,
+ 265, 265, 265, 265, 265, 265, 265, 265
} ;
-static const flex_int16_t yy_nxt[690] =
+static const flex_int16_t yy_nxt[730] =
{ 0,
- 10, 11, 12, 13, 10, 14, 15, 16, 17, 18,
- 19, 20, 21, 22, 23, 24, 25, 25, 26, 27,
- 10, 28, 29, 30, 28, 31, 28, 32, 28, 33,
- 34, 28, 28, 35, 36, 37, 38, 28, 39, 40,
- 28, 28, 28, 41, 42, 43, 44, 45, 46, 47,
- 28, 28, 29, 30, 28, 31, 28, 32, 28, 33,
- 34, 28, 28, 35, 36, 37, 38, 28, 39, 40,
- 28, 28, 28, 41, 42, 43, 44, 10, 48, 10,
- 49, 10, 10, 50, 52, 53, 52, 53, 54, 87,
- 54, 56, 57, 56, 57, 60, 61, 237, 62, 58,
+ 10, 11, 12, 11, 13, 10, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 25, 26,
+ 27, 10, 28, 29, 30, 28, 31, 28, 32, 28,
+ 33, 34, 28, 28, 35, 36, 37, 38, 28, 39,
+ 40, 28, 28, 28, 41, 42, 43, 44, 45, 46,
+ 47, 28, 28, 29, 30, 28, 31, 28, 32, 28,
+ 33, 34, 28, 28, 35, 36, 37, 38, 28, 39,
+ 40, 28, 28, 28, 41, 42, 43, 44, 10, 48,
+ 10, 49, 10, 10, 50, 52, 53, 52, 240, 80,
+ 54, 52, 53, 52, 81, 229, 54, 56, 57, 56,
- 226, 58, 60, 61, 129, 62, 88, 89, 79, 63,
- 64, 64, 73, 80, 65, 90, 63, 64, 64, 87,
- 74, 65, 225, 75, 76, 95, 96, 77, 81, 81,
- 81, 78, 131, 81, 81, 81, 88, 89, 97, 91,
- 82, 99, 73, 100, 98, 90, 101, 92, 102, 106,
- 74, 93, 94, 75, 76, 95, 96, 77, 110, 111,
- 107, 78, 83, 133, 108, 134, 103, 222, 97, 91,
- 82, 99, 104, 100, 98, 109, 101, 92, 102, 106,
- 130, 93, 94, 135, 105, 126, 126, 126, 110, 111,
- 107, 136, 83, 133, 108, 134, 103, 126, 126, 126,
+ 56, 57, 56, 60, 61, 62, 58, 63, 228, 58,
+ 60, 61, 62, 67, 63, 67, 88, 89, 64, 65,
+ 65, 74, 71, 66, 71, 64, 65, 65, 90, 75,
+ 66, 91, 76, 77, 142, 142, 78, 82, 82, 82,
+ 79, 225, 82, 82, 82, 96, 88, 89, 97, 83,
+ 98, 74, 92, 107, 111, 223, 99, 112, 90, 75,
+ 93, 91, 76, 77, 94, 95, 78, 100, 203, 101,
+ 79, 84, 102, 127, 103, 96, 127, 108, 97, 83,
+ 98, 109, 92, 107, 111, 104, 99, 112, 174, 174,
+ 93, 105, 110, 135, 94, 95, 115, 100, 115, 101,
- 137, 142, 104, 138, 127, 109, 139, 143, 130, 81,
- 81, 81, 144, 135, 105, 140, 140, 145, 146, 147,
- 148, 136, 149, 150, 151, 152, 128, 155, 156, 157,
- 137, 142, 158, 138, 127, 159, 139, 143, 160, 153,
- 220, 164, 144, 165, 166, 167, 154, 145, 146, 147,
- 148, 168, 149, 150, 151, 152, 128, 155, 156, 157,
- 161, 169, 158, 171, 171, 159, 129, 129, 160, 153,
- 162, 164, 173, 165, 166, 167, 154, 163, 126, 126,
- 126, 168, 131, 174, 140, 140, 171, 171, 200, 125,
- 161, 169, 175, 176, 177, 178, 179, 180, 181, 182,
+ 124, 84, 102, 106, 103, 136, 119, 108, 119, 137,
+ 123, 109, 123, 138, 123, 104, 125, 128, 128, 128,
+ 139, 105, 110, 135, 129, 128, 128, 128, 67, 131,
+ 67, 131, 133, 106, 133, 136, 144, 140, 145, 137,
+ 141, 146, 147, 138, 148, 149, 130, 82, 82, 82,
+ 139, 150, 151, 152, 129, 153, 157, 158, 159, 154,
+ 160, 161, 162, 166, 120, 167, 144, 140, 145, 168,
+ 141, 146, 147, 155, 148, 149, 130, 169, 170, 116,
+ 156, 150, 151, 152, 163, 153, 157, 158, 159, 154,
+ 160, 161, 162, 166, 164, 167, 171, 172, 115, 168,
- 162, 183, 173, 184, 185, 186, 187, 163, 172, 172,
- 172, 188, 125, 174, 172, 172, 172, 172, 172, 172,
- 189, 190, 175, 176, 177, 178, 179, 180, 181, 182,
- 193, 183, 194, 184, 185, 186, 187, 191, 195, 196,
- 197, 188, 130, 130, 172, 172, 172, 172, 172, 172,
- 189, 190, 192, 198, 199, 123, 122, 119, 130, 201,
- 193, 118, 194, 115, 114, 170, 67, 191, 195, 196,
- 197, 202, 203, 204, 205, 206, 207, 208, 209, 210,
- 211, 212, 192, 198, 199, 172, 172, 172, 213, 201,
- 214, 172, 172, 172, 172, 172, 172, 215, 216, 219,
+ 115, 165, 173, 155, 173, 176, 132, 169, 170, 132,
+ 156, 119, 68, 119, 163, 123, 123, 123, 125, 128,
+ 128, 128, 177, 131, 164, 131, 171, 131, 133, 131,
+ 133, 165, 175, 175, 175, 176, 178, 179, 175, 175,
+ 175, 175, 175, 175, 180, 181, 182, 142, 142, 183,
+ 184, 185, 177, 186, 187, 188, 189, 190, 191, 192,
+ 193, 196, 194, 197, 198, 199, 178, 179, 175, 175,
+ 175, 175, 175, 175, 180, 181, 182, 195, 200, 183,
+ 184, 185, 201, 186, 187, 188, 189, 190, 191, 192,
+ 193, 196, 194, 197, 198, 199, 202, 173, 127, 173,
- 66, 202, 203, 204, 205, 206, 207, 208, 209, 210,
- 211, 212, 221, 223, 224, 227, 228, 229, 213, 217,
- 214, 172, 172, 172, 172, 172, 172, 215, 216, 219,
- 218, 230, 231, 232, 233, 234, 235, 236, 238, 239,
- 240, 241, 221, 223, 224, 227, 228, 229, 242, 217,
- 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
- 253, 230, 231, 232, 233, 234, 235, 236, 238, 239,
- 240, 241, 254, 255, 256, 257, 258, 259, 242, 260,
- 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
- 253, 261, 125, 123, 122, 120, 119, 118, 116, 115,
+ 132, 174, 174, 124, 132, 132, 121, 195, 200, 204,
+ 205, 206, 201, 207, 208, 209, 210, 211, 212, 213,
+ 214, 215, 216, 217, 218, 219, 202, 175, 175, 175,
+ 222, 220, 224, 175, 175, 175, 175, 175, 175, 204,
+ 205, 206, 221, 207, 208, 209, 210, 211, 212, 213,
+ 214, 215, 216, 217, 218, 219, 226, 227, 230, 231,
+ 222, 220, 224, 175, 175, 175, 175, 175, 175, 232,
+ 233, 234, 235, 236, 237, 238, 239, 241, 242, 243,
+ 244, 245, 246, 247, 248, 249, 226, 227, 230, 231,
+ 250, 251, 252, 253, 254, 255, 256, 257, 258, 232,
- 114, 112, 254, 255, 256, 257, 258, 259, 84, 260,
- 71, 70, 68, 67, 66, 262, 262, 262, 262, 262,
- 262, 261, 51, 51, 51, 51, 51, 51, 51, 51,
- 55, 55, 55, 55, 55, 55, 55, 55, 59, 59,
- 59, 59, 59, 59, 59, 59, 69, 69, 262, 262,
- 69, 69, 69, 69, 72, 72, 85, 85, 262, 85,
- 85, 85, 85, 85, 86, 86, 86, 113, 113, 262,
- 113, 113, 113, 113, 113, 117, 117, 262, 117, 262,
- 117, 117, 117, 121, 262, 262, 121, 121, 121, 121,
- 121, 124, 124, 262, 124, 124, 124, 124, 124, 132,
+ 233, 234, 235, 236, 237, 238, 239, 241, 242, 243,
+ 244, 245, 246, 247, 248, 249, 259, 260, 261, 262,
+ 250, 251, 252, 253, 254, 255, 256, 257, 258, 263,
+ 264, 120, 117, 116, 113, 85, 72, 69, 68, 265,
+ 265, 265, 265, 265, 265, 265, 259, 260, 261, 262,
+ 265, 265, 265, 265, 265, 265, 265, 265, 265, 263,
+ 264, 51, 51, 51, 51, 51, 51, 51, 51, 55,
+ 55, 55, 55, 55, 55, 55, 55, 59, 59, 59,
+ 59, 59, 59, 59, 59, 70, 70, 265, 265, 70,
+ 70, 70, 70, 73, 73, 86, 86, 265, 86, 86,
- 132, 132, 141, 141, 9, 262, 262, 262, 262, 262,
- 262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
- 262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
- 262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
- 262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
- 262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
- 262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
- 262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
- 262, 262, 262, 262, 262, 262, 262, 262, 262
+ 86, 86, 86, 87, 87, 87, 114, 114, 265, 114,
+ 114, 114, 114, 114, 118, 118, 265, 118, 265, 118,
+ 118, 118, 122, 265, 265, 122, 122, 122, 122, 122,
+ 126, 126, 265, 126, 126, 126, 126, 126, 134, 134,
+ 134, 143, 143, 9, 265, 265, 265, 265, 265, 265,
+ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265,
+ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265,
+ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265,
+ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265,
+ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265,
+
+ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265,
+ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265,
+ 265, 265, 265, 265, 265, 265, 265, 265, 265
} ;
-static const flex_int16_t yy_chk[690] =
+static const flex_int16_t yy_chk[730] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -659,73 +664,78 @@
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 3, 3, 4, 4, 3, 29,
- 4, 5, 5, 6, 6, 7, 7, 220, 7, 5,
+ 1, 1, 1, 1, 1, 3, 3, 3, 223, 23,
+ 3, 4, 4, 4, 23, 210, 4, 5, 5, 5,
- 207, 6, 8, 8, 69, 8, 30, 31, 23, 7,
- 7, 7, 22, 23, 7, 32, 8, 8, 8, 29,
- 22, 8, 205, 22, 22, 34, 35, 22, 25, 25,
- 25, 22, 70, 24, 24, 24, 30, 31, 36, 33,
- 24, 37, 22, 37, 36, 32, 37, 33, 37, 39,
- 22, 33, 33, 22, 22, 34, 35, 22, 41, 44,
- 40, 22, 24, 73, 40, 74, 38, 202, 36, 33,
- 24, 37, 38, 37, 36, 40, 37, 33, 37, 39,
- 69, 33, 33, 75, 38, 64, 64, 64, 41, 44,
- 40, 76, 24, 73, 40, 74, 38, 63, 63, 63,
+ 6, 6, 6, 7, 7, 7, 5, 7, 208, 6,
+ 8, 8, 8, 11, 8, 11, 29, 30, 7, 7,
+ 7, 22, 14, 7, 14, 8, 8, 8, 31, 22,
+ 8, 32, 22, 22, 83, 83, 22, 25, 25, 25,
+ 22, 205, 24, 24, 24, 34, 29, 30, 35, 24,
+ 36, 22, 33, 39, 41, 203, 36, 44, 31, 22,
+ 33, 32, 22, 22, 33, 33, 22, 37, 172, 37,
+ 22, 24, 37, 127, 37, 34, 126, 40, 35, 24,
+ 36, 40, 33, 39, 41, 38, 36, 44, 129, 129,
+ 33, 38, 40, 74, 33, 33, 52, 37, 52, 37,
- 77, 87, 38, 78, 63, 40, 78, 88, 70, 81,
- 81, 81, 89, 75, 38, 82, 82, 90, 91, 91,
- 93, 76, 94, 95, 96, 97, 63, 98, 99, 100,
- 77, 87, 101, 78, 63, 102, 78, 88, 104, 97,
- 200, 106, 89, 107, 108, 109, 97, 90, 91, 91,
- 93, 110, 94, 95, 96, 97, 63, 98, 99, 100,
- 105, 111, 101, 127, 127, 102, 129, 130, 104, 97,
- 105, 106, 133, 107, 108, 109, 97, 105, 126, 126,
- 126, 110, 131, 134, 140, 140, 171, 171, 170, 125,
- 105, 111, 135, 136, 137, 138, 139, 142, 143, 144,
+ 124, 24, 37, 38, 37, 75, 56, 40, 56, 76,
+ 60, 40, 60, 77, 62, 38, 62, 64, 64, 64,
+ 78, 38, 40, 74, 64, 65, 65, 65, 67, 70,
+ 67, 70, 71, 38, 71, 75, 88, 79, 89, 76,
+ 79, 90, 91, 77, 92, 92, 64, 82, 82, 82,
+ 78, 94, 95, 96, 64, 97, 99, 100, 101, 98,
+ 102, 103, 105, 107, 120, 108, 88, 79, 89, 109,
+ 79, 90, 91, 98, 92, 92, 64, 110, 111, 116,
+ 98, 94, 95, 96, 106, 97, 99, 100, 101, 98,
+ 102, 103, 105, 107, 106, 108, 112, 113, 115, 109,
- 105, 145, 133, 146, 147, 152, 154, 105, 128, 128,
- 128, 155, 124, 134, 128, 128, 128, 128, 128, 128,
- 157, 158, 135, 136, 137, 138, 139, 142, 143, 144,
- 161, 145, 162, 146, 147, 152, 154, 160, 163, 166,
- 167, 155, 129, 130, 128, 128, 128, 128, 128, 128,
- 157, 158, 160, 168, 169, 123, 122, 119, 131, 173,
- 161, 118, 162, 115, 114, 112, 67, 160, 163, 166,
- 167, 174, 175, 176, 177, 178, 179, 180, 181, 184,
- 185, 186, 160, 168, 169, 172, 172, 172, 187, 173,
- 189, 172, 172, 172, 172, 172, 172, 191, 193, 197,
+ 115, 106, 117, 98, 117, 135, 70, 110, 111, 71,
+ 98, 119, 68, 119, 106, 123, 125, 123, 125, 128,
+ 128, 128, 136, 131, 106, 131, 112, 132, 133, 132,
+ 133, 106, 130, 130, 130, 135, 137, 138, 130, 130,
+ 130, 130, 130, 130, 139, 140, 141, 142, 142, 144,
+ 145, 146, 136, 147, 148, 149, 154, 156, 157, 159,
+ 160, 163, 162, 164, 165, 168, 137, 138, 130, 130,
+ 130, 130, 130, 130, 139, 140, 141, 162, 169, 144,
+ 145, 146, 170, 147, 148, 149, 154, 156, 157, 159,
+ 160, 163, 162, 164, 165, 168, 171, 173, 63, 173,
- 66, 174, 175, 176, 177, 178, 179, 180, 181, 184,
- 185, 186, 201, 203, 204, 210, 211, 212, 187, 196,
- 189, 172, 172, 172, 172, 172, 172, 191, 193, 197,
- 196, 213, 214, 215, 216, 217, 218, 219, 221, 222,
- 223, 224, 201, 203, 204, 210, 211, 212, 225, 196,
- 226, 227, 229, 231, 232, 234, 235, 239, 241, 242,
- 243, 213, 214, 215, 216, 217, 218, 219, 221, 222,
- 223, 224, 246, 249, 250, 252, 253, 258, 225, 259,
- 226, 227, 229, 231, 232, 234, 235, 239, 241, 242,
- 243, 260, 62, 61, 60, 58, 57, 56, 54, 53,
+ 131, 174, 174, 61, 132, 133, 58, 162, 169, 176,
+ 177, 178, 170, 179, 180, 181, 182, 183, 184, 187,
+ 188, 189, 190, 192, 194, 196, 171, 175, 175, 175,
+ 200, 199, 204, 175, 175, 175, 175, 175, 175, 176,
+ 177, 178, 199, 179, 180, 181, 182, 183, 184, 187,
+ 188, 189, 190, 192, 194, 196, 206, 207, 213, 214,
+ 200, 199, 204, 175, 175, 175, 175, 175, 175, 215,
+ 216, 217, 218, 219, 220, 221, 222, 224, 225, 226,
+ 227, 228, 229, 230, 232, 234, 206, 207, 213, 214,
+ 235, 237, 238, 242, 244, 245, 246, 249, 252, 215,
- 52, 50, 246, 249, 250, 252, 253, 258, 26, 259,
- 21, 14, 13, 12, 11, 9, 0, 0, 0, 0,
- 0, 260, 263, 263, 263, 263, 263, 263, 263, 263,
- 264, 264, 264, 264, 264, 264, 264, 264, 265, 265,
- 265, 265, 265, 265, 265, 265, 266, 266, 0, 0,
- 266, 266, 266, 266, 267, 267, 268, 268, 0, 268,
- 268, 268, 268, 268, 269, 269, 269, 270, 270, 0,
- 270, 270, 270, 270, 270, 271, 271, 0, 271, 0,
- 271, 271, 271, 272, 0, 0, 272, 272, 272, 272,
- 272, 273, 273, 0, 273, 273, 273, 273, 273, 274,
+ 216, 217, 218, 219, 220, 221, 222, 224, 225, 226,
+ 227, 228, 229, 230, 232, 234, 253, 255, 256, 261,
+ 235, 237, 238, 242, 244, 245, 246, 249, 252, 262,
+ 263, 57, 54, 53, 50, 26, 21, 13, 12, 9,
+ 0, 0, 0, 0, 0, 0, 253, 255, 256, 261,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 262,
+ 263, 266, 266, 266, 266, 266, 266, 266, 266, 267,
+ 267, 267, 267, 267, 267, 267, 267, 268, 268, 268,
+ 268, 268, 268, 268, 268, 269, 269, 0, 0, 269,
+ 269, 269, 269, 270, 270, 271, 271, 0, 271, 271,
- 274, 274, 275, 275, 262, 262, 262, 262, 262, 262,
- 262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
- 262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
- 262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
- 262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
- 262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
- 262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
- 262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
- 262, 262, 262, 262, 262, 262, 262, 262, 262
+ 271, 271, 271, 272, 272, 272, 273, 273, 0, 273,
+ 273, 273, 273, 273, 274, 274, 0, 274, 0, 274,
+ 274, 274, 275, 0, 0, 275, 275, 275, 275, 275,
+ 276, 276, 0, 276, 276, 276, 276, 276, 277, 277,
+ 277, 278, 278, 265, 265, 265, 265, 265, 265, 265,
+ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265,
+ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265,
+ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265,
+ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265,
+ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265,
+
+ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265,
+ 265, 265, 265, 265, 265, 265, 265, 265, 265, 265,
+ 265, 265, 265, 265, 265, 265, 265, 265, 265
} ;
static yy_state_type yy_last_accepting_state;
@@ -1098,13 +1108,13 @@
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 263 )
+ if ( yy_current_state >= 266 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
++yy_cp;
}
- while ( yy_current_state != 262 );
+ while ( yy_current_state != 265 );
yy_cp = (yy_last_accepting_cpos);
yy_current_state = (yy_last_accepting_state);
@@ -1866,7 +1876,7 @@
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 263 )
+ if ( yy_current_state >= 266 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
@@ -1899,11 +1909,11 @@
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 263 )
+ if ( yy_current_state >= 266 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
- yy_is_jam = (yy_current_state == 262);
+ yy_is_jam = (yy_current_state == 265);
return yy_is_jam ? 0 : yy_current_state;
}
diff --git a/tools/pioasm/lexer.ll b/tools/pioasm/lexer.ll
index 939b06f..5604b70 100644
--- a/tools/pioasm/lexer.ll
+++ b/tools/pioasm/lexer.ll
@@ -27,7 +27,7 @@
yy::parser::symbol_type make_BINARY(const std::string &s, const yy::parser::location_type& loc);
%}
-blank [ \t]
+blank [ \t\r]
whitesp {blank}+
comment (";"|"//")[^\n]*
@@ -77,7 +77,7 @@
<code_block>{
{blank}+ loc.step();
\n+ { auto loc_newline = loc; loc_newline.end = loc_newline.begin; loc.lines(yyleng); loc.step(); }
- "%}" { BEGIN(INITIAL); auto loc2 = loc; loc2.begin = code_block_start.begin; return yy::parser::make_CODE_BLOCK_CONTENTS(code_block_contents, loc2); }
+ "%}"{blank}* { BEGIN(INITIAL); auto loc2 = loc; loc2.begin = code_block_start.begin; return yy::parser::make_CODE_BLOCK_CONTENTS(code_block_contents, loc2); }
.* { code_block_contents += std::string(yytext) + "\n"; }
}
diff --git a/tools/pioasm/python_output.cpp b/tools/pioasm/python_output.cpp
index 38f7ffe..e932baf 100644
--- a/tools/pioasm/python_output.cpp
+++ b/tools/pioasm/python_output.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ * Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -283,9 +283,7 @@
if (arg1 & 0x2u) {
guts += "clear, ";
} else if (arg1 & 0x1u) {
- guts += "wait, ";
- } else {
- guts += "nowait, ";
+ guts += "block, ";
}
auto irq = std::to_string(arg2 & 7u);
if (arg2 & 0x10u) {