Compare commits

...
341 Commits
Author SHA1 Message Date
Earle F. Philhower, III f9321b034f Update version 2022-11-28 10:07:41 -08:00
Earle F. Philhower, III 65dd19a158 Allow building w/o USB for normal and picoprobe builds (#1013)
Supersedes #972.  Thanks @kholk
2022-11-28 10:01:35 -08:00
Earle F. Philhower, III be60060941 Fix newline issue w/Waveshare PR (#1012)
Go back to UNIX format endlines.  No functional changes.
2022-11-28 09:43:55 -08:00
Engineer_Will 39ac1d6bfb Add some Waveshare board descriptions (#1004) 2022-11-28 09:35:23 -08:00
Earle F. Philhower, III d94ca66e3e Update Wire per @chrisckc debugging (#1011)
Merge in changes @chrisckc debugged while working at 400khz on his own project.
See https://github.com/earlephilhower/arduino-pico/issues/979#issuecomment-1328237128
2022-11-28 08:50:51 -08:00
brabl2 e47e3c73c2 Fix memcpy to unallocated memory in EEPROM.cpp (#1000)
The memcpy to unallocated memory was done in two cases:
1) The 'size' parameter was not multiple of 256.
2) The begin() was called two times and the 2nd call 'size' was greater than 1st time 'size'. (e.g. 1st size=256, 2nd size=512)
2022-11-24 10:25:48 -08:00
diesel437 f11c22d984 Using PIO_FRAMEWORK_ARDUINO_NO_USB build flag would cause internal rp2040 fifo not being initialized correct. (#1001) 2022-11-24 10:02:25 -08:00
Earle F. Philhower, III bd4a2d232f Update rp2040.rst 2022-11-23 08:19:36 -08:00
Earle F. Philhower, III 158cf3c7b3 Update rp2040.rst 2022-11-23 07:57:59 -08:00
imwoo90 a7cf5cd1ca Fix GPIO interrupt on freeRTOS (#959) 2022-11-22 18:26:19 -08:00
Sylwester 4e6e1d6024 Use PIN_I2S_ defines if they exist in board pin definition. (#991) 2022-11-22 17:42:32 -08:00
Earle F. Philhower, III 0133ecc887 Avoid race conditions in I2C(Wire) callbacks (#995)
Fixes #979

Make sure to read the last byte of I2C data in the case where the IRQ happens
and the STOP signal is also asserted.

Also ensure all branches of the IRQ handler look at the same point in time
value for the IRQ status.
2022-11-22 17:14:44 -08:00
Paint Your Dragonandlady ada 913dfad1ad Add Adafruit Feather RP2040 SCORPIO (#987)
* add rough for scorpio

* Add SCORPIO items from ladyada

* Change PID in makeboards.py instead of boards.txt

* Fix PID in scorpio JSON

* README: Add Feather SCORPIO to supported boards

* Fix PIDs using values from MBAdafruitBoards

Still unsure about pid.[1-7] but let's see what happens

* boards.txt fixed by running makeboards.py

Co-authored-by: lady ada <limor@ladyada.net>
2022-11-22 16:56:48 -08:00
Earle F. Philhower, III 2062f94adc Update README.md 2022-11-21 09:01:30 -08:00
Maximilian Gerhardt f9db547cf3 Do not require USB init variable for TinyUSB (#981) 2022-11-21 09:00:41 -08:00
Maximilian Gerhardt 2782dd1716 Add Waveshare RP2040 Zero (#980) 2022-11-21 08:52:00 -08:00
Sylwester 852219caf5 Add DatanoiseTV PicoADK board (#964) 2022-11-08 16:18:03 -08:00
Earle F. Philhower, III 07fbed06c6 Fix Arduino Nano Connect USB VID:PID tuples (#970)
Fixes #968
2022-11-08 08:59:21 -08:00
Earle F. Philhower, III ea5f8241e3 Remove stdio.h include from CYW43 SDK override (#965) 2022-11-07 08:48:54 -08:00
Earle F. Philhower, III 895ffced8e Fix analogWrite scaling issues (#962)
The PWM internals on the RP2040 are based on 8 slices with independent
clocking.  Make sure that we init the PWM slice being used only once per
change of frequency/range.

Only init the scaling values one time, because we also adjust the input
scale/frequency values when calculating them.  If we ran this twice (i.e.
writing to two slices), it would overwrite the pseudo scale/slow scale
values with 1 causing the wrong PWM values to be set.

Fixes #955
2022-11-07 06:43:14 -08:00
Earle F. Philhower, III 40855c90fb Update version 2022-11-03 08:54:31 -07:00
Earle F. Philhower, III 6570c4856b Fix deadlock in attachInterruptParam (#953)
Thanks to @imwoo90 comment in https://github.com/earlephilhower/arduino-pico/issues/878#issuecomment-1302276196
2022-11-03 08:40:57 -07:00
风飘雨 008c4d62ef Fix SerialPIO bit length, update flyboard2040 pins (#950) 2022-11-03 08:35:40 -07:00
Earle F. Philhower, III 63dfd9ab6b Properly disable Ethernet IRQ, don't drop packets (#951)
Fix #944
2022-11-02 15:27:02 -07:00
Earle F. Philhower, III 9b28fc3e17 Free PIO SM on SerialPIO::end (#949)
Fixes #945
2022-10-31 17:10:59 -07:00
Drzony 6bbaf64daf Async scan + bugfixes (#947)
* Support asynchronous WiFi scan

* Fixed buffer overflow in getChipId

* ESP compatibility fixes

* fixup! ESP compatibility fixes
2022-10-31 17:01:10 -07:00
AngeloGioacchino Del Regno 44eeebbc6f cores/rp2040: _freertos.cpp: Avoid memory leak and unnecessary allocation (#948)
There's a memory leak around the corner: creating the mutex means
that we allocate memory for it, but if we cannot find any free slot in the
FMMap array, we're simply returning a nullptr without ever freeing the
previously allocated memory.

Instead of allocating it out of the free-slot check, do it inside.
While at it, also check if the mutex creation succeeded before assigning
it to a FMMap slot.
2022-10-31 14:29:00 -07:00
Earle F. Philhower, III ec7631096b Update GH actions to non-deprecated versions (#938) 2022-10-27 14:35:52 -07:00
Earle F. Philhower, III 07a1484d72 Add WiFi.channel() reporting (#937)
Also return error conditions when WiFi status is inquired while not
connected.
2022-10-27 13:02:09 -07:00
Earle F. Philhower, III 9503620525 Add WiFi.BSSID() undocumented call (#936)
Using same method as #934 and Infineon wifi-host-driver sources
2022-10-27 09:09:48 -07:00
mecparts e05a3b8ad0 Add a way to return the RSSI value (#934)
See https://forums.raspberrypi.com/viewtopic.php?t=341774
2022-10-27 08:00:59 -07:00
Earle F. Philhower, III 9d0b9bef67 Update version 2022-10-25 08:02:54 -07:00
per1234 0446b732fa Add protocol-explicit upload.tool properties required for pluggable discovery compatibility (#933)
A new flexible and powerful "pluggable discovery" system was added to the Arduino boards platform framework. This system
makes it easy for Arduino boards platform authors to use any arbitrary communication channel between the board and
development tools.

Boards platform configurations that use the old property syntax are automatically translated to the new syntax by
Arduino CLI:

https://arduino.github.io/arduino-cli/latest/platform-specification/#sketch-upload-configuration

> For backward compatibility with IDE 1.8.15 and older the previous syntax is still supported

This translation is only done in platforms that use the old syntax exclusively. If `pluggable_discovery` properties are
defined for the platform then the new pluggable discovery-style `upload.tool.<protocol_name>` properties must be defined
for each board as well.

This platform includes a "UF2 Devices" discovery tool for `uf2conv` protocol ports. This tool now uses the modern
Arduino pluggable discovery system. `pluggable_discovery` properties were added to `platform.txt` in order to configure
the Arduino development tools to use this pluggable discovery tool. The `upload.tool.<protocol_name>` properties in
`boards.txt` were not updated at that time.

Global properties of that name were added to platform.txt, but this approach is not provided for by the Arduino Platform
specification:

https://arduino.github.io/arduino-cli/latest/platform-specification/#sketch-upload-configuration

> A specific upload.tool.<protocol_name> property should be defined for every board in boards.txt:

Those missing properties caused uploads to fail for users of the recent versions of Arduino IDE and Arduino CLI with an
error of the form:

Error during Upload: Property 'upload.tool.<protocol_name>' is undefined

(where `<protocol_name>` is the protocol of the selected port, if any)

It is also important to provide compatibility with versions of Arduino development tools from before the introduction of
the modern pluggable discovery system. For this reason, the old style `<board ID>.upload.tool` properties are retained.
Old versions of the development tools will treat the `<board ID>.upload.tool.<protocol_name>` properties as an unused
arbitrary user defined property with no special significance and the new versions of the development tools will do the
same for the `upload.tool` properties.
2022-10-24 08:50:13 -07:00
Earle F. Philhower, III c3da4ada61 Add basic Pimoroni PGA2040 board definition (#930)
Because the board needs a unique BOOT2.S, add a definition to make it
easier to use.
2022-10-22 10:19:30 -07:00
Earle F. Philhower, III 4fdcc6e5ac Only init PWM on requested pin (#926)
Avoid glitches on other pins, fix #919
2022-10-20 04:56:44 -07:00
Maximilian Gerhardt b82336c8d9 Add W25Q64JV QSPI /4 Boot2 file (#929)
Fixes #927
2022-10-20 04:25:37 -07:00
Earle F. Philhower, III 075958883f Update version 2022-10-16 10:50:29 -07:00
Fredrik Jansson fe632cde4b Increase analogWrite frequency range, bugfixes (#918)
* analogWrite: fix overflow and wrap value (#917)

-avoid overflow when calculating analogScale * analogFreq, perform
the multiplication in floating point.

-use analogScale - 1 to set the PWM wrap value. Wrap is the highest
value the counter reaches, not the counter period.

* analogWrite: increase frequency range (#917)

- increase frequency range to 10 MHz

- decrease the lowest allowed resolution to 2 bits, and the
  minimal analogRange value to 3. This makes 10 MHz output possible
  with system clock frequencies down to 50 MHz.

- allow clkdiv values >= 1.0, was 2.0. This makes it possible to
  manually set frequency and analogRange so that
  frequency * analogRange = system clock frequency.
  This gives the best possible frequency accuracy and
  resolution.
2022-10-16 10:43:49 -07:00
Earle F. Philhower, III 10090b60a9 Rewrite PicoW LWIP interface for stability (#916)
Random crashes, infinite loops, and other lockups were happening to the PicoW
while under high load from multiple clients.

This seems to have been due to two issues:

* The periodic sys_check_timeouts() call from an alarm/IRQ was happening while
  the core was in LWIP code. LWIP is not re-entrant or multi-core/thread safe
  so this is a bad thing. Some calls may not have been locked with a manual
  addition of the LWIPMutex object to hit this.
* The WiFi driver supplies packet data during an interrupt. PBUF work is
  legal in an interrupt, but actually calling netif->input() from an IRQ to
  queue up the Ethernet packet for processing is illegal if LWIP is already
  in progress.
   
Rearchitect the LWIP interface to fix these problems:
* Disable interrupts during malloc/etc. to avoid the possibility of the
  periodic LWIP timeout check interrupting and potentially calling user
  code which did a memory operation
* Wrap all used LWIP calls to note LWIP code will be executing, instead of
  manually eyeballing and adding in protection in user code.
* Remove all user code LWIPMutex blocking, the wrapping takes care of it.
* When an Ethernet packet is received by interrupt and we're in LWIP code,
  just throw the packet away for now. The upper layers can handle retransmit.
  (A possible optimization would be to set the packet aside and add a
  housekeeping portion to the LWIP wrappers to netif->input() them when safe).
* Ignore callbacks during TCP connection teardown when the ClientContext
  passed from LWIP == nullptr
2022-10-15 12:00:35 -07:00
Earle F. Philhower, III a6bdb27178 Use static allocation for IRQ stack (#915)
noInterrupts/interrupts use a stack to allow multiple calls to work
properly.  The original code was using a std::stack which will use
malloc() to allocate entry space.  This seems like a bad idea, and
makes it so it's impossible to disable interrupts for malloc/free,
etc.

Define a fixed stack size and use straight C code to manage the IRQ
stacks.  Slightly more fixed memory requirements, but significantly
lower total RAM requirements and no malloc() dependency.
2022-10-14 13:46:00 -07:00
brtchip-tuannguyen 62ed93f12a Add board BridgeTek IDM2040-7A (#912) 2022-10-13 08:26:11 -07:00
Earle F. Philhower, III e89ce78c79 Fix memory leak in WebServer (#914)
Fixes #908
2022-10-12 11:25:56 -07:00
Earle F. Philhower, III 98c4b921b8 Un-hardcode LED pin in AdvancedWebServer example (#909)
Partial #908
2022-10-11 09:30:41 -07:00
Sabas 86765cebb2 Update VID&PID HunterCatNFC 2040 (#907) 2022-10-11 09:12:56 -07:00
Earle F. Philhower, III 25ceb08f93 Clear LWIP started flag on LWIPIntfDev::end (#905)
When moving between different modes or even WiFi.begin/ends, any setting
of the IPs will fail because the internal flag _started was not cleared.
Clear _started on a ::end call.

Fixes #884
2022-10-09 18:25:24 -07:00
Mücahid Kamber 205983e206 Adds Degz Mizu board (#904) 2022-10-07 15:52:18 -07:00
Earle F. Philhower, III 1e7098c1cb Add OpenOCD/GDB support for IDE 2.0 (#900)
Add (undocumented) support for the debugger in the IDE 2.0.
2022-10-05 12:19:18 -07:00
Earle F. Philhower, III 68ecdfc023 Update README.md 2022-10-05 07:15:50 -07:00
Melopero a9356ceca5 Add Melopero Cookie RP2040 (#899) 2022-10-05 07:10:07 -07:00
Earle F. Philhower, III 69ab736cf8 Update version 2022-10-04 17:14:52 -07:00
Earle F. Philhower, III 3e758dcebb Add TARGET_RP2040 to build defines (#898)
Fixes #896 since it seems the Arduino.cc core defines this constant
2022-10-04 17:04:25 -07:00
Earle F. Philhower, III b249811e28 Support IDE2, detect UF2 volumes (#897)
Allow the IDE to detect UF2 volumes (i.e. when you hold BOOTDEL and
plug in the board).

Allows the IDE2 to properly upload using OTA and serial.

Fixes #890 and others
2022-10-04 16:52:36 -07:00
Earle F. Philhower, III 7f216f35ab Allow double-reset to jump to USB bootloader (#893)
Call `rp2040.enableDoubleResetBootloader()` anywhere in the code to
enable the check.  W/o that call, the checker will be linked in.

See #892

CORE1 doesn't start until well after the C runtime initialization,
so the flag won't be overwritten.

Also increase timeout to 350ms because OTA bootup can be
slow.
2022-10-04 14:04:40 -07:00
Earle F. Philhower, III 029471ecca Drive pin LOW after Tone(period) timeout (#887)
Fixes #886
2022-09-29 13:03:49 -07:00
Earle F. Philhower, III 4cc6c36c37 Fix Serial1/2 debug output mode in CoreMutex (#883)
Fixes #882
2022-09-26 14:19:00 -07:00
Earle F. Philhower, III 0cd5b0ac47 Allow setCTS/RTS(UART_PIN_NOT_DEFINED) (#881)
Fixes #880
2022-09-26 08:13:44 -07:00
Earle F. Philhower, III 939c83127e Fix deadlock during attachInterrupt (#879)
Fixes #878
2022-09-25 10:02:48 -07:00
Tim Boldt 3768aa7e1f Fix typo in HttpClient HTTPS example (#876) 2022-09-24 19:23:56 -07:00
Earle F. Philhower, III 7a85c3917f Allow setting the WiFi region for PicoW (#875)
Fixes #874
2022-09-23 12:22:22 -07:00
Earle F. Philhower, III cd0e83843f Update version 2022-09-21 19:19:24 -07:00
Earle F. Philhower, III 78ce055165 Ensure ArduinoCore API is included in package (#871) 2022-09-21 19:18:53 -07:00
Earle F. Philhower, III d9478801ed Update version 2022-09-21 17:56:26 -07:00
Earle F. Philhower, III 77fe24f798 Update Cytron Pico SPI pinout (#869)
See #851.  Add SPI1.
2022-09-21 17:55:41 -07:00
Brent Rubell 4e77ee02e8 Add WDT functions to RP2040 Helper (#862) 2022-09-21 17:51:42 -07:00
Pontus Oldberg 91b4bdb58f Adds Challenger RP2040 NFC board (#846) 2022-09-09 07:41:33 -07:00
Dario GogliandoloandDario Gogliandolo d6628972c5 Enabled static memory allocation with example (#842)
Co-authored-by: Dario Gogliandolo <dario.gogliandolo@smartme.io>
2022-09-08 07:09:38 -07:00
Earle F. Philhower, III b0d0e292c9 Minor - Add number separators (#845) 2022-09-07 15:19:12 -07:00
Earle F. Philhower, III e2b04e7405 Minor tweak, NULL=>nullptr (#844) 2022-09-07 14:41:04 -07:00
Earle F. Philhower, III f79b0867b6 Remove duplicated ArduinoCore-API files (#840)
Use #include .... to reference them from the cores directory to ensure
they keep up to date.
2022-09-06 13:21:49 -07:00
Earle F. Philhower, III db337a9b36 Increase SerialUSB speed (#833)
Add calls to `tud_task` to pump the USB interface in the SerialUSB methods.

See #832 for more info.
2022-09-06 12:44:34 -07:00
Khoi Hoang 1303ef55b2 Add Serial3 for Arduino Nano Connect RP2040. Fix #807 (#838) 2022-09-06 12:34:49 -07:00
Earle F. Philhower, III 85d39cf242 Restore GPIO functions on SerialUART::end (#836)
Fix #834
2022-09-04 19:23:51 -07:00
Earle F. Philhower, III 2d777accc6 Update README.md 2022-09-04 11:38:58 -07:00
Earle F. Philhower, III 3f36f7fab1 Update README.md 2022-09-04 11:38:46 -07:00
Earle F. Philhower, III 1812b829dc Update version 2022-09-03 09:34:46 -07:00
Earle F. Philhower, III 36d5cebde6 Remove binary info header, was crashing picotool (#831)
Because OTA has changed the flash map from standard, picotool ends up
crashing or hanging while trying to operate on the current built files.

Remove the binary_info calls and structures completely to avoid any
issue.

Fixes #803
2022-09-02 23:17:03 -07:00
Earle F. Philhower, III 34d311fd81 Update version 2022-09-02 08:59:01 -07:00
Earle F. Philhower, III 59bd3b5144 Update DNSServer.h 2022-09-01 21:04:41 -07:00
Earle F. Philhower, III 805d20d199 Use pipes between GCC stages (#827)
Should speed builds up slightly, depending on the OS and virus scanning.
2022-09-01 18:49:05 -07:00
Earle F. Philhower, III 166f63f955 Update PicoOTA.h 2022-08-31 14:40:53 -07:00
Earle F. Philhower, III d2beb2da19 Add upsteam multicast compatibility APIs (#821)
Fixes #747 while remaining ESP8266 compatible
2022-08-31 11:06:18 -07:00
Earle F. Philhower, III 7ef44d9878 Clean up WebServer send() methods (#820)
Avoid creating Strings when sending out results.
2022-08-31 08:21:16 -07:00
Earle F. Philhower, III 408813c387 Add SDFS header to SpeedTest to simplify use 2022-08-31 08:09:42 -07:00
Earle F. Philhower, III 4d2f64a12b Add bidirectional bulk SPI transfer, update SdFAT (#819)
Should speed up SD transfers significantly (2.5x+).

See #801
2022-08-31 07:42:34 -07:00
Earle F. Philhower, III 9997461e3a Shrink MIME table flash usage by ~500 bytes (#818)
Decreases WebServer sketch sizes.
2022-08-30 19:21:57 -07:00
Earle F. Philhower, III 4699522299 Remove completed TODO 2022-08-30 16:28:24 -07:00
Earle F. Philhower, III a582ca7b95 Avoid potential lockup w/Serial.read unconnected (#817)
Fixes #816

If a byte is available, return it even if the USB stack reports
disconnected.
2022-08-30 12:05:08 -07:00
Filipe Mendonça 024ae9bb42 Fix WiFi MAC Address string output (#812)
Fixes #811
2022-08-29 17:51:40 -07:00
Earle F. Philhower, III 38bcf4f956 Minor WebServer style/unused var cleanup (#810) 2022-08-29 13:25:32 -07:00
Earle F. Philhower, III 486caf42a0 Remove microscopic malloc() from WebServer (#809)
Don't try and heap allocate temporaty <16b chunks.
2022-08-29 12:35:14 -07:00
Earle F. Philhower, III 92f2ca9108 Don't re-initialize ADC for every reading (#808) 2022-08-29 11:46:05 -07:00
Earle F. Philhower, III bde4da2b7e Protect core/Newlib mutexes from task preemption under FreeRTOS (#798)
Fixes #795 

Replace all CoreMutex and Newlib mutex accesses with FreeRTOS calls
when in FreeRTOS mode.  Avoid issues with hange/etc. due to priority
inversion.

No changes to normal operating mode.

Add a FreeRTOS stress test that caught the issue fixed here.
2022-08-29 08:56:59 -07:00
Earle F. Philhower, III b4b1c39049 Add ExteremeElectric JSON 2022-08-28 12:38:14 -07:00
Earle F. Philhower, III b233cb6e7f Identify boards when in compound USB device mode (#806)
Allows the IDE to detect boards when using the Keyboard, Joystick,
or Mouse libraries.

Thanks @DaleMitchell for the idea!
2022-08-28 12:34:06 -07:00
Danilo Campos 95d1bfb760 Add Home Assistant starter to tutorials listing (#804) 2022-08-28 09:45:49 -07:00
Earle F. Philhower, III 064dd4794f Minor header/directrory cleanup (#802) 2022-08-27 13:04:57 -07:00
Earle F. Philhower, III 257db5ac7d Update version 2022-08-27 09:33:50 -07:00
Earle F. Philhower, III 9ff31b91f4 Add ExtremeElectronics RC2040 (#799)
Fixes #797
2022-08-25 12:47:39 -07:00
Earle F. Philhower, III 0edba2ee2a Add WebServer, WebServerSecure, HTTPUpdateServer, HTTPUpdateServerSecure (#791)
* Add HTTP-parser lib to support ESP32 WebServer
* Add WebServer from ESP32.  Only supports HTTP
* Separate HTTP server from the network server
Instead of managing the WiFiServer/WiFiServerSecure in the same object
as the HTTP handling, split them into separate objects.  This lets
HTTP and HTTPS servers work without templates or duplicating code.
The HTTP block just gets a `WiFiClient*` and works with that to only
do HTTP processing, while the upper object handles the appropriate
server and client types.
* Add HTTPS server
* Clean up some THandlerFunction refs
* Refactor into a template-ized WebServer/WebServerSecure
* Add DNSServer examples which need WebServer
* Fix CoreMutex infinite recursion crash
Core could crash while Serial debugging was going on and prints were
happening from LWIP/IRQ land and the main app.
* Add HTTPUpdateServer(Secure)
* Add MIME include, optimize WebServer::send(size,len)
When send()ing a large buffer, the WebServer::send() call would
actually convert that buffer into a String (i.e. duplicate it, and
potential issues with embedded \0s in binary data).
Make a simple override to send(size, len) to allow writing from the
source buffer instead.
* Fix WiFiClient::send(Stream), add FSBrowser example
2022-08-23 15:51:32 -07:00
NuclearPhoenix c501306c4f Fix functions in docs: RP2040 Helper Class (#793) 2022-08-23 07:40:18 -07:00
Earle F. Philhower, III 8aad2ca3d2 Update version 2022-08-21 19:54:11 -07:00
Earle F. Philhower, III de215a6e1b Add WiFi.getHostname() call 2022-08-21 19:53:18 -07:00
Earle F. Philhower, III 0b390d7dc4 Add HTTPUpdate class to pull updates from HTTP(S) (#789)
* Add HTTPUpdate class to pull updates from HTTP(S)
* Increase GH runners for pulls
WiFi builds and examples are taking some serious time now
* HTTPUpdate tests build on Pico W
2022-08-21 18:24:59 -07:00
Earle F. Philhower, III a3f5fee6a5 Make StreamDev stubs private to HTTPClient (#788) 2022-08-21 17:20:34 -07:00
Earle F. Philhower, III a3f4d89bc4 Ensure OTA errors are sent in single UDP packet (#787)
OTA text error messages were getting lost because they were sent in
multiple UDP packets, one per print(). Now collect the full error and
report in a single print, allowing text messages to appear in ESPOTA.
2022-08-21 15:29:23 -07:00
Earle F. Philhower, III 2044d2e51c Fix OTA signing (#786)
Force the builder to include the path where we build the signing header.

Undo a breaking bug in the Updater class (TBD fix in ESP8266)

Fixes #783
2022-08-21 15:20:00 -07:00
Earle F. Philhower, III f9e3278863 Report "no filesystem" on OTA uploads w/o a FS (#785)
Give a meaningful error when OTA is attempted against a chip which does
not have a filesystem configured.
2022-08-21 13:19:26 -07:00
Earle F. Philhower, III 0d15723444 Add HTTPClient, ported from the ESP8266 (#784)
Remove the need to have a separate WiFiClient that's destroyed after
the HTTPClient.  Let the object handle its own client, and pass through
any SSL requests.

Also supports the original ::begin methods which need a
WiFiClient(Secure) to be passed in and managed by the app.
2022-08-21 12:49:06 -07:00
Earle F. Philhower, III 6e0d6a27ec Avoid rescanning/connecting on WiFiMulti.run (#782)
If the WiFi network is already up, don't run the scan and connection
algorithm in WiFiMulti.
2022-08-21 08:33:17 -07:00
Earle F. Philhower, III a2465f5fb7 Port ESP8266 DNSServer (#779)
Add a simple DNS server for AP mode
Point DHCP server DNS entry to GW for DNSServer
2022-08-20 17:58:54 -07:00
arturo182 88e98f17b6 EEPROM: Add an update function (#780)
According to the Arduino docs, update works just like put, but it first checks if the value is different from the current one.
This is how our put already works, so we just alias update to put and we're done.
Function added to be more compatible with the Arduino API.
Also see #778
2022-08-20 17:50:40 -07:00
Earle F. Philhower, III b4db1ad54a Fix softAP config call 2022-08-20 12:24:08 -07:00
Earle F. Philhower, III 7be472932b Add ESP8266 compat functions for AP mode (#777)
Fixes #767
2022-08-20 12:00:05 -07:00
Earle F. Philhower, III d019f31ef1 Report ::connected() as false when WiFi link drops (#774)
There may be an issue in the CYW43 driver that causes a link to never be
reported as going down once it has connected, when it was disassociated or
when the wlan shuts off unexpectedly.

Work around it by clearing the internal link active in a TCP callback for
the CYW43 driver.

Reports disconnection properly now, as well as reconnection.

Fixes #762
2022-08-19 18:03:21 -07:00
Earle F. Philhower, III e2afeaef27 Add simple WiFiMulti support (#771)
Takes a list of APs, finds the one with highest RSSI, and tries to connect.
2022-08-19 12:28:56 -07:00
Earle F. Philhower, III 2b6ab6c19d Don't return from reboot (#772)
rp2040.reboot() would set a reboot timer for 100ms in the future, but then
return to user code and ran it until the timer expired.  Now infinite loop
until the WDT fires.
2022-08-19 12:21:17 -07:00
Earle F. Philhower, III 0ef026cfa4 Avoid spurious -O3 warning (#770)
Fixes #768
2022-08-18 13:56:09 -07:00
Earle F. Philhower, III 5787b4c02b Allow selecting SPI port for SD/SDFS filesystem (#759)
Fixes #758
2022-08-14 21:59:13 -07:00
Earle F. Philhower, III e947895119 Update version 2022-08-12 12:29:32 -07:00
Earle F. Philhower, III bb91d978b1 Add OTA.O to make p.io builds function (#755)
Partial #754
2022-08-12 06:09:29 -07:00
Earle F. Philhower, III da86a8942b Add OTA update support (#711)
Adds a 12K OTA stub 3rd stage bootloader, which reads new firmware
from the LittleFS filesystem and flashes on reboot.

By storing the OTA commands in a file in flash, it is possible to
recover from a power failure during OTA programming.  On power
resume, the OTA block will simply re-program from the beginning.

Support cryptographic signed OTA updates, if desired.  Includes
host-side signing logic via openssl.

Add PicoOTA library which encapsulates the file format for
the updater, including CRC32 checking.

Add LEAmDNS support to allow Arduino IDE discovery

Add ArduinoOTA class for IDE uploads

Add MD5Builder class

Add Updater class which supports writing and validating
cryptographically signed binaries from any source (http,
Ethernet, WiFi, Serial, etc.)

Add documentation and readmes.
2022-08-12 00:26:51 -07:00
freeasabeer 71be07e69f Increase FreeRTOS timer task stack to 1024 (#752) 2022-08-11 14:30:57 -07:00
Odd Stråbø be18c76c99 Udp: default local_ip to IP_ANY_TYPE when IPv6 is enabled (#750) 2022-08-10 15:25:02 -07:00
Earle F. Philhower, IIIandOdd Stråbø af2671d8eb IPv6 initial support from @oddstr13 (#748)
* Apply @oddstr13 multicast patch to cyw43 driver
* Initial work for enabling IPv6
* Allow accessing CYW43 stats when LWIP_SYS_CHECK_MS is not set
* Use cyw43_set_allmulti to allow receiving multicast
* Add tools/libpico/build to gitignore

Co-authored-by: Odd Stråbø <oddstr13@openshell.no>
2022-08-09 18:05:43 -07:00
Maximilian Gerhardt 11cb82b058 Fix typo in XIAO board name (#745) 2022-08-09 09:57:51 -07:00
Earle F. Philhower, III ab6a2aaadb Update README.md 2022-08-07 21:36:23 -07:00
Sabas a358f892d3 Add board ElectronicCats Hunter Cat NFC (#741)
* add board ElectronicCats Hunter Cat NFC

* update huntercat nfc
2022-08-07 21:36:04 -07:00
Earle F. Philhower, III cabb06d495 Fix UART wrong ::available() during wraparound (#739)
Fixes #735 .  Thanks to @ Haggarman for the find and fix.
2022-08-06 09:38:16 -07:00
Earle F. Philhower, III 005cba3acd Stop random crashes while writing to flash (#730)
FreeRTOS SMP was updated to:
a) Move ths SYSTICK handler, which cannot be disabled and can fire
   even with IRQs disabled, to RAM
b) Add a flag from the core to the SYSTICK handler to hold off on
   any PendSV (task switch) calls while we are doing the idleOtherCore.

The core now sets this flag, _holdPendSV, and adds add'l FreeRTOS SMP
calls to really, really tell the OS we can't, don't, and better not
be swapped out while writing to flash.

Fixes #719
2022-07-29 22:40:48 -07:00
Earle F. Philhower, III bb029cc287 Increase LWIP MEM_SIZE to > TCP_SND_BUF (#731)
The send buffers are set to 8 * MSS = ~11.5K.  MEM_SIZE is now set to
be larger than that, 16K, in order to help avoid having tcp_write fail
with ENOMEM.  The attempt to use a smaller size is still included, which
will allow a tcp_write of up to 16 * 16K = 256K, i.e. all of memory.

Fixes #725
2022-07-29 22:35:37 -07:00
Earle F. Philhower, III 8fd56ada8b Adjust tcp_write size when memory is tight (#729)
Increases the MEM_SIZE outstanding write buffer to 8K

Allows the ClientContext to attempt to send smaller buffer chunks in the
case where MEM_SIZE won't allow the full tcp_sndbuf() transfer.

Fixes #725
2022-07-29 13:40:03 -07:00
Earle F. Philhower, III 5ab19e9a9f Fix I2S timing (#728)
BCLK was running at 50% of expected speed.

Fixes #714
2022-07-29 12:40:04 -07:00
Earle F. Philhower, III 82abc76e0c Add CMSIS defines to Platform.io (#721)
Ref: https://github.com/earlephilhower/arduino-pico/pull/717#issuecomment-1197921851
2022-07-28 12:29:16 -07:00
AngeloGioacchino Del Regno 6e0175bd8e platform.txt: Add compiler flags for ARM CMSIS (#717)
Adds compiler flags to correctly build Cortex-M0/M0+ code variants for
libraries inside of the ARM CMSIS codebase.

This was tested with the Arduino_CMSIS-DSP library.
2022-07-27 19:11:50 -07:00
Pontus OldbergandEarle F. Philhower, III e6e87fd307 Added to possibility to have extra compiler directives for a board. (#713)
* Adds support for Challenger RP2040 WiFi boards

* Added Challenger board to makeboards build script

* Adds new challenger board with LTE modem.

* Updated after getting approved PID from Raspberry Pi

* Add support for reverse numbering of analog pins.

* Added minimal HW support for onboard WiFi modem.

* Added challenger-nb-rp2040-wifi and RPICO32 module.

* Updated PID for RPICO32

* Added a simple support class for challenger LTE boards

* Update ChallengerLTE.cpp

Fixed spelling error

* Adds option for setting USB max power in makeboards.py

* Added new board Challenger RP2040 LoRa

* Added new lora board to readme.

* Added missing SERIAL2 and LoRa module GIO pins.

* Added support for enabling UART CTS and RTS pins.

* Updated boards.txt after merge conflict of makeboards.py

* Fixed incorrect indention

* Fixed PR comments

* Add new Challenger RP2040 WiFi/BLE board (https://ilabs.se/challenger-rp2040-wifi-ble-datasheet)

* * Updated PID for WiFi/BLE board
* Added abstraction pins for both versions of wifi modules
* Added support for replacing support class serial port.
* Added support for retrieving support class serial port.

* Fixed spelling errors.

* Updated helper class for Challenger NB board.

* Added Challenger sdrtc and subghz boards.

* Updated readme.

* Re ran makeboards to generate new index.

* Added to possibility to have extra compiler directives for a board.

* Added extra compiler options to JSON generation.

* Allows having a list of extra macros to define

* Fixed incorrect USB PID for Challenger NB board.

* Added board initialization for all wifi boards.

Co-authored-by: Earle F. Philhower, III <earlephilhower@yahoo.com>
2022-07-27 08:36:50 -07:00
Earle F. Philhower, III 1f5139d209 Update version 2022-07-24 12:58:02 -07:00
Earle F. Philhower, III 2397d034e3 Remove SPI init from CYW43 ethernet shim 2022-07-23 14:20:10 -07:00
Earle F. Philhower, III c889a3c1f0 Add NTP waitSet callback (#705)
Allows printing "."s or flashing an LED while NTP is waiting for sync.
2022-07-23 14:07:11 -07:00
Earle F. Philhower, III cfc05dab2c Add basic ESP32 WiFiClientSecure support (#704)
Simple sketches should work without modification, but some modes (listed
in the docs) are not possible to support on the Pico W with BearSSL.

Fixes #691
2022-07-23 10:59:40 -07:00
Earle F. Philhower, III 4a174106cc Add BearSSL to README 2022-07-22 12:48:52 -07:00
Earle F. Philhower, III f04c8536c8 Make AP mode report WL_CONNECTED (#702) 2022-07-22 12:32:28 -07:00
Earle F. Philhower, III a97dc38e87 Uploading for the first time docs from @fjansson (#699)
Fixes #688
2022-07-21 12:09:49 -07:00
Earle F. Philhower, III 042c6af887 Add USB VID/PID to Platform.IO HWIDs (#698) 2022-07-21 12:08:21 -07:00
Earle F. Philhower, III 0e18f0986a Enable IPv4 or IPv4/IPv6 stacks, Ethernet class (#695)
IPv4-only mode saves 20KB+ of flash memory.

Add some backwards compatibility with the global Arduino Ethernet
class when running in IPv4 only mode.

Fixes #687

* Speed P.IO build by not cloning 2GB of sources
* Document P.IO new option
2022-07-21 11:57:21 -07:00
Maximilian Gerhardt 40f4fdf246 Fix PlatformIO linking for variant-specific overrides (#696) 2022-07-21 04:49:09 -07:00
Benjamin AignerandBenjamin Aigner 67b3c8fc25 Adding a Joystick library, concurrently usable with Keyboard & Mouse (#692)
Co-authored-by: Benjamin Aigner <beni@asterics-foundation.org>
2022-07-21 04:40:04 -07:00
Earle F. Philhower, III b88ad3d143 Support original Pico with ROM B0 (#693)
The SDK disabled float/double support for some functions by default on the
original B0 ROMs.  Manually re-enable it.

Fixes #689
2022-07-20 12:07:34 -07:00
Maximilian Gerhardt be9e25785c Correct PlatformIO build for Pico W, add to CI (#686)
* Add LWIP defines from platform.txt

* Add WiFi example to PIO CI
2022-07-19 08:09:47 -07:00
Earle F. Philhower, III 824070b899 Update version 2022-07-18 20:28:49 -07:00
Earle F. Philhower, III c3a580ee89 Add WiFiClientSecure and WifiServerSecure (TLS) support, NTP (#683)
* Add TLS (https) support
* Add NTP server
* Clean up include path, add BearSSL headers
* Allow 2 NTP servers, add ESP8266 compat define
* Add MFLN SSL example, free/used/total heap getters
* Enable stack thunking
* Add tested SSL examples
* Add BSSL_validation demo
* Add Client Certificate example
* Add RP2040 helper docs
* Clean up doc errors, missing doc version info
* Add WiFiClientSecure documentation
* Add NTP docs

Fixes #679
2022-07-18 20:24:11 -07:00
Earle F. Philhower, III 53cecae109 Update version 2022-07-17 05:52:01 -07:00
Earle F. Philhower, III 61742c9357 Disable WiFi.begin on plain Pico, add JSON (#682) 2022-07-17 05:51:03 -07:00
Earle F. Philhower, III fee036604c Provide dummy CYW43 callbacks when no WiFi used (#681)
Fixes #680
2022-07-16 11:57:27 -07:00
Earle F. Philhower, III 988940b25e Update version 2022-07-15 16:49:36 -07:00
Earle F. Philhower, III abf2c586c7 Add Pico W WiFi support (#670)
* Add support for the WiFi chip on the Pico W board.
* USB interrupt now no longer hard coded (conflicted with the WiFi IRQ).
* Add in Pico W board to makeboards.py
* Add in GPIO and variant support
* Initialize WiFi in the Variant
* Use manual LWIP, fix size accounting
* Remove the SDK WiFi overrides
* Pulling in work done in the ESP8266 core.
* Make IPAddress support IPv6
* Build LWIP with IPv4 and IPv6 support
* Use proper MAC
* Avoid cyw_warn crash.  Make macro to a comment while building
* Add WiFiServer
* Add WiFiUdp
* Move LWIP-specific support files to LWIP_Ethernet
* Add WiFi::ping (ICMP ping)
* Move ICMP echo (ping) to LWIPIntfDev
* Move hostByName to LwipIntfDev
* Add AP mode with simple DHCP server
* Add some examples and basic ESP8266 compat hacks
* Update Adafruit TinyUSB to fix crash
* Set DHCP hostname
* Make Wifi.begin() return CONNECTED with link + IP
* Return connected() on WiFi::begin
* Fix spurious TCP retransmission
* Protect LWIP from reentrancy

The Pico SDK calls "sys_check_timeouts() from inside a periodic interrupt.
This appears unsafe, as the interrupt could happen while already in the
(non-reentrant) LWIP code.

Block the interrupt from calling sys_check_timeouts by using a global flag
manually set via an RAII recursive lock.

Add interrupt protection macros around critical sections inside LWIP via
the standard defines.

These two changes should make LWIP significantly more stable and long
running.

* Support disconnecting and reconnecting WiFi
* Add WiFiServer simple example
* Update documentation

Fixes #666
Fixed #665
2022-07-15 16:47:53 -07:00
Earle F. Philhower, III c025c4a1f8 Fix ::printf/etc. due to mutex size conflict (#677)
When real multicore/lockign support was added to newlib, there was an opaque
field in FILE that was used as a mutex, but was only 4 bytes in size.  The
recursive mutexes on the RP2040 are 8 bytes.  This mismatch caused corruption
of the FILE structure and crashes of the system when ::printf/::puts/etc. were
run.

Adjust the lock field size in FILE to 8 bytes and rebuild the toolchain to
fix.
2022-07-14 09:04:02 -07:00
Earle F. Philhower, III fb05d96979 Add delay to 2nd core start for Picoprobe (#676)
No idea why, but when a Picoprobe upload and reset is used, the 2nd core
does not start w/o a __wfe() call on the first one before launch.

Fixes #674
Fixes #402
2022-07-14 07:43:27 -07:00
Earle F. Philhower, III 8eb030ed89 Update TinyUSB to 1.13.3 (#672)
Fix errors in WebUSB buffering
Fixes #642
2022-07-08 13:45:01 -07:00
Pontus Oldberg 5be405308e Add support for new SD/RTC and SubGHz boards (#663) 2022-06-30 10:16:44 -07:00
Earle F. Philhower, III af0c1c87f5 Automatically update the JSON file in makeboards (#664)
Keep the Arduino Board Manager list up-to-date from makeboards.py
2022-06-29 12:50:42 -07:00
Earle F. Philhower, III cfaae84813 Update version 2022-06-28 15:07:55 -07:00
Earle F. Philhower, III da8ab1e9dd Return # of bytes written by SerialUSB::write (#662)
Before always returned 0 on a ::write.  Now properly return the count
of bytes that were sent to the USB port.

Thanks to Terry Haas for the report.
2022-06-28 13:01:06 -07:00
Maximilian Gerhardt baf65f510f Add notes on TinyUSB documentation and quirks (#659)
Fixes #648
2022-06-26 15:26:23 -07:00
Maximilian Gerhardt 13f68fbc64 Make TinyUSB linking work automatically with PIO (#658) 2022-06-26 13:24:55 -07:00
Stefan Staub 3071b3f2dd Update GPIO docs (digital.rst) (#656) 2022-06-25 10:00:29 -07:00
Earle F. Philhower, III de069cf8c9 Update version 2022-06-24 11:25:21 -07:00
Earle F. Philhower, III 8cf8923a18 Update to Adafruit_TinyUSB_Arduino 1.12.0 (#654)
* Update to Adafruit_TinyUSB_Arduino 1.12.0

* DualRole requires add'l libraries, skip in CI
2022-06-24 11:24:31 -07:00
Earle F. Philhower, III d954510c9d Update to latest pico-sdk develop branch (#653)
Fixes #651
2022-06-24 02:19:24 -07:00
Earle F. Philhower, III 8966a9b094 Actually pass in the PIO key for auto-publishing (#652)
Need to manually list the secrets to export to the environment.
2022-06-23 17:12:21 -07:00
Earle F. Philhower, III 3d9611d020 Update FreeRTOS SMP branch to latest upstream (#649) 2022-06-22 17:18:50 -07:00
Earle F. Philhower, III 78b7f26076 Update README.md 2022-06-20 19:17:52 -07:00
Earle F. Philhower, III 7233c39166 Update to latest pico-sdk, allow lock.c->lock.cpp (#646)
Minor change to keep the core all CPP.  Patch just made it into pico-sdk
develop branch allowing recursive mutexes to be auto_init in C++.
Update and rebuild libpico.a.
2022-06-20 11:14:31 -07:00
Earle F. Philhower, III 0ee072671b Update version 2022-06-20 08:30:24 -07:00
Earle F. Philhower, III 1130007761 Make mutexes init in DATA, not ((counstructor)) (#645)
There was a race condition in making mutexes that were only init in
an __attribute((constructor)) code block.  For example, a global
object might do a `malloc` in its constructor which would depend on
the malloc mutex...which may not yet have been initted.

Make them initted in the .data section, instead, which is guaranteed
good before any global constructors are called.
2022-06-20 08:29:08 -07:00
Earle F. Philhower, III a0060d9c3a Add dependency file generation to build (#644)
Fixes #643
2022-06-20 07:50:28 -07:00
Earle F. Philhower, III 66eb0613b0 Major multicore fixes Newlib and FreeRTOS (#640)
Instead of wrapping the memory functions in the link stage, rebuild
Newlib and enable retargetable locks.  Override the weak definitions
in the libc.a with our own, SDK based ones.

The wrapping utilized before catches app-level memory allocations
but misses allocations inside Newlib libc (like printf/etc.).

Each core needs its own _impure_ptr or else crashes like the one seen
in parallel printf_floats can happen.  Enable it in the toolchain
build and implement a simple swapper here.

FreeRTOS SMP doesn't support Newlib's dynamic reent which is needed
to allow save MT support.  Minor patch to FreeRTOS and update the
FreeRTOS variant.cpp and setup to support it.
2022-06-20 07:35:30 -07:00
Earle F. Philhower, III af8f544913 Update pio publish to match PIO PR build (#641) 2022-06-19 09:14:08 -07:00
Earle F. Philhower, III 803184c164 Update to latest Adafruit_TinyUSB (#639)
Fixes #582
2022-06-19 08:57:14 -07:00
Earle F. Philhower, III 857f91771f Update to develop branch of pico-sdk (#636)
The realloc() wrapper was included in the develop branch of pico-sdk, so
use it instead of a local, unreproducible version of the SDK.

Should have no effect on code.
2022-06-17 12:13:01 -07:00
Maximilian Gerhardt 592418d9f3 Minor PIO Docs Fixup (#635)
* Fix link display in PlatformIO Docs, Remove JLink warning

* Remove unfinished sentence
2022-06-17 09:49:51 -07:00
Maximilian Gerhardt 0a23dfeb42 Update PlatformIO board files, add PIO CI (#634)
* Shift arduino attribute higher in JSON file

* Try out PlatformIO CI

* Trigger CI

* Clone recursively, actually use own repo

* Fix YAML

* Build Verbose

* Revert to checkout@v2 version, add TinyUSB to examples

* Try fix TInyUSB example

* Pull repo recursively

* Use v3 after all, correct path to example

* Only do CI on PR
2022-06-17 08:57:18 -07:00
Maximilian Gerhardt 4a94677ee5 Update PlatformIO builder script and docs (#633)
* Update board generation, use renamed function

* Update documentation with new platform integration state

* Remove accidentally pushed file

* Use correct update command

* Use correct highlighting

* Use correct language

* Add section on debugging

* Add docs on filesystem, minor corrections

* Use -iprefix in compilation, but still expose all include paths to IDE

* Add exception and RTTI support, document them

* Fix typo
2022-06-16 18:59:46 -07:00
mnltake 3414b73172 Add analogReadResolution() docs (#631) 2022-06-16 08:16:58 -07:00
Pontus Oldberg 3bcbb24603 Updated helper class for Challenger NB board. (#629) 2022-06-15 09:16:47 -07:00
Ha Thach 26752f6f90 Aadd f_cpu 120, 240 mhz option (#628) 2022-06-15 09:12:43 -07:00
Earle F. Philhower, III 8999ec2c7a Add Platform.IO publish to release process 2022-06-14 13:07:19 -07:00
Earle F. Philhower, III 778cf4cb9e Update version 2022-06-14 12:34:22 -07:00
Earle F. Philhower, III b6a9e756e4 Remove unneeded and invalid file changes
The makever script sets up the repo properly, so no need to patch things
in the package stage.
2022-06-14 12:32:26 -07:00
Earle F. Philhower, III 285c964c98 Update version 2022-06-14 12:05:48 -07:00
Earle F. Philhower, III 1d6f66f834 Shrink flash and RAM usage even more (#627)
Remove MIDI support from the core's main TinyUSB.  MIDI is still supported
using the Adafruit TinyUSB library, just like before (the core never
did use it).

Compile the Pico-SDK using `-Os`

Remove unneeded warning in UF2 upload

Blink.ino shows a savings of 3.5KB flash and 400 bytes of RAM.

For comparison, with this PR blink.ino reports:
````
Sketch uses 49908 bytes (3%) of program storage space. Maximum is 1568768 bytes.
Global variables use 7024 bytes (2%) of dynamic memory, leaving 255120 bytes for local variables. Maximum is 262144 bytes.
````

As comparison, using the MBED core blink.ino reports:
````
Sketch uses 78882 bytes (0%) of program storage space. Maximum is 16777216 bytes.
Global variables use 42780 bytes (15%) of dynamic memory, leaving 227556 bytes for local variables. Maximum is 270336 bytes.
````

So, with this PR we use **37% less flash** and and **87% less RAM**
for simple sketches.
2022-06-13 11:54:38 -07:00
Earle F. Philhower, III 3fb8cbf39f Temporary fix for muilticore realloc (#625)
This PR includes a pico-sdk built using the fix in
https://github.com/raspberrypi/pico-sdk/pull/864

To properly fix it requires a new pico-sdk release. but until then I am
building against my own fork of pico-sdk and including the binary.
When 1.3.2 is out (and assuming my PR is approved) I'll update the pico-sdk
link.

Fixes #614
2022-06-12 13:38:02 -07:00
Earle F. Philhower, III c352105176 Remove IRQ-level malloc from USB setup
Fixes a hang found while debugging #614.  Do all memory allocations and
USB descriptor setup in main code prior to `tusb_init()`.  Avoids potential
deadlock in cases where the app is allocating while the USB port is being
set up.
2022-06-10 22:58:23 -07:00
Earle F. Philhower, III c4623f4297 Disable Wire slave interrupt on ::end (#621)
Fixes #620
2022-06-10 11:42:04 -07:00
Maximilian Gerhardt 1c85a1ca52 Activate default -Os optimization for Platform.IO (#619) 2022-06-10 09:28:26 -07:00
Earle F. Philhower, III fdf30febea Hide get.py download percent when not interactive (#618)
When get.py is run in a script the percent-update printouts shown while
downloading the toolchain end up as 100s to 1000s of lines in log files.

When stdout is not a terminal, avoid printing these percentages and
shrink logfiles significantly. Errors/etc. are still reported as normal.
2022-06-09 18:00:45 -07:00
Earle F. Philhower, III 7d5e7f5dda Remove obsolete include paths from build.inc (#616)
As noted in #615
2022-06-09 15:35:24 -07:00
Maximilian Gerhardt e3a1debc65 Fix IDE include paths / Intellisense (#615) 2022-06-09 15:30:22 -07:00
Earle F. Philhower, III 578d3d2a76 Reduce flash, RAM use, reduce download/install (#613)
Free up 4K of RAM and 6K of flash when no exceptions are enables (default).
The original toolchain was including exception code in libstdc++ by default.

Reduce installation by ~50MB and download by ~25M by removing unused LTO
gcc support.
2022-06-07 16:07:07 -07:00
Earle F. Philhower, III e3053f69f8 Add GCC stack protector support (#611) 2022-06-06 20:07:40 -07:00
Earle F. Philhower, III 04ec75e515 Try and upload ASAP instead of hard-waiting 10sec (#610)
Fixes #609 and a niggling slowness in uploads.  Try to find the drive
in a loop for 10 seconds, instead of only checking once after 10 seconds.
Avoid 100% CPU usage while waiting for Pico drive
2022-06-06 18:21:34 -07:00
Earle F. Philhower, III 420d669a4b Add C++ exception option to menus (#607)
Depends on new toolchain from
https://github.com/earlephilhower/pico-quick-toolchain/pull/11

Fixes #251
2022-06-06 10:28:54 -07:00
FeuerSturm 9e3f6ade61 Fix WizFi360-EVB-Pico pins_arduino.h (#608)
Slight difference to generic RP2040
PIN_SERIAL2_TX + PIN_SERIAL2_RX are
switched with PIN_WIRE0_SDA + PIN_WIRE0_SCL
2022-06-05 16:59:22 -07:00
Earle F. Philhower, III 0aa0f973aa Update version 2022-06-05 10:18:10 -07:00
Earle F. Philhower, III 8fc9c19af9 Add new WizNet boards to README 2022-06-05 10:17:37 -07:00
Earle F. Philhower, III 10b869ef30 Fix XIAO RP2040, allow swapping HW units 0/1 (#606)
Add plumbing to allow `Wire`, `Serial1`, `SPI1` to map to the 2nd
hardware unit for devices where the PCB layout only brings out the
2nd port.

Fix the Seeedstudio XAIO pins

Fixes #594
2022-06-04 21:37:28 -07:00
FeuerSturm c863dad73e New WIZnet boards (#605)
- added WIZnet WizFi360-EVB-Pico
- added WIZnet W5500-EVB-Pico
- corrected WIZnet W5100S-EVB-Pico PID
2022-06-03 11:56:13 -07:00
Earle F. Philhower, III 24583494c6 Fix Wire::available() when ::requestFrom fails (#604)
Avoids returning 2^32 bytes in the case of a requestFrom read fails
due to timeout.
2022-06-01 17:58:54 -07:00
Earle F. Philhower, III 4ede3ff8a4 Add attachInterruptParam (#602)
Fixed #601

Allows apps to provide a callback parameter in the `attachInterrupt` call
to be passed back to the function when the interrupt happens.
2022-05-31 18:14:34 -07:00
Arya11111andArya11111 a58154b52b Modify DFRobot Beetle pin_arduinos.h (#597)
Co-authored-by: Arya11111 <xuepeng@dfrobot.com>
2022-05-25 15:13:25 -07:00
Earle F. Philhower, III 9e659b003c Deallocate resources on SerialPIO::end (#596)
Fixes #593

When SerialPIO::end is called, stop the PIO SMs and potentially
disable the IRQ handler if this is the last RX port on that PIO.
2022-05-25 03:08:50 -07:00
Earle F. Philhower, III 7d30e6da61 Update piouart.rst 2022-05-24 08:09:01 -07:00
Pontus Oldberg a9b24827e2 Updated PID for WiFi/BLE board and other changes (#595) 2022-05-24 08:07:49 -07:00
Earle F. Philhower, III fc55e1e778 Update version 2022-05-20 12:05:12 -07:00
Earle F. Philhower, III 0188ccf696 Remove obsolete programmers.txt entries (not used) 2022-05-20 11:59:29 -07:00
Earle F. Philhower, III 65d50e4d8b Upgrade to Pico-SDK 1.3.1 (#588)
Looks like only minor changes to the SDK, should not affect the core.
2022-05-20 11:53:20 -07:00
Earle F. Philhower, III 3ce961f84d Add in missing JSON files 2022-05-20 05:27:57 -07:00
Earle F. Philhower, III eaf5e049eb Update package_pico_index.template.json 2022-05-20 05:27:03 -07:00
Pontus Oldberg e4153b03bc Add new Challenger RP2040 WiFi/BLE board (#587) 2022-05-20 05:26:01 -07:00
Earle F. Philhower, III a3a5abac23 Fix Wire I2C restart handling (#586)
Fixes #585

On an I2C bus restart, call the onReceive callback and clear the buffer.

Thanks to @DWiskow for the debug and patch!
2022-05-19 16:00:52 -07:00
Earle F. Philhower, III 8054015bff Clean up misc obsolete references (#584)
Remove pico-extras from makelibpico.sh
Remove refs to SPIFFS in FS.h
Remove travis::: markers
Update Arduino IDE URL
2022-05-18 17:33:16 -07:00
Arya11111andArya11111 646d56046f DFRobot Beetle modify some notes. (#580)
Co-authored-by: Arya11111 <xuepeng@dfrobot.com>
2022-05-11 07:29:59 -07:00
Earle F. Philhower, III 7b296a4dc9 Remove pico-extras from package 2022-05-10 08:44:18 -07:00
Earle F. Philhower, III 61ac01c31b Update version 2022-05-10 08:42:22 -07:00
Earle F. Philhower, III 79a2128704 Remove doc refs to Pico-Extras
Fixes #578
2022-05-08 09:27:48 -07:00
Earle F. Philhower, III 0c9359cddd Fix picoprobe and pico-debug upload recipes (#577)
Need to munge the platform.txt on release.

Fixes #576
2022-05-07 18:53:02 -07:00
Arya11111andArya11111 dbf855e1aa Modify DFRobot pins_arduino.h (#573)
Co-authored-by: Arya11111 <xuepeng@dfrobot.com>
2022-05-05 11:35:20 -07:00
Earle F. Philhower, III 0afd6ae54f Fix order of bootsel IRQ/idle calls (#572)
Reverse the order of IRQ and idle restore to match the way
they were initiated.
2022-05-04 18:48:35 -07:00
Earle F. Philhower, III 07500e89db Rewrite I2S from scratch, add I2S input support (#569)
Rewrite the I2S code from scratch to eliminate the dependence on the
pico-extras implementation and to support I2S input as well.

8-bit, 16-bit, 24-bit, and 32-bit words are supported.

Multiple I2S ports are allowed (theoretically up to 6 because
2 DMA channels are required per port).

I2S input and I2S output are supported.

Add input example

Fixes #535
Fixes #99
Fixes #562
2022-05-04 18:43:27 -07:00
iKK001andStephan Korner 3adc1c5321 Correct Serial1 and Serial2 pinout definitions added (#570)
Co-authored-by: Stephan Korner <stephan.korner@trihow.com>
2022-05-04 13:04:01 -07:00
ogatatsu 55394a7dcd Fix compile error when configSUPPORT_STATIC_ALLOCATION is set to 1 (#564) (#566) 2022-04-30 19:07:21 -07:00
Earle F. Philhower, III 230758b1ee Add invert option to SWSerial (#563)
Thanks to @StefanKellerAC !
2022-04-28 08:17:12 -07:00
Earle F. Philhower, III d7e02c6f34 Fix SWSerial polarity. (#560) 2022-04-27 21:05:16 -07:00
Earle F. Philhower, III c32ad45724 Clean up some minor doc errors/formats (#559) 2022-04-27 16:07:27 -07:00
Earle F. Philhower, III 541e23d663 Update to major version 2.0.0 2022-04-27 12:10:55 -07:00
Earle F. Philhower, III 65fe176795 Make default CPU speed 133MHz (#557)
The chip supports 133MHz and the other Pico core already defaults to
the higher speed, so make 133 the default.

It can still be changed through the menus and will stay at 125 unless
pre-existing users change it so they will see no difference.
2022-04-27 11:31:21 -07:00
Earle F. Philhower, III cfc91804c8 Fix memory corruption introducted in FreeRTOS port (#556)
To remove compiler warning the valid core macro was modified to only check
that the core passed in was < # of total cores.  Unfortunately there are
parts of the FreeRTOS code where the passed in core # is -1.  The upstream
catches this and returns FALSE, but my hacked version returned TRUE.  This
caused interesting memory corruption errors and crashes when the
current task block[-1] was updated.

Undo the change and fix the 1 spot where a warning happens instead.

Undo the forced compiler -O0 for port.c, it was only masking the fault.
2022-04-27 09:42:15 -07:00
Earle F. Philhower, III 88d213a30b Additional FreeRTOS adjustments (#555)
Use low power WFE when idle.

Set PORT.C to built `-O0` always because it seems to occasinally end
up with interrupts disabled in task code, causing the SYSTICK never to
fire and killing task switching.

No need for dynamic exceptions.  We don't move the execbase.
2022-04-27 03:53:07 -07:00
Earle F. Philhower, III 189b796499 More FreeRTOS ISR work 2022-04-25 19:11:38 -07:00
Earle F. Philhower, III af7f430227 Change the RTD theme (#554)
Alabaster is not my favorite, try something with colors...
2022-04-25 18:03:07 -07:00
Andy2No 797abb5a7f Update SimpleTone.ino (#552)
Adds code to define which pins are used, moving them from the defaults, which are the same as the only three analogue input pins, and adding comments to explain how to change them.

The original didn't give any clues about which pins were used, which isn't ideal for a beginner - it was necessary to look at the code for the library, to work that out.

The new code redundantly defines a pWS pin number (as pBCLK+1), which isn't used in the example, but is meant as a reminder to the person using it, of how to wire up WS.
2022-04-25 12:21:34 -07:00
Earle F. Philhower, III ffff21a936 Update FreeRTOS library to avoid random crashes (#553) 2022-04-25 12:10:48 -07:00
Earle F. Philhower, III 781fb3ab48 Update docs, increase max analogWriteFreq to 1MHz (#551) 2022-04-25 08:23:50 -07:00
Earle F. Philhower, III bda630e419 Add FreeRTOS support thanks to @hfellner (#533)
Using all the work from @hfellner and others, add FreeRTOS
SMP support.

Allow idling cores through the FreeRTOS FIFO queue to
allow for file system and EEPROM support.

Make delay a weak function so FreeRTOS can override.

Add cycle count support under FreeRTOS using a PIO SM.

Use a task-based approach for handling the USB periodic work
instead of the IRQ-based one in the main core.

Set 8 prio levels so it fits in 3 bits nicely (0..7).
2022-04-24 20:59:57 -07:00
Earle F. Philhower, III 9afdc48ddd Add SoftwareSerial wrapper around SerialPIO (#548)
I receive mails weekly asking how to use `SoftwareSerial` on this core.
Avoid the issue by including a simple wrapper class around `SerialPIO`
which gives the proper class name and constructor parameters.

Note that inverted mode is not supported.
2022-04-24 15:07:55 -07:00
Earle F. Philhower, III 3ee031abc9 Add ::overflow() return to SerialUART/SerialPIO (#547)
Matching the Arduino SoftwareSerial API
2022-04-24 14:44:23 -07:00
Earle F. Philhower, III d1f9bce083 Document the Generic RP2040 option (#546)
Fixes #522
2022-04-24 11:04:17 -07:00
Earle F. Philhower, III 670957487a Update version 2022-04-22 12:55:08 -07:00
Earle F. Philhower, III 1c0133704e Update to LittleFS 2.5 (#545) 2022-04-22 12:22:27 -07:00
Earle F. Philhower, III 5927d4ee2b Fix SerialPIO sampling, avoid reading random garbage (#544)
Adjust the 1/2 bit time to match the number of extra cycles in the actual
PIO loop.

Throw out the entire start bit, which results in sampling the data at the
midpoint and not the starting time of a bit (which was causing random
failures on read data).

Tested at 300bps all the way to 2,000,000bps using a loopback connection.

Fixes #360
2022-04-21 19:48:30 -07:00
Earle F. Philhower, III 5dee051a7a Update version 2022-04-17 14:40:27 -07:00
Earle F. Philhower, III 561110231d Add SparkFun Thing Plus RP2040 (#540) 2022-04-17 14:39:28 -07:00
Earle F. Philhower, III eff908385e Add Seeed XAIO RP2040 support (#538)
Fixes #537
2022-04-16 10:52:06 -07:00
Jean-Luc Béchennec 784a6ed5ad Added the ability to set pad current via pinMode: OUTPUT_2MA, OUTPUT_… (#532) 2022-04-10 13:33:19 -07:00
Earle F. Philhower, III da2d08a27b Update keywords.txt 2022-04-09 11:27:01 -07:00
Earle F. Philhower, III 061b38f0b8 Add RTS/CTS to Arduino Nano Connect Serial2(NINA) (#525)
Fixes #524
2022-03-30 14:12:24 -07:00
Arya11111 9971bda9cb Modify DFRobot pins_arduino.h file. (#521) 2022-03-29 07:17:00 -07:00
Earle F. Philhower, III 6cb2bf7009 Update version 2022-03-17 08:42:29 -07:00
randomllama 50befc42c3 udisks v2.9.0 dropped the trailing period for "udisksctl mount". (#516) 2022-03-16 14:25:44 -07:00
Earle F. Philhower, III 53043830e7 Avoid "chunkiness" of UART FIFO availability (#511)
* Avoid "chunkiness" of UART FIFO availability

The UART FIFO will generate an IRQ to transfer data into the SerialUART
FIFOs either every 4 received bytes, or every 4 idle byte times.  This
causes the ::available count to report "0" until either of those two
cases happen, causing a potentially delay in data becoming available to
the app.

Change the code to pull data from the HW FIFO on a read/available/peek.
Use a non-blocking mutex and IRQ disabling to safely empty the FIFO from
user space.  The mutex added to the IRQ is non-blocking and will be
a single CAS the vast majority of the time, so it should not impact the
Serial performance.

Fixes #464 and others where `setPollingMode()` was needed as a workaround.

Make sure we have all mutexes locked before we disable the port and free
the queue to avoid evil cases.

Only init the mutexes once, on object creation.

In polled mode, don't bother acquiring/releasing the fifo mutex.

When begin() is called on an already running port, call end() to clean
up the old data/etc. before making a new queue/config.  This avoids a
memory leak and potential write-after-free case.
2022-03-16 08:46:20 -07:00
Maximilian Gerhardt 8deb47f2c3 Auto-ignore Adafruit TinyUSB Library if not active (#513)
Originally from https://github.com/episource/platform-raspberrypi/blob/my-platform-pico/builder/frameworks/arduino-pico/arduino-pico.py#L104-L115
2022-03-14 09:01:41 -07:00
Earle F. Philhower, III 01093482e7 Add script to update version number, new header (#506)
Define ARDUINO_PICO_MAJOR/_MINOR/_REVISION for app use and update the
Platform.IO and Arduino files for a new release version.

Fixes #309
Fixes #487
2022-03-06 11:04:19 -08:00
Earle F. Philhower, III da215aecd4 Fix QT Py serial (Serial2 pinned out, not Serial1) (#505) 2022-03-05 14:28:45 -08:00
Earle F. Philhower, III be21c31eab Update package_pico_index.template.json 2022-02-24 04:58:27 -08:00
Earle F. Philhower, III 6457cb7dd0 Update README.md 2022-02-24 04:57:35 -08:00
Arya11111 e444a7329c Add DFRobot Beetle RP2040 boards V1.0.0 (#502) 2022-02-24 04:56:59 -08:00
Earle F. Philhower, III 28d7818c2b Merge branch 'master' of https://github.com/earlephilhower/arduino-pico 2022-02-23 08:48:41 -08:00
Earle F. Philhower, III 6561310d25 Minor OOM check in PIO support routines 2022-02-23 08:48:16 -08:00
Pontus Oldberg f8e8a7b72e Updating LoRa board pins and UART hw flow. (#499)
* Added missing SERIAL2 and LoRa module GIO pins.
* Added support for enabling UART CTS and RTS pins.
2022-02-22 01:45:24 -08:00
Bodmer 5a0d67f1ac PDM library: Update PIO and interrupt use (#496)
The PIO and state machine were hard wired, so this caused problems if they were not free. The approach used by the Servo library has been adopted so a free PIO and SM are searched.

The DMA_IRQ_0 was grabbed exclusively, but this conflicts with SPI DMA use. The interrupt is now shared, but has been allocated the highest possible priority.

Since the PDM PIO use is receive only, the PIO state machine RX FIFO's can be joined to reduce DMA interrupt load.
2022-02-20 13:20:43 -08:00
Earle F. Philhower, III 03626e615b Alphabetize the boards menu (#495)
Reorder the boards menu to make it easier to find any specific
board.  Add a note to the script asking manufacturers to keep it
that way.
2022-02-20 09:21:01 -08:00
Earle F. Philhower, III bac6dae0ad Document new restartCore1 call 2022-02-20 08:46:25 -08:00
Magnus Nordlander 5c186d8467 Added ability to reset and relaunch core 1 (#493) 2022-02-20 08:43:30 -08:00
Earle F. Philhower, III 25b34913c6 Update package_pico_index.template.json 2022-02-19 09:57:56 -08:00
Pontus Oldberg 8dabe44693 Add support for Challenger RP2040 LoRa (#494) 2022-02-19 06:56:32 -08:00
Earle F. Philhower, III 8a7977fcb3 Fix SerialPIO receive interrupt on PIO1 (#490)
Fixes #489

Only the PIO0 IRQ handler was ever installed due to a hardcoding bug.
Attach the IRQ handler to the PIO being started instead.
2022-02-15 12:10:12 -08:00
Earle F. Philhower, III d689165a39 Update OpenOCD for Winx32 to be x64 compatible (#485) 2022-02-13 12:54:27 -08:00
Earle F. Philhower, III f2fd654b84 Bump to 1.11.0 2022-02-12 12:38:35 -08:00
Earle F. Philhower, III 1b61a86618 Update GDB and OpenOCD to work together, finally (#482)
GDB for non-Linux systems was built w/o expat which caused odd behavior
under Windows and other systems (i.e. breakpoints not working, etc.)
New toolchain manually builds cross-compiled libexpat and ensures it is
used, fixing the issue.

Windows OpenOCD binaries now come from manually built and tested copies
(using a real Windows system).

Fixes #478
Fixes #457
Fixes #456
and probably others...
2022-02-12 12:35:03 -08:00
Earle F. Philhower, III 44cd697b29 Add SerialUART::setPollingMode() (#473)
Fixes #472

Instead of using interrupts, explicitly call the IRQ handler dueing Serial
read/peek/available calls.

Add to keywords.txt for syntax hilighting.

Add poll calls in the SerialUART::write-like calls (write,
flush, etc.)

Really remove division from IRQ routines/
2022-02-10 12:22:27 -08:00
Earle F. Philhower, III d562b00c37 Use Powershell to find UF2 drive if WMIC fails (#476)
Microsoft is deprecating WMIC, so fall back to a Powershell call in
case of failure to ruin WMIC.

Belt and suspenders, set PowerShell non-interactive mode and null STDIN.
2022-02-10 12:15:43 -08:00
Earle F. Philhower, III ba92377eba Decrease size of used FIFO in SerialUART (#471)
Fixes #468

The FIFO limit was set to 1/2, or 16 bytes on POR and not set by the core,
so for low baud this could result in a LONG time without data moving from
hardware FIFO to the SW ring buffer and timeouts/etc.

Now use the API call which sets it to 1/8, or 4 bytes of data to speed up
the transfer 4x.

Also avoid using the divider in the IRQ routine because it is not clear
from the docs of the Pico SDK IRQ callback routine preserves divider
state or not.  If not, doing division in an IRQ could result in random
data corruption in the main app.

Add memory barriers to ensure the order of data into RAM is preserved
and that GCC doesn't reorder writes.
2022-02-08 12:14:40 -08:00
gsexton acbe190a20 Fix OpenSUSE upload, make mount point fionding more robust (#467)
Change order of tests to favor /run/media over /media. Parse output of udiskctl mount to find mount path
2022-02-08 08:24:30 -08:00
Earle F. Philhower, III 4cd65d1512 Remove timeout for SerialUART/SerialPIO::read/peek (#466)
Fixes #464 and other incompatibilities

Remove the timeout check from ::read and ::peek on the SerialUART/PIO
classes  (SerialUSB already ignores it).  See documentation
https://www.arduino.cc/reference/en/language/functions/communication/serial/settimeout/
and thanks to @jandrassy's explanation
https://github.com/earlephilhower/arduino-pico/issues/464#issuecomment-1031657044
2022-02-07 12:33:49 -08:00
Earle F. Philhower, III bbae702e9f Add support for analogReadResolution, default 10b (#461)
Most other boards and the MBED RP2040 support analogReadResolution which
just shifts read data around as needed, with a default of only 10b of
resolution.  The Pico ADC technically supports 12b, but only has about
8b of real data after noise, so you're not really losing anything in the
general case.

Fixes #460
2022-02-05 10:10:45 -08:00
Earle F. Philhower, III c4046602f0 Allow changing I2C clock speed while running (#459)
Fixes #458
2022-02-04 18:08:35 -08:00
Earle F. Philhower, III baf925fefd Update to 1.10.0 release 2022-02-02 18:15:59 -08:00
Earle F. Philhower, III ec00479640 Update to 1.3.2-a toolchain, setjmp/longjmp fix (#454)
Fixes #453, a crash caused by Newlib having ARM instructions in
the Thumb-only Cortex-M0+.
2022-02-02 18:00:06 -08:00
Earle F. Philhower, III 66e4866091 Prepare for 1.9.15 2022-01-29 03:36:20 -08:00
Earle F. Philhower, III 5b47a61209 Update package_pico_index.template.json 2022-01-29 03:34:18 -08:00
Earle F. Philhower, III b0365cd9ad Update platform.txt 2022-01-29 03:32:08 -08:00
Spegs21 36bb604d38 Update tinyusb 1.9.2 (#445) 2022-01-29 03:22:14 -08:00
Earle F. Philhower, III d8835df9ab Fix pgm_read_ macros with inline functions (#449)
Fixes #447
2022-01-28 18:44:34 -08:00
Earle F. Philhower, III d24c8442c4 Make pio build script executable by default (#446)
In order to be consistent the other tools in the directory.
2022-01-28 12:46:51 -08:00
Maximilian Gerhardt 4a955b2a28 Correctly use earlephilhower.varant if variant not given, ensure USB power macro is always there (#444)
Fixes a crash of the builder script, `board.get("build.variant", None)` will throw an exception if the `build.variant` was not found (and not return `None` as the fallback value), but an empty string works, so check against that.

USB power defines moved directly into the board files, but still ensure that the macro always exists (with a default fallback value) to not fail the build.
2022-01-28 04:15:31 -08:00
Earle F. Philhower, III 4f27ec44eb Generate Platform.IO board definitions (#426)
As part of the boards.txt generation, also make necessary files for
Platform.IO.

Fixes #399
2022-01-28 04:08:59 -08:00
Earle F. Philhower, III 843630c3c7 Remove unused copy of std C++ library (#443) 2022-01-27 12:16:41 -08:00
Maximilian Gerhardt 00c0bc1e6e Fix libraries and RAM size in PlatformIO build (#440) 2022-01-26 16:56:36 -08:00
Kattni 5980993774 Add NeoPixel pins to Adafruit boards (#438) 2022-01-26 11:41:39 -08:00
Earle F. Philhower, III 72c875183a Update README.md 2022-01-26 08:46:51 -08:00
风飘雨 97f9afac0a Add board flyboard2040core (#437)
Thx!
2022-01-26 08:46:13 -08:00
Earle F. Philhower, III a7035ab61e Rename SDFat directory for Adafruit compatibility
Fixes #416
2022-01-24 12:38:35 -08:00
Earle F. Philhower, III ea4c0999d0 Add interpolater include path (#428)
Fixes #427.  The libpico.a build already includes the HW interpolator
sources, but the include was missing from the Arduino path.
2022-01-22 11:30:47 -08:00
Earle F. Philhower, III d51fa99b70 Update package.json 2022-01-20 08:54:58 -08:00
Earle F. Philhower, III 2c97bffc54 Update to latest upstream LittleFS (#425)
Also clean up output in SpeedTest, make more human friendly
2022-01-19 18:09:40 -08:00
Earle F. Philhower, III 626b62c413 Update to latest upstream Keyboard/Mouse (#424)
Keyboard class now has support for non-en_US layouts, and documentation has
been added to the Mouse class.

Thanks to @rico0260 for letting me know about the update, and for the initial PR!
2022-01-19 17:46:31 -08:00
Earle F. Philhower, III 25b9ca821e Only call Wire.onReceive if data is available (#423)
The Pico HW seems to generate an interrupt on the end of every I2C
write cycle, even if the slave address wasn't actually targeted.
This would cause the onReceive method to be called with a 0-len
parameter for every write on the I2C bus.

Now, only call onReceive if there is 1 or more bytes of data available.
2022-01-19 16:16:39 -08:00
Earle F. Philhower, III d5ddf4cd7f Move SdFat to master/head (#422)
SdFat used to point to unnamed commit in the ESP8266SdFat repo.
Master in that repo has now been moved to that commit, so make this
core use the master branch for sanity's sake.
2022-01-19 12:30:12 -08:00
Earle F. Philhower, III d43dcbcf8c Remove duplicate millis/micros definitions (#419)
Fixes #418
2022-01-15 09:40:31 -08:00
Juraj Andrássy 1fdc0ab7c1 Arduino Nano R2040 Connect Nina pins access with WiFiNINA lib (#404) 2022-01-09 09:11:27 -08:00
Khoi Hoang 9408b7e2c4 Fix WiFiNINA issue for Arduino Nano Connect (#403)
Fixes #373
2022-01-09 08:03:53 -08:00
Earle F. Philhower, III 12f3505eea Update the platform release version 2022-01-05 12:16:21 -08:00
Earle F. Philhower, III 464ee85884 Make Wire buffer default to 256 for MBED compatibility (#412)
Fixes #411
2022-01-05 12:14:34 -08:00
Earle F. Philhower, III 87d745d5dc Add missing board names 2022-01-05 07:45:09 -08:00
Earle F. Philhower, III 576f8941d6 Add setFIFOSize to UART Serial ports (#410)
Allow setting the size of the receive buffer by the application using a
call to Serial1/2.setFIFOSize(xxx) before the begin() call.
2022-01-04 19:02:38 -08:00
Earle F. Philhower, III 039cbcf2cf Update package.json 2022-01-04 18:53:31 -08:00
arturo182 f91c4b3b9d Add the RP2040 Stamp board (#407) 2022-01-03 11:38:05 -08:00
Earle F. Philhower, III 83b9486985 Allow setting the SerialPIO FIFO depth in the constructor (#405)
Defaults to 32 bytes, like the HW Serial ports, but can be set to
any desired value when instantiated.
2022-01-02 11:31:06 -08:00
Earle F. Philhower, III dc54eeb8d0 Update package.json 2022-01-02 09:45:44 -08:00
Earle F. Philhower, III 3a2a7f8cf1 Fix hang on Serial overflow, PIOSerial stop bit handling (#401)
When the Serial software FIFOs overeflowed, the IRQ handler would not
read any more data from the hardware FIFOs.  This would cause the
IRQ handler to be continually called as soon as it exited since the
HW FIFOS were not empty.

Now always read every available HW FIFO entry and throw out any that
don't fit in the SW FIFO.

Also fix a too long by half stop bit timing in the PIOSerial receiver.
2022-01-02 05:46:33 -08:00
Khoi Hoang 52a22e5185 Fix Nano_RP2040_Connect pinout issue (#400)
Fix issues with [WiFiNINA](https://github.com/arduino-libraries/WiFiNINA) and [WiFiNINA_Generic](https://github.com/khoih-prog/WiFiNINA_Generic) libraries

Fixes #373
Fixes #375 
Fixes #376
2022-01-01 13:05:25 -08:00
Earle F. Philhower, III cae8c70e51 Add the PIO UARTs to the list 2021-12-30 16:02:15 -08:00
Earle F. Philhower, III 513bd81810 Add SDA/SCL variables like other cores export (#398)
Fixes #368.  Thanks @bperrybap!
2021-12-30 15:57:13 -08:00
Earle F. Philhower, III 891f653ead Update package.json 2021-12-30 09:56:59 -08:00
Ken Piper 5b270aab61 Fix A0-A3 pin definitions for Adafruit QT Py RP2040 (#397) 2021-12-30 09:56:38 -08:00
Maximilian Gerhardt 6591da9acf Fix PlatformIO build (#395)
Defines USBD_MAX_POWER_MA as a static 250mA, which is correct for all the boards supported in platform-raspberrypi (aka, RaspberryPi Pico and Nano RP2040 Connect)
2021-12-29 09:19:47 -08:00
Earle F. Philhower, III c80c08d32c Update package.json 2021-12-28 08:27:34 -08:00
Earle F. Philhower, III ce7d337c5c Add SoftwareSerial-like PIO based UARTs (#391)
Adds support to the core for PIO-based, software-created UARTs, up to 8 (the number of PIO state machines) possible.

By using a custom program on the PIO state machines, it allows for very high bit rates and does not require CPU or interrupts.

Bit widths from 5- to 8-bits, 1 or 2 stop bits, and even/odd/none parity are supported.
2021-12-28 08:27:08 -08:00
Earle F. Philhower, III dc1198bd9c Use interrupts to capture Serial UART data, not polling (#393)
PR #379 was an ugly hack which works only if you poll the Serial port more
frequently than ~8 byte times.

This PR replaces the polling with an IRQ based lockless writer/reader queue
so that even if you only read every 32 byte times, the Serial1/2 port should
not lose data.  It also should use less CPU and allow for somewhat higher
throughput.
2021-12-28 08:21:03 -08:00
Earle F. Philhower, III f46d7cc84f Speed up SPI by not reinitting if the paramters are the same as before (#394)
Leave the SPI port initted after a transaction, and when a new one comes in
check if it is the same settings we're already running.  If so, do nothing.
If not, deinit and reinit.  In general the settings will be identical, so
this will speed things up massively.

Fixes #392
2021-12-27 12:25:12 -08:00
Earle F. Philhower, III 5ee764390e Update README.md 2021-12-26 05:29:10 -08:00
Limor "Ladyada" Fried 894a82f54f Add Adafruit KB2040 (#390) 2021-12-26 05:28:50 -08:00
Earle F. Philhower, III 5cc9835303 Add warning not to edit boards.txt (#383) 2021-12-23 08:09:59 -08:00
Earle F. Philhower, III 48877984b7 Remove redundant board.mcu in boards.txt, fix precompiled libs (#382)
* Remove redundant/wrong second board.mcu in boards.txt

Fixes #380

Boards.txt had the setting board.mcu twice.  The first one was correct,
while the second one wasn't and shouldn't have been there.  Remove it.

* Include fix from @rei-vilo in #381
2021-12-23 07:55:34 -08:00
Earle F. Philhower, III a58f49018a Add a poor-man's software FIFO for serial UART reads (#379)
Because the hardware FIFO is quite small and doesn't report the actual number
of bytes available, implement a software FIFO that will pull all available
bytes out of the HW FIFO on any Serial call.  It's not as efficient or as
bulletproof as an IRQ based method, but it is simpler to implement and can
help with issues like #378
2021-12-23 07:41:34 -08:00
Earle F. Philhower, III 7120a1508c Update to SDK version 1.3.0 (#371) 2021-12-14 18:59:24 -08:00
Pontus Oldberg a808f4ae6a Adds option for setting USB max power in makeboards.py (#370) 2021-12-10 04:11:22 -08:00
Pontus Oldberg 4d1f5baa7e Adds a lightweight support class for LTE functionality (#367) 2021-12-09 09:55:09 -08:00
Pontus Oldberg f106035100 Adds support for Challenger NB RP2040 WiFi board and RPICO32 module (#366) 2021-12-07 09:44:38 -08:00
Earle F. Philhower, III 21f49d032b Update README.md 2021-12-06 00:03:11 -08:00
Wai Weng 341307cb8d Added new variant: Cytron Maker Nano RP2040. (#365) 2021-12-06 00:02:54 -08:00
Earle F. Philhower, III 85990ff51d Support CMSIS and rename conflicting header file (#362) 2021-12-03 12:49:34 -08:00
564 changed files with 97972 additions and 8258 deletions
+71 -40
View File
@@ -6,6 +6,10 @@ name: Arduino-Pico CI
on:
pull_request:
env:
TRAVIS_BUILD_DIR: ${{ github.workspace }}
TRAVIS_TAG: ${{ github.ref }}
jobs:
@@ -14,21 +18,21 @@ jobs:
name: Check spelling
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: true
- name: Run codespell
uses: codespell-project/actions-codespell@master
with:
skip: ./pico-extras,./ArduinoCore-API,./libraries/SdFat,./libraries/Adafruit_TinyUSB_Arduino,./libraries/LittleFS/lib,./tools/pyserial,./pico-sdk,./.github,./docs/i2s.rst,./cores/rp2040/api
ignore_words_list: ser,DOUT
skip: ./ArduinoCore-API,./libraries/ESP8266SdFat,./libraries/Adafruit_TinyUSB_Arduino,./libraries/LittleFS/lib,./tools/pyserial,./pico-sdk,./.github,./docs/i2s.rst,./cores/rp2040/api,./libraries/FreeRTOS,./tools/libbearssl/bearssl,./include,./libraries/WiFi/examples/BearSSL_Server,./ota/uzlib,./libraries/http-parser/lib,./libraries/WebServer/examples/HelloServerBearSSL/HelloServerBearSSL.ino,./libraries/HTTPUpdateServer/examples/SecureBearSSLUpdater/SecureBearSSLUpdater.ino,./.git
ignore_words_list: ser,dout
# Consistent style
astyle:
name: Style, Boards, Package
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: false
- name: Check package references
@@ -36,7 +40,7 @@ jobs:
./tests/ci/pkgrefs_test.sh
- name: Check boards.txt was not edited after makeboards.py
run: |
./tools/makeboards.py > boards.txt
./tools/makeboards.py
# If anything changed, GIT should return an error and fail the test
git diff --exit-code
- name: Run astyle on all code/examples
@@ -46,10 +50,6 @@ jobs:
./tests/restyle.sh
# If anything changed, GIT should return an error and fail the test
git diff --exit-code
- name: Check Arduino API copy is clean
run: |
git submodule update --init ./ArduinoCore-API
diff -r ./cores/rp2040/api ./ArduinoCore-API/api
# Build all examples on linux (core and Arduino IDE)
build-linux:
@@ -57,32 +57,28 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
chunk: [0, 1, 2, 3]
chunk: [0, 1, 2, 3, 4, 5]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: true
- uses: actions/setup-python@v2
- uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Cache Linux toolchain
id: cache-linux
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ./tools/dist
key: ${{ runner.os }}-${{ hashFiles('package/package_pico_index.template.json', 'tests/common.sh') }}
- name: Build Sketches
env:
TRAVIS_BUILD_DIR: ${{ github.workspace }}
TRAVIS_TAG: ${{ github.ref }}
BUILD_PARITY: custom
mod: 4
mod: 6
rem: ${{ matrix.chunk }}
run: |
cd pico-sdk
git submodule update --init
cd ../pico-extras
git submodule update --init
cd ..
bash ./tests/build.sh
@@ -91,28 +87,24 @@ jobs:
name: Build TinyUSB Examples
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: true
- uses: actions/setup-python@v2
- uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Cache Linux toolchain
id: cache-linux
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ./tools/dist
key: ${{ runner.os }}-${{ hashFiles('package/package_pico_index.template.json', 'tests/common.sh') }}
- name: Build Sketches
env:
TRAVIS_BUILD_DIR: ${{ github.workspace }}
TRAVIS_TAG: ${{ github.ref }}
BUILD_PARITY: custom
run: |
cd pico-sdk
git submodule update --init
cd ../pico-extras
git submodule update --init
cd ..
bash ./tests/build-tinyusb.sh
@@ -121,22 +113,20 @@ jobs:
name: Windows
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: true
- uses: actions/setup-python@v2
- uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Cache Windows toolchain
id: cache-windows
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ./tools/dist
key: ${{ runner.os }}-${{ hashFiles('package/package_pico_index.template.json', 'tests/common.sh') }}
- name: Build Sketch
env:
TRAVIS_BUILD_DIR: ${{ github.workspace }}
TRAVIS_TAG: ${{ github.ref }}
WINDOWS: 1
BUILD_PARITY: custom
mod: 500
@@ -147,8 +137,6 @@ jobs:
try { Get-Command python3 } catch { copy (get-command python).source (get-command python).source.Replace("python.exe", "python3.exe") }
cd pico-sdk
git submodule update --init
cd ../pico-extras
git submodule update --init
cd ..
bash ./tests/build.sh
@@ -156,24 +144,22 @@ jobs:
# Single build under macOS to ensure the Mac toolchain is good.
build-mac:
name: Mac
runs-on: macOS-latest
runs-on: macOS-12
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: true
- uses: actions/setup-python@v2
- uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Cache Mac toolchain
id: cache-mac
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ./tools/dist
key: ${{ runner.os }}-${{ hashFiles('package/package_pico_index.template.json', 'tests/common.sh') }}
- name: Build Sketch
env:
TRAVIS_BUILD_DIR: ${{ github.workspace }}
TRAVIS_TAG: ${{ github.ref }}
MACOSX: 1
BUILD_PARITY: custom
mod: 500
@@ -181,8 +167,53 @@ jobs:
run: |
cd pico-sdk
git submodule update --init
cd ../pico-extras
git submodule update --init
cd ..
bash ./tests/build.sh
# Build a few examples with PlatformIO to test if integration works
build-platformio:
name: Build PlatformIO Examples
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: 'true'
- name: Initialize needed submodules
run: |
cd pico-sdk
git submodule update --init
cd ../libraries/Adafruit_TinyUSB_Arduino
git submodule update --init
cd ../..
- name: Cache pip
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Cache PlatformIO
uses: actions/cache@v3
with:
path: ~/.platformio
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Install PlatformIO
run: |
python -m pip install --upgrade pip
pip install --upgrade platformio
pio pkg install --global --platform https://github.com/maxgerhardt/platform-raspberrypi.git
pio pkg install --global --tool symlink://.
- name: Build Multicore Example
run: pio ci --board=rpipico --board=adafruit_feather -O "platform_packages=framework-arduinopico@symlink:///home/runner/work/arduino-pico/arduino-pico" libraries/rp2040/examples/Multicore/Multicore.ino
- name: Build Fade Example
run: pio ci --board=rpipico --board=adafruit_feather -O "platform_packages=framework-arduinopico@symlink:///home/runner/work/arduino-pico/arduino-pico" libraries/rp2040/examples/Fade/Fade.ino
- name: Build TinyUSB Example
run: pio ci --board=rpipico --board=adafruit_feather -O "platform_packages=framework-arduinopico@symlink:///home/runner/work/arduino-pico/arduino-pico" -O "build_flags=-DUSE_TINYUSB" libraries/Adafruit_TinyUSB_Arduino/examples/CDC/cdc_multi/cdc_multi.ino
- name: Build WiFi Example
run: pio ci --board=rpipicow -O "platform_packages=framework-arduinopico@symlink:///home/runner/work/arduino-pico/arduino-pico" libraries/WiFi/examples/ScanNetworks/ScanNetworks.ino
- name: Build Signed OTA Example
run: pio ci --board=rpipicow -O "platform_packages=framework-arduinopico@symlink:///home/runner/work/arduino-pico/arduino-pico" libraries/ArduinoOTA/examples/SignedOTA/SignedOTA.ino
+22 -2
View File
@@ -9,19 +9,39 @@ jobs:
name: Update master JSON file
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: true
- uses: actions/setup-python@v2
- name: Cache pip
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Cache PlatformIO
uses: actions/cache@v3
with:
path: ~/.platformio
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
- uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Install PlatformIO
run: |
python -m pip install --upgrade pip
pip install --upgrade platformio
- name: Deploy updated JSON
env:
TRAVIS_BUILD_DIR: ${{ github.workspace }}
BUILD_TYPE: package
CI_GITHUB_API_KEY: ${{ secrets.GITHUB_TOKEN }}
PLATFORMIO_AUTH_TOKEN: ${{ secrets.PLATFORMIO_AUTH_TOKEN }}
run: |
pip3 install PyGithub
TAG=$(git describe --exact-match --tags)
curl -L -o package_rp2040_index.json "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/releases/download/$TAG/package_rp2040_index.json"
./package/update_release.py --token ${CI_GITHUB_API_KEY} --repo "$GITHUB_REPOSITORY" --tag global package_rp2040_index.json
# Upload to Platform.IO
curl -LO $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/releases/download/$TAG/rp2040-$TAG.zip
pio package publish rp2040-$TAG.zip --non-interactive
+2 -3
View File
@@ -15,11 +15,11 @@ jobs:
name: Package
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: true
fetch-depth: 0
- uses: actions/setup-python@v2
- uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Build package JSON
@@ -29,7 +29,6 @@ jobs:
CI_GITHUB_API_KEY: ${{ secrets.GITHUB_TOKEN }}
run: |
(cd pico-sdk && git submodule update --init)
(cd pico-extras && git submodule update --init)
(cd ./package && bash ./build_boards_manager_package.sh)
pip3 install PyGithub
# Create a draft release and upload the ZIP and JSON files.
+4
View File
@@ -1,3 +1,7 @@
.DS_Store
system
tools/dist
docs/_build
ota/build
tools/libpico/build
platform.local.txt
+17 -5
View File
@@ -3,7 +3,7 @@
url = https://github.com/earlephilhower/ArduinoCore-API.git
[submodule "pico-sdk"]
path = pico-sdk
url = https://github.com/raspberrypi/pico-sdk.git
url = https://github.com/earlephilhower/pico-sdk.git
[submodule "system/pyserial"]
path = tools/pyserial
url = https://github.com/pyserial/pyserial.git
@@ -11,17 +11,29 @@
path = libraries/LittleFS/lib/littlefs
url = https://github.com/littlefs-project/littlefs.git
[submodule "libraries/SdFat"]
path = libraries/SdFat
path = libraries/ESP8266SdFat
url = https://github.com/earlephilhower/ESP8266SdFat.git
[submodule "pico-extras"]
path = pico-extras
url = https://github.com/raspberrypi/pico-extras.git
[submodule "libraries/Keyboard"]
path = libraries/Keyboard
url = https://github.com/earlephilhower/Keyboard
[submodule "libraries/Mouse"]
path = libraries/Mouse
url = https://github.com/earlephilhower/Mouse
[submodule "libraries/Joystick"]
path = libraries/Joystick
url = https://github.com/benjaminaigner/Joystick
[submodule "libraries/Adafruit_TinyUSB_Arduino"]
path = libraries/Adafruit_TinyUSB_Arduino
url = https://github.com/adafruit/Adafruit_TinyUSB_Arduino.git
[submodule "libraries/FreeRTOS/lib/FreeRTOS-Kernel"]
path = libraries/FreeRTOS/lib/FreeRTOS-Kernel
url = https://github.com/earlephilhower/FreeRTOS-Kernel.git
[submodule "tools/libbearssl/bearssl"]
path = tools/libbearssl/bearssl
url = https://github.com/earlephilhower/bearssl-esp8266.git
[submodule "ota/uzlib"]
path = ota/uzlib
url = https://github.com/pfalcon/uzlib.git
[submodule "libraries/http_parser/lib/http-parser"]
path = libraries/http-parser/lib/http-parser
url = https://github.com/nodejs/http-parser.git
+55 -11
View File
@@ -11,20 +11,49 @@ See https://arduino-pico.readthedocs.io/en/latest/ along with the examples for m
# Supported Boards
* Raspberry Pi Pico
* Raspberry Pi Pico W
* Adafruit Feather RP2040
* Adafruit Feather RP2040 SCORPIO
* Adafruit ItsyBitsy RP2040
* Adafruit KB2040
* Adafruit Macropad RP2040
* Adafruit QTPy RP2040
* Adafruit STEMMA Friend RP2040
* Adafruit Trinkey RP2040 QT
* Arduino Nano RP2040 Connect (preliminary)
* Arduino Nano RP2040 Connect
* BridgeTek IDM2040-7A
* Cytron Maker Pi RP2040
* Cytron Maker Nano RP2040
* DatanoiseTV PicoADK+
* Degz Mizu
* DeRuiLab FlyBoard2040 Core
* DFRobot Beetle RP2040
* ElectronicCats Hunter Cat NFC
* ExtremeElectronics RC2040
* Invector Labs Challenger RP2040 WiFi
* Invector Labs Challenger RP2040 WiFi/BLE
* Invector Labs Challenger NB RP2040 WiFi
* Invector Labs Challenger RP2040 LTE
* Invector Labs Challenger RP2040 LoRa
* Invector Labs Challenger RP2040 SubGHz
* Invector Labs Challenger RP2040 SD/RTC
* Invector Labs RPICO32
* Melopero Cookie RP2040
* Melopero Shake RP2040
* Pimoroni PGA2040
* Seeed XIAO RP2040
* Solder Party RP2040 Stamp
* SparkFun ProMicro RP2040
* SparkFun Thing Plus RP2040
* uPesy RP2040 DevKit
* Waveshare RP2040 Zero
* Waveshare RP2040 One
* Waveshare RP2040 Plus
* Waveshare RP2040 LCD 0.96
* Waveshare RP2040 LCD 1.28
* WIZnet W5100S-EVB-Pico
* WIZnet W5500-EVB-Pico
* WIZnet WizFi360-EVB-Pico
* Generic (configurable flash, I/O pins)
# Installing via Arduino Boards Manager
@@ -60,8 +89,6 @@ cd ~/Arduino/hardware/pico/rp2040
git submodule update --init
cd pico-sdk
git submodule update --init
cd ../pico-extras
git submodule update --init
cd ../tools
python3 ./get.py
`````
@@ -75,7 +102,7 @@ If you follow Les' step-by-step you will also have a fully functional `CMake`-ba
To upload your first sketch, you will need to hold the BOOTSEL button down while plugging in the Pico to your computer.
Then hit the upload button and the sketch should be transferred and start to run.
After the first upload, this should not be necessary as the `arduino-pico` core has auto-reset support.
After the first upload, this should not be necessary as the `arduino-pico` core has auto-reset support.
Select the appropriate serial port shown in the Arduino Tools->Port->Serial Port menu once (this setting will stick and does not need to be
touched for multiple uploads). This selection allows the auto-reset tool to identify the proper device to reset.
Them hit the upload button and your sketch should upload and run.
@@ -87,8 +114,8 @@ follow the initial procedure of holding the BOOTSEL button down while plugging i
The onboard flash filesystem for the Pico, LittleFS, lets you upload a filesystem image from the sketch directory for your sketch to use. Download the needed plugin from
* https://github.com/earlephilhower/arduino-pico-littlefs-plugin/releases
To install, follow the directions in
* https://github.com/earlephilhower/arduino-pico-littlefs-plugin/blob/master/README.md
To install, follow the directions in
* https://github.com/earlephilhower/arduino-pico-littlefs-plugin/blob/master/README.md
For detailed usage information, please check the ESP8266 repo documentation (ignore SPIFFS related notes) available at
* https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html
@@ -131,17 +158,24 @@ The installed tools include a version of OpenOCD (in the pqt-openocd directory)
# Features
* Adafruit TinyUSB Arduino (USB mouse, keyboard, flash drive, generic HID, CDC Serial, MIDI, WebUSB, others)
* Generic Arduino USB Serial, Keyboard, and Mouse emulation
* WiFi (Pico W)
* HTTP client and server (WebServer)
* SSL/TLS/HTTPS
* Over-the-Air (OTA) upgrades
* Filesystems (LittleFS and SD/SDFS)
* Multicore support (setup1() and loop1())
* FreeRTOS SMP support
* Overclocking and underclocking from the menus
* digitalWrite/Read, shiftIn/Out, tone, analogWrite(PWM)/Read, temperature
* Peripherals: SPI master, Wire(I2C) master/slave, dual UART, emulated EEPROM, I2S audio output, Servo
* printf (i.e. debug) output over USB serial
* Peripherals: SPI master, Wire(I2C) master/slave, dual UART, emulated EEPROM, I2S audio input, I2S audio output, Servo
* printf (i.e. debug) output over USB serial
The RP2040 PIO state machines (SMs) are used to generate jitter-free:
* Servos
* Tones
* I2S Input
* I2S Output
* Software UARTs (Serial ports)
# Tutorials from Across the Web
Here are some links to coverage and additional tutorials for using `arduino-pico`
@@ -150,6 +184,7 @@ Here are some links to coverage and additional tutorials for using `arduino-pico
* Pre-release Adafruit QT Py RP2040 - https://www.youtube.com/watch?v=sfC1msqXX0I
* Adafruit Feather RP2040 running LCD + TMP117 - https://www.youtube.com/watch?v=fKDeqZiIwHg
* Demonstration of Servos and I2C in Korean - https://cafe.naver.com/arduinoshield/1201
* Home Assistant Pico W integration starter project using Arduino - https://github.com/daniloc/PicoW_HomeAssistant_Starter
# Contributing
If you want to contribute or have bugfixes, drop me a note at <earlephilhower@yahoo.com> or open an issue/PR here.
@@ -157,11 +192,20 @@ If you want to contribute or have bugfixes, drop me a note at <earlephilhower@ya
# Licensing and Credits
* The [Arduino IDE and ArduinoCore-API](https://arduino.cc) are developed and maintained by the Arduino team. The IDE is licensed under GPL.
* The [RP2040 GCC-based toolchain](https://github.com/earlephilhower/pico-quick-toolchain) is licensed under under the GPL.
* The [Pico-SDK](https://github.com/raspberrypi/pico-sdk) and [Pico-Extras](https://github.com/raspberrypi/pico-extras) are by Raspberry Pi (Trading) Ltd and licensed under the BSD 3-Clause license.
* The [Pico-SDK](https://github.com/raspberrypi/pico-sdk) is by Raspberry Pi (Trading) Ltd and licensed under the BSD 3-Clause license.
* [Arduino-Pico](https://github.com/earlephilhower/arduino-pico) core files are licensed under the LGPL.
* [LittleFS](https://github.com/ARMmbed/littlefs) library written by ARM Limited and released under the [BSD 3-clause license](https://github.com/ARMmbed/littlefs/blob/master/LICENSE.md).
* [UF2CONV.PY](https://github.com/microsoft/uf2) is by Microsoft Corporation and licensed under the MIT license.
* Some filesystem code taken from the [ESP8266 Arduino Core](https://github.com/esp8266/Arduino) and licensed under the LGPL.
* Networking and filesystem code taken from the [ESP8266 Arduino Core](https://github.com/esp8266/Arduino) and licensed under the LGPL.
* DHCP server for AP host mode from the [Micropython Project](https://micropython.org), distributed under the MIT License.
* [FreeRTOS](https://freertos.org) is Copyright Amazon.com, Inc. or its affiliates, and distributed under the MIT license.
* [lwIP](https://savannah.nongnu.org/projects/lwip/) is (c) the Swedish Institute of Computer Science and licenced under the BSD license.
* [BearSSL](https://bearssl.org) library written by Thomas Pornin, is distributed under the [MIT License](https://bearssl.org/#legal-details).
* [UZLib](https://github.com/pfalcon/uzlib) is copyright (c) 2003 Joergen Ibsen and distributed under the zlib license.
* [LEAmDNS](https://github.com/LaborEtArs/ESP8266mDNS) is copyright multiple authors and distributed under the MIT license.
* [http-parser](https://github.com/nodejs/http-parser) is copyright Joyent, Inc. and other Node contributors.
* WebServer code modified from the [ESP32 WebServer](https://github.com/espressif/arduino-esp32/tree/master/libraries/WebServer) and is copyright (c) 2015 Ivan Grokhotkov and others
-Earle F. Philhower, III
-Earle F. Philhower, III
earlephilhower@yahoo.com
+21312 -1792
View File
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,23 @@
// Padded and checksummed version of: generated\Winbond\W25Q16JVxQ\boot2.bin
.cpu cortex-m0plus
.thumb
.section .boot2, "ax"
.byte 0xf7, 0xb5, 0x73, 0x46, 0x21, 0x22, 0x02, 0x26, 0x01, 0x93, 0x29, 0x4b, 0xc0, 0x24, 0x5a, 0x60
.byte 0x9a, 0x68, 0x00, 0x27, 0xb2, 0x43, 0xda, 0x60, 0x9a, 0x60, 0x1a, 0x61, 0x5a, 0x61, 0x04, 0x23
.byte 0x01, 0x25, 0x64, 0x05, 0xa7, 0x60, 0x63, 0x61, 0x22, 0x4b, 0x30, 0x00, 0x1d, 0x60, 0xe0, 0x23
.byte 0xdb, 0x02, 0x23, 0x60, 0x35, 0x23, 0xa5, 0x60, 0x23, 0x66, 0x23, 0x66, 0x00, 0xf0, 0x4a, 0xf8
.byte 0xc0, 0xb2, 0xb0, 0x42, 0x12, 0xd0, 0x06, 0x23, 0x28, 0x00, 0x23, 0x66, 0x00, 0xf0, 0x42, 0xf8
.byte 0x25, 0x66, 0x03, 0x20, 0x27, 0x66, 0x26, 0x66, 0x00, 0xf0, 0x3c, 0xf8, 0x03, 0x36, 0x26, 0x66
.byte 0x02, 0x20, 0x26, 0x66, 0x00, 0xf0, 0x36, 0xf8, 0x28, 0x42, 0xf8, 0xd1, 0x00, 0x25, 0x12, 0x4b
.byte 0xa5, 0x60, 0x12, 0x4f, 0x23, 0x60, 0x12, 0x4b, 0x65, 0x60, 0x01, 0x26, 0x3b, 0x60, 0xeb, 0x23
.byte 0xa6, 0x60, 0x23, 0x66, 0x4b, 0x3b, 0x23, 0x66, 0x02, 0x20, 0x00, 0xf0, 0x23, 0xf8, 0x0d, 0x4b
.byte 0xa5, 0x60, 0x3b, 0x60, 0xa6, 0x60, 0x01, 0x9b, 0xab, 0x42, 0x08, 0xd1, 0x0a, 0x4b, 0x0b, 0x4a
.byte 0x13, 0x60, 0x1b, 0x68, 0x83, 0xf3, 0x08, 0x88, 0x09, 0x4b, 0x1b, 0x68, 0x18, 0x47, 0xf7, 0xbd
.byte 0x00, 0x00, 0x02, 0x40, 0xf0, 0x00, 0x00, 0x18, 0x00, 0x03, 0x5f, 0x00, 0xf4, 0x00, 0x00, 0x18
.byte 0x21, 0x22, 0x00, 0x00, 0x22, 0x20, 0x00, 0xa0, 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0
.byte 0x04, 0x01, 0x00, 0x10, 0xc0, 0x22, 0x03, 0x00, 0x04, 0x21, 0x52, 0x05, 0x90, 0x6a, 0x08, 0x42
.byte 0xfc, 0xd0, 0x01, 0x21, 0x90, 0x6a, 0x08, 0x42, 0xfc, 0xd1, 0x01, 0x3b, 0xdb, 0xb2, 0x10, 0x6e
.byte 0x00, 0x2b, 0xfa, 0xd1, 0x70, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xa0, 0xf0, 0x2f
+23
View File
@@ -0,0 +1,23 @@
// Padded and checksummed version of: boot2_w25q64jv.4.bin
.cpu cortex-m0plus
.thumb
.section .boot2, "ax"
.byte 0xf7, 0xb5, 0x73, 0x46, 0x21, 0x22, 0x02, 0x25, 0x01, 0x93, 0x29, 0x4b, 0xc0, 0x24, 0x5a, 0x60
.byte 0x9a, 0x68, 0x01, 0x26, 0xaa, 0x43, 0xda, 0x60, 0x9a, 0x60, 0x1a, 0x61, 0x5a, 0x61, 0x00, 0x23
.byte 0x64, 0x05, 0xa3, 0x60, 0x04, 0x33, 0x63, 0x61, 0x22, 0x4b, 0x28, 0x00, 0x1e, 0x60, 0xe0, 0x23
.byte 0xdb, 0x02, 0x23, 0x60, 0x35, 0x23, 0xa6, 0x60, 0x23, 0x66, 0x23, 0x66, 0x00, 0xf0, 0x4a, 0xf8
.byte 0xc0, 0xb2, 0xa8, 0x42, 0x12, 0xd0, 0x06, 0x23, 0x30, 0x00, 0x23, 0x66, 0x00, 0xf0, 0x42, 0xf8
.byte 0x31, 0x23, 0x28, 0x00, 0x23, 0x66, 0x25, 0x66, 0x00, 0xf0, 0x3c, 0xf8, 0x03, 0x35, 0x25, 0x66
.byte 0x02, 0x20, 0x25, 0x66, 0x00, 0xf0, 0x36, 0xf8, 0x30, 0x42, 0xf8, 0xd1, 0x00, 0x25, 0x12, 0x4b
.byte 0xa5, 0x60, 0x12, 0x4f, 0x23, 0x60, 0x12, 0x4b, 0x65, 0x60, 0x01, 0x26, 0x3b, 0x60, 0xeb, 0x23
.byte 0xa6, 0x60, 0x23, 0x66, 0x4b, 0x3b, 0x23, 0x66, 0x02, 0x20, 0x00, 0xf0, 0x23, 0xf8, 0x0d, 0x4b
.byte 0xa5, 0x60, 0x3b, 0x60, 0xa6, 0x60, 0x01, 0x9b, 0xab, 0x42, 0x08, 0xd1, 0x0a, 0x4b, 0x0b, 0x4a
.byte 0x13, 0x60, 0x1b, 0x68, 0x83, 0xf3, 0x08, 0x88, 0x09, 0x4b, 0x1b, 0x68, 0x18, 0x47, 0xf7, 0xbd
.byte 0x00, 0x00, 0x02, 0x40, 0xf0, 0x00, 0x00, 0x18, 0x00, 0x03, 0x5f, 0x00, 0xf4, 0x00, 0x00, 0x18
.byte 0x21, 0x22, 0x00, 0x00, 0x22, 0x20, 0x00, 0xa0, 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0
.byte 0x04, 0x01, 0x00, 0x10, 0xc0, 0x23, 0x02, 0x00, 0x04, 0x21, 0x5b, 0x05, 0x98, 0x6a, 0x08, 0x42
.byte 0xfc, 0xd0, 0x01, 0x21, 0x98, 0x6a, 0x08, 0x42, 0xfc, 0xd1, 0x18, 0x6e, 0x01, 0x2a, 0x00, 0xd0
.byte 0x18, 0x6e, 0x70, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x2d, 0x68, 0xca
+18 -5
View File
@@ -18,18 +18,19 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef Arduino_h
#define Arduino_h
#pragma once
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "stdlib_noniso.h" // Wacky deprecated AVR compatibility functions
#include "RP2040Version.h"
#include "api/ArduinoAPI.h"
#include "api/itoa.h" // ARM toolchain doesn't provide itoa etc, provide them
#include <pins_arduino.h>
#include "hardware/gpio.h" // Required for the port*Register macros
#include "debug_internal.h"
#include <RP2040.h> // CMSIS
// Try and make the best of the old Arduino abs() macro. When in C++, use
// the sane std::abs() call, but for C code use their macro since stdlib abs()
@@ -69,6 +70,7 @@ void noInterrupts();
#define portModeRegister(port) ((volatile uint32_t*) sio_hw->gpio_oe)
// ADC RP2040-specific calls
void analogReadResolution(int bits);
float analogReadTemp(); // Returns core temp in Centigrade
// PWM RP2040-specific calls
@@ -76,6 +78,9 @@ void analogWriteFreq(uint32_t freq);
void analogWriteRange(uint32_t range);
void analogWriteResolution(int res);
// FreeRTOS potential calls
extern bool __isFreeRTOS;
#ifdef __cplusplus
} // extern "C"
#endif
@@ -85,6 +90,15 @@ void analogWriteResolution(int res);
#define HAVE_HWSERIAL1
#define HAVE_HWSERIAL2
// PSTR/etc.
#ifndef FPSTR
#define FPSTR (const char *)
#endif
#ifndef PGM_VOID_P
#define PGM_VOID_P void *
#endif
#ifdef __cplusplus
#ifdef USE_TINYUSB
@@ -95,7 +109,8 @@ void analogWriteResolution(int res);
#endif
#include "SerialUART.h"
#include "RP2040.h"
#include "RP2040Support.h"
#include "SerialPIO.h"
#include "Bootsel.h"
// Template which will evaluate at *compile time* to a single 32b number
@@ -105,5 +120,3 @@ constexpr uint32_t __bitset(const int (&a)[N], size_t i = 0U) {
return i < N ? (1L << a[i]) | __bitset(a, i + 1) : 0;
}
#endif
#endif // Arduino_h
+1 -1
View File
@@ -47,8 +47,8 @@ static bool __no_inline_not_in_flash_func(get_bootsel_button)() {
GPIO_OVERRIDE_NORMAL << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB,
IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS);
interrupts();
rp2040.resumeOtherCore();
interrupts();
return button_state;
}
+66
View File
@@ -0,0 +1,66 @@
/*
CoreMutex for the Raspberry Pi Pico RP2040
Implements a deadlock-safe multicore mutex for sharing things like the
USB or UARTs.
Copyright (c) 2021 Earle F. Philhower, III <earlephilhower@yahoo.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "Arduino.h"
#include "CoreMutex.h"
CoreMutex::CoreMutex(mutex_t *mutex, uint8_t option) {
_mutex = mutex;
_acquired = false;
_option = option;
if (__isFreeRTOS) {
auto m = __get_freertos_mutex_for_ptr(mutex);
if (_option & FromISR) {
__freertos_mutex_take_from_isr(m);
} else {
__freertos_mutex_take(m);
}
} else {
uint32_t owner;
if (!mutex_try_enter(_mutex, &owner)) {
if (owner == get_core_num()) { // Deadlock!
if (_option & DebugEnable) {
DEBUGCORE("CoreMutex - Deadlock detected!\n");
}
return;
}
mutex_enter_blocking(_mutex);
}
}
_acquired = true;
}
CoreMutex::~CoreMutex() {
if (_acquired) {
if (__isFreeRTOS) {
auto m = __get_freertos_mutex_for_ptr(_mutex);
if (_option & FromISR) {
__freertos_mutex_give_from_isr(m);
} else {
__freertos_mutex_give(m);
}
} else {
mutex_exit(_mutex);
}
}
}
+9 -19
View File
@@ -24,28 +24,17 @@
#pragma once
#include "pico/mutex.h"
#include "_freertos.h"
enum {
DebugEnable = 1,
FromISR = 1 << 1,
};
class CoreMutex {
public:
CoreMutex(mutex_t *mutex) {
uint32_t owner;
_mutex = mutex;
_acquired = false;
if (!mutex_try_enter(_mutex, &owner)) {
if (owner == get_core_num()) { // Deadlock!
DEBUGCORE("CoreMutex - Deadlock detected!\n");
return;
}
mutex_enter_blocking(_mutex);
}
_acquired = true;
}
~CoreMutex() {
if (_acquired) {
mutex_exit(_mutex);
}
}
CoreMutex(mutex_t *mutex, uint8_t option = DebugEnable);
~CoreMutex();
operator bool() {
return _acquired;
@@ -54,4 +43,5 @@ public:
private:
mutex_t *_mutex;
bool _acquired;
u_int8_t _option;
};
+6 -22
View File
@@ -18,8 +18,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef FS_H
#define FS_H
#pragma once
#include <memory>
#include <Arduino.h>
@@ -51,7 +50,9 @@ enum SeekMode {
class File : public Stream {
public:
File(FileImplPtr p = FileImplPtr(), FS *baseFS = nullptr) : _p(p), _fakeDir(nullptr), _baseFS(baseFS) { }
File(FileImplPtr p = FileImplPtr(), FS *baseFS = nullptr) : _p(p), _fakeDir(nullptr), _baseFS(baseFS) {
_startMillis = millis(); /* workaround -O3 spurious warning #768 */
}
// Print methods:
size_t write(uint8_t) override;
@@ -91,9 +92,8 @@ public:
uint8_t obuf[256];
size_t doneLen = 0;
size_t sentLen;
int i;
while (src.available() > sizeof(obuf)) {
while ((size_t)src.available() > sizeof(obuf)) {
src.read(obuf, sizeof(obuf));
sentLen = write(obuf, sizeof(obuf));
doneLen = doneLen + sentLen;
@@ -188,15 +188,6 @@ public:
bool _autoFormat;
};
class SPIFFSConfig : public FSConfig {
public:
static constexpr uint32_t FSId = 0x53504946;
SPIFFSConfig(bool autoFormat = true) : FSConfig(FSId, autoFormat) { }
// Inherit _type and _autoFormat
// nothing yet, enableTime TBD when SPIFFS has metadate
};
class FS {
public:
FS(FSImplPtr impl) : _impl(impl) {
@@ -249,7 +240,7 @@ protected:
}
time_t (*_timeCallback)(void) = nullptr;
static time_t _defaultTimeCB(void) {
return time(NULL);
return time(nullptr);
}
};
@@ -272,11 +263,4 @@ using fs::SeekCur;
using fs::SeekEnd;
using fs::FSInfo;
using fs::FSConfig;
using fs::SPIFFSConfig;
#endif //FS_NO_GLOBALS
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SPIFFS)
extern fs::FS SPIFFS __attribute__((deprecated("SPIFFS has been deprecated. Please consider moving to LittleFS or other filesystems.")));
#endif
#endif //FS_H
+2 -4
View File
@@ -17,8 +17,8 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef FSIMPL_H
#define FSIMPL_H
#pragma once
#include <stddef.h>
#include <stdint.h>
@@ -149,5 +149,3 @@ protected:
};
} // namespace fs
#endif //FSIMPL_H
+290
View File
@@ -0,0 +1,290 @@
/*
PolledTimeout.h - Encapsulation of a polled Timeout
Copyright (c) 2018 Daniel Salazar. All rights reserved.
This file is part of the esp8266 core for Arduino environment.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include <limits> // std::numeric_limits
#include <type_traits> // std::is_unsigned
#define IRAM_ATTR
namespace esp8266 {
namespace polledTimeout {
namespace YieldPolicy {
struct DoNothing {
static void execute() {}
};
struct YieldOrSkip {
static void execute() {} //{esp_yield();}
};
template <unsigned long delayMs>
struct YieldAndDelayMs {
static void execute() {
delay(delayMs);
}
};
} //YieldPolicy
namespace TimePolicy {
struct TimeSourceMillis {
// time policy in milli-seconds based on millis()
using timeType = decltype(millis());
static timeType time() {
return millis();
}
static constexpr timeType ticksPerSecond = 1000;
static constexpr timeType ticksPerSecondMax = 1000;
};
struct TimeSourceCycles {
// time policy based on esp_get_cycle_count()
// this particular time measurement is intended to be called very often
// (every loop, every yield)
using timeType = decltype(rp2040.getCycleCount());
static timeType time() {
return rp2040.getCycleCount();
}
static constexpr timeType ticksPerSecond = F_CPU;
static constexpr timeType ticksPerSecondMax = F_CPU;
};
template <typename TimeSourceType, unsigned long long second_th>
// "second_th" units of timeType for one second
struct TimeUnit {
using timeType = typename TimeSourceType::timeType;
#if __GNUC__ < 5
// gcc-4.8 cannot compile the constexpr-only version of this function
// using #defines instead luckily works
static constexpr timeType computeRangeCompensation() {
#define number_of_secondTh_in_one_tick ((1.0 * second_th) / ticksPerSecond)
#define fractional (number_of_secondTh_in_one_tick - (long)number_of_secondTh_in_one_tick)
return ({
fractional == 0 ?
1 : // no need for compensation
(number_of_secondTh_in_one_tick / fractional) + 0.5; // scalar multiplier allowing exact division
});
#undef number_of_secondTh_in_one_tick
#undef fractional
}
#else
static constexpr timeType computeRangeCompensation() {
return ({
constexpr double number_of_secondTh_in_one_tick = (1.0 * second_th) / ticksPerSecond;
constexpr double fractional = number_of_secondTh_in_one_tick - (long)number_of_secondTh_in_one_tick;
fractional == 0 ?
1 : // no need for compensation
(number_of_secondTh_in_one_tick / fractional) + 0.5; // scalar multiplier allowing exact division
});
}
#endif
static constexpr timeType ticksPerSecond = TimeSourceType::ticksPerSecond;
static constexpr timeType ticksPerSecondMax = TimeSourceType::ticksPerSecondMax;
static constexpr timeType rangeCompensate = computeRangeCompensation();
static constexpr timeType user2UnitMultiplierMax = (ticksPerSecondMax * rangeCompensate) / second_th;
static constexpr timeType user2UnitMultiplier = (ticksPerSecond * rangeCompensate) / second_th;
static constexpr timeType user2UnitDivider = rangeCompensate;
// std::numeric_limits<timeType>::max() is reserved
static constexpr timeType timeMax = (std::numeric_limits<timeType>::max() - 1) / user2UnitMultiplierMax;
static timeType toTimeTypeUnit(const timeType userUnit) {
return (userUnit * user2UnitMultiplier) / user2UnitDivider;
}
static timeType toUserUnit(const timeType internalUnit) {
return (internalUnit * user2UnitDivider) / user2UnitMultiplier;
}
static timeType time() {
return TimeSourceType::time();
}
};
using TimeMillis = TimeUnit < TimeSourceMillis, 1'000 >;
using TimeFastMillis = TimeUnit < TimeSourceCycles, 1'000 >;
using TimeFastMicros = TimeUnit < TimeSourceCycles, 1'000'000 >;
using TimeFastNanos = TimeUnit < TimeSourceCycles, 1'000'000'000 >;
} //TimePolicy
template <bool PeriodicT, typename YieldPolicyT = YieldPolicy::DoNothing, typename TimePolicyT = TimePolicy::TimeMillis>
class timeoutTemplate {
public:
using timeType = typename TimePolicyT::timeType;
static_assert(std::is_unsigned<timeType>::value == true, "timeType must be unsigned");
static constexpr timeType alwaysExpired = 0;
static constexpr timeType neverExpires = std::numeric_limits<timeType>::max();
static constexpr timeType rangeCompensate = TimePolicyT::rangeCompensate; //debug
timeoutTemplate(const timeType userTimeout) {
reset(userTimeout);
}
IRAM_ATTR // fast
bool expired() {
YieldPolicyT::execute(); //in case of DoNothing: gets optimized away
if (PeriodicT) { //in case of false: gets optimized away
return expiredRetrigger();
}
return expiredOneShot();
}
IRAM_ATTR // fast
operator bool() {
return expired();
}
bool canExpire() const {
return !_neverExpires;
}
bool canWait() const {
return _timeout != alwaysExpired;
}
// Resets, will trigger after this new timeout.
IRAM_ATTR // called from ISR
void reset(const timeType newUserTimeout) {
reset();
_timeout = TimePolicyT::toTimeTypeUnit(newUserTimeout);
_neverExpires = (newUserTimeout < 0) || (newUserTimeout > timeMax());
}
// Resets, will trigger after the timeout previously set.
IRAM_ATTR // called from ISR
void reset() {
_start = TimePolicyT::time();
}
// Resets to just expired so that on next poll the check will immediately trigger for the user,
// also change timeout (after next immediate trigger).
IRAM_ATTR // called from ISR
void resetAndSetExpired(const timeType newUserTimeout) {
reset(newUserTimeout);
_start -= _timeout;
}
// Resets to just expired so that on next poll the check will immediately trigger for the user.
IRAM_ATTR // called from ISR
void resetAndSetExpired() {
reset();
_start -= _timeout;
}
void resetToNeverExpires() {
_timeout = alwaysExpired + 1; // because canWait() has precedence
_neverExpires = true;
}
timeType getTimeout() const {
return TimePolicyT::toUserUnit(_timeout);
}
static constexpr timeType timeMax() {
return TimePolicyT::timeMax;
}
private:
IRAM_ATTR // fast
bool checkExpired(const timeType internalUnit) const {
// canWait() is not checked here
// returns "can expire" and "time expired"
return (!_neverExpires) && ((internalUnit - _start) >= _timeout);
}
protected:
IRAM_ATTR // fast
bool expiredRetrigger() {
if (!canWait()) {
return true;
}
timeType current = TimePolicyT::time();
if (checkExpired(current)) {
unsigned long n = (current - _start) / _timeout; //how many _timeouts periods have elapsed, will usually be 1 (current - _start >= _timeout)
_start += n * _timeout;
return true;
}
return false;
}
IRAM_ATTR // fast
bool expiredOneShot() const {
// returns "always expired" or "has expired"
return !canWait() || checkExpired(TimePolicyT::time());
}
timeType _timeout;
timeType _start;
bool _neverExpires;
};
// legacy type names, deprecated (unit is milliseconds)
using oneShot = polledTimeout::timeoutTemplate<false> /*__attribute__((deprecated("use oneShotMs")))*/;
using periodic = polledTimeout::timeoutTemplate<true> /*__attribute__((deprecated("use periodicMs")))*/;
// standard versions (based on millis())
// timeMax() is 49.7 days ((2^32)-2 ms)
using oneShotMs = polledTimeout::timeoutTemplate<false>;
using periodicMs = polledTimeout::timeoutTemplate<true>;
// Time policy based on esp_get_cycle_count(), and intended to be called very often:
// "Fast" versions sacrifices time range for improved precision and reduced execution time (by 86%)
// (cpu cycles for ::expired(): 372 (millis()) vs 52 (esp_get_cycle_count()))
// timeMax() values:
// Ms: max is 26843 ms (26.8 s)
// Us: max is 26843545 us (26.8 s)
// Ns: max is 1073741823 ns ( 1.07 s)
// (time policy based on esp_get_cycle_count() is intended to be called very often)
using oneShotFastMs = polledTimeout::timeoutTemplate<false, YieldPolicy::DoNothing, TimePolicy::TimeFastMillis>;
using periodicFastMs = polledTimeout::timeoutTemplate<true, YieldPolicy::DoNothing, TimePolicy::TimeFastMillis>;
using oneShotFastUs = polledTimeout::timeoutTemplate<false, YieldPolicy::DoNothing, TimePolicy::TimeFastMicros>;
using periodicFastUs = polledTimeout::timeoutTemplate<true, YieldPolicy::DoNothing, TimePolicy::TimeFastMicros>;
using oneShotFastNs = polledTimeout::timeoutTemplate<false, YieldPolicy::DoNothing, TimePolicy::TimeFastNanos>;
using periodicFastNs = polledTimeout::timeoutTemplate<true, YieldPolicy::DoNothing, TimePolicy::TimeFastNanos>;
} //polledTimeout
/* A 1-shot timeout that auto-yields when in CONT can be built as follows:
using oneShotYieldMs = esp8266::polledTimeout::timeoutTemplate<false, esp8266::polledTimeout::YieldPolicy::YieldOrSkip>;
Other policies can be implemented by the user, e.g.: simple yield that panics in SYS, and the polledTimeout types built as needed as shown above, without modifying this file.
*/
}//esp8266
+33
View File
@@ -0,0 +1,33 @@
/*
RP2040 utility class
Copyright (c) 2021 Earle F. Philhower, III <earlephilhower@yahoo.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <Arduino.h>
#include <hardware/structs/psm.h>
extern "C" void boot_double_tap_check();
// The following check will never actually execute, but it will cause the boot reset
// checker to be linked in as part of the constructors.
void RP2040::enableDoubleResetBootloader() {
if (psm_hw->done == 0) {
boot_double_tap_check();
}
}
@@ -21,11 +21,20 @@
#include <hardware/clocks.h>
#include <hardware/irq.h>
#include <hardware/pio.h>
#include <pico/unique_id.h>
#include <hardware/exception.h>
#include <hardware/watchdog.h>
#include <hardware/structs/rosc.h>
#include <hardware/structs/systick.h>
#include <pico/multicore.h>
#include <pico/util/queue.h>
#include <CoreMutex.h>
#include "CoreMutex.h"
#include "ccount.pio.h"
#include <malloc.h>
#include "_freertos.h"
extern "C" volatile bool __otherCoreIdled;
class _MFIFO {
public:
@@ -45,9 +54,12 @@ public:
}
void registerCore() {
multicore_fifo_clear_irq();
irq_set_exclusive_handler(SIO_IRQ_PROC0 + get_core_num(), _irq);
irq_set_enabled(SIO_IRQ_PROC0 + get_core_num(), true);
if (!__isFreeRTOS) {
multicore_fifo_clear_irq();
irq_set_exclusive_handler(SIO_IRQ_PROC0 + get_core_num(), _irq);
irq_set_enabled(SIO_IRQ_PROC0 + get_core_num(), true);
}
// FreeRTOS port.c will handle the IRQ hooking
}
void push(uint32_t val) {
@@ -78,10 +90,15 @@ public:
if (!_multicore) {
return;
}
__holdUpPendSV = 1;
if (__isFreeRTOS) {
vTaskPreemptionDisable(nullptr);
vTaskSuspendAll();
}
mutex_enter_blocking(&_idleMutex);
_otherIdled = false;
__otherCoreIdled = false;
multicore_fifo_push_blocking(_GOTOSLEEP);
while (!_otherIdled) { /* noop */ }
while (!__otherCoreIdled) { /* noop */ }
}
void resumeOtherCore() {
@@ -89,97 +106,59 @@ public:
return;
}
mutex_exit(&_idleMutex);
_otherIdled = false;
__otherCoreIdled = false;
if (__isFreeRTOS) {
xTaskResumeAll();
vTaskPreemptionEnable(nullptr);
}
__holdUpPendSV = 0;
// Other core will exit busy-loop and return to operation
// once otherIdled == false.
// once __otherCoreIdled == false.
}
void clear() {
uint32_t val;
while (queue_try_remove(&_queue[0], &val)) {
tight_loop_contents();
}
while (queue_try_remove(&_queue[1], &val)) {
tight_loop_contents();
}
}
private:
static void __no_inline_not_in_flash_func(_irq)() {
multicore_fifo_clear_irq();
noInterrupts(); // We need total control, can't run anything
while (multicore_fifo_rvalid()) {
if (_GOTOSLEEP == multicore_fifo_pop_blocking()) {
_otherIdled = true;
while (_otherIdled) { /* noop */ }
break;
if (!__isFreeRTOS) {
multicore_fifo_clear_irq();
noInterrupts(); // We need total control, can't run anything
while (multicore_fifo_rvalid()) {
if (_GOTOSLEEP == multicore_fifo_pop_blocking()) {
__otherCoreIdled = true;
while (__otherCoreIdled) { /* noop */ }
break;
}
}
interrupts();
}
interrupts();
}
bool _multicore = false;
mutex_t _idleMutex;
static volatile bool _otherIdled;
queue_t _queue[2];
static constexpr int _GOTOSLEEP = 0x66666666;
static constexpr uint32_t _GOTOSLEEP = 0xC0DED02E;
};
class RP2040;
extern RP2040 rp2040;
class RP2040 {
public:
RP2040() {
_epoch = 0;
// Enable SYSTICK exception
exception_set_exclusive_handler(SYSTICK_EXCEPTION, _SystickHandler);
systick_hw->csr = 0x7;
systick_hw->rvr = 0x00FFFFFF;
}
extern "C" void main1();
class PIOProgram;
~RP2040() { /* noop */ }
// Convert from microseconds to PIO clock cycles
static int usToPIOCycles(int us) {
// Parenthesis needed to guarantee order of operations to avoid 32bit overflow
return (us * (clock_get_hz(clk_sys) / 1000000));
}
// Get current clock frequency
static int f_cpu() {
return clock_get_hz(clk_sys);
}
// Get CPU cycle count. Needs to do magic to extens 24b HW to something longer
volatile uint64_t _epoch = 0;
inline uint32_t getCycleCount() {
uint32_t epoch;
uint32_t ctr;
do {
epoch = (uint32_t)_epoch;
ctr = systick_hw->cvr;
} while (epoch != (uint32_t)_epoch);
return epoch + (1 << 24) - ctr; /* CTR counts down from 1<<24-1 */
}
inline uint64_t getCycleCount64() {
uint64_t epoch;
uint64_t ctr;
do {
epoch = _epoch;
ctr = systick_hw->cvr;
} while (epoch != _epoch);
return epoch + (1LL << 24) - ctr;
}
void idleOtherCore() {
fifo.idleOtherCore();
}
void resumeOtherCore() {
fifo.resumeOtherCore();
}
// Multicore comms FIFO
_MFIFO fifo;
private:
static void _SystickHandler() {
rp2040._epoch += 1LL << 24;
}
};
extern "C" char __StackLimit;
extern "C" char __bss_end__;
// Wrapper class for PIO programs, abstracting common operations out
// TODO - Add unload/destructor
@@ -235,3 +214,155 @@ private:
const pio_program_t *_pgm;
};
class RP2040 {
public:
RP2040() { /* noop */ }
~RP2040() { /* noop */ }
void begin() {
_epoch = 0;
if (!__isFreeRTOS) {
// Enable SYSTICK exception
exception_set_exclusive_handler(SYSTICK_EXCEPTION, _SystickHandler);
systick_hw->csr = 0x7;
systick_hw->rvr = 0x00FFFFFF;
} else {
int off = 0;
_ccountPgm = new PIOProgram(&ccount_program);
_ccountPgm->prepare(&_pio, &_sm, &off);
ccount_program_init(_pio, _sm, off);
pio_sm_set_enabled(_pio, _sm, true);
}
}
// Convert from microseconds to PIO clock cycles
static int usToPIOCycles(int us) {
// Parenthesis needed to guarantee order of operations to avoid 32bit overflow
return (us * (clock_get_hz(clk_sys) / 1'000'000));
}
// Get current clock frequency
static int f_cpu() {
return clock_get_hz(clk_sys);
}
// Get CPU cycle count. Needs to do magic to extens 24b HW to something longer
volatile uint64_t _epoch = 0;
inline uint32_t getCycleCount() {
if (!__isFreeRTOS) {
uint32_t epoch;
uint32_t ctr;
do {
epoch = (uint32_t)_epoch;
ctr = systick_hw->cvr;
} while (epoch != (uint32_t)_epoch);
return epoch + (1 << 24) - ctr; /* CTR counts down from 1<<24-1 */
} else {
return ccount_read(_pio, _sm);
}
}
inline uint64_t getCycleCount64() {
if (!__isFreeRTOS) {
uint64_t epoch;
uint64_t ctr;
do {
epoch = _epoch;
ctr = systick_hw->cvr;
} while (epoch != _epoch);
return epoch + (1LL << 24) - ctr;
} else {
return ccount_read(_pio, _sm);
}
}
inline int getFreeHeap() {
return getTotalHeap() - getUsedHeap();
}
inline int getUsedHeap() {
struct mallinfo m = mallinfo();
return m.uordblks;
}
inline int getTotalHeap() {
return &__StackLimit - &__bss_end__;
}
void idleOtherCore() {
fifo.idleOtherCore();
}
void resumeOtherCore() {
fifo.resumeOtherCore();
}
void restartCore1() {
multicore_reset_core1();
fifo.clear();
multicore_launch_core1(main1);
}
void reboot() {
watchdog_reboot(0, 0, 10);
while (1) {
continue;
}
}
inline void restart() {
reboot();
}
static void enableDoubleResetBootloader();
void wdt_begin(uint32_t delay_ms) {
watchdog_enable(delay_ms, 1);
}
void wdt_reset() {
watchdog_update();
}
const char *getChipID() {
static char id[2 * PICO_UNIQUE_BOARD_ID_SIZE_BYTES + 1] = { 0 };
if (!id[0]) {
pico_get_unique_board_id_string(id, sizeof(id));
}
return id;
}
// Multicore comms FIFO
_MFIFO fifo;
// TODO - Not so great HW random generator. 32-bits wide. Cryptographers somewhere are crying
uint32_t hwrand32() {
// Try and whiten the HW ROSC bit
uint32_t r = 0;
for (int k = 0; k < 32; k++) {
unsigned long int b;
do {
b = rosc_hw->randombit & 1;
if (b != (rosc_hw->randombit & 1)) {
break;
}
} while (true);
r <<= 1;
r |= b;
}
// Stir using the cycle count LSBs. In any WiFi use case this will be a random # since the connection time is not cycle-accurate
uint64_t rr = (((uint64_t)~r) << 32LL) | r;
rr >>= rp2040.getCycleCount() & 32LL;
return (uint32_t)rr;
}
private:
static void _SystickHandler() {
rp2040._epoch += 1LL << 24;
}
PIO _pio;
int _sm;
PIOProgram *_ccountPgm;
};
+105 -68
View File
@@ -40,7 +40,7 @@ mutex_t __usb_mutex;
// USB processing will be a periodic timer task
#define USB_TASK_INTERVAL 1000
#define USB_TASK_IRQ 31
static int __usb_task_irq;
// USB VID/PID (note that PID can change depending on the add'l interfaces)
#define USBD_VID (0x2E8A) // Raspberry Pi
@@ -52,7 +52,6 @@ mutex_t __usb_mutex;
#endif
#define USBD_DESC_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN)
#define USBD_MAX_POWER_MA (250)
#define USBD_ITF_CDC (0) // needs 2 interfaces
#define USBD_ITF_MAX (2)
@@ -72,8 +71,6 @@ mutex_t __usb_mutex;
#define EPNUM_HID 0x83
#define EPNUM_MIDI 0x01
const uint8_t *tud_descriptor_device_cb(void) {
static tusb_desc_device_t usbd_desc_device = {
@@ -92,7 +89,7 @@ const uint8_t *tud_descriptor_device_cb(void) {
.iSerialNumber = USBD_STR_SERIAL,
.bNumConfigurations = 1
};
if (__USBInstallSerial && !__USBInstallKeyboard && !__USBInstallMouse && !__USBInstallMIDI) {
if (__USBInstallSerial && !__USBInstallKeyboard && !__USBInstallMouse && !__USBInstallJoystick) {
// Can use as-is, this is the default USB case
return (const uint8_t *)&usbd_desc_device;
}
@@ -103,8 +100,8 @@ const uint8_t *tud_descriptor_device_cb(void) {
if (__USBInstallMouse) {
usbd_desc_device.idProduct |= 0x4000;
}
if (__USBInstallMIDI) {
usbd_desc_device.idProduct |= 0x2000;
if (__USBInstallJoystick) {
usbd_desc_device.idProduct |= 0x0100;
}
// Set the device class to 0 to indicate multiple device classes
usbd_desc_device.bDeviceClass = 0;
@@ -121,49 +118,91 @@ int __USBGetMouseReportID() {
return __USBInstallKeyboard ? 2 : 1;
}
int __USBGetJoystickReportID() {
int i = 1;
if (__USBInstallKeyboard) {
i++;
}
if (__USBInstallMouse) {
i++;
}
return i;
}
static int __hid_report_len = 0;
static uint8_t *__hid_report = nullptr;
static uint8_t *GetDescHIDReport(int *len) {
static uint8_t *report = nullptr;
int report_len = 0;
if (report) {
free(report);
report = nullptr;
}
if (__USBInstallKeyboard && __USBInstallMouse) {
uint8_t desc_hid_report[] = {
TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(1)),
TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(2))
};
report_len = sizeof(desc_hid_report);
report = (uint8_t *)malloc(report_len);
if (report) {
memcpy(report, desc_hid_report, report_len);
}
} else if (__USBInstallKeyboard && ! __USBInstallMouse) {
uint8_t desc_hid_report[] = {
TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(1))
};
report_len = sizeof(desc_hid_report);
report = (uint8_t *)malloc(report_len);
if (report) {
memcpy(report, desc_hid_report, report_len);
}
} else { // if (!__USBInstallKeyboard && __USBInstallMouse) {
uint8_t desc_hid_report[] = {
TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(1))
};
report_len = sizeof(desc_hid_report);
report = (uint8_t *)malloc(report_len);
if (report) {
memcpy(report, desc_hid_report, report_len);
}
}
if (len) {
*len = report_len;
*len = __hid_report_len;
}
return __hid_report;
}
void __SetupDescHIDReport() {
//allocate memory for the HID report descriptors. We don't use them, but need the size here.
uint8_t desc_hid_report_mouse[] = { TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(1)) };
uint8_t desc_hid_report_joystick[] = { TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(1)) };
uint8_t desc_hid_report_keyboard[] = { TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(1)) };
int size = 0;
//accumulate the size of all used HID report descriptors
if (__USBInstallKeyboard) {
size += sizeof(desc_hid_report_keyboard);
}
if (__USBInstallMouse) {
size += sizeof(desc_hid_report_mouse);
}
if (__USBInstallJoystick) {
size += sizeof(desc_hid_report_joystick);
}
//no HID used at all
if (size == 0) {
__hid_report = nullptr;
__hid_report_len = 0;
return;
}
//allocate the "real" HID report descriptor
__hid_report = (uint8_t *)malloc(size);
if (__hid_report) {
__hid_report_len = size;
//now copy the descriptors
//1.) keyboard descriptor, if requested
if (__USBInstallKeyboard) {
memcpy(__hid_report, desc_hid_report_keyboard, sizeof(desc_hid_report_keyboard));
}
//2.) mouse descriptor, if necessary. Additional offset & new array is necessary if there is a keyboard.
if (__USBInstallMouse) {
//determine if we need an offset (USB keyboard is installed)
if (__USBInstallKeyboard) {
uint8_t desc_local[] = { TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(2)) };
memcpy(__hid_report + sizeof(desc_hid_report_keyboard), desc_local, sizeof(desc_local));
} else {
memcpy(__hid_report, desc_hid_report_mouse, sizeof(desc_hid_report_mouse));
}
}
//3.) joystick descriptor. 2 additional checks are necessary for mouse and/or keyboard
if (__USBInstallJoystick) {
uint8_t reportid = 1;
int offset = 0;
if (__USBInstallKeyboard) {
reportid++;
offset += sizeof(desc_hid_report_keyboard);
}
if (__USBInstallMouse) {
reportid++;
offset += sizeof(desc_hid_report_mouse);
}
uint8_t desc_local[] = { TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(reportid)) };
memcpy(__hid_report + offset, desc_local, sizeof(desc_local));
}
}
return report;
}
// Invoked when received GET HID REPORT DESCRIPTOR
@@ -174,15 +213,17 @@ uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance) {
return GetDescHIDReport(nullptr);
}
static uint8_t *usbd_desc_cfg = nullptr;
const uint8_t *tud_descriptor_configuration_cb(uint8_t index) {
(void)index;
static uint8_t *usbd_desc_cfg = nullptr;
return usbd_desc_cfg;
}
void __SetupUSBDescriptor() {
if (!usbd_desc_cfg) {
bool hasHID = __USBInstallKeyboard || __USBInstallMouse;
bool hasHID = __USBInstallKeyboard || __USBInstallMouse || __USBInstallJoystick;
uint8_t interface_count = (__USBInstallSerial ? 2 : 0) + (hasHID ? 1 : 0) + (__USBInstallMIDI ? 2 : 0);
uint8_t interface_count = (__USBInstallSerial ? 2 : 0) + (hasHID ? 1 : 0);
uint8_t cdc_desc[TUD_CDC_DESC_LEN] = {
// Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval
@@ -197,13 +238,7 @@ const uint8_t *tud_descriptor_configuration_cb(uint8_t index) {
TUD_HID_DESCRIPTOR(hid_itf, 0, HID_ITF_PROTOCOL_NONE, hid_report_len, EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10)
};
uint8_t midi_itf = hid_itf + (hasHID ? 1 : 0);
uint8_t midi_desc[TUD_MIDI_DESC_LEN] = {
// Interface number, string index, EP Out & EP In address, EP size
TUD_MIDI_DESCRIPTOR(midi_itf, 0, EPNUM_MIDI, 0x80 | EPNUM_MIDI, 64)
};
int usbd_desc_len = TUD_CONFIG_DESC_LEN + (__USBInstallSerial ? sizeof(cdc_desc) : 0) + (hasHID ? sizeof(hid_desc) : 0) + (__USBInstallMIDI ? sizeof(midi_desc) : 0);
int usbd_desc_len = TUD_CONFIG_DESC_LEN + (__USBInstallSerial ? sizeof(cdc_desc) : 0) + (hasHID ? sizeof(hid_desc) : 0);
uint8_t tud_cfg_desc[TUD_CONFIG_DESC_LEN] = {
// Config number, interface count, string index, total length, attribute, power in mA
@@ -225,12 +260,8 @@ const uint8_t *tud_descriptor_configuration_cb(uint8_t index) {
memcpy(ptr, hid_desc, sizeof(hid_desc));
ptr += sizeof(hid_desc);
}
if (__USBInstallMIDI) {
memcpy(ptr, midi_desc, sizeof(midi_desc));
}
}
}
return usbd_desc_cfg;
}
const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
@@ -258,7 +289,7 @@ const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
len = 1;
} else {
if (index >= sizeof(usbd_desc_str) / sizeof(usbd_desc_str[0])) {
return NULL;
return nullptr;
}
const char *str = usbd_desc_str[index];
for (len = 0; len < DESC_STR_MAX - 1 && str[len]; ++len) {
@@ -277,31 +308,37 @@ static void usb_irq() {
// if the mutex is already owned, then we are in user code
// in this file which will do a tud_task itself, so we'll just do nothing
// until the next tick; we won't starve
if (mutex_try_enter(&__usb_mutex, NULL)) {
if (mutex_try_enter(&__usb_mutex, nullptr)) {
tud_task();
mutex_exit(&__usb_mutex);
}
}
static int64_t timer_task(__unused alarm_id_t id, __unused void *user_data) {
irq_set_pending(USB_TASK_IRQ);
irq_set_pending(__usb_task_irq);
return USB_TASK_INTERVAL;
}
void __USBStart() __attribute__((weak));
void __USBStart() {
if (tusb_inited()) {
// Already called
return;
}
__SetupDescHIDReport();
__SetupUSBDescriptor();
mutex_init(&__usb_mutex);
tusb_init();
irq_set_exclusive_handler(USB_TASK_IRQ, usb_irq);
irq_set_enabled(USB_TASK_IRQ, true);
__usb_task_irq = user_irq_claim_unused(true);
irq_set_exclusive_handler(__usb_task_irq, usb_irq);
irq_set_enabled(__usb_task_irq, true);
add_alarm_in_us(USB_TASK_INTERVAL, timer_task, NULL, true);
add_alarm_in_us(USB_TASK_INTERVAL, timer_task, nullptr, true);
}
+2 -1
View File
@@ -24,8 +24,8 @@
// Weak function definitions for each type of endpoint
extern void __USBInstallSerial() __attribute__((weak));
extern void __USBInstallKeyboard() __attribute__((weak));
extern void __USBInstallJoystick() __attribute__((weak));
extern void __USBInstallMouse() __attribute__((weak));
extern void __USBInstallMIDI() __attribute__((weak));
// Big, global USB mutex, shared with all USB devices to make sure we don't
// have multiple cores updating the TUSB state in parallel
@@ -34,6 +34,7 @@ extern mutex_t __usb_mutex;
// HID report ID inquiry (report ID will vary depending on the number/type of other HID)
int __USBGetKeyboardReportID();
int __USBGetMouseReportID();
int __USBGetJoystickReportID();
// Called by main() to init the USB HW/SW.
void __USBStart();
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#define ARDUINO_PICO_MAJOR 2
#define ARDUINO_PICO_MINOR 6
#define ARDUINO_PICO_REVISION 4
#define ARDUINO_PICO_VERSION_STR "2.6.4"
+379
View File
@@ -0,0 +1,379 @@
/*
Serial-over-PIO for the Raspberry Pi Pico RP2040
Copyright (c) 2021 Earle F. Philhower, III <earlephilhower@yahoo.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "SerialPIO.h"
#include "CoreMutex.h"
#include <hardware/gpio.h>
#include <map>
#include "pio_uart.pio.h"
// ------------------------------------------------------------------------
// -- Generates a unique program for differing bit lengths
static std::map<int, PIOProgram*> _txMap;
static std::map<int, PIOProgram*> _rxMap;
// Duplicate a program and replace the first insn with a "set x, repl"
static pio_program_t *pio_make_uart_prog(int repl, const pio_program_t *pg) {
pio_program_t *p = new pio_program_t;
p->length = pg->length;
p->origin = pg->origin;
uint16_t *insn = (uint16_t *)malloc(p->length * 2);
if (!insn) {
delete p;
return nullptr;
}
memcpy(insn, pg->instructions, p->length * 2);
insn[0] = pio_encode_set(pio_x, repl);
p->instructions = insn;
return p;
}
static PIOProgram *_getTxProgram(int bits) {
auto f = _txMap.find(bits);
if (f == _txMap.end()) {
pio_program_t * p = pio_make_uart_prog(bits, &pio_tx_program);
_txMap.insert({bits, new PIOProgram(p)});
f = _txMap.find(bits);
}
return f->second;
}
static PIOProgram *_getRxProgram(int bits) {
auto f = _rxMap.find(bits);
if (f == _rxMap.end()) {
pio_program_t * p = pio_make_uart_prog(bits, &pio_rx_program);
_rxMap.insert({bits, new PIOProgram(p)});
f = _rxMap.find(bits);
}
return f->second;
}
// ------------------------------------------------------------------------
// TODO - this works, but there must be a faster/better way...
static int _parity(int bits, int data) {
int p = 0;
for (int b = 0; b < bits; b++) {
p ^= (data & (1 << b)) ? 1 : 0;
}
return p;
}
// We need to cache generated SerialPIOs so we can add data to them from
// the shared handler
static SerialPIO *_pioSP[2][4];
static void __not_in_flash_func(_fifoIRQ)() {
for (int p = 0; p < 2; p++) {
for (int sm = 0; sm < 4; sm++) {
SerialPIO *s = _pioSP[p][sm];
if (s) {
s->_handleIRQ();
pio_interrupt_clear((p == 0) ? pio0 : pio1, sm);
}
}
}
}
void __not_in_flash_func(SerialPIO::_handleIRQ)() {
if (_rx == NOPIN) {
return;
}
while (!pio_sm_is_rx_fifo_empty(_rxPIO, _rxSM)) {
uint32_t decode = _rxPIO->rxf[_rxSM];
decode >>= 33 - _rxBits;
uint32_t val = 0;
for (int b = 0; b < _bits + 1; b++) {
val |= (decode & (1 << (b * 2))) ? 1 << b : 0;
}
if (_parity == UART_PARITY_EVEN) {
int p = ::_parity(_bits, val);
int r = (val & (1 << _bits)) ? 1 : 0;
if (p != r) {
// TODO - parity error
continue;
}
} else if (_parity == UART_PARITY_ODD) {
int p = ::_parity(_bits, val);
int r = (val & (1 << _bits)) ? 1 : 0;
if (p == r) {
// TODO - parity error
continue;
}
}
auto next_writer = _writer + 1;
if (next_writer == _fifoSize) {
next_writer = 0;
}
if (next_writer != _reader) {
_queue[_writer] = val & ((1 << _bits) - 1);
asm volatile("" ::: "memory"); // Ensure the queue is written before the written count advances
_writer = next_writer;
} else {
_overflow = true;
}
}
}
SerialPIO::SerialPIO(pin_size_t tx, pin_size_t rx, size_t fifoSize) {
_tx = tx;
_rx = rx;
_fifoSize = fifoSize + 1; // Always one unused entry
_queue = new uint8_t[_fifoSize];
mutex_init(&_mutex);
}
SerialPIO::~SerialPIO() {
end();
delete[] _queue;
}
void SerialPIO::begin(unsigned long baud, uint16_t config) {
_overflow = false;
_baud = baud;
switch (config & SERIAL_PARITY_MASK) {
case SERIAL_PARITY_EVEN:
_parity = UART_PARITY_EVEN;
break;
case SERIAL_PARITY_ODD:
_parity = UART_PARITY_ODD;
break;
default:
_parity = UART_PARITY_NONE;
break;
}
switch (config & SERIAL_STOP_BIT_MASK) {
case SERIAL_STOP_BIT_1:
_stop = 1;
break;
default:
_stop = 2;
break;
}
switch (config & SERIAL_DATA_MASK) {
case SERIAL_DATA_5:
_bits = 5;
break;
case SERIAL_DATA_6:
_bits = 6;
break;
case SERIAL_DATA_7:
_bits = 7;
break;
default:
_bits = 8;
break;
}
if ((_tx == NOPIN) && (_rx == NOPIN)) {
DEBUGCORE("ERROR: No pins specified for SerialPIO\n");
return;
}
if (_tx != NOPIN) {
_txBits = _bits + _stop + (_parity != UART_PARITY_NONE ? 1 : 0) + 1/*start bit*/;
_txPgm = _getTxProgram(_txBits);
int off;
if (!_txPgm->prepare(&_txPIO, &_txSM, &off)) {
DEBUGCORE("ERROR: Unable to allocate PIO TX UART, out of PIO resources\n");
// ERROR, no free slots
return;
}
digitalWrite(_tx, HIGH);
pinMode(_tx, OUTPUT);
pio_tx_program_init(_txPIO, _txSM, off, _tx);
pio_sm_clear_fifos(_txPIO, _txSM); // Remove any existing data
// Put the divider into ISR w/o using up program space
pio_sm_put_blocking(_txPIO, _txSM, clock_get_hz(clk_sys) / _baud - 2);
pio_sm_exec(_txPIO, _txSM, pio_encode_pull(false, false));
pio_sm_exec(_txPIO, _txSM, pio_encode_mov(pio_isr, pio_osr));
// Start running!
pio_sm_set_enabled(_txPIO, _txSM, true);
}
if (_rx != NOPIN) {
_writer = 0;
_reader = 0;
_rxBits = 2 * (_bits + _stop + (_parity != UART_PARITY_NONE ? 1 : 0) + 1) - 1;
_rxPgm = _getRxProgram(_rxBits);
int off;
if (!_rxPgm->prepare(&_rxPIO, &_rxSM, &off)) {
DEBUGCORE("ERROR: Unable to allocate PIO RX UART, out of PIO resources\n");
return;
}
// Stash away the created RX port for the IRQ handler
_pioSP[pio_get_index(_rxPIO)][_rxSM] = this;
pinMode(_rx, INPUT);
pio_rx_program_init(_rxPIO, _rxSM, off, _rx);
pio_sm_clear_fifos(_rxPIO, _rxSM); // Remove any existing data
// Put phase divider into OSR w/o using add'l program memory
pio_sm_put_blocking(_rxPIO, _rxSM, clock_get_hz(clk_sys) / (_baud * 2) - 7 /* insns in PIO halfbit loop */);
pio_sm_exec(_rxPIO, _rxSM, pio_encode_pull(false, false));
// Join the TX FIFO to the RX one now that we don't need it
_rxPIO->sm[_rxSM].shiftctrl |= 0x80000000;
// Enable interrupts on rxfifo
switch (_rxSM) {
case 0: pio_set_irq0_source_enabled(_rxPIO, pis_sm0_rx_fifo_not_empty, true); break;
case 1: pio_set_irq0_source_enabled(_rxPIO, pis_sm1_rx_fifo_not_empty, true); break;
case 2: pio_set_irq0_source_enabled(_rxPIO, pis_sm2_rx_fifo_not_empty, true); break;
case 3: pio_set_irq0_source_enabled(_rxPIO, pis_sm3_rx_fifo_not_empty, true); break;
}
auto irqno = pio_get_index(_rxPIO) == 0 ? PIO0_IRQ_0 : PIO1_IRQ_0;
irq_set_exclusive_handler(irqno, _fifoIRQ);
irq_set_enabled(irqno, true);
pio_sm_set_enabled(_rxPIO, _rxSM, true);
}
_running = true;
}
void SerialPIO::end() {
if (!_running) {
return;
}
if (_tx != NOPIN) {
pio_sm_set_enabled(_txPIO, _txSM, false);
pio_sm_unclaim(_txPIO, _txSM);
}
if (_rx != NOPIN) {
pio_sm_set_enabled(_rxPIO, _rxSM, false);
pio_sm_unclaim(_rxPIO, _rxSM);
_pioSP[pio_get_index(_rxPIO)][_rxSM] = nullptr;
// If no more active, disable the IRQ
auto pioNum = pio_get_index(_rxPIO);
bool used = false;
for (int i = 0; i < 4; i++) {
used = used || !!_pioSP[pioNum][i];
}
if (!used) {
auto irqno = pioNum == 0 ? PIO0_IRQ_0 : PIO1_IRQ_0;
irq_set_enabled(irqno, false);
}
}
_running = false;
}
int SerialPIO::peek() {
CoreMutex m(&_mutex);
if (!_running || !m || (_rx == NOPIN)) {
return -1;
}
// If there's something in the FIFO now, just peek at it
if (_writer != _reader) {
return _queue[_reader];
}
return -1;
}
int SerialPIO::read() {
CoreMutex m(&_mutex);
if (!_running || !m || (_rx == NOPIN)) {
return -1;
}
if (_writer != _reader) {
auto ret = _queue[_reader];
asm volatile("" ::: "memory"); // Ensure the value is read before advancing
auto next_reader = (_reader + 1) % _fifoSize;
asm volatile("" ::: "memory"); // Ensure the reader value is only written once, correctly
_reader = next_reader;
return ret;
}
return -1;
}
bool SerialPIO::overflow() {
CoreMutex m(&_mutex);
if (!_running || !m || (_rx == NOPIN)) {
return false;
}
bool hold = _overflow;
_overflow = false;
return hold;
}
int SerialPIO::available() {
CoreMutex m(&_mutex);
if (!_running || !m || (_rx == NOPIN)) {
return 0;
}
return (_writer - _reader) % _fifoSize;
}
int SerialPIO::availableForWrite() {
CoreMutex m(&_mutex);
if (!_running || !m || (_tx == NOPIN)) {
return 0;
}
return 8 - pio_sm_get_tx_fifo_level(_txPIO, _txSM);
}
void SerialPIO::flush() {
CoreMutex m(&_mutex);
if (!_running || !m || (_tx == NOPIN)) {
return;
}
while (!pio_sm_is_tx_fifo_empty(_txPIO, _txSM)) {
delay(1); // Wait for all FIFO to be read
}
// Could have 1 byte being transmitted, so wait for bit times
delay((1000 * (_txBits + 1)) / _baud);
}
size_t SerialPIO::write(uint8_t c) {
CoreMutex m(&_mutex);
if (!_running || !m || (_tx == NOPIN)) {
return 0;
}
uint32_t val = c;
if (_parity == UART_PARITY_NONE) {
val |= 7 << _bits; // Set 2 stop bits, the HW will only transmit the required number
} else if (_parity == UART_PARITY_EVEN) {
val |= ::_parity(_bits, c) << _bits;
val |= 7 << (_bits + 1);
} else {
val |= (1 ^ ::_parity(_bits, c)) << _bits;
val |= 7 << (_bits + 1);
}
val <<= 1; // Start bit = low
pio_sm_put_blocking(_txPIO, _txSM, val);
return 1;
}
SerialPIO::operator bool() {
return _running;
}
#ifdef ARDUINO_NANO_RP2040_CONNECT
// NINA updates
SerialPIO Serial3(SERIAL3_TX, SERIAL3_RX);
#endif
+87
View File
@@ -0,0 +1,87 @@
/*
Serial-over-PIO for the Raspberry Pi Pico RP2040
Copyright (c) 2021 Earle F. Philhower, III <earlephilhower@yahoo.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include <Arduino.h>
#include "api/HardwareSerial.h"
#include <stdarg.h>
#include <queue>
#include <hardware/uart.h>
#include "CoreMutex.h"
extern "C" typedef struct uart_inst uart_inst_t;
class SerialPIO : public HardwareSerial {
public:
static const pin_size_t NOPIN = 0xff; // Use in constructor to disable RX or TX unit
SerialPIO(pin_size_t tx, pin_size_t rx, size_t fifoSize = 32);
~SerialPIO();
void begin(unsigned long baud = 115200) override {
begin(baud, SERIAL_8N1);
};
void begin(unsigned long baud, uint16_t config) override;
void end() override;
virtual int peek() override;
virtual int read() override;
virtual int available() override;
virtual int availableForWrite() override;
virtual void flush() override;
virtual size_t write(uint8_t c) override;
bool overflow();
using Print::write;
operator bool() override;
// Not to be called by users, only from the IRQ handler. In public so that the C-language IQR callback can access it
void _handleIRQ();
protected:
bool _running = false;
pin_size_t _tx, _rx;
int _baud;
int _bits;
uart_parity_t _parity;
int _stop;
bool _overflow;
mutex_t _mutex;
PIOProgram *_txPgm;
PIO _txPIO;
int _txSM;
int _txBits;
PIOProgram *_rxPgm;
PIO _rxPIO;
int _rxSM;
int _rxBits;
// Lockless, IRQ-handled circular queue
size_t _fifoSize;
uint32_t _writer;
uint32_t _reader;
uint8_t *_queue;
};
#ifdef ARDUINO_NANO_RP2040_CONNECT
// NINA updates
extern SerialPIO Serial3;
#endif
+269 -30
View File
@@ -65,46 +65,189 @@ bool SerialUART::setTX(pin_size_t pin) {
return false;
}
SerialUART::SerialUART(uart_inst_t *uart, pin_size_t tx, pin_size_t rx) {
bool SerialUART::setRTS(pin_size_t pin) {
constexpr uint32_t valid[2] = { __bitset({3, 15, 19}) /* UART0 */,
__bitset({7, 11, 23, 27}) /* UART1 */
};
if ((!_running) && ((pin == UART_PIN_NOT_DEFINED) || ((1 << pin) & valid[uart_get_index(_uart)]))) {
_rts = pin;
return true;
}
if (_running) {
panic("FATAL: Attempting to set Serial%d.RTS while running", uart_get_index(_uart) + 1);
} else {
panic("FATAL: Attempting to set Serial%d.RTS to illegal pin %d", uart_get_index(_uart) + 1, pin);
}
return false;
}
bool SerialUART::setCTS(pin_size_t pin) {
constexpr uint32_t valid[2] = { __bitset({2, 14, 18}) /* UART0 */,
__bitset({6, 10, 22, 26}) /* UART1 */
};
if ((!_running) && ((pin == UART_PIN_NOT_DEFINED) || ((1 << pin) & valid[uart_get_index(_uart)]))) {
_cts = pin;
return true;
}
if (_running) {
panic("FATAL: Attempting to set Serial%d.CTS while running", uart_get_index(_uart) + 1);
} else {
panic("FATAL: Attempting to set Serial%d.CTS to illegal pin %d", uart_get_index(_uart) + 1, pin);
}
return false;
}
bool SerialUART::setPollingMode(bool mode) {
if (_running) {
return false;
}
_polling = mode;
return true;
}
bool SerialUART::setFIFOSize(size_t size) {
if (!size || _running) {
return false;
}
_fifoSize = size + 1; // Always 1 unused entry
return true;
}
SerialUART::SerialUART(uart_inst_t *uart, pin_size_t tx, pin_size_t rx, pin_size_t rts, pin_size_t cts) {
_uart = uart;
_tx = tx;
_rx = rx;
_rts = rts;
_cts = cts;
mutex_init(&_mutex);
mutex_init(&_fifoMutex);
}
static void _uart0IRQ();
static void _uart1IRQ();
void SerialUART::begin(unsigned long baud, uint16_t config) {
if (_running) {
end();
}
_overflow = false;
_queue = new uint8_t[_fifoSize];
_baud = baud;
uart_init(_uart, baud);
int bits, stop;
uart_parity_t parity;
switch (config & SERIAL_PARITY_MASK) {
case SERIAL_PARITY_EVEN: parity = UART_PARITY_EVEN; break;
case SERIAL_PARITY_ODD: parity = UART_PARITY_ODD; break;
default: parity = UART_PARITY_NONE; break;
case SERIAL_PARITY_EVEN:
parity = UART_PARITY_EVEN;
break;
case SERIAL_PARITY_ODD:
parity = UART_PARITY_ODD;
break;
default:
parity = UART_PARITY_NONE;
break;
}
switch (config & SERIAL_STOP_BIT_MASK) {
case SERIAL_STOP_BIT_1: stop = 1; break;
default: stop = 2; break;
case SERIAL_STOP_BIT_1:
stop = 1;
break;
default:
stop = 2;
break;
}
switch (config & SERIAL_DATA_MASK) {
case SERIAL_DATA_5: bits = 5; break;
case SERIAL_DATA_6: bits = 6; break;
case SERIAL_DATA_7: bits = 7; break;
default: bits = 8; break;
case SERIAL_DATA_5:
bits = 5;
break;
case SERIAL_DATA_6:
bits = 6;
break;
case SERIAL_DATA_7:
bits = 7;
break;
default:
bits = 8;
break;
}
uart_set_format(_uart, bits, stop, parity);
_fcnTx = gpio_get_function(_tx);
_fcnRx = gpio_get_function(_rx);
gpio_set_function(_tx, GPIO_FUNC_UART);
gpio_set_function(_rx, GPIO_FUNC_UART);
if (_rts != UART_PIN_NOT_DEFINED) {
_fcnRts = gpio_get_function(_rts);
gpio_set_function(_rts, GPIO_FUNC_UART);
}
if (_cts != UART_PIN_NOT_DEFINED) {
_fcnCts = gpio_get_function(_cts);
gpio_set_function(_cts, GPIO_FUNC_UART);
}
uart_set_hw_flow(_uart, _rts != UART_PIN_NOT_DEFINED, _cts != UART_PIN_NOT_DEFINED);
_writer = 0;
_reader = 0;
if (!_polling) {
if (_uart == uart0) {
irq_set_exclusive_handler(UART0_IRQ, _uart0IRQ);
irq_set_enabled(UART0_IRQ, true);
} else {
irq_set_exclusive_handler(UART1_IRQ, _uart1IRQ);
irq_set_enabled(UART1_IRQ, true);
}
// Set the IRQ enables and FIFO level to minimum
uart_set_irq_enables(_uart, true, false);
} else {
// Polling mode has no IRQs used
}
_running = true;
_peek = -1;
}
void SerialUART::end() {
if (!_running) {
return;
}
uart_deinit(_uart);
_running = false;
if (!_polling) {
if (_uart == uart0) {
irq_set_enabled(UART0_IRQ, false);
} else {
irq_set_enabled(UART1_IRQ, false);
}
}
// Paranoia - ensure nobody else is using anything here at the same time
mutex_enter_blocking(&_mutex);
mutex_enter_blocking(&_fifoMutex);
uart_deinit(_uart);
delete[] _queue;
// Reset the mutexes once all is off/cleaned up
mutex_exit(&_fifoMutex);
mutex_exit(&_mutex);
// Restore pin functions
gpio_set_function(_tx, _fcnTx);
gpio_set_function(_rx, _fcnRx);
if (_rts != UART_PIN_NOT_DEFINED) {
gpio_set_function(_rts, _fcnRts);
}
if (_cts != UART_PIN_NOT_DEFINED) {
gpio_set_function(_cts, _fcnCts);
}
}
void SerialUART::_pumpFIFO() {
// Use the _fifoMutex to guard against the other core potentially
// running the IRQ (since we can't disable their IRQ handler).
// We guard against this core by disabling the IRQ handler and
// re-enabling if it was previously enabled at the end.
auto irqno = (_uart == uart0) ? UART0_IRQ : UART1_IRQ;
bool enabled = irq_is_enabled(irqno);
irq_set_enabled(irqno, false);
mutex_enter_blocking(&_fifoMutex);
_handleIRQ(false);
mutex_exit(&_fifoMutex);
irq_set_enabled(irqno, enabled);
}
int SerialUART::peek() {
@@ -112,15 +255,15 @@ int SerialUART::peek() {
if (!_running || !m) {
return -1;
}
if (_peek >= 0) {
return _peek;
}
if (uart_is_readable_within_us(_uart, _timeout * 1000)) {
_peek = uart_getc(_uart);
if (_polling) {
_handleIRQ(false);
} else {
_peek = -1; // Timeout
_pumpFIFO();
}
return _peek;
if (_writer != _reader) {
return _queue[_reader];
}
return -1;
}
int SerialUART::read() {
@@ -128,16 +271,30 @@ int SerialUART::read() {
if (!_running || !m) {
return -1;
}
if (_peek >= 0) {
int ret = _peek;
_peek = -1;
if (_polling) {
_handleIRQ(false);
} else {
_pumpFIFO();
}
if (_writer != _reader) {
auto ret = _queue[_reader];
asm volatile("" ::: "memory"); // Ensure the value is read before advancing
auto next_reader = (_reader + 1) % _fifoSize;
asm volatile("" ::: "memory"); // Ensure the reader value is only written once, correctly
_reader = next_reader;
return ret;
}
if (uart_is_readable_within_us(_uart, _timeout * 1000)) {
return uart_getc(_uart);
} else {
return -1; // Timeout
return -1;
}
bool SerialUART::overflow() {
CoreMutex m(&_mutex);
if (!_running || !m) {
return false;
}
bool hold = _overflow;
_overflow = false;
return hold;
}
int SerialUART::available() {
@@ -145,7 +302,12 @@ int SerialUART::available() {
if (!_running || !m) {
return 0;
}
return (uart_is_readable(_uart)) ? 1 : 0;
if (_polling) {
_handleIRQ(false);
} else {
_pumpFIFO();
}
return (_fifoSize + _writer - _reader) % _fifoSize;
}
int SerialUART::availableForWrite() {
@@ -153,6 +315,9 @@ int SerialUART::availableForWrite() {
if (!_running || !m) {
return 0;
}
if (_polling) {
_handleIRQ(false);
}
return (uart_is_writable(_uart)) ? 1 : 0;
}
@@ -161,6 +326,9 @@ void SerialUART::flush() {
if (!_running || !m) {
return;
}
if (_polling) {
_handleIRQ(false);
}
uart_tx_wait_blocking(_uart);
}
@@ -169,6 +337,9 @@ size_t SerialUART::write(uint8_t c) {
if (!_running || !m) {
return 0;
}
if (_polling) {
_handleIRQ(false);
}
uart_putc_raw(_uart, c);
return 1;
}
@@ -178,6 +349,9 @@ size_t SerialUART::write(const uint8_t *p, size_t len) {
if (!_running || !m) {
return 0;
}
if (_polling) {
_handleIRQ(false);
}
size_t cnt = len;
while (cnt) {
uart_putc_raw(_uart, *p);
@@ -191,9 +365,6 @@ SerialUART::operator bool() {
return _running;
}
SerialUART Serial1(uart0, PIN_SERIAL1_TX, PIN_SERIAL1_RX);
SerialUART Serial2(uart1, PIN_SERIAL2_TX, PIN_SERIAL2_RX);
void arduino::serialEvent1Run(void) {
if (serialEvent1 && Serial1.available()) {
serialEvent1();
@@ -205,3 +376,71 @@ void arduino::serialEvent2Run(void) {
serialEvent2();
}
}
// IRQ handler, called when FIFO > 1/8 full or when it had held unread data for >32 bit times
void __not_in_flash_func(SerialUART::_handleIRQ)(bool inIRQ) {
if (inIRQ) {
uint32_t owner;
if (!mutex_try_enter(&_fifoMutex, &owner)) {
// Main app on the other core has the mutex so it is
// in the process of pulling data out of the HW FIFO
return;
}
}
// ICR is write-to-clear
uart_get_hw(_uart)->icr = UART_UARTICR_RTIC_BITS | UART_UARTICR_RXIC_BITS;
while (uart_is_readable(_uart)) {
auto val = uart_getc(_uart);
auto next_writer = _writer + 1;
if (next_writer == _fifoSize) {
next_writer = 0;
}
if (next_writer != _reader) {
_queue[_writer] = val;
asm volatile("" ::: "memory"); // Ensure the queue is written before the written count advances
// Avoid using division or mod because the HW divider could be in use
_writer = next_writer;
} else {
_overflow = true;
}
}
if (inIRQ) {
mutex_exit(&_fifoMutex);
}
}
#ifndef __SERIAL1_DEVICE
#define __SERIAL1_DEVICE uart0
#endif
#ifndef __SERIAL2_DEVICE
#define __SERIAL2_DEVICE uart1
#endif
#if defined(PIN_SERIAL1_RTS)
SerialUART Serial1(__SERIAL1_DEVICE, PIN_SERIAL1_TX, PIN_SERIAL1_RX, PIN_SERIAL1_RTS, PIN_SERIAL1_CTS);
#else
SerialUART Serial1(__SERIAL1_DEVICE, PIN_SERIAL1_TX, PIN_SERIAL1_RX);
#endif
#if defined(PIN_SERIAL2_RTS)
SerialUART Serial2(__SERIAL2_DEVICE, PIN_SERIAL2_TX, PIN_SERIAL2_RX, PIN_SERIAL2_RTS, PIN_SERIAL2_CTS);
#else
SerialUART Serial2(__SERIAL2_DEVICE, PIN_SERIAL2_TX, PIN_SERIAL2_RX);
#endif
static void __not_in_flash_func(_uart0IRQ)() {
if (__SERIAL1_DEVICE == uart0) {
Serial1._handleIRQ();
} else {
Serial2._handleIRQ();
}
}
static void __not_in_flash_func(_uart1IRQ)() {
if (__SERIAL2_DEVICE == uart1) {
Serial2._handleIRQ();
} else {
Serial1._handleIRQ();
}
}
+23 -2
View File
@@ -23,22 +23,28 @@
#include <Arduino.h>
#include "api/HardwareSerial.h"
#include <stdarg.h>
#include <queue>
#include "CoreMutex.h"
extern "C" typedef struct uart_inst uart_inst_t;
#define UART_PIN_NOT_DEFINED (255u)
class SerialUART : public HardwareSerial {
public:
SerialUART(uart_inst_t *uart, pin_size_t tx, pin_size_t rx);
SerialUART(uart_inst_t *uart, pin_size_t tx, pin_size_t rx, pin_size_t rts = UART_PIN_NOT_DEFINED, pin_size_t cts = UART_PIN_NOT_DEFINED);
// Select the pinout. Call before .begin()
bool setRX(pin_size_t pin);
bool setTX(pin_size_t pin);
bool setRTS(pin_size_t pin);
bool setCTS(pin_size_t pin);
bool setPinout(pin_size_t tx, pin_size_t rx) {
bool ret = setRX(rx);
ret &= setTX(tx);
return ret;
}
bool setFIFOSize(size_t size);
bool setPollingMode(bool mode = true);
void begin(unsigned long baud = 115200) override {
begin(baud, SERIAL_8N1);
@@ -54,15 +60,30 @@ public:
virtual size_t write(uint8_t c) override;
virtual size_t write(const uint8_t *p, size_t len) override;
using Print::write;
bool overflow();
operator bool() override;
// Not to be called by users, only from the IRQ handler. In public so that the C-language IQR callback can access it
void _handleIRQ(bool inIRQ = true);
private:
bool _running = false;
uart_inst_t *_uart;
pin_size_t _tx, _rx;
pin_size_t _rts, _cts;
enum gpio_function _fcnTx, _fcnRx, _fcnRts, _fcnCts;
int _baud;
int _peek;
mutex_t _mutex;
bool _polling = false;
bool _overflow;
// Lockless, IRQ-handled circular queue
uint32_t _writer;
uint32_t _reader;
size_t _fifoSize = 32;
uint8_t *_queue;
mutex_t _fifoMutex; // Only needed when non-IRQ updates _writer
void _pumpFIFO(); // User space FIFO transfer
};
extern SerialUART Serial1; // HW UART 0
+18 -11
View File
@@ -64,52 +64,57 @@ void SerialUSB::end() {
}
int SerialUSB::peek() {
CoreMutex m(&__usb_mutex);
CoreMutex m(&__usb_mutex, false);
if (!_running || !m) {
return 0;
}
uint8_t c;
tud_task();
return tud_cdc_peek(&c) ? (int) c : -1;
}
int SerialUSB::read() {
CoreMutex m(&__usb_mutex);
CoreMutex m(&__usb_mutex, false);
if (!_running || !m) {
return -1;
}
if (tud_cdc_connected() && tud_cdc_available()) {
tud_task();
if (tud_cdc_available()) {
return tud_cdc_read_char();
}
return -1;
}
int SerialUSB::available() {
CoreMutex m(&__usb_mutex);
CoreMutex m(&__usb_mutex, false);
if (!_running || !m) {
return 0;
}
tud_task();
return tud_cdc_available();
}
int SerialUSB::availableForWrite() {
CoreMutex m(&__usb_mutex);
CoreMutex m(&__usb_mutex, false);
if (!_running || !m) {
return 0;
}
tud_task();
return tud_cdc_write_available();
}
void SerialUSB::flush() {
CoreMutex m(&__usb_mutex);
CoreMutex m(&__usb_mutex, false);
if (!_running || !m) {
return;
}
tud_cdc_write_flush();
tud_task();
}
size_t SerialUSB::write(uint8_t c) {
@@ -117,13 +122,13 @@ size_t SerialUSB::write(uint8_t c) {
}
size_t SerialUSB::write(const uint8_t *buf, size_t length) {
CoreMutex m(&__usb_mutex);
CoreMutex m(&__usb_mutex, false);
if (!_running || !m) {
return 0;
}
static uint64_t last_avail_time;
int i = 0;
int written = 0;
if (tud_cdc_connected()) {
for (size_t i = 0; i < length;) {
int n = length - i;
@@ -136,12 +141,13 @@ size_t SerialUSB::write(const uint8_t *buf, size_t length) {
tud_task();
tud_cdc_write_flush();
i += n2;
written += n2;
last_avail_time = time_us_64();
} else {
tud_task();
tud_cdc_write_flush();
if (!tud_cdc_connected() ||
(!tud_cdc_write_available() && time_us_64() > last_avail_time + 1000000 /* 1 second */)) {
(!tud_cdc_write_available() && time_us_64() > last_avail_time + 1'000'000 /* 1 second */)) {
break;
}
}
@@ -150,11 +156,12 @@ size_t SerialUSB::write(const uint8_t *buf, size_t length) {
// reset our timeout
last_avail_time = 0;
}
return i;
tud_task();
return written;
}
SerialUSB::operator bool() {
CoreMutex m(&__usb_mutex);
CoreMutex m(&__usb_mutex, false);
if (!_running || !m) {
return false;
}
+1 -4
View File
@@ -18,8 +18,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __SERIALUSB_H__
#define __SERIALUSB_H__
#pragma once
#include <Arduino.h>
#include "api/HardwareSerial.h"
@@ -54,5 +53,3 @@ extern SerialUSB Serial;
namespace arduino {
extern void serialEventRun(void) __attribute__((weak));
};
#endif
+59
View File
@@ -0,0 +1,59 @@
/*
SoftwareSerial wrapper for SerialPIO
Copyright (c) 2022 Earle F. Philhower, III <earlephilhower@yahoo.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "SerialPIO.h"
class SoftwareSerial : public SerialPIO {
public:
// Note the rx/tx pins are swapped in PIO vs SWSerial
SoftwareSerial(pin_size_t rx, pin_size_t tx, bool invert = false) : SerialPIO(tx, rx) {
_invert = invert;
}
~SoftwareSerial() {
if (_invert) {
gpio_set_outover(_tx, 0);
gpio_set_outover(_rx, 0);
}
}
virtual void begin(unsigned long baud = 115200) override {
begin(baud, SERIAL_8N1);
};
void begin(unsigned long baud, uint16_t config) override {
SerialPIO::begin(baud, config);
if (_invert) {
gpio_set_outover(_tx, GPIO_OVERRIDE_INVERT);
gpio_set_inover(_rx, GPIO_OVERRIDE_INVERT);
}
}
void listen() { /* noop */ }
bool isListening() {
return true;
}
private:
bool _invert;
};
+247
View File
@@ -0,0 +1,247 @@
/**
StreamString.h
Copyright (c) 2020 D. Gauchard. All rights reserved.
This file is part of the esp8266 core for Arduino environment.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __STREAMSTRING_H
#define __STREAMSTRING_H
#include <limits>
#include <algorithm>
#include "Stream.h"
#include "api/String.h"
///////////////////////////////////////////////////////////////
// S2Stream points to a String and makes it a Stream
// (it is also the helper for StreamString)
class S2Stream: public Stream {
public:
S2Stream(String& string, int peekPointer = -1) : string(&string), peekPointer(peekPointer) { }
S2Stream(String* string, int peekPointer = -1) : string(string), peekPointer(peekPointer) { }
virtual int available() override {
return string->length();
}
virtual int availableForWrite() override {
return std::numeric_limits<int16_t>::max();
}
virtual int read() override {
if (peekPointer < 0) {
// consume chars
if (string->length()) {
char c = string->charAt(0);
string->remove(0, 1);
return c;
}
} else if (peekPointer < (int)string->length()) {
// return pointed and move pointer
return string->charAt(peekPointer++);
}
// everything is read
return -1;
}
virtual size_t write(uint8_t data) override {
return string->concat((char)data);
}
// virtual int read(uint8_t* buffer, size_t len) override
// {
// if (peekPointer < 0)
// {
// // string will be consumed
// size_t l = std::min(len, (size_t)string->length());
// memcpy(buffer, string->c_str(), l);
// string->remove(0, l);
// return l;
// }
//
// if (peekPointer >= (int)string->length())
// {
// return 0;
// }
//
// // only the pointer is moved
// size_t l = std::min(len, (size_t)(string->length() - peekPointer));
// memcpy(buffer, string->c_str() + peekPointer, l);
// peekPointer += l;
// return l;
// }
virtual size_t write(const uint8_t* buffer, size_t len) override {
return string->concat((const char*)buffer, len) ? len : 0;
}
virtual int peek() override {
if (peekPointer < 0) {
if (string->length()) {
return string->charAt(0);
}
} else if (peekPointer < (int)string->length()) {
return string->charAt(peekPointer);
}
return -1;
}
virtual void flush() override {
// nothing to do
}
#if 0
virtual bool inputCanTimeout() override {
return false;
}
virtual bool outputCanTimeout() override {
return false;
}
//// Stream's peekBufferAPI
virtual bool hasPeekBufferAPI() const override {
return true;
}
virtual size_t peekAvailable() {
if (peekPointer < 0) {
return string->length();
}
return string->length() - peekPointer;
}
virtual const char* peekBuffer() override {
if (peekPointer < 0) {
return string->c_str();
}
if (peekPointer < (int)string->length()) {
return string->c_str() + peekPointer;
}
return nullptr;
}
virtual void peekConsume(size_t consume) override {
if (peekPointer < 0) {
// string is really consumed
string->remove(0, consume);
} else {
// only the pointer is moved
peekPointer = std::min((size_t)string->length(), peekPointer + consume);
}
}
virtual ssize_t streamRemaining() override {
return peekPointer < 0 ? string->length() : string->length() - peekPointer;
}
// calling setConsume() will consume bytes as the stream is read
// (enabled by default)
void setConsume() {
peekPointer = -1;
}
#endif
// Reading this stream will mark the string as read without consuming
// (not enabled by default)
// Calling resetPointer() resets the read state and allows rereading.
void resetPointer(int pointer = 0) {
peekPointer = pointer;
}
protected:
String* string;
int peekPointer; // -1:String is consumed / >=0:resettable pointer
};
// StreamString is a S2Stream holding the String
class StreamString: public String, public S2Stream {
protected:
void resetpp() {
if (peekPointer > 0) {
peekPointer = 0;
}
}
public:
StreamString(StreamString&& bro) : String(bro), S2Stream(this) { }
StreamString(const StreamString& bro) : String(bro), S2Stream(this) { }
// duplicate String constructors and operator=:
StreamString(const char* text = nullptr) : String(text), S2Stream(this) { }
StreamString(const String& string) : String(string), S2Stream(this) { }
StreamString(const __FlashStringHelper* str) : String(str), S2Stream(this) { }
StreamString(String&& string) : String(string), S2Stream(this) { }
explicit StreamString(char c) : String(c), S2Stream(this) { }
explicit StreamString(unsigned char c, unsigned char base = 10) :
String(c, base), S2Stream(this) {
}
explicit StreamString(int i, unsigned char base = 10) : String(i, base), S2Stream(this) { }
explicit StreamString(unsigned int i, unsigned char base = 10) : String(i, base), S2Stream(this) {
}
explicit StreamString(long l, unsigned char base = 10) : String(l, base), S2Stream(this) { }
explicit StreamString(unsigned long l, unsigned char base = 10) :
String(l, base), S2Stream(this) {
}
explicit StreamString(float f, unsigned char decimalPlaces = 2) :
String(f, decimalPlaces), S2Stream(this) {
}
explicit StreamString(double d, unsigned char decimalPlaces = 2) :
String(d, decimalPlaces), S2Stream(this) {
}
StreamString& operator=(const StreamString& rhs) {
String::operator=(rhs);
resetpp();
return *this;
}
StreamString& operator=(const String& rhs) {
String::operator=(rhs);
resetpp();
return *this;
}
StreamString& operator=(const char* cstr) {
String::operator=(cstr);
resetpp();
return *this;
}
StreamString& operator=(const __FlashStringHelper* str) {
String::operator=(str);
resetpp();
return *this;
}
StreamString& operator=(String&& rval) {
String::operator=(rval);
resetpp();
return *this;
}
};
#endif // __STREAMSTRING_H
+14 -4
View File
@@ -28,6 +28,7 @@ typedef struct {
pin_size_t pin;
PIO pio;
int sm;
int off;
alarm_id_t alarm;
} Tone;
@@ -38,10 +39,18 @@ auto_init_mutex(_toneMutex);
static PIOProgram _tone2Pgm(&tone2_program);
static std::map<pin_size_t, Tone *> _toneMap;
static inline bool pio_sm_get_enabled(PIO pio, uint sm) {
check_pio_param(pio);
check_sm_param(sm);
return (pio->ctrl & ~(1u << sm)) & (1 << sm);
}
int64_t _stopTonePIO(alarm_id_t id, void *user_data) {
(void) id;
Tone *tone = (Tone *)user_data;
tone->alarm = 0;
digitalWrite(tone->pin, LOW);
pinMode(tone->pin, OUTPUT);
pio_sm_set_enabled(tone->pio, tone->sm, false);
return 0;
}
@@ -62,7 +71,7 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) {
return; // Weird deadlock case
}
int us = 1000000 / frequency / 2;
int us = 1'000'000 / frequency / 2;
if (us < 5) {
us = 5;
}
@@ -72,14 +81,12 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) {
newTone = new Tone();
newTone->pin = pin;
pinMode(pin, OUTPUT);
int off;
if (!_tone2Pgm.prepare(&newTone->pio, &newTone->sm, &off)) {
if (!_tone2Pgm.prepare(&newTone->pio, &newTone->sm, &newTone->off)) {
DEBUGCORE("ERROR: tone unable to start, out of PIO resources\n");
// ERROR, no free slots
delete newTone;
return;
}
tone2_program_init(newTone->pio, newTone->sm, off, pin);
newTone->alarm = 0;
} else {
newTone = entry->second;
@@ -88,6 +95,9 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) {
newTone->alarm = 0;
}
}
if (!pio_sm_get_enabled(newTone->pio, newTone->sm)) {
tone2_program_init(newTone->pio, newTone->sm, newTone->off, pin);
}
pio_sm_clear_fifos(newTone->pio, newTone->sm); // Remove any old updates that haven't yet taken effect
pio_sm_put_blocking(newTone->pio, newTone->sm, RP2040::usToPIOCycles(us));
pio_sm_set_enabled(newTone->pio, newTone->sm, true);
+56
View File
@@ -0,0 +1,56 @@
/*
_freertos.cpp - Internal core definitions for FreeRTOS
Copyright (c) 2022 Earle F. Philhower, III <earlephilhower@yahoo.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "_freertos.h"
#include "pico/mutex.h"
#include <stdlib.h>
typedef struct {
mutex_t *src;
SemaphoreHandle_t dst;
} FMMap;
static FMMap *_map = nullptr;
extern "C" SemaphoreHandle_t __get_freertos_mutex_for_ptr(mutex_t *m) {
if (!_map) {
_map = (FMMap *)calloc(sizeof(FMMap), 16);
}
// Pre-existing map
for (int i = 0; i < 16; i++) {
if (m == _map[i].src) {
return _map[i].dst;
}
}
for (int i = 0; i < 16; i++) {
if (_map[i].src == nullptr) {
// Make a new mutex
SemaphoreHandle_t fm = __freertos_mutex_create();
if (fm == nullptr) {
return nullptr;
}
_map[i].src = m;
_map[i].dst = fm;
return fm;
}
}
return nullptr; // Need to make space for more mutex maps!
}
+66
View File
@@ -0,0 +1,66 @@
/*
_freertos.h - Internal core definitions for FreeRTOS
Copyright (c) 2022 Earle F. Philhower, III <earlephilhower@yahoo.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "pico/mutex.h"
// Cannot include refs to FreeRTOS's actual semaphore calls because they
// are implemented as macros, so we have a wrapper in our variant hook
// to handle it.
extern bool __isFreeRTOS;
// FreeRTOS has been set up
extern volatile bool __freeRTOSinitted;
extern "C" {
#ifndef INC_FREERTOS_H
struct QueueDefinition; /* Using old naming convention so as not to break kernel aware debuggers. */
typedef struct QueueDefinition * QueueHandle_t;
typedef QueueHandle_t SemaphoreHandle_t;
#endif
extern SemaphoreHandle_t __freertos_mutex_create() __attribute__((weak));
extern SemaphoreHandle_t _freertos_recursive_mutex_create() __attribute__((weak));
extern void __freertos_mutex_take(SemaphoreHandle_t mtx) __attribute__((weak));
extern void __freertos_mutex_take_from_isr(SemaphoreHandle_t mtx) __attribute__((weak));
extern int __freertos_mutex_try_take(SemaphoreHandle_t mtx) __attribute__((weak));
extern void __freertos_mutex_give(SemaphoreHandle_t mtx) __attribute__((weak));
extern void __freertos_mutex_give_from_isr(SemaphoreHandle_t mtx) __attribute__((weak));
extern void __freertos_recursive_mutex_take(SemaphoreHandle_t mtx) __attribute__((weak));
extern int __freertos_recursive_mutex_try_take(SemaphoreHandle_t mtx) __attribute__((weak));
extern void __freertos_recursive_mutex_give(SemaphoreHandle_t mtx) __attribute__((weak));
#ifndef INC_FREERTOS_H
extern void vTaskSuspendAll() __attribute__((weak));
extern int32_t xTaskResumeAll() __attribute__((weak));
typedef struct tskTaskControlBlock * TaskHandle_t;
extern void vTaskPreemptionDisable(TaskHandle_t p) __attribute__((weak));
extern void vTaskPreemptionEnable(TaskHandle_t p) __attribute__((weak));
#endif
extern SemaphoreHandle_t __get_freertos_mutex_for_ptr(mutex_t *m);
}
// Halt the FreeRTOS PendSV task switching magic
extern "C" int __holdUpPendSV;
+2 -57
View File
@@ -1,57 +1,2 @@
/*
Arduino API main include
Copyright (c) 2016 Arduino LLC. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef ARDUINO_API_H
#define ARDUINO_API_H
// version 1.2.0
#define ARDUINO_API_VERSION 10200
#include "Binary.h"
#ifdef __cplusplus
#include "Interrupts.h"
#include "IPAddress.h"
#include "Print.h"
#include "Printable.h"
#include "PluggableUSB.h"
#include "Server.h"
#include "String.h"
#include "Stream.h"
#include "Udp.h"
#include "USBAPI.h"
#include "WCharacter.h"
#endif
/* Standard C library includes */
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <math.h>
// Misc Arduino core functions
#include "Common.h"
#ifdef __cplusplus
// Compatibility layer for older code
#include "Compat.h"
#endif
#endif
#pragma once
#include "../../../ArduinoCore-API/api/ArduinoAPI.h"
+2 -552
View File
@@ -1,552 +1,2 @@
/*
binary.h - Definitions for binary constants
Deprecated -- use 0b binary literals instead
Copyright (c) 2006 David A. Mellis. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef Binary_h
#define Binary_h
/* If supported, 0b binary literals are preferable to these constants.
* In that case, warn the user about these being deprecated (if possible). */
#if __cplusplus >= 201402L
/* C++14 introduces binary literals; C++11 introduces [[deprecated()]] */
#define DEPRECATED(x) [[deprecated("use " #x " instead")]]
#elif __GNUC__ >= 6
/* GCC 4.3 supports binary literals; GCC 6 supports __deprecated__ on enums*/
#define DEPRECATED(x) __attribute__ ((__deprecated__ ("use " #x " instead")))
#else
/* binary literals not supported, or "deprecated" warning not displayable */
#define DEPRECATED(x)
#endif
enum {
B0 DEPRECATED(0b0 ) = 0,
B00 DEPRECATED(0b00 ) = 0,
B000 DEPRECATED(0b000 ) = 0,
B0000 DEPRECATED(0b0000 ) = 0,
B00000 DEPRECATED(0b00000 ) = 0,
B000000 DEPRECATED(0b000000 ) = 0,
B0000000 DEPRECATED(0b0000000 ) = 0,
B00000000 DEPRECATED(0b00000000) = 0,
B1 DEPRECATED(0b1 ) = 1,
B01 DEPRECATED(0b01 ) = 1,
B001 DEPRECATED(0b001 ) = 1,
B0001 DEPRECATED(0b0001 ) = 1,
B00001 DEPRECATED(0b00001 ) = 1,
B000001 DEPRECATED(0b000001 ) = 1,
B0000001 DEPRECATED(0b0000001 ) = 1,
B00000001 DEPRECATED(0b00000001) = 1,
B10 DEPRECATED(0b10 ) = 2,
B010 DEPRECATED(0b010 ) = 2,
B0010 DEPRECATED(0b0010 ) = 2,
B00010 DEPRECATED(0b00010 ) = 2,
B000010 DEPRECATED(0b000010 ) = 2,
B0000010 DEPRECATED(0b0000010 ) = 2,
B00000010 DEPRECATED(0b00000010) = 2,
B11 DEPRECATED(0b11 ) = 3,
B011 DEPRECATED(0b011 ) = 3,
B0011 DEPRECATED(0b0011 ) = 3,
B00011 DEPRECATED(0b00011 ) = 3,
B000011 DEPRECATED(0b000011 ) = 3,
B0000011 DEPRECATED(0b0000011 ) = 3,
B00000011 DEPRECATED(0b00000011) = 3,
B100 DEPRECATED(0b100 ) = 4,
B0100 DEPRECATED(0b0100 ) = 4,
B00100 DEPRECATED(0b00100 ) = 4,
B000100 DEPRECATED(0b000100 ) = 4,
B0000100 DEPRECATED(0b0000100 ) = 4,
B00000100 DEPRECATED(0b00000100) = 4,
B101 DEPRECATED(0b101 ) = 5,
B0101 DEPRECATED(0b0101 ) = 5,
B00101 DEPRECATED(0b00101 ) = 5,
B000101 DEPRECATED(0b000101 ) = 5,
B0000101 DEPRECATED(0b0000101 ) = 5,
B00000101 DEPRECATED(0b00000101) = 5,
B110 DEPRECATED(0b110 ) = 6,
B0110 DEPRECATED(0b0110 ) = 6,
B00110 DEPRECATED(0b00110 ) = 6,
B000110 DEPRECATED(0b000110 ) = 6,
B0000110 DEPRECATED(0b0000110 ) = 6,
B00000110 DEPRECATED(0b00000110) = 6,
B111 DEPRECATED(0b111 ) = 7,
B0111 DEPRECATED(0b0111 ) = 7,
B00111 DEPRECATED(0b00111 ) = 7,
B000111 DEPRECATED(0b000111 ) = 7,
B0000111 DEPRECATED(0b0000111 ) = 7,
B00000111 DEPRECATED(0b00000111) = 7,
B1000 DEPRECATED(0b1000 ) = 8,
B01000 DEPRECATED(0b01000 ) = 8,
B001000 DEPRECATED(0b001000 ) = 8,
B0001000 DEPRECATED(0b0001000 ) = 8,
B00001000 DEPRECATED(0b00001000) = 8,
B1001 DEPRECATED(0b1001 ) = 9,
B01001 DEPRECATED(0b01001 ) = 9,
B001001 DEPRECATED(0b001001 ) = 9,
B0001001 DEPRECATED(0b0001001 ) = 9,
B00001001 DEPRECATED(0b00001001) = 9,
B1010 DEPRECATED(0b1010 ) = 10,
B01010 DEPRECATED(0b01010 ) = 10,
B001010 DEPRECATED(0b001010 ) = 10,
B0001010 DEPRECATED(0b0001010 ) = 10,
B00001010 DEPRECATED(0b00001010) = 10,
B1011 DEPRECATED(0b1011 ) = 11,
B01011 DEPRECATED(0b01011 ) = 11,
B001011 DEPRECATED(0b001011 ) = 11,
B0001011 DEPRECATED(0b0001011 ) = 11,
B00001011 DEPRECATED(0b00001011) = 11,
B1100 DEPRECATED(0b1100 ) = 12,
B01100 DEPRECATED(0b01100 ) = 12,
B001100 DEPRECATED(0b001100 ) = 12,
B0001100 DEPRECATED(0b0001100 ) = 12,
B00001100 DEPRECATED(0b00001100) = 12,
B1101 DEPRECATED(0b1101 ) = 13,
B01101 DEPRECATED(0b01101 ) = 13,
B001101 DEPRECATED(0b001101 ) = 13,
B0001101 DEPRECATED(0b0001101 ) = 13,
B00001101 DEPRECATED(0b00001101) = 13,
B1110 DEPRECATED(0b1110 ) = 14,
B01110 DEPRECATED(0b01110 ) = 14,
B001110 DEPRECATED(0b001110 ) = 14,
B0001110 DEPRECATED(0b0001110 ) = 14,
B00001110 DEPRECATED(0b00001110) = 14,
B1111 DEPRECATED(0b1111 ) = 15,
B01111 DEPRECATED(0b01111 ) = 15,
B001111 DEPRECATED(0b001111 ) = 15,
B0001111 DEPRECATED(0b0001111 ) = 15,
B00001111 DEPRECATED(0b00001111) = 15,
B10000 DEPRECATED(0b10000 ) = 16,
B010000 DEPRECATED(0b010000 ) = 16,
B0010000 DEPRECATED(0b0010000 ) = 16,
B00010000 DEPRECATED(0b00010000) = 16,
B10001 DEPRECATED(0b10001 ) = 17,
B010001 DEPRECATED(0b010001 ) = 17,
B0010001 DEPRECATED(0b0010001 ) = 17,
B00010001 DEPRECATED(0b00010001) = 17,
B10010 DEPRECATED(0b10010 ) = 18,
B010010 DEPRECATED(0b010010 ) = 18,
B0010010 DEPRECATED(0b0010010 ) = 18,
B00010010 DEPRECATED(0b00010010) = 18,
B10011 DEPRECATED(0b10011 ) = 19,
B010011 DEPRECATED(0b010011 ) = 19,
B0010011 DEPRECATED(0b0010011 ) = 19,
B00010011 DEPRECATED(0b00010011) = 19,
B10100 DEPRECATED(0b10100 ) = 20,
B010100 DEPRECATED(0b010100 ) = 20,
B0010100 DEPRECATED(0b0010100 ) = 20,
B00010100 DEPRECATED(0b00010100) = 20,
B10101 DEPRECATED(0b10101 ) = 21,
B010101 DEPRECATED(0b010101 ) = 21,
B0010101 DEPRECATED(0b0010101 ) = 21,
B00010101 DEPRECATED(0b00010101) = 21,
B10110 DEPRECATED(0b10110 ) = 22,
B010110 DEPRECATED(0b010110 ) = 22,
B0010110 DEPRECATED(0b0010110 ) = 22,
B00010110 DEPRECATED(0b00010110) = 22,
B10111 DEPRECATED(0b10111 ) = 23,
B010111 DEPRECATED(0b010111 ) = 23,
B0010111 DEPRECATED(0b0010111 ) = 23,
B00010111 DEPRECATED(0b00010111) = 23,
B11000 DEPRECATED(0b11000 ) = 24,
B011000 DEPRECATED(0b011000 ) = 24,
B0011000 DEPRECATED(0b0011000 ) = 24,
B00011000 DEPRECATED(0b00011000) = 24,
B11001 DEPRECATED(0b11001 ) = 25,
B011001 DEPRECATED(0b011001 ) = 25,
B0011001 DEPRECATED(0b0011001 ) = 25,
B00011001 DEPRECATED(0b00011001) = 25,
B11010 DEPRECATED(0b11010 ) = 26,
B011010 DEPRECATED(0b011010 ) = 26,
B0011010 DEPRECATED(0b0011010 ) = 26,
B00011010 DEPRECATED(0b00011010) = 26,
B11011 DEPRECATED(0b11011 ) = 27,
B011011 DEPRECATED(0b011011 ) = 27,
B0011011 DEPRECATED(0b0011011 ) = 27,
B00011011 DEPRECATED(0b00011011) = 27,
B11100 DEPRECATED(0b11100 ) = 28,
B011100 DEPRECATED(0b011100 ) = 28,
B0011100 DEPRECATED(0b0011100 ) = 28,
B00011100 DEPRECATED(0b00011100) = 28,
B11101 DEPRECATED(0b11101 ) = 29,
B011101 DEPRECATED(0b011101 ) = 29,
B0011101 DEPRECATED(0b0011101 ) = 29,
B00011101 DEPRECATED(0b00011101) = 29,
B11110 DEPRECATED(0b11110 ) = 30,
B011110 DEPRECATED(0b011110 ) = 30,
B0011110 DEPRECATED(0b0011110 ) = 30,
B00011110 DEPRECATED(0b00011110) = 30,
B11111 DEPRECATED(0b11111 ) = 31,
B011111 DEPRECATED(0b011111 ) = 31,
B0011111 DEPRECATED(0b0011111 ) = 31,
B00011111 DEPRECATED(0b00011111) = 31,
B100000 DEPRECATED(0b100000 ) = 32,
B0100000 DEPRECATED(0b0100000 ) = 32,
B00100000 DEPRECATED(0b00100000) = 32,
B100001 DEPRECATED(0b100001 ) = 33,
B0100001 DEPRECATED(0b0100001 ) = 33,
B00100001 DEPRECATED(0b00100001) = 33,
B100010 DEPRECATED(0b100010 ) = 34,
B0100010 DEPRECATED(0b0100010 ) = 34,
B00100010 DEPRECATED(0b00100010) = 34,
B100011 DEPRECATED(0b100011 ) = 35,
B0100011 DEPRECATED(0b0100011 ) = 35,
B00100011 DEPRECATED(0b00100011) = 35,
B100100 DEPRECATED(0b100100 ) = 36,
B0100100 DEPRECATED(0b0100100 ) = 36,
B00100100 DEPRECATED(0b00100100) = 36,
B100101 DEPRECATED(0b100101 ) = 37,
B0100101 DEPRECATED(0b0100101 ) = 37,
B00100101 DEPRECATED(0b00100101) = 37,
B100110 DEPRECATED(0b100110 ) = 38,
B0100110 DEPRECATED(0b0100110 ) = 38,
B00100110 DEPRECATED(0b00100110) = 38,
B100111 DEPRECATED(0b100111 ) = 39,
B0100111 DEPRECATED(0b0100111 ) = 39,
B00100111 DEPRECATED(0b00100111) = 39,
B101000 DEPRECATED(0b101000 ) = 40,
B0101000 DEPRECATED(0b0101000 ) = 40,
B00101000 DEPRECATED(0b00101000) = 40,
B101001 DEPRECATED(0b101001 ) = 41,
B0101001 DEPRECATED(0b0101001 ) = 41,
B00101001 DEPRECATED(0b00101001) = 41,
B101010 DEPRECATED(0b101010 ) = 42,
B0101010 DEPRECATED(0b0101010 ) = 42,
B00101010 DEPRECATED(0b00101010) = 42,
B101011 DEPRECATED(0b101011 ) = 43,
B0101011 DEPRECATED(0b0101011 ) = 43,
B00101011 DEPRECATED(0b00101011) = 43,
B101100 DEPRECATED(0b101100 ) = 44,
B0101100 DEPRECATED(0b0101100 ) = 44,
B00101100 DEPRECATED(0b00101100) = 44,
B101101 DEPRECATED(0b101101 ) = 45,
B0101101 DEPRECATED(0b0101101 ) = 45,
B00101101 DEPRECATED(0b00101101) = 45,
B101110 DEPRECATED(0b101110 ) = 46,
B0101110 DEPRECATED(0b0101110 ) = 46,
B00101110 DEPRECATED(0b00101110) = 46,
B101111 DEPRECATED(0b101111 ) = 47,
B0101111 DEPRECATED(0b0101111 ) = 47,
B00101111 DEPRECATED(0b00101111) = 47,
B110000 DEPRECATED(0b110000 ) = 48,
B0110000 DEPRECATED(0b0110000 ) = 48,
B00110000 DEPRECATED(0b00110000) = 48,
B110001 DEPRECATED(0b110001 ) = 49,
B0110001 DEPRECATED(0b0110001 ) = 49,
B00110001 DEPRECATED(0b00110001) = 49,
B110010 DEPRECATED(0b110010 ) = 50,
B0110010 DEPRECATED(0b0110010 ) = 50,
B00110010 DEPRECATED(0b00110010) = 50,
B110011 DEPRECATED(0b110011 ) = 51,
B0110011 DEPRECATED(0b0110011 ) = 51,
B00110011 DEPRECATED(0b00110011) = 51,
B110100 DEPRECATED(0b110100 ) = 52,
B0110100 DEPRECATED(0b0110100 ) = 52,
B00110100 DEPRECATED(0b00110100) = 52,
B110101 DEPRECATED(0b110101 ) = 53,
B0110101 DEPRECATED(0b0110101 ) = 53,
B00110101 DEPRECATED(0b00110101) = 53,
B110110 DEPRECATED(0b110110 ) = 54,
B0110110 DEPRECATED(0b0110110 ) = 54,
B00110110 DEPRECATED(0b00110110) = 54,
B110111 DEPRECATED(0b110111 ) = 55,
B0110111 DEPRECATED(0b0110111 ) = 55,
B00110111 DEPRECATED(0b00110111) = 55,
B111000 DEPRECATED(0b111000 ) = 56,
B0111000 DEPRECATED(0b0111000 ) = 56,
B00111000 DEPRECATED(0b00111000) = 56,
B111001 DEPRECATED(0b111001 ) = 57,
B0111001 DEPRECATED(0b0111001 ) = 57,
B00111001 DEPRECATED(0b00111001) = 57,
B111010 DEPRECATED(0b111010 ) = 58,
B0111010 DEPRECATED(0b0111010 ) = 58,
B00111010 DEPRECATED(0b00111010) = 58,
B111011 DEPRECATED(0b111011 ) = 59,
B0111011 DEPRECATED(0b0111011 ) = 59,
B00111011 DEPRECATED(0b00111011) = 59,
B111100 DEPRECATED(0b111100 ) = 60,
B0111100 DEPRECATED(0b0111100 ) = 60,
B00111100 DEPRECATED(0b00111100) = 60,
B111101 DEPRECATED(0b111101 ) = 61,
B0111101 DEPRECATED(0b0111101 ) = 61,
B00111101 DEPRECATED(0b00111101) = 61,
B111110 DEPRECATED(0b111110 ) = 62,
B0111110 DEPRECATED(0b0111110 ) = 62,
B00111110 DEPRECATED(0b00111110) = 62,
B111111 DEPRECATED(0b111111 ) = 63,
B0111111 DEPRECATED(0b0111111 ) = 63,
B00111111 DEPRECATED(0b00111111) = 63,
B1000000 DEPRECATED(0b1000000 ) = 64,
B01000000 DEPRECATED(0b01000000) = 64,
B1000001 DEPRECATED(0b1000001 ) = 65,
B01000001 DEPRECATED(0b01000001) = 65,
B1000010 DEPRECATED(0b1000010 ) = 66,
B01000010 DEPRECATED(0b01000010) = 66,
B1000011 DEPRECATED(0b1000011 ) = 67,
B01000011 DEPRECATED(0b01000011) = 67,
B1000100 DEPRECATED(0b1000100 ) = 68,
B01000100 DEPRECATED(0b01000100) = 68,
B1000101 DEPRECATED(0b1000101 ) = 69,
B01000101 DEPRECATED(0b01000101) = 69,
B1000110 DEPRECATED(0b1000110 ) = 70,
B01000110 DEPRECATED(0b01000110) = 70,
B1000111 DEPRECATED(0b1000111 ) = 71,
B01000111 DEPRECATED(0b01000111) = 71,
B1001000 DEPRECATED(0b1001000 ) = 72,
B01001000 DEPRECATED(0b01001000) = 72,
B1001001 DEPRECATED(0b1001001 ) = 73,
B01001001 DEPRECATED(0b01001001) = 73,
B1001010 DEPRECATED(0b1001010 ) = 74,
B01001010 DEPRECATED(0b01001010) = 74,
B1001011 DEPRECATED(0b1001011 ) = 75,
B01001011 DEPRECATED(0b01001011) = 75,
B1001100 DEPRECATED(0b1001100 ) = 76,
B01001100 DEPRECATED(0b01001100) = 76,
B1001101 DEPRECATED(0b1001101 ) = 77,
B01001101 DEPRECATED(0b01001101) = 77,
B1001110 DEPRECATED(0b1001110 ) = 78,
B01001110 DEPRECATED(0b01001110) = 78,
B1001111 DEPRECATED(0b1001111 ) = 79,
B01001111 DEPRECATED(0b01001111) = 79,
B1010000 DEPRECATED(0b1010000 ) = 80,
B01010000 DEPRECATED(0b01010000) = 80,
B1010001 DEPRECATED(0b1010001 ) = 81,
B01010001 DEPRECATED(0b01010001) = 81,
B1010010 DEPRECATED(0b1010010 ) = 82,
B01010010 DEPRECATED(0b01010010) = 82,
B1010011 DEPRECATED(0b1010011 ) = 83,
B01010011 DEPRECATED(0b01010011) = 83,
B1010100 DEPRECATED(0b1010100 ) = 84,
B01010100 DEPRECATED(0b01010100) = 84,
B1010101 DEPRECATED(0b1010101 ) = 85,
B01010101 DEPRECATED(0b01010101) = 85,
B1010110 DEPRECATED(0b1010110 ) = 86,
B01010110 DEPRECATED(0b01010110) = 86,
B1010111 DEPRECATED(0b1010111 ) = 87,
B01010111 DEPRECATED(0b01010111) = 87,
B1011000 DEPRECATED(0b1011000 ) = 88,
B01011000 DEPRECATED(0b01011000) = 88,
B1011001 DEPRECATED(0b1011001 ) = 89,
B01011001 DEPRECATED(0b01011001) = 89,
B1011010 DEPRECATED(0b1011010 ) = 90,
B01011010 DEPRECATED(0b01011010) = 90,
B1011011 DEPRECATED(0b1011011 ) = 91,
B01011011 DEPRECATED(0b01011011) = 91,
B1011100 DEPRECATED(0b1011100 ) = 92,
B01011100 DEPRECATED(0b01011100) = 92,
B1011101 DEPRECATED(0b1011101 ) = 93,
B01011101 DEPRECATED(0b01011101) = 93,
B1011110 DEPRECATED(0b1011110 ) = 94,
B01011110 DEPRECATED(0b01011110) = 94,
B1011111 DEPRECATED(0b1011111 ) = 95,
B01011111 DEPRECATED(0b01011111) = 95,
B1100000 DEPRECATED(0b1100000 ) = 96,
B01100000 DEPRECATED(0b01100000) = 96,
B1100001 DEPRECATED(0b1100001 ) = 97,
B01100001 DEPRECATED(0b01100001) = 97,
B1100010 DEPRECATED(0b1100010 ) = 98,
B01100010 DEPRECATED(0b01100010) = 98,
B1100011 DEPRECATED(0b1100011 ) = 99,
B01100011 DEPRECATED(0b01100011) = 99,
B1100100 DEPRECATED(0b1100100 ) = 100,
B01100100 DEPRECATED(0b01100100) = 100,
B1100101 DEPRECATED(0b1100101 ) = 101,
B01100101 DEPRECATED(0b01100101) = 101,
B1100110 DEPRECATED(0b1100110 ) = 102,
B01100110 DEPRECATED(0b01100110) = 102,
B1100111 DEPRECATED(0b1100111 ) = 103,
B01100111 DEPRECATED(0b01100111) = 103,
B1101000 DEPRECATED(0b1101000 ) = 104,
B01101000 DEPRECATED(0b01101000) = 104,
B1101001 DEPRECATED(0b1101001 ) = 105,
B01101001 DEPRECATED(0b01101001) = 105,
B1101010 DEPRECATED(0b1101010 ) = 106,
B01101010 DEPRECATED(0b01101010) = 106,
B1101011 DEPRECATED(0b1101011 ) = 107,
B01101011 DEPRECATED(0b01101011) = 107,
B1101100 DEPRECATED(0b1101100 ) = 108,
B01101100 DEPRECATED(0b01101100) = 108,
B1101101 DEPRECATED(0b1101101 ) = 109,
B01101101 DEPRECATED(0b01101101) = 109,
B1101110 DEPRECATED(0b1101110 ) = 110,
B01101110 DEPRECATED(0b01101110) = 110,
B1101111 DEPRECATED(0b1101111 ) = 111,
B01101111 DEPRECATED(0b01101111) = 111,
B1110000 DEPRECATED(0b1110000 ) = 112,
B01110000 DEPRECATED(0b01110000) = 112,
B1110001 DEPRECATED(0b1110001 ) = 113,
B01110001 DEPRECATED(0b01110001) = 113,
B1110010 DEPRECATED(0b1110010 ) = 114,
B01110010 DEPRECATED(0b01110010) = 114,
B1110011 DEPRECATED(0b1110011 ) = 115,
B01110011 DEPRECATED(0b01110011) = 115,
B1110100 DEPRECATED(0b1110100 ) = 116,
B01110100 DEPRECATED(0b01110100) = 116,
B1110101 DEPRECATED(0b1110101 ) = 117,
B01110101 DEPRECATED(0b01110101) = 117,
B1110110 DEPRECATED(0b1110110 ) = 118,
B01110110 DEPRECATED(0b01110110) = 118,
B1110111 DEPRECATED(0b1110111 ) = 119,
B01110111 DEPRECATED(0b01110111) = 119,
B1111000 DEPRECATED(0b1111000 ) = 120,
B01111000 DEPRECATED(0b01111000) = 120,
B1111001 DEPRECATED(0b1111001 ) = 121,
B01111001 DEPRECATED(0b01111001) = 121,
B1111010 DEPRECATED(0b1111010 ) = 122,
B01111010 DEPRECATED(0b01111010) = 122,
B1111011 DEPRECATED(0b1111011 ) = 123,
B01111011 DEPRECATED(0b01111011) = 123,
B1111100 DEPRECATED(0b1111100 ) = 124,
B01111100 DEPRECATED(0b01111100) = 124,
B1111101 DEPRECATED(0b1111101 ) = 125,
B01111101 DEPRECATED(0b01111101) = 125,
B1111110 DEPRECATED(0b1111110 ) = 126,
B01111110 DEPRECATED(0b01111110) = 126,
B1111111 DEPRECATED(0b1111111 ) = 127,
B01111111 DEPRECATED(0b01111111) = 127,
B10000000 DEPRECATED(0b10000000) = 128,
B10000001 DEPRECATED(0b10000001) = 129,
B10000010 DEPRECATED(0b10000010) = 130,
B10000011 DEPRECATED(0b10000011) = 131,
B10000100 DEPRECATED(0b10000100) = 132,
B10000101 DEPRECATED(0b10000101) = 133,
B10000110 DEPRECATED(0b10000110) = 134,
B10000111 DEPRECATED(0b10000111) = 135,
B10001000 DEPRECATED(0b10001000) = 136,
B10001001 DEPRECATED(0b10001001) = 137,
B10001010 DEPRECATED(0b10001010) = 138,
B10001011 DEPRECATED(0b10001011) = 139,
B10001100 DEPRECATED(0b10001100) = 140,
B10001101 DEPRECATED(0b10001101) = 141,
B10001110 DEPRECATED(0b10001110) = 142,
B10001111 DEPRECATED(0b10001111) = 143,
B10010000 DEPRECATED(0b10010000) = 144,
B10010001 DEPRECATED(0b10010001) = 145,
B10010010 DEPRECATED(0b10010010) = 146,
B10010011 DEPRECATED(0b10010011) = 147,
B10010100 DEPRECATED(0b10010100) = 148,
B10010101 DEPRECATED(0b10010101) = 149,
B10010110 DEPRECATED(0b10010110) = 150,
B10010111 DEPRECATED(0b10010111) = 151,
B10011000 DEPRECATED(0b10011000) = 152,
B10011001 DEPRECATED(0b10011001) = 153,
B10011010 DEPRECATED(0b10011010) = 154,
B10011011 DEPRECATED(0b10011011) = 155,
B10011100 DEPRECATED(0b10011100) = 156,
B10011101 DEPRECATED(0b10011101) = 157,
B10011110 DEPRECATED(0b10011110) = 158,
B10011111 DEPRECATED(0b10011111) = 159,
B10100000 DEPRECATED(0b10100000) = 160,
B10100001 DEPRECATED(0b10100001) = 161,
B10100010 DEPRECATED(0b10100010) = 162,
B10100011 DEPRECATED(0b10100011) = 163,
B10100100 DEPRECATED(0b10100100) = 164,
B10100101 DEPRECATED(0b10100101) = 165,
B10100110 DEPRECATED(0b10100110) = 166,
B10100111 DEPRECATED(0b10100111) = 167,
B10101000 DEPRECATED(0b10101000) = 168,
B10101001 DEPRECATED(0b10101001) = 169,
B10101010 DEPRECATED(0b10101010) = 170,
B10101011 DEPRECATED(0b10101011) = 171,
B10101100 DEPRECATED(0b10101100) = 172,
B10101101 DEPRECATED(0b10101101) = 173,
B10101110 DEPRECATED(0b10101110) = 174,
B10101111 DEPRECATED(0b10101111) = 175,
B10110000 DEPRECATED(0b10110000) = 176,
B10110001 DEPRECATED(0b10110001) = 177,
B10110010 DEPRECATED(0b10110010) = 178,
B10110011 DEPRECATED(0b10110011) = 179,
B10110100 DEPRECATED(0b10110100) = 180,
B10110101 DEPRECATED(0b10110101) = 181,
B10110110 DEPRECATED(0b10110110) = 182,
B10110111 DEPRECATED(0b10110111) = 183,
B10111000 DEPRECATED(0b10111000) = 184,
B10111001 DEPRECATED(0b10111001) = 185,
B10111010 DEPRECATED(0b10111010) = 186,
B10111011 DEPRECATED(0b10111011) = 187,
B10111100 DEPRECATED(0b10111100) = 188,
B10111101 DEPRECATED(0b10111101) = 189,
B10111110 DEPRECATED(0b10111110) = 190,
B10111111 DEPRECATED(0b10111111) = 191,
B11000000 DEPRECATED(0b11000000) = 192,
B11000001 DEPRECATED(0b11000001) = 193,
B11000010 DEPRECATED(0b11000010) = 194,
B11000011 DEPRECATED(0b11000011) = 195,
B11000100 DEPRECATED(0b11000100) = 196,
B11000101 DEPRECATED(0b11000101) = 197,
B11000110 DEPRECATED(0b11000110) = 198,
B11000111 DEPRECATED(0b11000111) = 199,
B11001000 DEPRECATED(0b11001000) = 200,
B11001001 DEPRECATED(0b11001001) = 201,
B11001010 DEPRECATED(0b11001010) = 202,
B11001011 DEPRECATED(0b11001011) = 203,
B11001100 DEPRECATED(0b11001100) = 204,
B11001101 DEPRECATED(0b11001101) = 205,
B11001110 DEPRECATED(0b11001110) = 206,
B11001111 DEPRECATED(0b11001111) = 207,
B11010000 DEPRECATED(0b11010000) = 208,
B11010001 DEPRECATED(0b11010001) = 209,
B11010010 DEPRECATED(0b11010010) = 210,
B11010011 DEPRECATED(0b11010011) = 211,
B11010100 DEPRECATED(0b11010100) = 212,
B11010101 DEPRECATED(0b11010101) = 213,
B11010110 DEPRECATED(0b11010110) = 214,
B11010111 DEPRECATED(0b11010111) = 215,
B11011000 DEPRECATED(0b11011000) = 216,
B11011001 DEPRECATED(0b11011001) = 217,
B11011010 DEPRECATED(0b11011010) = 218,
B11011011 DEPRECATED(0b11011011) = 219,
B11011100 DEPRECATED(0b11011100) = 220,
B11011101 DEPRECATED(0b11011101) = 221,
B11011110 DEPRECATED(0b11011110) = 222,
B11011111 DEPRECATED(0b11011111) = 223,
B11100000 DEPRECATED(0b11100000) = 224,
B11100001 DEPRECATED(0b11100001) = 225,
B11100010 DEPRECATED(0b11100010) = 226,
B11100011 DEPRECATED(0b11100011) = 227,
B11100100 DEPRECATED(0b11100100) = 228,
B11100101 DEPRECATED(0b11100101) = 229,
B11100110 DEPRECATED(0b11100110) = 230,
B11100111 DEPRECATED(0b11100111) = 231,
B11101000 DEPRECATED(0b11101000) = 232,
B11101001 DEPRECATED(0b11101001) = 233,
B11101010 DEPRECATED(0b11101010) = 234,
B11101011 DEPRECATED(0b11101011) = 235,
B11101100 DEPRECATED(0b11101100) = 236,
B11101101 DEPRECATED(0b11101101) = 237,
B11101110 DEPRECATED(0b11101110) = 238,
B11101111 DEPRECATED(0b11101111) = 239,
B11110000 DEPRECATED(0b11110000) = 240,
B11110001 DEPRECATED(0b11110001) = 241,
B11110010 DEPRECATED(0b11110010) = 242,
B11110011 DEPRECATED(0b11110011) = 243,
B11110100 DEPRECATED(0b11110100) = 244,
B11110101 DEPRECATED(0b11110101) = 245,
B11110110 DEPRECATED(0b11110110) = 246,
B11110111 DEPRECATED(0b11110111) = 247,
B11111000 DEPRECATED(0b11111000) = 248,
B11111001 DEPRECATED(0b11111001) = 249,
B11111010 DEPRECATED(0b11111010) = 250,
B11111011 DEPRECATED(0b11111011) = 251,
B11111100 DEPRECATED(0b11111100) = 252,
B11111101 DEPRECATED(0b11111101) = 253,
B11111110 DEPRECATED(0b11111110) = 254,
B11111111 DEPRECATED(0b11111111) = 255
};
#undef DEPRECATED
#endif
#pragma once
#include "../../../ArduinoCore-API/api/Binary.h"
+1 -45
View File
@@ -1,46 +1,2 @@
/*
Client.h - Base class that provides Client
Copyright (c) 2011 Adrian McEwen. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "Stream.h"
#include "IPAddress.h"
namespace arduino {
class Client : public Stream {
public:
virtual int connect(IPAddress ip, uint16_t port) =0;
virtual int connect(const char *host, uint16_t port) =0;
virtual size_t write(uint8_t) =0;
virtual size_t write(const uint8_t *buf, size_t size) =0;
virtual int available() = 0;
virtual int read() = 0;
virtual int read(uint8_t *buf, size_t size) = 0;
virtual int peek() = 0;
virtual void flush() = 0;
virtual void stop() = 0;
virtual uint8_t connected() = 0;
virtual operator bool() = 0;
protected:
uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); };
};
}
#include "../../../ArduinoCore-API/api/Client.h"
+1 -10
View File
@@ -1,10 +1 @@
#include "Common.h"
/* C++ prototypes */
long map(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
uint16_t makeWord(uint16_t w) { return w; }
uint16_t makeWord(uint8_t h, uint8_t l) { return (h << 8) | l; }
#include "../../../ArduinoCore-API/api/Common.cpp"
+1 -168
View File
@@ -1,169 +1,2 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C"{
#endif
void yield(void);
typedef enum {
LOW = 0,
HIGH = 1,
CHANGE = 2,
FALLING = 3,
RISING = 4,
} PinStatus;
typedef enum {
INPUT = 0x0,
OUTPUT = 0x1,
INPUT_PULLUP = 0x2,
INPUT_PULLDOWN = 0x3,
} PinMode;
typedef enum {
LSBFIRST = 0,
MSBFIRST = 1,
} BitOrder;
#define PI 3.1415926535897932384626433832795
#define HALF_PI 1.5707963267948966192313216916398
#define TWO_PI 6.283185307179586476925286766559
#define DEG_TO_RAD 0.017453292519943295769236907684886
#define RAD_TO_DEG 57.295779513082320876798154814105
#define EULER 2.718281828459045235360287471352
#define SERIAL 0x0
#define DISPLAY 0x1
#ifndef constrain
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
#endif
#ifndef radians
#define radians(deg) ((deg)*DEG_TO_RAD)
#endif
#ifndef degrees
#define degrees(rad) ((rad)*RAD_TO_DEG)
#endif
#ifndef sq
#define sq(x) ((x)*(x))
#endif
typedef void (*voidFuncPtr)(void);
typedef void (*voidFuncPtrParam)(void*);
// interrupts() / noInterrupts() must be defined by the core
#define lowByte(w) ((uint8_t) ((w) & 0xff))
#define highByte(w) ((uint8_t) ((w) >> 8))
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitToggle(value, bit) ((value) ^= (1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
#ifndef bit
#define bit(b) (1UL << (b))
#endif
/* TODO: request for removal */
typedef bool boolean;
typedef uint8_t byte;
typedef uint16_t word;
void init(void);
void initVariant(void);
#ifndef HOST
int atexit(void (*func)()) __attribute__((weak));
#endif
int main() __attribute__((weak));
#ifdef EXTENDED_PIN_MODE
// Platforms who wnat to declare more than 256 pins need to define EXTENDED_PIN_MODE globally
typedef uint32_t pin_size_t;
#else
typedef uint8_t pin_size_t;
#endif
void pinMode(pin_size_t pinNumber, PinMode pinMode);
void digitalWrite(pin_size_t pinNumber, PinStatus status);
PinStatus digitalRead(pin_size_t pinNumber);
int analogRead(pin_size_t pinNumber);
void analogReference(uint8_t mode);
void analogWrite(pin_size_t pinNumber, int value);
unsigned long millis(void);
unsigned long micros(void);
void delay(unsigned long);
void delayMicroseconds(unsigned int us);
unsigned long pulseIn(pin_size_t pin, uint8_t state, unsigned long timeout);
unsigned long pulseInLong(pin_size_t pin, uint8_t state, unsigned long timeout);
void shiftOut(pin_size_t dataPin, pin_size_t clockPin, BitOrder bitOrder, uint8_t val);
uint8_t shiftIn(pin_size_t dataPin, pin_size_t clockPin, BitOrder bitOrder);
void attachInterrupt(pin_size_t interruptNumber, voidFuncPtr callback, PinStatus mode);
void attachInterruptParam(pin_size_t interruptNumber, voidFuncPtrParam callback, PinStatus mode, void* param);
void detachInterrupt(pin_size_t interruptNumber);
void setup(void);
void loop(void);
#ifdef __cplusplus
} // extern "C"
#endif
#ifdef __cplusplus
template<class T, class L>
auto min(const T& a, const L& b) -> decltype((b < a) ? b : a)
{
return (b < a) ? b : a;
}
template<class T, class L>
auto max(const T& a, const L& b) -> decltype((b < a) ? b : a)
{
return (a < b) ? b : a;
}
#else
#ifndef min
#define min(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; })
#endif
#ifndef max
#define max(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; })
#endif
#endif
#ifdef __cplusplus
/* C++ prototypes */
uint16_t makeWord(uint16_t w);
uint16_t makeWord(byte h, byte l);
#define word(...) makeWord(__VA_ARGS__)
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0);
void noTone(uint8_t _pin);
// WMath prototypes
long random(long);
long random(long, long);
void randomSeed(unsigned long);
long map(long, long, long, long, long);
#endif // __cplusplus
#include "../../../ArduinoCore-API/api/Common.h"
+2 -16
View File
@@ -1,16 +1,2 @@
#ifndef __COMPAT_H__
#define __COMPAT_H__
namespace arduino {
inline void pinMode(pin_size_t pinNumber, int mode) {
pinMode(pinNumber, (PinMode)mode);
};
inline void digitalWrite(pin_size_t pinNumber, int status) {
digitalWrite(pinNumber, (PinStatus)status);
};
}
#endif
#pragma once
#include "../../../ArduinoCore-API/api/Compat.h"
+1 -46
View File
@@ -1,47 +1,2 @@
/*
Copyright (c) 2016 Arduino LLC. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include <inttypes.h>
#include "Stream.h"
namespace arduino {
class HardwareI2C : public Stream
{
public:
virtual void begin() = 0;
virtual void begin(uint8_t address) = 0;
virtual void end() = 0;
virtual void setClock(uint32_t freq) = 0;
virtual void beginTransmission(uint8_t address) = 0;
virtual uint8_t endTransmission(bool stopBit) = 0;
virtual uint8_t endTransmission(void) = 0;
virtual size_t requestFrom(uint8_t address, size_t len, bool stopBit) = 0;
virtual size_t requestFrom(uint8_t address, size_t len) = 0;
virtual void onReceive(void(*)(int)) = 0;
virtual void onRequest(void(*)(void)) = 0;
};
}
#include "../../../ArduinoCore-API/api/HardwareI2C.h"
+1 -129
View File
@@ -1,130 +1,2 @@
/*
Copyright (c) 2018 Arduino LLC. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "Common.h"
#include <inttypes.h>
#include "Stream.h"
#define SPI_HAS_TRANSACTION
namespace arduino {
typedef enum {
SPI_MODE0 = 0,
SPI_MODE1 = 1,
SPI_MODE2 = 2,
SPI_MODE3 = 3,
} SPIMode;
class SPISettings {
public:
SPISettings(uint32_t clock, BitOrder bitOrder, SPIMode dataMode) {
if (__builtin_constant_p(clock)) {
init_AlwaysInline(clock, bitOrder, dataMode);
} else {
init_MightInline(clock, bitOrder, dataMode);
}
}
SPISettings(uint32_t clock, BitOrder bitOrder, int dataMode) {
if (__builtin_constant_p(clock)) {
init_AlwaysInline(clock, bitOrder, (SPIMode)dataMode);
} else {
init_MightInline(clock, bitOrder, (SPIMode)dataMode);
}
}
// Default speed set to 4MHz, SPI mode set to MODE 0 and Bit order set to MSB first.
SPISettings() { init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); }
bool operator==(const SPISettings& rhs) const
{
if ((this->clockFreq == rhs.clockFreq) &&
(this->bitOrder == rhs.bitOrder) &&
(this->dataMode == rhs.dataMode)) {
return true;
}
return false;
}
bool operator!=(const SPISettings& rhs) const
{
return !(*this == rhs);
}
uint32_t getClockFreq() const {
return clockFreq;
}
SPIMode getDataMode() const {
return dataMode;
}
BitOrder getBitOrder() const {
return (bitOrder);
}
private:
void init_MightInline(uint32_t clock, BitOrder bitOrder, SPIMode dataMode) {
init_AlwaysInline(clock, bitOrder, dataMode);
}
// Core developer MUST use an helper function in beginTransaction() to use this data
void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, SPIMode dataMode) __attribute__((__always_inline__)) {
this->clockFreq = clock;
this->dataMode = dataMode;
this->bitOrder = bitOrder;
}
uint32_t clockFreq;
SPIMode dataMode;
BitOrder bitOrder;
friend class HardwareSPI;
};
const SPISettings DEFAULT_SPI_SETTINGS = SPISettings();
class HardwareSPI
{
public:
virtual ~HardwareSPI() { }
virtual uint8_t transfer(uint8_t data) = 0;
virtual uint16_t transfer16(uint16_t data) = 0;
virtual void transfer(void *buf, size_t count) = 0;
// Transaction Functions
virtual void usingInterrupt(int interruptNumber) = 0;
virtual void notUsingInterrupt(int interruptNumber) = 0;
virtual void beginTransaction(SPISettings settings) = 0;
virtual void endTransaction(void) = 0;
// SPI Configuration methods
virtual void attachInterrupt() = 0;
virtual void detachInterrupt() = 0;
virtual void begin() = 0;
virtual void end() = 0;
};
// Alias SPIClass to HardwareSPI since it's already the defacto standard for SPI classe name
typedef HardwareSPI SPIClass;
}
#include "../../../ArduinoCore-API/api/HardwareSPI.h"
+1 -104
View File
@@ -1,105 +1,2 @@
/*
Copyright (c) 2016 Arduino LLC. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include <inttypes.h>
#include "Stream.h"
namespace arduino {
// XXX: Those constants should be defined as const int / enums?
// XXX: shall we use namespaces too?
#define SERIAL_PARITY_EVEN (0x1ul)
#define SERIAL_PARITY_ODD (0x2ul)
#define SERIAL_PARITY_NONE (0x3ul)
#define SERIAL_PARITY_MARK (0x4ul)
#define SERIAL_PARITY_SPACE (0x5ul)
#define SERIAL_PARITY_MASK (0xFul)
#define SERIAL_STOP_BIT_1 (0x10ul)
#define SERIAL_STOP_BIT_1_5 (0x20ul)
#define SERIAL_STOP_BIT_2 (0x30ul)
#define SERIAL_STOP_BIT_MASK (0xF0ul)
#define SERIAL_DATA_5 (0x100ul)
#define SERIAL_DATA_6 (0x200ul)
#define SERIAL_DATA_7 (0x300ul)
#define SERIAL_DATA_8 (0x400ul)
#define SERIAL_DATA_MASK (0xF00ul)
#define SERIAL_5N1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_5)
#define SERIAL_6N1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_6)
#define SERIAL_7N1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_7)
#define SERIAL_8N1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_8)
#define SERIAL_5N2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_5)
#define SERIAL_6N2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_6)
#define SERIAL_7N2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_7)
#define SERIAL_8N2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_8)
#define SERIAL_5E1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_5)
#define SERIAL_6E1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_6)
#define SERIAL_7E1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_7)
#define SERIAL_8E1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_8)
#define SERIAL_5E2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_5)
#define SERIAL_6E2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_6)
#define SERIAL_7E2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_7)
#define SERIAL_8E2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_8)
#define SERIAL_5O1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_5)
#define SERIAL_6O1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_6)
#define SERIAL_7O1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_7)
#define SERIAL_8O1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_8)
#define SERIAL_5O2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_5)
#define SERIAL_6O2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_6)
#define SERIAL_7O2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_7)
#define SERIAL_8O2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_8)
#define SERIAL_5M1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_5)
#define SERIAL_6M1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_6)
#define SERIAL_7M1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_7)
#define SERIAL_8M1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_8)
#define SERIAL_5M2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_5)
#define SERIAL_6M2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_6)
#define SERIAL_7M2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_7)
#define SERIAL_8M2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_8)
#define SERIAL_5S1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_SPACE | SERIAL_DATA_5)
#define SERIAL_6S1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_SPACE | SERIAL_DATA_6)
#define SERIAL_7S1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_SPACE | SERIAL_DATA_7)
#define SERIAL_8S1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_SPACE | SERIAL_DATA_8)
#define SERIAL_5S2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_SPACE | SERIAL_DATA_5)
#define SERIAL_6S2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_SPACE | SERIAL_DATA_6)
#define SERIAL_7S2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_SPACE | SERIAL_DATA_7)
#define SERIAL_8S2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_SPACE | SERIAL_DATA_8)
class HardwareSerial : public Stream
{
public:
virtual void begin(unsigned long) = 0;
virtual void begin(unsigned long baudrate, uint16_t config) = 0;
virtual void end() = 0;
virtual int available(void) = 0;
virtual int peek(void) = 0;
virtual int read(void) = 0;
virtual void flush(void) = 0;
virtual size_t write(uint8_t) = 0;
using Print::write; // pull in write(str) and write(buf, size) from Print
virtual operator bool() = 0;
};
// XXX: Are we keeping the serialEvent API?
extern void serialEventRun(void) __attribute__((weak));
}
#include "../../../ArduinoCore-API/api/HardwareSerial.h"
+1 -127
View File
@@ -1,127 +1 @@
/*
IPAddress.cpp - Base class that provides IPAddress
Copyright (c) 2011 Adrian McEwen. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "IPAddress.h"
#include "Print.h"
using namespace arduino;
IPAddress::IPAddress()
{
_address.dword = 0;
}
IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet)
{
_address.bytes[0] = first_octet;
_address.bytes[1] = second_octet;
_address.bytes[2] = third_octet;
_address.bytes[3] = fourth_octet;
}
IPAddress::IPAddress(uint32_t address)
{
_address.dword = address;
}
IPAddress::IPAddress(const uint8_t *address)
{
memcpy(_address.bytes, address, sizeof(_address.bytes));
}
bool IPAddress::fromString(const char *address)
{
// TODO: add support for "a", "a.b", "a.b.c" formats
int16_t acc = -1; // Accumulator
uint8_t dots = 0;
while (*address)
{
char c = *address++;
if (c >= '0' && c <= '9')
{
acc = (acc < 0) ? (c - '0') : acc * 10 + (c - '0');
if (acc > 255) {
// Value out of [0..255] range
return false;
}
}
else if (c == '.')
{
if (dots == 3) {
// Too much dots (there must be 3 dots)
return false;
}
if (acc < 0) {
/* No value between dots, e.g. '1..' */
return false;
}
_address.bytes[dots++] = acc;
acc = -1;
}
else
{
// Invalid char
return false;
}
}
if (dots != 3) {
// Too few dots (there must be 3 dots)
return false;
}
if (acc < 0) {
/* No value between dots, e.g. '1..' */
return false;
}
_address.bytes[3] = acc;
return true;
}
IPAddress& IPAddress::operator=(const uint8_t *address)
{
memcpy(_address.bytes, address, sizeof(_address.bytes));
return *this;
}
IPAddress& IPAddress::operator=(uint32_t address)
{
_address.dword = address;
return *this;
}
bool IPAddress::operator==(const uint8_t* addr) const
{
return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0;
}
size_t IPAddress::printTo(Print& p) const
{
size_t n = 0;
for (int i =0; i < 3; i++)
{
n += p.print(_address.bytes[i], DEC);
n += p.print('.');
}
n += p.print(_address.bytes[3], DEC);
return n;
}
const IPAddress arduino::INADDR_NONE(0,0,0,0);
#include "../../../ArduinoCore-API/api/IPAddress.cpp"
+1 -84
View File
@@ -1,85 +1,2 @@
/*
IPAddress.h - Base class that provides IPAddress
Copyright (c) 2011 Adrian McEwen. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include <stdint.h>
#include "Printable.h"
#include "String.h"
// forward declartions of global name space friend classes
class EthernetClass;
class DhcpClass;
class DNSClient;
namespace arduino {
// A class to make it easier to handle and pass around IP addresses
class IPAddress : public Printable {
private:
union {
uint8_t bytes[4]; // IPv4 address
uint32_t dword;
} _address;
// Access the raw byte array containing the address. Because this returns a pointer
// to the internal structure rather than a copy of the address this function should only
// be used when you know that the usage of the returned uint8_t* will be transient and not
// stored.
uint8_t* raw_address() { return _address.bytes; };
public:
// Constructors
IPAddress();
IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
IPAddress(uint32_t address);
IPAddress(const uint8_t *address);
bool fromString(const char *address);
bool fromString(const String &address) { return fromString(address.c_str()); }
// Overloaded cast operator to allow IPAddress objects to be used where a pointer
// to a four-byte uint8_t array is expected
operator uint32_t() const { return _address.dword; };
bool operator==(const IPAddress& addr) const { return _address.dword == addr._address.dword; };
bool operator!=(const IPAddress& addr) const { return _address.dword != addr._address.dword; };
bool operator==(const uint8_t* addr) const;
// Overloaded index operator to allow getting and setting individual octets of the address
uint8_t operator[](int index) const { return _address.bytes[index]; };
uint8_t& operator[](int index) { return _address.bytes[index]; };
// Overloaded copy operators to allow initialisation of IPAddress objects from other types
IPAddress& operator=(const uint8_t *address);
IPAddress& operator=(uint32_t address);
virtual size_t printTo(Print& p) const;
friend class UDP;
friend class Client;
friend class Server;
friend ::EthernetClass;
friend ::DhcpClass;
friend ::DNSClient;
};
extern const IPAddress INADDR_NONE;
}
#include "../../../ArduinoCore-API/api/IPAddress.h"
+2 -44
View File
@@ -1,44 +1,2 @@
#ifndef W_INTERRUPTS_CPP
#define W_INTERRUPTS_CPP
#ifdef __cplusplus
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include "Common.h"
namespace arduino {
template <typename T>
using voidTemplateFuncPtrParam = void (*)(T param);
template<typename T> struct __container__ {
void* param;
voidTemplateFuncPtrParam<T> function;
};
// C++ only overloaded version of attachInterrupt function
template<typename T> void attachInterrupt(pin_size_t interruptNum, voidTemplateFuncPtrParam<T> userFunc, PinStatus mode, T& param) {
struct __container__<T> *cont = new __container__<T>();
cont->param = &param;
cont->function = userFunc;
// TODO: check lambda scope
// TODO: add structure to delete(__container__) when detachInterrupt() is called
auto f = [](void* a) -> void
{
T param = *(T*)((struct __container__<T>*)a)->param;
(((struct __container__<T>*)a)->function)(param);
};
attachInterruptParam(interruptNum, f, mode, cont);
}
template<typename T> void attachInterrupt(pin_size_t interruptNum, voidTemplateFuncPtrParam<T*> userFunc, PinStatus mode, T* param) {
attachInterruptParam(interruptNum, (voidFuncPtrParam)userFunc, mode, (void*)param);
}
}
#endif
#endif
#pragma once
#include "../../../ArduinoCore-API/api/Interrupts.h"
+1 -101
View File
@@ -1,101 +1 @@
/*
PluggableUSB.cpp
Copyright (c) 2015 Arduino LLC
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "USBAPI.h"
#include "PluggableUSB.h"
using namespace arduino;
int PluggableUSB_::getInterface(uint8_t* interfaceCount)
{
int sent = 0;
PluggableUSBModule* node;
for (node = rootNode; node; node = node->next) {
int res = node->getInterface(interfaceCount);
if (res < 0)
return -1;
sent += res;
}
return sent;
}
int PluggableUSB_::getDescriptor(USBSetup& setup)
{
PluggableUSBModule* node;
for (node = rootNode; node; node = node->next) {
int ret = node->getDescriptor(setup);
// ret!=0 -> request has been processed
if (ret)
return ret;
}
return 0;
}
void PluggableUSB_::getShortName(char *iSerialNum)
{
PluggableUSBModule* node;
for (node = rootNode; node; node = node->next) {
iSerialNum += node->getShortName(iSerialNum);
}
*iSerialNum = 0;
}
bool PluggableUSB_::setup(USBSetup& setup)
{
PluggableUSBModule* node;
for (node = rootNode; node; node = node->next) {
if (node->setup(setup)) {
return true;
}
}
return false;
}
bool PluggableUSB_::plug(PluggableUSBModule *node)
{
if ((lastEp + node->numEndpoints) > totalEP) {
return false;
}
if (!rootNode) {
rootNode = node;
} else {
PluggableUSBModule *current = rootNode;
while (current->next) {
current = current->next;
}
current->next = node;
}
node->pluggedInterface = lastIf;
node->pluggedEndpoint = lastEp;
lastIf += node->numInterfaces;
for (uint8_t i = 0; i < node->numEndpoints; i++) {
*(unsigned int*)(epBuffer(lastEp)) = node->endpointType[i];
lastEp++;
}
return true;
// restart USB layer???
}
PluggableUSB_& PluggableUSB()
{
static PluggableUSB_ obj;
return obj;
}
#include "../../../ArduinoCore-API/api/PluggableUSB.cpp"
+2 -78
View File
@@ -1,78 +1,2 @@
/*
PluggableUSB.h
Copyright (c) 2015 Arduino LLC
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef PUSB_h
#define PUSB_h
#include "USBAPI.h"
#include <stdint.h>
#include <stddef.h>
namespace arduino {
class PluggableUSBModule {
public:
PluggableUSBModule(uint8_t numEps, uint8_t numIfs, unsigned int *epType) :
numEndpoints(numEps), numInterfaces(numIfs), endpointType(epType)
{ }
protected:
virtual bool setup(USBSetup& setup) = 0;
virtual int getInterface(uint8_t* interfaceCount) = 0;
virtual int getDescriptor(USBSetup& setup) = 0;
virtual uint8_t getShortName(char *name) { name[0] = 'A'+pluggedInterface; return 1; }
uint8_t pluggedInterface;
uint8_t pluggedEndpoint;
const uint8_t numEndpoints;
const uint8_t numInterfaces;
const unsigned int *endpointType;
PluggableUSBModule *next = NULL;
friend class PluggableUSB_;
};
class PluggableUSB_ {
public:
PluggableUSB_();
bool plug(PluggableUSBModule *node);
int getInterface(uint8_t* interfaceCount);
int getDescriptor(USBSetup& setup);
bool setup(USBSetup& setup);
void getShortName(char *iSerialNum);
private:
uint8_t lastIf;
uint8_t lastEp;
PluggableUSBModule* rootNode;
uint8_t totalEP;
};
}
// core need to define
void* epBuffer(unsigned int n); // -> returns a pointer to the Nth element of the EP buffer structure
// Replacement for global singleton.
// This function prevents static-initialization-order-fiasco
// https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use
arduino::PluggableUSB_& PluggableUSB();
#endif
#pragma once
#include "../../../ArduinoCore-API/api/PluggableUSB.h"
+1 -429
View File
@@ -1,429 +1 @@
/*
Copyright (c) 2014 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "Print.h"
using namespace arduino;
// Public Methods //////////////////////////////////////////////////////////////
/* default implementation: may be overridden */
size_t Print::write(const uint8_t *buffer, size_t size)
{
size_t n = 0;
while (size--) {
if (write(*buffer++)) n++;
else break;
}
return n;
}
size_t Print::print(const __FlashStringHelper *ifsh)
{
#if defined(__AVR__)
PGM_P p = reinterpret_cast<PGM_P>(ifsh);
size_t n = 0;
while (1) {
unsigned char c = pgm_read_byte(p++);
if (c == 0) break;
if (write(c)) n++;
else break;
}
return n;
#else
return print(reinterpret_cast<const char *>(ifsh));
#endif
}
size_t Print::print(const String &s)
{
return write(s.c_str(), s.length());
}
size_t Print::print(const char str[])
{
return write(str);
}
size_t Print::print(char c)
{
return write(c);
}
size_t Print::print(unsigned char b, int base)
{
return print((unsigned long) b, base);
}
size_t Print::print(int n, int base)
{
return print((long) n, base);
}
size_t Print::print(unsigned int n, int base)
{
return print((unsigned long) n, base);
}
size_t Print::print(long n, int base)
{
if (base == 0) {
return write(n);
} else if (base == 10) {
if (n < 0) {
int t = print('-');
n = -n;
return printNumber(n, 10) + t;
}
return printNumber(n, 10);
} else {
return printNumber(n, base);
}
}
size_t Print::print(unsigned long n, int base)
{
if (base == 0) return write(n);
else return printNumber(n, base);
}
size_t Print::print(long long n, int base)
{
if (base == 0) {
return write(n);
} else if (base == 10) {
if (n < 0) {
int t = print('-');
n = -n;
return printULLNumber(n, 10) + t;
}
return printULLNumber(n, 10);
} else {
return printULLNumber(n, base);
}
}
size_t Print::print(unsigned long long n, int base)
{
if (base == 0) return write(n);
else return printULLNumber(n, base);
}
size_t Print::print(double n, int digits)
{
return printFloat(n, digits);
}
size_t Print::println(const __FlashStringHelper *ifsh)
{
size_t n = print(ifsh);
n += println();
return n;
}
size_t Print::print(const Printable& x)
{
return x.printTo(*this);
}
size_t Print::println(void)
{
return write("\r\n");
}
size_t Print::println(const String &s)
{
size_t n = print(s);
n += println();
return n;
}
size_t Print::println(const char c[])
{
size_t n = print(c);
n += println();
return n;
}
size_t Print::println(char c)
{
size_t n = print(c);
n += println();
return n;
}
size_t Print::println(unsigned char b, int base)
{
size_t n = print(b, base);
n += println();
return n;
}
size_t Print::println(int num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(unsigned int num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(long num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(unsigned long num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(long long num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(unsigned long long num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(double num, int digits)
{
size_t n = print(num, digits);
n += println();
return n;
}
size_t Print::println(const Printable& x)
{
size_t n = print(x);
n += println();
return n;
}
size_t Print::printf(const char *format, ...) {
va_list arg;
va_start(arg, format);
char temp[64];
char* buffer = temp;
size_t len = vsnprintf(temp, sizeof(temp), format, arg);
va_end(arg);
if (len > sizeof(temp) - 1) {
buffer = new char[len + 1];
if (!buffer) {
return 0;
}
va_start(arg, format);
vsnprintf(buffer, len + 1, format, arg);
va_end(arg);
}
len = write((const uint8_t*) buffer, len);
if (buffer != temp) {
delete[] buffer;
}
return len;
}
// TODO - must be better way than cut-n-paste!
size_t Print::printf_P(const char *format, ...) {
va_list arg;
va_start(arg, format);
char temp[64];
char* buffer = temp;
size_t len = vsnprintf(temp, sizeof(temp), format, arg);
va_end(arg);
if (len > sizeof(temp) - 1) {
buffer = new char[len + 1];
if (!buffer) {
return 0;
}
va_start(arg, format);
vsnprintf(buffer, len + 1, format, arg);
va_end(arg);
}
len = write((const uint8_t*) buffer, len);
if (buffer != temp) {
delete[] buffer;
}
return len;
}
// Private Methods /////////////////////////////////////////////////////////////
size_t Print::printNumber(unsigned long n, uint8_t base)
{
char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
char *str = &buf[sizeof(buf) - 1];
*str = '\0';
// prevent crash if called with base == 1
if (base < 2) base = 10;
do {
char c = n % base;
n /= base;
*--str = c < 10 ? c + '0' : c + 'A' - 10;
} while(n);
return write(str);
}
// REFERENCE IMPLEMENTATION FOR ULL
// size_t Print::printULLNumber(unsigned long long n, uint8_t base)
// {
// // if limited to base 10 and 16 the bufsize can be smaller
// char buf[65];
// char *str = &buf[64];
// *str = '\0';
// // prevent crash if called with base == 1
// if (base < 2) base = 10;
// do {
// unsigned long long t = n / base;
// char c = n - t * base; // faster than c = n%base;
// n = t;
// *--str = c < 10 ? c + '0' : c + 'A' - 10;
// } while(n);
// return write(str);
// }
// FAST IMPLEMENTATION FOR ULL
size_t Print::printULLNumber(unsigned long long n64, uint8_t base)
{
// if limited to base 10 and 16 the bufsize can be 20
char buf[64];
uint8_t i = 0;
uint8_t innerLoops = 0;
// prevent crash if called with base == 1
if (base < 2) base = 10;
// process chunks that fit in "16 bit math".
uint16_t top = 0xFFFF / base;
uint16_t th16 = 1;
while (th16 < top)
{
th16 *= base;
innerLoops++;
}
while (n64 > th16)
{
// 64 bit math part
uint64_t q = n64 / th16;
uint16_t r = n64 - q*th16;
n64 = q;
// 16 bit math loop to do remainder. (note buffer is filled reverse)
for (uint8_t j=0; j < innerLoops; j++)
{
uint16_t qq = r/base;
buf[i++] = r - qq*base;
r = qq;
}
}
uint16_t n16 = n64;
while (n16 > 0)
{
uint16_t qq = n16/base;
buf[i++] = n16 - qq*base;
n16 = qq;
}
size_t bytes = i;
for (; i > 0; i--)
write((char) (buf[i - 1] < 10 ?
'0' + buf[i - 1] :
'A' + buf[i - 1] - 10));
return bytes;
}
size_t Print::printFloat(double number, int digits)
{
if (digits < 0)
digits = 2;
size_t n = 0;
if (isnan(number)) return print("nan");
if (isinf(number)) return print("inf");
if (number > 4294967040.0) return print ("ovf"); // constant determined empirically
if (number <-4294967040.0) return print ("ovf"); // constant determined empirically
// Handle negative numbers
if (number < 0.0)
{
n += print('-');
number = -number;
}
// Round correctly so that print(1.999, 2) prints as "2.00"
double rounding = 0.5;
for (uint8_t i=0; i<digits; ++i)
rounding /= 10.0;
number += rounding;
// Extract the integer part of the number and print it
unsigned long int_part = (unsigned long)number;
double remainder = number - (double)int_part;
n += print(int_part);
// Print the decimal point, but only if there are digits beyond
if (digits > 0) {
n += print(".");
}
// Extract digits from the remainder one at a time
while (digits-- > 0)
{
remainder *= 10.0;
unsigned int toPrint = (unsigned int)remainder;
n += print(toPrint);
remainder -= toPrint;
}
return n;
}
#include "../../../ArduinoCore-API/api/Print.cpp"
+1 -99
View File
@@ -1,100 +1,2 @@
/*
Copyright (c) 2016 Arduino LLC. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include <inttypes.h>
#include <stdio.h> // for size_t
#include "String.h"
#include "Printable.h"
#define DEC 10
#define HEX 16
#define OCT 8
#define BIN 2
namespace arduino {
class Print
{
private:
int write_error;
size_t printNumber(unsigned long, uint8_t);
size_t printULLNumber(unsigned long long, uint8_t);
size_t printFloat(double, int);
protected:
void setWriteError(int err = 1) { write_error = err; }
public:
Print() : write_error(0) {}
int getWriteError() { return write_error; }
void clearWriteError() { setWriteError(0); }
virtual size_t write(uint8_t) = 0;
size_t write(const char *str) {
if (str == NULL) return 0;
return write((const uint8_t *)str, strlen(str));
}
virtual size_t write(const uint8_t *buffer, size_t size);
size_t write(const char *buffer, size_t size) {
return write((const uint8_t *)buffer, size);
}
// default to zero, meaning "a single write may block"
// should be overriden by subclasses with buffering
virtual int availableForWrite() { return 0; }
size_t print(const __FlashStringHelper *);
size_t print(const String &);
size_t print(const char[]);
size_t print(char);
size_t print(unsigned char, int = DEC);
size_t print(int, int = DEC);
size_t print(unsigned int, int = DEC);
size_t print(long, int = DEC);
size_t print(unsigned long, int = DEC);
size_t print(long long, int = DEC);
size_t print(unsigned long long, int = DEC);
size_t print(double, int = 2);
size_t print(const Printable&);
size_t println(const __FlashStringHelper *);
size_t println(const String &s);
size_t println(const char[]);
size_t println(char);
size_t println(unsigned char, int = DEC);
size_t println(int, int = DEC);
size_t println(unsigned int, int = DEC);
size_t println(long, int = DEC);
size_t println(unsigned long, int = DEC);
size_t println(long long, int = DEC);
size_t println(unsigned long long, int = DEC);
size_t println(double, int = 2);
size_t println(const Printable&);
size_t println(void);
// EFP3 - Add printf() to make life so much easier...
size_t printf(const char *format, ...);
size_t printf_P(const char *format, ...);
virtual void flush() { /* Empty implementation for backward compatibility */ }
};
}
using namespace arduino;
#include "../../../ArduinoCore-API/api/Print.h"
+1 -38
View File
@@ -1,39 +1,2 @@
/*
Copyright (c) 2016 Arduino LLC. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include <stdlib.h>
namespace arduino {
class Print;
/** The Printable class provides a way for new classes to allow themselves to be printed.
By deriving from Printable and implementing the printTo method, it will then be possible
for users to print out instances of this class by passing them into the usual
Print::print and Print::println methods.
*/
class Printable
{
public:
virtual size_t printTo(Print& p) const = 0;
};
}
#include "../../../ArduinoCore-API/api/Printable.h"
+1 -141
View File
@@ -1,141 +1 @@
/*
Copyright (c) 2014 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef __cplusplus
#ifndef _RING_BUFFER_
#define _RING_BUFFER_
#include <stdint.h>
#include <string.h>
namespace arduino {
// Define constants and variables for buffering incoming serial data. We're
// using a ring buffer (I think), in which head is the index of the location
// to which to write the next incoming character and tail is the index of the
// location from which to read.
#define SERIAL_BUFFER_SIZE 64
template <int N>
class RingBufferN
{
public:
uint8_t _aucBuffer[N] ;
volatile int _iHead ;
volatile int _iTail ;
volatile int _numElems;
public:
RingBufferN( void ) ;
void store_char( uint8_t c ) ;
void clear();
int read_char();
int available();
int availableForStore();
int peek();
bool isFull();
private:
int nextIndex(int index);
inline bool isEmpty() const { return (_numElems == 0); }
};
typedef RingBufferN<SERIAL_BUFFER_SIZE> RingBuffer;
template <int N>
RingBufferN<N>::RingBufferN( void )
{
memset( _aucBuffer, 0, N ) ;
clear();
}
template <int N>
void RingBufferN<N>::store_char( uint8_t c )
{
// if we should be storing the received character into the location
// just before the tail (meaning that the head would advance to the
// current location of the tail), we're about to overflow the buffer
// and so we don't write the character or advance the head.
if (!isFull())
{
_aucBuffer[_iHead] = c ;
_iHead = nextIndex(_iHead);
_numElems++;
}
}
template <int N>
void RingBufferN<N>::clear()
{
_iHead = 0;
_iTail = 0;
_numElems = 0;
}
template <int N>
int RingBufferN<N>::read_char()
{
if (isEmpty())
return -1;
uint8_t value = _aucBuffer[_iTail];
_iTail = nextIndex(_iTail);
_numElems--;
return value;
}
template <int N>
int RingBufferN<N>::available()
{
return _numElems;
}
template <int N>
int RingBufferN<N>::availableForStore()
{
return (N - _numElems);
}
template <int N>
int RingBufferN<N>::peek()
{
if (isEmpty())
return -1;
return _aucBuffer[_iTail];
}
template <int N>
int RingBufferN<N>::nextIndex(int index)
{
return (uint32_t)(index + 1) % N;
}
template <int N>
bool RingBufferN<N>::isFull()
{
return (_numElems == N);
}
}
#endif /* _RING_BUFFER_ */
#endif /* __cplusplus */
#include "../../../ArduinoCore-API/api/RingBuffer.h"
+1 -30
View File
@@ -1,31 +1,2 @@
/*
Server.h - Base class that provides Server
Copyright (c) 2011 Adrian McEwen. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "Print.h"
namespace arduino {
class Server : public Print {
public:
virtual void begin() = 0;
};
}
#include "../../../ArduinoCore-API/api/Server.h"
+1 -321
View File
@@ -1,321 +1 @@
/*
Stream.cpp - adds parsing methods to Stream class
Copyright (c) 2008 David A. Mellis. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Created July 2011
parsing functions based on TextFinder library by Michael Margolis
findMulti/findUntil routines written by Jim Leonard/Xuth
*/
#include "Common.h"
#include "Stream.h"
#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait
using namespace arduino;
// private method to read stream with timeout
int Stream::timedRead()
{
int c;
_startMillis = millis();
do {
c = read();
if (c >= 0) return c;
} while(millis() - _startMillis < _timeout);
return -1; // -1 indicates timeout
}
// private method to peek stream with timeout
int Stream::timedPeek()
{
int c;
_startMillis = millis();
do {
c = peek();
if (c >= 0) return c;
} while(millis() - _startMillis < _timeout);
return -1; // -1 indicates timeout
}
// returns peek of the next digit in the stream or -1 if timeout
// discards non-numeric characters
int Stream::peekNextDigit(LookaheadMode lookahead, bool detectDecimal)
{
int c;
while (1) {
c = timedPeek();
if( c < 0 ||
c == '-' ||
(c >= '0' && c <= '9') ||
(detectDecimal && c == '.')) return c;
switch( lookahead ){
case SKIP_NONE: return -1; // Fail code.
case SKIP_WHITESPACE:
switch( c ){
case ' ':
case '\t':
case '\r':
case '\n': break;
default: return -1; // Fail code.
}
case SKIP_ALL:
break;
}
read(); // discard non-numeric
}
}
// Public Methods
//////////////////////////////////////////////////////////////
void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait
{
_timeout = timeout;
}
// find returns true if the target string is found
bool Stream::find(const char *target)
{
return findUntil(target, strlen(target), NULL, 0);
}
// reads data from the stream until the target string of given length is found
// returns true if target string is found, false if timed out
bool Stream::find(const char *target, size_t length)
{
return findUntil(target, length, NULL, 0);
}
// as find but search ends if the terminator string is found
bool Stream::findUntil(const char *target, const char *terminator)
{
return findUntil(target, strlen(target), terminator, strlen(terminator));
}
// reads data from the stream until the target string of the given length is found
// search terminated if the terminator string is found
// returns true if target string is found, false if terminated or timed out
bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator, size_t termLen)
{
if (terminator == NULL) {
MultiTarget t[1] = {{target, targetLen, 0}};
return findMulti(t, 1) == 0;
} else {
MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}};
return findMulti(t, 2) == 0;
}
}
// returns the first valid (long) integer value from the current position.
// lookahead determines how parseInt looks ahead in the stream.
// See LookaheadMode enumeration at the top of the file.
// Lookahead is terminated by the first character that is not a valid part of an integer.
// Once parsing commences, 'ignore' will be skipped in the stream.
long Stream::parseInt(LookaheadMode lookahead, char ignore)
{
bool isNegative = false;
long value = 0;
int c;
c = peekNextDigit(lookahead, false);
// ignore non numeric leading characters
if(c < 0)
return 0; // zero returned if timeout
do{
if((char)c == ignore)
; // ignore this character
else if(c == '-')
isNegative = true;
else if(c >= '0' && c <= '9') // is c a digit?
value = value * 10 + c - '0';
read(); // consume the character we got with peek
c = timedPeek();
}
while( (c >= '0' && c <= '9') || (char)c == ignore );
if(isNegative)
value = -value;
return value;
}
// as parseInt but returns a floating point value
float Stream::parseFloat(LookaheadMode lookahead, char ignore)
{
bool isNegative = false;
bool isFraction = false;
double value = 0.0;
int c;
double fraction = 1.0;
c = peekNextDigit(lookahead, true);
// ignore non numeric leading characters
if(c < 0)
return 0; // zero returned if timeout
do{
if((char)c == ignore)
; // ignore
else if(c == '-')
isNegative = true;
else if (c == '.')
isFraction = true;
else if(c >= '0' && c <= '9') { // is c a digit?
if(isFraction) {
fraction *= 0.1;
value = value + fraction * (c - '0');
} else {
value = value * 10 + c - '0';
}
}
read(); // consume the character we got with peek
c = timedPeek();
}
while( (c >= '0' && c <= '9') || (c == '.' && !isFraction) || (char)c == ignore );
if(isNegative)
value = -value;
return value;
}
// read characters from stream into buffer
// terminates if length characters have been read, or timeout (see setTimeout)
// returns the number of characters placed in the buffer
// the buffer is NOT null terminated.
//
size_t Stream::readBytes(char *buffer, size_t length)
{
size_t count = 0;
while (count < length) {
int c = timedRead();
if (c < 0) break;
*buffer++ = (char)c;
count++;
}
return count;
}
// as readBytes with terminator character
// terminates if length characters have been read, timeout, or if the terminator character detected
// returns the number of characters placed in the buffer (0 means no valid data found)
size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
{
size_t index = 0;
while (index < length) {
int c = timedRead();
if (c < 0 || (char)c == terminator) break;
*buffer++ = (char)c;
index++;
}
return index; // return number of characters, not including null terminator
}
String Stream::readString()
{
String ret;
int c = timedRead();
while (c >= 0)
{
ret += (char)c;
c = timedRead();
}
return ret;
}
String Stream::readStringUntil(char terminator)
{
String ret;
int c = timedRead();
while (c >= 0 && (char)c != terminator)
{
ret += (char)c;
c = timedRead();
}
return ret;
}
int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) {
// any zero length target string automatically matches and would make
// a mess of the rest of the algorithm.
for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
if (t->len <= 0)
return t - targets;
}
while (1) {
int c = timedRead();
if (c < 0)
return -1;
for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
// the simple case is if we match, deal with that first.
if ((char)c == t->str[t->index]) {
if (++t->index == t->len)
return t - targets;
else
continue;
}
// if not we need to walk back and see if we could have matched further
// down the stream (ie '1112' doesn't match the first position in '11112'
// but it will match the second position so we can't just reset the current
// index to 0 when we find a mismatch.
if (t->index == 0)
continue;
int origIndex = t->index;
do {
--t->index;
// first check if current char works against the new current index
if ((char)c != t->str[t->index])
continue;
// if it's the only char then we're good, nothing more to check
if (t->index == 0) {
t->index++;
break;
}
// otherwise we need to check the rest of the found string
int diff = origIndex - t->index;
size_t i;
for (i = 0; i < t->index; ++i) {
if (t->str[i] != t->str[i + diff])
break;
}
// if we successfully got through the previous loop then our current
// index is good.
if (i == t->index) {
t->index++;
break;
}
// otherwise we just try the next index
} while (t->index);
}
}
// unreachable
return -1;
}
#include "../../../ArduinoCore-API/api/Stream.cpp"
+1 -130
View File
@@ -1,131 +1,2 @@
/*
Stream.h - base class for character-based streams.
Copyright (c) 2010 David A. Mellis. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
parsing functions based on TextFinder library by Michael Margolis
*/
#pragma once
#include <inttypes.h>
#include "Print.h"
// compatability macros for testing
/*
#define getInt() parseInt()
#define getInt(ignore) parseInt(ignore)
#define getFloat() parseFloat()
#define getFloat(ignore) parseFloat(ignore)
#define getString( pre_string, post_string, buffer, length)
readBytesBetween( pre_string, terminator, buffer, length)
*/
namespace arduino {
// This enumeration provides the lookahead options for parseInt(), parseFloat()
// The rules set out here are used until either the first valid character is found
// or a time out occurs due to lack of input.
enum LookaheadMode{
SKIP_ALL, // All invalid characters are ignored.
SKIP_NONE, // Nothing is skipped, and the stream is not touched unless the first waiting character is valid.
SKIP_WHITESPACE // Only tabs, spaces, line feeds & carriage returns are skipped.
};
#define NO_IGNORE_CHAR '\x01' // a char not found in a valid ASCII numeric field
class Stream : public Print
{
protected:
unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read
unsigned long _startMillis; // used for timeout measurement
int timedRead(); // private method to read stream with timeout
int timedPeek(); // private method to peek stream with timeout
int peekNextDigit(LookaheadMode lookahead, bool detectDecimal); // returns the next numeric digit in the stream or -1 if timeout
public:
virtual int available() = 0;
virtual int read() = 0;
virtual int peek() = 0;
Stream() {_timeout=1000;}
// parsing methods
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
unsigned long getTimeout(void) { return _timeout; }
bool find(const char *target); // reads data from the stream until the target string is found
bool find(const uint8_t *target) { return find ((const char *)target); }
// returns true if target string is found, false if timed out (see setTimeout)
bool find(const char *target, size_t length); // reads data from the stream until the target string of given length is found
bool find(const uint8_t *target, size_t length) { return find ((const char *)target, length); }
// returns true if target string is found, false if timed out
bool find(char target) { return find (&target, 1); }
bool findUntil(const char *target, const char *terminator); // as find but search ends if the terminator string is found
bool findUntil(const uint8_t *target, const char *terminator) { return findUntil((const char *)target, terminator); }
bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen); // as above but search ends if the terminate string is found
bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) {return findUntil((const char *)target, targetLen, terminate, termLen); }
long parseInt(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR);
// returns the first valid (long) integer value from the current position.
// lookahead determines how parseInt looks ahead in the stream.
// See LookaheadMode enumeration at the top of the file.
// Lookahead is terminated by the first character that is not a valid part of an integer.
// Once parsing commences, 'ignore' will be skipped in the stream.
float parseFloat(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR);
// float version of parseInt
size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); }
// terminates if length characters have been read or timeout (see setTimeout)
// returns the number of characters placed in the buffer (0 means no valid data found)
size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character
size_t readBytesUntil( char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); }
// terminates if length characters have been read, timeout, or if the terminator character detected
// returns the number of characters placed in the buffer (0 means no valid data found)
// Arduino String functions to be added here
String readString();
String readStringUntil(char terminator);
protected:
long parseInt(char ignore) { return parseInt(SKIP_ALL, ignore); }
float parseFloat(char ignore) { return parseFloat(SKIP_ALL, ignore); }
// These overload exists for compatibility with any class that has derived
// Stream and used parseFloat/Int with a custom ignore character. To keep
// the public API simple, these overload remains protected.
struct MultiTarget {
const char *str; // string you're searching for
size_t len; // length of string you're searching for
size_t index; // index used by the search routine.
};
// This allows you to search for an arbitrary number of strings.
// Returns index of the target that is found first or -1 if timeout occurs.
int findMulti(struct MultiTarget *targets, int tCount);
};
#undef NO_IGNORE_CHAR
}
#include "../../../ArduinoCore-API/api/Stream.h"
+1 -768
View File
@@ -1,768 +1 @@
/*
String library for Wiring & Arduino
...mostly rewritten by Paul Stoffregen...
Copyright (c) 2009-10 Hernando Barragan. All rights reserved.
Copyright 2011, Paul Stoffregen, paul@pjrc.com
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "String.h"
#include "Common.h"
#include "itoa.h"
#include "deprecated-avr-comp/avr/dtostrf.h"
#include <float.h>
namespace arduino {
/*********************************************/
/* Static Member Initialisation */
/*********************************************/
size_t const String::FLT_MAX_DECIMAL_PLACES;
size_t const String::DBL_MAX_DECIMAL_PLACES;
/*********************************************/
/* Constructors */
/*********************************************/
String::String(const char *cstr)
{
init();
if (cstr) copy(cstr, strlen(cstr));
}
String::String(const char *cstr, unsigned int length)
{
init();
if (cstr) copy(cstr, length);
}
String::String(const String &value)
{
init();
*this = value;
}
String::String(const __FlashStringHelper *pstr)
{
init();
*this = pstr;
}
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
String::String(String &&rval)
{
init();
move(rval);
}
String::String(StringSumHelper &&rval)
{
init();
move(rval);
}
#endif
String::String(char c)
{
init();
char buf[2];
buf[0] = c;
buf[1] = 0;
*this = buf;
}
String::String(unsigned char value, unsigned char base)
{
init();
char buf[1 + 8 * sizeof(unsigned char)];
utoa(value, buf, base);
*this = buf;
}
String::String(int value, unsigned char base)
{
init();
char buf[2 + 8 * sizeof(int)];
itoa(value, buf, base);
*this = buf;
}
String::String(unsigned int value, unsigned char base)
{
init();
char buf[1 + 8 * sizeof(unsigned int)];
utoa(value, buf, base);
*this = buf;
}
String::String(long value, unsigned char base)
{
init();
char buf[2 + 8 * sizeof(long)];
ltoa(value, buf, base);
*this = buf;
}
String::String(unsigned long value, unsigned char base)
{
init();
char buf[1 + 8 * sizeof(unsigned long)];
ultoa(value, buf, base);
*this = buf;
}
String::String(float value, unsigned char decimalPlaces)
{
static size_t const FLOAT_BUF_SIZE = FLT_MAX_10_EXP + FLT_MAX_DECIMAL_PLACES + 1 /* '-' */ + 1 /* '.' */ + 1 /* '\0' */;
init();
char buf[FLOAT_BUF_SIZE];
decimalPlaces = min(decimalPlaces, FLT_MAX_DECIMAL_PLACES);
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
}
String::String(double value, unsigned char decimalPlaces)
{
static size_t const DOUBLE_BUF_SIZE = DBL_MAX_10_EXP + DBL_MAX_DECIMAL_PLACES + 1 /* '-' */ + 1 /* '.' */ + 1 /* '\0' */;
init();
char buf[DOUBLE_BUF_SIZE];
decimalPlaces = min(decimalPlaces, DBL_MAX_DECIMAL_PLACES);
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
}
String::~String()
{
if (buffer) free(buffer);
}
/*********************************************/
/* Memory Management */
/*********************************************/
inline void String::init(void)
{
buffer = NULL;
capacity = 0;
len = 0;
}
void String::invalidate(void)
{
if (buffer) free(buffer);
buffer = NULL;
capacity = len = 0;
}
unsigned char String::reserve(unsigned int size)
{
if (buffer && capacity >= size) return 1;
if (changeBuffer(size)) {
if (len == 0) buffer[0] = 0;
return 1;
}
return 0;
}
unsigned char String::changeBuffer(unsigned int maxStrLen)
{
char *newbuffer = (char *)realloc(buffer, maxStrLen + 1);
if (newbuffer) {
buffer = newbuffer;
capacity = maxStrLen;
return 1;
}
return 0;
}
/*********************************************/
/* Copy and Move */
/*********************************************/
String & String::copy(const char *cstr, unsigned int length)
{
if (!reserve(length)) {
invalidate();
return *this;
}
len = length;
memcpy(buffer, cstr, length);
buffer[len] = '\0';
return *this;
}
String & String::copy(const __FlashStringHelper *pstr, unsigned int length)
{
if (!reserve(length)) {
invalidate();
return *this;
}
len = length;
strcpy_P(buffer, (PGM_P)pstr);
return *this;
}
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
void String::move(String &rhs)
{
if (buffer) {
if (rhs && capacity >= rhs.len) {
memcpy(buffer, rhs.buffer, rhs.len);
len = rhs.len;
buffer[len] = '\0';
rhs.len = 0;
return;
} else {
free(buffer);
}
}
buffer = rhs.buffer;
capacity = rhs.capacity;
len = rhs.len;
rhs.buffer = NULL;
rhs.capacity = 0;
rhs.len = 0;
}
#endif
String & String::operator = (const String &rhs)
{
if (this == &rhs) return *this;
if (rhs.buffer) copy(rhs.buffer, rhs.len);
else invalidate();
return *this;
}
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
String & String::operator = (String &&rval)
{
if (this != &rval) move(rval);
return *this;
}
String & String::operator = (StringSumHelper &&rval)
{
if (this != &rval) move(rval);
return *this;
}
#endif
String & String::operator = (const char *cstr)
{
if (cstr) copy(cstr, strlen(cstr));
else invalidate();
return *this;
}
String & String::operator = (const __FlashStringHelper *pstr)
{
if (pstr) copy(pstr, strlen_P((PGM_P)pstr));
else invalidate();
return *this;
}
/*********************************************/
/* concat */
/*********************************************/
unsigned char String::concat(const String &s)
{
return concat(s.buffer, s.len);
}
unsigned char String::concat(const char *cstr, unsigned int length)
{
unsigned int newlen = len + length;
if (!cstr) return 0;
if (length == 0) return 1;
if (!reserve(newlen)) return 0;
memcpy(buffer + len, cstr, length);
len = newlen;
buffer[len] = '\0';
return 1;
}
unsigned char String::concat(const char *cstr)
{
if (!cstr) return 0;
return concat(cstr, strlen(cstr));
}
unsigned char String::concat(char c)
{
return concat(&c, 1);
}
unsigned char String::concat(unsigned char num)
{
char buf[1 + 3 * sizeof(unsigned char)];
itoa(num, buf, 10);
return concat(buf);
}
unsigned char String::concat(int num)
{
char buf[2 + 3 * sizeof(int)];
itoa(num, buf, 10);
return concat(buf);
}
unsigned char String::concat(unsigned int num)
{
char buf[1 + 3 * sizeof(unsigned int)];
utoa(num, buf, 10);
return concat(buf);
}
unsigned char String::concat(long num)
{
char buf[2 + 3 * sizeof(long)];
ltoa(num, buf, 10);
return concat(buf);
}
unsigned char String::concat(unsigned long num)
{
char buf[1 + 3 * sizeof(unsigned long)];
ultoa(num, buf, 10);
return concat(buf);
}
unsigned char String::concat(float num)
{
char buf[20];
char* string = dtostrf(num, 4, 2, buf);
return concat(string);
}
unsigned char String::concat(double num)
{
char buf[20];
char* string = dtostrf(num, 4, 2, buf);
return concat(string);
}
unsigned char String::concat(const __FlashStringHelper * str)
{
if (!str) return 0;
int length = strlen_P((const char *) str);
if (length == 0) return 1;
unsigned int newlen = len + length;
if (!reserve(newlen)) return 0;
strcpy_P(buffer + len, (const char *) str);
len = newlen;
return 1;
}
/*********************************************/
/* Concatenate */
/*********************************************/
StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(rhs.buffer, rhs.len)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!cstr || !a.concat(cstr)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, char c)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(c)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, int num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, long num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, float num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, double num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(rhs)) a.invalidate();
return a;
}
/*********************************************/
/* Comparison */
/*********************************************/
int String::compareTo(const String &s) const
{
if (!buffer || !s.buffer) {
if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer;
if (buffer && len > 0) return *(unsigned char *)buffer;
return 0;
}
return strcmp(buffer, s.buffer);
}
int String::compareTo(const char *cstr) const
{
if (!buffer || !cstr) {
if (cstr && *cstr) return 0 - *(unsigned char *)cstr;
if (buffer && len > 0) return *(unsigned char *)buffer;
return 0;
}
return strcmp(buffer, cstr);
}
unsigned char String::equals(const String &s2) const
{
return (len == s2.len && compareTo(s2) == 0);
}
unsigned char String::equals(const char *cstr) const
{
if (len == 0) return (cstr == NULL || *cstr == 0);
if (cstr == NULL) return buffer[0] == 0;
return strcmp(buffer, cstr) == 0;
}
unsigned char String::equalsIgnoreCase( const String &s2 ) const
{
if (this == &s2) return 1;
if (len != s2.len) return 0;
if (len == 0) return 1;
const char *p1 = buffer;
const char *p2 = s2.buffer;
while (*p1) {
if (tolower(*p1++) != tolower(*p2++)) return 0;
}
return 1;
}
unsigned char String::startsWith( const String &s2 ) const
{
if (len < s2.len) return 0;
return startsWith(s2, 0);
}
unsigned char String::startsWith( const String &s2, unsigned int offset ) const
{
if (offset > len - s2.len || !buffer || !s2.buffer) return 0;
return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0;
}
unsigned char String::endsWith( const String &s2 ) const
{
if ( len < s2.len || !buffer || !s2.buffer) return 0;
return strcmp(&buffer[len - s2.len], s2.buffer) == 0;
}
/*********************************************/
/* Character Access */
/*********************************************/
char String::charAt(unsigned int loc) const
{
return operator[](loc);
}
void String::setCharAt(unsigned int loc, char c)
{
if (loc < len) buffer[loc] = c;
}
char & String::operator[](unsigned int index)
{
static char dummy_writable_char;
if (index >= len || !buffer) {
dummy_writable_char = 0;
return dummy_writable_char;
}
return buffer[index];
}
char String::operator[]( unsigned int index ) const
{
if (index >= len || !buffer) return 0;
return buffer[index];
}
void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const
{
if (!bufsize || !buf) return;
if (index >= len) {
buf[0] = 0;
return;
}
unsigned int n = bufsize - 1;
if (n > len - index) n = len - index;
strncpy((char *)buf, buffer + index, n);
buf[n] = 0;
}
/*********************************************/
/* Search */
/*********************************************/
int String::indexOf(char c) const
{
return indexOf(c, 0);
}
int String::indexOf( char ch, unsigned int fromIndex ) const
{
if (fromIndex >= len) return -1;
const char* temp = strchr(buffer + fromIndex, ch);
if (temp == NULL) return -1;
return temp - buffer;
}
int String::indexOf(const String &s2) const
{
return indexOf(s2, 0);
}
int String::indexOf(const String &s2, unsigned int fromIndex) const
{
if (fromIndex >= len) return -1;
const char *found = strstr(buffer + fromIndex, s2.buffer);
if (found == NULL) return -1;
return found - buffer;
}
int String::lastIndexOf( char theChar ) const
{
return lastIndexOf(theChar, len - 1);
}
int String::lastIndexOf(char ch, unsigned int fromIndex) const
{
if (fromIndex >= len) return -1;
char tempchar = buffer[fromIndex + 1];
buffer[fromIndex + 1] = '\0';
char* temp = strrchr( buffer, ch );
buffer[fromIndex + 1] = tempchar;
if (temp == NULL) return -1;
return temp - buffer;
}
int String::lastIndexOf(const String &s2) const
{
return lastIndexOf(s2, len - s2.len);
}
int String::lastIndexOf(const String &s2, unsigned int fromIndex) const
{
if (s2.len == 0 || len == 0 || s2.len > len) return -1;
if (fromIndex >= len) fromIndex = len - 1;
int found = -1;
for (char *p = buffer; p <= buffer + fromIndex; p++) {
p = strstr(p, s2.buffer);
if (!p) break;
if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer;
}
return found;
}
String String::substring(unsigned int left, unsigned int right) const
{
if (left > right) {
unsigned int temp = right;
right = left;
left = temp;
}
String out;
if (left >= len) return out;
if (right > len) right = len;
out.copy(buffer + left, right - left);
return out;
}
/*********************************************/
/* Modification */
/*********************************************/
void String::replace(char find, char replace)
{
if (!buffer) return;
for (char *p = buffer; *p; p++) {
if (*p == find) *p = replace;
}
}
void String::replace(const String& find, const String& replace)
{
if (len == 0 || find.len == 0) return;
int diff = replace.len - find.len;
char *readFrom = buffer;
char *foundAt;
if (diff == 0) {
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
memcpy(foundAt, replace.buffer, replace.len);
readFrom = foundAt + replace.len;
}
} else if (diff < 0) {
unsigned int size = len; // compute size needed for result
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
readFrom = foundAt + find.len;
diff = 0 - diff;
size -= diff;
}
if (size == len) return;
int index = len - 1;
while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
readFrom = buffer + index + find.len;
memmove(readFrom - diff, readFrom, len - (readFrom - buffer));
len -= diff;
buffer[len] = 0;
memcpy(buffer + index, replace.buffer, replace.len);
index--;
}
} else {
unsigned int size = len; // compute size needed for result
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
readFrom = foundAt + find.len;
size += diff;
}
if (size == len) return;
if (size > capacity && !changeBuffer(size)) return; // XXX: tell user!
int index = len - 1;
while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
readFrom = buffer + index + find.len;
memmove(readFrom + diff, readFrom, len - (readFrom - buffer));
len += diff;
buffer[len] = 0;
memcpy(buffer + index, replace.buffer, replace.len);
index--;
}
}
}
void String::remove(unsigned int index){
// Pass the biggest integer as the count. The remove method
// below will take care of truncating it at the end of the
// string.
remove(index, (unsigned int)-1);
}
void String::remove(unsigned int index, unsigned int count){
if (index >= len) { return; }
if (count <= 0) { return; }
if (count > len - index) { count = len - index; }
char *writeTo = buffer + index;
len = len - count;
memmove(writeTo, buffer + index + count,len - index);
buffer[len] = 0;
}
void String::toLowerCase(void)
{
if (!buffer) return;
for (char *p = buffer; *p; p++) {
*p = tolower(*p);
}
}
void String::toUpperCase(void)
{
if (!buffer) return;
for (char *p = buffer; *p; p++) {
*p = toupper(*p);
}
}
void String::trim(void)
{
if (!buffer || len == 0) return;
char *begin = buffer;
while (isspace(*begin)) begin++;
char *end = buffer + len - 1;
while (isspace(*end) && end >= begin) end--;
len = end + 1 - begin;
if (begin > buffer) memmove(buffer, begin, len);
buffer[len] = 0;
}
/*********************************************/
/* Parsing / Conversion */
/*********************************************/
long String::toInt(void) const
{
if (buffer) return atol(buffer);
return 0;
}
float String::toFloat(void) const
{
return float(toDouble());
}
double String::toDouble(void) const
{
if (buffer) return atof(buffer);
return 0;
}
} // namespace arduino
#include "../../../ArduinoCore-API/api/String.cpp"
+2 -259
View File
@@ -1,259 +1,2 @@
/*
String library for Wiring & Arduino
...mostly rewritten by Paul Stoffregen...
Copyright (c) 2009-10 Hernando Barragan. All right reserved.
Copyright 2011, Paul Stoffregen, paul@pjrc.com
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef __cplusplus
#ifndef __ARDUINO_STRINGS__
#define __ARDUINO_STRINGS__
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#if defined(__AVR__)
#include "avr/pgmspace.h"
#else
#include "deprecated-avr-comp/avr/pgmspace.h"
#endif
namespace arduino {
// When compiling programs with this class, the following gcc parameters
// dramatically increase performance and memory (RAM) efficiency, typically
// with little or no increase in code size.
// -felide-constructors
// -std=c++0x
class __FlashStringHelper;
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
// An inherited class for holding the result of a concatenation. These
// result objects are assumed to be writable by subsequent concatenations.
class StringSumHelper;
// The string class
class String
{
friend class StringSumHelper;
// use a function pointer to allow for "if (s)" without the
// complications of an operator bool(). for more information, see:
// http://www.artima.com/cppsource/safebool.html
typedef void (String::*StringIfHelperType)() const;
void StringIfHelper() const {}
static size_t const FLT_MAX_DECIMAL_PLACES = 10;
static size_t const DBL_MAX_DECIMAL_PLACES = FLT_MAX_DECIMAL_PLACES;
public:
// constructors
// creates a copy of the initial value.
// if the initial value is null or invalid, or if memory allocation
// fails, the string will be marked as invalid (i.e. "if (s)" will
// be false).
String(const char *cstr = "");
String(const char *cstr, unsigned int length);
String(const uint8_t *cstr, unsigned int length) : String((const char*)cstr, length) {}
String(const String &str);
String(const __FlashStringHelper *str);
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
String(String &&rval);
String(StringSumHelper &&rval);
#endif
explicit String(char c);
explicit String(unsigned char, unsigned char base=10);
explicit String(int, unsigned char base=10);
explicit String(unsigned int, unsigned char base=10);
explicit String(long, unsigned char base=10);
explicit String(unsigned long, unsigned char base=10);
explicit String(float, unsigned char decimalPlaces=2);
explicit String(double, unsigned char decimalPlaces=2);
~String(void);
// memory management
// return true on success, false on failure (in which case, the string
// is left unchanged). reserve(0), if successful, will validate an
// invalid string (i.e., "if (s)" will be true afterwards)
unsigned char reserve(unsigned int size);
inline unsigned int length(void) const {return len;}
// creates a copy of the assigned value. if the value is null or
// invalid, or if the memory allocation fails, the string will be
// marked as invalid ("if (s)" will be false).
String & operator = (const String &rhs);
String & operator = (const char *cstr);
String & operator = (const __FlashStringHelper *str);
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
String & operator = (String &&rval);
String & operator = (StringSumHelper &&rval);
#endif
// concatenate (works w/ built-in types)
// returns true on success, false on failure (in which case, the string
// is left unchanged). if the argument is null or invalid, the
// concatenation is considered unsucessful.
unsigned char concat(const String &str);
unsigned char concat(const char *cstr);
unsigned char concat(const char *cstr, unsigned int length);
unsigned char concat(const uint8_t *cstr, unsigned int length) {return concat((const char*)cstr, length);}
unsigned char concat(char c);
unsigned char concat(unsigned char num);
unsigned char concat(int num);
unsigned char concat(unsigned int num);
unsigned char concat(long num);
unsigned char concat(unsigned long num);
unsigned char concat(float num);
unsigned char concat(double num);
unsigned char concat(const __FlashStringHelper * str);
// if there's not enough memory for the concatenated value, the string
// will be left unchanged (but this isn't signalled in any way)
String & operator += (const String &rhs) {concat(rhs); return (*this);}
String & operator += (const char *cstr) {concat(cstr); return (*this);}
String & operator += (char c) {concat(c); return (*this);}
String & operator += (unsigned char num) {concat(num); return (*this);}
String & operator += (int num) {concat(num); return (*this);}
String & operator += (unsigned int num) {concat(num); return (*this);}
String & operator += (long num) {concat(num); return (*this);}
String & operator += (unsigned long num) {concat(num); return (*this);}
String & operator += (float num) {concat(num); return (*this);}
String & operator += (double num) {concat(num); return (*this);}
String & operator += (const __FlashStringHelper *str){concat(str); return (*this);}
friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs);
friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr);
friend StringSumHelper & operator + (const StringSumHelper &lhs, char c);
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, int num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, long num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, float num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, double num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs);
// comparison (only works w/ Strings and "strings")
operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; }
int compareTo(const String &s) const;
int compareTo(const char *cstr) const;
unsigned char equals(const String &s) const;
unsigned char equals(const char *cstr) const;
friend unsigned char operator == (const String &a, const String &b) { return a.equals(b); }
friend unsigned char operator == (const String &a, const char *b) { return a.equals(b); }
friend unsigned char operator == (const char *a, const String &b) { return b == a; }
friend unsigned char operator < (const String &a, const String &b) { return a.compareTo(b) < 0; }
friend unsigned char operator < (const String &a, const char *b) { return a.compareTo(b) < 0; }
friend unsigned char operator < (const char *a, const String &b) { return b.compareTo(a) > 0; }
friend unsigned char operator != (const String &a, const String &b) { return !(a == b); }
friend unsigned char operator != (const String &a, const char *b) { return !(a == b); }
friend unsigned char operator != (const char *a, const String &b) { return !(a == b); }
friend unsigned char operator > (const String &a, const String &b) { return b < a; }
friend unsigned char operator > (const String &a, const char *b) { return b < a; }
friend unsigned char operator > (const char *a, const String &b) { return b < a; }
friend unsigned char operator <= (const String &a, const String &b) { return !(b < a); }
friend unsigned char operator <= (const String &a, const char *b) { return !(b < a); }
friend unsigned char operator <= (const char *a, const String &b) { return !(b < a); }
friend unsigned char operator >= (const String &a, const String &b) { return !(a < b); }
friend unsigned char operator >= (const String &a, const char *b) { return !(a < b); }
friend unsigned char operator >= (const char *a, const String &b) { return !(a < b); }
unsigned char equalsIgnoreCase(const String &s) const;
unsigned char startsWith( const String &prefix) const;
unsigned char startsWith(const String &prefix, unsigned int offset) const;
unsigned char endsWith(const String &suffix) const;
// character acccess
char charAt(unsigned int index) const;
void setCharAt(unsigned int index, char c);
char operator [] (unsigned int index) const;
char& operator [] (unsigned int index);
void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const;
void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const
{ getBytes((unsigned char *)buf, bufsize, index); }
const char* c_str() const { return buffer; }
char* begin() { return buffer; }
char* end() { return buffer + length(); }
const char* begin() const { return c_str(); }
const char* end() const { return c_str() + length(); }
// search
int indexOf( char ch ) const;
int indexOf( char ch, unsigned int fromIndex ) const;
int indexOf( const String &str ) const;
int indexOf( const String &str, unsigned int fromIndex ) const;
int lastIndexOf( char ch ) const;
int lastIndexOf( char ch, unsigned int fromIndex ) const;
int lastIndexOf( const String &str ) const;
int lastIndexOf( const String &str, unsigned int fromIndex ) const;
String substring( unsigned int beginIndex ) const { return substring(beginIndex, len); };
String substring( unsigned int beginIndex, unsigned int endIndex ) const;
// modification
void replace(char find, char replace);
void replace(const String& find, const String& replace);
void remove(unsigned int index);
void remove(unsigned int index, unsigned int count);
void toLowerCase(void);
void toUpperCase(void);
void trim(void);
// parsing/conversion
long toInt(void) const;
float toFloat(void) const;
double toDouble(void) const;
protected:
char *buffer; // the actual char array
unsigned int capacity; // the array length minus one (for the '\0')
unsigned int len; // the String length (not counting the '\0')
protected:
void init(void);
void invalidate(void);
unsigned char changeBuffer(unsigned int maxStrLen);
// copy and move
String & copy(const char *cstr, unsigned int length);
String & copy(const __FlashStringHelper *pstr, unsigned int length);
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
void move(String &rhs);
#endif
};
class StringSumHelper : public String
{
public:
StringSumHelper(const String &s) : String(s) {}
StringSumHelper(const char *p) : String(p) {}
StringSumHelper(char c) : String(c) {}
StringSumHelper(unsigned char num) : String(num) {}
StringSumHelper(int num) : String(num) {}
StringSumHelper(unsigned int num) : String(num) {}
StringSumHelper(long num) : String(num) {}
StringSumHelper(unsigned long num) : String(num) {}
StringSumHelper(float num) : String(num) {}
StringSumHelper(double num) : String(num) {}
};
} // namespace arduino
#endif // __cplusplus
#endif // __ARDUINO_STRINGS__
#pragma once
#include "../../../ArduinoCore-API/api/String.h"
+2 -64
View File
@@ -1,64 +1,2 @@
/*
USBAPI.h
Copyright (c) 2005-2014 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __USBAPI__
#define __USBAPI__
#include <stdint.h>
namespace arduino {
//================================================================================
//================================================================================
// Low level API
typedef struct __attribute__((packed))
{
union {
uint8_t bmRequestType;
struct {
uint8_t direction : 5;
uint8_t type : 2;
uint8_t transferDirection : 1;
};
};
uint8_t bRequest;
uint8_t wValueL;
uint8_t wValueH;
uint16_t wIndex;
uint16_t wLength;
} USBSetup;
}
//================================================================================
// USB APIs (C scope)
//================================================================================
int USB_SendControl(uint8_t flags, const void* d, int len);
int USB_RecvControl(void* d, int len);
int USB_RecvControlLong(void* d, int len);
uint8_t USB_Available(uint8_t ep);
uint8_t USB_SendSpace(uint8_t ep);
int USB_Send(uint8_t ep, const void* data, int len); // blocking
int USB_Recv(uint8_t ep, void* data, int len); // non-blocking
int USB_Recv(uint8_t ep); // non-blocking
void USB_Flush(uint8_t ep);
#endif
#pragma once
#include "../../../ArduinoCore-API/api/USBAPI.h"
+1 -91
View File
@@ -1,92 +1,2 @@
/*
* Udp.cpp: Library to send/receive UDP packets.
*
* NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these)
* 1) UDP does not guarantee the order in which assembled UDP packets are received. This
* might not happen often in practice, but in larger network topologies, a UDP
* packet can be received out of sequence.
* 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being
* aware of it. Again, this may not be a concern in practice on small local networks.
* For more information, see http://www.cafeaulait.org/course/week12/35.html
*
* MIT License:
* Copyright (c) 2008 Bjoern Hartmann
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* bjoern@cs.stanford.edu 12/30/2008
*/
#pragma once
#include "Stream.h"
#include "IPAddress.h"
namespace arduino {
class UDP : public Stream {
public:
virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
virtual uint8_t beginMulticast(IPAddress, uint16_t) { return 0; } // initialize, start listening on specified multicast IP address and port. Returns 1 if successful, 0 on failure
virtual void stop() =0; // Finish with the UDP socket
// Sending UDP packets
// Start building up a packet to send to the remote host specific in ip and port
// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
virtual int beginPacket(IPAddress ip, uint16_t port) =0;
// Start building up a packet to send to the remote host specific in host and port
// Returns 1 if successful, 0 if there was a problem resolving the hostname or port
virtual int beginPacket(const char *host, uint16_t port) =0;
// Finish off this packet and send it
// Returns 1 if the packet was sent successfully, 0 if there was an error
virtual int endPacket() =0;
// Write a single byte into the packet
virtual size_t write(uint8_t) =0;
// Write size bytes from buffer into the packet
virtual size_t write(const uint8_t *buffer, size_t size) =0;
// Start processing the next available incoming packet
// Returns the size of the packet in bytes, or 0 if no packets are available
virtual int parsePacket() =0;
// Number of bytes remaining in the current packet
virtual int available() =0;
// Read a single byte from the current packet
virtual int read() =0;
// Read up to len bytes from the current packet and place them into buffer
// Returns the number of bytes read, or 0 if none are available
virtual int read(unsigned char* buffer, size_t len) =0;
// Read up to len characters from the current packet and place them into buffer
// Returns the number of characters read, or 0 if none are available
virtual int read(char* buffer, size_t len) =0;
// Return the next byte from the current packet without moving on to the next byte
virtual int peek() =0;
virtual void flush() =0; // Finish reading the current packet
// Return the IP address of the host who sent the current incoming packet
virtual IPAddress remoteIP() =0;
// Return the port of the host who sent the current incoming packet
virtual uint16_t remotePort() =0;
protected:
uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); };
};
}
using namespace arduino;
#include "../../../ArduinoCore-API/api/Udp.h"
+2 -171
View File
@@ -1,171 +1,2 @@
/*
WCharacter.h - Character utility functions for Wiring & Arduino
Copyright (c) 2010 Hernando Barragan. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef Character_h
#define Character_h
#include <ctype.h>
namespace arduino {
// WCharacter.h prototypes
inline bool isAlphaNumeric(int c) __attribute__((always_inline));
inline bool isAlpha(int c) __attribute__((always_inline));
inline bool isAscii(int c) __attribute__((always_inline));
inline bool isWhitespace(int c) __attribute__((always_inline));
inline bool isControl(int c) __attribute__((always_inline));
inline bool isDigit(int c) __attribute__((always_inline));
inline bool isGraph(int c) __attribute__((always_inline));
inline bool isLowerCase(int c) __attribute__((always_inline));
inline bool isPrintable(int c) __attribute__((always_inline));
inline bool isPunct(int c) __attribute__((always_inline));
inline bool isSpace(int c) __attribute__((always_inline));
inline bool isUpperCase(int c) __attribute__((always_inline));
inline bool isHexadecimalDigit(int c) __attribute__((always_inline));
inline int toAscii(int c) __attribute__((always_inline));
inline int toLowerCase(int c) __attribute__((always_inline));
inline int toUpperCase(int c)__attribute__((always_inline));
// Checks for an alphanumeric character.
// It is equivalent to (isalpha(c) || isdigit(c)).
inline bool isAlphaNumeric(int c)
{
return ( isalnum(c) == 0 ? false : true);
}
// Checks for an alphabetic character.
// It is equivalent to (isupper(c) || islower(c)).
inline bool isAlpha(int c)
{
return ( isalpha(c) == 0 ? false : true);
}
// Checks whether c is a 7-bit unsigned char value
// that fits into the ASCII character set.
inline bool isAscii(int c)
{
return ( isascii (c) == 0 ? false : true);
}
// Checks for a blank character, that is, a space or a tab.
inline bool isWhitespace(int c)
{
return ( isblank (c) == 0 ? false : true);
}
// Checks for a control character.
inline bool isControl(int c)
{
return ( iscntrl (c) == 0 ? false : true);
}
// Checks for a digit (0 through 9).
inline bool isDigit(int c)
{
return ( isdigit (c) == 0 ? false : true);
}
// Checks for any printable character except space.
inline bool isGraph(int c)
{
return ( isgraph (c) == 0 ? false : true);
}
// Checks for a lower-case character.
inline bool isLowerCase(int c)
{
return (islower (c) == 0 ? false : true);
}
// Checks for any printable character including space.
inline bool isPrintable(int c)
{
return ( isprint (c) == 0 ? false : true);
}
// Checks for any printable character which is not a space
// or an alphanumeric character.
inline bool isPunct(int c)
{
return ( ispunct (c) == 0 ? false : true);
}
// Checks for white-space characters. For the avr-libc library,
// these are: space, formfeed ('\f'), newline ('\n'), carriage
// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v').
inline bool isSpace(int c)
{
return ( isspace (c) == 0 ? false : true);
}
// Checks for an uppercase letter.
inline bool isUpperCase(int c)
{
return ( isupper (c) == 0 ? false : true);
}
// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7
// 8 9 a b c d e f A B C D E F.
inline bool isHexadecimalDigit(int c)
{
return ( isxdigit (c) == 0 ? false : true);
}
// Converts c to a 7-bit unsigned char value that fits into the
// ASCII character set, by clearing the high-order bits.
inline int toAscii(int c)
{
return toascii (c);
}
// Warning:
// Many people will be unhappy if you use this function.
// This function will convert accented letters into random
// characters.
// Converts the letter c to lower case, if possible.
inline int toLowerCase(int c)
{
return tolower (c);
}
// Converts the letter c to upper case, if possible.
inline int toUpperCase(int c)
{
return toupper (c);
}
}
#endif
#pragma once
#include "../../../ArduinoCore-API/api/WCharacter.h"
@@ -1,37 +1 @@
/*
dtostrf - Emulation for dtostrf function from avr-libc
Copyright (c) 2016 Arduino LLC. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// This is a default implementation for dtostrf function.
// This file should be used if the standard lib doesn't provide an
// implementation of dtostrf.
// Create a file called "dtostrf.c" with the following include:
// #include "api/deprecated-avr-comp/avr/dtostrf.c.impl"
#include <stdio.h>
char *dtostrf (double val, signed char width, unsigned char prec, char *sout) {
asm(".global _printf_float");
char fmt[20];
sprintf(fmt, "%%%d.%df", width, prec);
sprintf(sout, fmt, val);
return sout;
}
#include "../../../../../ArduinoCore-API/api/deprecated-avr-comp/avr/dtostrf.c.impl"
@@ -1,34 +1,2 @@
/*
dtostrf - Emulation for dtostrf function from avr-libc
Copyright (c) 2015 Arduino LLC. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#if !defined(ARDUINO_ARCH_AVR)
#ifdef __cplusplus
extern "C" {
#endif
char *dtostrf(double val, signed char width, unsigned char prec, char *sout);
#ifdef __cplusplus
}
#endif
#endif
#include "../../../../../ArduinoCore-API/api/deprecated-avr-comp/avr/dtostrf.h"
@@ -1,23 +1,2 @@
/*
Copyright (c) 2015 Arduino LCC. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
Empty file.
This file is here to allow compatibility with sketches (made for AVR)
that includes <AVR/interrupt.h>
*/
#pragma once
#include "../../../../../ArduinoCore-API/api/deprecated-avr-comp/avr/interrupt.h"
@@ -1,142 +1,2 @@
/*
pgmspace.h - Definitions for compatibility with AVR pgmspace macros
Copyright (c) 2015 Arduino LLC
Based on work of Paul Stoffregen on Teensy 3 (http://pjrc.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE
*/
#ifndef __PGMSPACE_H_
#define __PGMSPACE_H_ 1
#include <inttypes.h>
#define PROGMEM
#define PGM_P const char *
#define PSTR(str) (str)
#define _SFR_BYTE(n) (n)
typedef void prog_void;
typedef char prog_char;
typedef unsigned char prog_uchar;
typedef int8_t prog_int8_t;
typedef uint8_t prog_uint8_t;
typedef int16_t prog_int16_t;
typedef uint16_t prog_uint16_t;
typedef int32_t prog_int32_t;
typedef uint32_t prog_uint32_t;
typedef int64_t prog_int64_t;
typedef uint64_t prog_uint64_t;
typedef const void* int_farptr_t;
typedef const void* uint_farptr_t;
#define memchr_P(s, c, n) memchr((s), (c), (n))
#define memcmp_P(s1, s2, n) memcmp((s1), (s2), (n))
#define memccpy_P(dest, src, c, n) memccpy((dest), (src), (c), (n))
#define memcpy_P(dest, src, n) memcpy((dest), (src), (n))
#define memmem_P(haystack, haystacklen, needle, needlelen) memmem((haystack), (haystacklen), (needle), (needlelen))
#define memrchr_P(s, c, n) memrchr((s), (c), (n))
#define strcat_P(dest, src) strcat((dest), (src))
#define strchr_P(s, c) strchr((s), (c))
#define strchrnul_P(s, c) strchrnul((s), (c))
#define strcmp_P(a, b) strcmp((a), (b))
#define strcpy_P(dest, src) strcpy((dest), (src))
#define strcasecmp_P(s1, s2) strcasecmp((s1), (s2))
#define strcasestr_P(haystack, needle) strcasestr((haystack), (needle))
#define strcspn_P(s, accept) strcspn((s), (accept))
#define strlcat_P(s1, s2, n) strlcat((s1), (s2), (n))
#define strlcpy_P(s1, s2, n) strlcpy((s1), (s2), (n))
#define strlen_P(a) strlen((a))
#define strnlen_P(s, n) strnlen((s), (n))
#define strncmp_P(s1, s2, n) strncmp((s1), (s2), (n))
#define strncasecmp_P(s1, s2, n) strncasecmp((s1), (s2), (n))
#define strncat_P(s1, s2, n) strncat((s1), (s2), (n))
#define strncpy_P(s1, s2, n) strncpy((s1), (s2), (n))
#define strpbrk_P(s, accept) strpbrk((s), (accept))
#define strrchr_P(s, c) strrchr((s), (c))
#define strsep_P(sp, delim) strsep((sp), (delim))
#define strspn_P(s, accept) strspn((s), (accept))
#define strstr_P(a, b) strstr((a), (b))
#define strtok_P(s, delim) strtok((s), (delim))
#define strtok_rP(s, delim, last) strtok((s), (delim), (last))
#define strlen_PF(a) strlen((a))
#define strnlen_PF(src, len) strnlen((src), (len))
#define memcpy_PF(dest, src, len) memcpy((dest), (src), (len))
#define strcpy_PF(dest, src) strcpy((dest), (src))
#define strncpy_PF(dest, src, len) strncpy((dest), (src), (len))
#define strcat_PF(dest, src) strcat((dest), (src))
#define strlcat_PF(dest, src, len) strlcat((dest), (src), (len))
#define strncat_PF(dest, src, len) strncat((dest), (src), (len))
#define strcmp_PF(s1, s2) strcmp((s1), (s2))
#define strncmp_PF(s1, s2, n) strncmp((s1), (s2), (n))
#define strcasecmp_PF(s1, s2) strcasecmp((s1), (s2))
#define strncasecmp_PF(s1, s2, n) strncasecmp((s1), (s2), (n))
#define strstr_PF(s1, s2) strstr((s1), (s2))
#define strlcpy_PF(dest, src, n) strlcpy((dest), (src), (n))
#define memcmp_PF(s1, s2, n) memcmp((s1), (s2), (n))
#define sprintf_P(s, f, ...) sprintf((s), (f), __VA_ARGS__)
#define snprintf_P(s, f, ...) snprintf((s), (f), __VA_ARGS__)
#define vsprintf_P(s, f, ...) vsprintf((s), (f), __VA_ARGS__)
#define vsnprintf_P(s, f, ...) vsnprintf((s), (f), __VA_ARGS__)
#if 0
// Requires natural aligned addresses
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#define pgm_read_word(addr) (*(const unsigned short *)(addr))
#define pgm_read_dword(addr) (*(const unsigned long *)(addr))
#define pgm_read_float(addr) (*(const float *)(addr))
#define pgm_read_ptr(addr) (*(void *const *)(addr))
#else
// Supports misaligned addresses
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#define pgm_read_word(addr) ((unsigned short)(pgm_read_byte((intptr_t)addr) | (pgm_read_byte((intptr_t)addr + 1) << 8)))
#define pgm_read_dword(addr) ((unsigned long)(pgm_read_byte((intptr_t)addr) | (pgm_read_byte((intptr_t)addr + 1) << 8)) | \
(pgm_read_byte((intptr_t)addr + 2) << 16) | (pgm_read_byte((intptr_t)addr + 3) << 24))
#define pgm_read_ptr(addr) ((void *)pgm_read_dword(addr))
static inline float pgm_read_float(const void *addr) {
union {
void *p;
float f;
} x;
x.p = pgm_read_ptr(addr);
return x.f;
}
#endif
#define pgm_read_byte_near(addr) pgm_read_byte(addr)
#define pgm_read_word_near(addr) pgm_read_word(addr)
#define pgm_read_dword_near(addr) pgm_read_dword(addr)
#define pgm_read_float_near(addr) pgm_read_float(addr)
#define pgm_read_ptr_near(addr) pgm_read_ptr(addr)
#define pgm_read_byte_far(addr) pgm_read_byte(addr)
#define pgm_read_word_far(addr) pgm_read_word(addr)
#define pgm_read_dword_far(addr) pgm_read_dword(addr)
#define pgm_read_float_far(addr) pgm_read_float(addr)
#define pgm_read_ptr_far(addr) pgm_read_ptr(addr)
#define pgm_get_far_address(addr) (&(addr))
#endif
#pragma once
#include "../../../../../ArduinoCore-API/api/deprecated-avr-comp/avr/pgmspace.h"
+1 -36
View File
@@ -1,37 +1,2 @@
/*
Copyright (c) 2016 Arduino LLC. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
// Standard C functions required in Arduino API
// If these functions are not provided by the standard library, the
// core should supply an implementation of them.
#ifdef __cplusplus
extern "C" {
#endif
extern char* itoa(int value, char *string, int radix);
extern char* ltoa(long value, char *string, int radix);
extern char* utoa(unsigned value, char *string, int radix);
extern char* ultoa(unsigned long value, char *string, int radix);
#ifdef __cplusplus
} // extern "C"
#endif
#include "../../../ArduinoCore-API/api/itoa.h"
+62
View File
@@ -0,0 +1,62 @@
; Cycle Count for the Raspberry Pi Pico RP2040
;
; Copyright (c) 2022 Earle F. Philhower, III <earlephilhower@yahoo.com>
;
; This library is free software; you can redistribute it and/or
; modify it under the terms of the GNU Lesser General Public
; License as published by the Free Software Foundation; either
; version 2.1 of the License, or (at your option) any later version.
;
; This library is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
; Lesser General Public License for more details.
;
; You should have received a copy of the GNU Lesser General Public
; License along with this library; if not, write to the Free Software
; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
; Cycle count is stored in {-y, -x}
.program ccount
cnt:
jmp x-- cnt
epoch:
jmp y-- cnt
% c-sdk {
static inline void ccount_program_init(PIO pio, uint sm, uint offset) {
pio_sm_config c = ccount_program_get_default_config(offset);
pio_sm_init(pio, sm, offset, &c);
pio_sm_exec(pio, sm, pio_encode_set(pio_x, 0));
pio_sm_exec(pio, sm, pio_encode_set(pio_y, 0));
}
static inline uint64_t ccount_read(PIO pio, uint sm) {
static uint64_t extra = 0;
// Guard against having the epoch rollover while we're reading the time.
// If epoch2 != epoch1, we looped in middle and get new LSW
pio_sm_exec(pio, sm, pio_encode_mov(pio_isr, pio_y));
pio_sm_exec(pio, sm, pio_encode_push(false, false));
pio_sm_exec(pio, sm, pio_encode_mov(pio_isr, pio_x));
pio_sm_exec(pio, sm, pio_encode_push(false, false));
pio_sm_exec(pio, sm, pio_encode_mov(pio_isr, pio_y));
pio_sm_exec(pio, sm, pio_encode_push(false, false));
pio_sm_exec(pio, sm, pio_encode_mov(pio_isr, pio_x));
pio_sm_exec(pio, sm, pio_encode_push(false, false));
extra += 8;
uint32_t y1 = -((int)pio_sm_get_blocking(pio, sm));
uint32_t x1 = -((int)pio_sm_get_blocking(pio, sm));
uint32_t y2 = -((int)pio_sm_get_blocking(pio, sm));
uint32_t x2 = -((int)pio_sm_get_blocking(pio, sm));
uint64_t val;
if (y2 != y1) {
val = ((((uint64_t)y2) << 32LL) | x2) + y2 /* adjust for missed cycle every epoch increment */;
} else {
val = ((((uint64_t)y1) << 32LL) | x1) + y1 /* adjust for missed cycle every epoch increment */;
}
return val + extra;
}
%}
+71
View File
@@ -0,0 +1,71 @@
// -------------------------------------------------- //
// This file is autogenerated by pioasm; do not edit! //
// -------------------------------------------------- //
#pragma once
#if !PICO_NO_HARDWARE
#include "hardware/pio.h"
#endif
// ------ //
// ccount //
// ------ //
#define ccount_wrap_target 0
#define ccount_wrap 1
static const uint16_t ccount_program_instructions[] = {
// .wrap_target
0x0040, // 0: jmp x--, 0
0x0080, // 1: jmp y--, 0
// .wrap
};
#if !PICO_NO_HARDWARE
static const struct pio_program ccount_program = {
.instructions = ccount_program_instructions,
.length = 2,
.origin = -1,
};
static inline pio_sm_config ccount_program_get_default_config(uint offset) {
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_wrap(&c, offset + ccount_wrap_target, offset + ccount_wrap);
return c;
}
static inline void ccount_program_init(PIO pio, uint sm, uint offset) {
pio_sm_config c = ccount_program_get_default_config(offset);
pio_sm_init(pio, sm, offset, &c);
pio_sm_exec(pio, sm, pio_encode_set(pio_x, 0));
pio_sm_exec(pio, sm, pio_encode_set(pio_y, 0));
}
static inline uint64_t ccount_read(PIO pio, uint sm) {
static uint64_t extra = 0;
// Guard against having the epoch rollover while we're reading the time.
// If epoch2 != epoch1, we looped in middle and get new LSW
pio_sm_exec(pio, sm, pio_encode_mov(pio_isr, pio_y));
pio_sm_exec(pio, sm, pio_encode_push(false, false));
pio_sm_exec(pio, sm, pio_encode_mov(pio_isr, pio_x));
pio_sm_exec(pio, sm, pio_encode_push(false, false));
pio_sm_exec(pio, sm, pio_encode_mov(pio_isr, pio_y));
pio_sm_exec(pio, sm, pio_encode_push(false, false));
pio_sm_exec(pio, sm, pio_encode_mov(pio_isr, pio_x));
pio_sm_exec(pio, sm, pio_encode_push(false, false));
extra += 8;
uint32_t y1 = -((int)pio_sm_get_blocking(pio, sm));
uint32_t x1 = -((int)pio_sm_get_blocking(pio, sm));
uint32_t y2 = -((int)pio_sm_get_blocking(pio, sm));
uint32_t x2 = -((int)pio_sm_get_blocking(pio, sm));
uint64_t val;
if (y2 != y1) {
val = ((((uint64_t)y2) << 32LL) | x2) + y2 /* adjust for missed cycle every epoch increment */;
} else {
val = ((((uint64_t)y1) << 32LL) | x1) + y1 /* adjust for missed cycle every epoch increment */;
}
return val + extra;
}
#endif
+3
View File
@@ -25,6 +25,9 @@
#include "Adafruit_TinyUSB_API.h"
#endif
extern "C" void delay(unsigned long ms) __attribute__((weak));
extern "C" void yield() __attribute__((weak));
extern "C"
{
+7
View File
@@ -0,0 +1,7 @@
libb64: Base64 Encoding/Decoding Routines
======================================
Authors:
-------
Chris Venter chris.venter@gmail.com http://rocketpod.blogspot.com
+29
View File
@@ -0,0 +1,29 @@
Copyright-Only Dedication (based on United States law)
or Public Domain Certification
The person or persons who have associated work with this document (the
"Dedicator" or "Certifier") hereby either (a) certifies that, to the best of
his knowledge, the work of authorship identified is in the public domain of the
country from which the work is published, or (b) hereby dedicates whatever
copyright the dedicators holds in the work of authorship identified below (the
"Work") to the public domain. A certifier, moreover, dedicates any copyright
interest he may have in the associated work, and for these purposes, is
described as a "dedicator" below.
A certifier has taken reasonable steps to verify the copyright status of this
work. Certifier recognizes that his good faith efforts may not shield him from
liability if in fact the work certified is not in the public domain.
Dedicator makes this dedication for the benefit of the public at large and to
the detriment of the Dedicator's heirs and successors. Dedicator intends this
dedication to be an overt act of relinquishment in perpetuity of all present
and future rights under copyright law, whether vested or contingent, in the
Work. Dedicator understands that such relinquishment of all rights includes
the relinquishment of all rights to enforce (by lawsuit or otherwise) those
copyrights in the Work.
Dedicator recognizes that, once placed in the public domain, the Work may be
freely reproduced, distributed, transmitted, used, modified, built upon, or
otherwise exploited by anyone for any purpose, commercial or non-commercial,
and in any way, including by methods that have not yet been invented or
conceived.
+111
View File
@@ -0,0 +1,111 @@
/*
cdecoder.c - c source to a base64 decoding algorithm implementation
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#include <pgmspace.h>
#include <stdint.h>
#include "cdecode.h"
extern "C" {
static int base64_decode_value_signed(int8_t value_in) {
static const int8_t decoding[] PROGMEM = {62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51};
static const int8_t decoding_size = sizeof(decoding);
value_in -= 43;
if (value_in < 0 || value_in > decoding_size) {
return -1;
}
return pgm_read_byte(&decoding[(int)value_in]);
}
void base64_init_decodestate(base64_decodestate* state_in) {
state_in->step = step_a;
state_in->plainchar = 0;
}
static int base64_decode_block_signed(const int8_t* code_in, const int length_in, int8_t* plaintext_out, base64_decodestate* state_in) {
const int8_t* codechar = code_in;
int8_t* plainchar = plaintext_out;
int8_t fragment;
*plainchar = state_in->plainchar;
switch (state_in->step) {
while (1) {
case step_a:
do {
if (codechar == code_in + length_in) {
state_in->step = step_a;
state_in->plainchar = *plainchar;
return plainchar - plaintext_out;
}
fragment = (int8_t)base64_decode_value_signed(*codechar++);
} while (fragment < 0);
*plainchar = (fragment & 0x03f) << 2;
// falls through
case step_b:
do {
if (codechar == code_in + length_in) {
state_in->step = step_b;
state_in->plainchar = *plainchar;
return plainchar - plaintext_out;
}
fragment = (int8_t)base64_decode_value_signed(*codechar++);
} while (fragment < 0);
*plainchar++ |= (fragment & 0x030) >> 4;
*plainchar = (fragment & 0x00f) << 4;
// falls through
case step_c:
do {
if (codechar == code_in + length_in) {
state_in->step = step_c;
state_in->plainchar = *plainchar;
return plainchar - plaintext_out;
}
fragment = (int8_t)base64_decode_value_signed(*codechar++);
} while (fragment < 0);
*plainchar++ |= (fragment & 0x03c) >> 2;
*plainchar = (fragment & 0x003) << 6;
// falls through
case step_d:
do {
if (codechar == code_in + length_in) {
state_in->step = step_d;
state_in->plainchar = *plainchar;
return plainchar - plaintext_out;
}
fragment = (int8_t)base64_decode_value_signed(*codechar++);
} while (fragment < 0);
*plainchar++ |= (fragment & 0x03f);
}
}
/* control should not reach here */
return plainchar - plaintext_out;
}
static int base64_decode_chars_signed(const int8_t* code_in, const int length_in, int8_t* plaintext_out) {
base64_decodestate _state;
base64_init_decodestate(&_state);
int len = base64_decode_block_signed(code_in, length_in, plaintext_out, &_state);
if (len > 0) {
plaintext_out[len] = 0;
}
return len;
}
int base64_decode_value(char value_in) {
return base64_decode_value_signed(*((int8_t *) &value_in));
}
int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in) {
return base64_decode_block_signed((int8_t *) code_in, length_in, (int8_t *) plaintext_out, state_in);
}
int base64_decode_chars(const char* code_in, const int length_in, char* plaintext_out) {
return base64_decode_chars_signed((int8_t *) code_in, length_in, (int8_t *) plaintext_out);
}
};
+35
View File
@@ -0,0 +1,35 @@
/*
cdecode.h - c header for a base64 decoding algorithm
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#pragma once
#define base64_decode_expected_len(n) ((n * 3) / 4)
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
step_a, step_b, step_c, step_d
} base64_decodestep;
typedef struct {
base64_decodestep step;
char plainchar;
} base64_decodestate;
void base64_init_decodestate(base64_decodestate* state_in);
int base64_decode_value(char value_in);
int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in);
int base64_decode_chars(const char* code_in, const int length_in, char* plaintext_out);
#ifdef __cplusplus
} // extern "C"
#endif
+126
View File
@@ -0,0 +1,126 @@
/*
cencoder.c - c source to a base64 encoding algorithm implementation
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#include "cencode.h"
extern "C" {
void base64_init_encodestate(base64_encodestate* state_in) {
state_in->step = step_A;
state_in->result = 0;
state_in->stepcount = 0;
state_in->stepsnewline = BASE64_CHARS_PER_LINE;
}
void base64_init_encodestate_nonewlines(base64_encodestate* state_in) {
base64_init_encodestate(state_in);
state_in->stepsnewline = -1;
}
char base64_encode_value(const char n) {
char r;
if (n < 26) {
r = n + 'A';
} else if (n < 26 + 26) {
r = n - 26 + 'a';
} else if (n < 26 + 26 + 10) {
r = n - 26 - 26 + '0';
} else if (n == 62) {
r = '+';
} else {
r = '/';
}
return r;
}
int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in) {
const char* plainchar = plaintext_in;
const char* const plaintextend = plaintext_in + length_in;
char* codechar = code_out;
char result;
char fragment;
result = state_in->result;
switch (state_in->step) {
while (1) {
case step_A:
if (plainchar == plaintextend) {
state_in->result = result;
state_in->step = step_A;
return codechar - code_out;
}
fragment = *plainchar++;
result = (fragment & 0x0fc) >> 2;
*codechar++ = base64_encode_value(result);
result = (fragment & 0x003) << 4;
// falls through
case step_B:
if (plainchar == plaintextend) {
state_in->result = result;
state_in->step = step_B;
return codechar - code_out;
}
fragment = *plainchar++;
result |= (fragment & 0x0f0) >> 4;
*codechar++ = base64_encode_value(result);
result = (fragment & 0x00f) << 2;
// falls through
case step_C:
if (plainchar == plaintextend) {
state_in->result = result;
state_in->step = step_C;
return codechar - code_out;
}
fragment = *plainchar++;
result |= (fragment & 0x0c0) >> 6;
*codechar++ = base64_encode_value(result);
result = (fragment & 0x03f) >> 0;
*codechar++ = base64_encode_value(result);
++(state_in->stepcount);
if ((state_in->stepcount == BASE64_CHARS_PER_LINE / 4) && (state_in->stepsnewline > 0)) {
*codechar++ = '\n';
state_in->stepcount = 0;
}
}
}
/* control should not reach here */
return codechar - code_out;
}
int base64_encode_blockend(char* code_out, base64_encodestate* state_in) {
char* codechar = code_out;
switch (state_in->step) {
case step_B:
*codechar++ = base64_encode_value(state_in->result);
*codechar++ = '=';
*codechar++ = '=';
break;
case step_C:
*codechar++ = base64_encode_value(state_in->result);
*codechar++ = '=';
break;
case step_A:
break;
}
*codechar = 0x00;
return codechar - code_out;
}
int base64_encode_chars(const char* plaintext_in, int length_in, char* code_out) {
base64_encodestate _state;
base64_init_encodestate(&_state);
int len = base64_encode_block(plaintext_in, length_in, code_out, &_state);
return len + base64_encode_blockend((code_out + len), &_state);
}
};
+45
View File
@@ -0,0 +1,45 @@
/*
cencode.h - c header for a base64 encoding algorithm
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#pragma once
#define BASE64_CHARS_PER_LINE 72
#define base64_encode_expected_len_nonewlines(n) ((((4 * (n)) / 3) + 3) & ~3)
#define base64_encode_expected_len(n) \
(base64_encode_expected_len_nonewlines(n) + ((n / ((BASE64_CHARS_PER_LINE * 3) / 4)) + 1))
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
step_A, step_B, step_C
} base64_encodestep;
typedef struct {
base64_encodestep step;
char result;
int stepcount;
int stepsnewline;
} base64_encodestate;
void base64_init_encodestate(base64_encodestate* state_in);
void base64_init_encodestate_nonewlines(base64_encodestate* state_in);
char base64_encode_value(char value_in);
int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in);
int base64_encode_blockend(char* code_out, base64_encodestate* state_in);
int base64_encode_chars(const char* plaintext_in, int length_in, char* code_out);
#ifdef __cplusplus
} // extern "C"
#endif
+182
View File
@@ -0,0 +1,182 @@
/*
Newlib retargetable lock class using RP2040 SDK
Overrides weak functions in Newlib for locking to safely support
multi-core operation. Does not need any --wrap for memory allocators.
Copyright (c) 2022 Earle F. Philhower, III <earlephilhower@yahoo.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <pico/mutex.h>
#include <sys/lock.h>
#include "_freertos.h"
// HACK ALERT
// Pico-SDK defines mutex which can be at global scope, but when the auto_init_
// macros are used they are defined as static. Newlib needs global access to
// these mutextes, so instead of hacking pico-sdk just make "static" a no-op.
#define static
auto_init_recursive_mutex(__lock___sinit_recursive_mutex);
auto_init_recursive_mutex(__lock___sfp_recursive_mutex);
auto_init_recursive_mutex(__lock___atexit_recursive_mutex);
auto_init_mutex(__lock___at_quick_exit_mutex);
auto_init_recursive_mutex(__lock___malloc_recursive_mutex);
auto_init_recursive_mutex(__lock___env_recursive_mutex);
auto_init_mutex(__lock___tz_mutex);
auto_init_mutex(__lock___dd_hash_mutex);
auto_init_mutex(__lock___arc4random_mutex);
#undef static
// FreeRTOS hack - Allow Newlib to use FreeRTOS mutexes which preserve TASKID which
// is needed to support multithread
SemaphoreHandle_t __lock___sinit_recursive_mutex_freertos;
SemaphoreHandle_t __lock___sfp_recursive_mutex_freertos;
SemaphoreHandle_t __lock___atexit_recursive_mutex_freertos;
SemaphoreHandle_t __lock___at_quick_exit_mutex_freertos;
SemaphoreHandle_t __lock___malloc_recursive_mutex_freertos;
SemaphoreHandle_t __lock___env_recursive_mutex_freertos;
SemaphoreHandle_t __lock___tz_mutex_freertos;
SemaphoreHandle_t __lock___dd_hash_mutex_freertos;
SemaphoreHandle_t __lock___arc4random_mutex_freertos;
void __initFreeRTOSMutexes() {
__lock___sinit_recursive_mutex_freertos = _freertos_recursive_mutex_create();
__lock___sfp_recursive_mutex_freertos = _freertos_recursive_mutex_create();
__lock___atexit_recursive_mutex_freertos = _freertos_recursive_mutex_create();
__lock___at_quick_exit_mutex_freertos = __freertos_mutex_create();
__lock___malloc_recursive_mutex_freertos = _freertos_recursive_mutex_create();
__lock___env_recursive_mutex_freertos = _freertos_recursive_mutex_create();
__lock___tz_mutex_freertos = __freertos_mutex_create();
__lock___dd_hash_mutex_freertos = __freertos_mutex_create();
__lock___arc4random_mutex_freertos = __freertos_mutex_create();
}
static SemaphoreHandle_t __getFreeRTOSMutex(_LOCK_T lock) {
mutex_t *l = (mutex_t *)lock;
if (l == &__lock___at_quick_exit_mutex) {
return __lock___at_quick_exit_mutex_freertos;
} else if (l == &__lock___tz_mutex) {
return __lock___tz_mutex_freertos;
} else if (l == &__lock___dd_hash_mutex) {
return __lock___dd_hash_mutex_freertos;
} else if (l == &__lock___arc4random_mutex) {
return __lock___arc4random_mutex_freertos;
}
return nullptr;
}
static SemaphoreHandle_t __getFreeRTOSRecursiveMutex(_LOCK_T lock) {
recursive_mutex_t *l = (recursive_mutex_t *)lock;
if (l == &__lock___sinit_recursive_mutex) {
return __lock___sinit_recursive_mutex_freertos;
} else if (l == &__lock___sfp_recursive_mutex) {
return __lock___sfp_recursive_mutex_freertos;
} else if (l == &__lock___atexit_recursive_mutex) {
return __lock___atexit_recursive_mutex_freertos;
} else if (l == &__lock___malloc_recursive_mutex) {
return __lock___malloc_recursive_mutex_freertos;
} else if (l == &__lock___env_recursive_mutex) {
return __lock___env_recursive_mutex_freertos;
}
return nullptr;
}
void __retarget_lock_init(_LOCK_T *lock) {
if (__freeRTOSinitted) {
/* Already done in initFreeRTOSMutexes() */
} else {
mutex_init((mutex_t*) lock);
}
}
void __retarget_lock_init_recursive(_LOCK_T *lock) {
if (__freeRTOSinitted) {
/* Already done in initFreeRTOSMutexes() */
} else {
recursive_mutex_init((recursive_mutex_t*) lock);
}
}
void __retarget_lock_close(_LOCK_T lock) {
(void) lock;
}
void __retarget_lock_close_recursive(_LOCK_T lock) {
(void) lock;
}
void __retarget_lock_acquire(_LOCK_T lock) {
if (__freeRTOSinitted) {
auto mtx = __getFreeRTOSMutex(lock);
__freertos_mutex_take(mtx);
} else {
mutex_enter_blocking((mutex_t*)lock);
}
}
void __retarget_lock_acquire_recursive(_LOCK_T lock) {
if (__freeRTOSinitted) {
auto mtx = __getFreeRTOSRecursiveMutex(lock);
__freertos_recursive_mutex_take(mtx);
} else {
recursive_mutex_enter_blocking((recursive_mutex_t*)lock);
}
}
int __retarget_lock_try_acquire(_LOCK_T lock) {
int ret;
if (__freeRTOSinitted) {
auto mtx = __getFreeRTOSMutex(lock);
ret = __freertos_mutex_try_take(mtx);
} else {
ret = mutex_try_enter((mutex_t *)lock, nullptr);
}
return ret;
}
int __retarget_lock_try_acquire_recursive(_LOCK_T lock) {
int ret;
if (__freeRTOSinitted) {
auto mtx = __getFreeRTOSRecursiveMutex(lock);
ret = __freertos_recursive_mutex_try_take(mtx);
} else {
ret = recursive_mutex_try_enter((recursive_mutex_t*)lock, nullptr);
}
return ret;
}
void __retarget_lock_release(_LOCK_T lock) {
if (__freeRTOSinitted) {
auto mtx = __getFreeRTOSMutex(lock);
__freertos_mutex_give(mtx);
} else {
mutex_exit((mutex_t*)lock);
}
}
void __retarget_lock_release_recursive(_LOCK_T lock) {
if (__freeRTOSinitted) {
auto mtx = __getFreeRTOSRecursiveMutex(lock);
__freertos_recursive_mutex_give(mtx);
} else {
recursive_mutex_exit((recursive_mutex_t*)lock);
}
}
+326
View File
@@ -0,0 +1,326 @@
/*
LWIP wrappers to protect against timer-based re-entrancy
Copyright (c) 202s Earle F. Philhower, III <earlephilhower@yahoo.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "pico/mutex.h"
#include "lwip/pbuf.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
#include "lwip/dns.h"
#include "lwip/raw.h"
#include "lwip/timeouts.h"
// Global indicator that we're inside an LWIP block
extern "C" {
volatile bool __inLWIP = false;
}
auto_init_recursive_mutex(__mtxLWIP);
class LWIPMutex {
public:
LWIPMutex() {
noInterrupts();
recursive_mutex_enter_blocking(&__mtxLWIP);
__inLWIP = true;
_ref++;
interrupts();
}
~LWIPMutex() {
noInterrupts();
if (0 == --_ref) {
__inLWIP = false;
}
recursive_mutex_exit(&__mtxLWIP);
interrupts();
}
private:
static int _ref;
};
int LWIPMutex::_ref = 0;
extern "C" {
extern u8_t __real_pbuf_header(struct pbuf *p, s16_t header_size);
u8_t __wrap_pbuf_header(struct pbuf *p, s16_t header_size) {
LWIPMutex m;
return __real_pbuf_header(p, header_size);
}
extern u8_t __real_pbuf_free(struct pbuf *p);
u8_t __wrap_pbuf_free(struct pbuf *p) {
LWIPMutex m;
return __real_pbuf_free(p);
}
extern struct pbuf *__real_pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type);
struct pbuf *__wrap_pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type) {
LWIPMutex m;
return __real_pbuf_alloc(l, length, type);
}
extern err_t __real_pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len);
err_t __wrap_pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len) {
LWIPMutex m;
return __real_pbuf_take(buf, dataptr, len);
}
extern u16_t __real_pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset);
u16_t __wrap_pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset) {
LWIPMutex m;
return __real_pbuf_copy_partial(p, dataptr, len, offset);
}
extern void __real_pbuf_ref(struct pbuf *p);
void __wrap_pbuf_ref(struct pbuf *p) {
LWIPMutex m;
__real_pbuf_ref(p);
}
extern u8_t __real_pbuf_get_at(const struct pbuf* p, u16_t offset);
u8_t __wrap_pbuf_get_at(const struct pbuf* p, u16_t offset) {
LWIPMutex m;
return __real_pbuf_get_at(p, offset);
}
extern void *__real_pbuf_get_contiguous(const struct pbuf *p, void *buffer, size_t bufsize, u16_t len, u16_t offset);
void *__wrap_pbuf_get_contiguous(const struct pbuf *p, void *buffer, size_t bufsize, u16_t len, u16_t offset) {
LWIPMutex m;
return __real_pbuf_get_contiguous(p, buffer, bufsize, len, offset);
}
extern void __real_pbuf_cat(struct pbuf *head, struct pbuf *tail);
void __wrap_pbuf_cat(struct pbuf *head, struct pbuf *tail) {
LWIPMutex m;
__real_pbuf_cat(head, tail);
}
extern void __real_tcp_arg(struct tcp_pcb *pcb, void *arg);
void __wrap_tcp_arg(struct tcp_pcb *pcb, void *arg) {
LWIPMutex m;
__real_tcp_arg(pcb, arg);
}
extern struct tcp_pcb *__real_tcp_new(void);
struct tcp_pcb *__wrap_tcp_new(void) {
LWIPMutex m;
return __real_tcp_new();
}
extern err_t __real_tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port);
err_t __wrap_tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) {
LWIPMutex m;
return __real_tcp_bind(pcb, ipaddr, port);
}
extern struct tcp_pcb *__real_tcp_listen(struct tcp_pcb *pcb);
struct tcp_pcb *__wrap_tcp_listen(struct tcp_pcb *pcb) {
LWIPMutex m;
return __real_tcp_listen(pcb);
}
extern struct tcp_pcb *__real_tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog);
struct tcp_pcb *__wrap_tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) {
LWIPMutex m;
return __real_tcp_listen_with_backlog(pcb, backlog);
}
extern void __real_tcp_accept(struct tcp_pcb *pcb, err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err));
void __wrap_tcp_accept(struct tcp_pcb *pcb, err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err)) {
LWIPMutex m;
__real_tcp_accept(pcb, accept);
}
extern err_t __real_tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port, err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err));
err_t __wrap_tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port, err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err)) {
LWIPMutex m;
return __real_tcp_connect(pcb, ipaddr, port, connected);
}
extern err_t __real_tcp_write(struct tcp_pcb *pcb, const void *dataptr, u16_t len, u8_t apiflags);
err_t __wrap_tcp_write(struct tcp_pcb *pcb, const void *dataptr, u16_t len, u8_t apiflags) {
LWIPMutex m;
return __real_tcp_write(pcb, dataptr, len, apiflags);
}
extern void __real_tcp_sent(struct tcp_pcb *pcb, err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len));
void __wrap_tcp_sent(struct tcp_pcb *pcb, err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len)) {
LWIPMutex m;
__real_tcp_sent(pcb, sent);
}
extern void __real_tcp_recv(struct tcp_pcb *pcb, err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err));
void __wrap_tcp_recv(struct tcp_pcb *pcb, err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)) {
LWIPMutex m;
__real_tcp_recv(pcb, recv);
}
extern void __real_tcp_recved(struct tcp_pcb *pcb, u16_t len);
void __wrap_tcp_recved(struct tcp_pcb *pcb, u16_t len) {
LWIPMutex m;
__real_tcp_recved(pcb, len);
}
extern void __real_tcp_poll(struct tcp_pcb *pcb, err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval);
void __wrap_tcp_poll(struct tcp_pcb *pcb, err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval) {
LWIPMutex m;
__real_tcp_poll(pcb, poll, interval);
}
extern err_t __real_tcp_close(struct tcp_pcb *pcb);
err_t __wrap_tcp_close(struct tcp_pcb *pcb) {
LWIPMutex m;
return __real_tcp_close(pcb);
}
extern void __real_tcp_abort(struct tcp_pcb *pcb);
void __wrap_tcp_abort(struct tcp_pcb *pcb) {
LWIPMutex m;
__real_tcp_abort(pcb);
}
extern void __real_tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg, err_t err));
void __wrap_tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg, err_t err)) {
LWIPMutex m;
__real_tcp_err(pcb, err);
}
extern err_t __real_tcp_output(struct tcp_pcb *pcb);
err_t __wrap_tcp_output(struct tcp_pcb *pcb) {
LWIPMutex m;
return __real_tcp_output(pcb);
}
extern void __real_tcp_setprio(struct tcp_pcb *pcb, u8_t prio);
void __wrap_tcp_setprio(struct tcp_pcb *pcb, u8_t prio) {
LWIPMutex m;
return __real_tcp_setprio(pcb, prio);
}
extern void __real_tcp_backlog_delayed(struct tcp_pcb* pcb);
void __wrap_tcp_backlog_delayed(struct tcp_pcb* pcb) {
LWIPMutex m;
return __real_tcp_backlog_delayed(pcb);
}
extern void __real_tcp_backlog_accepted(struct tcp_pcb* pcb);
void __wrap_tcp_backlog_accepted(struct tcp_pcb* pcb) {
LWIPMutex m;
return __real_tcp_backlog_accepted(pcb);
}
extern struct udp_pcb *__real_udp_new(void);
struct udp_pcb *__wrap_udp_new(void) {
LWIPMutex m;
return __real_udp_new();
}
extern void __real_udp_remove(struct udp_pcb *pcb);
void __wrap_udp_remove(struct udp_pcb *pcb) {
LWIPMutex m;
__real_udp_remove(pcb);
}
extern err_t __real_udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port);
err_t __wrap_udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) {
LWIPMutex m;
return __real_udp_bind(pcb, ipaddr, port);
}
extern err_t __real_udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port);
err_t __wrap_udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) {
LWIPMutex m;
return __real_udp_connect(pcb, ipaddr, port);
}
extern err_t __real_udp_disconnect(struct udp_pcb *pcb);
err_t __wrap_udp_disconnect(struct udp_pcb *pcb) {
LWIPMutex m;
return __real_udp_disconnect(pcb);
}
extern err_t __real_udp_send(struct udp_pcb *pcb, struct pbuf *p);
err_t __wrap_udp_send(struct udp_pcb *pcb, struct pbuf *p) {
LWIPMutex m;
return __real_udp_send(pcb, p);
}
extern void __real_udp_recv(struct udp_pcb *pcb, void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p, ip_addr_t *addr, u16_t port), void *recv_arg);
void __wrap_udp_recv(struct udp_pcb *pcb, void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p, ip_addr_t *addr, u16_t port), void *recv_arg) {
LWIPMutex m;
__real_udp_recv(pcb, recv, recv_arg);
}
extern err_t __real_udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif);
err_t __wrap_udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif) {
LWIPMutex m;
return __real_udp_sendto_if(pcb, p, dst_ip, dst_port, netif);
}
extern void __real_sys_check_timeouts(void);
void __wrap_sys_check_timeouts(void) {
LWIPMutex m;
__real_sys_check_timeouts();
}
extern err_t __real_dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg);
err_t __wrap_dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg) {
LWIPMutex m;
return __real_dns_gethostbyname(hostname, addr, found, callback_arg);
}
extern err_t __real_dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg, u8_t dns_addrtype);
err_t __wrap_dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg, u8_t dns_addrtype) {
LWIPMutex m;
return __real_dns_gethostbyname_addrtype(hostname, addr, found, callback_arg, dns_addrtype);
}
extern struct raw_pcb *__real_raw_new(u8_t proto);
struct raw_pcb *__wrap_raw_new(u8_t proto) {
LWIPMutex m;
return __real_raw_new(proto);
}
extern void __real_raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg);
void __wrap_raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg) {
LWIPMutex m;
__real_raw_recv(pcb, recv, recv_arg);
}
extern err_t __real_raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr);
err_t __wrap_raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr) {
LWIPMutex m;
return __real_raw_bind(pcb, ipaddr);
}
extern err_t __real_raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr);
err_t __wrap_raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr) {
LWIPMutex m;
return __real_raw_sendto(pcb, p, ipaddr);
}
extern void __real_raw_remove(struct raw_pcb *pcb);
void __wrap_raw_remove(struct raw_pcb *pcb) {
LWIPMutex m;
__real_raw_remove(pcb);
}
}; // extern "C"
+91 -30
View File
@@ -22,26 +22,34 @@
#include "RP2040USB.h"
#include <pico/stdlib.h>
#include <pico/multicore.h>
#include <reent.h>
RP2040 rp2040;
extern "C" {
volatile bool __otherCoreIdled = false;
int __holdUpPendSV = 0;
};
volatile bool _MFIFO::_otherIdled = false;
mutex_t _pioMutex;
extern void setup();
extern void loop();
// FreeRTOS potential includes
extern void initFreeRTOS() __attribute__((weak));
extern void startFreeRTOS() __attribute__((weak));
bool __isFreeRTOS;
volatile bool __freeRTOSinitted;
// Weak empty variant initialization. May be redefined by variant files.
void initVariant() __attribute__((weak));
void initVariant() { }
// Optional 2nd core setup and loop
extern void setup1() __attribute__((weak));
extern void loop1() __attribute__((weak));
static void main1() {
extern "C" void main1() {
rp2040.fifo.registerCore();
if (setup1) {
setup1();
@@ -53,14 +61,47 @@ static void main1() {
}
}
extern void __loop() {
#ifdef USE_TINYUSB
yield();
#endif
if (arduino::serialEventRun) {
arduino::serialEventRun();
}
if (arduino::serialEvent1Run) {
arduino::serialEvent1Run();
}
if (arduino::serialEvent2Run) {
arduino::serialEvent2Run();
}
}
static struct _reent *_impure_ptr1 = nullptr;
extern "C" int main() {
#if F_CPU != 125000000
set_sys_clock_khz(F_CPU / 1000, true);
#endif
// Let rest of core know if we're using FreeRTOS
__isFreeRTOS = initFreeRTOS ? true : false;
// Allocate impure_ptr (newlib temps) if there is a 2nd core running
if (!__isFreeRTOS && (setup1 || loop1)) {
_impure_ptr1 = (struct _reent*)calloc(sizeof(struct _reent), 1);
_REENT_INIT_PTR(_impure_ptr1);
}
mutex_init(&_pioMutex);
rp2040.begin();
initVariant();
if (__isFreeRTOS) {
initFreeRTOS();
}
#ifndef NO_USB
#ifdef USE_TINYUSB
TinyUSB_Device_Init(0);
@@ -69,43 +110,63 @@ extern "C" int main() {
__USBStart();
#ifndef DISABLE_USB_SERIAL
// Enable serial port for reset/upload always
Serial.begin(115200);
if (!__isFreeRTOS) {
// Enable serial port for reset/upload always
Serial.begin(115200);
}
#endif
#endif
#endif
#if defined DEBUG_RP2040_PORT
DEBUG_RP2040_PORT.begin(115200);
#endif
#ifndef NO_USB
if (setup1 || loop1) {
rp2040.fifo.begin(2);
multicore_launch_core1(main1);
} else {
rp2040.fifo.begin(1);
if (!__isFreeRTOS) {
DEBUG_RP2040_PORT.begin(115200);
}
rp2040.fifo.registerCore();
#endif
setup();
while (true) {
loop();
if (!__isFreeRTOS) {
if (setup1 || loop1) {
rp2040.fifo.begin(2);
} else {
rp2040.fifo.begin(1);
}
rp2040.fifo.registerCore();
}
#ifdef USE_TINYUSB
yield();
#endif
if (arduino::serialEventRun) {
arduino::serialEventRun();
if (!__isFreeRTOS) {
if (setup1 || loop1) {
delay(1); // Needed to make Picoprobe upload start 2nd core
multicore_launch_core1(main1);
}
if (arduino::serialEvent1Run) {
arduino::serialEvent1Run();
}
if (arduino::serialEvent2Run) {
arduino::serialEvent2Run();
setup();
while (true) {
loop();
__loop();
}
} else {
rp2040.fifo.begin(2);
startFreeRTOS();
}
return 0;
}
extern "C" unsigned long ulMainGetRunTimeCounterValue() {
return rp2040.getCycleCount64();
}
extern "C" void __register_impure_ptr(struct _reent *p) {
if (get_core_num() == 0) {
_impure_ptr = p;
} else {
_impure_ptr1 = p;
}
}
extern "C" struct _reent *__wrap___getreent() {
if (get_core_num() == 0) {
return _impure_ptr;
} else {
return _impure_ptr1;
}
}
+53
View File
@@ -0,0 +1,53 @@
/*
Malloc/etc. interrupt locking wrappers
Copyright (c) 2022 Earle F. Philhower, III <earlephilhower@yahoo.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <Arduino.h>
extern "C" void *__real_malloc(size_t size);
extern "C" void *__real_calloc(size_t count, size_t size);
extern "C" void *__real_realloc(void *mem, size_t size);
extern "C" void __real_free(void *mem);
extern "C" void *__wrap_malloc(size_t size) {
noInterrupts();
void *rc = __real_malloc(size);
interrupts();
return rc;
}
extern "C" void *__wrap_calloc(size_t count, size_t size) {
noInterrupts();
void *rc = __real_calloc(count, size);
interrupts();
return rc;
}
extern "C" void *__wrap_realloc(void *mem, size_t size) {
noInterrupts();
void *rc = __real_realloc(mem, size);
interrupts();
return rc;
}
extern "C" void __wrap_free(void *mem) {
noInterrupts();
__real_free(mem);
interrupts();
}
+109
View File
@@ -0,0 +1,109 @@
; pio_uart for the Raspberry Pi Pico RP2040
;
; Based loosely off of the uart_rx/_tx examples in the pico-examples repo,
; but heavily modified and optimized to not require changing the PIO
; clocks so that Tone and Servo won't be affected, and multiple different
; PIO ports can be run at different baud at the same time.
;
; Copyright (c) 2021 Earle F. Philhower, III <earlephilhower@yahoo.com>
;
; This library is free software; you can redistribute it and/or
; modify it under the terms of the GNU Lesser General Public
; License as published by the Free Software Foundation; either
; version 2.1 of the License, or (at your option) any later version.
;
; This library is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
; Lesser General Public License for more details.
;
; You should have received a copy of the GNU Lesser General Public
; License along with this library; if not, write to the Free Software
; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
.program pio_tx
.side_set 1 opt
; We shift out the start and stop bit as part of the FIFO
set x, 9
pull side 1 ; Force stop bit
; Send the bits
bitloop:
out pins, 1
mov y, isr ; ISR is loaded by the setup routine with the period-1 count
wait_bit:
jmp y-- wait_bit
jmp x-- bitloop
% c-sdk {
static inline void pio_tx_program_init(PIO pio, uint sm, uint offset, uint pin_tx) {
// Tell PIO to initially drive output-high on the selected pin, then map PIO
// onto that pin with the IO muxes.
pio_sm_set_pins_with_mask(pio, sm, 1u << pin_tx, 1u << pin_tx);
pio_sm_set_pindirs_with_mask(pio, sm, 1u << pin_tx, 1u << pin_tx);
pio_gpio_init(pio, pin_tx);
pio_sm_config c = pio_tx_program_get_default_config(offset);
// OUT shifts to right, no autopull
sm_config_set_out_shift(&c, true, false, 32);
// We are mapping both OUT and side-set to the same pin, because sometimes
// we need to assert user data onto the pin (with OUT) and sometimes
// assert constant values (start/stop bit)
sm_config_set_out_pins(&c, pin_tx, 1);
sm_config_set_sideset_pins(&c, pin_tx);
// We only need TX, so get an 8-deep FIFO!
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
pio_sm_init(pio, sm, offset, &c);
}
%}
.program pio_rx
; IN pin 0 and JMP pin are both mapped to the GPIO used as UART RX.
start:
set x, 18 ; Preload bit counter...we'll shift in the start bit and stop bit, and each bit will be double-recorded (to be fixed by RP2040 code)
wait 0 pin 0 ; Stall until start bit is asserted
bitloop:
; Delay until 1/2 way into the bit time
mov y, osr
wait_half:
jmp y-- wait_half
; Read in the bit
in pins, 1 ; Shift data bit into ISR
jmp x-- bitloop ; Loop all bits
push ; Stuff it and wait for next start
% c-sdk {
static inline void pio_rx_program_init(PIO pio, uint sm, uint offset, uint pin) {
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false);
pio_gpio_init(pio, pin);
gpio_pull_up(pin);
pio_sm_config c = pio_rx_program_get_default_config(offset);
sm_config_set_in_pins(&c, pin); // for WAIT, IN
sm_config_set_jmp_pin(&c, pin); // for JMP
// Shift to right, autopull disabled
sm_config_set_in_shift(&c, true, false, 32);
pio_sm_init(pio, sm, offset, &c);
}
%}
+107
View File
@@ -0,0 +1,107 @@
// -------------------------------------------------- //
// This file is autogenerated by pioasm; do not edit! //
// -------------------------------------------------- //
#if !PICO_NO_HARDWARE
#include "hardware/pio.h"
#endif
// ------ //
// pio_tx //
// ------ //
#define pio_tx_wrap_target 0
#define pio_tx_wrap 5
static const uint16_t pio_tx_program_instructions[] = {
// .wrap_target
0xe029, // 0: set x, 9
0x98a0, // 1: pull block side 1
0x6001, // 2: out pins, 1
0xa046, // 3: mov y, isr
0x0084, // 4: jmp y--, 4
0x0042, // 5: jmp x--, 2
// .wrap
};
#if !PICO_NO_HARDWARE
static const struct pio_program pio_tx_program = {
.instructions = pio_tx_program_instructions,
.length = 6,
.origin = -1,
};
static inline pio_sm_config pio_tx_program_get_default_config(uint offset) {
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_wrap(&c, offset + pio_tx_wrap_target, offset + pio_tx_wrap);
sm_config_set_sideset(&c, 2, true, false);
return c;
}
static inline void pio_tx_program_init(PIO pio, uint sm, uint offset, uint pin_tx) {
// Tell PIO to initially drive output-high on the selected pin, then map PIO
// onto that pin with the IO muxes.
pio_sm_set_pins_with_mask(pio, sm, 1u << pin_tx, 1u << pin_tx);
pio_sm_set_pindirs_with_mask(pio, sm, 1u << pin_tx, 1u << pin_tx);
pio_gpio_init(pio, pin_tx);
pio_sm_config c = pio_tx_program_get_default_config(offset);
// OUT shifts to right, no autopull
sm_config_set_out_shift(&c, true, false, 32);
// We are mapping both OUT and side-set to the same pin, because sometimes
// we need to assert user data onto the pin (with OUT) and sometimes
// assert constant values (start/stop bit)
sm_config_set_out_pins(&c, pin_tx, 1);
sm_config_set_sideset_pins(&c, pin_tx);
// We only need TX, so get an 8-deep FIFO!
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
pio_sm_init(pio, sm, offset, &c);
}
#endif
// ------ //
// pio_rx //
// ------ //
#define pio_rx_wrap_target 0
#define pio_rx_wrap 6
static const uint16_t pio_rx_program_instructions[] = {
// .wrap_target
0xe032, // 0: set x, 18
0x2020, // 1: wait 0 pin, 0
0xa047, // 2: mov y, osr
0x0083, // 3: jmp y--, 3
0x4001, // 4: in pins, 1
0x0042, // 5: jmp x--, 2
0x8020, // 6: push block
// .wrap
};
#if !PICO_NO_HARDWARE
static const struct pio_program pio_rx_program = {
.instructions = pio_rx_program_instructions,
.length = 7,
.origin = -1,
};
static inline pio_sm_config pio_rx_program_get_default_config(uint offset) {
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_wrap(&c, offset + pio_rx_wrap_target, offset + pio_rx_wrap);
return c;
}
static inline void pio_rx_program_init(PIO pio, uint sm, uint offset, uint pin) {
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false);
pio_gpio_init(pio, pin);
gpio_pull_up(pin);
pio_sm_config c = pio_rx_program_get_default_config(offset);
sm_config_set_in_pins(&c, pin); // for WAIT, IN
sm_config_set_jmp_pin(&c, pin); // for JMP
// Shift to right, autopull disabled
sm_config_set_in_shift(&c, true, false, 32);
pio_sm_init(pio, sm, offset, &c);
}
#endif
+10 -3
View File
@@ -90,8 +90,8 @@ extern "C" int _gettimeofday(struct timeval *tv, void *tz) {
(void) tz;
uint64_t now_us = to_us_since_boot(get_absolute_time()) + __timedelta_us;
if (tv) {
tv->tv_sec = now_us / 1000000L;
tv->tv_usec = now_us % 1000000L;
tv->tv_sec = now_us / 1'000'000L;
tv->tv_usec = now_us % 1'000'000L;
}
return 0;
}
@@ -101,13 +101,20 @@ extern "C" int settimeofday(const struct timeval *tv, const struct timezone *tz)
uint64_t now_us = to_us_since_boot(get_absolute_time());
if (tv) {
uint64_t newnow_us;
newnow_us = tv->tv_sec * 1000000L;
newnow_us = tv->tv_sec * 1'000'000L;
newnow_us += tv->tv_usec;
__timedelta_us = newnow_us - now_us;
}
return 0;
}
// For NTP
extern "C" void __setSystemTime(unsigned long long sec, unsigned long usec) {
uint64_t now_us = to_us_since_boot(get_absolute_time());
uint64_t newnow_us = sec * 1'000'000LL + usec;
__timedelta_us = newnow_us - now_us;
}
extern "C" int _isatty(int file) {
(void) file;
errno = ENOSYS;
@@ -0,0 +1,348 @@
/*
Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
SPDX-License-Identifier: BSD-3-Clause
*/
// Taken from the Pico-SDK v1.4.0 and hacked by EFP3 to allow overriding the LWIP setup
//#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"
#include <lwip/init.h>
#include "lwip/timeouts.h"
#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
extern volatile bool __inLWIP;
// 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 && LWIP_SYS_CHECK_MS
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
if (!__inLWIP) {
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 (__inLWIP || (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);
lwip_init();
// 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);
// }
}
#ifdef ARDUINO_RASPBERRY_PI_PICO_W
void __attribute__((weak)) cyw43_cb_tcpip_init(cyw43_t *self, int itf);
void cyw43_cb_tcpip_init(cyw43_t *self, int itf) {
(void) self;
(void) itf;
}
void __attribute__((weak)) cyw43_cb_tcpip_deinit(cyw43_t *self, int itf);
void cyw43_cb_tcpip_deinit(cyw43_t *self, int itf) {
(void) self;
(void) itf;
}
void __attribute__((weak)) cyw43_cb_tcpip_set_link_up(cyw43_t *self, int itf);
void cyw43_cb_tcpip_set_link_up(cyw43_t *self, int itf) {
(void) self;
(void) itf;
}
void __attribute__((weak)) cyw43_cb_tcpip_set_link_down(cyw43_t *self, int itf);
void cyw43_cb_tcpip_set_link_down(cyw43_t *self, int itf) {
(void) self;
(void) itf;
}
void __attribute__((weak)) cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf);
void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf) {
(void) cb_data;
(void) itf;
(void) len;
(void) buf;
}
#endif
#endif
@@ -0,0 +1,90 @@
/*
Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
Hacked by EFP3 to allow disabling unless requested
SPDX-License-Identifier: BSD-3-Clause
*/
#include "pico.h"
#include "pico/time.h"
#include "pico/bootrom.h"
#include "pico/binary_info.h"
// PICO_CONFIG: PICO_BOOTSEL_VIA_DOUBLE_RESET_TIMEOUT_MS, Window of opportunity for a second press of a reset button to enter BOOTSEL mode (milliseconds), type=int, default=200, group=pico_bootsel_via_double_reset
#ifndef PICO_BOOTSEL_VIA_DOUBLE_RESET_TIMEOUT_MS
#define PICO_BOOTSEL_VIA_DOUBLE_RESET_TIMEOUT_MS 350
#endif
// PICO_CONFIG: PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED, Optionally define a pin to use as bootloader activity LED when BOOTSEL mode is entered via reset double tap, type=int, min=0, max=29, group=pico_bootsel_via_double_reset
// PICO_CONFIG: PICO_BOOTSEL_VIA_DOUBLE_RESET_INTERFACE_DISABLE_MASK, Optionally disable either the mass storage interface (bit 0) or the PICOBOOT interface (bit 1) when entering BOOTSEL mode via double reset, type=int, min=0, max=3, default=0, group=pico_bootsel_via_double_reset
#ifndef PICO_BOOTSEL_VIA_DOUBLE_RESET_INTERFACE_DISABLE_MASK
#define PICO_BOOTSEL_VIA_DOUBLE_RESET_INTERFACE_DISABLE_MASK 0u
#endif
/** \defgroup pico_bootsel_via_double_reset pico_bootsel_via_double_reset
When the 'pico_bootsel_via_double_reset' library is linked, a function is
injected before main() which will detect when the system has been reset
twice in quick succession, and enter the USB ROM bootloader (BOOTSEL mode)
when this happens. This allows a double tap of a reset button on a
development board to be used to enter the ROM bootloader, provided this
library is always linked.
*/
#if !PICO_NO_BI_BOOTSEL_VIA_DOUBLE_RESET
bi_decl(bi_program_feature("double reset -> BOOTSEL"));
#endif
// Doesn't make any sense for a RAM only binary
#if !PICO_NO_FLASH
static const uint32_t magic_token[] = {
0xf01681de, 0xbd729b29, 0xd359be7a,
};
// Place our marker on the 2nd core's stack...which will not have been touched when this code is executing
static uint32_t *magic_location = (uint32_t*)0x20040000;
//static uint32_t __uninitialized_ram(magic_location)[count_of(magic_token)];
/* Check for double reset and enter BOOTSEL mode if detected
This function is registered to run automatically before main(). The
algorithm is:
1. Check for magic token in memory; enter BOOTSEL mode if found.
2. Initialise that memory with that magic token.
3. Do nothing for a short while (few hundred ms).
4. Clear the magic token.
5. Continue with normal boot.
Resetting the device twice quickly will interrupt step 3, leaving the token
in place so that the second boot will go to the bootloader.
*/
/*static*/ void __attribute__((constructor)) boot_double_tap_check(void) {
for (uint i = 0; i < count_of(magic_token); i++) {
if (magic_location[i] != magic_token[i]) {
// Arm, wait, then disarm and continue booting
for (i = 0; i < count_of(magic_token); i++) {
magic_location[i] = magic_token[i];
}
busy_wait_us(PICO_BOOTSEL_VIA_DOUBLE_RESET_TIMEOUT_MS * 1000);
magic_location[0] = 0;
return;
}
}
// Detected a double reset, so enter USB bootloader
magic_location[0] = 0;
#ifdef PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED
const uint32_t led_mask = 1u << PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED;
#else
const uint32_t led_mask = 0u;
#endif
reset_usb_boot(
led_mask,
PICO_BOOTSEL_VIA_DOUBLE_RESET_INTERFACE_DISABLE_MASK
);
}
#endif
+1 -5
View File
@@ -19,8 +19,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef STDLIB_NONISO_H
#define STDLIB_NONISO_H
#pragma once
#ifdef __cplusplus
extern "C" {
@@ -54,6 +53,3 @@ const char* strrstr(const char*__restrict p_pcString,
#ifdef __cplusplus
} // extern "C"
#endif
#endif
+32 -19
View File
@@ -27,8 +27,9 @@
#include <hardware/adc.h>
static uint32_t analogScale = 255;
static uint16_t analogFreq = 1000;
static bool pwmInitted = false;
static uint32_t analogFreq = 1000;
static uint32_t pwmInitted = 0;
static bool scaleInitted = false;
static bool adcInitted = false;
static uint16_t analogWritePseudoScale = 1;
static uint16_t analogWriteSlowScale = 1;
@@ -42,29 +43,31 @@ extern "C" void analogWriteFreq(uint32_t freq) {
if (freq < 100) {
DEBUGCORE("ERROR: analogWriteFreq too low (%d)\n", freq);
analogFreq = 100;
} else if (freq > 60000) {
} else if (freq > 10'000'000) {
DEBUGCORE("ERROR: analogWriteFreq too high (%d)\n", freq);
analogFreq = 60000;
analogFreq = 10'000'000;
} else {
analogFreq = freq;
}
pwmInitted = false;
pwmInitted = 0;
scaleInitted = false;
}
extern "C" void analogWriteRange(uint32_t range) {
if (range == analogScale) {
return;
}
if ((range >= 15) && (range <= 65535)) {
if ((range >= 3) && (range <= 65535)) {
analogScale = range;
pwmInitted = false;
pwmInitted = 0;
scaleInitted = false;
} else {
DEBUGCORE("ERROR: analogWriteRange out of range (%d)\n", range);
}
}
extern "C" void analogWriteResolution(int res) {
if ((res >= 4) && (res <= 16)) {
if ((res >= 2) && (res <= 16)) {
analogWriteRange((1 << res) - 1);
} else {
DEBUGCORE("ERROR: analogWriteResolution out of range (%d)\n", res);
@@ -78,29 +81,29 @@ extern "C" void analogWrite(pin_size_t pin, int val) {
DEBUGCORE("ERROR: Illegal analogWrite pin (%d)\n", pin);
return;
}
if (!pwmInitted) {
if (!scaleInitted) {
// For low frequencies, we need to scale the output max value up to achieve lower periods
analogWritePseudoScale = 1;
while (((clock_get_hz(clk_sys) / (float)(analogScale * analogFreq)) > 255.0) && (analogScale < 32678)) {
while (((clock_get_hz(clk_sys) / ((float)analogScale * analogFreq)) > 255.0) && (analogScale < 32678)) {
analogWritePseudoScale++;
analogScale *= 2;
DEBUGCORE("Adjusting analogWrite values PS=%d, scale=%d\n", analogWritePseudoScale, analogScale);
}
// For high frequencies, we need to scale the output max value down to actually hit the frequency target
analogWriteSlowScale = 1;
while (((clock_get_hz(clk_sys) / (float)(analogScale * analogFreq)) < 2.0) && (analogScale > 32)) {
while (((clock_get_hz(clk_sys) / ((float)analogScale * analogFreq)) < 1.0) && (analogScale >= 6)) {
analogWriteSlowScale++;
analogScale /= 2;
DEBUGCORE("Adjusting analogWrite values SS=%d, scale=%d\n", analogWriteSlowScale, analogScale);
}
scaleInitted = true;
}
if (!(pwmInitted & (1 << pwm_gpio_to_slice_num(pin)))) {
pwm_config c = pwm_get_default_config();
pwm_config_set_clkdiv(&c, clock_get_hz(clk_sys) / (float)(analogScale * analogFreq));
pwm_config_set_wrap(&c, analogScale);
for (int i = 0; i < 30; i++) {
pwm_init(pwm_gpio_to_slice_num(i), &c, true);
}
pwmInitted = true;
pwm_config_set_clkdiv(&c, clock_get_hz(clk_sys) / ((float)analogScale * analogFreq));
pwm_config_set_wrap(&c, analogScale - 1);
pwm_init(pwm_gpio_to_slice_num(pin), &c, true);
pwmInitted |= 1 << pwm_gpio_to_slice_num(pin);
}
val <<= analogWritePseudoScale;
@@ -117,6 +120,7 @@ extern "C" void analogWrite(pin_size_t pin, int val) {
}
auto_init_mutex(_adcMutex);
static int _readBits = 10;
extern "C" int analogRead(pin_size_t pin) {
CoreMutex m(&_adcMutex);
@@ -130,10 +134,11 @@ extern "C" int analogRead(pin_size_t pin) {
}
if (!adcInitted) {
adc_init();
adcInitted = true;
}
adc_gpio_init(pin);
adc_select_input(pin - minPin);
return adc_read();
return (_readBits < 12) ? adc_read() >> (12 - _readBits) : adc_read() << (_readBits - 12);
}
extern "C" float analogReadTemp() {
@@ -144,6 +149,7 @@ extern "C" float analogReadTemp() {
}
if (!adcInitted) {
adc_init();
adcInitted = true;
}
adc_set_temp_sensor_enabled(true);
delay(1); // Allow things to settle. Without this, readings can be erratic
@@ -153,3 +159,10 @@ extern "C" float analogReadTemp() {
float t = 27.0f - ((v * 3.3f / 4096.0f) - 0.706f) / 0.001721f; // From the datasheet
return t;
}
extern "C" void analogReadResolution(int bits) {
CoreMutex m(&_adcMutex);
if (m && ((bits > 0) && (bits < 32))) {
_readBits = bits;
}
}
+23 -3
View File
@@ -23,7 +23,8 @@
static PinMode _pm[30];
extern "C" void pinMode(pin_size_t ulPin, PinMode ulMode) {
extern "C" void pinMode(pin_size_t ulPin, PinMode ulMode) __attribute__((weak, alias("__pinMode")));
extern "C" void __pinMode(pin_size_t ulPin, PinMode ulMode) {
switch (ulMode) {
case INPUT:
gpio_init(ulPin);
@@ -43,7 +44,24 @@ extern "C" void pinMode(pin_size_t ulPin, PinMode ulMode) {
gpio_put(ulPin, 1);
break;
case OUTPUT:
case OUTPUT_4MA:
gpio_init(ulPin);
gpio_set_drive_strength(ulPin, GPIO_DRIVE_STRENGTH_4MA);
gpio_set_dir(ulPin, true);
break;
case OUTPUT_2MA:
gpio_init(ulPin);
gpio_set_drive_strength(ulPin, GPIO_DRIVE_STRENGTH_2MA);
gpio_set_dir(ulPin, true);
break;
case OUTPUT_8MA:
gpio_init(ulPin);
gpio_set_drive_strength(ulPin, GPIO_DRIVE_STRENGTH_8MA);
gpio_set_dir(ulPin, true);
break;
case OUTPUT_12MA:
gpio_init(ulPin);
gpio_set_drive_strength(ulPin, GPIO_DRIVE_STRENGTH_12MA);
gpio_set_dir(ulPin, true);
break;
default:
@@ -59,7 +77,8 @@ extern "C" void pinMode(pin_size_t ulPin, PinMode ulMode) {
_pm[ulPin] = ulMode;
}
extern "C" void digitalWrite(pin_size_t ulPin, PinStatus ulVal) {
extern "C" void digitalWrite(pin_size_t ulPin, PinStatus ulVal) __attribute__((weak, alias("__digitalWrite")));
extern "C" void __digitalWrite(pin_size_t ulPin, PinStatus ulVal) {
if (ulPin > 29) {
DEBUGCORE("ERROR: Illegal pin in pinMode (%d)\n", ulPin);
return;
@@ -82,7 +101,8 @@ extern "C" void digitalWrite(pin_size_t ulPin, PinStatus ulVal) {
}
}
extern "C" PinStatus digitalRead(pin_size_t ulPin) {
extern "C" PinStatus digitalRead(pin_size_t ulPin) __attribute__((weak, alias("__digitalRead")));
extern "C" PinStatus __digitalRead(pin_size_t ulPin) {
if (ulPin > 29) {
DEBUGCORE("ERROR: Illegal pin in digitalRead (%d)\n", ulPin);
return LOW;
+76 -27
View File
@@ -22,48 +22,77 @@
#include <CoreMutex.h>
#include <hardware/gpio.h>
#include <hardware/sync.h>
#include <stack>
#include <map>
// Support nested IRQ disable/re-enable
static std::stack<uint32_t> _irqStack[2];
#define maxIRQs 15
static uint32_t _irqStackTop[2] = { 0, 0 };
static uint32_t _irqStack[2][maxIRQs];
extern "C" void interrupts() {
if (_irqStack[get_core_num()].empty()) {
auto core = get_core_num();
if (!_irqStackTop[core]) {
// ERROR
return;
}
auto oldIrqs = _irqStack[get_core_num()].top();
_irqStack[get_core_num()].pop();
restore_interrupts(oldIrqs);
restore_interrupts(_irqStack[core][--_irqStackTop[core]]);
}
extern "C" void noInterrupts() {
_irqStack[get_core_num()].push(save_and_disable_interrupts());
auto core = get_core_num();
if (_irqStackTop[core] == maxIRQs) {
// ERROR
panic("IRQ stack overflow");
}
_irqStack[core][_irqStackTop[core]++] = save_and_disable_interrupts();
}
// Only 1 GPIO IRQ callback for all pins, so we need to look at the pin it's for and
// dispatch to the real callback manually
auto_init_mutex(_irqMutex);
static std::map<pin_size_t, voidFuncPtr> _map;
class CBInfo {
public:
CBInfo(voidFuncPtr cb) : _cb(cb), _useParam(false), _param(nullptr) { };
CBInfo(voidFuncPtrParam cbParam, void *param) : _cbParam(cbParam), _useParam(true), _param(param) { };
void callback() {
if (_useParam && _cbParam) {
_cbParam(_param);
} else if (_cb) {
_cb();
}
}
private:
union {
voidFuncPtr _cb;
voidFuncPtrParam _cbParam;
};
bool _useParam;
void *_param;
};
static std::map<pin_size_t, CBInfo> _map;
void _gpioInterruptDispatcher(uint gpio, uint32_t events) {
(void) events;
// Only need to lock around the std::map check, not the whole IRQ callback
voidFuncPtr cb = nullptr;
{
CoreMutex m(&_irqMutex);
if (m) {
auto irq = _map.find(gpio);
if (irq != _map.end()) {
cb = irq->second;
}
CoreMutex m(&_irqMutex, (FromISR | DebugEnable));
if (m) {
auto irq = _map.find(gpio);
if (irq != _map.end()) {
auto cb = irq->second;
cb.callback();
}
}
if (cb) {
cb(); // Do the callback
} else {
// ERROR, but we're in an IRQ so do nothing
}
// To be called when appropriately protected w/IRQ and mutex protects
static void _detachInterruptInternal(pin_size_t pin) {
auto irq = _map.find(pin);
if (irq != _map.end()) {
gpio_set_irq_enabled(pin, 0x0f /* all */, false);
_map.erase(pin);
}
}
@@ -83,8 +112,32 @@ extern "C" void attachInterrupt(pin_size_t pin, voidFuncPtr callback, PinStatus
default: return; // ERROR
}
noInterrupts();
detachInterrupt(pin);
_map.insert({pin, callback});
_detachInterruptInternal(pin);
CBInfo cb(callback);
_map.insert({pin, cb});
gpio_set_irq_enabled_with_callback(pin, events, true, _gpioInterruptDispatcher);
interrupts();
}
void attachInterruptParam(pin_size_t pin, voidFuncPtrParam callback, PinStatus mode, void *param) {
CoreMutex m(&_irqMutex);
if (!m) {
return;
}
uint32_t events;
switch (mode) {
case LOW: events = 1; break;
case HIGH: events = 2; break;
case FALLING: events = 4; break;
case RISING: events = 8; break;
case CHANGE: events = 4 | 8; break;
default: return; // ERROR
}
noInterrupts();
_detachInterruptInternal(pin);
CBInfo cb(callback, param);
_map.insert({pin, cb});
gpio_set_irq_enabled_with_callback(pin, events, true, _gpioInterruptDispatcher);
interrupts();
}
@@ -96,10 +149,6 @@ extern "C" void detachInterrupt(pin_size_t pin) {
}
noInterrupts();
auto irq = _map.find(pin);
if (irq != _map.end()) {
gpio_set_irq_enabled(pin, 0x0f /* all */, false);
_map.erase(pin);
}
_detachInterruptInternal(pin);
interrupts();
}
+17 -1
View File
@@ -13,6 +13,11 @@ int analogRead(pin_size_t pin = A0..A3)
Returns a value from 0...4095 correspionding to the ADC reading
of the specific pin.
void analogReadResolution(int bits)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Determines the resolution (in bits) of the value returned by the analogRead() function.
Default resolution is 10bit.
float analogReadTemp()
~~~~~~~~~~~~~~~~~~~~~~
Returns the temperature, in Celsius, of the onboard thermal sensor.
@@ -30,10 +35,21 @@ While up to 16 PWM channels can be generated, they are not independent
and there are significant restrictions as to allowed pins in parallel.
See the `RP2040 datasheet <https://datasheets.raspberrypi.org/rp2040/rp2040-datasheet.pdf>`_ for full details.
Analog Output Restrictions
--------------------------
The PWM generator source clock restricts the legal combinations of
frequency and ranges. For example, at 1MHz only about 6 bits of range
are possible. When you define an ``analogWriteFreq`` and ``analogWriteRange``
that can't be fulfilled by the hardware, the frequency will be preserved
but the accuracy (range) will be reduced automatically. Your code will
still send in the range you specify, but the core itself will transparently
map it into the allowable PWN range.
void analogWriteFreq(uint32_t freq)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sets the master PWM frequency used (i.e. how often the PWM output cycles).
From 100Hz to 60KHz are supported.
From 100Hz to 1MHz are supported.
void analogWriteRange(uint32_t range) and analogWriteResolution(int res)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+146
View File
@@ -0,0 +1,146 @@
:orphan:
WiFiClientSecure Class
======================
`BearSSL::WiFiClientSecure` is the object which actually handles TLS encrypted WiFi connections to a remote server or client. It extends `WiFiClient` and so can be used with minimal changes to code that does unsecured communications.
Validating X509 Certificates (Am I talking to the server I think I'm talking to?)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Prior to connecting to a server, the `BearSSL::WiFiClientSecure` needs to be told how to verify the identity of the other machine. **By default BearSSL will not validate any connections and will refuse to connect to any server.**
There are multiple modes to tell BearSSL how to verify the identity of the remote server. See the `BearSSL_Validation` example for real uses of the following methods:
setInsecure()
^^^^^^^^^^^^^
Don't verify any X509 certificates. There is no guarantee that the server connected to is the one you think it is in this case.
setKnownKey(const BearSSL::PublicKey \*pk)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Assume the server is using the specific public key. This does not verify the identity of the server or the X509 certificate it sends, it simply assumes that its public key is the one given. If the server updates its public key at a later point then connections will fail.
setFingerprint(const uint8_t fp[20]) / setFingerprint(const char \*fpStr)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Verify the SHA1 fingerprint of the certificate returned matches this one. If the server certificate changes, it will fail. If an array of 20 bytes are sent in, it is assumed they are the binary SHA1 values. If a `char*` string is passed in, it is parsed as a series of human-readable hex values separated by spaces or colons (e.g. `setFingerprint("00:01:02:03:...:1f");`)
This fingerprint is calculated on the raw X509 certificate served by the server. In very rare cases, these certificates have certain encodings which should be normalized before taking a fingerprint (but in order to preserve memory BearSSL does not do this normalization since it would need RAM for an entire copy of the cert), and the fingerprint BearSSL calculates will not match the fingerprint OpenSSL calculates. In this case, you can enable SSL debugging and get a dump of BearSSL's calculated fingerprint and use that one in your code, or use full certificate validation. See the `original issue and debug here <https://github.com/esp8266/Arduino/issues/6209>`__.
setTrustAnchors(BearSSL::X509List \*ta)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use the passed-in certificate(s) as a trust anchor, accepting remote certificates signed by any of these. If you have many trust anchors it may make sense to use a `BearSSL::CertStore` because it will only require RAM for a single trust anchor (while the `setTrustAnchors` call requires memory for all certificates in the list).
setX509Time(time_t now)
^^^^^^^^^^^^^^^^^^^^^^^
For `setTrustAnchors` and `CertStore` , the current time (set via SNTP) is used to verify the certificate against the list, so SNTP must be enabled and functioning before the connection is attempted. If you cannot use SNTP for some reason, you can manually set the "present time" that BearSSL will use to validate a certificate with this call where `now` is standard UNIX time.
Client Certificates (Proving I'm who I say I am to the server)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TLS servers can request that a client identify themselves with an X509 certificate signed by a trust anchor it honors (i.e. a global TA or a private CA). This is commonly done for applications like MQTT. By default the client doesn't send a certificate, and in cases where a certificate is required the server will disconnect and no connection will be possible.
setClientRSACert / setClientECCert
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Sets a client certificate to send to a TLS server that requests one. It should be called before `connect()` to add a certificate to the client in case the server requests it. Note that certificates include both a certificate and a private key. Both should be provided to you by your certificate generator. Elliptic Curve (EC) keys require additional information, as shown in the prototype.
MFLN or Maximum Fragment Length Negotiation (Saving RAM)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Because TLS was developed on systems with many megabytes of memory, they require by default a 16KB buffer for receive and transmit. That's enormous for the ESP8266, which has only around 40KB total heap available.
We can (and do) minimize the transmission buffer down to slightly more than 512 bytes to save memory, since BearSSL can internally ensure transmissions larger than that are broken up into smaller chunks that do fit. But that still leaves the 16KB receive buffer requirement since we cannot in general guarantee the TLS peer will send in smaller chunks.
TLS 1.2 added MFLN, which lets a client negotiate smaller buffers with a server and reduce the memory requirements on the ESP8266. Unfortunately, BearSSL needs to know the buffer sizes before it begins connection, so applications that want to use smaller buffers need to check the remote server's support before `connect()` .
probeMaxFragmentLength(host, port, len)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use one of these calls **before** connection to determine if a specific fragment length is supported (len must be a power of two from 512 to 4096, per the specification). This does **not** initiate a SSL connection, it simply opens a TCP port and performs a trial handshake to check support.
setBufferSizes(int recv, int xmit)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Once you have verified (or know beforehand) that MFLN is supported you can use this call to set the size of memory buffers allocated by the connection object. This must be called **before** `connect()` or it will be ignored.
In certain applications where the TLS server does not support MFLN (not many do as of this writing as it is relatively new to OpenSSL), but you control both the ESP8266 and the server to which it is communicating, you may still be able to `setBufferSizes()` smaller if you guarantee no chunk of data will overflow those buffers.
bool getMFLNStatus()
^^^^^^^^^^^^^^^^^^^^
After a successful connection, this method returns whether or not MFLN negotiation succeeded or not. If it did not succeed, and you reduced the receive buffer with `setBufferSizes` then you may experience reception errors if the server attempts to send messages larger than your receive buffer.
Sessions (Resuming connections fast)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
setSession(BearSSL::Session &sess)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you are connecting to a server repeatedly in a fixed time period (usually 30 or 60 minutes, but normally configurable at the server), a TLS session can be used to cache crypto settings and speed up connections significantly.
Errors
~~~~~~
BearSSL can fail in many more unique and interesting ways. Use these calls to get more information when something fails.
getLastSSLError(char \*dest = NULL, size_t len = 0)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Returns the last BearSSL error code encountered and optionally set a user-allocated buffer to a human-readable form of the error. To only get the last error integer code, just call without any parameters (`int errCode = getLastSSLError();`).
Limiting Ciphers (New connections faster)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There is very rarely reason to use these calls, but they are available.
setCiphers()
^^^^^^^^^^^^
Takes an array (in PROGMEM is valid) or a std::vector of 16-bit BearSSL cipher identifiers and restricts BearSSL to only use them. If the server requires a different cipher, then connection will fail. Generally this is not useful except in cases where you want to connect to servers using a specific cipher. See the BearSSL headers for more information on the supported ciphers.
setCiphersLessSecure()
^^^^^^^^^^^^^^^^^^^^^^
Helper function which essentially limits BearSSL to less secure ciphers than it would natively choose, but they may be helpful and faster if your server depended on specific crypto options.
Limiting TLS(SSL) Versions
~~~~~~~~~~~~~~~~~~~~~~~~~~
By default, BearSSL will connect with TLS 1.0, TLS 1.1, or TLS 1.2 protocols (depending on the request of the remote side). If you want to limit to a subset, use the following call:
setSSLVersion(uint32_t min, uint32_t max)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Valid values for min and max are `BR_TLS10`, `BR_TLS11`, `BR_TLS12`. Min and max may be set to the same value if only a single TLS version is desired.
ESP32 Compatibility
===================
Simple ESP32 ``WiFiClientSecure`` compatibility is built-in, allow for some sketches to run without any modification.
The following methods are implemented:
.. code :: cpp
void setCACert(const char *rootCA);
void setCertificate(const char *client_ca);
void setPrivateKey(const char *private_key);
bool loadCACert(Stream& stream, size_t size);
bool loadCertificate(Stream& stream, size_t size);
bool loadPrivateKey(Stream& stream, size_t size);
int connect(IPAddress ip, uint16_t port, int32_t timeout);
int connect(const char *host, uint16_t port, int32_t timeout);
int connect(IPAddress ip, uint16_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key);
int connect(const char *host, uint16_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key);
Note that the SSL backend is very different between Arduino-Pico and ESP32-Arduino (BearSSL vs. mbedTLS). This means
that, for instance, the SSL connection will check valid dates of certificates (and hence require system time to be
set on the Pico, which is automatically done in this case).
TLS-Pre Shared Keys (PSK) is not supported by BearSSL, and hence not implemented here. Neither is ALPN.
For more advanced control, it is recommended to port to the native Pico calls which allows much more flexibility and control.
+64
View File
@@ -0,0 +1,64 @@
:orphan:
WiFiServerSecure Class
----------------------
Implements a TLS encrypted server with optional client certificate validation. See `Server Class <server-class.rst>`__ for general information and `BearSSL Secure Client Class <bearssl-client-secure-class.rst>`__ for basic server and BearSSL concepts.
setBufferSizes(int recv, int xmit)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Similar to the `BearSSL::WiFiClientSecure` method, sets the receive and transmit buffer sizes. Note that servers cannot request a buffer size from the client, so if these are shrunk and the client tries to send a chunk larger than the receive buffer, it will always fail. Needs to be called before `begin()`
Setting Server Certificates
~~~~~~~~~~~~~~~~~~~~~~~~~~~
TLS servers require a certificate identifying itself and containing its public key, and a private key they will use to encrypt information with. The application author is responsible for generating this certificate and key, either using a self-signed generator or using a commercial certification authority. **Do not re-use the certificates included in the examples provided.**
This example command will generate a RSA 2048-bit key and certificate:
.. code:: bash
openssl req -x509 -nodes -newkey rsa:2048 -keyout key.pem -out cert.pem -days 4096
Again, it is up to the application author to generate this certificate and key and keep the private key safe and **private.**
setRSACert(const BearSSL::X509List \*chain, const BearSSL::PrivateKey \*sk)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Sets a RSA certificate and key to be used by the server when connections are received. Needs to be called before `begin()`
setECCert(const BearSSL::X509List \*chain, unsigned cert_issuer_key_type, const BearSSL::PrivateKey \*sk)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Sets an elliptic curve certificate and key for the server. Needs to be called before `begin()`.
Client sessions (Resuming connections fast)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The TLS handshake process takes a long time because of all the back and forth between the client and the server. You can shorten it by caching the clients' sessions which will skip a few steps in the TLS handshake. In order for this to work, your client also needs to cache the session. `BearSSL::WiFiClientSecure <bearssl-client-secure-class.rst#sessions-resuming-connections-fast>`__ can do that as well as modern web browsers.
Here are the kind of performance improvements that you'll be able to see for TLS handshakes with an ESP8266 with it's clock set at 160MHz on a network with fairly low latency:
* With an EC key of 256 bits, a request taking ~360ms without caching takes ~60ms with caching.
* With an RSA key of 2048 bits, a request taking ~1850ms without caching takes ~70ms with caching.
setCache(BearSSL::ServerSessions \*cache)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Sets the cache for the server's sessions. When choosing the size of the cache, remember that each client session takes 100 bytes. If you setup a cache for 10 sessions, it will take 1000 bytes. Needs to be called before `begin()`
When creating the cache, you can use any of the 2 available constructors:
* `BearSSL::ServerSessions(ServerSession *sessions, uint32_t size)`: Creates a cache with the given buffer and number of sessions.
* `BearSSL::ServerSessions(uint32_t size)`: Dynamically allocates a cache for the given number of sessions.
Requiring Client Certificates
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TLS servers can request the client to identify itself by transmitting a certificate during handshake. If the client cannot transmit the certificate, the connection will be dropped by the server.
setClientTrustAnchor(const BearSSL::X509List \*client_CA_ta)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Sets the trust anchor (normally a self-signing CA) that all received certificates will be verified against. Needs to be called before `begin()`.
+113
View File
@@ -0,0 +1,113 @@
:orphan:
BearSSL WiFi Classes
--------------------
Methods and properties described in this section are specific to the Raspberry Pi Pico W and the ESP8266. They are not covered in `Arduino WiFi library <https://www.arduino.cc/en/Reference/WiFi>`__ documentation. Before they are fully documented please refer to information below.
The `BearSSL <https://bearssl.org>`__ library (with modifications for ESP8266 compatibility and to use ROM tables whenever possible) is used to perform all cryptography and TLS operations. The main ported repo is available `on GitHub <https://github.com/earlephilhower/bearssl-esp8266>`__.
CPU Requirements
~~~~~~~~~~~~~~~~
SSL operations take significant CPU cycles to run, so it will connect significantly slower than unprotected connections on the Pico, but the actual data transfer rates once connected are similar.
See the section on `sessions <#sessions-resuming-connections-fast>`__ and `limiting cryptographic negotiation <#limiting-ciphers-new-connections-faster>`__ for ways of ensuring faster modes are used.
Memory Requirements
~~~~~~~~~~~~~~~~~~~
BearSSL doesn't perform memory allocations at runtime, but it does require allocation of memory at the beginning of a connection. There are two memory chunks required:
. A per-application secondary stack
. A per-connection TLS receive/transmit buffer plus overhead
The per-application secondary stack is approximately 7KB in size and is used for temporary variables during BearSSL processing. Only one stack is required, and it will be allocated whenever any `BearSSL::WiFiClientSecure` or `BearSSL::WiFiServerSecure` are instantiated. So, in the case of a global client or server, the memory will be allocated before `setup()` is called.
The per-connection buffers are approximately 22KB in size, but in certain circumstances it can be reduced dramatically by using MFLN or limiting message sizes. See the `MLFN section <#mfln-or-maximum-fragment-length-negotiation-saving-ram>`__ below for more information.
Object Lifetimes
~~~~~~~~~~~~~~~~
There are many configuration options that require passing in a pointer to an object (i.e. a pointer to a private key, or a certificate list). In order to preserve memory, BearSSL does NOT copy the objects passed in via these pointers and as such any pointer passed in to BearSSL needs to be preserved for the life of the client object. For example, the following code is **in error**:
.. code:: cpp
BearSSL::WiFiClientSecure client;
const char x509CA PROGMEM = ".......";
void setup() {
BearSSL::X509List x509(x509CA);
client.setTrustAnchor(&x509);
}
void loop() {
client.connect("192.168.1.1", 443);
}
Because the pointer to the local object `x509` no longer is valid after setup(), expect to crash in the main `loop()` where it is accessed by the `client` object.
As a rule, either keep your objects global, use `new` to create them, or ensure that all objects needed live inside the same scope as the client.
TLS and HTTPS Basics
~~~~~~~~~~~~~~~~~~~~
The following discussion is only intended to give a rough idea of TLS/HTTPS(which is just HTTP over a TLS connection) and the components an application needs to manage to make a TLS connection. For more detailed information, please check the relevant `RFC 5246 <https://tools.ietf.org/search/rfc5246>`__ and others.
TLS can be broken into two stages: verifying the identities of server (and potentially client), and then encrypting blocks of data bidirectionally. Verifying the identity of the other partner is handled via keys encoded in X509 certificates, optionally signed by a series of other entities.
Public and Private Keys
~~~~~~~~~~~~~~~~~~~~~~~
Cryptographic keys are required for many of the BearSSL functions. Both public and private keys are supported, with either Elliptic Curve or RSA key support.
To generate a public or private key from an existing PEM (ASCII format) or DER (binary format), the simplest method is to use the constructor:
.. code:: cpp
BearSSL::PublicKey(const char *pemString)
... or ...
BearSSL::PublicKey(const uint8_t *derArray, size_t derLen)
Note that `PROGMEM` strings and arrays are natively supported by these constructors and no special `*_P` modes are required. There are additional functions to identify the key type and access the underlying BearSSL proprietary types, but they are not needed by user applications.
TLS Sessions
~~~~~~~~~~~~
TLS supports the notion of a session (completely independent and different from HTTP sessions) which allow clients to reconnect to a server without having to renegotiate encryption settings or validate X509 certificates. This can save significant time (3-4 seconds in the case of EC keys) and can help save power by allowing the ESP8266 to sleep for a long time, reconnect and transmit some samples using the SSL session, and then jump back to sleep quicker.
`BearSSL::Session` is an opaque class. Use the `BearSSL::WiFiClientSecure.setSession(&BearSSLSession)` method to apply it before the first `BearSSL::WiFiClientSecure.connect()` and it will be updated with session parameters during the operation of the connection. After the connection has had `.close()` called on it, serialize the `BearSSL::Session` object to stable storage (EEPROM, RTC RAM, etc.) and restore it before trying to reconnect. See the `BearSSL_Sessions` example for a detailed example.
`Sessions <#sessions-resuming-connections-fast>`__ contains additional information on the sessions API.
X.509 Certificate(s)
~~~~~~~~~~~~~~~~~~~~
X509 certificates are used to identify peers in TLS connections. Normally only the server identifies itself, but the client can also supply an X509 certificate if desired (this is often done in MQTT applications). The certificate contains many fields, but the most interesting in our applications are the name, the public key, and potentially a chain of signing that leads back to a trusted authority (like a global internet CA or a company-wide private certificate authority).
Any call that takes an X509 certificate can also take a list of X509 certificates, so there is no special `X509` class, simply `BearSSL::X509List` (which may only contain a single certificate).
Generating a certificate to be used to validate using the constructor
.. code:: cpp
BearSSL::X509List(const char *pemX509);
...or...
BearSSL::X509List(const uint8_t *derCert, size_t derLen);
If you need to add additional certificates (unlikely in normal operation), the `::append()` operation can be used.
Certificate Stores
~~~~~~~~~~~~~~~~~~
The web browser you're using to read this document keeps a list of 100s of certification authorities (CAs) worldwide that it trusts to attest to the identity of websites.
In many cases your application will know the specific CA it needs to validate web or MQTT servers against (often just a single, self-signing CA private to your institution). Simply load your private CA in a `BearSSL::X509List` and use that as your trust anchor.
However, there are cases where you will not know beforehand which CA you will need (i.e. a user enters a website through a keypad), and you need to keep the list of CAs just like your web browser. In those cases, you need to generate a certificate bundle on the PC while compiling your application, upload the `certs.ar` bundle to LittleFS or SD when uploading your application binary, and pass it to a `BearSSL::CertStore()` in order to validate TLS peers.
See the `BearSSL_CertStore` example for full details.
Supported Crypto
~~~~~~~~~~~~~~~~
Please see the `BearSSL website <https://bearssl.org>`__ for detailed cryptographic information. In general, TLS 1.2, TLS 1.1, and TLS 1.0 are supported with RSA and Elliptic Curve keys and a very rich set of hashing and symmetric encryption codes. Please note that Elliptic Curve (EC) key operations take a significant amount of time.
+6 -6
View File
@@ -19,7 +19,7 @@
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
import sphinx_rtd_theme
# -- General configuration ------------------------------------------------
@@ -30,7 +30,7 @@
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = []
extensions = ['sphinx_rtd_theme']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@@ -46,7 +46,7 @@ master_doc = 'index'
# General information about the project.
project = u'Arduino-Pico'
copyright = u'2021, Earle F. Philhower, III'
copyright = u'2022, Earle F. Philhower, III'
author = u'Earle F. Philhower, III'
# The version info for the project you're documenting, acts as replacement for
@@ -54,9 +54,9 @@ author = u'Earle F. Philhower, III'
# built documents.
#
# The short X.Y version.
version = u'1.0.0'
version = u'2.6.4'
# The full version, including alpha/beta/rc tags.
release = u'1.0.0'
release = u'2.6.4'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -82,7 +82,7 @@ todo_include_todos = False
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'
html_theme = 'sphinx_rtd_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
+8
View File
@@ -6,6 +6,14 @@ Board-Specific Pins
The Raspberry Pi Pico RP2040 chip supports up to 30 digital I/O pins,
however not all boards provide access to all pins.
Input Modes
-----------
The Raspberry Pi Pico has 3 Input modes settings for use with `pinMode`: `INPUT`, `INPUT_PULLUP` and `INPUT_PULLDOWN`
Output Modes (Pad Strength)
---------------------------
The Raspberry Pi Pico has the ability to set the current that a pin (actually the pad associated with it) is capable of supplying. The current can be set to values of 2mA, 4mA, 8mA and 12mA. By default, on a reset, the setting is 4mA. A `pinMode(x, OUTPUT)`, where `x` is the pin number, is also the default setting. 4 settings have been added for use with `pinMode`: `OUTPUT_2MA`, `OUTPUT_4MA`, which has the same behavior as `OUTPUT`, `OUTPUT_8MA` and `OUTPUT_12MA`.
Tone/noTone
-----------
Simple square wave tone generation is possible for up to 8 channels using
+1 -1
View File
@@ -55,4 +55,4 @@ Returns the length of the EEPROM (i.e. the value specified in
EEPROM Examples
---------------
Three EEPROM `examples<https://github.com/earlephilhower/arduino-pico/tree/master/libraries/EEPROM>`_ are included.
Three EEPROM `examples <https://github.com/earlephilhower/arduino-pico/tree/master/libraries/EEPROM>`_ are included.
+49
View File
@@ -0,0 +1,49 @@
FreeRTOS SMP
============
The SMP (multicore) port of FreeRTOS is included with the core. This allows complex
task operations and real preemptive multithreading in your sketches. While the
``setup1`` and ``loop1`` way of multitasking is simplest for most folks, FreeRTOS
is much more powerful.
Enabling FreeRTOS
-----------------
To enable FreeRTOS, simply add
.. code:: c++
#include <FreeRTOS.h>
to your sketch and it will be included and enabled automatically.
Configuration and Predefined Tasks
----------------------------------
FreeRTOS is configured with 8 priority levels (0 through 7) and a process for
``setup()/loop()``, ``setup1()/loop1()``, and the USB port will be created. The task
quantum is 1 millisecond (i.e. 1,000 switches per second).
``setup()`` and ``loop()`` are assigned to only run on core 0, while ``setup1()`` and ``loop1()``
only run in core 1 in this mode, the same as the default multithreading mode.
You can launch and manage additional processes using the standard FreeRTOS routines.
``delay()`` and ``yield()`` free the CPU for other tasks, while ``delayMicroseconds()`` does not.
Caveats
-------
While the core now supports FreeRTOS, most (probably all) Arduino libraries were not written
to support preemptive multithreading. This means that all calls to a particular library should
be made from a single task.
In particular, the ``LittleFS`` and ``SDFS`` libraries can not be called from different
threads. Do all ``File`` operations from a single thread or else undefined behavior
(aka strange crashes or data corruption) can occur.
More Information
----------------
For full FreeRTOS documentation look at `FreeRTOS.org <https://freertos.org/index.html>`__
and `FreeRTOS SMP support <https://freertos.org/symmetric-multiprocessing-introduction.html>`__.
+11 -1
View File
@@ -98,9 +98,19 @@ The included ``SD`` library is the Arduino standard one. Please refer to
the [Arduino SD reference](https://www.arduino.cc/en/reference/SD) for
more information.
Using Second SPI port for SD
----------------------------
The ``SD`` library ``begin()`` has been modified to allow you to use the
second SPI port, ``SPI1``. Just use the following call in place of
``SD.begin(cspin)``
.. code:: cpp
SD.begin(cspin, SPI1);
File system object (LittleFS/SD/SDFS)
--------------------------------------------
-------------------------------------
setConfig
~~~~~~~~~
+40
View File
@@ -0,0 +1,40 @@
HTTPClient Library
==================
A simple HTTP requestor that can handle both HTTP and HTTP requests is
included as the ``HTTPClient`` library.
Check the examples for use under HTTP and HTTPS configurations. In general,
for HTTP connections (unsecured and very uncommon on the internet today) simply
passing in a URL and performiung a GET is sufficient to transfer data.
.. code:: cpp
// Error checking is left as an exercise for the reader...
HTTPClient http;
if (http.begin("http://my.server/url")) {
if (http.GET() > 0) {
String data = http.getString();
}
http.end();
}
For HTTPS connections, simply add the appropriate WiFiClientSecure calls
as needed (i.e. ``setInsecure()``, ``setTrustAnchor``, etc.). See the
WiFiClientSecure documentation for more details.
.. code:: cpp
// Error checking is left as an exercise for the reader...
HTTPClient https;
https.setInsecure(); // Use certs, but do not check their authenticity
if (https.begin("https://my.secure.server/url")) {
if (https.GET() > 0) {
String data = https.getString();
}
https.end();
}
Unlike the ESP8266 and ESP32 ``HTTPClient`` implementations it is not necessary
to create a ``WiFiClient`` or ``WiFiClientSecure`` to pass in to the ``HTTPClient``
object.
+144 -52
View File
@@ -1,89 +1,181 @@
I2S (Digital Audio) Output Library
==================================
I2S (Digital Audio) Audio Library
=================================
While the RP2040 chip on the Raspberry Pi Pico does not include a hardware
I2S device, it is possible to use the PIO (Programmable I/O) state machines
to implement one dynamically.
This I2S library uses the ``pico-extras`` I2S audio library and wraps it in
an Arduino I2S library. It supports 16 bits/sample and frequencies of up
to 48kHZ, with configurable BCLK, LRCLK(always pin "BCLK + 1"), and DOUT pins.
Digital audio input and output are supported at 8, 16, 24, and 32 bits per
sample.
Theoretically up to 6 I2S ports may be created, but in practice there
may not be enough resources (DMA, PIO SM) to actually create and use so
many.
Create an I2S port by instantiating a variable of the I2S class
specifying the direction. Configure it using API calls below before
using it.
**Note:** This I2S device takes over the entire PIO1 (second) unit and adjusts
its clock frequency to meet the I2S needs. That means when only 4 Tones
or only 4 Servos may be used when the I2S device is used.
I2S Class API
-------------
I2S(OUTPUT)
~~~~~~~~~~~
Creates an I2S output port. Needs to be connected up to the
desired pins (see below) and started before any output can happen.
I2S(INPUT)
~~~~~~~~~~
Creates an I2S input port. Needs to be connected up to the
desired pins (see below) and started before any input can happen.
bool setBCLK(pin_size_t pin)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sets the BCLK pin of the I2S device. The LRCLK/word clock will be ``pin + 1``
due to limitations of the PIO state machines. Call this before ``I2S.begin()``
Default BCLK = 26, LRCLK = 27
due to limitations of the PIO state machines. Call this before ``I2S::begin()``
bool setDOUT(pin_size_t pin)
bool setDATA(pin_size_t pin)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sets the DOUT pin of the I2S device. Any pin may be used. Default DOUT = 28
Call before ``I2S.begin()``
Sets the DOUT or DIN pin of the I2S device. Any pin may be used.
Call before ``I2S::begin()``
bool begin(long sampleRate)
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Start the I2S device up with the given sample rate. The pins selected above
will be turned to output and the I2S will begin to drive silence frames (all
zero) out.
bool setBitsPerSample(int bits)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Specify how many bits per audio sample to read or write. Note that
for 24-bit samples, audio samples must be left-aligned (i.e. bits 31...8).
Call before ``I2S::begin()``
bool setBuffers(size_t buffers, size_t bufferWords, int32_t silenceSample = 0)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Set the number of DMA buffers and their size in 32-bit words as well as
the word to fill when no data is available to send to the I2S hardware.
Call before ``I2S::begin()``.
bool setFrequency(long sampleRate)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sets the word clock frequency, but does not start the I2S device if not
already running. May be called after ``I2S::begin()`` to change the
sample rate on-the-fly.
bool begin()/begin(long sampleRate)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Start the I2S device up with the given sample rate, or with the value set
using the prior ``setFrequency`` call.
void end()
~~~~~~~~~~
Stops the I2S device. **Note, at present the memory allocated for I2S buffers
is not freed leading to a memory leak when ``end()`` is called. This is due
to the state of the ``pico-extras`` release which this code uses.**
Stops the I2S device.
void flush()
~~~~~~~~~~~~
Sends any partial frames in memory to the I2S output device. They may NOT play
immediately. Potential use case for this call would be when the frequency of
the output will be changing.
Waits until all the I2S buffers have been output.
size_t write(uint8_t)
~~~~~~~~~~~~~~~~~~~~~
Provided for compatibility, but not very useful. Writes a sample from 0...255
to the I2S buffer. See ``write(int16_t)`` for a better one
size_t write(uint8_t/int8_t/int16_t/int32_t)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Writes a single sample of ``bitsPerSample`` to the buffer. It is up to the
user to keep track of left/right channels. Note this writes data equivalent
to one channel's data, not the size of the passed in variable (i.e. if you have
a 16-bit sample size and ``write((int8_t)-5); write((int8_t)5);`` you will have
written **2 samples** to the I2S buffer of whatever the I2S size, not a single
16-bit sample.
This call will block (wait) until space is available to actually write
the data.
size_t write(int32_t val, bool sync)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Writes 32 bits of data to the I2S buffer (regardless of the configured I2S
bit size). When ``sync`` is true, it will not return until the data has
been writte. When ``sync`` is false, it will return ``0`` immediately if
there is no space present in the I2S buffer.
size_t write(const uint8_t \*buffer, size_t size)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Transfers number of bytes from an application buffer to the I2S output buffer.
Be aware that ``size`` is in *bytes** and not samples. Size must be a multiple
of **4 bytes** (i.e. one left/right sample). Will not block, so check
the return value to find out how many bytes were actually written.
of **4 bytes**. Will not block, so check the return value to find out how
many bytes were actually written.
int availableForWrite()
~~~~~~~~~~~~~~~~~~~~~~~
Returns the number of **32-bit L/R samples** that can be written without
Returns the number of L/R samples that can be written without
potentially blocking.
bool setFrequency(int newFreq)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Adjusts the I2S output frequency. When changing frequency while I2S output
is underway, be sure to use ``I2S.flush()`` before changing the frequency to
ensure the older data is played at the right frequency.
int read()
~~~~~~~~~~
Reads a single sample of I2S data, whatever the I2S sample size is configured.
Will not return until data is available.
size_t write(int16_t)
~~~~~~~~~~~~~~~~~~~~~
Writes a single 16-bit left or right sample to the I2S output buffer. The
user is required to ensure that an even number of samples is written (i.e.
left and right) over the application lifetime. The application also needs
to track which sample is next to be written (right/left). For this reason,
the ``write(void *b, size_t lrsamples)`` call may be easier and faster to use.
int peek()
~~~~~~~~~~
Returns the next sample to be read from the I2S buffer (without actually
removing it).
size_t write(const void \*buffer, size_t lrsamples)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Writes up to size left+right packed samples to the I2S device. Non-blocking,
will writefrom 0...size samples and return that count. Be sure your app
handles partial writes (i.e. by ``yield()`` ing and then retrying to write the
remaining data.)
void onTransmit(void (\*fn)(void))
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sets a callback to be called when an I2S DMA buffer is fully transmitted.
Will be in an interrupt context so the specified function must operate
quickly and not use blocking calls like delay() or write to the I2S.
The ``onTransmit`` callback is not supported.
void onReceive(void (\*fn)(void))
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sets a callback to be called when an I2S DMA buffer is fully read in.
Will be in an interrupt context so the specified function must operate
quickly and not use blocking calls like delay() or read from the I2S.
See the `ESP8266Audio <https://github.com/earlephilhower/ESP8266Audio>`_ library
for a working example, or look at the included sample tone generator.
Sample Writing/Reading API
--------------------------
Because I2S streams consist of a natural left and right sample, it is often
convenient to write or read both with a single call. The following calls
allow applications to read or write both samples at the same time, and
explicitly indicate the bit widths required (to avoid potential issues with
type conversion on calls).
size_t write8(int8_t l, int8_t r)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Writes a left and right 8-bit sample to the I2S buffers. Blocks until space
is available.
size_t write16(int16_t l, int16_t r)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Writes a left and right 16-bit sample to the I2S buffers. Blocks until space
is available.
size_t write24(int32_t l, int32_t r)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Writes a left and right 24-bit sample to the I2S buffers. See note below
about 24-bit mode. Blocks until space is available.
size_t write32(int32_t l, int32_t r)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Writes a left and right 32-bit sample to the I2S buffers. Blocks until space
is available.
bool read8(int8_t \*l, int8_t \*r)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Reads a left and right 8-bit sample and returns ``true`` on success. Will block
until data is available.
bool read16(int16_t \*l, int16_t \*r)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Reads a left and right 16-bit sample and returns ``true`` on success. Will block
until data is available.
bool read24(int32_t \*l, int32_t \*r)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Reads a left and right 24-bit sample and returns ``true`` on success. See note below
about 24-bit mode. Will block until data is available.
bool read32(int32_t \*l, int32_t \*r)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Reads a left and right 32-bit sample and returns ``true`` on success. Will block
until data is available.
Note About 24-bit Samples
-------------------------
24-bit samples are stored as left-aligned 32-bit values with bits 7..0
ignored. Only the upper 24 bits 31...8 will be transmitted or
received. The actual I2S protocol will only transmit or receive 24 bits
in this mode, even though the data is 32-bit packed.
+37
View File
@@ -34,3 +34,40 @@ Debug messages from `printf` and the Core can be printed to a Serial port
to allow for easier debugging. Select the desired port and verbosity.
Selecting a port for debug output does not stop a sketch from using it
for normal operations.
Generic RP2040 Support
----------------------
If your RP2040 board isn't in the menus you can still use it with the
IDE by using the `Board->Generic RP2040` menu option. You will need to
then set the flash size (see above) and tell the IDE how to communicate
with the flash chip using the `Tools->Boot Stage 2` menu.
Boot Stage 2 Options for Generic RP2040
---------------------------------------
The Arduino Pico needs to set up its internal flash interface to talk to
whatever flash chip is in the system. While all flash chips support a
basic (and slow) 1-bit operation using common timings, each different
brand (and sometimes model) of flash chip require custom timings to work
in QSPI (4-bit) mode. The `Boot Stage 2` menu lets you select from
the supported timings.
The options with `/2` in them divide the system clock by 2 to drive the
bus. Options with `/4` divide the clock by 4 and so are slower but more
compatible.
If you can't match a chip name in the menu to your flash chip, a simple
test can be run to determine which is correct. Simpily load the `Blink`
example, select the first option in the `Boot Stage 2` menu, and upload.
If that works, note it and continue. Iterate through the options and
note which ones work. If an option doesn't work, unplug the chip and
hold the BOOTSEL button down while re-inserting it to enter the ROM
uploader mode. (The CPU and flash will not be harmed if the test fails.)
If one of the custom bootloaders (not `Generic SPI /2 or /4`) worked, use
that option to get best performance. If none worked other than the
`Generic SPI /2 or /4` then use that. The `/2` options of all models
is preferred as it is faster, but some boards do require `/4` on the
custom chip interfaces.
When in doubt, `Generic SPI /4` should work with any flash chip but is
slow.
Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Some files were not shown because too many files have changed in this diff Show More