577 Commits

Author SHA1 Message Date
d967be0245 x
Some checks failed
Push (dev), Pull Request / Run Clang lint (push) Has been cancelled
Push (dev), Pull Request / Run Python lint (push) Has been cancelled
2026-01-02 01:43:15 -07:00
b040f336d4 (XXX) use scratch lwip 2026-01-02 01:43:15 -07:00
1bf1ea7596 [common] Log at warning level mDNS services or TXT records cannot be added 2026-01-02 01:43:15 -07:00
Kuba Szczodrzyński
29303f7ec9 [boards] Add generic-rtl8720cf-2mb-896k board
Some checks failed
Push (dev), Pull Request / Run Clang lint (push) Has been cancelled
Push (dev), Pull Request / Run Python lint (push) Has been cancelled
Push (master) / Deploy docs (push) Has been cancelled
2025-11-17 20:32:54 +01:00
Kuba Szczodrzyński
c6b06d4be6 [release] v1.9.2
Some checks failed
Release / Run Clang lint (push) Has been cancelled
Release / Publish PlatformIO platform (push) Has been cancelled
Release / Publish GitHub release (push) Has been cancelled
2025-09-19 22:44:44 +02:00
Kuba Szczodrzyński
c9b2f9dd23 [boards] Fix syntax error in WB02A 2025-09-19 22:44:44 +02:00
Kuba Szczodrzyński
40590d174f [core] Update ltchiptool to v4.12.2 2025-09-19 22:39:47 +02:00
Rishab Mehta
780fb72bba [docs] Update README.md (#323) 2025-09-19 22:37:02 +02:00
Henri Chain
e9977a26e4 [boards] Add WB02A board (#332) 2025-09-19 22:36:51 +02:00
Piotr Szulc
1d97f0ce84 [core] Avoid re-defining C++ round() method (#321) 2025-09-19 22:36:35 +02:00
Luca Olivetti
895b6e89c5 [lightning-ln882h] Fix GPIO interrupt support (#326)
* fix interrupt handling for the ln882h

- all GPIOS can generate interrupts
- added calls to NVIC_SetPriority/NVIC_EnableIRQ/NVIC_DisableIRQ

* fix clang formatting error

* only call NVIC_DisableIRQ if no other gpio is using an interrupt

* fix (again) clang-format errors

* add IRQ capability on all pins

* don't bother with NVIC_DisableIRQ

* use pin->gpio instead of interruptNumber, use macro GPIO_GET_PORT for clarity

* Mark interrupts as supported for the LN882H

---------

Co-authored-by: lamauny <pub.elc@free.fr>
2025-09-19 22:25:03 +02:00
Kuba Szczodrzyński
9114bc4c49 [release] v1.9.1
Some checks failed
Release / Run Clang lint (push) Has been cancelled
Release / Publish PlatformIO platform (push) Has been cancelled
Release / Publish GitHub release (push) Has been cancelled
2025-06-01 19:38:36 +02:00
Kuba Szczodrzyński
9eae0cd253 [common] Add Arduino emptyString declaration 2025-06-01 19:38:11 +02:00
Kuba Szczodrzyński
37f096d3b5 [release] v1.9.0
Some checks failed
Release / Run Clang lint (push) Has been cancelled
Release / Publish PlatformIO platform (push) Has been cancelled
Release / Publish GitHub release (push) Has been cancelled
2025-05-28 15:51:09 +02:00
Kuba Szczodrzyński
6bf549b104 [misc] Update .clang-format style 2025-05-28 15:50:18 +02:00
lamauny
3054db9d9b [lightning-ln882h] Fix analog read, add Wi-Fi calibration, add generic board (#319)
* [ln882x] fix analog read

* [ln882h] add wifi temp calibration task

* [ln882h] add generic-ln882hki board

* [ln882h] fix wifi null pointer crash
2025-05-28 15:45:10 +02:00
lamauny
69e7e2debe [lightning-ln882h] Add support for Lightning LN882H family (#312)
* fix mbedtls bad pointer in function call (prototype mismatch)

* fix issue with weak families functions implemented in static library, it will never be linked. fixed by redefining prototypes inside families

* [ln882x] add support for lightning ln882x & ln882h families

* add i2c (wire) support

* add analog (adc) support

* add watchdog support

* [ln882x] changed default uart 0/1 pins; added board wl2s

* [ln882x] fix IRQ & ADC pins

* [ln882x] boards cosmetic

* [ln882x] wifi sta use otp mac addr by default; re-enabled wifi powersave mode

* [ln882x] clang-format clean code

* [ln882x] clang-format clean code

* Update families.json

* Apply suggestions from code review

* [ln882x] reformat json board files

* [ln882x] os_queue cleanup

* [ln882x] removed Beken auto-download command

* [ln882x] removed personal script file

* [ln882x] removed unusefull pi section in debugging.md

* [ln882x] removed Arduino.h and changed private I2C definition

* [ln882x] updated README.md

* [ln882x] changed pin naming scheme to PA/PB

* [ln882x] clean code

* [ln882x] clean code

* [ln882x] add ota image verification

* Update push-dev.yml

* [ln882x] fix boards ADC missing inputs]

* [ln882x] removed reg_xxx fixup files and use include guards instead

* [ln882x] cleanup code

* [ln882x] cleanup code

* [ln882x] fix lt_init weak functions linking

* [ln882x] revert lt_api.h modification, fixed with previous commit

* [ln882x] setup UF2 firmware for flasher with partitions

* [ln882x] update README.md

* [ln882x] include ln_wifi.h and ln_serial.h to avoid including bad headers on case insensitive systems

* [ln882x] Replace RingBuffer by SerialRingBuffer

* [ln882x] clang-format

* [ln882x] update README.md

* Apply suggestions from code review

* Reformat board JSON files

* Add mkdocs link redirect

* Update ltchiptool to v4.12.0

---------

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2025-03-25 17:26:53 +01:00
Kuba Szczodrzyński
6083cca72e [misc] Update style to clang-format 19, black 25 and isort 6 2025-01-30 18:50:55 +01:00
Kuba Szczodrzyński
d17ea4da0f [release] v1.8.0
Some checks failed
Release / Run Clang lint (push) Has been cancelled
Release / Publish PlatformIO platform (push) Has been cancelled
Release / Publish GitHub release (push) Has been cancelled
2025-01-14 22:13:16 +01:00
Hajo Noerenberg
2ea0066536 [common] Make Serial RX buffer size configurable, increase default to 256 bytes (#313)
* Make Serial RX buffer configurable and set default to 256 bytes

* Replace RingBuffer by SerialRingBuffer
2025-01-13 12:14:41 +01:00
Martin Prokopič
3d23211c1e [realtek-ambz2] Fix partition table & bootloader flashing via UART (#307) 2024-12-17 17:13:04 +01:00
shilga
1769680d9e [realtek-ambz2] Fix C linkage for sys_now() in lwipopts (#286) 2024-12-17 11:50:44 +01:00
kuwoyuki
92351c0b92 [boards] Add RTL8710BX AFW121T board (#305)
* feat: afw121t board

* Update layout, regenerate with boardgen

---------

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2024-12-16 15:46:36 +01:00
Kuba Szczodrzyński
0f6c31386b [release] v1.7.0
Some checks failed
Release / Run Clang lint (push) Has been cancelled
Release / Publish PlatformIO platform (push) Has been cancelled
Release / Publish GitHub release (push) Has been cancelled
2024-09-05 16:41:10 +02:00
Kuba Szczodrzyński
a9009a8cee [misc] Update .clang-format style 2024-09-05 16:36:55 +02:00
Piotr Szulc
31e1d51dbd [common] Cleanup mDNS code, cache service records (#263)
* Handle possible failure of mdns_resp_add_service

* One more place where mdns_resp_add_service may fail

* addServiceImpl should always store services

* Register in services when new netif is added

* Refactored handling of cached services.

---------

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2024-09-05 15:54:04 +02:00
Luca Olivetti
41819f2fd6 [beken-72xx] Fix CHANGE interrupt logic (#290)
* fix CHANGE interrupt for beken-72xx

* Update cores/beken-72xx/arduino/src/wiring_irq.c

---------

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2024-09-05 14:46:42 +02:00
David Woodhouse
17043f634f [beken-72xx] Add IPv6 and lwIP 2.2.0 support (#292)
* mDNS: Fix build against LwIP 2.2.0

* Stop defining ip_addr_t when !CONFIG_IPV6

The only reason we had to do this is because we forgot to define LWIP_IPV4,
which is fixed in our LwIP port now, but keep it around for !CONFIG_IPV6
for now for builds against older LwIP.

* Allow returning IPv6 results from WiFiClass::hostByName()

* Add ipv6 and extra mDNS files for LwIP 2.2.0

* Add IPv6 support to BK72xx WifiSTA

Add an allLocalIPv6() method to return a *vector* of addresses, rather
than just one. It's not clear where the enableIpV6() and localIPv6()
methods came from; they don't seem to be part of the standard Arduino
class.

Eventually at least for ESPHome, I'd like to stop using these classes
and just let the ESPHome wifi component talk directly to LwIP. Or maybe
LibreTiny should offer an API compatible with the esp-idf one which is
a light wrapper around LwIP.

But short of a major refactor, this seems like a reasonable option.

* Update LwIP default to 2.2.0

* Apply suggestions from code review

---------

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2024-09-05 14:46:13 +02:00
devgs
e1c5761df9 [beken-72xx] Allow setting deep sleep wake-up pins as floating (#275)
According to guide `gpio_stay_*_map` are specifically there to prevent
pulling pins to a specific level and let them float during deep sleep.

https://docs.bekencorp.com/sdk_3.0.x/bk7238/build/en/latest/developer-guide/power_save/sleep_test.html

This allows any external low-power circuitry to change a pin level, as
required, to trigger the wake up

This requires changes in BDK and was implemented via fixup. Also, exposed
`gpio_stay_lo_map` parameter via `lt_deep_sleep_keep_floating_gpio` to
manage this configuration for pins in range P0-P31.
2024-09-05 14:45:48 +02:00
Kuba Szczodrzyński
fbaae21011 [release] v1.6.0
Some checks failed
Release / Run Clang lint (push) Has been cancelled
Release / Publish PlatformIO platform (push) Has been cancelled
Release / Publish GitHub release (push) Has been cancelled
2024-05-31 15:01:17 +02:00
Jaco Malan
fa2064b957 [realtek-ambz] Temporarily workaround CHANGE interrupts not supported (#282)
* fix change interruptsnot supported on rtl8710b

* Update cores/realtek-amb/arduino/src/wiring_irq.c

---------

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2024-05-31 14:59:46 +02:00
Kuba Szczodrzyński
21a194f43d [core] Fix lwIP debugging support 2024-05-31 14:58:38 +02:00
devgs
b255402659 [beken-72xx] Fix race condition when checking Wi-Fi SSID (#274)
* Fix for a race condition in WiFi connection loop

There seems to be the race between the event RW_EVT_STA_CONNECTED
and an actual valid SSID value returned by BDK. If even a small delay
is injected immediately after the event reception the valid value
becomes available. Without this fix, due to a polling nature of ESPHome
WiFiComponent::check_connecting_finished function may observe the
WiFiSTAConnectStatus::CONNECTED status but with an empty SSID value,
leading to `Incomplete connection.` warning and immediate attempt to
start another connection, while the current one was actually established.

* Fixed clang format conformance

* Apply suggestions from code review

* Update cores/beken-72xx/arduino/libraries/WiFi/WiFiEvents.cpp

Co-authored-by: Cossid <83468485+Cossid@users.noreply.github.com>

---------

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
Co-authored-by: Cossid <83468485+Cossid@users.noreply.github.com>
2024-05-31 14:54:41 +02:00
Kuba Szczodrzyński
dfabfbb921 [beken-72xx] Increase MBEDTLS_ENTROPY_MAX_SOURCES 2024-05-18 13:50:25 +02:00
Kuba Szczodrzyński
3b36a70c9a [core] Fix ESP_LOG#() macro syntax 2024-05-18 13:50:10 +02:00
Piotr Szulc
d1386a8e9d [libs] Fix mDNS string memory corruption, print error on record add failure (#260)
* Fixed unsafe conversion to underscore string

* Fixed formatting

* Save one byte if underscore not needed

* Don't allocate new string if already underscored

* Fix missing first character while copying

* Renamed function and made it inline

* Don't use signed index variable when searching for service

* Add proper cleanup of LwIPmDNS

- Free allocated memory both on end() and in the destructor
- Unregister callback from netif

* Don't free const pointer

* Removed unneeded casting

* Don't break the loop if failed to add txt record

* Fixed code formatting
2024-03-08 12:21:14 +01:00
Kuba Szczodrzyński
67b92b7f56 [release] v1.5.1
Some checks failed
Release / Run Clang lint (push) Has been cancelled
Release / Publish PlatformIO platform (push) Has been cancelled
Release / Publish GitHub release (push) Has been cancelled
2024-02-29 14:14:01 +01:00
Hajo Noerenberg
a1f8516e60 [realtek-ambz] Fix crash after WiFi scan (#258) 2024-02-26 21:35:35 +01:00
cap9qd
cf52021d38 [core] Split reboot reasons due to wakeup (#254)
* Updates to break out wakeup reasons.

Per https://github.com/libretiny-eu/libretiny/issues/234

* Update cores/common/base/api/lt_device.h

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>

* fix clang-format

* Fix formatting of python files.

* Update lt_device.h

---------

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2024-02-25 18:45:22 +01:00
cap9qd
b78c9387a6 [beken-72xx] Fix duration rollover in deep sleep (#253) 2024-02-22 20:24:40 +01:00
Kuba Szczodrzyński
b748d99437 [release] v1.5.0
Some checks failed
Release / Run Clang lint (push) Has been cancelled
Release / Publish PlatformIO platform (push) Has been cancelled
Release / Publish GitHub release (push) Has been cancelled
2024-02-20 17:16:15 +01:00
Anna
9a33fc0a69 [docs] Improve getting started guide (#252)
* Update Readme & improve md layout

- ESPHome now supports LibreTiny natively
- Added extra PIO docs references
- Reworded some sections slightly, to accomodate proper grammar
- PIO deprecated the `platformio platform install` command, replaced this with the official recommendation/replacement

* Use backslash for line break, revert changing indent

---------

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2024-02-20 17:14:12 +01:00
Hajo Noerenberg
4cddc01f22 [libs] Fix MD5 calculation during OTA update (#240) 2024-01-17 22:49:33 +01:00
Piotr Szulc
1d80b5fff7 [beken-72xx] Free list returned by wlan_sta_scan_result() (#226)
* Free list returned by wlan_sta_scan_result()

* scanAlloc improvements

There were a few things I didn't like about this function:
1) realloc() was called a bit too often.
2) if realloc() failed, the previous memory was not freed.
3) scanAlloc returned previous count or 255 on error. But there was no real check for error and 255 could've been used as index to null. I think it's better to simple return boolean.
4) scanAlloc was clearing memory only up to (and excluding) the new entries.

* Corrected clearing new entries in scanAlloc

* scanAlloc() now returns number of allocated items

* Fixed compilation issues related to goto.
2024-01-06 19:41:01 +01:00
Cossid
140cf07173 [docs] Use official ESPHome version, add LT dev version guide (#223)
* Update ESPHome documentation

* Update note format

* Switch to https github format, give manual PR checkout instructions until a better method is found.

* Fix yaml sample spacing

* Fix indent

* Add addon migration info

* Replace spaces with tabs

---------

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2024-01-06 19:40:44 +01:00
Piotr Szulc
1e3a82f439 [beken-72xx] Improve ddev ADC support (#220) 2024-01-06 19:40:33 +01:00
Cossid
c90794e9f5 [beken-72xx] Allow connecting to specific BSSID if provided (#209)
* Switch to bk_wlan_start_sta_adv for specific bssid control.

* Allow split sta/adv_sta configs.

* Add wifi_mode back for regular STA mode.

* Fix apparent bug of setting null/empty wifi key.
Reset STA_ADV_CFG.dhcp_mode in reconnect, as it seems to not survive for some reason.
Do les _CFG setting in reconnect()

* Move all _CFG setting to begin()

* Fix dhcp_mode in STA_ADV_CFG.

* Remove no longer necessary dhcp_mode re-set.

* Formatting cleanups.

* Formatting.

* Update cores/beken-72xx/arduino/libraries/WiFi/WiFiSTA.cpp

* Apply suggestions from code review

---------

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2024-01-06 19:40:08 +01:00
Kuba Szczodrzyński
03c723c73d [docs] Add draft Beken key extraction docs 2024-01-06 19:20:03 +01:00
Gerard Du Pre
bad2ffdd07 [docs] Update docker compose image name (#225)
The docs about using docker  compose for libre tuya had an error.
When setting what image to use in compose you dont have to put docker pull, just the image you are going to use
2023-12-25 19:42:53 +01:00
Piotr Szulc
eed39c9cfb [beken-72xx] Pause PWM instead of stopping, track PWM state (#222)
* Pause PWM instead of stopping on duty cycle 0.

* Merged paused and stopped conditions
2023-12-16 13:57:47 +01:00
Piotr Szulc
7bd6d1d815 [beken-72xx] Fix stopping PWM, use pin-scoped PWM struct (#215)
* Fixed stopping PWM

* Clang-formatted as required

* Use separate memory block for each pwm pin
2023-12-08 19:20:41 +01:00
Piotr Szulc
bb7fcd5c4d [docs] Add more UPK key descriptions (#219)
* Added description of some UPK keys

* More keys described.

This time by experimenting on my PIR-enabled lamp.
Motion is reported correctly via GPIO defined as pirin_pin.
I am also trying to set the PIR sensitivity by applying PWM to the pirsense_pin, and I _think_ it works. More experiments are needed.

* Add UPK2ESPHome link, reformat table

* Add descriptions from BK7231N SDK

* Update docs/resources/tuya-pin-config.md

* Corrected description of cwmaxp

* Description of ambient light sensor values

---------

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2023-12-08 19:13:15 +01:00
Kuba Szczodrzyński
9b8e00c7fa [boards] Support and validate MCU name aliases 2023-11-14 22:38:22 +01:00
Kuba Szczodrzyński
b97825d552 [boards] Add T112_V1.1 board, change scaling of small boards 2023-11-14 22:30:13 +01:00
Kuba Szczodrzyński
085b5aed16 [boards] Update boardgen to v0.10.1 2023-10-28 14:58:52 +02:00
protectivedad
7f43624824 [builder] Fix printing flash layout in env.py (#191)
Pointed to the proper item.
2023-10-27 13:34:09 +02:00
Kuba Szczodrzyński
1ed0000819 [release] v1.4.1
Some checks failed
Release / Run Clang lint (push) Has been cancelled
Release / Publish PlatformIO platform (push) Has been cancelled
Release / Publish GitHub release (push) Has been cancelled
2023-09-22 17:54:18 +02:00
Mike La Spina
3b79636d00 [libs] Fix SerialClass available() return value (#173)
Co-authored-by: descipher <120155735+GelidusResearch@users.noreply.github.com>
2023-09-21 17:19:51 +02:00
Kuba Szczodrzyński
5a4b932a37 [release] v1.4.0
Some checks failed
Release / Run Clang lint (push) Has been cancelled
Release / Publish PlatformIO platform (push) Has been cancelled
Release / Publish GitHub release (push) Has been cancelled
2023-09-10 19:37:52 +02:00
Kuba Szczodrzyński
dd2ae149ad [github] Move repository to libretiny-eu organization 2023-09-10 19:31:57 +02:00
Kuba Szczodrzyński
0f5d0a8889 [platform] Install ltchiptool in separate virtual environment (#166)
* [platform] Install ltchiptool in separate virtual environment

* [platform] Fix f-string syntax, set LibreTiny path in ltchiptool

* [platform] Fix venv site-packages path

* [platform] Fix installing pip without ensurepip

* [platform] Install binary dependencies only
2023-09-10 19:23:27 +02:00
Kuba Szczodrzyński
3750ae6953 [docs] Fix flashing redirect links 2023-09-02 15:20:08 +02:00
Kuba Szczodrzyński
5be993f9eb [docs] Add various redirect links for ESPHome docs 2023-09-02 15:12:12 +02:00
Kuba Szczodrzyński
57c43ce515 [libs] Fix possible MD5 memory leak in Update 2023-08-30 11:35:11 +02:00
Kuba Szczodrzyński
159ffa76fd [release] v1.3.0
Some checks failed
Release / Run Clang lint (push) Has been cancelled
Release / Publish PlatformIO platform (push) Has been cancelled
Release / Publish GitHub release (push) Has been cancelled
2023-08-29 19:21:09 +02:00
Kuba Szczodrzyński
1ac3d30d84 [libs] Implement Update MD5 2023-08-29 19:19:28 +02:00
Kuba Szczodrzyński
631ef6ba59 [github] Reuse GitHub workflows 2023-08-29 14:39:39 +02:00
Kuba Szczodrzyński
27393e47c3 [beken-72xx] Initialize UART to fix deep sleep 2023-08-23 16:08:03 +02:00
Péter Sárközi
bd47772c04 [beken-72xx] Fix GPIO deep sleep wakeup edge (#159)
Manufacturer docs: https://docs-bekencorp-com.translate.goog/sdk_3.0.x/bk7238/html/developer-guide/power_save/sleep_test.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=hu&_x_tr_pto=wapp

Discussion: https://github.com/libretiny-eu/libretiny-esphome/pull/11
2023-08-23 16:06:55 +02:00
Kuba Szczodrzyński
f3871388ce [docs] Restore feature support table 2023-08-18 13:47:06 +02:00
Ivan Kravets
62874bebf4 [misc] Fix PlatformIO repository URL (#157) 2023-08-17 19:23:10 +02:00
Kuba Szczodrzyński
2ca368305c [release] v1.2.1
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-08-17 19:04:50 +02:00
Kuba Szczodrzyński
f697ae6f11 [docs] Add migration to OpenBeken guide 2023-08-17 18:38:04 +02:00
Kuba Szczodrzyński
ef6dd35977 [docs] Rewrite flashing guides 2023-08-17 17:17:10 +02:00
Hajo Noerenberg
ccf21b4eab [realtek-ambz] Enable Mbed-TLS for MD5 hashing, remove Polar SSL (#156)
* Enable Mbed-TLS, remove Polar SSL

* Reformat lt_defs.h

---------

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2023-08-17 15:20:02 +02:00
Kuba Szczodrzyński
e99c6124e7 [docs] Add video guide link, use ready Docker images 2023-07-13 21:19:04 +02:00
Kuba Szczodrzyński
5721bd74d7 [docs] Update LibreTiny ESPHome component naming 2023-07-13 20:41:21 +02:00
Kuba Szczodrzyński
ff443ca488 [release] v1.2.0
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-07-13 18:02:58 +02:00
Péter Sárközi
93e0a5d066 [beken-72xx] Implement deep sleep (#140)
* Initial support code for Deep Sleep

* Global functions

* Remove unnecessary override

* clang-format

* Support for multiple pins

* Fix math

* Add a way to unset GPIOs

* Clang format

* Update brief

---------

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2023-07-13 18:00:14 +02:00
Kuba Szczodrzyński
150c2ef26d Merge branch 'family/ambz2' 2023-07-13 17:31:52 +02:00
Kuba Szczodrzyński
4d81fcac26 [realtek-ambz2] Flash bootloader & partition table in UF2 2023-07-13 17:00:42 +02:00
Kuba Szczodrzyński
a3bbdf1c16 [core] Migrate to uf2ota v5.0.0, refactor OTA API 2023-07-13 12:15:48 +02:00
Kuba Szczodrzyński
39df2e7b54 [core] Move C types to API units 2023-07-13 12:06:37 +02:00
Sonic-Amiga
6169f68119 [realtek-ambz] Improve flashing guide, add test pads for WR2 board (#147)
* platform/realtek-ambz: Improve flashing guide

Known USB adapter compatibility issues. Emphasize, so that the paragraph is
easier to notice.

Signed-off-by: Pavel Fedin <pavel_fedin@mail.ru>

* base/wr2: Add UART2 test pads to the WR2 diagram

The module has UART2, necessary for flashing, only on test pads. Document this.

Signed-off-by: Pavel Fedin <pavel_fedin@mail.ru>

* Move test pads to separate files, update variants

* Update wiring guide

---------

Signed-off-by: Pavel Fedin <pavel_fedin@mail.ru>
Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2023-07-11 11:46:36 +02:00
Kuba Szczodrzyński
e38e53bac0 [core] Split lt_api.c into separate units 2023-06-22 18:30:14 +02:00
Kuba Szczodrzyński
b38a4d5d46 [core] Add hardware peripheral availability defines 2023-06-21 17:02:48 +02:00
Kuba Szczodrzyński
96412624d9 Merge branch 'master' into family/ambz2 2023-06-21 13:35:52 +02:00
Kuba Szczodrzyński
f8876bba87 [release] v1.1.0
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-06-20 19:37:25 +02:00
Kuba Szczodrzyński
68b5773827 [core] Remove boardgen submodule, again 2023-06-20 19:28:12 +02:00
Kuba Szczodrzyński
74659901c0 [boards] Fix BW15 PCB template name 2023-06-20 19:09:46 +02:00
Kuba Szczodrzyński
73ede2838c Merge branch 'master' into family/ambz2 2023-06-20 18:53:46 +02:00
Kuba Szczodrzyński
273a86532b [beken-72xx] Add initial BK7231Q support, add WA2 board 2023-06-20 17:22:12 +02:00
Kuba Szczodrzyński
05e13dafed [beken-72xx] Rename BK7231U to BK7231T, add BK7231Q family 2023-06-20 17:19:21 +02:00
Kuba Szczodrzyński
6af97d2691 [boards] Add Tuya series 1 boards 2023-06-18 20:19:05 +02:00
Kuba Szczodrzyński
f9fb78feed [boards] Add T102 and T103 boards 2023-06-18 16:48:49 +02:00
Kuba Szczodrzyński
96dbbe0919 [boards] Move custom templates from boardgen, add WB2L_M1 board 2023-06-18 16:11:55 +02:00
Kuba Szczodrzyński
0ef66af342 [boards] Embed shielding in PCB template 2023-06-18 11:34:24 +02:00
Kuba Szczodrzyński
7ed48bf9fc [boards] Add Tuya WBLC5 and CBLC5 boards 2023-06-18 00:13:05 +02:00
Adrián Panella
1335b84391 [boards] Add Tuya CBU board (#106)
* add CBU module

* boardgen templates

These should go in boardgen package.
Included here for reference

* boardgen output

* [boards] Update for latest version of boardgen

* [boards] Change CBU silkscreen, add variant file

---------

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2023-06-17 21:25:17 +02:00
Kuba Szczodrzyński
e2794d5f84 [builder] Fix running ltchiptool with no baudrate 2023-05-31 12:38:15 +02:00
Kuba Szczodrzyński
e7f35c584b [realtek-ambz2] Reuse Log UART for Serial 2023-05-31 12:37:34 +02:00
Kuba Szczodrzyński
1e49c3ff6f [realtek-ambz2] Fix missing flash API resource lock unit 2023-05-31 12:36:46 +02:00
Kuba Szczodrzyński
e256ac8e46 [builder] Fix ltchiptool empty quotes on Windows 2023-05-30 18:49:58 +02:00
Kuba Szczodrzyński
9c6e9d1525 [realtek-ambz2] Disable SoftwareSerial and Wire 2023-05-30 18:15:44 +02:00
Kuba Szczodrzyński
41985e5743 [core] Move common flags to base.py 2023-05-29 22:26:33 +02:00
Kuba Szczodrzyński
f1e41f7cc1 [realtek-ambz2] Add GDB init command 2023-05-29 22:25:23 +02:00
Kuba Szczodrzyński
6135e4f7b0 [boards] Update flash layouts, add W302 chip 2023-05-29 16:16:58 +02:00
Kuba Szczodrzyński
af8c7417b3 [realtek-ambz2] Keep LOG UART enabled, wipe OTA2 in UF2 2023-05-28 19:18:54 +02:00
Kuba Szczodrzyński
babdb1287f [realtek-ambz2] Replace lwIP with external port 2023-05-27 20:54:40 +02:00
Kuba Szczodrzyński
4532c88873 [core] Add lt_set_debug_mode() function, update core types 2023-05-27 16:03:46 +02:00
Kuba Szczodrzyński
bc1b83d931 Merge branch 'master' into family/ambz2 2023-05-27 15:43:35 +02:00
Kuba Szczodrzyński
87ad0798e4 [realtek-ambz2] Adapt WiFi library to ambz2_sdk 2023-05-27 15:41:07 +02:00
Kuba Szczodrzyński
a80032d46c [core] Move Wiring common core to wiring/, reset watchdog in yield() 2023-05-26 15:29:33 +02:00
Kuba Szczodrzyński
4dae304f51 [core] Add lt_get_device_mac() function 2023-05-25 20:43:00 +02:00
Kuba Szczodrzyński
9b7d34fa65 [realtek-ambz2] Fix C++ support, implement SerialClass 2023-05-25 14:35:41 +02:00
Kuba Szczodrzyński
c0cc602c9a [core] Add configure() for SerialClass 2023-05-25 14:29:35 +02:00
Kuba Szczodrzyński
e5f98ff41f [core] Refactor Wiring, use PinData for parameters 2023-05-24 22:01:05 +02:00
Kuba Szczodrzyński
bc74c21599 [realtek-ambz2] Enable compilation of Arduino core 2023-05-24 13:02:33 +02:00
Kuba Szczodrzyński
3836ad20b7 [core] Refactor SerialClass as API library 2023-05-24 11:55:07 +02:00
Kuba Szczodrzyński
b073290989 [realtek-ambz2] Implement base C API 2023-05-23 19:54:00 +02:00
Kuba Szczodrzyński
43c9d0db10 [docs] Add Porting new families guide 2023-05-23 15:58:11 +02:00
Kuba Szczodrzyński
c40bdd68af [realtek-ambz2] Use external FreeRTOS port 2023-05-23 15:14:59 +02:00
Kuba Szczodrzyński
620e457eb6 [realtek-ambz2] Fix C++ linker support 2023-05-23 12:56:42 +02:00
Kuba Szczodrzyński
5c4da6e82b [core] Fix ltchiptool installation in PlatformIO 2023-05-23 12:12:42 +02:00
Kuba Szczodrzyński
8c636e44f7 [realtek-ambz2] Add initial SDK fixups and API layer 2023-05-23 12:11:17 +02:00
Kuba Szczodrzyński
07e9aa1ded [realtek-ambz2] Make compiling base core possible 2023-05-19 10:42:59 +02:00
Kuba Szczodrzyński
27a7faaab7 [core] Remove boardgen submodule 2023-05-18 22:14:58 +02:00
Kuba Szczodrzyński
752768b1e2 [docs] Update supported chip list, remove AmebaZ2 boards for now 2023-05-18 21:03:08 +02:00
Kuba Szczodrzyński
f7c28eeea4 [release] v1.0.2
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-05-11 16:20:26 +02:00
Albert Koczy
113b2fc31d [docs] Fix dead link to Boards & CPU list (#124) 2023-05-07 12:31:27 +02:00
Stroe Andrei Catalin
86924d8785 [beken-72xx] Fix delay, yet again (#116) 2023-05-01 23:28:01 +02:00
Stroe Andrei Catalin
219415174e [libs] Fix mDNS after a wifi disconnect / reconnect event (#112)
* [libs] Fix mDNS not responding when device disconnects / reconnects to wifi

* Minor bugfix

* Reworked mDNS fix

* Update LwIPmDNS.cpp
2023-05-01 21:44:03 +02:00
Stroe Andrei Catalin
8999cb9091 [beken-72xx] Fix delay macro (#114)
* [beken-72xx] Fix delay macro

* Better fix for delay
2023-05-01 21:08:01 +02:00
Kuba Szczodrzyński
8337ac121e [core] Fix reentrant malloc wrappers 2023-05-01 20:58:37 +02:00
Kuba Szczodrzyński
d332315e7a [beken-72xx] Fix WiFi compilation issue 2023-04-28 21:24:41 +02:00
Péter Sárközi
882f58bae4 [beken-72xx] Implement WiFi powersave (#111)
* Rebase

* Clang-format
2023-04-28 17:21:49 +02:00
Kuba Szczodrzyński
2c86a36fe0 [release] v1.0.1
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-04-28 14:19:21 +02:00
Kuba Szczodrzyński
b984519546 [core] Update ltchiptool to fix PlatformIO publishing 2023-04-28 14:18:51 +02:00
Kuba Szczodrzyński
7b0f6b22c1 [release] v1.0.0
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-04-27 23:39:11 +02:00
Kuba Szczodrzyński
3b8a4f1b60 Merge branch 'structure-refactor' 2023-04-27 23:36:51 +02:00
Kuba Szczodrzyński
edd2c0542b [core] Update ltchiptool to v4.0.0 2023-04-27 23:32:28 +02:00
Kuba Szczodrzyński
dbc905dca3 [core] Rename project to LibreTiny 2023-04-27 23:30:46 +02:00
Kuba Szczodrzyński
461e4c6df0 [core] Prepare for project name change 2023-04-24 11:35:39 +02:00
Kuba Szczodrzyński
85a687fc56 [docs] Add migration page 2023-04-24 10:47:06 +02:00
Kuba Szczodrzyński
c5361a4738 [beken-72xx] Use realloc() based on malloc() 2023-04-22 18:29:52 +02:00
Kuba Szczodrzyński
42c18859f3 [core] Update ltchiptool to fix activating OTA 2023-04-22 18:10:47 +02:00
Kuba Szczodrzyński
1ba6834391 [docs] Update configuration docs 2023-04-11 20:11:42 +02:00
Kuba Szczodrzyński
376a4db4cb [release] v0.13.0
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-04-11 19:34:24 +02:00
Kuba Szczodrzyński
775e06b259 [core] Fix compilation on Linux 2023-04-11 19:15:56 +02:00
Kuba Szczodrzyński
3ba3c2a2be [realtek-ambz] Fix linker script XIP region length 2023-04-05 10:48:46 +02:00
Kuba Szczodrzyński
76ad89e2f1 [release] v1.0.0-alpha.1 2023-03-26 19:30:42 +02:00
Kuba Szczodrzyński
2a7f1b52a0 [core] Update ltchiptool to v4.0.0 2023-03-26 17:44:40 +02:00
Kuba Szczodrzyński
bd75b54dce [core] Allow customizing flash layout 2023-03-25 21:13:11 +01:00
Kuba Szczodrzyński
070f2afd66 [core] Generate linker scripts based on flash layout 2023-03-25 20:44:19 +01:00
Kuba Szczodrzyński
0e84e08a18 [core] Support adding custom board JSON, pass it to ltchiptool 2023-03-25 20:10:15 +01:00
Kuba Szczodrzyński
4c1ab20ba4 [core] Allow specifying custom library options 2023-03-23 22:49:48 +01:00
Kuba Szczodrzyński
63ac7b365d [core] Add ESP inline library 2023-03-20 21:29:57 +01:00
Kuba Szczodrzyński
c51bf0b7db [core] Migrate to GPIO-based pin numbering 2023-03-20 21:28:50 +01:00
Kuba Szczodrzyński
201db4668e [realtek-ambz] Fix WiFi AP mode and DNS 2023-03-18 13:27:16 +01:00
Kuba Szczodrzyński
250e67ab1f [realtek-ambz] Update stdlib compatibility 2023-03-17 18:17:35 +01:00
Kuba Szczodrzyński
2e30d34021 [core] Update Arduino compatibility, fix MD5 library 2023-03-17 17:33:43 +01:00
Kuba Szczodrzyński
2882eaa0c2 [core] Print platform versions, add GCC version to startup banner 2023-03-17 17:32:28 +01:00
Kuba Szczodrzyński
8faffedddc [core] Fix swapped flash reading/writing API 2023-03-16 17:48:34 +01:00
Kuba Szczodrzyński
5260930919 Merge branch 'master' into structure-refactor 2023-03-16 11:21:17 +01:00
Kuba Szczodrzyński
24832d3277 [beken-72xx] Fix bootloop by aggressive GCC optimization 2023-03-15 23:19:26 +01:00
Kuba Szczodrzyński
8f338a6b30 [beken-72xx] Fix bootloop by undefined instruction on GCC 10 2023-03-15 17:26:09 +01:00
Kuba Szczodrzyński
3d3f3700a8 [core] Update lwIP for SDK-independent headers 2023-03-14 13:07:44 +01:00
Kuba Szczodrzyński
eae64d34e2 [core] Update ltchiptool to v3.0.2 2023-03-14 11:34:09 +01:00
Kuba Szczodrzyński
a27e76bfa7 [realtek-ambz] Backport UART fix from structure-refactor 2023-03-13 22:30:02 +01:00
Kuba Szczodrzyński
b050662a5c [core] Use external FreeRTOS library 2023-03-13 22:18:02 +01:00
Kuba Szczodrzyński
f69b4bea4f Merge branch 'master' into structure-refactor 2023-03-13 17:46:13 +01:00
Kuba Szczodrzyński
4e3b081c60 [core] Include GCC version in the startup banner 2023-03-13 17:27:21 +01:00
Kuba Szczodrzyński
a2de77ce30 [core] Use GCC 10.3.1 with -Os for all families 2023-03-13 16:50:13 +01:00
Kuba Szczodrzyński
5de98ed56c [realtek-ambz] Selectively update GCC to v10.3.1 2023-03-12 22:27:26 +01:00
Kuba Szczodrzyński
ff8ac6036c [realtek-ambz] Update GCC to v5.4.1 2023-03-12 14:12:04 +01:00
Kuba Szczodrzyński
c3f12ab247 [core] Rename CPU and memory APIs 2023-03-12 14:11:16 +01:00
Kuba Szczodrzyński
dfcb36361e [docs] Refactor & update API documentation 2023-03-11 21:58:43 +01:00
Kuba Szczodrzyński
c4a3e9e2ee [beken-72xx] Re-enable OTA encryption 2023-03-11 16:59:57 +01:00
Kuba Szczodrzyński
fd1afea1bc [core] Refactor LT class into C methods 2023-03-10 19:08:55 +01:00
Kuba Szczodrzyński
65cf460691 [core] Migrate to UF2 OTA format version 2 2023-03-09 11:46:40 +01:00
Kuba Szczodrzyński
046f7df7d1 [realtek-ambz] Fix UART setup and receiving, implement ADR 2023-03-05 16:45:16 +01:00
Kuba Szczodrzyński
8323bafd4c [beken-72xx] Fix include path and delay() alias 2023-03-05 14:42:59 +01:00
Kuba Szczodrzyński
6b92aac1da [core] Organize GCC compilation flags 2023-03-04 17:19:24 +01:00
Kuba Szczodrzyński
3113b387c3 [boards] Move docs generation to GitHub Actions 2023-03-04 16:56:49 +01:00
Kuba Szczodrzyński
6d2b653f61 [core] Remove public FreeRTOS dependency 2023-03-04 12:47:45 +01:00
Kuba Szczodrzyński
47daefe675 [realtek-amb] Fix or suppress compilation warnings 2023-03-04 11:12:58 +01:00
Kuba Szczodrzyński
e8c18f4e66 [core] Add common malloc() implementation 2023-03-04 11:12:55 +01:00
Kuba Szczodrzyński
76a82768fe [realtek-ambz2] Update base core to new structure 2023-03-04 11:12:48 +01:00
Kuba Szczodrzyński
8be5aeab59 [core] Update Arduino compatibility 2023-03-04 11:12:36 +01:00
Kuba Szczodrzyński
fbfd96ecdb [realtek-ambz] Update Arduino core to new structure 2023-03-04 11:10:38 +01:00
Kuba Szczodrzyński
dee20c859c [core] Use void instead of MD5 context struct 2023-03-04 11:10:35 +01:00
Kuba Szczodrzyński
ce0a88147b [realtek-ambz] Update base core to new structure 2023-03-04 11:10:30 +01:00
Kuba Szczodrzyński
7f62f1e965 [beken-72xx] Make WiFiData private 2023-03-04 11:10:25 +01:00
Kuba Szczodrzyński
b51501fb21 [beken-72xx] Update Arduino core to new structure 2023-03-04 11:10:18 +01:00
Kuba Szczodrzyński
72ab64461c [builder] Add library queue to manage cloned environments 2023-03-04 11:10:05 +01:00
Kuba Szczodrzyński
26b393e059 [core] Replace usages of PIN_SERIAL_TX with HAS_SERIAL 2023-03-04 11:09:38 +01:00
Kuba Szczodrzyński
bc328657aa [beken-72xx] Update base core to new structure 2023-03-04 11:09:27 +01:00
Kuba Szczodrzyński
c579219427 [core] Make PIO detach existing packages instead of overwriting 2023-03-04 11:06:04 +01:00
Kuba Szczodrzyński
3413d70210 [core] Update PIO builders to new structure 2023-03-04 11:05:56 +01:00
Kuba Szczodrzyński
8bbc7e13fb [core] Move arduino/ files to cores/ 2023-03-04 11:05:28 +01:00
Kuba Szczodrzyński
f1ecb312c7 [core] Move platform/ files to cores/ 2023-03-04 11:05:24 +01:00
Kuba Szczodrzyński
3407891e9c [core] Refactor families.json 2023-03-04 11:05:19 +01:00
Kuba Szczodrzyński
8f447a4a72 [release] v0.12.6
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-02-02 22:28:52 +01:00
Kuba Szczodrzyński
8ace11e462 [core] Fix Python lint 2023-02-02 22:28:10 +01:00
Kuba Szczodrzyński
949dfe7266 [core] Use PIO repackages of vendor frameworks 2023-02-02 22:21:12 +01:00
Kuba Szczodrzyński
f0d490aef9 [docs] Fix ESPHome sample config indent 2023-02-02 21:59:14 +01:00
Kuba Szczodrzyński
bdedae981a [beken-72xx] Fix UF2 RBL relative offset 2023-01-28 16:38:28 +01:00
Kuba Szczodrzyński
9e0750c9d3 [release] v0.12.5
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-01-28 13:00:10 +01:00
Kuba Szczodrzyński
9a3e512b1b [boards] Add LSC LMA35 T variant 2023-01-28 13:00:10 +01:00
Kuba Szczodrzyński
861e741030 [beken-72xx] Disable OTA encryption 2023-01-28 12:53:57 +01:00
Kuba Szczodrzyński
a3e7e21d45 [core] Migrate to ltchiptool v3.0.0 2023-01-28 12:53:57 +01:00
Matt Shepcar
86db2fcf61 [beken-72xx] Fix for flicker when PWM lights turn on/off on bk7231n (#68) 2023-01-28 12:52:01 +01:00
Kuba Szczodrzyński
fcd72e013a [docs] Add ESPHome Dashboard usage docs 2023-01-26 20:41:57 +01:00
Kuba Szczodrzyński
2450f8c64b [release] v0.12.4
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-01-26 11:28:25 +01:00
Kuba Szczodrzyński
676a9b1686 [core] Fix reinstalling ltchiptool 2023-01-26 11:28:09 +01:00
Kuba Szczodrzyński
b10db63c74 [realtek-ambz] Fix WiFi station BSSID retrieval 2023-01-19 17:38:45 +01:00
Kuba Szczodrzyński
4b25ef7516 [realtek-ambz] Fix resetting OTA switch when it reaches 0 2023-01-19 16:53:27 +01:00
Kuba Szczodrzyński
de0d19cda6 [docs] Update ltchiptool installation info 2023-01-19 12:29:59 +01:00
Kuba Szczodrzyński
c55386af0e [docs] Add icons to external links 2023-01-18 19:06:18 +01:00
Kuba Szczodrzyński
33fe1c7a54 Merge branch 'docs-refactor' 2023-01-18 18:39:11 +01:00
Kuba Szczodrzyński
bf6d05e92a [docs] Remove AmbZ doxygen build 2023-01-18 18:38:52 +01:00
Kuba Szczodrzyński
b6113d8d2b [docs] Configure MkDocs Material 2023-01-18 18:32:34 +01:00
Kuba Szczodrzyński
bc31154035 [docs] Add Tuya Pinout Config to resources 2023-01-18 17:59:51 +01:00
Kuba Szczodrzyński
edfe0329bf [docs] Update links in board docs 2023-01-18 17:59:19 +01:00
Kuba Szczodrzyński
1e11dd776a [docs] Move resources to chip family docs 2023-01-18 17:56:09 +01:00
Kuba Szczodrzyński
028526d22d [docs] Add ltchiptool GUI download button 2023-01-18 15:00:01 +01:00
Kuba Szczodrzyński
7ac2d854f2 [docs] Move tools docs to a subdirectory 2023-01-18 14:59:36 +01:00
Kuba Szczodrzyński
279c81e431 [docs] Update code block styles 2023-01-18 14:02:12 +01:00
Kuba Szczodrzyński
4e319b40ed [docs] Fix ltchiptool docs badges 2023-01-18 13:30:13 +01:00
Kuba Szczodrzyński
d082b39980 [docs] Add ltchiptool screenshot 2023-01-17 22:45:00 +01:00
Kuba Szczodrzyński
277402f577 [docs] Update chip flashing guides, fix mkdocs building 2023-01-17 22:33:57 +01:00
Kuba Szczodrzyński
9e95c507b1 [docs] Refactor docs structure, add project upload guides 2023-01-17 18:56:15 +01:00
Kuba Szczodrzyński
7440fc6f46 [core] Add parent_description key to families 2023-01-16 10:42:30 +01:00
Kuba Szczodrzyński
a24028f674 [beken-72xx] Fix RBL app size typo 2023-01-16 10:41:17 +01:00
Stroe Andrei Catalin
00913b013f [beken-72xx] Fix compilation on ARM systems (#58)
* Fix toolchain for BK7231 on ARM cpus

* Fix format

* PR comments

* PR Comments, part 2
2023-01-03 21:15:03 +01:00
Mihai Ambrosie
447d08d613 [realtek-ambz] Fix 4M/980k linker script name (#56) 2023-01-03 10:56:48 +01:00
Kuba Szczodrzyński
d4f7736b2d [release] v0.12.3
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-01-02 20:32:46 +01:00
Kuba Szczodrzyński
60f72fffdf [core] Fix installing ltchiptool, again 2023-01-02 20:32:29 +01:00
Kuba Szczodrzyński
77af9c1cba [release] v0.12.2
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-01-02 19:41:39 +01:00
Kuba Szczodrzyński
1b2414337f [core] Fix installing ltchiptool 2023-01-02 19:40:55 +01:00
Kuba Szczodrzyński
d41f1f2a4d [release] v0.12.1
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-01-02 17:06:16 +01:00
Kuba Szczodrzyński
f9967ff990 [core] Fix importing ltchiptool after updating 2023-01-02 17:05:35 +01:00
Kuba Szczodrzyński
db0ab41ea4 [realtek-ambz] Check SoftwareSerial before stopping 2023-01-02 16:03:49 +01:00
Kuba Szczodrzyński
da95cc30d3 [realtek-ambz] Move to GNU++11, update TODO.md 2023-01-02 16:02:57 +01:00
Ross Reedstrom
6b3001573e [docs] Fix link to supported boards (#53) 2023-01-01 14:05:57 +01:00
Kuba Szczodrzyński
b85f6f8c3f [release] v0.12.0
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2022-12-30 15:52:14 +01:00
Kuba Szczodrzyński
d036ac9fba [core] Migrate to ltchiptool v2.0.0 2022-12-30 15:51:32 +01:00
Kuba Szczodrzyński
f63a114371 [beken-72xx] Support compilation for BK7251 family 2022-12-08 20:16:44 +01:00
Kuba Szczodrzyński
8cb59661ac [boards] Add initial support for BK7252 2022-12-08 20:04:17 +01:00
Kuba Szczodrzyński
fc1da609f2 [beken-72xx] Add BL2028N to supported chips 2022-12-08 17:48:04 +01:00
Kuba Szczodrzyński
c6566323fd [boards] Move IC pinouts to separate directory 2022-12-08 17:26:46 +01:00
Kuba Szczodrzyński
30e1533ad9 [core] Rename BK7231T family to BK7231U 2022-12-08 17:19:42 +01:00
Kuba Szczodrzyński
71dfea1904 [release] v0.11.0
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2022-12-07 17:43:19 +01:00
Kuba Szczodrzyński
4fa7457423 [boards] Update boardgen and generated board files 2022-12-07 17:03:41 +01:00
kolos
9583bb35f5 [core] Include SNTP app from lwIP (#38) 2022-12-06 22:47:22 +01:00
Kuba Szczodrzyński
e806c4db3a [docs] Output boards.json to site/ directory 2022-12-06 21:37:26 +01:00
Kuba Szczodrzyński
665ab22de5 [docs] Generate JSON file with supported boards 2022-12-06 21:34:46 +01:00
Kuba Szczodrzyński
ec4e946643 [core] Add restartDownloadMode() method 2022-11-26 19:36:10 +01:00
Kuba Szczodrzyński
9e4bbe3e36 [realtek-ambz] Fix software rebooting 2022-11-26 19:35:40 +01:00
Kuba Szczodrzyński
1172c1a852 [realtek-ambz] Update lwIP to v2.1.3 2022-11-26 15:32:33 +01:00
Stroe Andrei Catalin
8a4392bb22 [beken-72xx] Add support for CHANGE interrupts (#34)
* [beken-72xx] Added support for ANY_EDGE interrupts

* clang format

* PR comments

* Update wiring_irq.c

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2022-10-21 22:19:10 +02:00
Stroe Andrei Catalin
a79a2d60d3 [core] Use mDNS hostname as instance name by default (#32) 2022-10-15 16:39:54 +02:00
blakadder
9553ff66a3 [docs] Update docs URL in basic README (#31) 2022-10-08 22:35:08 +02:00
blakadder
79c6f05291 [docs] Update site_url (#30)
* update site url to new one

* Update mkdocs.yml

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2022-10-08 22:34:50 +02:00
David Buezas
3e691de24a [beken-72xx] Fix micros() usage with disabled interrupts (#28)
* Workaround for micros when used inside interruptLock blocks

* Fix comment formatting

* Cover case when millis overflows

* Improve variable names.
2022-10-05 12:51:20 +02:00
David Buezas
303def49cb [beken-72xx] Implement accurate delayMicroseconds() (#26)
* Implements accurate delayMicroseconds

* renamed to cammelCase, moved #defines and clang-formatted
2022-10-03 15:14:31 +02:00
Kuba Szczodrzyński
18653781d5 [beken-72xx] Replace delay() define with inline function 2022-10-03 15:12:15 +02:00
Kuba Szczodrzyński
2a75bdbeda [beken-72xx] Update TLV and calibration flash layout 2022-10-01 15:01:38 +02:00
Kuba Szczodrzyński
4a6926eb6c [beken-72xx] Fix restarting AP with shorter password 2022-10-01 15:00:08 +02:00
Kuba Szczodrzyński
3dc4007fa7 [core] Update ltchiptool to fix realtek-ambz OTA issue 2022-09-30 18:42:09 +02:00
Kuba Szczodrzyński
9c3833d66c [realtek-ambz] Provide unknown reset reason 2022-09-27 12:53:08 +02:00
Kuba Szczodrzyński
41966f33c2 [github] Add FUNDING.yml 2022-09-25 22:26:25 +02:00
Kuba Szczodrzyński
50fea2a8f0 [boards] Add RTL8710BX board with 4 MiB flash 2022-09-23 12:25:30 +02:00
Kuba Szczodrzyński
05cb7f7947 [realtek-ambz] Implement watchdog API 2022-09-21 21:46:11 +02:00
Kuba Szczodrzyński
5b6b80e3cd [tools] Migrate to bk7231tools from PyPI 2022-09-21 21:41:08 +02:00
Kuba Szczodrzyński
2c59af8399 [docs] Add Beken flash support list 2022-09-21 21:24:59 +02:00
Kuba Szczodrzyński
b404f9fa42 [core] Append revision info to version string 2022-09-15 19:59:34 +02:00
Kuba Szczodrzyński
8dc8340ce4 [realtek-ambz] Use GCC 5.2.1 to fix ranlib missing 2022-09-15 18:37:19 +02:00
Kuba Szczodrzyński
30f08a145e [realtek-ambz] Export SoftwareSerial availability macro 2022-09-15 18:31:20 +02:00
Kuba Szczodrzyński
d3d140fa60 [builder] Fix Python lint 2022-09-15 17:38:08 +02:00
Kuba Szczodrzyński
5f8e687e68 [core] Fix getResetReasonName() API 2022-09-15 14:51:14 +02:00
Kuba Szczodrzyński
fab640901d [core] Add textual reset reason API 2022-09-15 13:55:16 +02:00
Kuba Szczodrzyński
9a053fb6ff [core] Export LT class as ESP alias 2022-09-15 13:53:12 +02:00
Kuba Szczodrzyński
24e4b0b376 [builder] Use ranlib from the toolchain 2022-09-15 12:16:22 +02:00
Kuba Szczodrzyński
b8eee999e2 [docs] Add remaining config options, add warning about latest version 2022-09-15 11:47:25 +02:00
Kuba Szczodrzyński
7fe9a114b7 [beken-72xx] Auto-reboot after detecting download-mode commands 2022-09-14 19:57:23 +02:00
Kuba Szczodrzyński
05b2fb4fcb [beken-72xx] Implement micros() properly; use high-res timer for OS 2022-09-14 19:56:51 +02:00
Kuba Szczodrzyński
830d8762cd [beken-72xx] Disable watchdog feeding in BDK 2022-09-14 19:55:10 +02:00
Kuba Szczodrzyński
3f81666369 [beken-72xx] Implement watchdog & reset reason APIs 2022-09-13 17:42:13 +02:00
Kuba Szczodrzyński
d40f4003b5 [boards] Add FCC ID to board docs 2022-09-11 16:39:15 +02:00
Kuba Szczodrzyński
1585e425ce [boards] Add CB2L board 2022-09-11 16:20:48 +02:00
Kuba Szczodrzyński
bbc7613079 [boards] Add remaining CB3x series boards 2022-09-11 14:26:02 +02:00
Kuba Szczodrzyński
ec54745174 [docs] Update Tuya all boards list 2022-09-11 14:24:51 +02:00
Kuba Szczodrzyński
a29453de12 [docs] Add 3-rd party libs used in ESPHome 2022-09-10 19:08:57 +02:00
Kuba Szczodrzyński
db5bf4fc46 [docs] Add dumping instructions 2022-09-10 18:24:10 +02:00
Kuba Szczodrzyński
9495e3418c [beken-72xx] Fake enabling AP to fix connection issues, set default IP 2022-09-10 16:44:45 +02:00
Kuba Szczodrzyński
83573a743b [core] Implement WiFiUDP based on lwIP 2022-09-10 16:15:28 +02:00
Kuba Szczodrzyński
f5dcd82747 [core] Add printf format attribute to lt_log() 2022-09-10 16:14:38 +02:00
Kuba Szczodrzyński
070ec2f48f [core] Update ArduinoCore-API to support Print::printf() 2022-09-10 16:14:10 +02:00
Kuba Szczodrzyński
96c7fdc02c [beken-72xx] Reset scan state after timeout 2022-09-09 20:21:33 +02:00
Kuba Szczodrzyński
dfde2d8a62 [release] v0.10.0
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2022-09-03 21:40:04 +02:00
Kuba Szczodrzyński
a3f57114da [core] Update ltchiptool to v1.5.2 2022-09-03 21:38:46 +02:00
Kuba Szczodrzyński
904af10914 [core] Implement POSIX gettimeofday() and settimeofday() 2022-09-03 21:26:07 +02:00
Kuba Szczodrzyński
9b5013a694 [beken-72xx] Move periodic heap logging to core 2022-09-03 21:25:39 +02:00
Kuba Szczodrzyński
922adfd3d4 [core] Print full error details in Update library 2022-09-03 21:24:46 +02:00
Kuba Szczodrzyński
362144033b [core] Move main.cpp to core directory 2022-09-03 20:01:24 +02:00
Kuba Szczodrzyński
caf9a579d3 [beken-72xx] Fix writing 0% and 100% with PWM 2022-09-03 19:01:17 +02:00
Kuba Szczodrzyński
cb40fdcdbe [beken-72xx] Unprotect flash before writing 2022-09-03 17:50:36 +02:00
Kuba Szczodrzyński
ef15e754c9 [core] Make LT API usable from C 2022-09-03 17:49:19 +02:00
Kuba Szczodrzyński
d55568c146 [beken-72xx] Fix PWM on BK7231N 2022-09-02 23:58:38 +02:00
Kuba Szczodrzyński
e134863db1 [realtek-ambz] Fix mDNS compilation problem on lwIP < 2.1.0 2022-09-02 21:11:12 +02:00
Kuba Szczodrzyński
c37ae51dd3 [core] Update default logging options, fix disabling logger 2022-09-02 14:35:21 +02:00
Kuba Szczodrzyński
4fc2ff43c1 [core] Make info, warning and error logging per-module configurable 2022-09-02 14:12:05 +02:00
Kuba Szczodrzyński
607f13d935 [core] Refactor per-module logger macros 2022-09-02 14:02:00 +02:00
Kuba Szczodrzyński
44c1a3f695 [beken-72xx] Fix digitalRead() setting wrong pin mode 2022-09-01 21:13:04 +02:00
Kuba Szczodrzyński
d30decfbc8 [core] Fix lwipopts.h invalid include 2022-09-01 19:09:19 +02:00
Kuba Szczodrzyński
705b2f794e [beken-72xx] Increase TCP/IP stack size to fix mDNS stack overflow 2022-08-31 22:39:49 +02:00
Kuba Szczodrzyński
4958690d9e [core] Make lwIP debugging configurable 2022-08-31 22:38:07 +02:00
Kuba Szczodrzyński
d7749d3a24 [core] Export Update combined error code 2022-08-31 22:28:47 +02:00
Kuba Szczodrzyński
73e07a594f [core] Add mDNS debug logging, start IGMP if not enabled 2022-08-31 22:28:13 +02:00
Kuba Szczodrzyński
755c2ef400 [core] Add periodical free heap logging 2022-08-31 22:26:12 +02:00
Kuba Szczodrzyński
3f588e970a [core] Rework mDNS responder to fix TXT records 2022-08-27 00:00:45 +02:00
Kuba Szczodrzyński
3264807e77 [core] Fix StreamString clearing data using println() 2022-08-26 20:03:01 +02:00
Kuba Szczodrzyński
01225d4648 [beken-72xx] Update to external lwIP v2.1.3 2022-08-26 20:02:57 +02:00
Kuba Szczodrzyński
48aa809c98 [beken-72xx] Move to external lwIP v2.0.2 2022-08-25 23:34:54 +02:00
Kuba Szczodrzyński
4a722d4069 [core] Add option to debug FlashDB 2022-08-25 13:45:01 +02:00
Kuba Szczodrzyński
07aca2a0e7 [beken-72xx] Unprotect flash after initializing 2022-08-25 13:44:24 +02:00
Kuba Szczodrzyński
10000d9b6c [beken-72xx] Fix enabling WiFi AP mode only 2022-08-18 14:15:41 +02:00
Kuba Szczodrzyński
f0e247f31e [core] Print error if WiFi mode changing failed 2022-08-18 14:15:05 +02:00
Kuba Szczodrzyński
593dec5e88 [beken-72xx] Update ltchiptool to fix corrupted output binaries 2022-08-17 22:40:56 +02:00
Kuba Szczodrzyński
c45b86c993 [beken-72xx] Fix enabling AP mode 2022-08-17 15:17:14 +02:00
Kuba Szczodrzyński
02f01f2199 [beken-72xx] Initialize WiFiData when needed, null-terminate SSIDs 2022-08-17 11:24:32 +02:00
Kuba Szczodrzyński
88b1adc2d6 [github] Fix docs custom domain deployment 2022-08-16 23:24:20 +02:00
Kuba Szczodrzyński
a0a0e6775b [beken-72xx] Improve WiFi status recognition, fix null pointer access 2022-08-16 22:52:05 +02:00
Kuba Szczodrzyński
4096253694 [github] Add custom domain for docs workflow 2022-08-16 18:22:29 +02:00
Kuba Szczodrzyński
33ba44ebda [core] Move running OTA detection to family code 2022-08-16 18:01:38 +02:00
Kuba Szczodrzyński
9b4cf2a92b [core] Pin GitHub packages to known-good versions 2022-08-07 19:48:54 +02:00
Kuba Szczodrzyński
e6b915d8e3 [tools] Move dumptool to ltchiptool 2022-08-06 19:33:21 +02:00
Kuba Szczodrzyński
bb73fb5f55 [core] Force updating ltchiptool to fix linking problems 2022-08-06 17:07:28 +02:00
Kuba Szczodrzyński
10c5945afb [core] Allow exporting UF2 under a custom filename 2022-08-06 17:06:08 +02:00
Kuba Szczodrzyński
0bd613d556 [core] Support upload_flags property 2022-08-06 16:50:12 +02:00
Kuba Szczodrzyński
aae2f65b9e [release] v0.9.0
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2022-08-06 13:42:37 +02:00
Kuba Szczodrzyński
d02197474e [docs] Update ESPHome docs, add cloudcutter guide 2022-08-06 13:37:47 +02:00
Kuba Szczodrzyński
41b37e9c24 [core] Update ltchiptool to v1.4.0 2022-08-06 13:06:44 +02:00
Kuba Szczodrzyński
b03400fac2 [beken-72xx] Implement OTA API, add Update debugging 2022-08-06 11:36:53 +02:00
Kuba Szczodrzyński
3e808f7b6b [beken-72xx] Write OTA package to UF2 image 2022-08-05 20:29:48 +02:00
Kuba Szczodrzyński
1e3a8971fb [core] Migrate tools to ltchiptool 2022-08-05 20:29:45 +02:00
Kuba Szczodrzyński
d8c0105b97 [examples] Fix PinScan compilation on realtek-ambz 2022-08-03 12:48:50 +02:00
Kuba Szczodrzyński
b3689cbac8 [beken-72xx] Specify keys for OTA packaging 2022-08-01 19:56:34 +02:00
Kuba Szczodrzyński
1b5d6472f7 [examples] Fix PinScan telnet functionality 2022-08-01 11:28:56 +02:00
Kuba Szczodrzyński
e9511c507a [core] Allow disabling LT logger programmatically 2022-08-01 11:28:16 +02:00
Kuba Szczodrzyński
365f64ded5 [beken-72xx] Make Serial.end() disable hardware UART 2022-08-01 11:27:57 +02:00
Kuba Szczodrzyński
3601fa63d8 [examples] Add PinScan example 2022-08-01 10:52:58 +02:00
Kuba Szczodrzyński
5d00ddf516 [beken-72xx] Fix detaching interrupt handler 2022-07-31 23:25:12 +02:00
Kuba Szczodrzyński
0051453cad [beken-72xx] Implement interrupts 2022-07-31 21:35:02 +02:00
Kuba Szczodrzyński
7920ea2dda [beken-72xx] Fix SerialClass character reading 2022-07-31 14:52:09 +02:00
Kuba Szczodrzyński
9416e45a75 [docs] Restructure documentation, clarify some parts 2022-07-31 13:05:24 +02:00
Kuba Szczodrzyński
98a65c81af [boards] Add usage info to board README 2022-07-31 12:47:24 +02:00
Kuba Szczodrzyński
8e1f06e79b [boards] Add LSC LMA35 board, update boardgen 2022-07-30 19:48:58 +02:00
Kuba Szczodrzyński
58a09f453d [realtek-ambz] Fix errors related to lwIP 2022-07-30 17:18:46 +02:00
Kuba Szczodrzyński
7dc69982b6 [beken-72xx] Fix putchar_p UART index 2022-07-30 15:42:30 +02:00
Kuba Szczodrzyński
46e4041ed8 [beken-72xx] Mark mDNS as broken 2022-07-28 22:18:04 +02:00
Kuba Szczodrzyński
0e129130b1 [core] Print errors about starting main task 2022-07-28 20:29:53 +02:00
Kuba Szczodrzyński
33c9868f90 [core] Remove duplicated WMath functions 2022-07-28 13:46:42 +02:00
Kuba Szczodrzyński
fb04b1830e [release] v0.8.0
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2022-07-26 11:11:52 +02:00
Kuba Szczodrzyński
9509194bd0 [beken-72xx] Correct sys_config.h path 2022-07-26 11:11:14 +02:00
Kuba Szczodrzyński
60322a243a [boards] Fix missing vendor field in generic boards 2022-07-26 11:10:45 +02:00
Kuba Szczodrzyński
4ed7067537 [boards] Add generic definitions for each family 2022-07-25 19:59:53 +02:00
Kuba Szczodrzyński
69086e8fba [boards] Rename small/large base boards to show size 2022-07-25 19:58:16 +02:00
Kuba Szczodrzyński
a4b63bb037 [tools] Make util/markdown.py pre-Python 3.10 compatible 2022-07-21 23:08:53 +02:00
Kuba Szczodrzyński
5ffb2f6619 [boards] Add BW15 board definition, update boardgen 2022-07-21 23:08:49 +02:00
Kuba Szczodrzyński
41eaf9b9e4 [realtek-ambz2] Add initial AmebaZ2 support 2022-07-21 23:08:45 +02:00
Kuba Szczodrzyński
28bb777399 [core] Move family config to separate dir, define Realtek parent 2022-07-21 23:08:39 +02:00
Kuba Szczodrzyński
f375a35cc8 [core] Move library include wrappers to common 2022-07-21 23:08:39 +02:00
Kuba Szczodrzyński
1d41d84083 [boards] Move common partitions to base JSON 2022-07-21 23:08:28 +02:00
Kuba Szczodrzyński
357be177fc [core] Make WiFi sleep & TX power methods weak 2022-07-12 21:12:54 +02:00
Kuba Szczodrzyński
23c3335de8 [beken-72xx] Use Hostapd MD5 implementation 2022-07-12 13:05:02 +02:00
Kuba Szczodrzyński
963b164783 [beken-72xx] Define struct ip_addr as IPv4 2022-07-12 13:01:46 +02:00
Kuba Szczodrzyński
0c22a02641 [beken-72xx] Use mbedTLS MD5 implementation 2022-07-12 12:48:27 +02:00
Kuba Szczodrzyński
10cb5c2c76 [core] Add missing C++ stdlib includes 2022-07-12 12:48:02 +02:00
Kuba Szczodrzyński
6d36c9ef7b [boards] Add remaining WB2x and WB3x boards 2022-07-11 16:42:45 +02:00
Kuba Szczodrzyński
aed97a5e92 [boards] Add remaining WR2x and WR3x boards 2022-07-11 14:23:10 +02:00
Kuba Szczodrzyński
b6008fc9bb [docs] Add family flashing guides 2022-07-11 12:03:28 +02:00
Kuba Szczodrzyński
f9359679ad [docs] Add Getting started guide 2022-07-11 10:54:16 +02:00
Kuba Szczodrzyński
052d7be1a9 [beken-72xx] Move to GNU++11 2022-07-10 20:18:12 +02:00
Kuba Szczodrzyński
ead577a116 [release] v0.7.0
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2022-07-10 19:50:07 +02:00
Kuba Szczodrzyński
ccf7d972ce [beken-72xx] Implement WiFi events 2022-07-10 19:49:14 +02:00
Kuba Szczodrzyński
b2df9e6a8b [beken-72xx] Use chip ID based on MAC address 2022-07-07 18:01:35 +02:00
Kuba Szczodrzyński
e37014ebd6 [beken-72xx] Wrap BkDriverFlash for correct partition offsets 2022-07-07 17:45:58 +02:00
Kuba Szczodrzyński
c96ef2ff7a [beken-72xx] Add draft BK7231N support 2022-07-07 17:18:25 +02:00
Kuba Szczodrzyński
c19dd0d87e [beken-72xx] Fix WiFi using DHCP 2022-07-07 17:15:52 +02:00
Kuba Szczodrzyński
02f972bd5f [boards] Add CB2S board definition 2022-07-07 14:57:35 +02:00
Kuba Szczodrzyński
15facd8866 [realtek-ambz] Fix reading MAC address without WiFi enabled 2022-07-05 13:16:51 +02:00
Kuba Szczodrzyński
cf584c3bd6 [tools] Fix link2bin with long command line 2022-07-04 22:37:25 +02:00
Kuba Szczodrzyński
4744351964 [core] Allow changing SDK, logger & Serial output ports 2022-07-04 13:56:03 +02:00
Kuba Szczodrzyński
31b753ab5a [core] Allow configuring silencing of SDK output 2022-07-04 13:55:58 +02:00
Kuba Szczodrzyński
3cb944dde2 [realtek-ambz] Implement SoftwareSerial class 2022-07-03 22:54:18 +02:00
Kuba Szczodrzyński
1b4265f522 [docs] Add TODO list 2022-07-03 19:50:27 +02:00
Kuba Szczodrzyński
5d16338faa [realtek-ambz] Add missing #define 2022-07-03 19:48:24 +02:00
Kuba Szczodrzyński
673b8233e5 [realtek-ambz] Refactor Serial class 2022-07-03 19:15:33 +02:00
Kuba Szczodrzyński
0dd2e2583b [core] Rename init() to initArduino() 2022-07-03 16:49:46 +02:00
Kuba Szczodrzyński
c19f24cbfd [beken-72xx] Implement WiFi Access Point mode 2022-07-01 19:16:48 +02:00
Kuba Szczodrzyński
cfb6830d95 [beken-72xx] Revert scanning before connecting 2022-07-01 19:15:14 +02:00
Kuba Szczodrzyński
27dea356cf [beken-72xx] Fix station with static IP 2022-07-01 19:14:41 +02:00
Kuba Szczodrzyński
352a425c4f [beken-72xx] Wait for init_thread to start TCP/IP 2022-07-01 18:49:14 +02:00
Kuba Szczodrzyński
4beaa79d02 [beken-72xx] Revert to standard station config struct 2022-07-01 18:48:11 +02:00
Kuba Szczodrzyński
e54eab83f2 [beken-72xx] Use station data structs in WiFiData 2022-07-01 16:17:48 +02:00
Kuba Szczodrzyński
e74a491b4a [core] Move SSID & passphrase validation to common 2022-07-01 15:36:49 +02:00
Kuba Szczodrzyński
a9415c1db7 [core] Fix compilation and linking on Linux 2022-07-01 12:47:32 +02:00
Kuba Szczodrzyński
a83959ab5f [release] v0.6.1
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2022-06-30 21:22:12 +02:00
Kuba Szczodrzyński
b1896002e5 [boards] Add missing URL field in generic-native.json 2022-06-30 21:21:29 +02:00
Kuba Szczodrzyński
cc39de9b04 [core] Fix beken-72xx-arduino.py formatting 2022-06-30 20:47:54 +02:00
Kuba Szczodrzyński
a286b5d067 [release] v0.6.0
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2022-06-30 20:34:38 +02:00
Kuba Szczodrzyński
f071f57abf [beken-72xx] Enable mDNS responder, set IGMP flag on netif 2022-06-30 20:33:08 +02:00
Kuba Szczodrzyński
0e0fe334cd [beken-72xx] Scan networks before connecting, if needed 2022-06-30 20:30:52 +02:00
Kuba Szczodrzyński
23410c618d [beken-72xx] Mark SSL client as broken 2022-06-30 19:35:43 +02:00
Kuba Szczodrzyński
b44898f08d [core] Update verbose messages in MbedTLSClient 2022-06-30 19:34:45 +02:00
Kuba Szczodrzyński
165f356439 [core] Fix MbedTLSClient memory leak 2022-06-30 19:33:56 +02:00
Kuba Szczodrzyński
1d0df2936b [beken-72xx] Increase main task stack size 2022-06-30 19:32:37 +02:00
Kuba Szczodrzyński
1684d63e04 [beken-72xx] Fix lwip_ioctl() given wrong argument size 2022-06-30 16:28:29 +02:00
Kuba Szczodrzyński
cf5dfb43d6 [beken-72xx] Fix WiFi station connection 2022-06-29 19:00:15 +02:00
Kuba Szczodrzyński
ded6638ef6 [beken-72xx] Implement broken WiFi station 2022-06-28 22:49:28 +02:00
Kuba Szczodrzyński
a8228851d9 [realtek-ambz] Make WiFi SDK code less verbose 2022-06-27 21:04:22 +02:00
Kuba Szczodrzyński
633289def6 [realtek-ambz] Fix reporting invalid networks after scanning 2022-06-27 21:04:19 +02:00
Kuba Szczodrzyński
f4ff13d6b7 [realtek-ambz] Move WiFiClient and WiFiServer to NetUtils library 2022-06-27 21:04:15 +02:00
Kuba Szczodrzyński
0493ec2245 [beken-72xx] Implement WiFi scanning 2022-06-27 13:03:52 +02:00
Kuba Szczodrzyński
4c6bbb8aae [realtek-ambz] Simplify WiFi scan result handler 2022-06-27 13:01:06 +02:00
Kuba Szczodrzyński
b625f636be [libs] Fix WiFiMulti compiling with debugging enabled 2022-06-27 12:57:33 +02:00
Kuba Szczodrzyński
3bfd62d075 [boards] Update BK7231T partition layout 2022-06-26 19:12:12 +02:00
Kuba Szczodrzyński
b405adb359 [realtek-ambz] Add a wrapper around WiFi::mode() 2022-06-26 18:10:13 +02:00
Kuba Szczodrzyński
accf37de39 [core] Specify toolchain prefix in board.json 2022-06-26 16:04:49 +02:00
Kuba Szczodrzyński
582eed3be8 [core] Fix return types for some methods, check feature flags 2022-06-26 16:03:30 +02:00
Kuba Szczodrzyński
35d5ec03a3 [core] Fix platform.py for frameworks without package 2022-06-26 16:00:55 +02:00
Kuba Szczodrzyński
737c627d44 [boards] Add generic-native board template 2022-06-26 14:42:43 +02:00
Kuba Szczodrzyński
84a3120c7f [docs] Support generic boards in update_docs.py 2022-06-26 14:41:55 +02:00
Kuba Szczodrzyński
99b9ed1181 [docs] Make update_docs.py errors clearer, check for build.variant 2022-06-26 14:41:22 +02:00
Kuba Szczodrzyński
0d636a3285 [docs] Clarify family configuration variables 2022-06-25 10:19:43 +02:00
Kuba Szczodrzyński
79ccd47f71 [beken-72xx] Fix compilation without WiFi implemented 2022-06-25 10:19:20 +02:00
Kuba Szczodrzyński
3ffc70abe5 [realtek-ambz] Fix reading chip MAC address from eFuse 2022-06-24 21:47:00 +02:00
Kuba Szczodrzyński
f4f2eda481 [docs] Fix RTL8710BX clock speed & chip ID 2022-06-24 21:13:58 +02:00
Kuba Szczodrzyński
f4b2c74b0e [realtek-ambz] Fix issues without ADC2, use correct 468k linker script 2022-06-24 21:13:35 +02:00
Kuba Szczodrzyński
111e5a66b6 [core] Fix import errors on latest PIO Core 2022-06-24 21:11:19 +02:00
Kuba Szczodrzyński
b90723130d [boards] Add BW12 board, update boardgen to v0.4.2 2022-06-24 20:05:44 +02:00
Kuba Szczodrzyński
e6179761d4 [boards] Remove unneeded linker scripts 2022-06-24 20:04:16 +02:00
Kuba Szczodrzyński
b371fd3468 [tools] Fix merge_dicts for d2 immutability 2022-06-24 12:18:36 +02:00
Kuba Szczodrzyński
c8fccdbb47 [realtek-ambz] Move common WiFi code to LT API 2022-06-23 23:30:28 +02:00
Kuba Szczodrzyński
4876401809 [beken-72xx] Implement Serial classes 2022-06-23 17:06:44 +02:00
Kuba Szczodrzyński
45af7c188a [beken-72xx] Add UF2 uploading based on bk7231tools 2022-06-23 14:23:22 +02:00
Kuba Szczodrzyński
236e9ccda6 [beken-72xx] Generate UF2 firmware images 2022-06-23 13:32:31 +02:00
Kuba Szczodrzyński
94e8b9f87e [beken-72xx] Fix suppressing SDK output during init 2022-06-22 23:37:12 +02:00
Kuba Szczodrzyński
c9580d6627 [core] Fix hexdump() line formatting 2022-06-22 23:36:36 +02:00
Kuba Szczodrzyński
87929373e2 [realtek-ambz] Declare all wrapped printf() methods 2022-06-21 23:42:02 +02:00
Kuba Szczodrzyński
4e2aec9ced [tools] Fix link2bin issues when having spaces in project name 2022-06-21 19:25:44 +02:00
Kuba Szczodrzyński
fa7957f5e2 [beken-72xx] Fix linking with SDK framework 2022-06-21 18:53:02 +02:00
Kuba Szczodrzyński
4f15805246 [beken-72xx] Implement analogRead() 2022-06-21 18:49:12 +02:00
Kuba Szczodrzyński
cf67c815e9 [docs] Update LT API main page 2022-06-20 21:43:06 +02:00
Kuba Szczodrzyński
5533dc807f [beken-72xx] Implement Wiring core, digital I/O and PWM 2022-06-20 21:34:11 +02:00
Kuba Szczodrzyński
ac2aabe6e3 [beken-72xx] Implement API reboot() and getCpuFreq() 2022-06-20 21:29:02 +02:00
Kuba Szczodrzyński
c6a428ddd4 [core] Rename PinInfo features fields 2022-06-20 21:28:32 +02:00
Kuba Szczodrzyński
a83a845d5a [realtek-ambz] Move common digital/analog utils into core 2022-06-20 21:28:24 +02:00
Kuba Szczodrzyński
c91b188f96 [beken-72xx] Fix Arduino delay(), fix reading heap size 2022-06-20 15:54:20 +02:00
Kuba Szczodrzyński
53a6f4593e [core] Add macros for wrapping and disabling SDK printf() 2022-06-20 15:54:13 +02:00
Kuba Szczodrzyński
0dda769d0f [beken-72xx] Add preliminary Arduino framework core 2022-06-19 23:53:15 +02:00
Kuba Szczodrzyński
848df066c4 [boards] Add WB2L variant definition 2022-06-19 23:42:40 +02:00
Kuba Szczodrzyński
b4005d8bad [realtek-ambz] Standardize all stdio output with printf library 2022-06-19 23:30:40 +02:00
Kuba Szczodrzyński
34c0df2761 [core] Disable FAL info logging 2022-06-19 18:38:22 +02:00
Kuba Szczodrzyński
cedfc2c8db [core] Fix compilation warnings 2022-06-19 17:33:02 +02:00
Kuba Szczodrzyński
c9fe63ec7b [core] Add defines for enabling implemented features 2022-06-19 17:31:14 +02:00
Kuba Szczodrzyński
2fedcb61b5 [core] Migrate Flash library to common code based on FAL 2022-06-19 17:23:16 +02:00
Kuba Szczodrzyński
272b033253 [core] Provide entire flash as "root" partition 2022-06-19 14:18:13 +02:00
Kuba Szczodrzyński
cae03d54d6 [core] Move startup code to libretuya/common 2022-06-19 14:13:51 +02:00
Kuba Szczodrzyński
e70f1a591f [core] Migrate to auto-generated variant definitions 2022-06-18 23:19:28 +02:00
Kuba Szczodrzyński
0e768ac6e4 [core] Move Arduino flags to arduino-common 2022-06-18 21:57:51 +02:00
Kuba Szczodrzyński
bc056eaca2 [docs] Add auto-generated module support page 2022-06-18 21:08:29 +02:00
Kuba Szczodrzyński
a6ad84a3b8 [docs] Use note tag and include-markdown 2022-06-18 21:05:31 +02:00
Kuba Szczodrzyński
a5b953dc80 [core] Add a prefix to ChipFamily enum 2022-06-18 21:04:17 +02:00
Kuba Szczodrzyński
d446b05387 [boards] Add WB2L pinout 2022-06-15 23:23:45 +02:00
Kuba Szczodrzyński
e864e5ef24 [boards] Move PCB definitions to subdir, use base IC pinouts 2022-06-15 23:20:59 +02:00
Kuba Szczodrzyński
e669507759 [beken-72xx] Support C++11 2022-06-14 18:54:31 +02:00
Kuba Szczodrzyński
e50c04cbe1 [beken-72xx] Don't init everything by default, make it quiet 2022-06-14 18:18:49 +02:00
Kuba Szczodrzyński
56dd57f4a0 [beken-72xx] Remove unused components 2022-06-14 17:28:00 +02:00
Kuba Szczodrzyński
f2abb564c7 [beken-72xx] Fix BK7231S 1.0.5 bootloader compatibility 2022-06-14 16:33:13 +02:00
Kuba Szczodrzyński
4e7abb2350 [beken-72xx] Move family fixups to parent 2022-06-14 16:11:25 +02:00
Kuba Szczodrzyński
540e499389 [beken-72xx] Implement SDK binary building 2022-06-14 15:39:28 +02:00
Kuba Szczodrzyński
191a2bdd2a [docs] Add debugging info for RPi 4, fix GPIO numbers 2022-06-14 11:43:07 +02:00
Kuba Szczodrzyński
4d1c8357b4 [realtek-ambz] Move C++ flags to SDK builder 2022-06-13 17:08:20 +02:00
Kuba Szczodrzyński
85b5b1df91 [beken-72xx] Add base BK7231 support config 2022-06-13 16:58:46 +02:00
Kuba Szczodrzyński
c3e2c105d4 [core] Build with properties from Family object 2022-06-12 12:49:04 +02:00
Kuba Szczodrzyński
dba602a081 [tools] Add Beken binary crypto utility 2022-06-11 23:00:00 +02:00
Kuba Szczodrzyński
c3f2ce57f0 [tools] Move functions to utilities, add universal CRC16 class 2022-06-11 18:25:10 +02:00
Kuba Szczodrzyński
bbf8e0b6b6 [realtek-ambz] Better handle WiFi events 2022-06-06 21:45:18 +02:00
Kuba Szczodrzyński
03ab020dc8 [realtek-ambz] Fix ADC reading 2022-06-06 21:44:54 +02:00
Kuba Szczodrzyński
9c1f3225a6 [core] Refactor LibreTuyaAPI into separate units 2022-06-06 16:17:02 +02:00
Kuba Szczodrzyński
f72dd3b7d7 [realtek-ambz] Fix PWM output 2022-06-06 14:52:11 +02:00
Kuba Szczodrzyński
48f6210607 [realtek-ambz] Add gpioRecover() to disable SWD 2022-06-04 22:32:36 +02:00
Kuba Szczodrzyński
6f9be2b139 [realtek-ambz] Fix float abi linking errors 2022-06-04 20:40:09 +02:00
Kuba Szczodrzyński
3217525873 [realtek-ambz] Implement attachInterruptParam 2022-06-04 20:39:24 +02:00
Kuba Szczodrzyński
e26972bd2f [core] Fix OTA not resetting buffer after partial writes 2022-06-04 16:36:37 +02:00
Kuba Szczodrzyński
bf31533306 [core] Add LT.getCpuFreq() method 2022-06-04 16:36:13 +02:00
Kuba Szczodrzyński
0ca0577667 [core] Add cbuf and StreamString libraries 2022-06-04 14:12:36 +02:00
Kuba Szczodrzyński
0e797e7e04 [core] Fix logger color formatting 2022-06-04 13:37:29 +02:00
Kuba Szczodrzyński
a661ef3a3f [core] Add more compat code 2022-06-04 13:37:15 +02:00
Kuba Szczodrzyński
17dc1dcf8c [core] Allow specifying custom UF2 firmware name and version 2022-06-03 12:11:12 +02:00
Kuba Szczodrzyński
4c27aa57b1 [core] Add MD5 library 2022-06-03 12:08:41 +02:00
Kuba Szczodrzyński
a21c07fa03 [release] v0.5.0
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2022-06-02 23:06:11 +02:00
Kuba Szczodrzyński
bdffa7ef53 [core] Add UF2-based uploader 2022-06-02 23:05:35 +02:00
Kuba Szczodrzyński
22d40825bb [tools] Extract common utilities to separate modules 2022-06-02 22:22:23 +02:00
Kuba Szczodrzyński
50f26f546c [core] Use term "family" instead of "platform" 2022-06-02 22:22:19 +02:00
Kuba Szczodrzyński
9c7ea46ec3 [core] Build UF2 OTA image after linking 2022-06-02 22:21:51 +02:00
Kuba Szczodrzyński
5b4cf53d8a [tools] uf2ota: embed build date in extension tags 2022-06-02 14:14:16 +02:00
Kuba Szczodrzyński
79a701a4d4 [tools] uf2ota: fix for Python 3.7, fix Windows path compatibility 2022-06-02 14:12:03 +02:00
Kuba Szczodrzyński
81897e634c [realtek-ambz] Export both OTA images after linking 2022-06-01 21:41:04 +02:00
Kuba Szczodrzyński
3e11da4dd4 [docs] Add resources page 2022-05-31 12:06:24 +02:00
Kuba Szczodrzyński
12aa7fef04 [docs] Move sections from README to docs, add uf2families.json 2022-05-31 11:54:05 +02:00
Kuba Szczodrzyński
1ea6420bbc [core] Add Update library 2022-05-30 22:31:04 +02:00
Kuba Szczodrzyński
f3f1f36525 [core] Add uf2ota library source 2022-05-30 22:23:40 +02:00
Kuba Szczodrzyński
dee9a98cc3 [core] Update OTA API 2022-05-30 21:59:22 +02:00
Kuba Szczodrzyński
3345ce3fb9 [docs] Add missing documents to SUMMARY.md 2022-05-28 20:13:01 +02:00
Kuba Szczodrzyński
de70583838 [core] Put full UF2 Family ID in ChipFamily 2022-05-28 20:09:10 +02:00
Kuba Szczodrzyński
a43a737004 [realtek-ambz] Implement API class methods, fix CPU clock 2022-05-28 19:41:44 +02:00
Kuba Szczodrzyński
1f6899354f [core] Add LT class API methods 2022-05-28 19:39:43 +02:00
Kuba Szczodrzyński
9110a0c47e [docs] Document the UF2 OTA format 2022-05-28 14:48:07 +02:00
Kuba Szczodrzyński
b549790798 [tools] Implement UF2 binary patching, add dumping images 2022-05-28 14:47:45 +02:00
Kuba Szczodrzyński
5df430f3be [tools] Add UF2 OTA writer tool 2022-05-27 20:53:08 +02:00
Kuba Szczodrzyński
f3e8bcd74a [realtek-ambz] Add KVS partition, update boardgen 2022-05-27 15:29:46 +02:00
Kuba Szczodrzyński
4b050e11cf [core] Add dynamic FAL_PART_TABLE generation 2022-05-27 15:29:21 +02:00
Kuba Szczodrzyński
7ddbc09564 [core] Workaround LwIPmDNS compilation 2022-05-26 14:24:51 +02:00
Kuba Szczodrzyński
d3d62f80fd [realtek-ambz] Fix WiFi encryption type conversion 2022-05-26 14:24:29 +02:00
Kuba Szczodrzyński
bc7dbe6eec [api] Fix hexdump() default parameters 2022-05-25 12:27:52 +02:00
Kuba Szczodrzyński
e625f55353 [api] Add hexdump() utility 2022-05-24 17:55:12 +02:00
Kuba Szczodrzyński
aeebff9d5d [realtek-ambz] Fix WiFiEvents linking when not needed 2022-05-24 17:47:45 +02:00
Kuba Szczodrzyński
9a3c077ef1 [core] Add FlashDB KVS library 2022-05-24 17:43:30 +02:00
Kuba Szczodrzyński
91ae692058 [core] Fix gathering external library dependencies 2022-05-24 17:30:14 +02:00
Kuba Szczodrzyński
ad590d1eb2 [release] v0.4.0
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2022-05-23 14:21:19 +02:00
Kuba Szczodrzyński
8b00358901 [core] Add lwIP-based mDNS responder library 2022-05-23 14:20:41 +02:00
Kuba Szczodrzyński
bf4d8bb9be [realtek-ambz] Update to external lwIP v2.0.0 2022-05-23 12:49:18 +02:00
Kuba Szczodrzyński
157dd2f407 [realtek-ambz] Move to external lwIP v1.4.1 2022-05-23 12:49:18 +02:00
Kuba Szczodrzyński
1dc47878d4 [core] Allow using external framework parts 2022-05-18 20:57:09 +02:00
Kuba Szczodrzyński
36e4b6fd45 [core] Write manifests when installing packages 2022-05-18 20:47:40 +02:00
Kuba Szczodrzyński
36d9a6e7e4 [realtek-ambz] Support WiFi events 2022-05-17 19:27:35 +02:00
Kuba Szczodrzyński
b7cceed4d3 [core] Create POSIX utils module 2022-05-16 15:54:52 +02:00
Kuba Szczodrzyński
694c06e7f5 [core] Allow using "arduino" as framework 2022-05-16 15:53:51 +02:00
Kuba Szczodrzyński
12338747bf [realtek-ambz] Add Wire library 2022-05-14 21:47:56 +02:00
Kuba Szczodrzyński
f4f9788f68 [github] Add board readme generated with boardgen 2022-05-14 20:20:39 +02:00
Kuba Szczodrzyński
b9cdcad262 [core] Add boardgen submodule 2022-05-14 14:21:15 +02:00
Kuba Szczodrzyński
e4cd2ddec8 [core] Split boards as base files 2022-05-10 17:48:41 +02:00
Kuba Szczodrzyński
1477649a50 [core] Move LibreTuyaAPI to core directory 2022-05-09 15:41:22 +02:00
Kuba Szczodrzyński
2e80469ab3 [core] Fix and enable SSL client support 2022-05-08 18:43:10 +02:00
Kuba Szczodrzyński
ccf63a4cdb [realtek-ambz] Add platform configs to fixups 2022-05-08 18:42:19 +02:00
Kuba Szczodrzyński
b464871f73 [realtek-ambz] Remove PolarSSL completely, fix errno 2022-05-08 18:41:56 +02:00
Kuba Szczodrzyński
e44834a95e [docs] Fix mkdocs deployment, again, again 2022-05-07 20:47:34 +02:00
Kuba Szczodrzyński
4efefc5c6c [docs] Fix mkdocs deployment, again 2022-05-07 20:38:13 +02:00
Kuba Szczodrzyński
dfd852b2db [docs] Fix mkdocs deployment 2022-05-07 20:36:41 +02:00
Kuba Szczodrzyński
afa7141ceb [docs] Add Doxygen 2022-05-07 20:35:03 +02:00
Kuba Szczodrzyński
ed76b23c69 [release] v0.3.0
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2022-05-06 20:28:10 +02:00
Kuba Szczodrzyński
a469a466ff [github] Update README.md badges 2022-05-06 20:27:43 +02:00
Kuba Szczodrzyński
589d3ef4d8 [core] Refactor realtek-ambz, cleanup, reformat, add missing copyrights 2022-05-06 20:27:06 +02:00
Kuba Szczodrzyński
5aba2eb4a1 [core] Reformat filter_rtl_hard_fault.py with updated black 2022-05-06 15:47:46 +02:00
Kuba Szczodrzyński
b7df8d7b37 [github] Add lint check workflow 2022-05-06 15:42:54 +02:00
Kuba Szczodrzyński
61554e6c7e [realtek-ambz] Describe C library functions 2022-05-06 15:42:27 +02:00
Kuba Szczodrzyński
d8cc61bc0e [realtek-ambz] Remove old WiFi library 2022-05-06 12:14:48 +02:00
Kuba Szczodrzyński
4b6e3956d6 [realtek-ambz] Implement SSL client, cleanup compilation 2022-05-05 21:25:19 +02:00
Kuba Szczodrzyński
9659ff8afa [core] Add MbedTLSClient 2022-05-05 20:56:37 +02:00
Kuba Szczodrzyński
783955cc5d [core] Refactor build system, cleanup unused files 2022-05-04 21:45:30 +02:00
Kuba Szczodrzyński
048556803b [core] Move non-interface classes to libraries 2022-04-30 21:08:09 +02:00
Kuba Szczodrzyński
5c46939556 [release] v0.2.0
Some checks failed
PlatformIO Publish / publish (push) Has been cancelled
2022-04-30 19:11:29 +02:00
Kuba Szczodrzyński
222d58e973 [core] Add WebServer library from ESP32 2022-04-30 19:04:46 +02:00
Kuba Szczodrzyński
38343112a5 [core] Add WiFiServer(addr, port) constructor 2022-04-30 19:03:37 +02:00
Kuba Szczodrzyński
770a7bc4fa [core] Fix GDB init commands 2022-04-30 19:03:02 +02:00
Kuba Szczodrzyński
d6695f127d [core] Add FS API from ESP32 2022-04-30 19:02:23 +02:00
Kuba Szczodrzyński
35e5fc5173 [realtek-ambz] Fix WiFiClient copy assignment 2022-04-30 19:00:17 +02:00
Kuba Szczodrzyński
b58ea46c22 [docs] Fix debugging.md case 2022-04-29 23:19:42 +02:00
Kuba Szczodrzyński
470eb64051 [docs] Migrate to mkdocs 2022-04-29 23:16:32 +02:00
Kuba Szczodrzyński
6192e9be72 [docs] Describe libraries 2022-04-29 21:32:00 +02:00
Kuba Szczodrzyński
b518451888 [realtek-ambz] Fix enabling WiFi before scanning 2022-04-29 21:31:47 +02:00
Kuba Szczodrzyński
7b5dcdf07e [core] Add HTTPClient and WiFiMulti libs 2022-04-29 21:31:29 +02:00
Kuba Szczodrzyński
515d47f055 [core] Add MQTT library compatibility 2022-04-29 19:19:49 +02:00
814 changed files with 52768 additions and 28320 deletions

32
.clang-format Normal file
View File

@@ -0,0 +1,32 @@
# 2025-02-12
Language: Cpp
BasedOnStyle: LLVM
AlignAfterOpenBracket: BlockIndent
AlignArrayOfStructures: Left
AlignConsecutiveAssignments: true
AlignConsecutiveMacros: AcrossComments
AlignEscapedNewlinesLeft: true
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Empty
AllowShortFunctionsOnASingleLine: Empty
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
BreakBeforeTernaryOperators: true
ColumnLimit: 120
ContinuationIndentWidth: 4
EmptyLineBeforeAccessModifier: Always
FixNamespaceComments: true
IndentAccessModifiers: false
IndentCaseLabels: true
IndentWidth: 4
LambdaBodyIndentation: Signature
MaxEmptyLinesToKeep: 1
PenaltyReturnTypeOnItsOwnLine: 1000
QualifierAlignment: Left
ReflowComments: true
SeparateDefinitionBlocks: Always
TabWidth: 4
UseTab: Always

3
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,3 @@
ko_fi: kuba2k2
custom:
- "https://paypal.me/kuba2k2"

View File

@@ -1,46 +0,0 @@
name: PlatformIO Publish
on:
push:
tags:
- v*.*.*
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Cache pip
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Cache PlatformIO
uses: actions/cache@v2
with:
path: ~/.platformio
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
- name: Set up Python
uses: actions/setup-python@v2
- name: Install PlatformIO
run: |
python -m pip install --upgrade pip
pip install --upgrade platformio
- name: Publish PlatformIO package
run: pio package publish --non-interactive
env:
CI: true
PLATFORMIO_AUTH_TOKEN: ${{ secrets.PLATFORMIO_AUTH_TOKEN }}
- name: Get latest version
id: get_version
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
- name: Release on GitHub
uses: softprops/action-gh-release@v1
with:
name: ${{ steps.get_version.outputs.VERSION }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

13
.github/workflows/push-dev.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
name: Push (dev), Pull Request
on:
push:
branches: ["**"]
pull_request:
workflow_dispatch:
jobs:
lint-clang:
name: Run Clang lint
uses: kuba2k2/kuba2k2/.github/workflows/lint-clang.yml@master
lint-python:
name: Run Python lint
uses: kuba2k2/kuba2k2/.github/workflows/lint-python.yml@master

44
.github/workflows/push-master.yml vendored Normal file
View File

@@ -0,0 +1,44 @@
name: Push (master)
on:
push:
branches: ["master"]
workflow_dispatch:
jobs:
docs:
name: Deploy docs
runs-on: ubuntu-latest
steps:
- name: Checkout main
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install docs dependencies
run: pip install -U ltchiptool "boardgen>=0.11.0"
- name: Generate docs and static JSON files
run: |
mkdir -p site/
boardgen ltci
python docs/scripts/write_boards.py
python docs/scripts/write_apis.py
python docs/scripts/prepare_doxygen.py
python docs/scripts/build_json.py
cp *.json site/
- name: Set custom domain
run: |
mkdir -p site/
echo docs.libretiny.eu > site/CNAME
- name: Deploy docs
uses: libretiny-eu/mkdocs-deploy-gh-pages@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CONFIG_FILE: mkdocs.yml
EXTRA_PACKAGES: build-base doxygen
REQUIREMENTS: docs/requirements.txt
CUSTOM_DOMAIN: docs.libretiny.eu

22
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,22 @@
name: Release
on:
push:
tags: ["v*.*.*"]
jobs:
lint-clang:
name: Run Clang lint
uses: kuba2k2/kuba2k2/.github/workflows/lint-clang.yml@master
publish-pio-platform:
name: Publish PlatformIO platform
needs:
- lint-clang
uses: kuba2k2/kuba2k2/.github/workflows/publish-pio-platform.yml@master
secrets:
PLATFORMIO_AUTH_TOKEN: ${{ secrets.PLATFORMIO_AUTH_TOKEN }}
gh-release:
name: Publish GitHub release
needs:
- publish-pio-platform
uses: kuba2k2/kuba2k2/.github/workflows/gh-release.yml@master
permissions:
contents: write

14
.gitignore vendored
View File

@@ -252,3 +252,17 @@ cython_debug/
# End of https://www.toptal.com/developers/gitignore/api/c,c++,visualstudiocode,python
.vscode/settings.json
# mkdocs
xml/
ltapi/
hashChanges.yaml
.piopm
# board files
docs/status/supported_*.md
docs/status/unsupported_boards_*.md
boards/**/*.svg
boards/**/*.md
# other generated files
docs/contrib/lt-api-functions.md

197
README.md
View File

@@ -1,196 +1,39 @@
# LibreTuya
# LibreTiny
<div align="center">
<small>(formerly LibreTuya)</small>
<div align="center" markdown>
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/libretiny-eu/libretiny/push-master.yml?label=docs&logo=markdown)](https://docs.libretiny.eu/)
![GitHub last commit](https://img.shields.io/github/last-commit/libretiny-eu/libretiny?logo=github)
[![Code style: clang-format](https://img.shields.io/badge/code%20style-clang--format-purple.svg)](.clang-format)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![Discord](https://img.shields.io/discord/967863521511608370?color=%235865F2&label=Discord&logo=discord&logoColor=white)](https://discord.gg/SyGCB9Xwtf)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/kuba2k2/platform/libretuya.svg)](https://registry.platformio.org/platforms/kuba2k2/libretuya)
![GitHub last commit](https://img.shields.io/github/last-commit/kuba2k2/libretuya)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/kuba2k2/platform/libretiny.svg)](https://registry.platformio.org/platforms/kuba2k2/libretiny)
![RTL8710BN](https://img.shields.io/badge/-rtl8710bn-blue)
![BK7231](https://img.shields.io/badge/-bk7231-blue)
![LN882H](https://img.shields.io/badge/-ln882h-blue)
</div>
PlatformIO development platform for IoT modules manufactured by Tuya Inc.
PlatformIO development platform for BK7231, RTL8710 and LN882H IoT chips.
The main goal of this project is to provide a usable build environment for IoT developers. While also providing vendor SDKs as PlatformIO cores,
the project focuses on developing working Arduino-compatible cores for supported platforms. The cores are inspired by Espressif's official core for ESP32,
which should make it easier to port/run existing ESP apps on Tuya IoT (and 3-rd party) platforms.
the project focuses on developing working Arduino-compatible cores for supported families. The cores are inspired by Espressif's official core for ESP32,
which should make it easier to port/run existing ESP apps on less-common, unsupported IoT modules.
LibreTuya also provides a common interface for all platform implementations. The interface is based on ESP32 official libraries.
**There's an [ESPHome port](https://docs.libretiny.eu/docs/projects/esphome/) based on LibreTiny, which supports BK7231 and RTL8710B chips.**
**Note:** this project is work-in-progress.
## Usage
<div align="center" markdown>
1. [Install PlatformIO](https://platformio.org/platformio-ide)
2. `platformio platform install libretuya`
3. Create a project, build it and upload!
4. See the [docs](docs/README.md) for any questions/problems.
## [⭐ Getting started ⭐](https://docs.libretiny.eu/docs/getting-started/)
## Board List
A (mostly) complete* list of Tuya wireless module boards.
&nbsp; | Module Name | MCU | Flash | RAM | Pins** | Wi-Fi | BLE | Platform name
------------------------------|------------------------------------------------------------------------------------------------|-------------------------|-------|----------|-------------|-------|-----|---------------
❌ | [WB1S](https://developer.tuya.com/en/docs/iot/wb1s?id=K9duevbj3ol4x) | BK7231T @ 120 MHz | 2 MiB | 256 KiB | 18 (11 I/O) | ✔️ | ✔️ | -
❌ | [WB2L](https://developer.tuya.com/en/docs/iot/wb2l-datasheet?id=K9duegc9bualu) | BK7231T @ 120 MHz | 2 MiB | 256 KiB | 7 (5 I/O) | ✔️ | ✔️ | -
❌ | [WB2S](https://developer.tuya.com/en/docs/iot/wb2s-module-datasheet?id=K9ghecl7kc479) | BK7231T @ 120 MHz | 2 MiB | 256 KiB | 11 (8 I/O) | ✔️ | ✔️ | -
❌ | [WB3L](https://developer.tuya.com/en/docs/iot/wb3l-module-datasheet?id=K9duiggw2v8sp) | BK7231T @ 120 MHz | 2 MiB | 256 KiB | 16 (12 I/O) | ✔️ | ✔️ | -
❌ | [WB3S](https://developer.tuya.com/en/docs/iot/wb3s-module-datasheet?id=K9dx20n6hz5n4) | BK7231T @ 120 MHz | 2 MiB | 256 KiB | 16 (11 I/O) | ✔️ | ✔️ | -
❌ | [WB3S-IPEX](https://developer.tuya.com/en/docs/iot/wb3sipex-module-datasheet?id=K9irq0laun21z) | BK7231T @ 120 MHz | 2 MiB | 256 KiB | 16 (11 I/O) | ✔️ | ✔️ | -
❌ | [WB8P](https://developer.tuya.com/en/docs/iot/wb8p-module-datasheet?id=K9fwx4f89tvzd) | BK7231T @ 120 MHz | 2 MiB | 256 KiB | 10 (8 I/O) | ✔️ | ✔️ | -
❌ | [WBLC5](https://developer.tuya.com/en/docs/iot/wblc5-module-datasheet?id=K9duilns1f3gi) | BK7231T @ 120 MHz | 2 MiB | 256 KiB | 6 (3 I/O) | ✔️ | ✔️ | -
❌ | [WBLC9](https://developer.tuya.com/en/docs/iot/wblc9-module-datasheet?id=K9hgglry2jp5h) | BK7231T @ 120 MHz | 2 MiB | 256 KiB | 8 (6 I/O) | ✔️ | ✔️ | -
❌ | [CB1S](https://developer.tuya.com/en/docs/iot/cb1s-module-datasheet?id=Kaij1abmwyjq2) | BK7231N @ 120 MHz | 2 MiB | 256 KiB | 18 (11 I/O) | ✔️ | ✔️ | -
❌ | [CB2L](https://developer.tuya.com/en/docs/iot/cb2l-module-datasheet?id=Kai2eku1m3pyl) | BK7231N @ 120 MHz | 2 MiB | 256 KiB | 7 (5 I/O) | ✔️ | ✔️ | -
❌ | [CB2S](https://developer.tuya.com/en/docs/iot/cb2s-module-datasheet?id=Kafgfsa2aaypq) | BK7231N @ 120 MHz | 2 MiB | 256 KiB | 11 (8 I/O) | ✔️ | ✔️ | -
❌ | [CB3L](https://developer.tuya.com/en/docs/iot/cb3l-module-datasheet?id=Kai51ngmrh3qm) | BK7231N @ 120 MHz | 2 MiB | 256 KiB | 16 (11 I/O) | ✔️ | ✔️ | -
❌ | [CB3S](https://developer.tuya.com/en/docs/iot/cb3s?id=Kai94mec0s076) | BK7231N @ 120 MHz | 2 MiB | 256 KiB | 22 (14 I/O) | ✔️ | ✔️ | -
❌ | [CB3S-NL](https://developer.tuya.com/en/docs/iot/CB3S-NL-module-datasheet?id=Kbaesan0vyoms) | BK7231NL (?) @ 120 MHz | 2 MiB | 256 KiB | 22 (14 I/O) | ✔️ | ✔️ | -
❌ | [CB3SE](https://developer.tuya.com/en/docs/iot/CB3SE-Module-Datasheet?id=Kanoiluul7nl2) | BK7231N @ 120 MHz | 2 MiB | 256 KiB | 22 (17 I/O) | ✔️ | ✔️ | -
❌ | [CB8P](https://developer.tuya.com/en/docs/iot/cb8p-module-datasheet?id=Kahvig14r1yk9) | BK7231N @ 120 MHz | 2 MiB | 256 KiB | 10 (8 I/O) | ✔️ | ✔️ | -
❌ | [CBLC5](https://developer.tuya.com/en/docs/iot/cblc5-module-datasheet?id=Ka07iqyusq1wm) | BK7231N @ 120 MHz | 2 MiB | 256 KiB | 6 (3 I/O) | ✔️ | ✔️ | -
❌ | [CBLC9](https://developer.tuya.com/en/docs/iot/cblc9-module-datasheet?id=Ka42cqnj9r0i5) | BK7231N @ 120 MHz | 2 MiB | 256 KiB | 8 (6 I/O) | ✔️ | ✔️ | -
❌ | [CBU](https://developer.tuya.com/en/docs/iot/cbu-module-datasheet?id=Ka07pykl5dk4u) | BK7231N @ 120 MHz | 2 MiB | 256 KiB | 21 (18 I/O) | ✔️ | ✔️ | -
❌ | [CBU-IPEX](https://developer.tuya.com/en/docs/iot/cbuipex-module-datasheet?id=Kaedsyurckrhu) | BK7231N @ 120 MHz | 2 MiB | 256 KiB | 21 (18 I/O) | ✔️ | ✔️ | -
❌ | [CBU-NL](https://developer.tuya.com/en/docs/iot/CBU-NL-module-datasheet?id=Kbaeq6j53y0yg) | BK7231N (?) @ 120 MHz | 2 MiB | 256 KiB | 21 (18 I/O) | ✔️ | ✔️ | -
❌ | [WR1](https://developer.tuya.com/en/docs/iot/wifiwr1module?id=K9605tc0k90t3) | RTL8710BN @ 125 MHz | 1 MiB | 256 KiB | 18 (11 I/O) | ✔️ | ❌ | -
❌ | [WR1-IPEX](https://developer.tuya.com/en/docs/iot/wifiwr1ipexmodule?id=K9605t977tx5u) | RTL8710BN @ 125 MHz | 1 MiB | 256 KiB | 18 (11 I/O) | ✔️ | ❌ | -
❌ | [WR1E](https://developer.tuya.com/en/docs/iot/wr1e?id=K96smbbeycxtf) | RTL8710BN @ 125 MHz | 2 MiB | 256 KiB | 18 (11 I/O) | ✔️ | ❌ | -
❌ | [WR2](https://developer.tuya.com/en/docs/iot/wifiwr2module?id=K9605tko0juc3) | RTL8710BN @ 125 MHz | 2 MiB | 256 KiB | 11 (8 I/O) | ✔️ | ❌ | -
❌ | [WR2E](https://developer.tuya.com/en/docs/iot/wr2e?id=K97scnsjhue4h) | RTL8710BN @ 125 MHz | 2 MiB | 256 KiB | 11 (8 I/O) | ✔️ | ❌ | -
❌ | [WR2L](https://developer.tuya.com/en/docs/iot/wifiwr2lmodule?id=K9605tnbj7gva) | RTL8710BX @ 62.5 MHz | 2 MiB | 256 KiB | 7 (5 I/O) | ✔️ | ❌ | -
❌ | [WR2LE](https://developer.tuya.com/en/docs/iot/wr2le?id=K9eio9y9e8i8c) | RTL8710BX @ 62.5 MHz | 2 MiB | 256 KiB | 7 (5 I/O) | ✔️ | ❌ | -
[`wr3`](boards/wr3/README.md) | [WR3](https://developer.tuya.com/en/docs/iot/wr3-module-datasheet?id=K9g3ainzbj9z1) | RTL8710BN @ 125 MHz | 2 MiB | 256 KiB | 16 (12 I/O) | ✔️ | ❌ | `realtek-ambz`
❌ | [WR3E](https://developer.tuya.com/en/docs/iot/wr3e-module-datasheet?id=K9elwlqbfosbc) | RTL8710BN @ 125 MHz | 2 MiB | 256 KiB | 16 (12 I/O) | ✔️ | ❌ | -
❌ | [WR3L](https://developer.tuya.com/en/docs/iot/wifiwr3lmodule?id=K9605tt0kveqm) | RTL8710BX @ 125 MHz (?) | 2 MiB | 256 KiB | 16 (12 I/O) | ✔️ | ❌ | -
❌ | [WR3LE](https://developer.tuya.com/en/docs/iot/wr3le?id=K986l7a1ha8tm) | RTL8710BX @ 62.5 MHz | 2 MiB | 256 KiB | 16 (12 I/O) | ✔️ | ❌ | -
❌ | [WR3N](https://developer.tuya.com/en/docs/iot/wr3n-datasheet?id=K98zdx31ztdge) | RTL8710BN @ 125 MHz | 2 MiB | 256 KiB | 16 (10 I/O) | ✔️ | ❌ | -
❌ | [WR4](https://developer.tuya.com/en/docs/iot/wifiwr4module?id=K9605tvu78p3e) | RTL8710BN @ 125 MHz | 1 MiB | 256 KiB | 16 (12 I/O) | ✔️ | ❌ | -
❌ | [WR5E](https://developer.tuya.com/en/docs/iot/wr5e?id=K986r9pxqxa8i) | RTL8710BX @ 62.5 MHz | 2 MiB | 256 KiB | 15 (12 I/O) | ✔️ | ❌ | -
❌ | [WR6-H](https://developer.tuya.com/en/docs/iot/wr6h-module-datasheet?id=K9pork8eeowgl) | RTL8710BN @ 125 MHz | 2 MiB | 256 KiB | 18 (12 I/O) | ✔️ | ❌ | -
❌ | [WR6](https://developer.tuya.com/en/docs/iot/wr6-datasheet?id=K97rp45u6gff9) | RTL8710BN @ 125 MHz | 2 MiB | 256 KiB | 18 (12 I/O) | ✔️ | ❌ | -
❌ | [WRG1](https://developer.tuya.com/en/docs/iot/wr6-datasheet?id=K97rp45u6gff9) | RTL8711AM @ 166 MHz | 4 MiB | 2048 KiB | 25 (20 I/O) | ✔️ | ❌ | -
❌ | [XR1](https://developer.tuya.com/en/docs/iot/xr1?id=K9lq3y9xo0zkx) | XR809 @ 160 MHz | 2 MiB | 384 KiB | 18 (11 I/O) | ✔️ | ❌ | -
❌ | [XR1-IPEX](https://developer.tuya.com/en/docs/iot/xr1ipex-module-datasheet?id=K9razqu9gqele) | XR809 @ 160 MHz | 2 MiB | 384 KiB | 18 (11 I/O) | ✔️ | ❌ | -
❌ | [XR3](https://developer.tuya.com/en/docs/iot/xr3-datasheet?id=K98s9168qi49g) | XR809 @ 160 MHz | 2 MiB | 384 KiB | 22 (17 I/O) | ✔️ | ❌ | -
❌ | [WE1S](https://developer.tuya.com/en/docs/iot/wifie1smodule?id=K9605thnvg3e7) | ESP8266EX @ 80/160 MHz | 2 MiB | 36 KiB | 18 (11 I/O) | ✔️ | ❌ | -
❌ | [WE2L](https://developer.tuya.com/en/docs/iot/wifie2lmodule?id=K9605ud0gkjmh) | ESP8285 @ 80/160 MHz | 1 MiB | 50 KiB | 7 (5 I/O) | ✔️ | ❌ | -
❌ | [WE2S](https://developer.tuya.com/en/docs/iot/wifie2smodule?id=K9605u79tgxug) | ESP8285 @ 80/160 MHz | 1 MiB | 50 KiB | 11 (8 I/O) | ✔️ | ❌ | -
❌ | [WE3L](https://developer.tuya.com/en/docs/iot/wifie3lpinmodule?id=K9605uj1ar87n) | ESP8266 @ 80/160 MHz | 2 MiB | 50 KiB | 16 (12 I/O) | ✔️ | ❌ | -
❌ | [WE3S](https://developer.tuya.com/en/docs/iot/wifie3smodule?id=K9605ua1cx9tv) | ESP8266 @ 80/160 MHz | 2 MiB | 50 KiB | 16 (12 I/O) | ✔️ | ❌ | -
❌ | [WE3SE](https://developer.tuya.com/en/docs/iot/we3se?id=K97qv6ab7oh8d) | ESP32 @ 240 MHz | 4 MiB | 520 KiB | 22 (17 I/O) | ✔️ | ✔️ | -
❌ | [WE5P](https://developer.tuya.com/en/docs/iot/wifie5pmodule?id=K9605um3dtjbx) | ESP8266 @ 80/160 MHz | 1 MiB | 50 KiB | 15 (11 I/O) | ✔️ | ❌ | -
\* Only modules featuring at least Wi-Fi. WBR, JWBR, CR, (TY)JW and (TY)LC Series are not included here
** I/O count includes GPIOs, ADCs, PWM outputs and UART, but doesn't count CEN/RST and power pins.
## Project structure
```
arduino/
├─ <platform name>/ Arduino Core for specific platform
│ ├─ cores/ Core files
│ ├─ libraries/ Supported built-in libraries
├─ libretuya/
│ ├─ api/ LibreTuya API for Arduino frameworks
│ ├─ compat/ Fixes for compatibility with ESP32 framework
│ ├─ libraries/ Built-in platform-independent libraries
boards/
├─ <board name>/ Board-specific code
│ ├─ variant.cpp Arduino variant initialization
│ ├─ variant.h Arduino variant pin configs
├─ <board name>.json PlatformIO board description
builder/
├─ frameworks/ Framework builders for PlatformIO
│ ├─ <platform name>-sdk.py Vanilla SDK build system
│ ├─ <platform name>-arduino.py Arduino Core build system
├─ arduino-common.py Builder to provide ArduinoCore-API and LibreTuya APIs
├─ main.py Main PlatformIO builder
docs/ Project documentation, guides, tips, etc.
platform/
├─ <platform name>/ Platform-specific configurations
│ ├─ bin/ Binary blobs (bootloaders, etc.)
│ ├─ fixups/ Code fix-ups to replace SDK parts
│ ├─ ld/ Linker scripts
│ ├─ openocd/ OpenOCD configuration files
tools/
├─ <tool name>/ Tools used during the build
platform.json PlatformIO manifest
platform.py Custom PlatformIO script
```
## Platforms
A list of platforms currently available in this project.
Platform name | Supported MCU(s) | Arduino Core | Source SDK (PIO framework)
---------------|------------------------------------------------------------------------|--------------|--------------------------------------------------------------------------
`realtek-ambz` | Realtek [AmebaZ](https://www.amebaiot.com/en/amebaz/) SoC (`RTL87xxB`) | ✔️ | `framework-realtek-amb1` ([amb1_sdk](https://github.com/ambiot/amb1_sdk))
### Realtek Ameba
The logic behind naming of Realtek chips and their series took me some time to figure out:
- RTL8xxxA - Ameba1/Ameba Series
- RTL8xxxB - AmebaZ Series
- RTL8xxxC - AmebaZ2/ZII Series
- RTL8xxxD - AmebaD Series
As such, there are numerous CPUs with the same numbers but different series, which makes them require different code and SDKs.
- [RTL8195AM](https://www.realtek.com/en/products/communications-network-ics/item/rtl8195am)
- RTL8710AF (found in amb1_arduino)
- [RTL8711AM](https://www.realtek.com/en/products/communications-network-ics/item/rtl8711am)
- [RTL8710BN](https://www.realtek.com/en/products/communications-network-ics/item/rtl8710bn)
- RTL8710BX (found in Tuya product pages)
- RTL8710B? (found in amb1_sdk)
- RTL8711B? (found in amb1_sdk)
- [RTL8710CM](https://www.realtek.com/en/products/communications-network-ics/item/rtl8710cm)
- RTL8722CSM (found in ambd_arduino)
- RTL8720DN (found in ambd_arduino)
- [RTL8721DM](https://www.realtek.com/en/products/communications-network-ics/item/rtl8721dm)
- RTL8722DM (found in ambd_arduino)
- and probably many more
Different Ameba series are not compatible with each other. Apparently, there isn't an official public SDK for AmebaZ that can support C++ properly.
## Arduino Core support status
Note: this list will probably change with each functionality update.
&nbsp; | `realtek-ambz`
--------------------|---------------
Core functions | ✔️
GPIO/PWM/IRQ | ✔️/❓/✔️
Analog input | ❓
UART I/O | ✔️
Flash I/O | ❓
**CORE LIBRARIES** |
SoftwareSerial | ❌
SPI | ❌
Wire | ❌
**OTHER LIBRARIES** |
Wi-Fi Station | ✔️
Wi-Fi Access Point | ✔️
Wi-Fi Events | ❌
Wi-Fi Client (SSL) | ✔️ (❌)
Wi-Fi Server | ✔️
SPIFFS | ❌
BLE | -
HTTP | ❌
NTP | ❌
OTA | ❌
MDNS | ❌
MQTT | ❌
SD | ❌
Legend:
- ✔️ working
- ❗ broken
- ❓ untested
- ❌ not implemented (yet?)
- \- not applicable
</div>
## License

65
SUMMARY.md Normal file
View File

@@ -0,0 +1,65 @@
* [Home](README.md)
* [😊 Getting started](docs/getting-started/README.md)
* [➡️ Info on accessing GPIOs](docs/getting-started/gpio.md)
* [](SUMMARY.md)
* [📺 Cloudcutter & ESPHome video guide](https://www.youtube.com/watch?v=sSj8f-HCHQ0)
* [💡 ESPHome setup guide](docs/projects/esphome.md)
* [🛖 ESPHome Hassio Add-On](https://github.com/libretiny-eu/esphome-hass-addon/pkgs/container/libretiny-esphome-hassio)
* [](SUMMARY.md)
* [📲 Flashing/dumping guide](docs/flashing/)
* [🔌 How to flash/enter download mode?](docs/platform/)
* [](SUMMARY.md)
* [💻 Chips, boards, features](docs/status/supported.md)
* [All boards](boards/)
* [](SUMMARY.md)
* 🍪 Chip family docs & info
* [Beken BK72xx](docs/platform/beken-72xx/README.md)
* [Finding encryption keys](docs/platform/beken-72xx/keys.md)
* [Realtek Ameba - info](docs/platform/realtek-amb/README.md)
* [Realtek AmebaZ](docs/platform/realtek-ambz/README.md)
* [Debugging](docs/platform/realtek-ambz/debugging.md)
* [Exception decoder](docs/platform/realtek-ambz/exception-decoder.md)
* [Lightning LN882x](docs/platform/lightning-ln882x/README.md)
* [🔧 LT Configuration](docs/dev/config.md)
* 🧑 Programmer's manual
* [⚠️ Migration guide](docs/dev/migration_v1.0.0.md)
* [🔋 PlatformIO Examples](examples/)
* [📖 LibreTiny API](docs/dev/lt-api.md)
* [C API](ltapi/dir_c7e317b16142bccc961a83c0babf0065.md)
* [C++ API](ltapi/dir_930634efd5dc4a957bbb6e685a3ccda1.md)
* 📚 Arduino Libraries
* [SoftwareSerial](ltapi/class_software_serial.md)
* [WiFi](ltapi/class_wi_fi_class.md)
* [](SUMMARY.md)
* [Flash](ltapi/class_flash_class.md)
* [IPv6Address](ltapi/classarduino_1_1_i_pv6_address.md)
* [MD5](ltapi/libraries_2common_2_m_d5_2_m_d5_8h.md)
* [mDNS](ltapi/classm_d_n_s.md)
* [Update](ltapi/class_update_class.md)
* [WiFiClient](ltapi/class_i_wi_fi_client.md)
* [WiFiClientSecure](ltapi/class_i_wi_fi_client_secure.md)
* [WiFiServer](ltapi/class_i_wi_fi_server.md)
* [WiFiUDP](ltapi/class_i_wi_fi_u_d_p.md)
* [](SUMMARY.md)
* [HTTPClient](ltapi/class_h_t_t_p_client.md)
* [StreamString](ltapi/class_stream_string.md)
* [WebServer](ltapi/class_web_server.md)
* [WiFiMulti](ltapi/class_wi_fi_multi.md)
* [](SUMMARY.md)
* [External compatible libraries](docs/dev/libs-3rd-party.md)
* Full documentation
* [Classes](ltapi/classes.md)
* [Functions](ltapi/functions.md)
* [Macros](ltapi/macros.md)
* [File list](ltapi/files.md)
* 👷 Contributor's manual (WIP)
* [Porting new families](docs/contrib/porting.md)
* [API functions guide](docs/contrib/lt-api.md)
* [C standard library](docs/contrib/stdlib.md)
* [📁 Project structure](docs/contrib/project-structure.md)
* [✈️ OTA format](docs/contrib/ota/README.md)
* [uf2ota.py tool](docs/contrib/ota/uf2ota.md)
* [uf2ota.h library](docs/contrib/ota/library.md)
* [📓 TODO](docs/TODO.md)
* [](SUMMARY.md)
* [🔗 Resources](docs/resources/)

View File

@@ -1,2 +0,0 @@
realtek-ambz Realtek AmebaZ Arduino Core
libretuya Interfaces for LibreTuya Arduino cores

View File

@@ -1,25 +0,0 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct {
uint8_t manufacturerId;
uint8_t chipId;
uint8_t chipSizeId;
} FlashId;
class IFlashClass {
public:
IFlashClass() {}
~IFlashClass() {}
virtual FlashId getChipId() = 0;
virtual uint32_t getSize() = 0;
virtual bool eraseSector(uint32_t sector) = 0;
virtual bool readBlock(uint32_t offset, uint8_t *data, size_t size) = 0;
virtual bool writeBlock(uint32_t offset, uint8_t *data, size_t size) = 0;
};

View File

@@ -1,91 +0,0 @@
/*
IPv6Address.cpp - Base class that provides IPv6Address
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 <Arduino.h>
#include <api/Print.h>
#include "IPv6Address.h"
IPv6Address::IPv6Address()
{
memset(_address.bytes, 0, sizeof(_address.bytes));
}
IPv6Address::IPv6Address(const uint8_t *address)
{
memcpy(_address.bytes, address, sizeof(_address.bytes));
}
IPv6Address::IPv6Address(const uint32_t *address)
{
memcpy(_address.bytes, (const uint8_t *)address, sizeof(_address.bytes));
}
IPv6Address& IPv6Address::operator=(const uint8_t *address)
{
memcpy(_address.bytes, address, sizeof(_address.bytes));
return *this;
}
bool IPv6Address::operator==(const uint8_t* addr) const
{
return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0;
}
size_t IPv6Address::printTo(Print& p) const
{
/* size_t n = 0;
for(int i = 0; i < 16; i+=2) {
if(i){
n += p.print(':');
}
n += p.printf("%02x", _address.bytes[i]);
n += p.printf("%02x", _address.bytes[i+1]);
}
return n; */
}
String IPv6Address::toString() const
{
char szRet[40];
sprintf(szRet,"%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
_address.bytes[0], _address.bytes[1], _address.bytes[2], _address.bytes[3],
_address.bytes[4], _address.bytes[5], _address.bytes[6], _address.bytes[7],
_address.bytes[8], _address.bytes[9], _address.bytes[10], _address.bytes[11],
_address.bytes[12], _address.bytes[13], _address.bytes[14], _address.bytes[15]);
return String(szRet);
}
bool IPv6Address::fromString(const char *address)
{
//format 0011:2233:4455:6677:8899:aabb:ccdd:eeff
if(strlen(address) != 39){
return false;
}
char * pos = (char *)address;
size_t i = 0;
for(i = 0; i < 16; i+=2) {
if(!sscanf(pos, "%2hhx", &_address.bytes[i]) || !sscanf(pos+2, "%2hhx", &_address.bytes[i+1])){
return false;
}
pos += 5;
}
return true;
}

View File

@@ -1,98 +0,0 @@
/*
IPv6Address.h - Base class that provides IPv6Address
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 <api/String.h>
#include <api/Print.h>
// A class to make it easier to handle and pass around IP addresses
namespace arduino {
class IPv6Address: public Printable
{
private:
union {
uint8_t bytes[16]; // IPv4 address
uint32_t dword[4];
} _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
IPv6Address();
IPv6Address(const uint8_t *address);
IPv6Address(const uint32_t *address);
virtual ~IPv6Address() {}
bool fromString(const char *address);
bool fromString(const String &address) { return fromString(address.c_str()); }
operator const uint8_t*() const
{
return _address.bytes;
}
operator const uint32_t*() const
{
return _address.dword;
}
bool operator==(const IPv6Address& addr) const
{
return (_address.dword[0] == addr._address.dword[0])
&& (_address.dword[1] == addr._address.dword[1])
&& (_address.dword[2] == addr._address.dword[2])
&& (_address.dword[3] == addr._address.dword[3]);
}
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 IPv6Address objects from other types
IPv6Address& operator=(const uint8_t *address);
// TODO implement printTo()
virtual size_t printTo(Print& p) const;
String toString() const;
friend class UDP;
friend class Client;
friend class Server;
};
}
using arduino::IPv6Address;

View File

@@ -1,36 +0,0 @@
#pragma once
#ifndef LT_VERSION
#define LT_VERSION 1.0.0
#endif
#ifndef LT_BOARD
#define LT_BOARD unknown
#endif
#define STRINGIFY(x) #x
#define STRINGIFY_MACRO(x) STRINGIFY(x)
#define LT_VERSION_STR STRINGIFY_MACRO(LT_VERSION)
#define LT_BOARD_STR STRINGIFY_MACRO(LT_BOARD)
#include <Arduino.h>
#include "LibreTuyaConfig.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#include "lt_logger.h"
#ifdef __cplusplus
} // extern "C"
#endif
#define LT_BANNER() \
LT_LOG( \
LT_LEVEL_INFO, \
"main.cpp", \
__LINE__, \
"LibreTuya v" LT_VERSION_STR " on " LT_BOARD_STR ", compiled at " __DATE__ " " __TIME__ \
)

View File

@@ -1,64 +0,0 @@
#pragma once
// see docs/API Configuration
// Loglevels
#define LT_LEVEL_VERBOSE LT_LEVEL_TRACE
#define LT_LEVEL_TRACE 0
#define LT_LEVEL_DEBUG 1
#define LT_LEVEL_INFO 2
#define LT_LEVEL_WARN 3
#define LT_LEVEL_ERROR 4
#define LT_LEVEL_FATAL 5
// Logger enabled/disabled
#ifndef LT_LOGGER
#define LT_LOGGER 1
#endif
// Logger format options
#ifndef LT_LOGGER_TIMESTAMP
#define LT_LOGGER_TIMESTAMP 1
#endif
#ifndef LT_LOGGER_FILE
#define LT_LOGGER_FILE 0
#endif
#ifndef LT_LOGGER_TASK
#define LT_LOGGER_TASK 1
#endif
#ifndef LT_LOGGER_COLOR
#define LT_LOGGER_COLOR 0
#endif
#ifndef LT_PRINTF_BROKEN
#define LT_PRINTF_BROKEN 0
#endif
// Global loglevel
#ifndef LT_LOGLEVEL
#define LT_LOGLEVEL LT_LEVEL_INFO
#endif
// Per-module debugging
#ifndef LT_DEBUG_WIFI
#define LT_DEBUG_WIFI 0
#endif
#ifndef LT_DEBUG_WIFI_CLIENT
#define LT_DEBUG_WIFI_CLIENT 0
#endif
#ifndef LT_DEBUG_WIFI_SERVER
#define LT_DEBUG_WIFI_SERVER 0
#endif
#ifndef LT_DEBUG_WIFI_STA
#define LT_DEBUG_WIFI_STA 0
#endif
#ifndef LT_DEBUG_WIFI_AP
#define LT_DEBUG_WIFI_AP 0
#endif

View File

@@ -1,177 +0,0 @@
/*
WiFi.h - esp32 Wifi support.
Based on WiFi.h from Arduino WiFi shield library.
Copyright (c) 2011-2014 Arduino. All right reserved.
Modified by Ivan Grokhotkov, December 2014
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 <api/IPAddress.h>
#include <api/IPv6Address.h>
#include <api/Print.h>
#include "WiFiType.h"
// TODO wifi events
// TODO WiFiMulti library
class IWiFiClass {
public:
virtual void printDiag(Print &dest) = 0;
};
class IWiFiGenericClass {
public:
virtual int32_t channel(void) = 0;
virtual bool mode(WiFiMode mode) = 0;
virtual WiFiMode getMode() = 0;
virtual WiFiStatus status() = 0;
virtual bool enableSTA(bool enable) = 0;
virtual bool enableAP(bool enable) = 0;
virtual bool setSleep(bool enable) = 0;
virtual bool getSleep() = 0;
virtual bool setTxPower(int power) = 0;
virtual int getTxPower() = 0;
virtual int hostByName(const char *hostname, IPAddress &aResult) {
aResult = hostByName(hostname);
return true;
}
virtual IPAddress hostByName(const char *hostname) = 0;
static IPAddress calculateNetworkID(IPAddress ip, IPAddress subnet);
static IPAddress calculateBroadcast(IPAddress ip, IPAddress subnet);
static uint8_t calculateSubnetCIDR(IPAddress subnetMask);
static String macToString(uint8_t *mac);
};
class IWiFiSTAClass {
public:
virtual WiFiStatus begin(
const char *ssid,
const char *passphrase = NULL,
int32_t channel = 0,
const uint8_t *bssid = NULL,
bool connect = true
) = 0;
virtual WiFiStatus begin(
char *ssid, char *passphrase = NULL, int32_t channel = 0, const uint8_t *bssid = NULL, bool connect = true
) = 0;
virtual bool config(
IPAddress localIP,
IPAddress gateway,
IPAddress subnet,
IPAddress dns1 = (uint32_t)0x00000000,
IPAddress dns2 = (uint32_t)0x00000000
) = 0;
virtual bool reconnect() = 0;
virtual bool disconnect(bool wifiOff = false) = 0;
virtual bool isConnected();
virtual bool setAutoReconnect(bool autoReconnect) = 0;
virtual bool getAutoReconnect() = 0;
virtual WiFiStatus waitForConnectResult(unsigned long timeout) = 0;
virtual IPAddress localIP() = 0;
virtual uint8_t *macAddress(uint8_t *mac) = 0;
virtual String macAddress() = 0;
virtual IPAddress subnetMask() = 0;
virtual IPAddress gatewayIP() = 0;
virtual IPAddress dnsIP(uint8_t dns_no = 0) = 0;
virtual IPAddress broadcastIP() = 0;
virtual IPAddress networkID() = 0;
virtual uint8_t subnetCIDR() = 0;
virtual bool enableIpV6() = 0;
virtual IPv6Address localIPv6() = 0;
virtual const char *getHostname() = 0;
virtual bool setHostname(const char *hostname) = 0;
virtual bool setMacAddress(const uint8_t *mac) = 0;
inline bool hostname(const String &aHostname) {
return setHostname(aHostname.c_str());
}
virtual const String SSID() = 0;
virtual const String psk() = 0;
virtual uint8_t *BSSID() = 0;
virtual String BSSIDstr() = 0;
virtual int8_t RSSI() = 0;
virtual WiFiAuthMode getEncryption() = 0;
};
class IWiFiScanClass {
public:
virtual int16_t scanNetworks(
bool async = false,
bool showHidden = false,
bool passive = false,
uint32_t maxMsPerChannel = 300,
uint8_t channel = 0
) = 0;
virtual bool getNetworkInfo(
uint8_t networkItem,
String &ssid,
WiFiAuthMode &encryptionType,
int32_t &RSSI,
uint8_t *&BSSID,
int32_t &channel
) = 0;
virtual int16_t scanComplete() = 0;
virtual void scanDelete() = 0;
virtual String SSID(uint8_t networkItem) = 0;
virtual WiFiAuthMode encryptionType(uint8_t networkItem) = 0;
virtual int32_t RSSI(uint8_t networkItem) = 0;
virtual uint8_t *BSSID(uint8_t networkItem) = 0;
virtual String BSSIDstr(uint8_t networkItem) = 0;
virtual int32_t channel(uint8_t networkItem) = 0;
};
class IWiFiAPClass {
public:
virtual bool softAP(
const char *ssid, const char *passphrase = NULL, int channel = 1, bool ssidHidden = false, int maxClients = 4
) = 0;
virtual bool softAPConfig(IPAddress localIP, IPAddress gateway, IPAddress subnet) = 0;
virtual bool softAPdisconnect(bool wifiOff = false) = 0;
virtual uint8_t softAPgetStationNum() = 0;
virtual IPAddress softAPIP() = 0;
virtual IPAddress softAPBroadcastIP() = 0;
virtual IPAddress softAPNetworkID() = 0;
virtual uint8_t softAPSubnetCIDR() = 0;
virtual bool softAPenableIpV6() = 0;
virtual IPv6Address softAPIPv6() = 0;
virtual const char *softAPgetHostname() = 0;
virtual bool softAPsetHostname(const char *hostname) = 0;
virtual uint8_t *softAPmacAddress(uint8_t *mac) = 0;
virtual String softAPmacAddress(void) = 0;
virtual const String softAPSSID(void) = 0;
};

View File

@@ -1,63 +0,0 @@
/*
WiFiClientSecure.h - Base class that provides Client SSL to ESP32
Copyright (c) 2011 Adrian McEwen. All right reserved.
Additions Copyright (C) 2017 Evandro Luis Copercini.
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 "WiFi.h"
class IWiFiClientSecure : public IWiFiClient {
public:
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);
int connect(IPAddress ip, uint16_t port, const char *pskIdent, const char *psKey);
int connect(const char *host, uint16_t port, const char *pskIdent, const char *psKey);
int lastError(char *buf, const size_t size);
void setInsecure(); // Don't validate the chain, just accept whatever is given. VERY INSECURE!
void setPreSharedKey(const char *pskIdent, const char *psKey); // psKey in Hex
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);
bool verify(const char *fingerprint, const char *domain_name);
void setHandshakeTimeout(unsigned long handshake_timeout);
WiFiClientSecure &operator=(const WiFiClientSecure &other);
bool operator==(const bool value) {
return bool() == value;
}
bool operator!=(const bool value) {
return bool() != value;
}
bool operator==(const WiFiClientSecure &);
bool operator!=(const WiFiClientSecure &rhs) {
return !this->operator==(rhs);
};
using Print::write;
};

View File

@@ -1,66 +0,0 @@
/*
ESP8266WiFiType.h - esp8266 Wifi support.
Copyright (c) 2011-2014 Arduino. All right reserved.
Modified by Ivan Grokhotkov, December 2014
Reworked by Markus Sattler, December 2015
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
#define WIFI_SCAN_RUNNING (-1)
#define WIFI_SCAN_FAILED (-2)
#define WiFiMode_t wifi_mode_t
#define WiFiMode wifi_mode_t
#define WiFiStatus wl_status_t
#define WiFiAuthMode wifi_auth_mode_t
#define WIFI_OFF WIFI_MODE_NULL
#define WIFI_STA WIFI_MODE_STA
#define WIFI_AP WIFI_MODE_AP
#define WIFI_AP_STA WIFI_MODE_APSTA
typedef enum {
WIFI_MODE_NULL = 0,
WIFI_MODE_STA,
WIFI_MODE_AP,
WIFI_MODE_APSTA,
WIFI_MODE_MAX,
} wifi_mode_t;
typedef enum {
WL_NO_SHIELD = 255, // for compatibility with WiFi Shield library
WL_IDLE_STATUS = 0,
WL_NO_SSID_AVAIL = 1,
WL_SCAN_COMPLETED = 2,
WL_CONNECTED = 3,
WL_CONNECT_FAILED = 4,
WL_CONNECTION_LOST = 5,
WL_DISCONNECTED = 6,
} wl_status_t;
typedef enum {
WIFI_AUTH_INVALID = 255,
WIFI_AUTH_AUTO = 200,
WIFI_AUTH_OPEN = 0,
WIFI_AUTH_WEP = 1,
WIFI_AUTH_WPA = 5,
WIFI_AUTH_WPA2 = 6,
WIFI_AUTH_WPA_PSK = 2,
WIFI_AUTH_WPA2_PSK = 3,
WIFI_AUTH_WPA_WPA2_PSK = 4,
} wifi_auth_mode_t;

View File

@@ -1,11 +0,0 @@
#pragma once
#include <Arduino.h>
#include <api/Udp.h>
class IWiFiUDP : public UDP {
public:
uint8_t beginMulticast(IPAddress ip, uint16_t port);
int beginMulticastPacket();
int beginPacket();
};

View File

@@ -1,89 +0,0 @@
#pragma once
#include "LibreTuyaConfig.h"
#include <stdint.h>
#if LT_LOGGER_FILE
#define LT_LOG(level, file, line, ...) lt_log(level, file, line, __VA_ARGS__)
void lt_log(const uint8_t level, const char *filename, const unsigned short line, const char *format, ...);
#else
#define LT_LOG(level, file, line, ...) lt_log(level, __VA_ARGS__)
void lt_log(const uint8_t level, const char *format, ...);
#endif
#if LT_LEVEL_TRACE >= LT_LOGLEVEL
#define LT_T(...) LT_LOG(LT_LEVEL_TRACE, __FILE__, __LINE__, __VA_ARGS__)
#define LT_V(...) LT_LOG(LT_LEVEL_TRACE, __FILE__, __LINE__, __VA_ARGS__)
#else
#define LT_T(...)
#define LT_V(...)
#endif
#if LT_LEVEL_DEBUG >= LT_LOGLEVEL
#define LT_D(...) LT_LOG(LT_LEVEL_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
#else
#define LT_D(...)
#endif
#if LT_LEVEL_INFO >= LT_LOGLEVEL
#define LT_I(...) LT_LOG(LT_LEVEL_INFO, __FILE__, __LINE__, __VA_ARGS__)
#else
#define LT_I(...)
#endif
#if LT_LEVEL_WARN >= LT_LOGLEVEL
#define LT_W(...) LT_LOG(LT_LEVEL_WARN, __FILE__, __LINE__, __VA_ARGS__)
#else
#define LT_W(...)
#endif
#if LT_LEVEL_ERROR >= LT_LOGLEVEL
#define LT_E(...) LT_LOG(LT_LEVEL_ERROR, __FILE__, __LINE__, __VA_ARGS__)
#else
#define LT_E(...)
#endif
#if LT_LEVEL_FATAL >= LT_LOGLEVEL
#define LT_F(...) LT_LOG(LT_LEVEL_FATAL, __FILE__, __LINE__, __VA_ARGS__)
#else
#define LT_F(...)
#endif
#define LT_T_MOD(module, ...) \
do { \
if (module) { \
LT_T(__VA_ARGS__) \
} \
} while (0)
#define LT_D_MOD(module, ...) \
do { \
if (module) { \
LT_D(__VA_ARGS__) \
} \
} while (0)
// WiFi.cpp
#define LT_T_WG(...) LT_T_MOD(LT_DEBUG_WIFI, __VA_ARGS__)
#define LT_V_WG(...) LT_T_MOD(LT_DEBUG_WIFI, __VA_ARGS__)
#define LT_D_WG(...) LT_D_MOD(LT_DEBUG_WIFI, __VA_ARGS__)
// WiFiClient.cpp
#define LT_T_WC(...) LT_T_MOD(LT_DEBUG_WIFI_CLIENT, __VA_ARGS__)
#define LT_V_WC(...) LT_T_MOD(LT_DEBUG_WIFI_CLIENT, __VA_ARGS__)
#define LT_D_WC(...) LT_D_MOD(LT_DEBUG_WIFI_CLIENT, __VA_ARGS__)
// WiFiServer.cpp
#define LT_T_WS(...) LT_T_MOD(LT_DEBUG_WIFI_SERVER, __VA_ARGS__)
#define LT_V_WS(...) LT_T_MOD(LT_DEBUG_WIFI_SERVER, __VA_ARGS__)
#define LT_D_WS(...) LT_D_MOD(LT_DEBUG_WIFI_SERVER, __VA_ARGS__)
// WiFiSTA.cpp
#define LT_T_WSTA(...) LT_T_MOD(LT_DEBUG_WIFI_STA, __VA_ARGS__)
#define LT_V_WSTA(...) LT_T_MOD(LT_DEBUG_WIFI_STA, __VA_ARGS__)
#define LT_D_WSTA(...) LT_D_MOD(LT_DEBUG_WIFI_STA, __VA_ARGS__)
// WiFiAP.cpp
#define LT_T_WAP(...) LT_T_MOD(LT_DEBUG_WIFI_AP, __VA_ARGS__)
#define LT_V_WAP(...) LT_T_MOD(LT_DEBUG_WIFI_AP, __VA_ARGS__)
#define LT_D_WAP(...) LT_D_MOD(LT_DEBUG_WIFI_AP, __VA_ARGS__)

View File

@@ -1,58 +0,0 @@
/*
Arduino.h - Main include file for the Arduino SDK
Copyright (c) 2005-2013 Arduino Team. 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
#ifdef __cplusplus
#include "WCharacterFixup.h"
#endif
#define PinMode PinModeArduino // this conflicts with SDK enum
#include <api/ArduinoAPI.h>
#include <api/LibreTuyaAPI.h>
#undef PinMode
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
extern uint32_t SystemCoreClock;
#define clockCyclesPerMicrosecond() ( SystemCoreClock / 1000000L )
#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (SystemCoreClock / 1000L) )
#define microsecondsToClockCycles(a) ( (a) * (SystemCoreClock / 1000000L) )
#include "WVariant.h"
#ifdef __cplusplus
} // extern "C"
#endif
// Include board variant
#include "variant.h"
#define interrupts() vPortClearInterruptMask(0)
#define noInterrupts() ulPortSetInterruptMask()
/*
* \brief SAM3 products have only one reference for ADC
*/
typedef enum _eAnalogReference
{
AR_DEFAULT,
} eAnalogReference ;

View File

@@ -1,7 +0,0 @@
#include <api/Print.h>
class CountingStream : public Print
{
virtual size_t write(uint8_t) { return 1; };
virtual size_t write(const uint8_t *buffer, size_t size) { return size; };
};

View File

@@ -1,198 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_FUNCTIONPOINTER_H
#define MBED_FUNCTIONPOINTER_H
#include <string.h>
#include <stdint.h>
/* If we had variaditic templates, this wouldn't be a problem, but until C++11 is enabled, we are stuck with multiple classes... */
/** A class for storing and calling a pointer to a static or member function
*/
template <typename R, typename A1>
class FunctionPointerArg1{
public:
/** Create a FunctionPointer, attaching a static function
*
* @param function The static function to attach (default is none)
*/
FunctionPointerArg1(R (*function)(A1) = 0) {
attach(function);
}
/** Create a FunctionPointer, attaching a member function
*
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
* @param function The address of the member function to attach
*/
template<typename T>
FunctionPointerArg1(T *object, R (T::*member)(A1)) {
attach(object, member);
}
/** Attach a static function
*
* @param function The static function to attach (default is none)
*/
void attach(R (*function)(A1)) {
_p.function = function;
_membercaller = 0;
}
/** Attach a member function
*
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
* @param function The address of the member function to attach
*/
template<typename T>
void attach(T *object, R (T::*member)(A1)) {
_p.object = static_cast<void*>(object);
*reinterpret_cast<R (T::**)(A1)>(_member) = member;
_membercaller = &FunctionPointerArg1::membercaller<T>;
}
/** Call the attached static or member function
*/
R call(A1 a) {
if (_membercaller == 0 && _p.function) {
return _p.function(a);
} else if (_membercaller && _p.object) {
return _membercaller(_p.object, _member, a);
}
return (R)0;
}
/** Get registered static function
*/
R(*get_function(A1))() {
return _membercaller ? (R(*)(A1))0 : (R(*)(A1))_p.function;
}
R operator ()(A1 a) {
return call(a);
}
operator bool(void) const {
return (_membercaller != NULL ? _p.object : (void*)_p.function) != NULL;
}
private:
template<typename T>
static R membercaller(void *object, uintptr_t *member, A1 a) {
T* o = static_cast<T*>(object);
R (T::**m)(A1) = reinterpret_cast<R (T::**)(A1)>(member);
return (o->**m)(a);
}
union {
R (*function)(A1); // static function pointer
void *object; // object this pointer
} _p;
uintptr_t _member[4]; // aligned raw member function pointer storage - converted back by registered _membercaller
R (*_membercaller)(void*, uintptr_t*, A1); // registered membercaller function to convert back and call _m.member on _object
};
/** A class for storing and calling a pointer to a static or member function (R ()(void))
*/
template <typename R>
class FunctionPointerArg1<R, void>{
public:
/** Create a FunctionPointer, attaching a static function
*
* @param function The static function to attach (default is none)
*/
FunctionPointerArg1(R (*function)(void) = 0) {
attach(function);
}
/** Create a FunctionPointer, attaching a member function
*
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
* @param function The address of the void member function to attach
*/
template<typename T>
FunctionPointerArg1(T *object, R (T::*member)(void)) {
attach(object, member);
}
/** Attach a static function
*
* @param function The void static function to attach (default is none)
*/
void attach(R (*function)(void)) {
_p.function = function;
_membercaller = 0;
}
/** Attach a member function
*
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
* @param function The address of the void member function to attach
*/
template<typename T>
void attach(T *object, R (T::*member)(void)) {
_p.object = static_cast<void*>(object);
*reinterpret_cast<R (T::**)(void)>(_member) = member;
_membercaller = &FunctionPointerArg1::membercaller<T>;
}
/** Call the attached static or member function
*/
R call(){
if (_membercaller == 0 && _p.function) {
return _p.function();
} else if (_membercaller && _p.object) {
return _membercaller(_p.object, _member);
}
return (R)0;
}
/** Get registered static function
*/
R(*get_function())() {
return _membercaller ? (R(*)())0 : (R(*)())_p.function;
}
R operator ()(void) {
return call();
}
operator bool(void) const {
return (_membercaller != NULL ? _p.object : (void*)_p.function) != NULL;
}
private:
template<typename T>
static R membercaller(void *object, uintptr_t *member) {
T* o = static_cast<T*>(object);
R (T::**m)(void) = reinterpret_cast<R (T::**)(void)>(member);
return (o->**m)();
}
union {
R (*function)(void); // static function pointer
void *object; // object this pointer
} _p;
uintptr_t _member[4]; // aligned raw member function pointer storage - converted back by registered _membercaller
R (*_membercaller)(void*, uintptr_t*); // registered membercaller function to convert back and call _m.member on _object
};
typedef FunctionPointerArg1<void, void> FunctionPointer;
typedef FunctionPointerArg1<void, int> event_callback_t;
#endif

View File

@@ -1,132 +0,0 @@
/*
Copyright (c) 2011 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 "Arduino.h"
#include "LOGUARTClass.h"
#define LOG_UART_MODIFIABLE_BAUD_RATE 1
#ifdef __cplusplus
extern "C" {
#endif
#include "osdep_service.h"
#include "rtl8710b.h"
extern int LOGUART_SetBaud(uint32_t BaudRate); // from fixups/log_uart.c
#ifdef __cplusplus
}
#endif
RingBuffer rx_buffer0;
LOGUARTClass::LOGUARTClass(int dwIrq, RingBuffer* pRx_buffer )
{
_rx_buffer = pRx_buffer;
_dwIrq = dwIrq;
}
// Protected Methods //////////////////////////////////////////////////////////////
// Public Methods //////////////////////////////////////////////////////////////
void IrqHandler( void )
{
uint8_t data = 0;
BOOL PullMode = _FALSE;
uint32_t IrqEn = DiagGetIsrEnReg();
DiagSetIsrEnReg(0);
data = DiagGetChar(PullMode);
if ( data > 0 )
rx_buffer0.store_char(data);
DiagSetIsrEnReg(IrqEn);
}
void LOGUARTClass::begin( const uint32_t dwBaudRate )
{
DIAG_UartReInit((IRQ_FUN) IrqHandler);
NVIC_SetPriority(UART_LOG_IRQ, 10);
LOGUART_SetBaud(dwBaudRate);
}
void LOGUARTClass::end( void )
{
// clear any received data
_rx_buffer->_iHead = _rx_buffer->_iTail ;
}
int LOGUARTClass::available( void )
{
return (uint32_t)(SERIAL_BUFFER_SIZE + _rx_buffer->_iHead - _rx_buffer->_iTail) % SERIAL_BUFFER_SIZE ;
}
int LOGUARTClass::peek( void )
{
if ( _rx_buffer->_iHead == _rx_buffer->_iTail )
return -1 ;
return _rx_buffer->_aucBuffer[_rx_buffer->_iTail] ;
}
int LOGUARTClass::read( void )
{
// if the head isn't ahead of the tail, we don't have any characters
if ( _rx_buffer->_iHead == _rx_buffer->_iTail )
return -1 ;
uint8_t uc = _rx_buffer->_aucBuffer[_rx_buffer->_iTail] ;
_rx_buffer->_iTail = (unsigned int)(_rx_buffer->_iTail + 1) % SERIAL_BUFFER_SIZE ;
return uc ;
}
void LOGUARTClass::flush( void )
{
// TODO:
// while ( serial_writable(&(this->sobj)) != 1 );
/*
// Wait for transmission to complete
while ((_pUart->UART_SR & UART_SR_TXRDY) != UART_SR_TXRDY)
;
*/
}
size_t LOGUARTClass::write( const uint8_t uc_data )
{
DiagPutChar(uc_data);
return 1;
}
LOGUARTClass Serial(UART_LOG_IRQ, &rx_buffer0);
bool Serial_available() {
return Serial.available() > 0;
}

View File

@@ -1,53 +0,0 @@
/*
Copyright (c) 2011 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
*/
#pragma once
#include "api/HardwareSerial.h"
#include "api/RingBuffer.h"
using namespace arduino;
class LOGUARTClass : public HardwareSerial
{
public:
LOGUARTClass(int dwIrq, RingBuffer* pRx_buffer );
void begin(const uint32_t dwBaudRate);
inline void begin(const uint32_t dwBaudRate, uint16_t config) {
begin(dwBaudRate); // TODO implement this properly
}
void end(void);
int available(void);
int peek(void);
int read(void);
void flush(void);
size_t write(const uint8_t c);
using Print::write; // pull in write(str) and write(buf, size) from Print
operator bool() { return true; }; // UART always active
protected:
RingBuffer *_rx_buffer;
int _dwIrq;
private:
friend bool Serial_available();
};

View File

@@ -1,59 +0,0 @@
#include "PowerManagement.h"
#include "Arduino.h"
#ifdef __cplusplus
extern "C" {
#include "freertos_pmu.h"
#include "sys_api.h"
#include "sleep_ex_api.h"
}
#endif
#include "variant.h"
#if defined(BOARD_RTL8195A)
#define SAVE_LOCK_PIN 18
#elif defined(BOARD_RTL8710)
#define SAVE_LOCK_PIN 7 // PB_1
#else
#define SAVE_LOCK_PIN 18
#endif
bool PowerManagementClass::reservePLL = true;
void PowerManagementClass::sleep(uint32_t bitflg) {
if (!safeLock()) {
pmu_release_wakelock(bitflg);
}
}
void PowerManagementClass::sleep(void) {
if (!safeLock()) {
pmu_release_wakelock(BIT(PMU_OS));
}
}
void PowerManagementClass::active(uint32_t bitflg) {
pmu_acquire_wakelock(bitflg);
}
void PowerManagementClass::active(void) {
pmu_acquire_wakelock(BIT(PMU_OS));
}
void PowerManagementClass::deepsleep(uint32_t duration_ms) {
if (!safeLock()) {
deepsleep_ex(DSLEEP_WAKEUP_BY_TIMER, duration_ms);
}
}
bool PowerManagementClass::safeLock() {
pinMode(SAVE_LOCK_PIN, INPUT_PULLUP);
return (digitalRead(SAVE_LOCK_PIN) == 1) ? false : true;
}
void PowerManagementClass::softReset() {
sys_reset();
}
PowerManagementClass PowerManagement;

View File

@@ -1,76 +0,0 @@
#ifndef _POWER_MANAGEMENT_H_
#define _POWER_MANAGEMENT_H_
#include <inttypes.h>
/**
* @class PowerManagementClass PowerManagement.h
* @brief Power management in Ameba
*/
class PowerManagementClass {
public:
/**
* @brief Allow OS automatically save power while idle
*
* As OS consider it would idle for more than 2s, it will invoke system suspend.
* If wlan is associated with AP, than it will under asslociated idle state.
*/
static void sleep(void);
static void sleep(uint32_t bitflg);
/**
* @brief Disallow OS automatically save power while idle
*/
static void active(void);
static void active(uint32_t bitflg);
/**
* @brief Reserved PLL while sleep
*
* Reserve PLL would keep FIFO of peripherals (Ex. UART) but cost more power (around 5mA).
* If we don't reserve PLL, it saves more power but we might missing data because FIFO is turned of this way.
*
* @param[in] reserve true for reserved, false for non-reserved
*/
static void setPllReserved(bool reserve);
/**
* @brief Enter deepsleep immediately
*
* Invoke deepsleep would make system enter deepsleep state immediately.
* It's the state that saves most power.
* As it wakeup from deepsleep, the system would behave just like reboot.
*
* @param[in] duration_ms wakeup after specific time in unit of millisecond
*/
static void deepsleep(uint32_t duration_ms);
/**
* @brief Check if system is allowed enter any power save state
*
* The pin 18 (GPIOE_5) is designed as safe lock.
* If pin 18 is HIGH, then we prevent Ameba enter any power save state.\n\n
* Under any power save state, we are not able to flash image to Ameba.
* Thus if user misuse deepsleep and make Ameba enter deepsleep immediately after boot up,
* then he would find it's hard to flash image.
* In this case, he can pull up pin 18.
*
* @return true if system not allowed enter any power save state, and false vise versa
*/
static bool safeLock();
/**
* @brief Reboot system
*
* Reboot system in soft way. Some registers is not powered off in this case, but mostly we could regard this as reboot.
*/
static void softReset();
private:
static bool reservePLL;
};
extern PowerManagementClass PowerManagement;
#endif

View File

@@ -1,17 +0,0 @@
#if 1 // !defined(BOARD_RTL8710)
#include "Arduino.h"
#ifdef __cplusplus
extern "C" {
extern void _tone(uint32_t ulPin, unsigned int frequency, unsigned long duration);
}
#endif
// a wrapper that support default value of duration
void tone(uint32_t ulPin, unsigned int frequency, unsigned long duration)
{
_tone(ulPin, frequency, duration);
}
#endif

View File

@@ -1,84 +0,0 @@
#include "Arduino.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "gpio_api.h"
#include "gpio_irq_api.h"
#include "gpio_irq_ex_api.h"
extern void *gpio_pin_struct[PINS_COUNT];
extern void *gpio_irq_handler_list[PINS_COUNT];
void gpioIrqHandler(uint32_t id, gpio_irq_event event) {
if (gpio_irq_handler_list[id] != NULL) {
((void (*)(uint32_t, uint32_t))gpio_irq_handler_list[id])(id, (uint32_t)event);
}
}
void attachInterrupt(pin_size_t interruptNumber, voidFuncPtr callback, PinStatus mode) {
if (pinInvalid(interruptNumber))
return;
gpio_irq_handler_list[interruptNumber] = callback;
if (g_APinDescription[interruptNumber].ulPinType == PIO_GPIO_IRQ &&
g_APinDescription[interruptNumber].ulPinMode == mode)
// Nothing changes in pin mode
return;
if (g_APinDescription[interruptNumber].ulPinType != PIO_GPIO_IRQ)
// pin mode changes; deinit gpio and free memory
pinRemoveMode(interruptNumber);
gpio_irq_t *gpio;
if (g_APinDescription[interruptNumber].ulPinType == NOT_INITIAL) {
// allocate memory if pin not used before
gpio = malloc(sizeof(gpio_irq_t));
gpio_pin_struct[interruptNumber] = gpio;
gpio_irq_init(gpio, g_APinDescription[interruptNumber].pinname, gpioIrqHandler, interruptNumber);
g_APinDescription[interruptNumber].ulPinType = PIO_GPIO_IRQ;
} else {
// pin already used as irq
gpio = (gpio_irq_t *)gpio_pin_struct[interruptNumber];
}
g_APinDescription[interruptNumber].ulPinMode = mode;
gpio_irq_event event;
switch (mode) {
case LOW:
event = IRQ_LOW;
break;
case HIGH:
event = IRQ_HIGH;
break;
case FALLING:
event = IRQ_FALL;
break;
case RISING:
event = IRQ_RISE;
break;
default:
return;
}
gpio_irq_set(gpio, event, 1);
gpio_irq_enable(gpio);
}
void detachInterrupt(pin_size_t interruptNumber) {
if (pinInvalid(interruptNumber))
return;
if (g_APinDescription[interruptNumber].ulPinType == PIO_GPIO_IRQ) {
pinRemoveMode(interruptNumber);
}
gpio_irq_handler_list[interruptNumber] = NULL;
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,77 +0,0 @@
/*
Copyright (c) 2011 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 <inttypes.h>
#include "api/Common.h"
extern "C" {
extern void rtl_srandom( uint32_t seed );
extern uint32_t rtl_random( void );
}
#ifndef srand
#define srand rtl_srandom
#endif
#ifndef rand
#define rand rtl_random
#endif
extern void randomSeed( uint32_t dwSeed )
{
if ( dwSeed != 0 )
{
srand( dwSeed ) ;
}
}
extern long random( long howbig )
{
if ( howbig == 0 )
{
return 0 ;
}
return rand() % howbig;
}
extern long random( long howsmall, long howbig )
{
if (howsmall >= howbig)
{
return howsmall;
}
long diff = howbig - howsmall;
return random(diff) + howsmall;
}
extern 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;
}
extern uint16_t makeWord( uint16_t w )
{
return w ;
}
extern uint16_t makeWord( uint8_t h, uint8_t l )
{
return (h << 8) | l ;
}

View File

@@ -1,105 +0,0 @@
#pragma once
#include "wiring_os.h"
#include "wiring_watchdog.h"
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <stdint.h>
#include <stdarg.h>
#define boolean boolean_rtl
#include "rtl_lib.h"
#undef boolean
/* moved from Arduino.h */
/*
* \brief Set CPU CLK 166MHz
* clk : 0 - 166666666 Hz, 1 - 83333333 Hz, 2 - 41666666 Hz, 3 - 20833333 Hz, 4 - 10416666 Hz, 5 - 4000000 Hz
* baud: 38400,...
*/
extern void Init_CPU_CLK_UART(int clkn, int baud);
extern void sys_info(void);
/* HalGetChipId:
* 0xff - RTL8711AM, 0xfe - RTL8195AM, 0xfd - RTL8711AF,
* 0xfc - RTL8710AF, 0xfb - RTL8711AN, 0xfa - RTL8710AM */
extern unsigned char HalGetChipId(void);
extern unsigned int HalGetCpuClk(void);
extern void wait_us(int us);
#define delay_us wait_us
extern void yield(void);
#ifndef printf
#define printf rtl_printf
#endif
#ifndef sprintf
#define sprintf rtl_sprintf
#endif
#define NOT_INITIAL (1UL<<0)
#define PIO_GPIO (1UL<<1)
#define PIO_PWM (1UL<<2)
#define PIO_I2C (1UL<<3)
#define PIO_ADC (1UL<<4)
#define PIO_DAC (1UL<<5)
#define PIO_GPIO_IRQ (1UL<<6)
#define PWM_MODE_ENABLED 1
#define PWM_MODE_DISABLED 0
/* Types used for the tables below */
typedef struct _PinDescription
{
// HW PinNames
uint32_t pinname;
// Current Pin Type
uint32_t ulPinType;
// Supported Pin Function
uint32_t ulPinAttribute;
// Current Pin Mode
uint32_t ulPinMode;
} PinDescription ;
/* Pins table to be instanciated into variant.cpp */
extern PinDescription g_APinDescription[];
extern bool pinInvalid(pin_size_t pinNumber);
extern void pinRemoveMode(pin_size_t pinNumber);
/* moved from wiring_digital.h */
/**************************** Extend API by RTK ***********************************/
extern uint32_t digitalPinToPort( uint32_t pinNumber );
extern uint32_t digitalPinToBitMask( uint32_t pinNumber );
/* moved from wiring_analog.h */
/*
* \brief Set the resolution of analogRead return values. Default is 10 bits (range from 0 to 1023).
*
* \param res
*/
extern void analogReadResolution(int res);
/*
* \brief Set the resolution of analogWrite parameters. Default is 8 bits (range from 0 to 255).
*
* \param res
*/
extern void analogWriteResolution(int res);
extern void analogOutputInit( void ) ;
extern void analogWritePeriod(int us);
/* moved from wiring_constants.h */
#define DEFAULT 1
#define EXTERNAL 0
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
extern uint32_t ulPortSetInterruptMask( void );
extern void vPortClearInterruptMask( uint32_t ulNewMask );
#ifdef __cplusplus
} // extern "C"
#endif

View File

@@ -1,100 +0,0 @@
/*
* WebSocketClient + SSL/TSL
* RTL8710AF pvvx 12/12/2016
*
*/
#include "Arduino.h"
#include "WebSocketClient.h"
WebSocketClient::WebSocketClient() {
}
WebSocketClient::WebSocketClient(char *url, int port, char *path, char* origin) {
client = create_wsclient(url, port, path, origin);
}
WebSocketClient::~WebSocketClient() {
close();
}
int WebSocketClient::begin(char *url, int port, char *path, char* origin) {
client = create_wsclient(url, port, path, origin);
if(client != NULL) return 1;
else return 0;
}
int WebSocketClient::connect() {
if(client != NULL) return ws_connect_url(client);
else return -1;
}
void WebSocketClient::send(char* message, int message_len, int use_mask) {
if(client != NULL && client->readyState > CLOSED) {
ws_send(message, message_len, use_mask, client);
ws_poll(0, client);
}
}
void WebSocketClient::sendBinary(uint8_t* message, int message_len, int use_mask) {
if(client != NULL && client->readyState > CLOSED) {
ws_sendBinary(message, message_len, use_mask, client);
ws_poll(0, client);
}
}
void WebSocketClient::sendPing() {
if(client != NULL && client->readyState > CLOSED) {
ws_sendPing(client);
ws_poll(0, client);
}
}
void WebSocketClient::poll(int timeout) {
if(client != NULL) ws_poll(timeout, client);
}
readyStateValues WebSocketClient::getReadyState() {
if(client != NULL) return ws_getReadyState(client);
else return CLOSED;
}
void WebSocketClient::dispatch(void (*callback)(wsclient_context *, int))
{
if(client != NULL) ws_dispatch(callback);
}
void WebSocketClient::close() {
if(client != NULL) {
ws_close(client);
if(client->ssl) {
free(client->ssl);
client->ssl = NULL;
}
client = NULL;
}
}
extern "C" void set_ssl_func(wsclient_context *wsclient); // in example_wsclient.c
void WebSocketClient::ssl_func_on(void)
{
set_ssl_func(client);
/*
client->fun_ops.ssl_fun_ops.memory_set_own = memory_set_own;
client->fun_ops.ssl_fun_ops.net_connect = net_connect;
client->fun_ops.ssl_fun_ops.ssl_init = ssl_init;
client->fun_ops.ssl_fun_ops.ssl_set_endpoint = ssl_set_endpoint;
client->fun_ops.ssl_fun_ops.ssl_set_authmode = ssl_set_authmode;
client->fun_ops.ssl_fun_ops.ssl_set_rng = ssl_set_rng;
client->fun_ops.ssl_fun_ops.ssl_set_bio = ssl_set_bio;
client->fun_ops.ssl_fun_ops.ssl_handshake = ssl_handshake;
client->fun_ops.ssl_fun_ops.net_close = net_close;
client->fun_ops.ssl_fun_ops.ssl_free = ssl_free;
client->fun_ops.ssl_fun_ops.ssl_read = ssl_read;
client->fun_ops.ssl_fun_ops.ssl_write = ssl_write;
client->fun_ops.ssl_fun_ops.net_recv = net_recv;
client->fun_ops.ssl_fun_ops.net_send = net_send;
client->ssl = (void *)zalloc(sizeof(struct _ssl_context)); // 380 bytes
*/
}

View File

@@ -1,116 +0,0 @@
/*
* WebSocketClient + SSL/TSL
* RTL8710AF pvvx 12/12/2016
*
*/
#ifndef WEBSOCKETCLIENT_H_
#define WEBSOCKETCLIENT_H_
#include <Arduino.h>
extern "C" {
#include "libwsclient.h"
#include "wsclient_api.h"
}
class WebSocketClient {
public:
WebSocketClient();
~WebSocketClient();
/*************************************************************************************************
** Function Name : begin
** Description : Creating the websocket client context structure
** Input : url:websocket server's url
** port:websocket server's port, if not given, default 80 for "ws", 443 for "wss"
** origin: the address or url of your self
** Return : Ok: 1
** Failed: 0
**************************************************************************************************/
WebSocketClient(char *url, int port, char *path = NULL, char* origin = NULL);
int begin(char *url, int port, char *path = NULL, char* origin = NULL);
/*************************************************************************************************
** Function Name : connect
** Description : Connecting to the websocket server
** Input : wsclient: the websocket client context created by create_wsclientfunction
** Return : Connected: the socket value
** Failed: -1
**************************************************************************************************/
int connect();
/*************************************************************************************************
** Function Name : ws_send
** Description : Create the sending string data and copy to tx_buf
** Input : message: the string that send to server(cannot exceeding the MAX_DATA_LEN
** message_len: the length of the string
** use_mask: 0/1; 1 means using mask for bynary
** wsclient: the websocket client context
** Return : None
**************************************************************************************************/
void send(char* message, int message_len, int use_mask);
/*************************************************************************************************
** Function Name : sendBinary
** Description : Create the sending binary data and copy to tx_buf
** Input : message: the binary that send to server(cannot exceeding the MAX_DATA_LEN
** message_len: the length of the binary
** use_mask: 0/1; 1 means using mask for bynary
** wsclient: the websocket client context
** Return : None
**************************************************************************************************/
void sendBinary(uint8_t* message, int message_len, int use_mask);
/*************************************************************************************************
** Function Name : sendPing
** Description : Sending Ping to websocket server
** Input : wsclient: the websocket client context
** Return : None
**************************************************************************************************/
void sendPing();
/*************************************************************************************************
** Function Name : poll
** Description : Receicing data from server and send the data in tx_buf
** Input : timeout(in milliseconds)
wsclient: the websocket client context
** Return : None
**************************************************************************************************/
void poll(int timeout);
/*************************************************************************************************
** Function Name : dispatch
** Description : callback function when getting message from server
** Input : function that resolve the message received and the message length
** Return : None
**************************************************************************************************/
void dispatch(void (*callback)(wsclient_context *, int));
/*************************************************************************************************
** Function Name : getReadyState
** Description : Getting the connection status
** Input : wsclient: the websocket client context
** Return : readyStateValues(4 types: CLOSING, CLOSED, CONNECTING, OPEN )
**************************************************************************************************/
readyStateValues getReadyState();
/*************************************************************************************************
** Function Name : close
** Description : Closing the connection with websocket server
** Input : wsclient: the websocket client context
** Return : None
**************************************************************************************************/
void close();
/*************************************************************************************************
** Function Name : ssl_func_on
** Description : Set SSL/TSL function
** Input : None
** Return : None
**************************************************************************************************/
void ssl_func_on(void);
private:
wsclient_context *client;
};
#endif // WEBSOCKETCLIENT_H_

View File

@@ -1,214 +0,0 @@
#include <platform_opts.h>
#include <lwip/sockets.h>
#include <lwip/netif.h>
#include <platform/platform_stdlib.h>
#include "ard_socket.h"
int start_server(uint16_t port, uint8_t protMode)
{
int _sock;
int timeout;
if(protMode == 0) {
timeout = 3000;
_sock = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
lwip_setsockopt(_sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
} else {
timeout = 1000;
_sock = lwip_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
lwip_setsockopt(_sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
}
if (_sock < 0) {
printf("\r\nERROR opening socket\r\n");
return -1;
}
struct sockaddr_in localHost;
memset(&localHost, 0, sizeof(localHost));
localHost.sin_family = AF_INET;
localHost.sin_port = htons(port);
localHost.sin_addr.s_addr = INADDR_ANY;
if (lwip_bind(_sock, (struct sockaddr *)&localHost, sizeof(localHost)) < 0) {
printf("\r\nERROR on binding\r\n");
return -1;
}
return _sock;
}
int sock_listen(int sock, int max)
{
if(lwip_listen(sock , max) < 0){
printf("\r\nERROR on listening\r\n");
return -1;
}
return 0;
}
int get_available(int sock)
{
int enable = 1;
int timeout;
int client_fd;
int err;
struct sockaddr_in cli_addr;
socklen_t client = sizeof(cli_addr);
do {
client_fd = lwip_accept(sock, (struct sockaddr *) &cli_addr, &client);
if (client_fd < 0) {
err = get_sock_errno(sock);
if (err != EAGAIN) {
break;
}
}
} while (client_fd < 0);
if(client_fd < 0){
printf("\r\nERROR on accept\r\n");
return -1;
}
else {
timeout = 3000;
lwip_setsockopt(client_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
timeout = 30000;
lwip_setsockopt(client_fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
lwip_setsockopt(client_fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
lwip_setsockopt(client_fd, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable));
printf("\r\nA client connected to this server :\r\n[PORT]: %d\r\n[IP]:%s\r\n\r\n", ntohs(cli_addr.sin_port), inet_ntoa(cli_addr.sin_addr.s_addr));
return client_fd;
}
}
int get_receive(int sock, uint8_t* data, int length, int flag, uint32_t *peer_addr, uint16_t *peer_port)
{
int ret = 0;
struct sockaddr from;
socklen_t fromlen;
uint8_t backup_recvtimeout = 0;
int backup_recv_timeout, recv_timeout, len;
if (flag & 0x01) {
// for MSG_PEEK, we try to peek packets by changing receiving timeout to 10ms
ret = lwip_getsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &backup_recv_timeout, &len);
if (ret >= 0) {
recv_timeout = 10;
ret = lwip_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &recv_timeout, sizeof(recv_timeout));
if (ret >= 0) {
backup_recvtimeout = 1;
}
}
}
ret = lwip_recvfrom(sock, data, length, flag, &from, &fromlen);
if ( ret >= 0 ) {
if (peer_addr != NULL) {
*peer_addr = ((struct sockaddr_in *)&from)->sin_addr.s_addr;
}
if (peer_port != NULL) {
*peer_port = ntohs(((struct sockaddr_in *)&from)->sin_port);
}
}
if ((flag & 0x01) && (backup_recvtimeout == 1)) {
// restore receiving timeout
lwip_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &backup_recv_timeout, sizeof(recv_timeout));
}
return ret;
}
int get_sock_errno(int sock)
{
int so_error;
socklen_t len = sizeof(so_error);
getsockopt(sock, SOL_SOCKET, SO_ERROR, &so_error, &len);
return so_error;
}
int set_sock_recv_timeout(int sock, int timeout)
{
return lwip_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
}
void stop_socket(int sock)
{
lwip_close(sock);
}
int send_data(int sock, const uint8_t *data, uint16_t len)
{
int ret;
ret = lwip_write(sock, data, len);
return ret;
}
int sendto_data(int sock, const uint8_t *data, uint16_t len, uint32_t peer_ip, uint16_t peer_port)
{
int ret;
struct sockaddr_in peer_addr;
memset(&peer_addr, 0, sizeof(peer_addr));
peer_addr.sin_family = AF_INET;
peer_addr.sin_addr.s_addr = peer_ip;
peer_addr.sin_port = htons(peer_port);
ret = lwip_sendto(sock, data, len, 0, (struct sockaddr*)&peer_addr, sizeof(struct sockaddr_in));
return ret;
}
int start_client(uint32_t ipAddress, uint16_t port, uint8_t protMode)
{
int enable = 1;
int timeout;
int _sock;
if(protMode == 0)//tcp
_sock = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
else
_sock = lwip_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (_sock < 0) {
printf("\r\nERROR opening socket\r\n");
return -1;
}
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = ipAddress;
serv_addr.sin_port = htons(port);
if (protMode == 0){//TCP MODE
if(connect(_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == 0){
printf("\r\nConnect to Server successful!\r\n");
timeout = 3000;
lwip_setsockopt(_sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
timeout = 30000;
lwip_setsockopt(_sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
lwip_setsockopt(_sock, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable));
lwip_setsockopt(_sock, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable));
return _sock;
}
else{
printf("\r\nConnect to Server failed!\r\n");
stop_socket(_sock);
return -1;
}
}
else {
//printf("\r\nUdp client setup Server's information successful!\r\n");
}
return _sock;
}

View File

@@ -1,25 +0,0 @@
#ifndef ARD_SOCKET_H
#define ARD_SOCKET_H
#include "main.h"
int start_server(uint16_t port, uint8_t protMode);
int sock_listen(int sock, int max);
int get_available(int sock);
int get_receive(int sock, uint8_t* data, int length, int flag, uint32_t *peer_addr, uint16_t *peer_port);
int get_sock_errno(int sock);
int set_sock_recv_timeout(int sock, int timeout);
void stop_socket(int sock);
int send_data(int sock, const uint8_t *data, uint16_t len);
int sendto_data(int sock, const uint8_t *data, uint16_t len, uint32_t peer_ip, uint16_t peer_port);
int start_client(uint32_t ipAddress, uint16_t port, uint8_t protMode);
#endif

View File

@@ -1,402 +0,0 @@
#include "Arduino.h"
#include <sockets.h>
#include <lwip/netif.h>
#include <mbedtls/ssl.h>
#include <mbedtls/net_sockets.h>
#include <mbedtls/error.h>
#include <mbedtls/debug.h>
#include "ard_ssl.h"
#define ARDUINO_MBEDTLS_DEBUG_LEVEL 0 // Set to 0 to disable debug messsages, 5 to enable all debug messages
static unsigned int ard_ssl_arc4random(void)
{
unsigned int res = xTaskGetTickCount();
static unsigned int seed = 0xDEADB00B;
seed = ((seed & 0x007F00FF) << 7) ^
((seed & 0x0F80FF00) >> 8) ^ // be sure to stir those low bits
(res << 13) ^ (res >> 9); // using the clock too!
return seed;
}
static void get_random_bytes(void *buf, size_t len)
{
unsigned int ranbuf;
unsigned int *lp;
int i, count;
count = len / sizeof(unsigned int);
lp = (unsigned int *) buf;
for (i = 0; i < count; i ++) {
lp[i] = ard_ssl_arc4random();
len -= sizeof(unsigned int);
}
if (len > 0) {
ranbuf = ard_ssl_arc4random();
memcpy(&lp[i], &ranbuf, len);
}
}
static int my_random(void *p_rng, unsigned char *output, size_t output_len)
{
p_rng = p_rng;
get_random_bytes(output, output_len);
return 0;
}
static int my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags)
{
char buf[1024];
((void)data);
mbedtls_x509_crt_info(buf, (sizeof(buf) - 1), "", crt);
if(ARDUINO_MBEDTLS_DEBUG_LEVEL < 3)
return(0);
printf( "\nVerify requested for (Depth %d):\n", depth );
printf( "%s", buf );
if ((*flags) == 0)
printf(" This certificate has no flags\n");
else
{
mbedtls_x509_crt_verify_info(buf, sizeof( buf ), " ! ", *flags);
printf("%s\n", buf);
}
return(0);
}
static void* my_calloc(size_t nelements, size_t elementSize)
{
size_t size;
void *ptr = NULL;
size = nelements * elementSize;
ptr = pvPortMalloc(size);
if(ptr)
memset(ptr, 0, size);
return ptr;
}
static void my_debug(void *ctx, int level, const char *file, int line, const char *str )
{
const char *p, *basename;
ctx = ctx; // Remove unused parameter warning
// Extract basename from file
for( p = basename = file; *p != '\0'; p++ )
if( *p == '/' || *p == '\\' )
basename = p + 1;
printf("%s:%04d: |%d| %s", basename, line, level, str );
}
int start_ssl_client(sslclient_context *ssl_client, uint32_t ipAddress, uint32_t port, unsigned char* rootCABuff, unsigned char* cli_cert, unsigned char* cli_key, unsigned char* pskIdent, unsigned char* psKey, char* SNI_hostname)
{
int ret = 0;
//int timeout;
int enable = 1;
int keep_idle = 30;
mbedtls_x509_crt* cacert = NULL;
mbedtls_x509_crt* _cli_crt = NULL;
mbedtls_pk_context* _clikey_rsa = NULL;
do {
ssl_client->socket = -1;
ssl_client->socket = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ssl_client->socket < 0) {
printf("ERROR: opening socket failed! \r\n");
ret = -1;
break;
}
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = ipAddress;
serv_addr.sin_port = htons(port);
lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable));
lwip_setsockopt(ssl_client->socket, IPPROTO_TCP, TCP_KEEPIDLE, &keep_idle, sizeof(keep_idle));
if (lwip_connect(ssl_client->socket, ((struct sockaddr *)&serv_addr), sizeof(serv_addr)) < 0) {
lwip_close(ssl_client->socket);
printf("ERROR: Connect to Server failed! \r\n");
ret = -1;
break;
} else {
/*/
if (lwip_connect(ssl_client->socket, ((struct sockaddr *)&serv_addr), sizeof(serv_addr)) == 0) {
timeout = ssl_client->recvTimeout;
lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
timeout = 30000;
lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
lwip_setsockopt(ssl_client->socket, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable));
lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable));
} else {
printf("ERROR: Connect to Server failed!\r\n");
ret = -1;
break;
}//*/
mbedtls_platform_set_calloc_free(my_calloc,vPortFree);
ssl_client->ssl = (mbedtls_ssl_context *)malloc(sizeof(mbedtls_ssl_context));
ssl_client->conf = (mbedtls_ssl_config *)malloc(sizeof(mbedtls_ssl_config));
if (( ssl_client->ssl == NULL )||( ssl_client->conf == NULL )) {
printf("ERROR: malloc ssl failed! \r\n");
ret = -1;
break;
}
mbedtls_ssl_init(ssl_client->ssl);
mbedtls_ssl_config_init(ssl_client->conf);
if (ARDUINO_MBEDTLS_DEBUG_LEVEL > 0) {
mbedtls_ssl_conf_verify(ssl_client->conf, my_verify, NULL);
mbedtls_ssl_conf_dbg(ssl_client->conf, my_debug, NULL);
mbedtls_debug_set_threshold(ARDUINO_MBEDTLS_DEBUG_LEVEL);
}
if((mbedtls_ssl_config_defaults(ssl_client->conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
printf("ERROR: mbedtls ssl config defaults failed! \r\n");
ret = -1;
break;
}
mbedtls_ssl_conf_rng(ssl_client->conf, my_random, NULL);
if (rootCABuff != NULL) {
// Configure mbedTLS to use certificate authentication method
cacert = (mbedtls_x509_crt *) mbedtls_calloc( sizeof(mbedtls_x509_crt), 1);
mbedtls_x509_crt_init(cacert);
if (mbedtls_x509_crt_parse(cacert, rootCABuff, (strlen((char*)rootCABuff)) + 1) != 0) {
printf("ERROR: mbedtls x509 crt parse failed! \r\n");
ret = -1;
break;
}
mbedtls_ssl_conf_ca_chain(ssl_client->conf, cacert, NULL);
mbedtls_ssl_conf_authmode(ssl_client->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
} else if (pskIdent != NULL && psKey != NULL) {
// Configure mbedTLS to use PSK authentication method
// Check for max length and even number of chars
uint16_t pskey_char_len = strlen((char*)psKey);
if ( ((pskey_char_len % 2) != 0) || (pskey_char_len > 2*MBEDTLS_PSK_MAX_LEN) ) {
printf("ERROR: TLS PSK not in valid hex format or too long \n");
return -1;
}
uint16_t psk_len = pskey_char_len/2;
unsigned char psk[MBEDTLS_PSK_MAX_LEN];
// Convert PSK from hexadecimal chars to binary
int i;
for (i = 0; i < pskey_char_len; i = i + 2) {
char c = psKey[i];
// Convert first 4 bits
if (c >= '0' && c <= '9') {
c = c - '0';
} else if (c >= 'A' && c <= 'F') {
c = c - 'A' + 10;
} else if (c >= 'a' && c <= 'f') {
c = c - 'a' + 10;
} else {
printf("ERROR: TLS PSK not in valid hex format \n");
return -1;
}
psk[i/2] = c << 4;
c = psKey[i+1];
// Convert next 4 bits
if (c >= '0' && c <= '9') {
c = c - '0';
} else if (c >= 'A' && c <= 'F') {
c = c - 'A' + 10;
} else if (c >= 'a' && c <= 'f') {
c = c - 'a' + 10;
} else {
printf("ERROR: TLS PSK not in valid hex format \r\n");
return -1;
}
psk[i/2] |= c;
}
if (mbedtls_ssl_conf_psk(ssl_client->conf, psk, psk_len, pskIdent, strlen((char*)pskIdent)) != 0) {
printf("ERROR: mbedtls conf psk failed! \r\n");
}
} else {
mbedtls_ssl_conf_authmode(ssl_client->conf, MBEDTLS_SSL_VERIFY_NONE);
}
if ((cli_cert != NULL) && (cli_key != NULL)) {
_cli_crt = (mbedtls_x509_crt *) mbedtls_calloc( sizeof(mbedtls_x509_crt), 1);
if (_cli_crt == NULL) {
printf("ERROR: malloc client_crt failed! \r\n");
ret = -1;
break;
}
mbedtls_x509_crt_init(_cli_crt);
_clikey_rsa = (mbedtls_pk_context *) mbedtls_calloc( sizeof(mbedtls_pk_context), 1);
if (_clikey_rsa == NULL) {
printf("ERROR: malloc client_rsa failed! \r\n");
ret = -1;
break;
}
mbedtls_pk_init(_clikey_rsa);
if (mbedtls_x509_crt_parse(_cli_crt, cli_cert, strlen((char*)cli_cert)+1) != 0) {
printf("ERROR: mbedtls x509 parse client_crt failed! \r\n");
ret = -1;
break;
}
if (mbedtls_pk_parse_key(_clikey_rsa, cli_key, strlen((char*)cli_key)+1, NULL, 0) != 0) {
printf("ERROR: mbedtls x509 parse client_rsa failed! \r\n");
ret = -1;
break;
}
mbedtls_ssl_conf_own_cert(ssl_client->conf, _cli_crt, _clikey_rsa);
}
if((mbedtls_ssl_setup(ssl_client->ssl, ssl_client->conf)) != 0) {
printf("ERROR: mbedtls ssl setup failed!\r\n");
ret = -1;
break;
}
mbedtls_ssl_set_bio(ssl_client->ssl, &ssl_client->socket, mbedtls_net_send, mbedtls_net_recv, NULL);
mbedtls_ssl_set_hostname(ssl_client->ssl, SNI_hostname);
ret = mbedtls_ssl_handshake(ssl_client->ssl);
if (ret < 0) {
printf("ERROR: mbedtls ssl handshake failed: -0x%04X \r\n", -ret);
ret = -1;
} else {
if (ARDUINO_MBEDTLS_DEBUG_LEVEL > 0) {
printf("mbedTLS SSL handshake success \r\n");
}
}
//mbedtls_debug_set_threshold(ARDUINO_MBEDTLS_DEBUG_LEVEL);
}
} while (0);
if (_clikey_rsa) {
mbedtls_pk_free(_clikey_rsa);
mbedtls_free(_clikey_rsa);
_clikey_rsa = NULL;
}
if (_cli_crt) {
mbedtls_x509_crt_free(_cli_crt);
mbedtls_free(_cli_crt);
_cli_crt = NULL;
}
if (cacert) {
mbedtls_x509_crt_free(cacert);
mbedtls_free(cacert);
cacert = NULL;
}
if (ret < 0) {
if (ssl_client->socket >= 0) {
mbedtls_net_free((mbedtls_net_context *)&ssl_client->socket);
ssl_client->socket = -1;
}
if (ssl_client->ssl != NULL) {
mbedtls_ssl_free(ssl_client->ssl);
free(ssl_client->ssl);
ssl_client->ssl = NULL;
}
if (ssl_client->conf != NULL) {
mbedtls_ssl_config_free(ssl_client->conf);
free(ssl_client->conf);
ssl_client->conf = NULL;
}
}
return ssl_client->socket;
}
void stop_ssl_socket(sslclient_context *ssl_client)
{
lwip_shutdown(ssl_client->socket, SHUT_RDWR);
lwip_close(ssl_client->socket);
//mbedtls_net_free((mbedtls_net_context *)&ssl_client->socket);
ssl_client->socket = -1;
if (ssl_client->ssl != NULL) {
mbedtls_ssl_free(ssl_client->ssl);
free(ssl_client->ssl);
ssl_client->ssl = NULL;
}
if (ssl_client->conf != NULL) {
mbedtls_ssl_config_free(ssl_client->conf);
free(ssl_client->conf);
ssl_client->conf = NULL;
}
}
int send_ssl_data(sslclient_context *ssl_client, const uint8_t *data, uint16_t len)
{
int ret = -1;
if (ssl_client->ssl != NULL) {
ret = mbedtls_ssl_write(ssl_client->ssl, data, len);
}
return ret;
}
int get_ssl_receive(sslclient_context *ssl_client, uint8_t* data, int length, int flag)
{
int ret = 0;
uint8_t has_backup_recvtimeout = 0;
int backup_recv_timeout, recv_timeout;
socklen_t len;
if (ssl_client->ssl == NULL) {
return 0;
}
if (flag & 0x01) {
// peek for 10ms
ret = lwip_getsockopt(ssl_client->socket, SOL_SOCKET, SO_RCVTIMEO, &backup_recv_timeout, &len);
if (ret >= 0) {
recv_timeout = 100;
ret = lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_RCVTIMEO, &recv_timeout, sizeof(recv_timeout));
if (ret >= 0) {
has_backup_recvtimeout = 1;
}
}
}
memset(data, 0, length);
ret = mbedtls_ssl_read(ssl_client->ssl, data, length);
if ((flag & 0x01) && (has_backup_recvtimeout == 1)) {
// restore receiving timeout
lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_RCVTIMEO, &backup_recv_timeout, sizeof(recv_timeout));
}
return ret;
}
int get_ssl_sock_errno(sslclient_context *ssl_client) {
int so_error;
socklen_t len = sizeof(so_error);
lwip_getsockopt(ssl_client->socket, SOL_SOCKET, SO_ERROR, &so_error, &len);
return so_error;
}
int get_ssl_bytes_avail(sslclient_context *ssl_client) {
if (ssl_client->ssl != NULL) {
return mbedtls_ssl_get_bytes_avail(ssl_client->ssl);
} else {
return 0;
}
}

View File

@@ -1,26 +0,0 @@
#ifndef ARD_SSL_H
#define ARD_SSL_H
struct mbedtls_ssl_context;
struct mbedtls_ssl_config;
typedef struct {
int socket;
int recvTimeout;
mbedtls_ssl_context *ssl;
mbedtls_ssl_config *conf;
} sslclient_context;
int start_ssl_client(sslclient_context *ssl_client, uint32_t ipAddress, uint32_t port, unsigned char* rootCABuff, unsigned char* cli_cert, unsigned char* cli_key, unsigned char* pskIdent, unsigned char* psKey, char* SNI_hostname);
void stop_ssl_socket(sslclient_context *ssl_client);
int send_ssl_data(sslclient_context *ssl_client, const uint8_t *data, uint16_t len);
int get_ssl_receive(sslclient_context *ssl_client, uint8_t* data, int length, int flag);
int get_ssl_sock_errno(sslclient_context *ssl_client);
int get_ssl_bytes_avail(sslclient_context *ssl_client);
#endif

View File

@@ -1,71 +0,0 @@
// Simple Base64 code
// (c) Copyright 2010 MCQN Ltd.
// Released under Apache License, version 2.0
#include "b64.h"
/* Simple test program
#include <stdio.h>
void main()
{
char* in = "amcewen";
char out[22];
b64_encode(in, 15, out, 22);
out[21] = '\0';
printf(out);
}
*/
int b64_encode(const unsigned char* aInput, int aInputLen, unsigned char* aOutput, int aOutputLen)
{
// Work out if we've got enough space to encode the input
// Every 6 bits of input becomes a byte of output
if (aOutputLen < (aInputLen*8)/6)
{
// FIXME Should we return an error here, or just the length
return (aInputLen*8)/6;
}
// If we get here we've got enough space to do the encoding
const char* b64_dictionary = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
if (aInputLen == 3)
{
aOutput[0] = b64_dictionary[aInput[0] >> 2];
aOutput[1] = b64_dictionary[(aInput[0] & 0x3)<<4|(aInput[1]>>4)];
aOutput[2] = b64_dictionary[(aInput[1]&0x0F)<<2|(aInput[2]>>6)];
aOutput[3] = b64_dictionary[aInput[2]&0x3F];
}
else if (aInputLen == 2)
{
aOutput[0] = b64_dictionary[aInput[0] >> 2];
aOutput[1] = b64_dictionary[(aInput[0] & 0x3)<<4|(aInput[1]>>4)];
aOutput[2] = b64_dictionary[(aInput[1]&0x0F)<<2];
aOutput[3] = '=';
}
else if (aInputLen == 1)
{
aOutput[0] = b64_dictionary[aInput[0] >> 2];
aOutput[1] = b64_dictionary[(aInput[0] & 0x3)<<4];
aOutput[2] = '=';
aOutput[3] = '=';
}
else
{
// Break the input into 3-byte chunks and process each of them
int i;
for (i = 0; i < aInputLen/3; i++)
{
b64_encode(&aInput[i*3], 3, &aOutput[i*4], 4);
}
if (aInputLen % 3 > 0)
{
// It doesn't fit neatly into a 3-byte chunk, so process what's left
b64_encode(&aInput[i*3], aInputLen % 3, &aOutput[i*4], aOutputLen - (i*4));
}
}
}

View File

@@ -1,7 +0,0 @@
#ifndef b64_h
#define b64_h
int b64_encode(const unsigned char* aInput, int aInputLen, unsigned char* aOutput, int aOutputLen);
#endif

View File

@@ -1,26 +0,0 @@
/*
Copyright (c) 2011 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
*/
extern "C" void __cxa_pure_virtual(void) ;
/* We compile with nodefaultlibs, so we need to provide an error
* handler for an empty pure virtual function */
extern "C" void __cxa_pure_virtual(void) {
while(1)
;
}

View File

@@ -1,36 +0,0 @@
#ifndef ARD_DEBUG_H
#define ARD_DEBUG_H
#include <stddef.h>
#include <stdint.h>
#ifdef DEBUG_RTL_CORE
#define DEBUGV(...) rtl_printf(__VA_ARGS__)
#endif
#ifndef DEBUGV
#define DEBUGV(...)
#endif
#ifdef __cplusplus
void hexdump(void * addr, int len = 16);
#else
void hexdump(void * addr, int len);
#endif
#ifdef __cplusplus
extern "C" {
#endif
void print_udp_pcb(void);
void print_tcp_pcb(void);
void DumpForOneBytes(void *addr, int cnt); // cnt max 0x70 !
void __panic_func(const char* file, int line, const char* func) __attribute__((noreturn));
#define panic() __panic_func(__FILE__, __LINE__, __func__)
#ifdef __cplusplus
}
#endif
#endif//ARD_DEBUG_H

View File

@@ -1,64 +0,0 @@
/*
Copyright (c) 2012 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
*/
/**
* Empty yield() hook.
*
* This function is intended to be used by library writers to build
* libraries or sketches that supports cooperative threads.
*
* Its defined as a weak symbol and it can be redefined to implement a
* real cooperative scheduler.
*/
static void __empty() {
// Empty
}
#include "cmsis_os.h"
void yield(void) {
vTaskDelay(1);
taskYIELD();
}
/**
* SysTick hook
*
* This function is called from SysTick handler, before the default
* handler provided by Arduino.
*/
static int __false() {
// Return false
return 0;
}
int sysTickHook(void) __attribute__ ((weak, alias("__false")));
/**
* SVC hook
* PendSV hook
*
* These functions are called from SVC handler, and PensSV handler.
* Default action is halting.
*/
static void __halt() {
// Halts
while (1)
;
}
void svcHook(void) __attribute__ ((weak, alias("__halt")));
void pendSVHook(void) __attribute__ ((weak, alias("__halt")));

View File

@@ -1,116 +0,0 @@
/*
Copyright (c) 2011 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 "api/itoa.h"
#include <string.h>
#ifdef __cplusplus
extern "C"{
#endif // __cplusplus
extern char* ltoa(long value, char *string, int radix)
{
char tmp[33];
char *tp = tmp;
long i;
unsigned long v;
int sign;
char *sp;
if ( string == NULL )
{
return 0 ;
}
if (radix > 36 || radix <= 1)
{
return 0 ;
}
sign = (radix == 10 && value < 0);
if (sign)
{
v = -value;
}
else
{
v = (unsigned long)value;
}
while (v || tp == tmp)
{
i = v % radix;
v = v / radix;
if (i < 10)
*tp++ = i+'0';
else
*tp++ = i + 'a' - 10;
}
sp = string;
if (sign)
*sp++ = '-';
while (tp > tmp)
*sp++ = *--tp;
*sp = 0;
return string;
}
extern char* ultoa(unsigned long value, char *string, int radix)
{
char tmp[33];
char *tp = tmp;
long i;
unsigned long v = value;
char *sp;
if ( string == NULL )
{
return 0;
}
if (radix > 36 || radix <= 1)
{
return 0;
}
while (v || tp == tmp)
{
i = v % radix;
v = v / radix;
if (i < 10)
*tp++ = i+'0';
else
*tp++ = i + 'a' - 10;
}
sp = string;
while (tp > tmp)
*sp++ = *--tp;
*sp = 0;
return string;
}
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

View File

@@ -1,120 +0,0 @@
#ifndef EASYWSCLIENT_H
#define EASYWSCLIENT_H
#include <platform/platform_stdlib.h>
/****************Define the debug message level*********************/
#define DEBUG_WSCLIENT 1
#define WSCLIENT_LOG(level, fmt, ...) printf("\n\r[WSCLIENT %s] %s: " fmt "\n", level, __FUNCTION__, ##__VA_ARGS__)
#if DEBUG_WSCLIENT == 2
#define WSCLIENT_DEBUG(fmt, ...) WSCLIENT_LOG("DEBUG", fmt, ##__VA_ARGS__)
#else
#define WSCLIENT_DEBUG(fmt, ...)
#endif
#if DEBUG_WSCLIENT
#define WSCLIENT_ERROR(fmt, ...) WSCLIENT_LOG("ERROR", fmt, ##__VA_ARGS__)
#else
#define WSCLIENT_ERROR(fmt, ...)
#endif
/*******************************************************************/
/****************Define the structures used*************************/
typedef enum{
CLOSING,
CLOSED,
CONNECTING,
OPEN
} readyStateValues;
struct wsheader_type{
unsigned header_size;
int fin;
int mask;
enum opcode_type {
CONTINUATION = 0x0,
TEXT_FRAME = 0x1,
BINARY_FRAME = 0x2,
CLOSE = 8,
PING = 9,
PONG = 0xa,
} opcode;
int N0;
uint64_t N;
uint8_t masking_key[4];
};
struct _wsclient_context;
struct _ssl_context;
struct ssl_fun_ops{
int (*memory_set_own)( void * (*malloc_func)( size_t ),void (*free_func)( void * ) );
int (*net_connect)( int *fd, const char *host, int port );
int (*ssl_init)( struct _ssl_context *ssl );
void (*ssl_set_endpoint)( struct _ssl_context *ssl, int endpoint );
void (*ssl_set_authmode)( struct _ssl_context *ssl, int authmode );
void (*ssl_set_rng)( struct _ssl_context *ssl,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
void (*ssl_set_bio)( struct _ssl_context *ssl,
int (*f_recv)(void *, unsigned char *, size_t), void *p_recv,
int (*f_send)(void *, const unsigned char *, size_t), void *p_send );
int (*ssl_handshake)( struct _ssl_context *ssl );
void (*net_close)( int fd );
void (*ssl_free)( struct _ssl_context *ssl );
int (*ssl_read)( struct _ssl_context *ssl, unsigned char *buf, size_t len );
int (*ssl_write)( struct _ssl_context *ssl, const unsigned char *buf, size_t len );
const char *(*ssl_get_ciphersuite)( const struct _ssl_context *ssl );
int (*net_recv)( void *ctx, unsigned char *buf, size_t len );
int (*net_send)( void *ctx, const unsigned char *buf, size_t len );
};
struct ws_fun_ops{
int (*hostname_connect)(struct _wsclient_context *wsclient);
void (*client_close)(struct _wsclient_context *wsclient);
int (*client_send)(struct _wsclient_context *wsclient, unsigned char *data, size_t data_len);
int (*client_read)(struct _wsclient_context *wsclient, unsigned char *data, size_t data_len);
struct ssl_fun_ops ssl_fun_ops;
};
typedef struct _wsclient_context{
char host[128];
char path[128];
char origin[200];
int port;
uint8_t use_ssl;
int sockfd;
readyStateValues readyState;
int tx_len;
void *ssl;
uint8_t *txbuf;
uint8_t *rxbuf;
uint8_t *receivedData;
struct ws_fun_ops fun_ops;
}wsclient_context;
/*******************************************************************/
/****************General functions used by wsclient*****************/
void ws_get_random_bytes(void *buf, size_t len);
void* ws_malloc(unsigned int size);
void ws_free(void *buf);
int ws_client_handshake(wsclient_context *wsclient);
int ws_check_handshake(wsclient_context *wsclient);
void ws_sendData(uint8_t type, size_t message_size, uint8_t* message, int useMask, wsclient_context *wsclient);
/*******************************************************************/
/*************Functions used by wsclient without SSL****************/
int ws_hostname_connect(wsclient_context *wsclient);
int ws_client_read(wsclient_context *wsclient, unsigned char *data, size_t data_len);
int ws_client_send(wsclient_context *wsclient, unsigned char *data, size_t data_len);
void ws_client_close(wsclient_context *wsclient);
/*******************************************************************/
/***************Functions used by wsclient with SSL*****************/
int wss_hostname_connect(wsclient_context *wsclient);
int wss_client_read(wsclient_context *wsclient, unsigned char *data, size_t data_len);
int wss_client_send(wsclient_context *wsclient, unsigned char *data, size_t data_len);
void wss_client_close(wsclient_context *wsclient);
/*******************************************************************/
#endif

View File

@@ -1,122 +0,0 @@
#include "Arduino.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "lwip_netconf.h"
#include "lwip/udp.h"
#include "lwip/tcpip.h"
#include "lwip/err.h"
//#include "lwip/mem.h"
#include "lwip/tcp.h"
#include "lwip/tcp_impl.h"
#include "lwip/udp.h"
/* Get one byte from the 4-byte address */
#define ip4_addr1(ipaddr) (((u8_t*)(ipaddr))[0])
#define ip4_addr2(ipaddr) (((u8_t*)(ipaddr))[1])
#define ip4_addr3(ipaddr) (((u8_t*)(ipaddr))[2])
#define ip4_addr4(ipaddr) (((u8_t*)(ipaddr))[3])
/* These are cast to u16_t, with the intent that they are often arguments
* to printf using the U16_F format from cc.h. */
#define ip4_addr1_16(ipaddr) ((u16_t)ip4_addr1(ipaddr))
#define ip4_addr2_16(ipaddr) ((u16_t)ip4_addr2(ipaddr))
#define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr))
#define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr))
#define IP2STR(ipaddr) ip4_addr1_16(ipaddr), \
ip4_addr2_16(ipaddr), \
ip4_addr3_16(ipaddr), \
ip4_addr4_16(ipaddr)
#define IPSTR "%d.%d.%d.%d"
extern const char * const tcp_state_str[];
/*
static const char * const tcp_state_str[] = {
"CLOSED",
"LISTEN",
"SYN_SENT",
"SYN_RCVD",
"ESTABLISHED",
"FIN_WAIT_1",
"FIN_WAIT_2",
"CLOSE_WAIT",
"CLOSING",
"LAST_ACK",
"TIME_WAIT"
};
*/
/******************************************************************************
* FunctionName : debug
* Parameters :
* Returns :
*******************************************************************************/
void print_udp_pcb(void)
{
struct udp_pcb *pcb;
bool prt_none = true;
rtl_printf("UDP pcbs:\n");
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
rtl_printf("flg:%02x\t" IPSTR ":%d\t" IPSTR ":%d\trecv:%p\n", pcb->flags, IP2STR(&pcb->local_ip), pcb->local_port, IP2STR(&pcb->remote_ip), pcb->remote_port, pcb->recv );
prt_none = false;
}
if(prt_none) rtl_printf("none\n");
}
/******************************************************************************
* FunctionName : debug
* Parameters :
* Returns :
*******************************************************************************/
void print_tcp_pcb(void)
{
struct tcp_pcb *pcb;
rtl_printf("Active PCB states:\n");
bool prt_none = true;
for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
rtl_printf("Port %d|%d\tflg:%02x\ttmr:%p\t%s\n", pcb->local_port, pcb->remote_port, pcb->flags, pcb->tmr, tcp_state_str[pcb->state]);
prt_none = false;
}
if(prt_none) rtl_printf("none\n");
rtl_printf("Listen PCB states:\n");
prt_none = true;
for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
rtl_printf("Port %d|%d\tflg:%02x\ttmr:%p\t%s\n", pcb->local_port, pcb->remote_port, pcb->flags, pcb->tmr, tcp_state_str[pcb->state]);
prt_none = false;
}
if(prt_none) rtl_printf("none\n");
rtl_printf("TIME-WAIT PCB states:\n");
prt_none = true;
for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
rtl_printf("Port %d|%d\tflg:%02x\ttmr:%p\t%s\n", pcb->local_port, pcb->remote_port, pcb->flags, pcb->tmr, tcp_state_str[pcb->state]);
prt_none = false;
}
if(prt_none) rtl_printf("none\n");
}
/******************************************************************************
* FunctionName : debug
* Parameters :
* Returns :
*******************************************************************************/
#if 0
//------------------------------------------------------------------------------
void chow_tcp_connection_info(void)
{
rtl_printf("TCP Server connections:\n");
TCP_SERV_CFG * p;
TCP_SERV_CONN * ts_conn;
bool prt_none = true;
for(p = phcfg; p != NULL; p = p->next) {
for(ts_conn = p->conn_links; ts_conn != NULL; ts_conn = ts_conn->next) {
rtl_printf("%d "IPSTR ":%d %s\n", p->port, ts_conn->remote_ip.b[0], ts_conn->remote_ip.b[1], ts_conn->remote_ip.b[2], ts_conn->remote_ip.b[3], ts_conn->remote_port, tspsrv_srvconn_state_msg(ts_conn->state) );
prt_none = false;
}
}
if(prt_none) rtl_printf("none\n");
}
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -1,104 +0,0 @@
/*
main.cpp - Main loop for Arduino sketches
Copyright (c) 2005-2013 Arduino Team. 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
*/
#define ARDUINO_MAIN
#include "Arduino.h"
#include "cmsis_os.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#include "rtl8710b.h"
#include "FreeRTOS.h"
#include "task.h"
#include "diag.h"
extern void HalCpuClkConfig(u8 CpuType);
extern void SystemCoreClockUpdate(void);
extern void En32KCalibration(void);
extern int tcm_heap_freeSpace(void);
extern void console_init(void);
#ifdef __cplusplus
} // extern "C"
#endif
osThreadId main_tid = 0;
// Weak empty variant initialization function.
// May be redefined by variant files.
void initVariant() __attribute__((weak));
void initVariant() { }
// Initialize C library
extern "C" void __libc_init_array(void);
/*
* \brief Init Random()
* \note Use in void __low_level_init(void) { Init_Rand(); } !
*/
void Init_Rand(void)
{
extern u32 _rand_z1, _rand_z2, _rand_z3, _rand_z4, _rand_first;
u32 *p = (u32 *)0x1FFFFF00;
while(p < (u32 *)0x20000000) _rand_z1 ^= *p++;
_rand_z1 ^= (*((u32 *)0x40002018) << 24) ^ (*((u32 *)0x40002118) << 16) ^ (*((u32 *)0x40002218) << 8) ^ *((u32 *)0x40002318);
_rand_z2 = ((_rand_z1 & 0x007F00FF) << 7) ^ ((_rand_z1 & 0x0F80FF00) >> 8);
_rand_z3 = ((_rand_z2 & 0x007F00FF) << 7) ^ ((_rand_z2 & 0x0F80FF00) >> 8);
_rand_z4 = ((_rand_z3 & 0x007F00FF) << 7) ^ ((_rand_z3 & 0x0F80FF00) >> 8);
_rand_first = 1;
}
/*
* \brief handle sketch
*/
void main_task( void const *arg )
{
setup();
for (;;)
{
loop();
if (serialEventRun) serialEventRun();
yield();
}
}
/*
* \brief Main entry point of Arduino application
*/
int main( void )
{
LT_BANNER();
init();
__libc_init_array();
initVariant();
osThreadDef(main_task, osPriorityRealtime, 1, 4096*4);
main_tid = osThreadCreate(osThread (main_task), NULL);
osKernelStart();
while(1);
return 0;
}

View File

@@ -1,29 +0,0 @@
#ifndef __NETBIOS_H__
#define __NETBIOS_H__
/** default port number for "NetBIOS Name service */
#define NETBIOS_PORT 137
/** size of a NetBIOS name */
#define NETBIOS_NAME_LEN 16
#ifndef NET_IF_NUM
#define NET_IF_NUM 2
#endif
#ifdef __cplusplus
extern "C" {
#endif
extern char netbios_name[NET_IF_NUM][NETBIOS_NAME_LEN + 1]; // default netifs/interfacenum: 0 - SoftAP, 1 - Station, 2 - Ethernet
// struct udp_pcb * netbios_pcb(void);
void netbios_init(void);
bool netbios_set_name(unsigned char interfacenum, char * name); // default netifs/interfacenum: 0 - SoftAP, 1 - Station, 2 - Ethernet
bool netbios_off(void);
#ifdef __cplusplus
}
#endif
#endif /* __NETBIOS_H__ */

View File

@@ -1,215 +0,0 @@
/*
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 <stdlib.h>
#include <assert.h>
#include <debug.h>
#include <Arduino.h>
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#include <diag.h>
extern void *pvPortMalloc( size_t xWantedSize );
extern void *os_zalloc( size_t xWantedSize );
extern void vPortFree( void *pv );
extern void *pvPortReAlloc( void *pv, size_t xWantedSize );
extern size_t xPortGetFreeHeapSize( void );
extern size_t xPortGetMinimumEverFreeHeapSize( void );
extern void *tcm_heap_malloc(int size);
extern void *tcm_heap_calloc(int size);
extern void tcm_heap_free(void * mem);
extern void tcm_heap_dump(void);
extern int tcm_heap_freeSpace(void);
__attribute__((noreturn)) void __panic_func(const char* file, int line, const char* func)
{
DiagPrintf("\r\nPanic: %s, line: %d, %s\r\n");
while(1);
}
#ifdef __cplusplus
} // extern "C"
#endif
void hexdump(void * ptr, int cnt)
{
char * p = (char *) ptr;
int c = cnt;
while(c > 64) {
DumpForOneBytes((void *)p, 64);
p += 64;
c -= 64;
}
if(c != 0) DumpForOneBytes((void *)p, c);
}
void debug_on(void)
{
ConfigDebugErr = -1;
ConfigDebugInfo = -1;
ConfigDebugWarn = -1;
CfgSysDebugErr = -1;
CfgSysDebugInfo = -1;
CfgSysDebugWarn = -1;
}
void sys_info(void) {
rtl_printf("\r\nCLK CPU\t\t%d Hz\r\nRAM heap\t%d bytes\r\nTCM heap\t%d bytes\r\n",
HalGetCpuClk(), xPortGetFreeHeapSize(), tcm_heap_freeSpace());
}
/* void * malloc(size_t size)
{
void * ret;
if((ret = pvPortMalloc(size)) == NULL)
ret = tcm_heap_malloc(size);
return ret;
}
void * zalloc(size_t size)
{
void * ret;
if((ret = pvPortMalloc(size)) == NULL)
ret = tcm_heap_calloc(size);
else memset(ret, 0, size);
return ret;
}
void *calloc(size_t count, size_t size)
{
return zalloc(count * size);
} */
void free(void *pv)
{
vPortFree(pv);
}
void * realloc(void *pv, size_t size)
{
return pvPortReAlloc(pv, size);
}
/* void *operator new(size_t size)
{
void * ret;
if((ret = zalloc(size)) == NULL) {
DiagPrintf("\r\nMEM error!\r\n");
while(1);
}
return ret;
}
void *operator new[](size_t size)
{
void * ret;
if((ret = zalloc(size)) == NULL) {
DiagPrintf("\r\nMEM error!\r\n");
while(1);
}
return ret;
}
void operator delete(void * ptr)
{
free(ptr);
}
void operator delete[](void * ptr)
{
free(ptr);
} */
/*
extern "C" void __cxa_pure_virtual(void) __attribute__ ((__noreturn__));
extern "C" void __cxa_deleted_virtual(void) __attribute__ ((__noreturn__));
void __cxa_pure_virtual(void)
{
panic();
}
void __cxa_deleted_virtual(void)
{
panic();
}
typedef struct {
uint8_t guard;
uint8_t ps;
} guard_t;
extern "C" int __cxa_guard_acquire(__guard* pg)
{
uint8_t ps = xt_rsil(15);
if (reinterpret_cast<guard_t*>(pg)->guard) {
xt_wsr_ps(ps);
return 0;
}
reinterpret_cast<guard_t*>(pg)->ps = ps;
return 1;
}
extern "C" void __cxa_guard_release(__guard* pg)
{
reinterpret_cast<guard_t*>(pg)->guard = 1;
xt_wsr_ps(reinterpret_cast<guard_t*>(pg)->ps);
}
extern "C" void __cxa_guard_abort(__guard* pg)
{
xt_wsr_ps(reinterpret_cast<guard_t*>(pg)->ps);
}
namespace std
{
void __throw_bad_function_call()
{
panic();
}
void __throw_length_error(char const*)
{
panic();
}
void __throw_bad_alloc()
{
panic();
}
void __throw_logic_error(const char* str)
{
panic();
}
void __throw_out_of_range(const char* str)
{
panic();
}
}
*/

View File

@@ -1,146 +0,0 @@
#include "server_drv.h"
#ifdef __cplusplus
extern "C" {
#include "ard_socket.h"
#include "platform_stdlib.h"
}
#endif
// Start server TCP on port specified
int ServerDrv::startServer(uint16_t port, uint8_t protMode)
{
int sock;
sock = start_server(port, protMode);
if (sock >= 0) {
if(protMode == TCP_MODE)
sock_listen(sock, 1);
}
return sock;
}
int ServerDrv::getAvailable(int sock)
{
return get_available(sock);
}
int ServerDrv::availData(int sock)
{
int ret;
uint8_t c;
if (sock < 0)
return 0;
if(_available) {
return 1;
} else {
// flag = MSG_PEEK
ret = get_receive(sock, &c, 1, 1, &_peer_addr, &_peer_port);
if ( ret == 1 ) {
_available = true;
return 1;
}
else{
return ret;
}
}
}
bool ServerDrv::getData(int sock, uint8_t *data, uint8_t peek)
{
int ret = 0;
int flag = 0;
if (peek) {
flag |= 1;
} else {
_available = false;
}
ret = get_receive(sock, data, 1, flag, &_peer_addr, &_peer_port);
if (ret == 1) {
return true;
}
return false;
}
int ServerDrv::getDataBuf(int sock, uint8_t *_data, uint16_t _dataLen)
{
int ret;
_available = false;
ret = get_receive(sock, _data, _dataLen, 0, &_peer_addr, &_peer_port);
return ret;
}
int ServerDrv::getLastErrno(int sock)
{
return get_sock_errno(sock);
}
void ServerDrv::stopClient(int sock)
{
stop_socket(sock);
_available = false;
}
bool ServerDrv::sendData(int sock, const uint8_t *data, uint16_t len)
{
int ret;
if (sock < 0)
return false;
ret = send_data(sock, data, len);
if (ret <= 0) {
return false;
}
return true;
}
bool ServerDrv::sendtoData(int sock, const uint8_t *data, uint16_t len, uint32_t peer_ip, uint16_t peer_port)
{
int ret;
if (sock < 0)
return false;
ret = sendto_data(sock, data, len, peer_ip, peer_port);
if (ret == 0) {
return false;
}
return true;
}
int ServerDrv::startClient(uint32_t ipAddress, uint16_t port, uint8_t protMode)
{
int sock;
sock = start_client(ipAddress, port, protMode);
return sock;
}
void ServerDrv::getRemoteData(int sock, uint32_t *ip, uint16_t *port)
{
// TODO: These data may be outdated?
*ip = _peer_addr;
*port = _peer_port;
}
int ServerDrv::setSockRecvTimeout(int sock, int timeout)
{
return set_sock_recv_timeout(sock, timeout);
}

View File

@@ -1,57 +0,0 @@
/*
server_drv.h - Library for Arduino Wifi shield.
Copyright (c) 2011-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 Server_Drv_h
#define Server_Drv_h
#include <inttypes.h>
typedef enum eProtMode {TCP_MODE, UDP_MODE}tProtMode;
#define DATA_LENTH 128
class ServerDrv
{
public:
int startServer(uint16_t port, uint8_t protMode=TCP_MODE);
int getAvailable(int sock);
int startClient(uint32_t ipAddress, uint16_t port, uint8_t protMode=TCP_MODE);
int getLastErrno(int sock);
void stopClient(int sock);
bool getData(int sock, uint8_t *data, uint8_t peek = 0);
int getDataBuf(int sock, uint8_t *_data, uint16_t _dataLen);
/* Usually used by TCP */
bool sendData(int sock, const uint8_t *data, uint16_t len);
/* Usually used by UDP */
bool sendtoData(int sock, const uint8_t *data, uint16_t len, uint32_t peer_ip, uint16_t peer_port);
int availData(int sock);
void getRemoteData(int sock, uint32_t *ip, uint16_t *port);
int setSockRecvTimeout(int sock, int timeout);
private:
bool _available;
uint32_t _peer_addr;
uint16_t _peer_port;
};
#endif

View File

@@ -1,20 +0,0 @@
The MIT License (MIT)
Copyright (c) 2013-2015 Peter Andersson (pelleplutt1976<at>gmail.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.

View File

@@ -1,146 +0,0 @@
# SPIFFS (SPI Flash File System)
**V0.3.4**
Copyright (c) 2013-2016 Peter Andersson (pelleplutt1976 at gmail.com)
For legal stuff, see [LICENSE](https://github.com/pellepl/spiffs/blob/master/LICENSE). Basically, you may do whatever you want with the source. Use, modify, sell, print it out, roll it and smoke it - as long as I won't be held responsible.
Love to hear feedback though!
## INTRODUCTION
Spiffs is a file system intended for SPI NOR flash devices on embedded targets.
Spiffs is designed with following characteristics in mind:
- Small (embedded) targets, sparse RAM without heap
- Only big areas of data (blocks) can be erased
- An erase will reset all bits in block to ones
- Writing pulls one to zeroes
- Zeroes can only be pulled to ones by erase
- Wear leveling
## FEATURES
What spiffs does:
- Specifically designed for low ram usage
- Uses statically sized ram buffers, independent of number of files
- Posix-like api: open, close, read, write, seek, stat, etc
- It can be run on any NOR flash, not only SPI flash - theoretically also on embedded flash of an microprocessor
- Multiple spiffs configurations can be run on same target - and even on same SPI flash device
- Implements static wear leveling
- Built in file system consistency checks
What spiffs does not:
- Presently, spiffs does not support directories. It produces a flat structure. Creating a file with path *tmp/myfile.txt* will create a file called *tmp/myfile.txt* instead of a *myfile.txt* under directory *tmp*.
- It is not a realtime stack. One write operation might take much longer than another.
- Poor scalability. Spiffs is intended for small memory devices - the normal sizes for SPI flashes. Going beyond ~128MB is probably a bad idea. This is a side effect of the design goal to use as little ram as possible.
- Presently, it does not detect or handle bad blocks.
## MORE INFO
See the [wiki](https://github.com/pellepl/spiffs/wiki) for configuring, integrating and using spiffs.
For design, see [docs/TECH_SPEC](https://github.com/pellepl/spiffs/blob/master/docs/TECH_SPEC).
For a generic spi flash driver, see [this](https://github.com/pellepl/spiflash_driver).
## HISTORY
### 0.3.4
- Added user callback file func.
- Fixed a stat bug with obj id.
- SPIFFS_probe_fs added
- Add possibility to compile a read-only version of spiffs
- Make magic dependent on fs length, if needed (see #59 & #66) (thanks @hreintke)
- Exposed SPIFFS_open_by_page_function
- Zero-size file cannot be seek #57 (thanks @lishen2)
- Add tell and eof functions #54 (thanks @raburton)
- Make api string params const #53 (thanks @raburton)
- Preserve user_data during mount() #51 (thanks @rojer)
New API functions:
- `SPIFFS_set_file_callback_func` - register a callback informing about file events
- `SPIFFS_probe_fs` - probe a spi flash trying to figure out size of fs
- `SPIFFS_open_by_page` - open a file by page index
- `SPIFFS_eof` - checks if end of file is reached
- `SPIFFS_tell` - returns current file offset
New config defines:
- `SPIFFS_READ_ONLY`
- `SPIFFS_USE_MAGIC_LENGTH`
### 0.3.3
**Might not be compatible with 0.3.2 structures. See issue #40**
- Possibility to add integer offset to file handles
- Truncate function presumes too few free pages #49
- Bug in truncate function #48 (thanks @PawelDefee)
- Update spiffs_gc.c - remove unnecessary parameter (thanks @PawelDefee)
- Update INTEGRATION docs (thanks @PawelDefee)
- Fix pointer truncation in 64-bit platforms (thanks @igrr)
- Zero-sized files cannot be read #44 (thanks @rojer)
- (More) correct calculation of max_id in obj_lu_find #42 #41 (thanks @lishen2)
- Check correct error code in obj_lu_find_free #41 (thanks @lishen2)
- Moar comments for SPIFFS_lseek (thanks @igrr)
- Fixed padding in spiffs_page_object_ix #40 (thanks @jmattsson @lishen2)
- Fixed gc_quick test (thanks @jmattsson)
- Add SPIFFS_EXCL flag #36
- SPIFFS_close may fail silently if cache is enabled #37
- User data in callbacks #34
- Ignoring SINGLETON build in cache setup (thanks Luca)
- Compilation error fixed #32 (thanks @chotasanjiv)
- Align cand_scores (thanks @hefloryd)
- Fix build warnings when SPIFFS_CACHE is 0 (thanks @ajaybhargav)
New config defines:
- `SPIFFS_FILEHDL_OFFSET`
### 0.3.2
- Limit cache size if too much cache is given (thanks pgeiem)
- New feature - Controlled erase. #23
- SPIFFS_rename leaks file descriptors #28 (thanks benpicco)
- moved dbg print defines in test framework to params_test.h
- lseek should return the resulting offset (thanks hefloryd)
- fixed type on dbg ifdefs
- silence warning about signed/unsigned comparison when spiffs_obj_id is 32 bit (thanks benpicco)
- Possible error in test_spiffs.c #21 (thanks yihcdaso-yeskela)
- Cache might writethrough too often #16
- even moar testrunner updates
- Test framework update and some added tests
- Some thoughts for next gen
- Test sigsevs when having too many sectors #13 (thanks alonewolfx2)
- GC might be suboptimal #11
- Fix eternal readdir when objheader at last block, last entry
New API functions:
- `SPIFFS_gc_quick` - call a nonintrusive gc
- `SPIFFS_gc` - call a full-scale intrusive gc
### 0.3.1
- Removed two return warnings, was too triggerhappy on release
### 0.3.0
- Added existing namecheck when creating files
- Lots of static analysis bugs #6
- Added rename func
- Fix SPIFFS_read length when reading beyond file size
- Added reading beyond file length testcase
- Made build a bit more configurable
- Changed name in spiffs from "errno" to "err_code" due to conflicts compiling in mingw
- Improved GC checks, fixed an append bug, more robust truncate for very special case
- GC checks preempts GC, truncate even less picky
- Struct alignment needed for some targets, define in spiffs config #10
- Spiffs filesystem magic, definable in config
New config defines:
- `SPIFFS_USE_MAGIC` - enable or disable magic check upon mount
- `SPIFFS_ALIGNED_OBJECT_INDEX_TABLES` - alignment for certain targets
New API functions:
- `SPIFFS_rename` - rename files
- `SPIFFS_clearerr` - clears last errno
- `SPIFFS_info` - returns info on used and total bytes in fs
- `SPIFFS_format` - formats the filesystem
- `SPIFFS_mounted` - checks if filesystem is mounted

View File

@@ -1,239 +0,0 @@
* USING SPIFFS
TODO
* SPIFFS DESIGN
Spiffs is inspired by YAFFS. However, YAFFS is designed for NAND flashes, and
for bigger targets with much more ram. Nevertheless, many wise thoughts have
been borrowed from YAFFS when writing spiffs. Kudos!
The main complication writing spiffs was that it cannot be assumed the target
has a heap. Spiffs must go along only with the work ram buffer given to it.
This forces extra implementation on many areas of spiffs.
** SPI flash devices using NOR technology
Below is a small description of how SPI flashes work internally. This is to
give an understanding of the design choices made in spiffs.
SPI flash devices are physically divided in blocks. On some SPI flash devices,
blocks are further divided into sectors. Datasheets sometimes name blocks as
sectors and vice versa.
Common memory capacaties for SPI flashes are 512kB up to 8MB of data, where
blocks may be 64kB. Sectors can be e.g. 4kB, if supported. Many SPI flashes
have uniform block sizes, whereas others have non-uniform - the latter meaning
that e.g. the first 16 blocks are 4kB big, and the rest are 64kB.
The entire memory is linear and can be read and written in random access.
Erasing can only be done block- or sectorwise; or by mass erase.
SPI flashes can normally be erased from 100.000 up to 1.000.000 cycles before
they fail.
A clean SPI flash from factory have all bits in entire memory set to one. A
mass erase will reset the device to this state. Block or sector erasing will
put the all bits in the area given by the sector or block to ones. Writing to a
NOR flash pulls ones to zeroes. Writing 0xFF to an address is simply a no-op.
Writing 0b10101010 to a flash address holding 0b00001111 will yield 0b00001010.
This way of "write by nand" is used considerably in spiffs.
Common characteristics of NOR flashes are quick reads, but slow writes.
And finally, unlike NAND flashes, NOR flashes seem to not need any error
correction. They always write correctly I gather.
** Spiffs logical structure
Some terminology before proceeding. Physical blocks/sectors means sizes stated
in the datasheet. Logical blocks and pages is something the integrator choose.
** Blocks and pages
Spiffs is allocated to a part or all of the memory of the SPI flash device.
This area is divided into logical blocks, which in turn are divided into
logical pages. The boundary of a logical block must coincide with one or more
physical blocks. The sizes for logical blocks and logical pages always remain
the same, they are uniform.
Example: non-uniform flash mapped to spiffs with 128kB logical blocks
PHYSICAL FLASH BLOCKS SPIFFS LOGICAL BLOCKS: 128kB
+-----------------------+ - - - +-----------------------+
| Block 1 : 16kB | | Block 1 : 128kB |
+-----------------------+ | |
| Block 2 : 16kB | | |
+-----------------------+ | |
| Block 3 : 16kB | | |
+-----------------------+ | |
| Block 4 : 16kB | | |
+-----------------------+ | |
| Block 5 : 64kB | | |
+-----------------------+ - - - +-----------------------+
| Block 6 : 64kB | | Block 2 : 128kB |
+-----------------------+ | |
| Block 7 : 64kB | | |
+-----------------------+ - - - +-----------------------+
| Block 8 : 64kB | | Block 3 : 128kB |
+-----------------------+ | |
| Block 9 : 64kB | | |
+-----------------------+ - - - +-----------------------+
| ... | | ... |
A logical block is divided further into a number of logical pages. A page
defines the smallest data holding element known to spiffs. Hence, if a file
is created being one byte big, it will occupy one page for index and one page
for data - it will occupy 2 x size of a logical page on flash.
So it seems it is good to select a small page size.
Each page has a metadata header being normally 5 to 9 bytes. This said, a very
small page size will make metadata occupy a lot of the memory on the flash. A
page size of 64 bytes will waste 8-14% on metadata, while 256 bytes 2-4%.
So it seems it is good to select a big page size.
Also, spiffs uses a ram buffer being two times the page size. This ram buffer
is used for loading and manipulating pages, but it is also used for algorithms
to find free file ids, scanning the file system, etc. Having too small a page
size means less work buffer for spiffs, ending up in more reads operations and
eventually gives a slower file system.
Choosing the page size for the system involves many factors:
- How big is the logical block size
- What is the normal size of most files
- How much ram can be spent
- How much data (vs metadata) must be crammed into the file system
- How fast must spiffs be
- Other things impossible to find out
So, chosing the Optimal Page Size (tm) seems tricky, to say the least. Don't
fret - there is no optimal page size. This varies from how the target will use
spiffs. Use the golden rule:
~~~ Logical Page Size = Logical Block Size / 256 ~~~
This is a good starting point. The final page size can then be derived through
heuristical experimenting for us non-analytical minds.
** Objects, indices and look-ups
A file, or an object as called in spiffs, is identified by an object id.
Another YAFFS rip-off. This object id is a part of the page header. So, all
pages know to which object/file they belong - not counting the free pages.
An object is made up of two types of pages: object index pages and data pages.
Data pages contain the data written by user. Index pages contain metadata about
the object, more specifically what data pages are part of the object.
The page header also includes something called a span index. Let's say a file
is written covering three data pages. The first data page will then have span
index 0, the second span index 1, and the last data page will have span index
2. Simple as that.
Finally, each page header contain flags, telling if the page is used,
deleted, finalized, holds index or data, and more.
Object indices also have span indices, where an object index with span index 0
is referred to as the object index header. This page does not only contain
references to data pages, but also extra info such as object name, object size
in bytes, flags for file or directory, etc.
If one were to create a file covering three data pages, named e.g.
"spandex-joke.txt", given object id 12, it could look like this:
PAGE 0 <things to be unveiled soon>
PAGE 1 page header: [obj_id:12 span_ix:0 flags:USED|DATA]
<first data page of joke>
PAGE 2 page header: [obj_id:12 span_ix:1 flags:USED|DATA]
<second data page of joke>
PAGE 3 page header: [obj_id:545 span_ix:13 flags:USED|DATA]
<some data belonging to object 545, probably not very amusing>
PAGE 4 page header: [obj_id:12 span_ix:2 flags:USED|DATA]
<third data page of joke>
PAGE 5 page header: [obj_id:12 span_ix:0 flags:USED|INDEX]
obj ix header: [name:spandex-joke.txt size:600 bytes flags:FILE]
obj ix: [1 2 4]
Looking in detail at page 5, the object index header page, the object index
array refers to each data page in order, as mentioned before. The index of the
object index array correlates with the data page span index.
entry ix: 0 1 2
obj ix: [1 2 4]
| | |
PAGE 1, DATA, SPAN_IX 0 --------/ | |
PAGE 2, DATA, SPAN_IX 1 --------/ |
PAGE 4, DATA, SPAN_IX 2 --------/
Things to be unveiled in page 0 - well.. Spiffs is designed for systems low on
ram. We cannot keep a dynamic list on the whereabouts of each object index
header so we can find a file fast. There might not even be a heap! But, we do
not want to scan all page headers on the flash to find the object index header.
The first page(s) of each block contains the so called object look-up. These
are not normal pages, they do not have a header. Instead, they are arrays
pointing out what object-id the rest of all pages in the block belongs to.
By this look-up, only the first page(s) in each block must to scanned to find
the actual page which contains the object index header of the desired object.
The object lookup is redundant metadata. The assumption is that it presents
less overhead reading a full page of data to memory from each block and search
that, instead of reading a small amount of data from each page (i.e. the page
header) in all blocks. Each read operation from SPI flash normally contains
extra data as the read command itself and the flash address. Also, depending on
the underlying implementation, other criterions may need to be passed for each
read transaction, like mutexes and such.
The veiled example unveiled would look like this, with some extra pages:
PAGE 0 [ 12 12 545 12 12 34 34 4 0 0 0 0 ...]
PAGE 1 page header: [obj_id:12 span_ix:0 flags:USED|DATA] ...
PAGE 2 page header: [obj_id:12 span_ix:1 flags:USED|DATA] ...
PAGE 3 page header: [obj_id:545 span_ix:13 flags:USED|DATA] ...
PAGE 4 page header: [obj_id:12 span_ix:2 flags:USED|DATA] ...
PAGE 5 page header: [obj_id:12 span_ix:0 flags:USED|INDEX] ...
PAGE 6 page header: [obj_id:34 span_ix:0 flags:USED|DATA] ...
PAGE 7 page header: [obj_id:34 span_ix:1 flags:USED|DATA] ...
PAGE 8 page header: [obj_id:4 span_ix:1 flags:USED|INDEX] ...
PAGE 9 page header: [obj_id:23 span_ix:0 flags:DELETED|INDEX] ...
PAGE 10 page header: [obj_id:23 span_ix:0 flags:DELETED|DATA] ...
PAGE 11 page header: [obj_id:23 span_ix:1 flags:DELETED|DATA] ...
PAGE 12 page header: [obj_id:23 span_ix:2 flags:DELETED|DATA] ...
...
Ok, so why are page 9 to 12 marked as 0 when they belong to object id 23? These
pages are deleted, so this is marked both in page header flags and in the look
up. This is an example where spiffs uses NOR flashes "nand-way" of writing.
As a matter of fact, there are two object id's which are special:
obj id 0 (all bits zeroes) - indicates a deleted page in object look up
obj id 0xff.. (all bits ones) - indicates a free page in object look up
Actually, the object id's have another quirk: if the most significant bit is
set, this indicates an object index page. If the most significant bit is zero,
this indicates a data page. So to be fully correct, page 0 in above example
would look like this:
PAGE 0 [ 12 12 545 12 *12 34 34 *4 0 0 0 0 ...]
where the asterisk means the msb of the object id is set.
This is another way to speed up the searches when looking for object indices.
By looking on the object id's msb in the object lookup, it is also possible
to find out whether the page is an object index page or a data page.

View File

@@ -1,15 +0,0 @@
* When mending lost pages, also see if they fit into length specified in object index header
SPIFFS2 thoughts
* Instead of exact object id:s in the object lookup tables, use a hash of span index and object id.
Eg. object id xor:ed with bit-reversed span index.
This should decrease number of actual pages that needs to be visited when looking thru the obj lut.
* Logical number of each block. When moving stuff in a garbage collected page, the free
page is assigned the same number as the garbage collected. Thus, object index pages do not have to
be rewritten.
* Steal one page, use as a bit parity page. When starting an fs modification operation, write one bit
as zero. When ending, write another bit as zero. On mount, if number of zeroes in page is uneven, a
check is automatically run.

View File

@@ -1,681 +0,0 @@
/*
* spiffs.h
*
* Created on: May 26, 2013
* Author: petera
*/
#ifndef SPIFFS_H_
#define SPIFFS_H_
#if defined(__cplusplus)
extern "C" {
#endif
#include "spiffs_config.h"
#define SPIFFS_OK 0
#define SPIFFS_ERR_NOT_MOUNTED -10000
#define SPIFFS_ERR_FULL -10001
#define SPIFFS_ERR_NOT_FOUND -10002
#define SPIFFS_ERR_END_OF_OBJECT -10003
#define SPIFFS_ERR_DELETED -10004
#define SPIFFS_ERR_NOT_FINALIZED -10005
#define SPIFFS_ERR_NOT_INDEX -10006
#define SPIFFS_ERR_OUT_OF_FILE_DESCS -10007
#define SPIFFS_ERR_FILE_CLOSED -10008
#define SPIFFS_ERR_FILE_DELETED -10009
#define SPIFFS_ERR_BAD_DESCRIPTOR -10010
#define SPIFFS_ERR_IS_INDEX -10011
#define SPIFFS_ERR_IS_FREE -10012
#define SPIFFS_ERR_INDEX_SPAN_MISMATCH -10013
#define SPIFFS_ERR_DATA_SPAN_MISMATCH -10014
#define SPIFFS_ERR_INDEX_REF_FREE -10015
#define SPIFFS_ERR_INDEX_REF_LU -10016
#define SPIFFS_ERR_INDEX_REF_INVALID -10017
#define SPIFFS_ERR_INDEX_FREE -10018
#define SPIFFS_ERR_INDEX_LU -10019
#define SPIFFS_ERR_INDEX_INVALID -10020
#define SPIFFS_ERR_NOT_WRITABLE -10021
#define SPIFFS_ERR_NOT_READABLE -10022
#define SPIFFS_ERR_CONFLICTING_NAME -10023
#define SPIFFS_ERR_NOT_CONFIGURED -10024
#define SPIFFS_ERR_NOT_A_FS -10025
#define SPIFFS_ERR_MOUNTED -10026
#define SPIFFS_ERR_ERASE_FAIL -10027
#define SPIFFS_ERR_MAGIC_NOT_POSSIBLE -10028
#define SPIFFS_ERR_NO_DELETED_BLOCKS -10029
#define SPIFFS_ERR_FILE_EXISTS -10030
#define SPIFFS_ERR_NOT_A_FILE -10031
#define SPIFFS_ERR_RO_NOT_IMPL -10032
#define SPIFFS_ERR_RO_ABORTED_OPERATION -10033
#define SPIFFS_ERR_PROBE_TOO_FEW_BLOCKS -10034
#define SPIFFS_ERR_PROBE_NOT_A_FS -10035
#define SPIFFS_ERR_INTERNAL -10050
#define SPIFFS_ERR_TEST -10100
// spiffs file descriptor index type. must be signed
typedef s16_t spiffs_file;
// spiffs file descriptor flags
typedef u16_t spiffs_flags;
// spiffs file mode
typedef u16_t spiffs_mode;
// object type
typedef u8_t spiffs_obj_type;
struct spiffs_t;
#if SPIFFS_HAL_CALLBACK_EXTRA
/* spi read call function type */
typedef s32_t (*spiffs_read)(struct spiffs_t *fs, u32_t addr, u32_t size, u8_t *dst);
/* spi write call function type */
typedef s32_t (*spiffs_write)(struct spiffs_t *fs, u32_t addr, u32_t size, u8_t *src);
/* spi erase call function type */
typedef s32_t (*spiffs_erase)(struct spiffs_t *fs, u32_t addr, u32_t size);
#else // SPIFFS_HAL_CALLBACK_EXTRA
/* spi read call function type */
typedef s32_t (*spiffs_read)(u32_t addr, u32_t size, u8_t *dst);
/* spi write call function type */
typedef s32_t (*spiffs_write)(u32_t addr, u32_t size, u8_t *src);
/* spi erase call function type */
typedef s32_t (*spiffs_erase)(u32_t addr, u32_t size);
#endif // SPIFFS_HAL_CALLBACK_EXTRA
/* file system check callback report operation */
typedef enum {
SPIFFS_CHECK_LOOKUP = 0,
SPIFFS_CHECK_INDEX,
SPIFFS_CHECK_PAGE
} spiffs_check_type;
/* file system check callback report type */
typedef enum {
SPIFFS_CHECK_PROGRESS = 0,
SPIFFS_CHECK_ERROR,
SPIFFS_CHECK_FIX_INDEX,
SPIFFS_CHECK_FIX_LOOKUP,
SPIFFS_CHECK_DELETE_ORPHANED_INDEX,
SPIFFS_CHECK_DELETE_PAGE,
SPIFFS_CHECK_DELETE_BAD_FILE,
} spiffs_check_report;
/* file system check callback function */
#if SPIFFS_HAL_CALLBACK_EXTRA
typedef void (*spiffs_check_callback)(struct spiffs_t *fs, spiffs_check_type type, spiffs_check_report report,
u32_t arg1, u32_t arg2);
#else // SPIFFS_HAL_CALLBACK_EXTRA
typedef void (*spiffs_check_callback)(spiffs_check_type type, spiffs_check_report report,
u32_t arg1, u32_t arg2);
#endif // SPIFFS_HAL_CALLBACK_EXTRA
/* file system listener callback operation */
typedef enum {
/* the file has been created */
SPIFFS_CB_CREATED = 0,
/* the file has been updated or moved to another page */
SPIFFS_CB_UPDATED,
/* the file has been deleted */
SPIFFS_CB_DELETED,
} spiffs_fileop_type;
/* file system listener callback function */
typedef void (*spiffs_file_callback)(struct spiffs_t *fs, spiffs_fileop_type op, spiffs_obj_id obj_id, spiffs_page_ix pix);
#ifndef SPIFFS_DBG
#define SPIFFS_DBG(...) \
print(__VA_ARGS__)
#endif
#ifndef SPIFFS_GC_DBG
#define SPIFFS_GC_DBG(...) printf(__VA_ARGS__)
#endif
#ifndef SPIFFS_CACHE_DBG
#define SPIFFS_CACHE_DBG(...) printf(__VA_ARGS__)
#endif
#ifndef SPIFFS_CHECK_DBG
#define SPIFFS_CHECK_DBG(...) printf(__VA_ARGS__)
#endif
/* Any write to the filehandle is appended to end of the file */
#define SPIFFS_APPEND (1<<0)
/* If the opened file exists, it will be truncated to zero length before opened */
#define SPIFFS_TRUNC (1<<1)
/* If the opened file does not exist, it will be created before opened */
#define SPIFFS_CREAT (1<<2)
/* The opened file may only be read */
#define SPIFFS_RDONLY (1<<3)
/* The opened file may only be writted */
#define SPIFFS_WRONLY (1<<4)
/* The opened file may be both read and writted */
#define SPIFFS_RDWR (SPIFFS_RDONLY | SPIFFS_WRONLY)
/* Any writes to the filehandle will never be cached */
#define SPIFFS_DIRECT (1<<5)
/* If SPIFFS_CREAT and SPIFFS_EXCL are set, SPIFFS_open() shall fail if the file exists */
#define SPIFFS_EXCL (1<<6)
#define SPIFFS_SEEK_SET (0)
#define SPIFFS_SEEK_CUR (1)
#define SPIFFS_SEEK_END (2)
#define SPIFFS_TYPE_FILE (1)
#define SPIFFS_TYPE_DIR (2)
#define SPIFFS_TYPE_HARD_LINK (3)
#define SPIFFS_TYPE_SOFT_LINK (4)
#ifndef SPIFFS_LOCK
#define SPIFFS_LOCK(fs)
#endif
#ifndef SPIFFS_UNLOCK
#define SPIFFS_UNLOCK(fs)
#endif
// phys structs
// spiffs spi configuration struct
typedef struct {
// physical read function
spiffs_read hal_read_f;
// physical write function
spiffs_write hal_write_f;
// physical erase function
spiffs_erase hal_erase_f;
#if SPIFFS_SINGLETON == 0
// physical size of the spi flash
u32_t phys_size;
// physical offset in spi flash used for spiffs,
// must be on block boundary
u32_t phys_addr;
// physical size when erasing a block
u32_t phys_erase_block;
// logical size of a block, must be on physical
// block size boundary and must never be less than
// a physical block
u32_t log_block_size;
// logical size of a page, must be at least
// log_block_size / 8
u32_t log_page_size;
#endif
#if SPIFFS_FILEHDL_OFFSET
// an integer offset added to each file handle
u16_t fh_ix_offset;
#endif
} spiffs_config;
typedef struct spiffs_t {
// file system configuration
spiffs_config cfg;
// number of logical blocks
u32_t block_count;
// cursor for free blocks, block index
spiffs_block_ix free_cursor_block_ix;
// cursor for free blocks, entry index
int free_cursor_obj_lu_entry;
// cursor when searching, block index
spiffs_block_ix cursor_block_ix;
// cursor when searching, entry index
int cursor_obj_lu_entry;
// primary work buffer, size of a logical page
u8_t *lu_work;
// secondary work buffer, size of a logical page
u8_t *work;
// file descriptor memory area
u8_t *fd_space;
// available file descriptors
u32_t fd_count;
// last error
s32_t err_code;
// current number of free blocks
u32_t free_blocks;
// current number of busy pages
u32_t stats_p_allocated;
// current number of deleted pages
u32_t stats_p_deleted;
// flag indicating that garbage collector is cleaning
u8_t cleaning;
// max erase count amongst all blocks
spiffs_obj_id max_erase_count;
#if SPIFFS_GC_STATS
u32_t stats_gc_runs;
#endif
#if SPIFFS_CACHE
// cache memory
void *cache;
// cache size
u32_t cache_size;
#if SPIFFS_CACHE_STATS
u32_t cache_hits;
u32_t cache_misses;
#endif
#endif
// check callback function
spiffs_check_callback check_cb_f;
// file callback function
spiffs_file_callback file_cb_f;
// mounted flag
u8_t mounted;
// user data
void *user_data;
// config magic
u32_t config_magic;
} spiffs;
/* spiffs file status struct */
typedef struct {
spiffs_obj_id obj_id;
u32_t size;
spiffs_obj_type type;
spiffs_page_ix pix;
u8_t name[SPIFFS_OBJ_NAME_LEN];
} spiffs_stat;
struct spiffs_dirent {
spiffs_obj_id obj_id;
u8_t name[SPIFFS_OBJ_NAME_LEN];
spiffs_obj_type type;
u32_t size;
spiffs_page_ix pix;
};
typedef struct {
spiffs *fs;
spiffs_block_ix block;
int entry;
} spiffs_DIR;
// functions
#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0
/**
* Special function. This takes a spiffs config struct and returns the number
* of blocks this file system was formatted with. This function relies on
* that following info is set correctly in given config struct:
*
* phys_addr, log_page_size, and log_block_size.
*
* Also, hal_read_f must be set in the config struct.
*
* One must be sure of the correct page size and that the physical address is
* correct in the probed file system when calling this function. It is not
* checked if the phys_addr actually points to the start of the file system,
* so one might get a false positive if entering a phys_addr somewhere in the
* middle of the file system at block boundary. In addition, it is not checked
* if the page size is actually correct. If it is not, weird file system sizes
* will be returned.
*
* If this function detects a file system it returns the assumed file system
* size, which can be used to set the phys_size.
*
* Otherwise, it returns an error indicating why it is not regarded as a file
* system.
*
* Note: this function is not protected with SPIFFS_LOCK and SPIFFS_UNLOCK
* macros. It returns the error code directly, instead of as read by
* SPIFFS_errno.
*
* @param config essential parts of the physical and logical
* configuration of the file system.
*/
s32_t SPIFFS_probe_fs(spiffs_config *config);
#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0
/**
* Initializes the file system dynamic parameters and mounts the filesystem.
* If SPIFFS_USE_MAGIC is enabled the mounting may fail with SPIFFS_ERR_NOT_A_FS
* if the flash does not contain a recognizable file system.
* In this case, SPIFFS_format must be called prior to remounting.
* @param fs the file system struct
* @param config the physical and logical configuration of the file system
* @param work a memory work buffer comprising 2*config->log_page_size
* bytes used throughout all file system operations
* @param fd_space memory for file descriptors
* @param fd_space_size memory size of file descriptors
* @param cache memory for cache, may be null
* @param cache_size memory size of cache
* @param check_cb_f callback function for reporting during consistency checks
*/
s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
u8_t *fd_space, u32_t fd_space_size,
void *cache, u32_t cache_size,
spiffs_check_callback check_cb_f);
/**
* Unmounts the file system. All file handles will be flushed of any
* cached writes and closed.
* @param fs the file system struct
*/
void SPIFFS_unmount(spiffs *fs);
/**
* Creates a new file.
* @param fs the file system struct
* @param path the path of the new file
* @param mode ignored, for posix compliance
*/
s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode);
/**
* Opens/creates a file.
* @param fs the file system struct
* @param path the path of the new file
* @param flags the flags for the open command, can be combinations of
* SPIFFS_APPEND, SPIFFS_TRUNC, SPIFFS_CREAT, SPIFFS_RD_ONLY,
* SPIFFS_WR_ONLY, SPIFFS_RDWR, SPIFFS_DIRECT
* @param mode ignored, for posix compliance
*/
spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs_mode mode);
/**
* Opens a file by given dir entry.
* Optimization purposes, when traversing a file system with SPIFFS_readdir
* a normal SPIFFS_open would need to traverse the filesystem again to find
* the file, whilst SPIFFS_open_by_dirent already knows where the file resides.
* @param fs the file system struct
* @param e the dir entry to the file
* @param flags the flags for the open command, can be combinations of
* SPIFFS_APPEND, SPIFFS_TRUNC, SPIFFS_CREAT, SPIFFS_RD_ONLY,
* SPIFFS_WR_ONLY, SPIFFS_RDWR, SPIFFS_DIRECT.
* SPIFFS_CREAT will have no effect in this case.
* @param mode ignored, for posix compliance
*/
spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_flags flags, spiffs_mode mode);
/**
* Opens a file by given page index.
* Optimization purposes, opens a file by directly pointing to the page
* index in the spi flash.
* If the page index does not point to a file header SPIFFS_ERR_NOT_A_FILE
* is returned.
* @param fs the file system struct
* @param page_ix the page index
* @param flags the flags for the open command, can be combinations of
* SPIFFS_APPEND, SPIFFS_TRUNC, SPIFFS_CREAT, SPIFFS_RD_ONLY,
* SPIFFS_WR_ONLY, SPIFFS_RDWR, SPIFFS_DIRECT.
* SPIFFS_CREAT will have no effect in this case.
* @param mode ignored, for posix compliance
*/
spiffs_file SPIFFS_open_by_page(spiffs *fs, spiffs_page_ix page_ix, spiffs_flags flags, spiffs_mode mode);
/**
* Reads from given filehandle.
* @param fs the file system struct
* @param fh the filehandle
* @param buf where to put read data
* @param len how much to read
* @returns number of bytes read, or -1 if error
*/
s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len);
/**
* Writes to given filehandle.
* @param fs the file system struct
* @param fh the filehandle
* @param buf the data to write
* @param len how much to write
* @returns number of bytes written, or -1 if error
*/
s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len);
/**
* Moves the read/write file offset. Resulting offset is returned or negative if error.
* lseek(fs, fd, 0, SPIFFS_SEEK_CUR) will thus return current offset.
* @param fs the file system struct
* @param fh the filehandle
* @param offs how much/where to move the offset
* @param whence if SPIFFS_SEEK_SET, the file offset shall be set to offset bytes
* if SPIFFS_SEEK_CUR, the file offset shall be set to its current location plus offset
* if SPIFFS_SEEK_END, the file offset shall be set to the size of the file plus offse, which should be negative
*/
s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence);
/**
* Removes a file by path
* @param fs the file system struct
* @param path the path of the file to remove
*/
s32_t SPIFFS_remove(spiffs *fs, const char *path);
/**
* Removes a file by filehandle
* @param fs the file system struct
* @param fh the filehandle of the file to remove
*/
s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh);
/**
* Gets file status by path
* @param fs the file system struct
* @param path the path of the file to stat
* @param s the stat struct to populate
*/
s32_t SPIFFS_stat(spiffs *fs, const char *path, spiffs_stat *s);
/**
* Gets file status by filehandle
* @param fs the file system struct
* @param fh the filehandle of the file to stat
* @param s the stat struct to populate
*/
s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s);
/**
* Flushes all pending write operations from cache for given file
* @param fs the file system struct
* @param fh the filehandle of the file to flush
*/
s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh);
/**
* Closes a filehandle. If there are pending write operations, these are finalized before closing.
* @param fs the file system struct
* @param fh the filehandle of the file to close
*/
s32_t SPIFFS_close(spiffs *fs, spiffs_file fh);
/**
* Renames a file
* @param fs the file system struct
* @param old path of file to rename
* @param newPath new path of file
*/
s32_t SPIFFS_rename(spiffs *fs, const char *old, const char *newPath);
/**
* Returns last error of last file operation.
* @param fs the file system struct
*/
s32_t SPIFFS_errno(spiffs *fs);
/**
* Clears last error.
* @param fs the file system struct
*/
void SPIFFS_clearerr(spiffs *fs);
/**
* Opens a directory stream corresponding to the given name.
* The stream is positioned at the first entry in the directory.
* On hydrogen builds the name argument is ignored as hydrogen builds always correspond
* to a flat file structure - no directories.
* @param fs the file system struct
* @param name the name of the directory
* @param d pointer the directory stream to be populated
*/
spiffs_DIR *SPIFFS_opendir(spiffs *fs, const char *name, spiffs_DIR *d);
/**
* Closes a directory stream
* @param d the directory stream to close
*/
s32_t SPIFFS_closedir(spiffs_DIR *d);
/**
* Reads a directory into given spifs_dirent struct.
* @param d pointer to the directory stream
* @param e the dirent struct to be populated
* @returns null if error or end of stream, else given dirent is returned
*/
struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e);
/**
* Runs a consistency check on given filesystem.
* @param fs the file system struct
*/
s32_t SPIFFS_check(spiffs *fs);
/**
* Returns number of total bytes available and number of used bytes.
* This is an estimation, and depends on if there a many files with little
* data or few files with much data.
* NB: If used number of bytes exceeds total bytes, a SPIFFS_check should
* run. This indicates a power loss in midst of things. In worst case
* (repeated powerlosses in mending or gc) you might have to delete some files.
*
* @param fs the file system struct
* @param total total number of bytes in filesystem
* @param used used number of bytes in filesystem
*/
s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used);
/**
* Formats the entire file system. All data will be lost.
* The filesystem must not be mounted when calling this.
*
* NB: formatting is awkward. Due to backwards compatibility, SPIFFS_mount
* MUST be called prior to formatting in order to configure the filesystem.
* If SPIFFS_mount succeeds, SPIFFS_unmount must be called before calling
* SPIFFS_format.
* If SPIFFS_mount fails, SPIFFS_format can be called directly without calling
* SPIFFS_unmount first.
*
* @param fs the file system struct
*/
s32_t SPIFFS_format(spiffs *fs);
/**
* Returns nonzero if spiffs is mounted, or zero if unmounted.
* @param fs the file system struct
*/
u8_t SPIFFS_mounted(spiffs *fs);
/**
* Tries to find a block where most or all pages are deleted, and erase that
* block if found. Does not care for wear levelling. Will not move pages
* around.
* If parameter max_free_pages are set to 0, only blocks with only deleted
* pages will be selected.
*
* NB: the garbage collector is automatically called when spiffs needs free
* pages. The reason for this function is to give possibility to do background
* tidying when user knows the system is idle.
*
* Use with care.
*
* Setting max_free_pages to anything larger than zero will eventually wear
* flash more as a block containing free pages can be erased.
*
* Will set err_no to SPIFFS_OK if a block was found and erased,
* SPIFFS_ERR_NO_DELETED_BLOCK if no matching block was found,
* or other error.
*
* @param fs the file system struct
* @param max_free_pages maximum number allowed free pages in block
*/
s32_t SPIFFS_gc_quick(spiffs *fs, u16_t max_free_pages);
/**
* Will try to make room for given amount of bytes in the filesystem by moving
* pages and erasing blocks.
* If it is physically impossible, err_no will be set to SPIFFS_ERR_FULL. If
* there already is this amount (or more) of free space, SPIFFS_gc will
* silently return. It is recommended to call SPIFFS_info before invoking
* this method in order to determine what amount of bytes to give.
*
* NB: the garbage collector is automatically called when spiffs needs free
* pages. The reason for this function is to give possibility to do background
* tidying when user knows the system is idle.
*
* Use with care.
*
* @param fs the file system struct
* @param size amount of bytes that should be freed
*/
s32_t SPIFFS_gc(spiffs *fs, u32_t size);
/**
* Check if EOF reached.
* @param fs the file system struct
* @param fh the filehandle of the file to check
*/
s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh);
/**
* Get position in file.
* @param fs the file system struct
* @param fh the filehandle of the file to check
*/
s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh);
/**
* Registers a callback function that keeps track on operations on file
* headers. Do note, that this callback is called from within internal spiffs
* mechanisms. Any operations on the actual file system being callbacked from
* in this callback will mess things up for sure - do not do this.
* This can be used to track where files are and move around during garbage
* collection, which in turn can be used to build location tables in ram.
* Used in conjuction with SPIFFS_open_by_page this may improve performance
* when opening a lot of files.
* Must be invoked after mount.
*
* @param fs the file system struct
* @param cb_func the callback on file operations
*/
s32_t SPIFFS_set_file_callback_func(spiffs *fs, spiffs_file_callback cb_func);
#if SPIFFS_TEST_VISUALISATION
/**
* Prints out a visualization of the filesystem.
* @param fs the file system struct
*/
s32_t SPIFFS_vis(spiffs *fs);
#endif
#if SPIFFS_BUFFER_HELP
/**
* Returns number of bytes needed for the filedescriptor buffer given
* amount of file descriptors.
*/
u32_t SPIFFS_buffer_bytes_for_filedescs(spiffs *fs, u32_t num_descs);
#if SPIFFS_CACHE
/**
* Returns number of bytes needed for the cache buffer given
* amount of cache pages.
*/
u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages);
#endif
#endif
#if SPIFFS_CACHE
#endif
#if defined(__cplusplus)
}
#endif
#endif /* SPIFFS_H_ */

View File

@@ -1,299 +0,0 @@
/*
* spiffs_cache.c
*
* Created on: Jun 23, 2013
* Author: petera
*/
#include "spiffs.h"
#include "spiffs_nucleus.h"
#if SPIFFS_CACHE
// returns cached page for give page index, or null if no such cached page
static spiffs_cache_page *spiffs_cache_page_get(spiffs *fs, spiffs_page_ix pix) {
spiffs_cache *cache = spiffs_get_cache(fs);
if ((cache->cpage_use_map & cache->cpage_use_mask) == 0) return 0;
int i;
for (i = 0; i < cache->cpage_count; i++) {
spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i);
if ((cache->cpage_use_map & (1<<i)) &&
(cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) == 0 &&
cp->pix == pix ) {
SPIFFS_CACHE_DBG("CACHE_GET: have cache page %i for %04x\n", i, pix);
cp->last_access = cache->last_access;
return cp;
}
}
//SPIFFS_CACHE_DBG("CACHE_GET: no cache for %04x\n", pix);
return 0;
}
// frees cached page
static s32_t spiffs_cache_page_free(spiffs *fs, int ix, u8_t write_back) {
s32_t res = SPIFFS_OK;
spiffs_cache *cache = spiffs_get_cache(fs);
spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, ix);
if (cache->cpage_use_map & (1<<ix)) {
if (write_back &&
(cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) == 0 &&
(cp->flags & SPIFFS_CACHE_FLAG_DIRTY)) {
u8_t *mem = spiffs_get_cache_page(fs, cache, ix);
res = SPIFFS_HAL_WRITE(fs, SPIFFS_PAGE_TO_PADDR(fs, cp->pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), mem);
}
cp->flags = 0;
cache->cpage_use_map &= ~(1 << ix);
if (cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) {
SPIFFS_CACHE_DBG("CACHE_FREE: free cache page %i objid %04x\n", ix, cp->obj_id);
} else {
SPIFFS_CACHE_DBG("CACHE_FREE: free cache page %i pix %04x\n", ix, cp->pix);
}
}
return res;
}
// removes the oldest accessed cached page
static s32_t spiffs_cache_page_remove_oldest(spiffs *fs, u8_t flag_mask, u8_t flags) {
s32_t res = SPIFFS_OK;
spiffs_cache *cache = spiffs_get_cache(fs);
if ((cache->cpage_use_map & cache->cpage_use_mask) != cache->cpage_use_mask) {
// at least one free cpage
return SPIFFS_OK;
}
// all busy, scan thru all to find the cpage which has oldest access
int i;
int cand_ix = -1;
u32_t oldest_val = 0;
for (i = 0; i < cache->cpage_count; i++) {
spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i);
if ((cache->last_access - cp->last_access) > oldest_val &&
(cp->flags & flag_mask) == flags) {
oldest_val = cache->last_access - cp->last_access;
cand_ix = i;
}
}
if (cand_ix >= 0) {
res = spiffs_cache_page_free(fs, cand_ix, 1);
}
return res;
}
// allocates a new cached page and returns it, or null if all cache pages are busy
static spiffs_cache_page *spiffs_cache_page_allocate(spiffs *fs) {
spiffs_cache *cache = spiffs_get_cache(fs);
if (cache->cpage_use_map == 0xffffffff) {
// out of cache memory
return 0;
}
int i;
for (i = 0; i < cache->cpage_count; i++) {
if ((cache->cpage_use_map & (1<<i)) == 0) {
spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i);
cache->cpage_use_map |= (1<<i);
cp->last_access = cache->last_access;
SPIFFS_CACHE_DBG("CACHE_ALLO: allocated cache page %i\n", i);
return cp;
}
}
// out of cache entries
return 0;
}
// drops the cache page for give page index
void spiffs_cache_drop_page(spiffs *fs, spiffs_page_ix pix) {
spiffs_cache_page *cp = spiffs_cache_page_get(fs, pix);
if (cp) {
spiffs_cache_page_free(fs, cp->ix, 0);
}
}
// ------------------------------
// reads from spi flash or the cache
s32_t spiffs_phys_rd(
spiffs *fs,
u8_t op,
spiffs_file fh,
u32_t addr,
u32_t len,
u8_t *dst) {
(void)fh;
s32_t res = SPIFFS_OK;
spiffs_cache *cache = spiffs_get_cache(fs);
spiffs_cache_page *cp = spiffs_cache_page_get(fs, SPIFFS_PADDR_TO_PAGE(fs, addr));
cache->last_access++;
if (cp) {
#if SPIFFS_CACHE_STATS
fs->cache_hits++;
#endif
cp->last_access = cache->last_access;
} else {
if ((op & SPIFFS_OP_TYPE_MASK) == SPIFFS_OP_T_OBJ_LU2) {
// for second layer lookup functions, we do not cache in order to prevent shredding
return SPIFFS_HAL_READ(fs, addr, len, dst);
}
#if SPIFFS_CACHE_STATS
fs->cache_misses++;
#endif
res = spiffs_cache_page_remove_oldest(fs, SPIFFS_CACHE_FLAG_TYPE_WR, 0);
cp = spiffs_cache_page_allocate(fs);
if (cp) {
cp->flags = SPIFFS_CACHE_FLAG_WRTHRU;
cp->pix = SPIFFS_PADDR_TO_PAGE(fs, addr);
}
s32_t res2 = SPIFFS_HAL_READ(fs,
addr - SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr),
SPIFFS_CFG_LOG_PAGE_SZ(fs),
spiffs_get_cache_page(fs, cache, cp->ix));
if (res2 != SPIFFS_OK) {
res = res2;
}
}
u8_t *mem = spiffs_get_cache_page(fs, cache, cp->ix);
memcpy(dst, &mem[SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr)], len);
return res;
}
// writes to spi flash and/or the cache
s32_t spiffs_phys_wr(
spiffs *fs,
u8_t op,
spiffs_file fh,
u32_t addr,
u32_t len,
u8_t *src) {
(void)fh;
spiffs_page_ix pix = SPIFFS_PADDR_TO_PAGE(fs, addr);
spiffs_cache *cache = spiffs_get_cache(fs);
spiffs_cache_page *cp = spiffs_cache_page_get(fs, pix);
if (cp && (op & SPIFFS_OP_COM_MASK) != SPIFFS_OP_C_WRTHRU) {
// have a cache page
// copy in data to cache page
if ((op & SPIFFS_OP_COM_MASK) == SPIFFS_OP_C_DELE &&
(op & SPIFFS_OP_TYPE_MASK) != SPIFFS_OP_T_OBJ_LU) {
// page is being deleted, wipe from cache - unless it is a lookup page
spiffs_cache_page_free(fs, cp->ix, 0);
return SPIFFS_HAL_WRITE(fs, addr, len, src);
}
u8_t *mem = spiffs_get_cache_page(fs, cache, cp->ix);
memcpy(&mem[SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr)], src, len);
cache->last_access++;
cp->last_access = cache->last_access;
if (cp->flags & SPIFFS_CACHE_FLAG_WRTHRU) {
// page is being updated, no write-cache, just pass thru
return SPIFFS_HAL_WRITE(fs, addr, len, src);
} else {
return SPIFFS_OK;
}
} else {
// no cache page, no write cache - just write thru
return SPIFFS_HAL_WRITE(fs, addr, len, src);
}
}
#if SPIFFS_CACHE_WR
// returns the cache page that this fd refers, or null if no cache page
spiffs_cache_page *spiffs_cache_page_get_by_fd(spiffs *fs, spiffs_fd *fd) {
spiffs_cache *cache = spiffs_get_cache(fs);
if ((cache->cpage_use_map & cache->cpage_use_mask) == 0) {
// all cpages free, no cpage cannot be assigned to obj_id
return 0;
}
int i;
for (i = 0; i < cache->cpage_count; i++) {
spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i);
if ((cache->cpage_use_map & (1<<i)) &&
(cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) &&
cp->obj_id == fd->obj_id) {
return cp;
}
}
return 0;
}
// allocates a new cache page and refers this to given fd - flushes an old cache
// page if all cache is busy
spiffs_cache_page *spiffs_cache_page_allocate_by_fd(spiffs *fs, spiffs_fd *fd) {
// before this function is called, it is ensured that there is no already existing
// cache page with same object id
spiffs_cache_page_remove_oldest(fs, SPIFFS_CACHE_FLAG_TYPE_WR, 0);
spiffs_cache_page *cp = spiffs_cache_page_allocate(fs);
if (cp == 0) {
// could not get cache page
return 0;
}
cp->flags = SPIFFS_CACHE_FLAG_TYPE_WR;
cp->obj_id = fd->obj_id;
fd->cache_page = cp;
return cp;
}
// unrefers all fds that this cache page refers to and releases the cache page
void spiffs_cache_fd_release(spiffs *fs, spiffs_cache_page *cp) {
if (cp == 0) return;
u32_t i;
spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
for (i = 0; i < fs->fd_count; i++) {
spiffs_fd *cur_fd = &fds[i];
if (cur_fd->file_nbr != 0 && cur_fd->cache_page == cp) {
cur_fd->cache_page = 0;
}
}
spiffs_cache_page_free(fs, cp->ix, 0);
cp->obj_id = 0;
}
#endif
// initializes the cache
void spiffs_cache_init(spiffs *fs) {
if (fs->cache == 0) return;
u32_t sz = fs->cache_size;
u32_t cache_mask = 0;
int i;
int cache_entries =
(sz - sizeof(spiffs_cache)) / (SPIFFS_CACHE_PAGE_SIZE(fs));
if (cache_entries <= 0) return;
for (i = 0; i < cache_entries; i++) {
cache_mask <<= 1;
cache_mask |= 1;
}
spiffs_cache cache;
memset(&cache, 0, sizeof(spiffs_cache));
cache.cpage_count = cache_entries;
cache.cpages = (u8_t *)((u8_t *)fs->cache + sizeof(spiffs_cache));
cache.cpage_use_map = 0xffffffff;
cache.cpage_use_mask = cache_mask;
memcpy(fs->cache, &cache, sizeof(spiffs_cache));
spiffs_cache *c = spiffs_get_cache(fs);
memset(c->cpages, 0, c->cpage_count * SPIFFS_CACHE_PAGE_SIZE(fs));
c->cpage_use_map &= ~(c->cpage_use_mask);
for (i = 0; i < cache.cpage_count; i++) {
spiffs_get_cache_page_hdr(fs, c, i)->ix = i;
}
}
#endif // SPIFFS_CACHE

View File

@@ -1,995 +0,0 @@
/*
* spiffs_check.c
*
* Contains functionality for checking file system consistency
* and mending problems.
* Three levels of consistency checks are implemented:
*
* Look up consistency
* Checks if indices in lookup pages are coherent with page headers
* Object index consistency
* Checks if there are any orphaned object indices (missing object index headers).
* If an object index is found but not its header, the object index is deleted.
* This is critical for the following page consistency check.
* Page consistency
* Checks for pages that ought to be indexed, ought not to be indexed, are multiple indexed
*
*
* Created on: Jul 7, 2013
* Author: petera
*/
#include "spiffs.h"
#include "spiffs_nucleus.h"
#if !SPIFFS_READ_ONLY
#if SPIFFS_HAL_CALLBACK_EXTRA
#define CHECK_CB(_fs, _type, _rep, _arg1, _arg2) \
do { \
if ((_fs)->check_cb_f) (_fs)->check_cb_f((_fs), (_type), (_rep), (_arg1), (_arg2)); \
} while (0)
#else
#define CHECK_CB(_fs, _type, _rep, _arg1, _arg2) \
do { \
if ((_fs)->check_cb_f) (_fs)->check_cb_f((_type), (_rep), (_arg1), (_arg2)); \
} while (0)
#endif
//---------------------------------------
// Look up consistency
// searches in the object indices and returns the referenced page index given
// the object id and the data span index
// destroys fs->lu_work
static s32_t spiffs_object_get_data_page_index_reference(
spiffs *fs,
spiffs_obj_id obj_id,
spiffs_span_ix data_spix,
spiffs_page_ix *pix,
spiffs_page_ix *objix_pix) {
s32_t res;
// calculate object index span index for given data page span index
spiffs_span_ix objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix);
// find obj index for obj id and span index
res = spiffs_obj_lu_find_id_and_span(fs, obj_id | SPIFFS_OBJ_ID_IX_FLAG, objix_spix, 0, objix_pix);
SPIFFS_CHECK_RES(res);
// load obj index entry
u32_t addr = SPIFFS_PAGE_TO_PADDR(fs, *objix_pix);
if (objix_spix == 0) {
// get referenced page from object index header
addr += sizeof(spiffs_page_object_ix_header) + data_spix * sizeof(spiffs_page_ix);
} else {
// get referenced page from object index
addr += sizeof(spiffs_page_object_ix) + SPIFFS_OBJ_IX_ENTRY(fs, data_spix) * sizeof(spiffs_page_ix);
}
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, 0, addr, sizeof(spiffs_page_ix), (u8_t *)pix);
return res;
}
// copies page contents to a new page
static s32_t spiffs_rewrite_page(spiffs *fs, spiffs_page_ix cur_pix, spiffs_page_header *p_hdr, spiffs_page_ix *new_pix) {
s32_t res;
res = spiffs_page_allocate_data(fs, p_hdr->obj_id, p_hdr, 0,0,0,0, new_pix);
SPIFFS_CHECK_RES(res);
res = spiffs_phys_cpy(fs, 0,
SPIFFS_PAGE_TO_PADDR(fs, *new_pix) + sizeof(spiffs_page_header),
SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + sizeof(spiffs_page_header),
SPIFFS_DATA_PAGE_SIZE(fs));
SPIFFS_CHECK_RES(res);
return res;
}
// rewrites the object index for given object id and replaces the
// data page index to a new page index
static s32_t spiffs_rewrite_index(spiffs *fs, spiffs_obj_id obj_id, spiffs_span_ix data_spix, spiffs_page_ix new_data_pix, spiffs_page_ix objix_pix) {
s32_t res;
spiffs_block_ix bix;
int entry;
spiffs_page_ix free_pix;
obj_id |= SPIFFS_OBJ_ID_IX_FLAG;
// find free entry
res = spiffs_obj_lu_find_free(fs, fs->free_cursor_block_ix, fs->free_cursor_obj_lu_entry, &bix, &entry);
SPIFFS_CHECK_RES(res);
free_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry);
// calculate object index span index for given data page span index
spiffs_span_ix objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix);
if (objix_spix == 0) {
// calc index in index header
entry = data_spix;
} else {
// calc entry in index
entry = SPIFFS_OBJ_IX_ENTRY(fs, data_spix);
}
// load index
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
0, SPIFFS_PAGE_TO_PADDR(fs, objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
SPIFFS_CHECK_RES(res);
spiffs_page_header *objix_p_hdr = (spiffs_page_header *)fs->lu_work;
// be ultra safe, double check header against provided data
if (objix_p_hdr->obj_id != obj_id) {
spiffs_page_delete(fs, free_pix);
return SPIFFS_ERR_CHECK_OBJ_ID_MISM;
}
if (objix_p_hdr->span_ix != objix_spix) {
spiffs_page_delete(fs, free_pix);
return SPIFFS_ERR_CHECK_SPIX_MISM;
}
if ((objix_p_hdr->flags & (SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_IXDELE | SPIFFS_PH_FLAG_INDEX |
SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET)) !=
(SPIFFS_PH_FLAG_IXDELE | SPIFFS_PH_FLAG_DELET)) {
spiffs_page_delete(fs, free_pix);
return SPIFFS_ERR_CHECK_FLAGS_BAD;
}
// rewrite in mem
if (objix_spix == 0) {
((spiffs_page_ix*)((u8_t *)fs->lu_work + sizeof(spiffs_page_object_ix_header)))[data_spix] = new_data_pix;
} else {
((spiffs_page_ix*)((u8_t *)fs->lu_work + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)] = new_data_pix;
}
res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
0, SPIFFS_PAGE_TO_PADDR(fs, free_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
SPIFFS_CHECK_RES(res);
res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT,
0, SPIFFS_BLOCK_TO_PADDR(fs, SPIFFS_BLOCK_FOR_PAGE(fs, free_pix)) + SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, free_pix) * sizeof(spiffs_page_ix),
sizeof(spiffs_obj_id),
(u8_t *)&obj_id);
SPIFFS_CHECK_RES(res);
res = spiffs_page_delete(fs, objix_pix);
return res;
}
// deletes an object just by marking object index header as deleted
static s32_t spiffs_delete_obj_lazy(spiffs *fs, spiffs_obj_id obj_id) {
spiffs_page_ix objix_hdr_pix;
s32_t res;
res = spiffs_obj_lu_find_id_and_span(fs, obj_id, 0, 0, &objix_hdr_pix);
if (res == SPIFFS_ERR_NOT_FOUND) {
return SPIFFS_OK;
}
SPIFFS_CHECK_RES(res);
u8_t flags = 0xff & ~SPIFFS_PH_FLAG_IXDELE;
res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT,
0, SPIFFS_PAGE_TO_PADDR(fs, objix_hdr_pix) + offsetof(spiffs_page_header, flags),
sizeof(u8_t),
(u8_t *)&flags);
return res;
}
// validates the given look up entry
static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, spiffs_page_header *p_hdr,
spiffs_page_ix cur_pix, spiffs_block_ix cur_block, int cur_entry, int *reload_lu) {
(void)cur_block;
(void)cur_entry;
u8_t delete_page = 0;
s32_t res = SPIFFS_OK;
spiffs_page_ix objix_pix;
spiffs_page_ix ref_pix;
// check validity, take actions
if (((lu_obj_id == SPIFFS_OBJ_ID_DELETED) && (p_hdr->flags & SPIFFS_PH_FLAG_DELET)) ||
((lu_obj_id == SPIFFS_OBJ_ID_FREE) && (p_hdr->flags & SPIFFS_PH_FLAG_USED) == 0)) {
// look up entry deleted / free but used in page header
SPIFFS_CHECK_DBG("LU: pix %04x deleted/free in lu but not on page\n", cur_pix);
*reload_lu = 1;
delete_page = 1;
if (p_hdr->flags & SPIFFS_PH_FLAG_INDEX) {
// header says data page
// data page can be removed if not referenced by some object index
res = spiffs_object_get_data_page_index_reference(fs, p_hdr->obj_id, p_hdr->span_ix, &ref_pix, &objix_pix);
if (res == SPIFFS_ERR_NOT_FOUND) {
// no object with this id, so remove page safely
res = SPIFFS_OK;
} else {
SPIFFS_CHECK_RES(res);
if (ref_pix == cur_pix) {
// data page referenced by object index but deleted in lu
// copy page to new place and re-write the object index to new place
spiffs_page_ix new_pix;
res = spiffs_rewrite_page(fs, cur_pix, p_hdr, &new_pix);
SPIFFS_CHECK_DBG("LU: FIXUP: data page not found elsewhere, rewriting %04x to new page %04x\n", cur_pix, new_pix);
SPIFFS_CHECK_RES(res);
*reload_lu = 1;
SPIFFS_CHECK_DBG("LU: FIXUP: %04x rewritten to %04x, affected objix_pix %04x\n", cur_pix, new_pix, objix_pix);
res = spiffs_rewrite_index(fs, p_hdr->obj_id, p_hdr->span_ix, new_pix, objix_pix);
if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
// index bad also, cannot mend this file
SPIFFS_CHECK_DBG("LU: FIXUP: index bad %i, cannot mend!\n", res);
res = spiffs_page_delete(fs, new_pix);
SPIFFS_CHECK_RES(res);
res = spiffs_delete_obj_lazy(fs, p_hdr->obj_id);
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr->obj_id, 0);
} else {
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_INDEX, p_hdr->obj_id, p_hdr->span_ix);
}
SPIFFS_CHECK_RES(res);
}
}
} else {
// header says index page
// index page can be removed if other index with same obj_id and spanix is found
res = spiffs_obj_lu_find_id_and_span(fs, p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, cur_pix, 0);
if (res == SPIFFS_ERR_NOT_FOUND) {
// no such index page found, check for a data page amongst page headers
// lu cannot be trusted
res = spiffs_obj_lu_find_id_and_span_by_phdr(fs, p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, 0);
if (res == SPIFFS_OK) { // ignore other errors
// got a data page also, assume lu corruption only, rewrite to new page
spiffs_page_ix new_pix;
res = spiffs_rewrite_page(fs, cur_pix, p_hdr, &new_pix);
SPIFFS_CHECK_DBG("LU: FIXUP: ix page with data not found elsewhere, rewriting %04x to new page %04x\n", cur_pix, new_pix);
SPIFFS_CHECK_RES(res);
*reload_lu = 1;
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
}
} else {
SPIFFS_CHECK_RES(res);
}
}
}
if (lu_obj_id != SPIFFS_OBJ_ID_FREE && lu_obj_id != SPIFFS_OBJ_ID_DELETED) {
// look up entry used
if ((p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG) != (lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG)) {
SPIFFS_CHECK_DBG("LU: pix %04x differ in obj_id lu:%04x ph:%04x\n", cur_pix, lu_obj_id, p_hdr->obj_id);
delete_page = 1;
if ((p_hdr->flags & SPIFFS_PH_FLAG_DELET) == 0 ||
(p_hdr->flags & SPIFFS_PH_FLAG_FINAL) ||
(p_hdr->flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_IXDELE)) == 0) {
// page deleted or not finalized, just remove it
} else {
if (p_hdr->flags & SPIFFS_PH_FLAG_INDEX) {
// if data page, check for reference to this page
res = spiffs_object_get_data_page_index_reference(fs, p_hdr->obj_id, p_hdr->span_ix, &ref_pix, &objix_pix);
if (res == SPIFFS_ERR_NOT_FOUND) {
// no object with this id, so remove page safely
res = SPIFFS_OK;
} else {
SPIFFS_CHECK_RES(res);
// if found, rewrite page with object id, update index, and delete current
if (ref_pix == cur_pix) {
spiffs_page_ix new_pix;
res = spiffs_rewrite_page(fs, cur_pix, p_hdr, &new_pix);
SPIFFS_CHECK_RES(res);
res = spiffs_rewrite_index(fs, p_hdr->obj_id, p_hdr->span_ix, new_pix, objix_pix);
if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
// index bad also, cannot mend this file
SPIFFS_CHECK_DBG("LU: FIXUP: index bad %i, cannot mend!\n", res);
res = spiffs_page_delete(fs, new_pix);
SPIFFS_CHECK_RES(res);
res = spiffs_delete_obj_lazy(fs, p_hdr->obj_id);
*reload_lu = 1;
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr->obj_id, 0);
}
SPIFFS_CHECK_RES(res);
}
}
} else {
// else if index, check for other pages with both obj_id's and spanix
spiffs_page_ix objix_pix_lu, objix_pix_ph;
// see if other object index page exists for lookup obj id and span index
res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, 0, &objix_pix_lu);
if (res == SPIFFS_ERR_NOT_FOUND) {
res = SPIFFS_OK;
objix_pix_lu = 0;
}
SPIFFS_CHECK_RES(res);
// see if other object index exists for page header obj id and span index
res = spiffs_obj_lu_find_id_and_span(fs, p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, 0, &objix_pix_ph);
if (res == SPIFFS_ERR_NOT_FOUND) {
res = SPIFFS_OK;
objix_pix_ph = 0;
}
SPIFFS_CHECK_RES(res);
// if both obj_id's found, just delete current
if (objix_pix_ph == 0 || objix_pix_lu == 0) {
// otherwise try finding first corresponding data pages
spiffs_page_ix data_pix_lu, data_pix_ph;
// see if other data page exists for look up obj id and span index
res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &data_pix_lu);
if (res == SPIFFS_ERR_NOT_FOUND) {
res = SPIFFS_OK;
objix_pix_lu = 0;
}
SPIFFS_CHECK_RES(res);
// see if other data page exists for page header obj id and span index
res = spiffs_obj_lu_find_id_and_span(fs, p_hdr->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &data_pix_ph);
if (res == SPIFFS_ERR_NOT_FOUND) {
res = SPIFFS_OK;
objix_pix_ph = 0;
}
SPIFFS_CHECK_RES(res);
spiffs_page_header new_ph;
new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL);
new_ph.span_ix = p_hdr->span_ix;
spiffs_page_ix new_pix;
if ((objix_pix_lu && data_pix_lu && data_pix_ph && objix_pix_ph == 0) ||
(objix_pix_lu == 0 && data_pix_ph && objix_pix_ph == 0)) {
// got a data page for page header obj id
// rewrite as obj_id_ph
new_ph.obj_id = p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG;
res = spiffs_rewrite_page(fs, cur_pix, &new_ph, &new_pix);
SPIFFS_CHECK_DBG("LU: FIXUP: rewrite page %04x as %04x to pix %04x\n", cur_pix, new_ph.obj_id, new_pix);
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
SPIFFS_CHECK_RES(res);
*reload_lu = 1;
} else if ((objix_pix_ph && data_pix_ph && data_pix_lu && objix_pix_lu == 0) ||
(objix_pix_ph == 0 && data_pix_lu && objix_pix_lu == 0)) {
// got a data page for look up obj id
// rewrite as obj_id_lu
new_ph.obj_id = lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG;
SPIFFS_CHECK_DBG("LU: FIXUP: rewrite page %04x as %04x\n", cur_pix, new_ph.obj_id);
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
res = spiffs_rewrite_page(fs, cur_pix, &new_ph, &new_pix);
SPIFFS_CHECK_RES(res);
*reload_lu = 1;
} else {
// cannot safely do anything
SPIFFS_CHECK_DBG("LU: FIXUP: nothing to do, just delete\n");
}
}
}
}
} else if (((lu_obj_id & SPIFFS_OBJ_ID_IX_FLAG) && (p_hdr->flags & SPIFFS_PH_FLAG_INDEX)) ||
((lu_obj_id & SPIFFS_OBJ_ID_IX_FLAG) == 0 && (p_hdr->flags & SPIFFS_PH_FLAG_INDEX) == 0)) {
SPIFFS_CHECK_DBG("LU: %04x lu/page index marking differ\n", cur_pix);
spiffs_page_ix data_pix, objix_pix_d;
// see if other data page exists for given obj id and span index
res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, cur_pix, &data_pix);
if (res == SPIFFS_ERR_NOT_FOUND) {
res = SPIFFS_OK;
data_pix = 0;
}
SPIFFS_CHECK_RES(res);
// see if other object index exists for given obj id and span index
res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, cur_pix, &objix_pix_d);
if (res == SPIFFS_ERR_NOT_FOUND) {
res = SPIFFS_OK;
objix_pix_d = 0;
}
SPIFFS_CHECK_RES(res);
delete_page = 1;
// if other data page exists and object index exists, just delete page
if (data_pix && objix_pix_d) {
SPIFFS_CHECK_DBG("LU: FIXUP: other index and data page exists, simply remove\n");
} else
// if only data page exists, make this page index
if (data_pix && objix_pix_d == 0) {
SPIFFS_CHECK_DBG("LU: FIXUP: other data page exists, make this index\n");
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_INDEX, lu_obj_id, p_hdr->span_ix);
spiffs_page_header new_ph;
spiffs_page_ix new_pix;
new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_INDEX);
new_ph.obj_id = lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG;
new_ph.span_ix = p_hdr->span_ix;
res = spiffs_page_allocate_data(fs, new_ph.obj_id, &new_ph, 0, 0, 0, 1, &new_pix);
SPIFFS_CHECK_RES(res);
res = spiffs_phys_cpy(fs, 0, SPIFFS_PAGE_TO_PADDR(fs, new_pix) + sizeof(spiffs_page_header),
SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + sizeof(spiffs_page_header),
SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header));
SPIFFS_CHECK_RES(res);
} else
// if only index exists, make data page
if (data_pix == 0 && objix_pix_d) {
SPIFFS_CHECK_DBG("LU: FIXUP: other index page exists, make this data\n");
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, lu_obj_id, p_hdr->span_ix);
spiffs_page_header new_ph;
spiffs_page_ix new_pix;
new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL);
new_ph.obj_id = lu_obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
new_ph.span_ix = p_hdr->span_ix;
res = spiffs_page_allocate_data(fs, new_ph.obj_id, &new_ph, 0, 0, 0, 1, &new_pix);
SPIFFS_CHECK_RES(res);
res = spiffs_phys_cpy(fs, 0, SPIFFS_PAGE_TO_PADDR(fs, new_pix) + sizeof(spiffs_page_header),
SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + sizeof(spiffs_page_header),
SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header));
SPIFFS_CHECK_RES(res);
} else {
// if nothing exists, we cannot safely make a decision - delete
}
}
else if ((p_hdr->flags & SPIFFS_PH_FLAG_DELET) == 0) {
SPIFFS_CHECK_DBG("LU: pix %04x busy in lu but deleted on page\n", cur_pix);
delete_page = 1;
} else if ((p_hdr->flags & SPIFFS_PH_FLAG_FINAL)) {
SPIFFS_CHECK_DBG("LU: pix %04x busy but not final\n", cur_pix);
// page can be removed if not referenced by object index
*reload_lu = 1;
res = spiffs_object_get_data_page_index_reference(fs, lu_obj_id, p_hdr->span_ix, &ref_pix, &objix_pix);
if (res == SPIFFS_ERR_NOT_FOUND) {
// no object with this id, so remove page safely
res = SPIFFS_OK;
delete_page = 1;
} else {
SPIFFS_CHECK_RES(res);
if (ref_pix != cur_pix) {
SPIFFS_CHECK_DBG("LU: FIXUP: other finalized page is referred, just delete\n");
delete_page = 1;
} else {
// page referenced by object index but not final
// just finalize
SPIFFS_CHECK_DBG("LU: FIXUP: unfinalized page is referred, finalizing\n");
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
u8_t flags = 0xff & ~SPIFFS_PH_FLAG_FINAL;
res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + offsetof(spiffs_page_header, flags),
sizeof(u8_t), (u8_t*)&flags);
}
}
}
}
if (delete_page) {
SPIFFS_CHECK_DBG("LU: FIXUP: deleting page %04x\n", cur_pix);
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_PAGE, cur_pix, 0);
res = spiffs_page_delete(fs, cur_pix);
SPIFFS_CHECK_RES(res);
}
return res;
}
static s32_t spiffs_lookup_check_v(spiffs *fs, spiffs_obj_id obj_id, spiffs_block_ix cur_block, int cur_entry,
const void *user_const_p, void *user_var_p) {
(void)user_const_p;
(void)user_var_p;
s32_t res = SPIFFS_OK;
spiffs_page_header p_hdr;
spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, cur_block, cur_entry);
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS,
(cur_block * 256)/fs->block_count, 0);
// load header
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr);
SPIFFS_CHECK_RES(res);
int reload_lu = 0;
res = spiffs_lookup_check_validate(fs, obj_id, &p_hdr, cur_pix, cur_block, cur_entry, &reload_lu);
SPIFFS_CHECK_RES(res);
if (res == SPIFFS_OK) {
return reload_lu ? SPIFFS_VIS_COUNTINUE_RELOAD : SPIFFS_VIS_COUNTINUE;
}
return res;
}
// Scans all object look up. For each entry, corresponding page header is checked for validity.
// If an object index header page is found, this is also checked
s32_t spiffs_lookup_consistency_check(spiffs *fs, u8_t check_all_objects) {
(void)check_all_objects;
s32_t res = SPIFFS_OK;
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS, 0, 0);
res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_lookup_check_v, 0, 0, 0, 0);
if (res == SPIFFS_VIS_END) {
res = SPIFFS_OK;
}
if (res != SPIFFS_OK) {
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_ERROR, res, 0);
}
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS, 256, 0);
return res;
}
//---------------------------------------
// Page consistency
// Scans all pages (except lu pages), reserves 4 bits in working memory for each page
// bit 0: 0 == FREE|DELETED, 1 == USED
// bit 1: 0 == UNREFERENCED, 1 == REFERENCED
// bit 2: 0 == NOT_INDEX, 1 == INDEX
// bit 3: unused
// A consistent file system will have only pages being
// * x000 free, unreferenced, not index
// * x011 used, referenced only once, not index
// * x101 used, unreferenced, index
// The working memory might not fit all pages so several scans might be needed
static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
const u32_t bits = 4;
const spiffs_page_ix pages_per_scan = SPIFFS_CFG_LOG_PAGE_SZ(fs) * 8 / bits;
s32_t res = SPIFFS_OK;
spiffs_page_ix pix_offset = 0;
// for each range of pages fitting into work memory
while (pix_offset < SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count) {
// set this flag to abort all checks and rescan the page range
u8_t restart = 0;
memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs));
spiffs_block_ix cur_block = 0;
// build consistency bitmap for id range traversing all blocks
while (!restart && cur_block < fs->block_count) {
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS,
(pix_offset*256)/(SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count) +
((((cur_block * pages_per_scan * 256)/ (SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count))) / fs->block_count),
0);
// traverse each page except for lookup pages
spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_PAGES(fs) + SPIFFS_PAGES_PER_BLOCK(fs) * cur_block;
while (!restart && cur_pix < SPIFFS_PAGES_PER_BLOCK(fs) * (cur_block+1)) {
//if ((cur_pix & 0xff) == 0)
// SPIFFS_CHECK_DBG("PA: processing pix %08x, block %08x of pix %08x, block %08x\n",
// cur_pix, cur_block, SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count, fs->block_count);
// read header
spiffs_page_header p_hdr;
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr);
SPIFFS_CHECK_RES(res);
u8_t within_range = (cur_pix >= pix_offset && cur_pix < pix_offset + pages_per_scan);
const u32_t pix_byte_ix = (cur_pix - pix_offset) / (8/bits);
const u8_t pix_bit_ix = (cur_pix & ((8/bits)-1)) * bits;
if (within_range &&
(p_hdr.flags & SPIFFS_PH_FLAG_DELET) && (p_hdr.flags & SPIFFS_PH_FLAG_USED) == 0) {
// used
fs->work[pix_byte_ix] |= (1<<(pix_bit_ix + 0));
}
if ((p_hdr.flags & SPIFFS_PH_FLAG_DELET) &&
(p_hdr.flags & SPIFFS_PH_FLAG_IXDELE) &&
(p_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_USED)) == 0) {
// found non-deleted index
if (within_range) {
fs->work[pix_byte_ix] |= (1<<(pix_bit_ix + 2));
}
// load non-deleted index
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
SPIFFS_CHECK_RES(res);
// traverse index for referenced pages
spiffs_page_ix *object_page_index;
spiffs_page_header *objix_p_hdr = (spiffs_page_header *)fs->lu_work;
int entries;
int i;
spiffs_span_ix data_spix_offset;
if (p_hdr.span_ix == 0) {
// object header page index
entries = SPIFFS_OBJ_HDR_IX_LEN(fs);
data_spix_offset = 0;
object_page_index = (spiffs_page_ix *)((u8_t *)fs->lu_work + sizeof(spiffs_page_object_ix_header));
} else {
// object page index
entries = SPIFFS_OBJ_IX_LEN(fs);
data_spix_offset = SPIFFS_OBJ_HDR_IX_LEN(fs) + SPIFFS_OBJ_IX_LEN(fs) * (p_hdr.span_ix - 1);
object_page_index = (spiffs_page_ix *)((u8_t *)fs->lu_work + sizeof(spiffs_page_object_ix));
}
// for all entries in index
for (i = 0; !restart && i < entries; i++) {
spiffs_page_ix rpix = object_page_index[i];
u8_t rpix_within_range = rpix >= pix_offset && rpix < pix_offset + pages_per_scan;
if ((rpix != (spiffs_page_ix)-1 && rpix > SPIFFS_MAX_PAGES(fs))
|| (rpix_within_range && SPIFFS_IS_LOOKUP_PAGE(fs, rpix))) {
// bad reference
SPIFFS_CHECK_DBG("PA: pix %04x bad pix / LU referenced from page %04x\n",
rpix, cur_pix);
// check for data page elsewhere
spiffs_page_ix data_pix;
res = spiffs_obj_lu_find_id_and_span(fs, objix_p_hdr->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
data_spix_offset + i, 0, &data_pix);
if (res == SPIFFS_ERR_NOT_FOUND) {
res = SPIFFS_OK;
data_pix = 0;
}
SPIFFS_CHECK_RES(res);
if (data_pix == 0) {
// if not, allocate free page
spiffs_page_header new_ph;
new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL);
new_ph.obj_id = objix_p_hdr->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
new_ph.span_ix = data_spix_offset + i;
res = spiffs_page_allocate_data(fs, new_ph.obj_id, &new_ph, 0, 0, 0, 1, &data_pix);
SPIFFS_CHECK_RES(res);
SPIFFS_CHECK_DBG("PA: FIXUP: found no existing data page, created new @ %04x\n", data_pix);
}
// remap index
SPIFFS_CHECK_DBG("PA: FIXUP: rewriting index pix %04x\n", cur_pix);
res = spiffs_rewrite_index(fs, objix_p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG,
data_spix_offset + i, data_pix, cur_pix);
if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
// index bad also, cannot mend this file
SPIFFS_CHECK_DBG("PA: FIXUP: index bad %i, cannot mend - delete object\n", res);
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, objix_p_hdr->obj_id, 0);
// delete file
res = spiffs_page_delete(fs, cur_pix);
} else {
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, objix_p_hdr->obj_id, objix_p_hdr->span_ix);
}
SPIFFS_CHECK_RES(res);
restart = 1;
} else if (rpix_within_range) {
// valid reference
// read referenced page header
spiffs_page_header rp_hdr;
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
0, SPIFFS_PAGE_TO_PADDR(fs, rpix), sizeof(spiffs_page_header), (u8_t*)&rp_hdr);
SPIFFS_CHECK_RES(res);
// cross reference page header check
if (rp_hdr.obj_id != (p_hdr.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) ||
rp_hdr.span_ix != data_spix_offset + i ||
(rp_hdr.flags & (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_USED)) !=
(SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_INDEX)) {
SPIFFS_CHECK_DBG("PA: pix %04x has inconsistent page header ix id/span:%04x/%04x, ref id/span:%04x/%04x flags:%02x\n",
rpix, p_hdr.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, data_spix_offset + i,
rp_hdr.obj_id, rp_hdr.span_ix, rp_hdr.flags);
// try finding correct page
spiffs_page_ix data_pix;
res = spiffs_obj_lu_find_id_and_span(fs, p_hdr.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
data_spix_offset + i, rpix, &data_pix);
if (res == SPIFFS_ERR_NOT_FOUND) {
res = SPIFFS_OK;
data_pix = 0;
}
SPIFFS_CHECK_RES(res);
if (data_pix == 0) {
// not found, this index is badly borked
SPIFFS_CHECK_DBG("PA: FIXUP: index bad, delete object id %04x\n", p_hdr.obj_id);
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id);
SPIFFS_CHECK_RES(res);
break;
} else {
// found it, so rewrite index
SPIFFS_CHECK_DBG("PA: FIXUP: found correct data pix %04x, rewrite ix pix %04x id %04x\n",
data_pix, cur_pix, p_hdr.obj_id);
res = spiffs_rewrite_index(fs, p_hdr.obj_id, data_spix_offset + i, data_pix, cur_pix);
if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
// index bad also, cannot mend this file
SPIFFS_CHECK_DBG("PA: FIXUP: index bad %i, cannot mend!\n", res);
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id);
} else {
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, p_hdr.obj_id, p_hdr.span_ix);
}
SPIFFS_CHECK_RES(res);
restart = 1;
}
}
else {
// mark rpix as referenced
const u32_t rpix_byte_ix = (rpix - pix_offset) / (8/bits);
const u8_t rpix_bit_ix = (rpix & ((8/bits)-1)) * bits;
if (fs->work[rpix_byte_ix] & (1<<(rpix_bit_ix + 1))) {
SPIFFS_CHECK_DBG("PA: pix %04x multiple referenced from page %04x\n",
rpix, cur_pix);
// Here, we should have fixed all broken references - getting this means there
// must be multiple files with same object id. Only solution is to delete
// the object which is referring to this page
SPIFFS_CHECK_DBG("PA: FIXUP: removing object %04x and page %04x\n",
p_hdr.obj_id, cur_pix);
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id);
SPIFFS_CHECK_RES(res);
// extra precaution, delete this page also
res = spiffs_page_delete(fs, cur_pix);
SPIFFS_CHECK_RES(res);
restart = 1;
}
fs->work[rpix_byte_ix] |= (1<<(rpix_bit_ix + 1));
}
}
} // for all index entries
} // found index
// next page
cur_pix++;
}
// next block
cur_block++;
}
// check consistency bitmap
if (!restart) {
spiffs_page_ix objix_pix;
spiffs_page_ix rpix;
u32_t byte_ix;
u8_t bit_ix;
for (byte_ix = 0; !restart && byte_ix < SPIFFS_CFG_LOG_PAGE_SZ(fs); byte_ix++) {
for (bit_ix = 0; !restart && bit_ix < 8/bits; bit_ix ++) {
u8_t bitmask = (fs->work[byte_ix] >> (bit_ix * bits)) & 0x7;
spiffs_page_ix cur_pix = pix_offset + byte_ix * (8/bits) + bit_ix;
// 000 ok - free, unreferenced, not index
if (bitmask == 0x1) {
// 001
SPIFFS_CHECK_DBG("PA: pix %04x USED, UNREFERENCED, not index\n", cur_pix);
u8_t rewrite_ix_to_this = 0;
u8_t delete_page = 0;
// check corresponding object index entry
spiffs_page_header p_hdr;
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr);
SPIFFS_CHECK_RES(res);
res = spiffs_object_get_data_page_index_reference(fs, p_hdr.obj_id, p_hdr.span_ix,
&rpix, &objix_pix);
if (res == SPIFFS_OK) {
if (((rpix == (spiffs_page_ix)-1 || rpix > SPIFFS_MAX_PAGES(fs)) || (SPIFFS_IS_LOOKUP_PAGE(fs, rpix)))) {
// pointing to a bad page altogether, rewrite index to this
rewrite_ix_to_this = 1;
SPIFFS_CHECK_DBG("PA: corresponding ref is bad: %04x, rewrite to this %04x\n", rpix, cur_pix);
} else {
// pointing to something else, check what
spiffs_page_header rp_hdr;
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
0, SPIFFS_PAGE_TO_PADDR(fs, rpix), sizeof(spiffs_page_header), (u8_t*)&rp_hdr);
SPIFFS_CHECK_RES(res);
if (((p_hdr.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) == rp_hdr.obj_id) &&
((rp_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL)) ==
(SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_DELET))) {
// pointing to something else valid, just delete this page then
SPIFFS_CHECK_DBG("PA: corresponding ref is good but different: %04x, delete this %04x\n", rpix, cur_pix);
delete_page = 1;
} else {
// pointing to something weird, update index to point to this page instead
if (rpix != cur_pix) {
SPIFFS_CHECK_DBG("PA: corresponding ref is weird: %04x %s%s%s%s, rewrite this %04x\n", rpix,
(rp_hdr.flags & SPIFFS_PH_FLAG_INDEX) ? "" : "INDEX ",
(rp_hdr.flags & SPIFFS_PH_FLAG_DELET) ? "" : "DELETED ",
(rp_hdr.flags & SPIFFS_PH_FLAG_USED) ? "NOTUSED " : "",
(rp_hdr.flags & SPIFFS_PH_FLAG_FINAL) ? "NOTFINAL " : "",
cur_pix);
rewrite_ix_to_this = 1;
} else {
// should not happen, destined for fubar
}
}
}
} else if (res == SPIFFS_ERR_NOT_FOUND) {
SPIFFS_CHECK_DBG("PA: corresponding ref not found, delete %04x\n", cur_pix);
delete_page = 1;
res = SPIFFS_OK;
}
if (rewrite_ix_to_this) {
// if pointing to invalid page, redirect index to this page
SPIFFS_CHECK_DBG("PA: FIXUP: rewrite index id %04x data spix %04x to point to this pix: %04x\n",
p_hdr.obj_id, p_hdr.span_ix, cur_pix);
res = spiffs_rewrite_index(fs, p_hdr.obj_id, p_hdr.span_ix, cur_pix, objix_pix);
if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
// index bad also, cannot mend this file
SPIFFS_CHECK_DBG("PA: FIXUP: index bad %i, cannot mend!\n", res);
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
res = spiffs_page_delete(fs, cur_pix);
SPIFFS_CHECK_RES(res);
res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id);
} else {
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, p_hdr.obj_id, p_hdr.span_ix);
}
SPIFFS_CHECK_RES(res);
restart = 1;
continue;
} else if (delete_page) {
SPIFFS_CHECK_DBG("PA: FIXUP: deleting page %04x\n", cur_pix);
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_PAGE, cur_pix, 0);
res = spiffs_page_delete(fs, cur_pix);
}
SPIFFS_CHECK_RES(res);
}
if (bitmask == 0x2) {
// 010
SPIFFS_CHECK_DBG("PA: pix %04x FREE, REFERENCED, not index\n", cur_pix);
// no op, this should be taken care of when checking valid references
}
// 011 ok - busy, referenced, not index
if (bitmask == 0x4) {
// 100
SPIFFS_CHECK_DBG("PA: pix %04x FREE, unreferenced, INDEX\n", cur_pix);
// this should never happen, major fubar
}
// 101 ok - busy, unreferenced, index
if (bitmask == 0x6) {
// 110
SPIFFS_CHECK_DBG("PA: pix %04x FREE, REFERENCED, INDEX\n", cur_pix);
// no op, this should be taken care of when checking valid references
}
if (bitmask == 0x7) {
// 111
SPIFFS_CHECK_DBG("PA: pix %04x USED, REFERENCED, INDEX\n", cur_pix);
// no op, this should be taken care of when checking valid references
}
}
}
}
SPIFFS_CHECK_DBG("PA: processed %04x, restart %i\n", pix_offset, restart);
// next page range
if (!restart) {
pix_offset += pages_per_scan;
}
} // while page range not reached end
return res;
}
// Checks consistency amongst all pages and fixes irregularities
s32_t spiffs_page_consistency_check(spiffs *fs) {
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS, 0, 0);
s32_t res = spiffs_page_consistency_check_i(fs);
if (res != SPIFFS_OK) {
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_ERROR, res, 0);
}
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS, 256, 0);
return res;
}
//---------------------------------------
// Object index consistency
// searches for given object id in temporary object id index,
// returns the index or -1
static int spiffs_object_index_search(spiffs *fs, spiffs_obj_id obj_id) {
u32_t i;
spiffs_obj_id *obj_table = (spiffs_obj_id *)fs->work;
obj_id &= ~SPIFFS_OBJ_ID_IX_FLAG;
for (i = 0; i < SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id); i++) {
if ((obj_table[i] & ~SPIFFS_OBJ_ID_IX_FLAG) == obj_id) {
return i;
}
}
return -1;
}
static s32_t spiffs_object_index_consistency_check_v(spiffs *fs, spiffs_obj_id obj_id, spiffs_block_ix cur_block,
int cur_entry, const void *user_const_p, void *user_var_p) {
(void)user_const_p;
s32_t res_c = SPIFFS_VIS_COUNTINUE;
s32_t res = SPIFFS_OK;
u32_t *log_ix = (u32_t*)user_var_p;
spiffs_obj_id *obj_table = (spiffs_obj_id *)fs->work;
CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS,
(cur_block * 256)/fs->block_count, 0);
if (obj_id != SPIFFS_OBJ_ID_FREE && obj_id != SPIFFS_OBJ_ID_DELETED && (obj_id & SPIFFS_OBJ_ID_IX_FLAG)) {
spiffs_page_header p_hdr;
spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, cur_block, cur_entry);
// load header
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr);
SPIFFS_CHECK_RES(res);
if (p_hdr.span_ix == 0 &&
(p_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) ==
(SPIFFS_PH_FLAG_DELET)) {
SPIFFS_CHECK_DBG("IX: pix %04x, obj id:%04x spix:%04x header not fully deleted - deleting\n",
cur_pix, obj_id, p_hdr.span_ix);
CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_DELETE_PAGE, cur_pix, obj_id);
res = spiffs_page_delete(fs, cur_pix);
SPIFFS_CHECK_RES(res);
return res_c;
}
if ((p_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) ==
(SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) {
return res_c;
}
if (p_hdr.span_ix == 0) {
// objix header page, register objid as reachable
int r = spiffs_object_index_search(fs, obj_id);
if (r == -1) {
// not registered, do it
obj_table[*log_ix] = obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
(*log_ix)++;
if (*log_ix >= SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id)) {
*log_ix = 0;
}
}
} else { // span index
// objix page, see if header can be found
int r = spiffs_object_index_search(fs, obj_id);
u8_t delete = 0;
if (r == -1) {
// not in temporary index, try finding it
spiffs_page_ix objix_hdr_pix;
res = spiffs_obj_lu_find_id_and_span(fs, obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &objix_hdr_pix);
res_c = SPIFFS_VIS_COUNTINUE_RELOAD;
if (res == SPIFFS_OK) {
// found, register as reachable
obj_table[*log_ix] = obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
} else if (res == SPIFFS_ERR_NOT_FOUND) {
// not found, register as unreachable
delete = 1;
obj_table[*log_ix] = obj_id | SPIFFS_OBJ_ID_IX_FLAG;
} else {
SPIFFS_CHECK_RES(res);
}
(*log_ix)++;
if (*log_ix >= SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id)) {
*log_ix = 0;
}
} else {
// in temporary index, check reachable flag
if ((obj_table[r] & SPIFFS_OBJ_ID_IX_FLAG)) {
// registered as unreachable
delete = 1;
}
}
if (delete) {
SPIFFS_CHECK_DBG("IX: FIXUP: pix %04x, obj id:%04x spix:%04x is orphan index - deleting\n",
cur_pix, obj_id, p_hdr.span_ix);
CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_DELETE_ORPHANED_INDEX, cur_pix, obj_id);
res = spiffs_page_delete(fs, cur_pix);
SPIFFS_CHECK_RES(res);
}
} // span index
} // valid object index id
return res_c;
}
// Removes orphaned and partially deleted index pages.
// Scans for index pages. When an index page is found, corresponding index header is searched for.
// If no such page exists, the index page cannot be reached as no index header exists and must be
// deleted.
s32_t spiffs_object_index_consistency_check(spiffs *fs) {
s32_t res = SPIFFS_OK;
// impl note:
// fs->work is used for a temporary object index memory, listing found object ids and
// indicating whether they can be reached or not. Acting as a fifo if object ids cannot fit.
// In the temporary object index memory, SPIFFS_OBJ_ID_IX_FLAG bit is used to indicate
// a reachable/unreachable object id.
memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs));
u32_t obj_id_log_ix = 0;
CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS, 0, 0);
res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_object_index_consistency_check_v, &obj_id_log_ix,
0, 0, 0);
if (res == SPIFFS_VIS_END) {
res = SPIFFS_OK;
}
if (res != SPIFFS_OK) {
CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_ERROR, res, 0);
}
CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS, 256, 0);
return res;
}
#endif // !SPIFFS_READ_ONLY

View File

@@ -1,253 +0,0 @@
/*
* spiffs_config.h
*
* Created on: Jul 3, 2013
* Author: petera
*/
#ifndef SPIFFS_CONFIG_H_
#define SPIFFS_CONFIG_H_
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#define c_memcpy memcpy
#define c_printf printf
#define c_memset memset
typedef int16_t file_t;
typedef int32_t s32_t;
typedef uint32_t u32_t;
typedef int16_t s16_t;
typedef uint16_t u16_t;
typedef int8_t s8_t;
typedef uint8_t u8_t;
#ifndef SEEK_SET
#define SEEK_SET 0 /* set file offset to offset */
#endif
#ifndef SEEK_CUR
#define SEEK_CUR 1 /* set file offset to current plus offset */
#endif
#ifndef SEEK_END
#define SEEK_END 2 /* set file offset to EOF plus offset */
#endif
#ifndef EOF
#define EOF (-1)
#endif
// compile time switches
// Set generic spiffs debug output call.
#ifndef SPIFFS_DBG
#define SPIFFS_DBG(...) //printf(__VA_ARGS__)
#endif
// Set spiffs debug output call for garbage collecting.
#ifndef SPIFFS_GC_DBG
#define SPIFFS_GC_DBG(...) //printf(__VA_ARGS__)
#endif
// Set spiffs debug output call for caching.
#ifndef SPIFFS_CACHE_DBG
#define SPIFFS_CACHE_DBG(...) //printf(__VA_ARGS__)
#endif
// Set spiffs debug output call for system consistency checks.
#ifndef SPIFFS_CHECK_DBG
#define SPIFFS_CHECK_DBG(...) //printf(__VA_ARGS__)
#endif
// Enable/disable API functions to determine exact number of bytes
// for filedescriptor and cache buffers. Once decided for a configuration,
// this can be disabled to reduce flash.
#ifndef SPIFFS_BUFFER_HELP
#define SPIFFS_BUFFER_HELP 1
#endif
// Enables/disable memory read caching of nucleus file system operations.
// If enabled, memory area must be provided for cache in SPIFFS_mount.
#ifndef SPIFFS_CACHE
#define SPIFFS_CACHE 1
#endif
#if SPIFFS_CACHE
// Enables memory write caching for file descriptors in hydrogen
#ifndef SPIFFS_CACHE_WR
#define SPIFFS_CACHE_WR 1
#endif
// Enable/disable statistics on caching. Debug/test purpose only.
#ifndef SPIFFS_CACHE_STATS
#define SPIFFS_CACHE_STATS 0
#endif
#endif
// Always check header of each accessed page to ensure consistent state.
// If enabled it will increase number of reads, will increase flash.
#ifndef SPIFFS_PAGE_CHECK
#define SPIFFS_PAGE_CHECK 1
#endif
// Define maximum number of gc runs to perform to reach desired free pages.
#ifndef SPIFFS_GC_MAX_RUNS
#define SPIFFS_GC_MAX_RUNS 5
#endif
// Enable/disable statistics on gc. Debug/test purpose only.
#ifndef SPIFFS_GC_STATS
#define SPIFFS_GC_STATS 0
#endif
// Garbage collecting examines all pages in a block which and sums up
// to a block score. Deleted pages normally gives positive score and
// used pages normally gives a negative score (as these must be moved).
// To have a fair wear-leveling, the erase age is also included in score,
// whose factor normally is the most positive.
// The larger the score, the more likely it is that the block will
// picked for garbage collection.
// Garbage collecting heuristics - weight used for deleted pages.
#ifndef SPIFFS_GC_HEUR_W_DELET
#define SPIFFS_GC_HEUR_W_DELET (5)
#endif
// Garbage collecting heuristics - weight used for used pages.
#ifndef SPIFFS_GC_HEUR_W_USED
#define SPIFFS_GC_HEUR_W_USED (-1)
#endif
// Garbage collecting heuristics - weight used for time between
// last erased and erase of this block.
#ifndef SPIFFS_GC_HEUR_W_ERASE_AGE
#define SPIFFS_GC_HEUR_W_ERASE_AGE (50)
#endif
// Object name maximum length.
#ifndef SPIFFS_OBJ_NAME_LEN
#define SPIFFS_OBJ_NAME_LEN (32)
#endif
// Size of buffer allocated on stack used when copying data.
// Lower value generates more read/writes. No meaning having it bigger
// than logical page size.
#ifndef SPIFFS_COPY_BUFFER_STACK
#define SPIFFS_COPY_BUFFER_STACK (64)
#endif
// Enable this to have an identifiable spiffs filesystem. This will look for
// a magic in all sectors to determine if this is a valid spiffs system or
// not on mount point. If not, SPIFFS_format must be called prior to mounting
// again.
#ifndef SPIFFS_USE_MAGIC
#define SPIFFS_USE_MAGIC (1)
#endif
// SPIFFS_LOCK and SPIFFS_UNLOCK protects spiffs from reentrancy on api level
// These should be defined on a multithreaded system
// define this to enter a mutex if you're running on a multithreaded system
#ifndef SPIFFS_LOCK
#define SPIFFS_LOCK(fs)
#endif
// define this to exit a mutex if you're running on a multithreaded system
#ifndef SPIFFS_UNLOCK
#define SPIFFS_UNLOCK(fs)
#endif
// Enable if only one spiffs instance with constant configuration will exist
// on the target. This will reduce calculations, flash and memory accesses.
// Parts of configuration must be defined below instead of at time of mount.
#ifndef SPIFFS_SINGLETON
#define SPIFFS_SINGLETON 0
#endif
#if SPIFFS_SINGLETON
// Instead of giving parameters in config struct, singleton build must
// give parameters in defines below.
#ifndef SPIFFS_CFG_PHYS_SZ
#define SPIFFS_CFG_PHYS_SZ(ignore) (1024*1024*2)
#endif
#ifndef SPIFFS_CFG_PHYS_ERASE_SZ
#define SPIFFS_CFG_PHYS_ERASE_SZ(ignore) (65536)
#endif
#ifndef SPIFFS_CFG_PHYS_ADDR
#define SPIFFS_CFG_PHYS_ADDR(ignore) (0)
#endif
#ifndef SPIFFS_CFG_LOG_PAGE_SZ
#define SPIFFS_CFG_LOG_PAGE_SZ(ignore) (256)
#endif
#ifndef SPIFFS_CFG_LOG_BLOCK_SZ
#define SPIFFS_CFG_LOG_BLOCK_SZ(ignore) (65536)
#endif
#endif
// Enable this if your target needs aligned data for index tables
#ifndef SPIFFS_ALIGNED_OBJECT_INDEX_TABLES
#define SPIFFS_ALIGNED_OBJECT_INDEX_TABLES 1
#endif
// Enable this if you want the HAL callbacks to be called with the spiffs struct
#ifndef SPIFFS_HAL_CALLBACK_EXTRA
#define SPIFFS_HAL_CALLBACK_EXTRA 0
#endif
// Enable this if you want to add an integer offset to all file handles
// (spiffs_file). This is useful if running multiple instances of spiffs on
// same target, in order to recognise to what spiffs instance a file handle
// belongs.
// NB: This adds config field fh_ix_offset in the configuration struct when
// mounting, which must be defined.
#ifndef SPIFFS_FILEHDL_OFFSET
#define SPIFFS_FILEHDL_OFFSET 0
#endif
// Set SPIFFS_TEST_VISUALISATION to non-zero to enable SPIFFS_vis function
// in the api. This function will visualize all filesystem using given printf
// function.
#ifndef SPIFFS_TEST_VISUALISATION
#define SPIFFS_TEST_VISUALISATION 1
#endif
#if SPIFFS_TEST_VISUALISATION
#ifndef spiffs_printf
#define spiffs_printf(...) c_printf(__VA_ARGS__)
#endif
// spiffs_printf argument for a free page
#ifndef SPIFFS_TEST_VIS_FREE_STR
#define SPIFFS_TEST_VIS_FREE_STR "_"
#endif
// spiffs_printf argument for a deleted page
#ifndef SPIFFS_TEST_VIS_DELE_STR
#define SPIFFS_TEST_VIS_DELE_STR "/"
#endif
// spiffs_printf argument for an index page for given object id
#ifndef SPIFFS_TEST_VIS_INDX_STR
#define SPIFFS_TEST_VIS_INDX_STR(id) "i"
#endif
// spiffs_printf argument for a data page for given object id
#ifndef SPIFFS_TEST_VIS_DATA_STR
#define SPIFFS_TEST_VIS_DATA_STR(id) "d"
#endif
#endif
// Types depending on configuration such as the amount of flash bytes
// given to spiffs file system in total (spiffs_file_system_size),
// the logical block size (log_block_size), and the logical page size
// (log_page_size)
// Block index type. Make sure the size of this type can hold
// the highest number of all blocks - i.e. spiffs_file_system_size / log_block_size
typedef u16_t spiffs_block_ix;
// Page index type. Make sure the size of this type can hold
// the highest page number of all pages - i.e. spiffs_file_system_size / log_page_size
typedef u16_t spiffs_page_ix;
// Object id type - most significant bit is reserved for index flag. Make sure the
// size of this type can hold the highest object id on a full system,
// i.e. 2 + (spiffs_file_system_size / (2*log_page_size))*2
typedef u16_t spiffs_obj_id;
// Object span index type. Make sure the size of this type can
// hold the largest possible span index on the system -
// i.e. (spiffs_file_system_size / log_page_size) - 1
typedef u16_t spiffs_span_ix;
#endif /* SPIFFS_CONFIG_H_ */

View File

@@ -1,576 +0,0 @@
#include "spiffs.h"
#include "spiffs_nucleus.h"
#if !SPIFFS_READ_ONLY
// Erases a logical block and updates the erase counter.
// If cache is enabled, all pages that might be cached in this block
// is dropped.
static s32_t spiffs_gc_erase_block(
spiffs *fs,
spiffs_block_ix bix) {
s32_t res;
SPIFFS_GC_DBG("gc: erase block %i\n", bix);
res = spiffs_erase_block(fs, bix);
SPIFFS_CHECK_RES(res);
#if SPIFFS_CACHE
{
u32_t i;
for (i = 0; i < SPIFFS_PAGES_PER_BLOCK(fs); i++) {
spiffs_cache_drop_page(fs, SPIFFS_PAGE_FOR_BLOCK(fs, bix) + i);
}
}
#endif
return res;
}
// Searches for blocks where all entries are deleted - if one is found,
// the block is erased. Compared to the non-quick gc, the quick one ensures
// that no updates are needed on existing objects on pages that are erased.
s32_t spiffs_gc_quick(
spiffs *fs, u16_t max_free_pages) {
s32_t res = SPIFFS_OK;
u32_t blocks = fs->block_count;
spiffs_block_ix cur_block = 0;
u32_t cur_block_addr = 0;
int cur_entry = 0;
spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
SPIFFS_GC_DBG("gc_quick: running\n");
#if SPIFFS_GC_STATS
fs->stats_gc_runs++;
#endif
int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
// find fully deleted blocks
// check each block
while (res == SPIFFS_OK && blocks--) {
u16_t deleted_pages_in_block = 0;
u16_t free_pages_in_block = 0;
int obj_lookup_page = 0;
// check each object lookup page
while (res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
int entry_offset = obj_lookup_page * entries_per_page;
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
0, cur_block_addr + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
// check each entry
while (res == SPIFFS_OK &&
cur_entry - entry_offset < entries_per_page &&
cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))) {
spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset];
if (obj_id == SPIFFS_OBJ_ID_DELETED) {
deleted_pages_in_block++;
} else if (obj_id == SPIFFS_OBJ_ID_FREE) {
// kill scan, go for next block
free_pages_in_block++;
if (free_pages_in_block > max_free_pages) {
obj_lookup_page = SPIFFS_OBJ_LOOKUP_PAGES(fs);
res = 1; // kill object lu loop
break;
}
} else {
// kill scan, go for next block
obj_lookup_page = SPIFFS_OBJ_LOOKUP_PAGES(fs);
res = 1; // kill object lu loop
break;
}
cur_entry++;
} // per entry
obj_lookup_page++;
} // per object lookup page
if (res == 1) res = SPIFFS_OK;
if (res == SPIFFS_OK &&
deleted_pages_in_block + free_pages_in_block == SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs) &&
free_pages_in_block <= max_free_pages) {
// found a fully deleted block
fs->stats_p_deleted -= deleted_pages_in_block;
res = spiffs_gc_erase_block(fs, cur_block);
return res;
}
cur_entry = 0;
cur_block++;
cur_block_addr += SPIFFS_CFG_LOG_BLOCK_SZ(fs);
} // per block
if (res == SPIFFS_OK) {
res = SPIFFS_ERR_NO_DELETED_BLOCKS;
}
return res;
}
// Checks if garbage collecting is necessary. If so a candidate block is found,
// cleansed and erased
s32_t spiffs_gc_check(
spiffs *fs,
u32_t len) {
s32_t res;
s32_t free_pages =
(SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * (fs->block_count-2)
- fs->stats_p_allocated - fs->stats_p_deleted;
int tries = 0;
if (fs->free_blocks > 3 &&
(s32_t)len < free_pages * (s32_t)SPIFFS_DATA_PAGE_SIZE(fs)) {
return SPIFFS_OK;
}
u32_t needed_pages = (len + SPIFFS_DATA_PAGE_SIZE(fs) - 1) / SPIFFS_DATA_PAGE_SIZE(fs);
// if (fs->free_blocks <= 2 && (s32_t)needed_pages > free_pages) {
// SPIFFS_GC_DBG("gc: full freeblk:%i needed:%i free:%i dele:%i\n", fs->free_blocks, needed_pages, free_pages, fs->stats_p_deleted);
// return SPIFFS_ERR_FULL;
// }
if ((s32_t)needed_pages > (s32_t)(free_pages + fs->stats_p_deleted)) {
SPIFFS_GC_DBG("gc_check: full freeblk:%i needed:%i free:%i dele:%i\n", fs->free_blocks, needed_pages, free_pages, fs->stats_p_deleted);
return SPIFFS_ERR_FULL;
}
do {
SPIFFS_GC_DBG("\ngc_check #%i: run gc free_blocks:%i pfree:%i pallo:%i pdele:%i [%i] len:%i of %i\n",
tries,
fs->free_blocks, free_pages, fs->stats_p_allocated, fs->stats_p_deleted, (free_pages+fs->stats_p_allocated+fs->stats_p_deleted),
len, free_pages*SPIFFS_DATA_PAGE_SIZE(fs));
spiffs_block_ix *cands;
int count;
spiffs_block_ix cand;
s32_t prev_free_pages = free_pages;
// if the fs is crammed, ignore block age when selecting candidate - kind of a bad state
res = spiffs_gc_find_candidate(fs, &cands, &count, free_pages <= 0);
SPIFFS_CHECK_RES(res);
if (count == 0) {
SPIFFS_GC_DBG("gc_check: no candidates, return\n");
return (s32_t)needed_pages < free_pages ? SPIFFS_OK : SPIFFS_ERR_FULL;
}
#if SPIFFS_GC_STATS
fs->stats_gc_runs++;
#endif
cand = cands[0];
fs->cleaning = 1;
//printf("gcing: cleaning block %i\n", cand);
res = spiffs_gc_clean(fs, cand);
fs->cleaning = 0;
if (res < 0) {
SPIFFS_GC_DBG("gc_check: cleaning block %i, result %i\n", cand, res);
} else {
SPIFFS_GC_DBG("gc_check: cleaning block %i, result %i\n", cand, res);
}
SPIFFS_CHECK_RES(res);
res = spiffs_gc_erase_page_stats(fs, cand);
SPIFFS_CHECK_RES(res);
res = spiffs_gc_erase_block(fs, cand);
SPIFFS_CHECK_RES(res);
free_pages =
(SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * (fs->block_count - 2)
- fs->stats_p_allocated - fs->stats_p_deleted;
if (prev_free_pages <= 0 && prev_free_pages == free_pages) {
// abort early to reduce wear, at least tried once
SPIFFS_GC_DBG("gc_check: early abort, no result on gc when fs crammed\n");
break;
}
} while (++tries < SPIFFS_GC_MAX_RUNS && (fs->free_blocks <= 2 ||
(s32_t)len > free_pages*(s32_t)SPIFFS_DATA_PAGE_SIZE(fs)));
free_pages =
(SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * (fs->block_count - 2)
- fs->stats_p_allocated - fs->stats_p_deleted;
if ((s32_t)len > free_pages*(s32_t)SPIFFS_DATA_PAGE_SIZE(fs)) {
res = SPIFFS_ERR_FULL;
}
SPIFFS_GC_DBG("gc_check: finished, %i dirty, blocks %i free, %i pages free, %i tries, res %i\n",
fs->stats_p_allocated + fs->stats_p_deleted,
fs->free_blocks, free_pages, tries, res);
return res;
}
// Updates page statistics for a block that is about to be erased
s32_t spiffs_gc_erase_page_stats(
spiffs *fs,
spiffs_block_ix bix) {
s32_t res = SPIFFS_OK;
int obj_lookup_page = 0;
int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
int cur_entry = 0;
u32_t dele = 0;
u32_t allo = 0;
// check each object lookup page
while (res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
int entry_offset = obj_lookup_page * entries_per_page;
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
// check each entry
while (res == SPIFFS_OK &&
cur_entry - entry_offset < entries_per_page && cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))) {
spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset];
if (obj_id == SPIFFS_OBJ_ID_FREE) {
} else if (obj_id == SPIFFS_OBJ_ID_DELETED) {
dele++;
} else {
allo++;
}
cur_entry++;
} // per entry
obj_lookup_page++;
} // per object lookup page
SPIFFS_GC_DBG("gc_check: wipe pallo:%i pdele:%i\n", allo, dele);
fs->stats_p_allocated -= allo;
fs->stats_p_deleted -= dele;
return res;
}
// Finds block candidates to erase
s32_t spiffs_gc_find_candidate(
spiffs *fs,
spiffs_block_ix **block_candidates,
int *candidate_count,
char fs_crammed) {
s32_t res = SPIFFS_OK;
u32_t blocks = fs->block_count;
spiffs_block_ix cur_block = 0;
u32_t cur_block_addr = 0;
spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
int cur_entry = 0;
// using fs->work area as sorted candidate memory, (spiffs_block_ix)cand_bix/(s32_t)score
int max_candidates = MIN(fs->block_count, (SPIFFS_CFG_LOG_PAGE_SZ(fs)-8)/(sizeof(spiffs_block_ix) + sizeof(s32_t)));
*candidate_count = 0;
memset(fs->work, 0xff, SPIFFS_CFG_LOG_PAGE_SZ(fs));
// divide up work area into block indices and scores
spiffs_block_ix *cand_blocks = (spiffs_block_ix *)fs->work;
s32_t *cand_scores = (s32_t *)(fs->work + max_candidates * sizeof(spiffs_block_ix));
// align cand_scores on s32_t boundary
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
cand_scores = (s32_t*)(((ptrdiff_t)cand_scores + sizeof(ptrdiff_t) - 1) & ~(sizeof(ptrdiff_t) - 1));
#pragma GCC diagnostic pop
*block_candidates = cand_blocks;
int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
// check each block
while (res == SPIFFS_OK && blocks--) {
u16_t deleted_pages_in_block = 0;
u16_t used_pages_in_block = 0;
int obj_lookup_page = 0;
// check each object lookup page
while (res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
int entry_offset = obj_lookup_page * entries_per_page;
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
0, cur_block_addr + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
// check each entry
while (res == SPIFFS_OK &&
cur_entry - entry_offset < entries_per_page &&
cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))) {
spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset];
if (obj_id == SPIFFS_OBJ_ID_FREE) {
// when a free entry is encountered, scan logic ensures that all following entries are free also
res = 1; // kill object lu loop
break;
} else if (obj_id == SPIFFS_OBJ_ID_DELETED) {
deleted_pages_in_block++;
} else {
used_pages_in_block++;
}
cur_entry++;
} // per entry
obj_lookup_page++;
} // per object lookup page
if (res == 1) res = SPIFFS_OK;
// calculate score and insert into candidate table
// stoneage sort, but probably not so many blocks
if (res == SPIFFS_OK && deleted_pages_in_block > 0) {
// read erase count
spiffs_obj_id erase_count;
res = _spiffs_rd(fs, SPIFFS_OP_C_READ | SPIFFS_OP_T_OBJ_LU2, 0,
SPIFFS_ERASE_COUNT_PADDR(fs, cur_block),
sizeof(spiffs_obj_id), (u8_t *)&erase_count);
SPIFFS_CHECK_RES(res);
spiffs_obj_id erase_age;
if (fs->max_erase_count > erase_count) {
erase_age = fs->max_erase_count - erase_count;
} else {
erase_age = SPIFFS_OBJ_ID_FREE - (erase_count - fs->max_erase_count);
}
s32_t score =
deleted_pages_in_block * SPIFFS_GC_HEUR_W_DELET +
used_pages_in_block * SPIFFS_GC_HEUR_W_USED +
erase_age * (fs_crammed ? 0 : SPIFFS_GC_HEUR_W_ERASE_AGE);
int cand_ix = 0;
SPIFFS_GC_DBG("gc_check: bix:%i del:%i use:%i score:%i\n", cur_block, deleted_pages_in_block, used_pages_in_block, score);
while (cand_ix < max_candidates) {
if (cand_blocks[cand_ix] == (spiffs_block_ix)-1) {
cand_blocks[cand_ix] = cur_block;
cand_scores[cand_ix] = score;
break;
} else if (cand_scores[cand_ix] < score) {
int reorder_cand_ix = max_candidates - 2;
while (reorder_cand_ix >= cand_ix) {
cand_blocks[reorder_cand_ix + 1] = cand_blocks[reorder_cand_ix];
cand_scores[reorder_cand_ix + 1] = cand_scores[reorder_cand_ix];
reorder_cand_ix--;
}
cand_blocks[cand_ix] = cur_block;
cand_scores[cand_ix] = score;
break;
}
cand_ix++;
}
(*candidate_count)++;
}
cur_entry = 0;
cur_block++;
cur_block_addr += SPIFFS_CFG_LOG_BLOCK_SZ(fs);
} // per block
return res;
}
typedef enum {
FIND_OBJ_DATA,
MOVE_OBJ_DATA,
MOVE_OBJ_IX,
FINISHED
} spiffs_gc_clean_state;
typedef struct {
spiffs_gc_clean_state state;
spiffs_obj_id cur_obj_id;
spiffs_span_ix cur_objix_spix;
spiffs_page_ix cur_objix_pix;
int stored_scan_entry_index;
u8_t obj_id_found;
} spiffs_gc;
// Empties given block by moving all data into free pages of another block
// Strategy:
// loop:
// scan object lookup for object data pages
// for first found id, check spix and load corresponding object index page to memory
// push object scan lookup entry index
// rescan object lookup, find data pages with same id and referenced by same object index
// move data page, update object index in memory
// when reached end of lookup, store updated object index
// pop object scan lookup entry index
// repeat loop until end of object lookup
// scan object lookup again for remaining object index pages, move to new page in other block
//
s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {
s32_t res = SPIFFS_OK;
int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
int cur_entry = 0;
spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
spiffs_gc gc;
spiffs_page_ix cur_pix = 0;
spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
spiffs_page_object_ix *objix = (spiffs_page_object_ix *)fs->work;
SPIFFS_GC_DBG("gc_clean: cleaning block %i\n", bix);
memset(&gc, 0, sizeof(spiffs_gc));
gc.state = FIND_OBJ_DATA;
if (fs->free_cursor_block_ix == bix) {
// move free cursor to next block, cannot use free pages from the block we want to clean
fs->free_cursor_block_ix = (bix+1)%fs->block_count;
fs->free_cursor_obj_lu_entry = 0;
SPIFFS_GC_DBG("gc_clean: move free cursor to block %i\n", fs->free_cursor_block_ix);
}
while (res == SPIFFS_OK && gc.state != FINISHED) {
SPIFFS_GC_DBG("gc_clean: state = %i entry:%i\n", gc.state, cur_entry);
gc.obj_id_found = 0;
// scan through lookup pages
int obj_lookup_page = cur_entry / entries_per_page;
u8_t scan = 1;
// check each object lookup page
while (scan && res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
int entry_offset = obj_lookup_page * entries_per_page;
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page),
SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
// check each entry
while (scan && res == SPIFFS_OK &&
cur_entry - entry_offset < entries_per_page && cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))) {
spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset];
cur_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, cur_entry);
// act upon object id depending on gc state
switch (gc.state) {
case FIND_OBJ_DATA:
if (obj_id != SPIFFS_OBJ_ID_DELETED && obj_id != SPIFFS_OBJ_ID_FREE &&
((obj_id & SPIFFS_OBJ_ID_IX_FLAG) == 0)) {
SPIFFS_GC_DBG("gc_clean: FIND_DATA state:%i - found obj id %04x\n", gc.state, obj_id);
gc.obj_id_found = 1;
gc.cur_obj_id = obj_id;
scan = 0;
}
break;
case MOVE_OBJ_DATA:
if (obj_id == gc.cur_obj_id) {
spiffs_page_header p_hdr;
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr);
SPIFFS_CHECK_RES(res);
SPIFFS_GC_DBG("gc_clean: MOVE_DATA found data page %04x:%04x @ %04x\n", gc.cur_obj_id, p_hdr.span_ix, cur_pix);
if (SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, p_hdr.span_ix) != gc.cur_objix_spix) {
SPIFFS_GC_DBG("gc_clean: MOVE_DATA no objix spix match, take in another run\n");
} else {
spiffs_page_ix new_data_pix;
if (p_hdr.flags & SPIFFS_PH_FLAG_DELET) {
// move page
res = spiffs_page_move(fs, 0, 0, obj_id, &p_hdr, cur_pix, &new_data_pix);
SPIFFS_GC_DBG("gc_clean: MOVE_DATA move objix %04x:%04x page %04x to %04x\n", gc.cur_obj_id, p_hdr.span_ix, cur_pix, new_data_pix);
SPIFFS_CHECK_RES(res);
// move wipes obj_lu, reload it
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page),
SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
SPIFFS_CHECK_RES(res);
} else {
// page is deleted but not deleted in lookup, scrap it
SPIFFS_GC_DBG("gc_clean: MOVE_DATA wipe objix %04x:%04x page %04x\n", obj_id, p_hdr.span_ix, cur_pix);
res = spiffs_page_delete(fs, cur_pix);
SPIFFS_CHECK_RES(res);
new_data_pix = SPIFFS_OBJ_ID_FREE;
}
// update memory representation of object index page with new data page
if (gc.cur_objix_spix == 0) {
// update object index header page
((spiffs_page_ix*)((u8_t *)objix_hdr + sizeof(spiffs_page_object_ix_header)))[p_hdr.span_ix] = new_data_pix;
SPIFFS_GC_DBG("gc_clean: MOVE_DATA wrote page %04x to objix_hdr entry %02x in mem\n", new_data_pix, SPIFFS_OBJ_IX_ENTRY(fs, p_hdr.span_ix));
} else {
// update object index page
((spiffs_page_ix*)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, p_hdr.span_ix)] = new_data_pix;
SPIFFS_GC_DBG("gc_clean: MOVE_DATA wrote page %04x to objix entry %02x in mem\n", new_data_pix, SPIFFS_OBJ_IX_ENTRY(fs, p_hdr.span_ix));
}
}
}
break;
case MOVE_OBJ_IX:
if (obj_id != SPIFFS_OBJ_ID_DELETED && obj_id != SPIFFS_OBJ_ID_FREE &&
(obj_id & SPIFFS_OBJ_ID_IX_FLAG)) {
// found an index object id
spiffs_page_header p_hdr;
spiffs_page_ix new_pix;
// load header
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr);
SPIFFS_CHECK_RES(res);
if (p_hdr.flags & SPIFFS_PH_FLAG_DELET) {
// move page
res = spiffs_page_move(fs, 0, 0, obj_id, &p_hdr, cur_pix, &new_pix);
SPIFFS_GC_DBG("gc_clean: MOVE_OBJIX move objix %04x:%04x page %04x to %04x\n", obj_id, p_hdr.span_ix, cur_pix, new_pix);
SPIFFS_CHECK_RES(res);
spiffs_cb_object_event(fs, 0, SPIFFS_EV_IX_UPD, obj_id, p_hdr.span_ix, new_pix, 0);
// move wipes obj_lu, reload it
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page),
SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
SPIFFS_CHECK_RES(res);
} else {
// page is deleted but not deleted in lookup, scrap it
SPIFFS_GC_DBG("gc_clean: MOVE_OBJIX wipe objix %04x:%04x page %04x\n", obj_id, p_hdr.span_ix, cur_pix);
res = spiffs_page_delete(fs, cur_pix);
if (res == SPIFFS_OK) {
spiffs_cb_object_event(fs, 0, SPIFFS_EV_IX_DEL, obj_id, p_hdr.span_ix, cur_pix, 0);
}
}
SPIFFS_CHECK_RES(res);
}
break;
default:
scan = 0;
break;
}
cur_entry++;
} // per entry
obj_lookup_page++;
} // per object lookup page
if (res != SPIFFS_OK) break;
// state finalization and switch
switch (gc.state) {
case FIND_OBJ_DATA:
if (gc.obj_id_found) {
// find out corresponding obj ix page and load it to memory
spiffs_page_header p_hdr;
spiffs_page_ix objix_pix;
gc.stored_scan_entry_index = cur_entry;
cur_entry = 0;
gc.state = MOVE_OBJ_DATA;
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr);
SPIFFS_CHECK_RES(res);
gc.cur_objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, p_hdr.span_ix);
SPIFFS_GC_DBG("gc_clean: FIND_DATA find objix span_ix:%04x\n", gc.cur_objix_spix);
res = spiffs_obj_lu_find_id_and_span(fs, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, gc.cur_objix_spix, 0, &objix_pix);
SPIFFS_CHECK_RES(res);
SPIFFS_GC_DBG("gc_clean: FIND_DATA found object index at page %04x\n", objix_pix);
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
0, SPIFFS_PAGE_TO_PADDR(fs, objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
SPIFFS_CHECK_RES(res);
SPIFFS_VALIDATE_OBJIX(objix->p_hdr, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, gc.cur_objix_spix);
gc.cur_objix_pix = objix_pix;
} else {
gc.state = MOVE_OBJ_IX;
cur_entry = 0; // restart entry scan index
}
break;
case MOVE_OBJ_DATA: {
// store modified objix (hdr) page
spiffs_page_ix new_objix_pix;
gc.state = FIND_OBJ_DATA;
cur_entry = gc.stored_scan_entry_index;
if (gc.cur_objix_spix == 0) {
// store object index header page
res = spiffs_object_update_index_hdr(fs, 0, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, gc.cur_objix_pix, fs->work, 0, 0, &new_objix_pix);
SPIFFS_GC_DBG("gc_clean: MOVE_DATA store modified objix_hdr page, %04x:%04x\n", new_objix_pix, 0);
SPIFFS_CHECK_RES(res);
} else {
// store object index page
res = spiffs_page_move(fs, 0, fs->work, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, gc.cur_objix_pix, &new_objix_pix);
SPIFFS_GC_DBG("gc_clean: MOVE_DATA store modified objix page, %04x:%04x\n", new_objix_pix, objix->p_hdr.span_ix);
SPIFFS_CHECK_RES(res);
spiffs_cb_object_event(fs, 0, SPIFFS_EV_IX_UPD, gc.cur_obj_id, objix->p_hdr.span_ix, new_objix_pix, 0);
}
}
break;
case MOVE_OBJ_IX:
gc.state = FINISHED;
break;
default:
cur_entry = 0;
break;
}
SPIFFS_GC_DBG("gc_clean: state-> %i\n", gc.state);
} // while state != FINISHED
return res;
}
#endif // !SPIFFS_READ_ONLY

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,751 +0,0 @@
/*
* spiffs_nucleus.h
*
* Created on: Jun 15, 2013
* Author: petera
*/
/* SPIFFS layout
*
* spiffs is designed for following spi flash characteristics:
* - only big areas of data (blocks) can be erased
* - erasing resets all bits in a block to ones
* - writing pulls ones to zeroes
* - zeroes cannot be pulled to ones, without erase
* - wear leveling
*
* spiffs is also meant to be run on embedded, memory constraint devices.
*
* Entire area is divided in blocks. Entire area is also divided in pages.
* Each block contains same number of pages. A page cannot be erased, but a
* block can be erased.
*
* Entire area must be block_size * x
* page_size must be block_size / (2^y) where y > 2
*
* ex: area = 1024*1024 bytes, block size = 65536 bytes, page size = 256 bytes
*
* BLOCK 0 PAGE 0 object lookup 1
* PAGE 1 object lookup 2
* ...
* PAGE n-1 object lookup n
* PAGE n object data 1
* PAGE n+1 object data 2
* ...
* PAGE n+m-1 object data m
*
* BLOCK 1 PAGE n+m object lookup 1
* PAGE n+m+1 object lookup 2
* ...
* PAGE 2n+m-1 object lookup n
* PAGE 2n+m object data 1
* PAGE 2n+m object data 2
* ...
* PAGE 2n+2m-1 object data m
* ...
*
* n is number of object lookup pages, which is number of pages needed to index all pages
* in a block by object id
* : block_size / page_size * sizeof(obj_id) / page_size
* m is number data pages, which is number of pages in block minus number of lookup pages
* : block_size / page_size - block_size / page_size * sizeof(obj_id) / page_size
* thus, n+m is total number of pages in a block
* : block_size / page_size
*
* ex: n = 65536/256*2/256 = 2, m = 65536/256 - 2 = 254 => n+m = 65536/256 = 256
*
* Object lookup pages contain object id entries. Each entry represent the corresponding
* data page.
* Assuming a 16 bit object id, an object id being 0xffff represents a free page.
* An object id being 0x0000 represents a deleted page.
*
* ex: page 0 : lookup : 0008 0001 0aaa ffff ffff ffff ffff ffff ..
* page 1 : lookup : ffff ffff ffff ffff ffff ffff ffff ffff ..
* page 2 : data : data for object id 0008
* page 3 : data : data for object id 0001
* page 4 : data : data for object id 0aaa
* ...
*
*
* Object data pages can be either object index pages or object content.
* All object data pages contains a data page header, containing object id and span index.
* The span index denotes the object page ordering amongst data pages with same object id.
* This applies to both object index pages (when index spans more than one page of entries),
* and object data pages.
* An object index page contains page entries pointing to object content page. The entry index
* in a object index page correlates to the span index in the actual object data page.
* The first object index page (span index 0) is called object index header page, and also
* contains object flags (directory/file), size, object name etc.
*
* ex:
* BLOCK 1
* PAGE 256: objectl lookup page 1
* [*123] [ 123] [ 123] [ 123]
* [ 123] [*123] [ 123] [ 123]
* [free] [free] [free] [free] ...
* PAGE 257: objectl lookup page 2
* [free] [free] [free] [free] ...
* PAGE 258: object index page (header)
* obj.id:0123 span.ix:0000 flags:INDEX
* size:1600 name:ex.txt type:file
* [259] [260] [261] [262]
* PAGE 259: object data page
* obj.id:0123 span.ix:0000 flags:DATA
* PAGE 260: object data page
* obj.id:0123 span.ix:0001 flags:DATA
* PAGE 261: object data page
* obj.id:0123 span.ix:0002 flags:DATA
* PAGE 262: object data page
* obj.id:0123 span.ix:0003 flags:DATA
* PAGE 263: object index page
* obj.id:0123 span.ix:0001 flags:INDEX
* [264] [265] [fre] [fre]
* [fre] [fre] [fre] [fre]
* PAGE 264: object data page
* obj.id:0123 span.ix:0004 flags:DATA
* PAGE 265: object data page
* obj.id:0123 span.ix:0005 flags:DATA
*
*/
#ifndef SPIFFS_NUCLEUS_H_
#define SPIFFS_NUCLEUS_H_
#define _SPIFFS_ERR_CHECK_FIRST (SPIFFS_ERR_INTERNAL - 1)
#define SPIFFS_ERR_CHECK_OBJ_ID_MISM (SPIFFS_ERR_INTERNAL - 1)
#define SPIFFS_ERR_CHECK_SPIX_MISM (SPIFFS_ERR_INTERNAL - 2)
#define SPIFFS_ERR_CHECK_FLAGS_BAD (SPIFFS_ERR_INTERNAL - 3)
#define _SPIFFS_ERR_CHECK_LAST (SPIFFS_ERR_INTERNAL - 4)
#define SPIFFS_VIS_COUNTINUE (SPIFFS_ERR_INTERNAL - 20)
#define SPIFFS_VIS_COUNTINUE_RELOAD (SPIFFS_ERR_INTERNAL - 21)
#define SPIFFS_VIS_END (SPIFFS_ERR_INTERNAL - 22)
#define SPIFFS_EV_IX_UPD 0
#define SPIFFS_EV_IX_NEW 1
#define SPIFFS_EV_IX_DEL 2
#define SPIFFS_OBJ_ID_IX_FLAG ((spiffs_obj_id)(1<<(8*sizeof(spiffs_obj_id)-1)))
#define SPIFFS_UNDEFINED_LEN (u32_t)(-1)
#define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0)
#define SPIFFS_OBJ_ID_FREE ((spiffs_obj_id)-1)
#if SPIFFS_USE_MAGIC
#if !SPIFFS_USE_MAGIC_LENGTH
#define SPIFFS_MAGIC(fs, bix) \
((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs)))
#else // SPIFFS_USE_MAGIC_LENGTH
#define SPIFFS_MAGIC(fs, bix) \
((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs) ^ ((fs)->block_count - (bix))))
#endif // SPIFFS_USE_MAGIC_LENGTH
#endif // SPIFFS_USE_MAGIC
#define SPIFFS_CONFIG_MAGIC (0x20090315)
#if SPIFFS_SINGLETON == 0
#define SPIFFS_CFG_LOG_PAGE_SZ(fs) \
((fs)->cfg.log_page_size)
#define SPIFFS_CFG_LOG_BLOCK_SZ(fs) \
((fs)->cfg.log_block_size)
#define SPIFFS_CFG_PHYS_SZ(fs) \
((fs)->cfg.phys_size)
#define SPIFFS_CFG_PHYS_ERASE_SZ(fs) \
((fs)->cfg.phys_erase_block)
#define SPIFFS_CFG_PHYS_ADDR(fs) \
((fs)->cfg.phys_addr)
#endif
// total number of pages
#define SPIFFS_MAX_PAGES(fs) \
( SPIFFS_CFG_PHYS_SZ(fs)/SPIFFS_CFG_LOG_PAGE_SZ(fs) )
// total number of pages per block, including object lookup pages
#define SPIFFS_PAGES_PER_BLOCK(fs) \
( SPIFFS_CFG_LOG_BLOCK_SZ(fs)/SPIFFS_CFG_LOG_PAGE_SZ(fs) )
// number of object lookup pages per block
#define SPIFFS_OBJ_LOOKUP_PAGES(fs) \
(MAX(1, (SPIFFS_PAGES_PER_BLOCK(fs) * sizeof(spiffs_obj_id)) / SPIFFS_CFG_LOG_PAGE_SZ(fs)) )
// checks if page index belongs to object lookup
#define SPIFFS_IS_LOOKUP_PAGE(fs,pix) \
(((pix) % SPIFFS_PAGES_PER_BLOCK(fs)) < SPIFFS_OBJ_LOOKUP_PAGES(fs))
// number of object lookup entries in all object lookup pages
#define SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) \
(SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))
// converts a block to physical address
#define SPIFFS_BLOCK_TO_PADDR(fs, block) \
( SPIFFS_CFG_PHYS_ADDR(fs) + (block)* SPIFFS_CFG_LOG_BLOCK_SZ(fs) )
// converts a object lookup entry to page index
#define SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, block, entry) \
((block)*SPIFFS_PAGES_PER_BLOCK(fs) + (SPIFFS_OBJ_LOOKUP_PAGES(fs) + entry))
// converts a object lookup entry to physical address of corresponding page
#define SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, block, entry) \
(SPIFFS_BLOCK_TO_PADDR(fs, block) + (SPIFFS_OBJ_LOOKUP_PAGES(fs) + entry) * SPIFFS_CFG_LOG_PAGE_SZ(fs) )
// converts a page to physical address
#define SPIFFS_PAGE_TO_PADDR(fs, page) \
( SPIFFS_CFG_PHYS_ADDR(fs) + (page) * SPIFFS_CFG_LOG_PAGE_SZ(fs) )
// converts a physical address to page
#define SPIFFS_PADDR_TO_PAGE(fs, addr) \
( ((addr) - SPIFFS_CFG_PHYS_ADDR(fs)) / SPIFFS_CFG_LOG_PAGE_SZ(fs) )
// gives index in page for a physical address
#define SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr) \
( ((addr) - SPIFFS_CFG_PHYS_ADDR(fs)) % SPIFFS_CFG_LOG_PAGE_SZ(fs) )
// returns containing block for given page
#define SPIFFS_BLOCK_FOR_PAGE(fs, page) \
( (page) / SPIFFS_PAGES_PER_BLOCK(fs) )
// returns starting page for block
#define SPIFFS_PAGE_FOR_BLOCK(fs, block) \
( (block) * SPIFFS_PAGES_PER_BLOCK(fs) )
// converts page to entry in object lookup page
#define SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, page) \
( (page) % SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs) )
// returns data size in a data page
#define SPIFFS_DATA_PAGE_SIZE(fs) \
( SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header) )
// returns physical address for block's erase count,
// always in the physical last entry of the last object lookup page
#define SPIFFS_ERASE_COUNT_PADDR(fs, bix) \
( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id) )
// returns physical address for block's magic,
// always in the physical second last entry of the last object lookup page
#define SPIFFS_MAGIC_PADDR(fs, bix) \
( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id)*2 )
// checks if there is any room for magic in the object luts
#define SPIFFS_CHECK_MAGIC_POSSIBLE(fs) \
( (SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) % (SPIFFS_CFG_LOG_PAGE_SZ(fs)/sizeof(spiffs_obj_id))) * sizeof(spiffs_obj_id) \
<= (SPIFFS_CFG_LOG_PAGE_SZ(fs)-sizeof(spiffs_obj_id)*2) )
// define helpers object
// entries in an object header page index
#define SPIFFS_OBJ_HDR_IX_LEN(fs) \
((SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix_header))/sizeof(spiffs_page_ix))
// entries in an object page index
#define SPIFFS_OBJ_IX_LEN(fs) \
((SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix))/sizeof(spiffs_page_ix))
// object index entry for given data span index
#define SPIFFS_OBJ_IX_ENTRY(fs, spix) \
((spix) < SPIFFS_OBJ_HDR_IX_LEN(fs) ? (spix) : (((spix)-SPIFFS_OBJ_HDR_IX_LEN(fs))%SPIFFS_OBJ_IX_LEN(fs)))
// object index span index number for given data span index or entry
#define SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, spix) \
((spix) < SPIFFS_OBJ_HDR_IX_LEN(fs) ? 0 : (1+((spix)-SPIFFS_OBJ_HDR_IX_LEN(fs))/SPIFFS_OBJ_IX_LEN(fs)))
#define SPIFFS_OP_T_OBJ_LU (0<<0)
#define SPIFFS_OP_T_OBJ_LU2 (1<<0)
#define SPIFFS_OP_T_OBJ_IX (2<<0)
#define SPIFFS_OP_T_OBJ_DA (3<<0)
#define SPIFFS_OP_C_DELE (0<<2)
#define SPIFFS_OP_C_UPDT (1<<2)
#define SPIFFS_OP_C_MOVS (2<<2)
#define SPIFFS_OP_C_MOVD (3<<2)
#define SPIFFS_OP_C_FLSH (4<<2)
#define SPIFFS_OP_C_READ (5<<2)
#define SPIFFS_OP_C_WRTHRU (6<<2)
#define SPIFFS_OP_TYPE_MASK (3<<0)
#define SPIFFS_OP_COM_MASK (7<<2)
// if 0, this page is written to, else clean
#define SPIFFS_PH_FLAG_USED (1<<0)
// if 0, writing is finalized, else under modification
#define SPIFFS_PH_FLAG_FINAL (1<<1)
// if 0, this is an index page, else a data page
#define SPIFFS_PH_FLAG_INDEX (1<<2)
// if 0, page is deleted, else valid
#define SPIFFS_PH_FLAG_DELET (1<<7)
// if 0, this index header is being deleted
#define SPIFFS_PH_FLAG_IXDELE (1<<6)
#define SPIFFS_CHECK_MOUNT(fs) \
((fs)->mounted != 0)
#define SPIFFS_CHECK_CFG(fs) \
((fs)->config_magic == SPIFFS_CONFIG_MAGIC)
#define SPIFFS_CHECK_RES(res) \
do { \
if ((res) < SPIFFS_OK) return (res); \
} while (0);
#define SPIFFS_API_CHECK_MOUNT(fs) \
if (!SPIFFS_CHECK_MOUNT((fs))) { \
(fs)->err_code = SPIFFS_ERR_NOT_MOUNTED; \
return -1; \
}
#define SPIFFS_API_CHECK_CFG(fs) \
if (!SPIFFS_CHECK_CFG((fs))) { \
(fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED; \
return -1; \
}
#define SPIFFS_API_CHECK_RES(fs, res) \
if ((res) < SPIFFS_OK) { \
(fs)->err_code = (res); \
return -1; \
}
#define SPIFFS_API_CHECK_RES_UNLOCK(fs, res) \
if ((res) < SPIFFS_OK) { \
(fs)->err_code = (res); \
SPIFFS_UNLOCK(fs); \
return -1; \
}
#define SPIFFS_VALIDATE_OBJIX(ph, objid, spix) \
if (((ph).flags & SPIFFS_PH_FLAG_USED) != 0) return SPIFFS_ERR_IS_FREE; \
if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \
if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \
if (((ph).flags & SPIFFS_PH_FLAG_INDEX) != 0) return SPIFFS_ERR_NOT_INDEX; \
if (((objid) & SPIFFS_OBJ_ID_IX_FLAG) == 0) return SPIFFS_ERR_NOT_INDEX; \
if ((ph).span_ix != (spix)) return SPIFFS_ERR_INDEX_SPAN_MISMATCH;
//if ((spix) == 0 && ((ph).flags & SPIFFS_PH_FLAG_IXDELE) == 0) return SPIFFS_ERR_DELETED;
#define SPIFFS_VALIDATE_DATA(ph, objid, spix) \
if (((ph).flags & SPIFFS_PH_FLAG_USED) != 0) return SPIFFS_ERR_IS_FREE; \
if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \
if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \
if (((ph).flags & SPIFFS_PH_FLAG_INDEX) == 0) return SPIFFS_ERR_IS_INDEX; \
if ((objid) & SPIFFS_OBJ_ID_IX_FLAG) return SPIFFS_ERR_IS_INDEX; \
if ((ph).span_ix != (spix)) return SPIFFS_ERR_DATA_SPAN_MISMATCH;
// check id
#define SPIFFS_VIS_CHECK_ID (1<<0)
// report argument object id to visitor - else object lookup id is reported
#define SPIFFS_VIS_CHECK_PH (1<<1)
// stop searching at end of all look up pages
#define SPIFFS_VIS_NO_WRAP (1<<2)
#if SPIFFS_HAL_CALLBACK_EXTRA
#define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \
(_fs)->cfg.hal_write_f((_fs), (_paddr), (_len), (_src))
#define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \
(_fs)->cfg.hal_read_f((_fs), (_paddr), (_len), (_dst))
#define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \
(_fs)->cfg.hal_erase_f((_fs), (_paddr), (_len))
#else // SPIFFS_HAL_CALLBACK_EXTRA
#define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \
(_fs)->cfg.hal_write_f((_paddr), (_len), (_src))
#define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \
(_fs)->cfg.hal_read_f((_paddr), (_len), (_dst))
#define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \
(_fs)->cfg.hal_erase_f((_paddr), (_len))
#endif // SPIFFS_HAL_CALLBACK_EXTRA
#if SPIFFS_CACHE
#define SPIFFS_CACHE_FLAG_DIRTY (1<<0)
#define SPIFFS_CACHE_FLAG_WRTHRU (1<<1)
#define SPIFFS_CACHE_FLAG_OBJLU (1<<2)
#define SPIFFS_CACHE_FLAG_OBJIX (1<<3)
#define SPIFFS_CACHE_FLAG_DATA (1<<4)
#define SPIFFS_CACHE_FLAG_TYPE_WR (1<<7)
#define SPIFFS_CACHE_PAGE_SIZE(fs) \
(sizeof(spiffs_cache_page) + SPIFFS_CFG_LOG_PAGE_SZ(fs))
#define spiffs_get_cache(fs) \
((spiffs_cache *)((fs)->cache))
#define spiffs_get_cache_page_hdr(fs, c, ix) \
((spiffs_cache_page *)(&((c)->cpages[(ix) * SPIFFS_CACHE_PAGE_SIZE(fs)])))
#define spiffs_get_cache_page(fs, c, ix) \
((u8_t *)(&((c)->cpages[(ix) * SPIFFS_CACHE_PAGE_SIZE(fs)])) + sizeof(spiffs_cache_page))
// cache page struct
typedef struct {
// cache flags
u8_t flags;
// cache page index
u8_t ix;
// last access of this cache page
u32_t last_access;
union {
// type read cache
struct {
// read cache page index
spiffs_page_ix pix;
};
#if SPIFFS_CACHE_WR
// type write cache
struct {
// write cache
spiffs_obj_id obj_id;
// offset in cache page
u32_t offset;
// size of cache page
u16_t size;
};
#endif
};
} spiffs_cache_page;
// cache struct
typedef struct {
u8_t cpage_count;
u32_t last_access;
u32_t cpage_use_map;
u32_t cpage_use_mask;
u8_t *cpages;
} spiffs_cache;
#endif
// spiffs nucleus file descriptor
typedef struct {
// the filesystem of this descriptor
spiffs *fs;
// number of file descriptor - if 0, the file descriptor is closed
spiffs_file file_nbr;
// object id - if SPIFFS_OBJ_ID_ERASED, the file was deleted
spiffs_obj_id obj_id;
// size of the file
u32_t size;
// cached object index header page index
spiffs_page_ix objix_hdr_pix;
// cached offset object index page index
spiffs_page_ix cursor_objix_pix;
// cached offset object index span index
spiffs_span_ix cursor_objix_spix;
// current absolute offset
u32_t offset;
// current file descriptor offset
u32_t fdoffset;
// fd flags
spiffs_flags flags;
#if SPIFFS_CACHE_WR
spiffs_cache_page *cache_page;
#endif
} spiffs_fd;
// object structs
// page header, part of each page except object lookup pages
// NB: this is always aligned when the data page is an object index,
// as in this case struct spiffs_page_object_ix is used
typedef struct __attribute(( packed )) {
// object id
spiffs_obj_id obj_id;
// object span index
spiffs_span_ix span_ix;
// flags
u8_t flags;
} spiffs_page_header;
// object index header page header
typedef struct __attribute(( packed ))
#if SPIFFS_ALIGNED_OBJECT_INDEX_TABLES
__attribute(( aligned(sizeof(spiffs_page_ix)) ))
#endif
{
// common page header
spiffs_page_header p_hdr;
// alignment
u8_t _align[4 - ((sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3))];
// size of object
u32_t size;
// type of object
spiffs_obj_type type;
// name of object
u8_t name[SPIFFS_OBJ_NAME_LEN];
} spiffs_page_object_ix_header;
// object index page header
typedef struct __attribute(( packed )) {
spiffs_page_header p_hdr;
u8_t _align[4 - ((sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3))];
} spiffs_page_object_ix;
// callback func for object lookup visitor
typedef s32_t (*spiffs_visitor_f)(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry,
const void *user_const_p, void *user_var_p);
#if SPIFFS_CACHE
#define _spiffs_rd(fs, op, fh, addr, len, dst) \
spiffs_phys_rd((fs), (op), (fh), (addr), (len), (dst))
#define _spiffs_wr(fs, op, fh, addr, len, src) \
spiffs_phys_wr((fs), (op), (fh), (addr), (len), (src))
#else
#define _spiffs_rd(fs, op, fh, addr, len, dst) \
spiffs_phys_rd((fs), (addr), (len), (dst))
#define _spiffs_wr(fs, op, fh, addr, len, src) \
spiffs_phys_wr((fs), (addr), (len), (src))
#endif
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
// ---------------
s32_t spiffs_phys_rd(
spiffs *fs,
#if SPIFFS_CACHE
u8_t op,
spiffs_file fh,
#endif
u32_t addr,
u32_t len,
u8_t *dst);
s32_t spiffs_phys_wr(
spiffs *fs,
#if SPIFFS_CACHE
u8_t op,
spiffs_file fh,
#endif
u32_t addr,
u32_t len,
u8_t *src);
s32_t spiffs_phys_cpy(
spiffs *fs,
spiffs_file fh,
u32_t dst,
u32_t src,
u32_t len);
s32_t spiffs_phys_count_free_blocks(
spiffs *fs);
s32_t spiffs_obj_lu_find_entry_visitor(
spiffs *fs,
spiffs_block_ix starting_block,
int starting_lu_entry,
u8_t flags,
spiffs_obj_id obj_id,
spiffs_visitor_f v,
const void *user_const_p,
void *user_var_p,
spiffs_block_ix *block_ix,
int *lu_entry);
s32_t spiffs_erase_block(
spiffs *fs,
spiffs_block_ix bix);
#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
s32_t spiffs_probe(
spiffs_config *cfg);
#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
// ---------------
s32_t spiffs_obj_lu_scan(
spiffs *fs);
s32_t spiffs_obj_lu_find_free_obj_id(
spiffs *fs,
spiffs_obj_id *obj_id,
const u8_t *conflicting_name);
s32_t spiffs_obj_lu_find_free(
spiffs *fs,
spiffs_block_ix starting_block,
int starting_lu_entry,
spiffs_block_ix *block_ix,
int *lu_entry);
s32_t spiffs_obj_lu_find_id(
spiffs *fs,
spiffs_block_ix starting_block,
int starting_lu_entry,
spiffs_obj_id obj_id,
spiffs_block_ix *block_ix,
int *lu_entry);
s32_t spiffs_obj_lu_find_id_and_span(
spiffs *fs,
spiffs_obj_id obj_id,
spiffs_span_ix spix,
spiffs_page_ix exclusion_pix,
spiffs_page_ix *pix);
s32_t spiffs_obj_lu_find_id_and_span_by_phdr(
spiffs *fs,
spiffs_obj_id obj_id,
spiffs_span_ix spix,
spiffs_page_ix exclusion_pix,
spiffs_page_ix *pix);
// ---------------
s32_t spiffs_page_allocate_data(
spiffs *fs,
spiffs_obj_id obj_id,
spiffs_page_header *ph,
u8_t *data,
u32_t len,
u32_t page_offs,
u8_t finalize,
spiffs_page_ix *pix);
s32_t spiffs_page_move(
spiffs *fs,
spiffs_file fh,
u8_t *page_data,
spiffs_obj_id obj_id,
spiffs_page_header *page_hdr,
spiffs_page_ix src_pix,
spiffs_page_ix *dst_pix);
s32_t spiffs_page_delete(
spiffs *fs,
spiffs_page_ix pix);
// ---------------
s32_t spiffs_object_create(
spiffs *fs,
spiffs_obj_id obj_id,
const u8_t name[SPIFFS_OBJ_NAME_LEN],
spiffs_obj_type type,
spiffs_page_ix *objix_hdr_pix);
s32_t spiffs_object_update_index_hdr(
spiffs *fs,
spiffs_fd *fd,
spiffs_obj_id obj_id,
spiffs_page_ix objix_hdr_pix,
u8_t *new_objix_hdr_data,
const u8_t name[SPIFFS_OBJ_NAME_LEN],
u32_t size,
spiffs_page_ix *new_pix);
void spiffs_cb_object_event(
spiffs *fs,
spiffs_fd *fd,
int ev,
spiffs_obj_id obj_id,
spiffs_span_ix spix,
spiffs_page_ix new_pix,
u32_t new_size);
s32_t spiffs_object_open_by_id(
spiffs *fs,
spiffs_obj_id obj_id,
spiffs_fd *f,
spiffs_flags flags,
spiffs_mode mode);
s32_t spiffs_object_open_by_page(
spiffs *fs,
spiffs_page_ix pix,
spiffs_fd *f,
spiffs_flags flags,
spiffs_mode mode);
s32_t spiffs_object_append(
spiffs_fd *fd,
u32_t offset,
u8_t *data,
u32_t len);
s32_t spiffs_object_modify(
spiffs_fd *fd,
u32_t offset,
u8_t *data,
u32_t len);
s32_t spiffs_object_read(
spiffs_fd *fd,
u32_t offset,
u32_t len,
u8_t *dst);
s32_t spiffs_object_truncate(
spiffs_fd *fd,
u32_t new_len,
u8_t remove_object);
s32_t spiffs_object_find_object_index_header_by_name(
spiffs *fs,
const u8_t name[SPIFFS_OBJ_NAME_LEN],
spiffs_page_ix *pix);
// ---------------
s32_t spiffs_gc_check(
spiffs *fs,
u32_t len);
s32_t spiffs_gc_erase_page_stats(
spiffs *fs,
spiffs_block_ix bix);
s32_t spiffs_gc_find_candidate(
spiffs *fs,
spiffs_block_ix **block_candidate,
int *candidate_count,
char fs_crammed);
s32_t spiffs_gc_clean(
spiffs *fs,
spiffs_block_ix bix);
s32_t spiffs_gc_quick(
spiffs *fs, u16_t max_free_pages);
// ---------------
s32_t spiffs_fd_find_new(
spiffs *fs,
spiffs_fd **fd);
s32_t spiffs_fd_return(
spiffs *fs,
spiffs_file f);
s32_t spiffs_fd_get(
spiffs *fs,
spiffs_file f,
spiffs_fd **fd);
#if SPIFFS_CACHE
void spiffs_cache_init(
spiffs *fs);
void spiffs_cache_drop_page(
spiffs *fs,
spiffs_page_ix pix);
#if SPIFFS_CACHE_WR
spiffs_cache_page *spiffs_cache_page_allocate_by_fd(
spiffs *fs,
spiffs_fd *fd);
void spiffs_cache_fd_release(
spiffs *fs,
spiffs_cache_page *cp);
spiffs_cache_page *spiffs_cache_page_get_by_fd(
spiffs *fs,
spiffs_fd *fd);
#endif
#endif
s32_t spiffs_lookup_consistency_check(
spiffs *fs,
u8_t check_all_objects);
s32_t spiffs_page_consistency_check(
spiffs *fs);
s32_t spiffs_object_index_consistency_check(
spiffs *fs);
#endif /* SPIFFS_NUCLEUS_H_ */

View File

@@ -1,131 +0,0 @@
#include "ssl_drv.h"
#ifdef __cplusplus
extern "C" {
#include "platform_stdlib.h"
}
#endif
uint16_t SSLDrv::availData(sslclient_context *ssl_client)
{
//int ret;
if (ssl_client->socket < 0) {
return 0;
}
if (_available) {
return 1;
} else {
return getData(ssl_client, c, 1);
}
}
bool SSLDrv::getData(sslclient_context *ssl_client, uint8_t *data, uint8_t peek)
{
int ret = 0;
int flag = 0;
if (_available) {
/* we already has data to read */
data[0] = c[0];
//if (peek) {
//} else {
// /* It's not peek and the data has been taken */
// _available = false;
//}
if (!peek) {
/* It's not peek and the data has been taken */
_available = false;
}
return true;
}
if (peek) {
flag |= 1;
}
ret = get_ssl_receive(ssl_client, c, 1, flag);
if (ret == 1) {
data[0] = c[0];
if (peek) {
_available = true;
} else {
_available = false;
}
return true;
}
return false;
}
int SSLDrv::getDataBuf(sslclient_context *ssl_client, uint8_t *_data, uint16_t _dataLen)
{
int ret;
if (_available) {
/* there is one byte cached */
_data[0] = c[0];
_available = false;
_dataLen--;
if (_dataLen > 0) {
ret = get_ssl_receive(ssl_client, _data, _dataLen, 0);
if (ret > 0) {
ret++;
return ret;
} else {
return 1;
}
} else {
return 1;
}
} else {
ret = get_ssl_receive(ssl_client, _data, _dataLen, 0);
}
return ret;
}
void SSLDrv::stopClient(sslclient_context *ssl_client)
{
stop_ssl_socket(ssl_client);
_available = false;
}
bool SSLDrv::sendData(sslclient_context *ssl_client, const uint8_t *data, uint16_t len)
{
int ret;
if (ssl_client->socket < 0) {
return false;
}
ret = send_ssl_data(ssl_client, data, len);
if (ret == 0) {
return false;
}
return true;
}
int SSLDrv::startClient(sslclient_context *ssl_client, uint32_t ipAddress, uint32_t port, unsigned char* rootCABuff, unsigned char* cli_cert, unsigned char* cli_key, unsigned char* pskIdent, unsigned char* psKey, char* SNI_hostname)
{
int ret;
ret = start_ssl_client(ssl_client, ipAddress, port, rootCABuff, cli_cert, cli_key, pskIdent, psKey, SNI_hostname);
return ret;
}
int SSLDrv::getLastErrno(sslclient_context *ssl_client)
{
return get_ssl_sock_errno(ssl_client);
}
int SSLDrv::setSockRecvTimeout(int sock, int timeout)
{
return setSockRecvTimeout(sock, timeout);
}

View File

@@ -1,33 +0,0 @@
#ifndef SSL_DRV_H
#define SSL_DRV_H
#include "Arduino.h"
#include <inttypes.h>
#define DATA_LENTH 128
#ifdef __cplusplus
extern "C" {
#include "ard_ssl.h"
}
#endif
class SSLDrv
{
public:
int startClient(sslclient_context *ssl_client, uint32_t ipAddress, uint32_t port, unsigned char* rootCABuff, unsigned char* cli_cert, unsigned char* cli_key, unsigned char* pskIdent, unsigned char* psKey, char* SNI_hostname);
void stopClient(sslclient_context *ssl_client);
bool getData(sslclient_context *ssl_client, uint8_t *data, uint8_t peek=0);
int getDataBuf(sslclient_context *ssl_client, uint8_t *_data, uint16_t _dataLen);
bool sendData(sslclient_context *ssl_client, const uint8_t *data, uint16_t len);
uint16_t availData(sslclient_context *ssl_client);
sslclient_context *init(void);
int getLastErrno(sslclient_context *ssl_client);
int setSockRecvTimeout(int sock, int timeout);
private:
bool _available;
uint8_t c[1];
};
#endif

View File

@@ -1,60 +0,0 @@
/*
Copyright (c) 2011 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
*/
/**
* \file syscalls.h
*
* Implementation of newlib syscall.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
extern caddr_t _sbrk( int incr ) ;
extern int link( char *cOld, char *cNew ) ;
extern int _close( int file ) ;
extern int _fstat( int file, struct stat *st ) ;
extern int _isatty( int file ) ;
extern int _lseek( int file, int ptr, int dir ) ;
extern int _read(int file, char *ptr, int len) ;
extern int _write( int file, char *ptr, int len ) ;
#ifdef __cplusplus
}
#endif

View File

@@ -1,492 +0,0 @@
#include "wifi_drv.h"
// arduino includes
#include "wl_definitions.h"
#include "wl_types.h"
#include "Arduino.h"
#ifdef __cplusplus
extern "C" {
// RTK includes
#include "main.h"
#include "wifi_conf.h"
#include "wifi_constants.h"
#include "wifi_structures.h"
#include "lwip_netconf.h"
#include "lwip/err.h"
#include "lwip/api.h"
#include <dhcp/dhcps.h>
extern struct netif xnetif[NET_IF_NUM];
}
#endif
// Array of data to cache the information related to the networks discovered
uint8_t WiFiDrv::_networkCount = 0;
char WiFiDrv::_networkSsid[][WL_SSID_MAX_LENGTH] = {{"1"},{"2"},{"3"},{"4"},{"5"}};
int32_t WiFiDrv::_networkRssi[WL_NETWORKS_LIST_MAXNUM] = { 0 };
uint32_t WiFiDrv::_networkEncr[WL_NETWORKS_LIST_MAXNUM] = { 0 };
static bool init_wlan = false;
static int wifi_mode = NULL;
static rtw_network_info_t wifi = {0};
static rtw_ap_info_t ap = {0};
static unsigned char password[65] = {0};
rtw_wifi_setting_t WiFiDrv::wifi_setting;
static void init_wifi_struct(void)
{
memset(wifi.ssid.val, 0, sizeof(wifi.ssid.val));
memset(wifi.bssid.octet, 0, ETH_ALEN);
memset(password, 0, sizeof(password));
wifi.ssid.len = 0;
wifi.password = NULL;
wifi.password_len = 0;
wifi.key_id = -1;
memset(ap.ssid.val, 0, sizeof(ap.ssid.val));
ap.ssid.len = 0;
ap.password = NULL;
ap.password_len = 0;
ap.channel = 1;
}
void WiFiDrv::wifiDriverInit()
{
struct netif * pnetif = &xnetif[0];
if (init_wlan == false) {
init_wlan = true;
LwIP_Init();
wifi_on(RTW_MODE_STA);
wifi_mode = RTW_MODE_STA;
}else if (init_wlan == true) {
if (wifi_mode != RTW_MODE_STA){
dhcps_deinit();
wifi_off();
vTaskDelay(20);
wifi_on(RTW_MODE_STA);
dhcps_init(pnetif);
wifi_mode = RTW_MODE_STA;
}
}
}
int8_t WiFiDrv::wifiSetNetwork(char* ssid, uint8_t ssid_len)
{
int ret;
uint8_t dhcp_result;
memset(wifi.bssid.octet, 0, ETH_ALEN);
memcpy(wifi.ssid.val, ssid, ssid_len);
wifi.ssid.len = ssid_len;
wifi.security_type = RTW_SECURITY_OPEN;
wifi.password = NULL;
wifi.password_len = 0;
wifi.key_id = 0;
ret = wifi_connect((char*)wifi.ssid.val, wifi.security_type, (char*)wifi.password, wifi.ssid.len,
wifi.password_len, wifi.key_id, NULL);
if (ret == RTW_SUCCESS) {
dhcp_result = LwIP_DHCP(0, DHCP_START);
init_wifi_struct();
if ( dhcp_result == DHCP_ADDRESS_ASSIGNED ) {
return WL_SUCCESS;
} else {
wifi_disconnect();
return WL_FAILURE;
}
} else {
init_wifi_struct();
return WL_FAILURE;
}
}
int8_t WiFiDrv::wifiSetPassphrase(char* ssid, uint8_t ssid_len, const char *passphrase, const uint8_t len)
{
int ret;
uint8_t dhcp_result;
memset(wifi.bssid.octet, 0, ETH_ALEN);
memcpy(wifi.ssid.val, ssid, ssid_len);
wifi.ssid.len = ssid_len;
wifi.security_type = RTW_SECURITY_WPA2_AES_PSK;
memset(password, 0, sizeof(password));
memcpy(password, passphrase, len);
wifi.password = password;
wifi.password_len = len;
wifi.key_id = 0;
ret = wifi_connect((char*)wifi.ssid.val, wifi.security_type, (char*)wifi.password, wifi.ssid.len,
wifi.password_len, wifi.key_id, NULL);
if (ret == RTW_SUCCESS) {
dhcp_result = LwIP_DHCP(0, DHCP_START);
init_wifi_struct();
if ( dhcp_result == DHCP_ADDRESS_ASSIGNED ) {
return WL_SUCCESS;
} else {
wifi_disconnect();
return WL_FAILURE;
}
} else {
init_wifi_struct();
return WL_FAILURE;
}
}
int8_t WiFiDrv::wifiSetKey(char* ssid, uint8_t ssid_len, uint8_t key_idx, const void *key, const uint8_t len)
{
int ret;
uint8_t dhcp_result;
int i, idx;
const unsigned char* k = (const unsigned char *)key;
memset(wifi.bssid.octet, 0, ETH_ALEN);
memcpy(wifi.ssid.val, ssid, ssid_len);
wifi.ssid.len = ssid_len;
wifi.security_type = RTW_SECURITY_WEP_PSK;
memset(password, 0, sizeof(password));
// convert hex sring to hex value
for (i=0, idx=0; i<len; i++) {
if ( k[i] >= '0' && k[i] <= '9' ) {
password[idx] += (k[i] - '0');
} else if ( k[i] >= 'a' && k[i] <= 'f' ) {
password[idx] += (k[i] - 'a' + 10);
} else if ( k[i] >= 'A' && k[i] <= 'F' ) {
password[idx] += (k[i] - 'A' + 10);
}
if (i % 2 == 0) {
password[idx] *= 16;
} else {
idx++;
}
}
wifi.password = password;
wifi.password_len = len/2;
wifi.key_id = key_idx;
ret = wifi_connect((char*)wifi.ssid.val, wifi.security_type, (char*)wifi.password, wifi.ssid.len,
wifi.password_len, wifi.key_id, NULL);
if (ret == RTW_SUCCESS) {
dhcp_result = LwIP_DHCP(0, DHCP_START);
init_wifi_struct();
if ( dhcp_result == DHCP_ADDRESS_ASSIGNED ) {
return WL_SUCCESS;
} else {
wifi_disconnect();
return WL_FAILURE;
}
} else {
init_wifi_struct();
return WL_FAILURE;
}
}
int8_t WiFiDrv::apSetNetwork(char* ssid, uint8_t ssid_len)
{
int ret = WL_SUCCESS;
ap.ssid.len = ssid_len;
if(ap.ssid.len > 32){
printf("Error: SSID length can't exceed 32\n\r");
ret = WL_FAILURE;
}
strcpy((char *)ap.ssid.val, (char*)ssid);
return ret;
}
int8_t WiFiDrv::apSetPassphrase(const char *passphrase, uint8_t len)
{
int ret = WL_SUCCESS;
strcpy((char *)password, (char*)passphrase);
ap.password = password;
ap.password_len = len;
return ret;
}
int8_t WiFiDrv::apSetChannel(const char *channel)
{
int ret = WL_SUCCESS;
ap.channel = (unsigned char) atoi((const char *)channel);
return ret;
}
int8_t WiFiDrv::apActivate()
{
#if CONFIG_LWIP_LAYER
struct ip_addr ipaddr;
struct ip_addr netmask;
struct ip_addr gw;
struct netif * pnetif = &xnetif[0];
#endif
int timeout = 20;
int ret = WL_SUCCESS;
if(ap.ssid.val[0] == 0){
printf("Error: SSID can't be empty\n\r");
ret = WL_FAILURE;
goto exit;
}
if(ap.password == NULL){
ap.security_type = RTW_SECURITY_OPEN;
}
else{
ap.security_type = RTW_SECURITY_WPA2_AES_PSK;
}
#if CONFIG_LWIP_LAYER
dhcps_deinit();
IP4_ADDR(&ipaddr, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1 , NETMASK_ADDR2, NETMASK_ADDR3);
IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
netif_set_addr(pnetif, &ipaddr, &netmask,&gw);
#endif
wifi_off();
vTaskDelay(20);
if (wifi_on(RTW_MODE_AP) < 0){
printf("\n\rERROR: Wifi on failed!");
ret = WL_FAILURE;
goto exit;
}
printf("\n\rStarting AP ...");
if((ret = wifi_start_ap((char*)ap.ssid.val, ap.security_type, (char*)ap.password, ap.ssid.len, ap.password_len, ap.channel) )< 0) {
printf("\n\rERROR: Operation failed!");
ret = WL_FAILURE;
goto exit;
}
while(1) {
char essid[33];
if(wext_get_ssid(WLAN0_NAME, (unsigned char *) essid) > 0) {
if(strcmp((const char *) essid, (const char *)ap.ssid.val) == 0) {
printf("\n\r%s started\n", ap.ssid.val);
ret = WL_SUCCESS;
break;
}
}
if(timeout == 0) {
printf("\n\rERROR: Start AP timeout!");
ret = WL_FAILURE;
break;
}
vTaskDelay(1 * configTICK_RATE_HZ);
timeout --;
}
#if CONFIG_LWIP_LAYER
//LwIP_UseStaticIP(pnetif);
dhcps_init(pnetif);
#endif
exit:
init_wifi_struct( );
if(ret == WL_SUCCESS){
wifi_mode = RTW_MODE_AP;
}
return ret;
}
int8_t WiFiDrv::disconnect()
{
wifi_disconnect();
return WL_DISCONNECTED;
}
uint8_t WiFiDrv::getConnectionStatus()
{
wifiDriverInit();
if (wifi_is_connected_to_ap() == 0) {
return WL_CONNECTED;
} else {
return WL_DISCONNECTED;
}
}
uint8_t* WiFiDrv::getMacAddress()
{
return LwIP_GetMAC(&xnetif[0]);
}
void WiFiDrv::getIpAddress(IPAddress& ip)
{
ip = LwIP_GetIP(&xnetif[0]);
}
void WiFiDrv::getSubnetMask(IPAddress& mask)
{
mask = LwIP_GetMASK(&xnetif[0]);
}
void WiFiDrv::getGatewayIP(IPAddress& ip)
{
ip = LwIP_GetGW(&xnetif[0]);
}
char* WiFiDrv::getCurrentSSID()
{
wifi_get_setting(WLAN0_NAME, &wifi_setting);
return (char *)(wifi_setting.ssid);
}
uint8_t* WiFiDrv::getCurrentBSSID()
{
uint8_t bssid[ETH_ALEN];
wext_get_bssid(WLAN0_NAME, bssid);
return bssid;
}
int32_t WiFiDrv::getCurrentRSSI()
{
int rssi = 0;
wifi_get_rssi(&rssi);
return rssi;
}
uint8_t WiFiDrv::getCurrentEncryptionType()
{
wifi_get_setting(WLAN0_NAME, &wifi_setting);
return (wifi_setting.security_type);
}
rtw_result_t WiFiDrv::wifidrv_scan_result_handler( rtw_scan_handler_result_t* malloced_scan_result )
{
rtw_scan_result_t* record;
if (malloced_scan_result->scan_complete != RTW_TRUE) {
record = &malloced_scan_result->ap_details;
record->SSID.val[record->SSID.len] = 0; /* Ensure the SSID is null terminated */
if ( _networkCount < WL_NETWORKS_LIST_MAXNUM ) {
strcpy( _networkSsid[_networkCount], (char *)record->SSID.val);
_networkRssi[_networkCount] = record->signal_strength;
_networkEncr[_networkCount] = record->security;
_networkCount++;
}
}
return RTW_SUCCESS;
}
int8_t WiFiDrv::startScanNetworks()
{
_networkCount = 0;
if( wifi_scan_networks(wifidrv_scan_result_handler, NULL ) != RTW_SUCCESS ){
return WL_FAILURE;
}
return WL_SUCCESS;
}
uint8_t WiFiDrv::getScanNetworks()
{
return _networkCount;
}
char* WiFiDrv::getSSIDNetoworks(uint8_t networkItem)
{
if (networkItem >= WL_NETWORKS_LIST_MAXNUM)
return NULL;
return _networkSsid[networkItem];
}
uint8_t WiFiDrv::getEncTypeNetowrks(uint8_t networkItem)
{
if (networkItem >= WL_NETWORKS_LIST_MAXNUM)
return NULL;
uint8_t encType = 0;
if ( _networkEncr[networkItem] == RTW_SECURITY_OPEN ) {
encType = ENC_TYPE_NONE;
} else if ( (_networkEncr[networkItem] & AES_ENABLED) || (_networkEncr[networkItem] == RTW_SECURITY_WPA_WPA2_MIXED) ) {
encType = ENC_TYPE_CCMP;
} else if ( _networkEncr[networkItem] & TKIP_ENABLED ) {
encType = ENC_TYPE_TKIP;
} else if ( _networkEncr[networkItem] == RTW_SECURITY_WEP_PSK ) {
encType = ENC_TYPE_WEP;
}
return encType;
}
uint32_t WiFiDrv::getEncTypeNetowrksEx(uint8_t networkItem)
{
return (networkItem >= WL_NETWORKS_LIST_MAXNUM) ? NULL : _networkEncr[networkItem];
}
int32_t WiFiDrv::getRSSINetoworks(uint8_t networkItem)
{
if (networkItem >= WL_NETWORKS_LIST_MAXNUM)
return NULL;
return _networkRssi[networkItem];
}
char* WiFiDrv::getFwVersion()
{
// The version is for compatible to arduino example code
return "1.1.0";
}
int WiFiDrv::getHostByName(const char* aHostname, IPAddress& aResult)
{
ip_addr_t ip_addr;
err_t err;
err = netconn_gethostbyname(aHostname, &ip_addr);
if (err != ERR_OK) {
return WL_FAILURE;
}
else{
aResult = ip_addr.addr;
return WL_SUCCESS;
}
}
int WiFiDrv::disablePowerSave()
{
return wifi_disable_powersave();
}

View File

@@ -1,272 +0,0 @@
/*
wifi_drv.h - Library for Arduino Wifi shield.
Copyright (c) 2011-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 WiFi_Drv_h
#define WiFi_Drv_h
#include <inttypes.h>
#include "api/IPAddress.h"
#include "wl_definitions.h"
#ifdef __cplusplus
extern "C" {
// rtk includes
#include "wifi_structures.h"
}
#endif
// Key index length
#define KEY_IDX_LEN 1
// 5 secs of delay to have the connection established
#define WL_DELAY_START_CONNECTION 5000
// firmware version string length
#define WL_FW_VER_LENGTH 6
class WiFiDrv
{
private:
// settings of requested network
static uint8_t _networkCount;
static char _networkSsid[WL_NETWORKS_LIST_MAXNUM][WL_SSID_MAX_LENGTH];
static int32_t _networkRssi[WL_NETWORKS_LIST_MAXNUM];
static uint32_t _networkEncr[WL_NETWORKS_LIST_MAXNUM];
// settings of current selected network
static rtw_wifi_setting_t wifi_setting;
static rtw_result_t wifidrv_scan_result_handler( rtw_scan_handler_result_t* malloced_scan_result );
public:
/*
* Driver initialization
*/
static void wifiDriverInit();
/*
* Set the desired network which the connection manager should try to
* connect to.
*
* The ssid of the desired network should be specified.
*
* param ssid: The ssid of the desired network.
* param ssid_len: Lenght of ssid string.
* return: WL_SUCCESS or WL_FAILURE
*/
static int8_t wifiSetNetwork(char* ssid, uint8_t ssid_len);
/* Start Wifi connection with passphrase
* the most secure supported mode will be automatically selected
*
* param ssid: Pointer to the SSID string.
* param ssid_len: Lenght of ssid string.
* param passphrase: Passphrase. Valid characters in a passphrase
* must be between ASCII 32-126 (decimal).
* param len: Lenght of passphrase string.
* return: WL_SUCCESS or WL_FAILURE
*/
static int8_t wifiSetPassphrase(char* ssid, uint8_t ssid_len, const char *passphrase, const uint8_t len);
/* Start Wifi connection with WEP encryption.
* Configure a key into the device. The key type (WEP-40, WEP-104)
* is determined by the size of the key (5 bytes for WEP-40, 13 bytes for WEP-104).
*
* param ssid: Pointer to the SSID string.
* param ssid_len: Lenght of ssid string.
* param key_idx: The key index to set. Valid values are 0-3.
* param key: Key input buffer.
* param len: Lenght of key string.
* return: WL_SUCCESS or WL_FAILURE
*/
static int8_t wifiSetKey(char* ssid, uint8_t ssid_len, uint8_t key_idx, const void *key, const uint8_t len);
/* Set ip configuration disabling dhcp client
*
* param validParams: set the number of parameters that we want to change
* i.e. validParams = 1 means that we'll change only ip address
* validParams = 3 means that we'll change ip address, gateway and netmask
* param local_ip: Static ip configuration
* param gateway: Static gateway configuration
* param subnet: Static subnet mask configuration
*/
static void config(uint8_t validParams, uint32_t local_ip, uint32_t gateway, uint32_t subnet);
/* Set DNS ip configuration
*
* param validParams: set the number of parameters that we want to change
* i.e. validParams = 1 means that we'll change only dns_server1
* validParams = 2 means that we'll change dns_server1 and dns_server2
* param dns_server1: Static DNS server1 configuration
* param dns_server2: Static DNS server2 configuration
*/
static void setDNS(uint8_t validParams, uint32_t dns_server1, uint32_t dns_server2);
/*
* Disconnect from the network
*
* return: WL_SUCCESS or WL_FAILURE
*/
static int8_t disconnect();
/*
* Disconnect from the network
*
* return: one value of wl_status_t enum
*/
static uint8_t getConnectionStatus();
/*
* Get the interface MAC address.
*
* return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH
*/
static uint8_t* getMacAddress();
/*
* Get the interface IP address.
*
* return: copy the ip address value in IPAddress object
*/
static void getIpAddress(IPAddress& ip);
/*
* Get the interface subnet mask address.
*
* return: copy the subnet mask address value in IPAddress object
*/
static void getSubnetMask(IPAddress& mask);
/*
* Get the gateway ip address.
*
* return: copy the gateway ip address value in IPAddress object
*/
static void getGatewayIP(IPAddress& ip);
/*
* Return the current SSID associated with the network
*
* return: ssid string
*/
static char* getCurrentSSID();
/*
* Return the current BSSID associated with the network.
* It is the MAC address of the Access Point
*
* return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH
*/
static uint8_t* getCurrentBSSID();
/*
* Return the current RSSI /Received Signal Strength in dBm)
* associated with the network
*
* return: signed value
*/
static int32_t getCurrentRSSI();
/*
* Return the Encryption Type associated with the network
*
* return: one value of wl_enc_type enum
*/
static uint8_t getCurrentEncryptionType();
/*
* Start scan WiFi networks available
*
* return: Number of discovered networks
*/
static int8_t startScanNetworks();
/*
* Get the networks available
*
* return: Number of discovered networks
*/
static uint8_t getScanNetworks();
/*
* Return the SSID discovered during the network scan.
*
* param networkItem: specify from which network item want to get the information
*
* return: ssid string of the specified item on the networks scanned list
*/
static char* getSSIDNetoworks(uint8_t networkItem);
/*
* Return the RSSI of the networks discovered during the scanNetworks
*
* param networkItem: specify from which network item want to get the information
*
* return: signed value of RSSI of the specified item on the networks scanned list
*/
static int32_t getRSSINetoworks(uint8_t networkItem);
/*
* Return the encryption type of the networks discovered during the scanNetworks
*
* param networkItem: specify from which network item want to get the information
*
* return: encryption type (enum wl_enc_type) of the specified item on the networks scanned list
*/
static uint8_t getEncTypeNetowrks(uint8_t networkItem);
/*
* Return the security type and encryption type of the networks discovered during the scanNetworks
*
* param networkItem: specify from which network item want to get the information
*
* return: security and encryption type of the specified item on the networks scanned list
*/
static uint32_t getEncTypeNetowrksEx(uint8_t networkItem);
/*
* Resolve the given hostname to an IP address.
* param aHostname: Name to be resolved
* param aResult: IPAddress structure to store the returned IP address
* result: 1 if aIPAddrString was successfully converted to an IP address,
* else error code
*/
static int getHostByName(const char* aHostname, IPAddress& aResult);
/*
* Get the firmware version
* result: version as string with this format a.b.c
*/
static char* getFwVersion();
static int8_t apSetNetwork(char* ssid, uint8_t ssid_len);
static int8_t apSetPassphrase(const char *passphrase, uint8_t len);
static int8_t apSetChannel(const char *channel);
static int8_t apActivate();
static int disablePowerSave();
};
extern WiFiDrv wiFiDrv;
#endif

View File

@@ -1,122 +0,0 @@
/*
Copyright (c) 2011 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 "Arduino.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "cmsis_os.h"
#ifndef portNVIC_SYSTICK_CURRENT_VALUE_REG
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
#endif
extern uint32_t xTaskGetTickCount();
extern uint32_t xTaskGetTickCountFromISR();
static __inline uint32_t __get_ipsr__(void)
{
volatile uint32_t __regIPSR __asm("ipsr");
return(__regIPSR);
}
void init(void)
{
// nop
}
void delay( uint32_t ms )
{
osStatus ret;
ret = osDelay(ms);
if ( (ret != osEventTimeout) && (ret != osOK) ) {
//printf("delay : ERROR : 0x%x \n", ret);
}
}
void delayMicroseconds(unsigned int us)
{
int i;
uint32_t t0, tn;
int dfactor = 0;
#if defined(BOARD_RTL8710)
// dfactor = 10 * us - 10 + (40 * us / 100);
dfactor = 20 * us - 10 + (81 * us / 100);
#elif defined(BOARD_RTL8195A)
dfactor = 20 * us - 10 + (81 * us / 100);
#else
dfactor = 20 * us - 10 + (81 * us / 100);
#endif
if ( us > 100 ) {
t0 = micros();
do {
tn = micros();
} while ( tn >= t0 && tn < (t0 + us - 1) );
} else {
for (i=0; i<dfactor; i++) {
asm("nop");
}
}
}
uint32_t millis( void )
{
return (__get_ipsr__() == 0) ? xTaskGetTickCount() : xTaskGetTickCountFromISR();
}
uint32_t micros( void )
{
uint32_t tick1, tick2;
uint32_t us;
uint32_t tick_per_us;
#if defined(BOARD_RTL8710)
tick_per_us = 166666; // 83333;
#elif defined(BOARD_RTL8195A)
tick_per_us = 166666;
#else
tick_per_us = 166666;
#endif
if (__get_ipsr__() == 0) {
tick1 = xTaskGetTickCount();
us = portNVIC_SYSTICK_CURRENT_VALUE_REG;
tick2 = xTaskGetTickCount();
} else {
tick1 = xTaskGetTickCountFromISR();
us = portNVIC_SYSTICK_CURRENT_VALUE_REG;
tick2 = xTaskGetTickCountFromISR();
}
if (tick1 == tick2) {
return tick1 * 1000 - us*1000 / tick_per_us;
} else if( (us*1000 / tick_per_us) < 500 ) {
return tick1 * 1000 - us*1000 / tick_per_us;
} else {
return tick1 * 1000;
}
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,240 +0,0 @@
/*
Copyright (c) 2011 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
*/
// RTL8710 module do not support ADC/DAC
#if 1 // !defined(BOARD_RTL8710)
#include "Arduino.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "analogin_api.h"
#include "analogout_api.h"
#include "pwmout_api.h"
#include "gpio_ex_api.h"
/* ADC */
analogin_t adc1;
analogin_t adc2;
analogin_t adc3;
static const float ADC_slope1 = (3.12)/(3410.0-674.0);
static const float ADC_slope2 = (3.3-3.12)/(3454.0-3410.0);
bool g_adc_enabled[] = {
false, false, false
};
extern void *gpio_pin_struct[];
//
// Arduino
//
static int _readResolution = 10;
static int _writeResolution = 8;
static int _writePeriod = 20000;
void analogReadResolution(int res) {
_readResolution = res;
}
void analogWriteResolution(int res) {
_writeResolution = res;
}
void analogWritePeriod(int us) {
_writePeriod = us;
}
static inline uint32_t mapResolution(uint32_t value, uint32_t from, uint32_t to) {
if (from == to)
return value;
if (from > to)
return value >> (from-to);
else
return value << (to-from);
}
uint8_t analog_reference = AR_DEFAULT;
void analogReference(uint8_t mode)
{
analog_reference = mode;
}
int analogRead(pin_size_t pinNumber)
{
uint32_t ulValue = 0;
uint32_t ulChannel;
uint16_t ret = 0;
float voltage;
float adc_value;
switch ( pinNumber ) {
case PIN_A0:
if (g_adc_enabled[0] == false)
{
analogin_init(&adc1, AD_1);
g_adc_enabled[0] = true;
}
case PIN_A1:
if (g_adc_enabled[1] == false)
{
analogin_init(&adc2, AD_2);
g_adc_enabled[1] = true;
}
ret = analogin_read_u16(&adc2);
break;
case PIN_A2:
if (g_adc_enabled[2] == false)
{
analogin_init(&adc3, AD_3);
g_adc_enabled[2] = true;
}
ret = analogin_read_u16(&adc3);
break;
default:
printf("%s : pinNumber %d wrong\n", __FUNCTION__, pinNumber);
return 0;
}
ret >>= 4;
if (ret < 674) {
voltage = 0;
} else if ( ret > 3410){
voltage = (float)(ret - 3410)*ADC_slope2 + 3.12;
} else {
voltage = (float)(ret-674)*ADC_slope1;
}
ret = round((1<<_readResolution)*voltage/3.3);
if ( ret >= (1<<_readResolution) ) ret = (1<<_readResolution) - 1;
return ret;
}
void analogOutputInit(void) {
// nop
}
// Right now, PWM output only works on the pins with
// hardware support. These are defined in the appropriate
// pins_*.c file. For the rest of the pins, we default
// to digital output.
void analogWrite(pin_size_t pinNumber, int value)
{
pwmout_t *obj;
if ((g_APinDescription[pinNumber].ulPinAttribute & PIO_PWM) == PIO_PWM) {
/* Handle */
if ( g_APinDescription[pinNumber].ulPinType != PIO_PWM )
{
if ( (g_APinDescription[pinNumber].ulPinType == PIO_GPIO) || (g_APinDescription[pinNumber].ulPinType == PIO_GPIO_IRQ) ) {
pinRemoveMode(pinNumber);
}
gpio_pin_struct[pinNumber] = malloc ( sizeof(pwmout_t) );
pwmout_t *obj = (pwmout_t *)gpio_pin_struct[pinNumber];
pwmout_init( obj, g_APinDescription[pinNumber].pinname );
pwmout_period_us( obj, _writePeriod);
pwmout_write( obj, value * 1.0 / (1<<_writeResolution));
g_APinDescription[pinNumber].ulPinType = PIO_PWM;
g_APinDescription[pinNumber].ulPinMode = PWM_MODE_ENABLED;
} else {
pwmout_t *obj = (pwmout_t *)gpio_pin_struct[pinNumber];
pwmout_period_us( obj, _writePeriod);
pwmout_write( obj, value * 1.0 / (1<<_writeResolution));
/* if ( g_APinDescription[pinNumber].ulPinMode == PWM_MODE_DISABLED ) {
HAL_Pwm_Enable( &obj->pwm_hal_adp );
} */
}
}
}
typedef struct _tone_argument {
uint32_t ulPin;
uint32_t timer_id;
};
void _tone_timer_handler(void const *argument)
{
struct _tone_argument *arg = (struct _tone_argument *)argument;
uint32_t ulPin = (uint32_t) argument;
noTone(arg->ulPin);
os_timer_delete(arg->timer_id);
free( (struct _tone_argument *) arg );
}
void _tone(uint32_t ulPin, unsigned int frequency, unsigned long duration)
{
pwmout_t *obj;
if ((g_APinDescription[ulPin].ulPinAttribute & PIO_PWM) != PIO_PWM) {
return;
}
if ( g_APinDescription[ulPin].ulPinType != PIO_PWM )
{
if ( (g_APinDescription[ulPin].ulPinType == PIO_GPIO) || (g_APinDescription[ulPin].ulPinType == PIO_GPIO_IRQ) ) {
pinRemoveMode(ulPin);
}
gpio_pin_struct[ulPin] = malloc ( sizeof(pwmout_t) );
pwmout_t *obj = (pwmout_t *)gpio_pin_struct[ulPin];
pwmout_init( obj, g_APinDescription[ulPin].pinname);
pwmout_period( obj, 1.0/frequency );
pwmout_pulsewidth( obj, 1.0/(frequency * 2) );
g_APinDescription[ulPin].ulPinType = PIO_PWM;
g_APinDescription[ulPin].ulPinMode = PWM_MODE_ENABLED;
} else {
// There is already a PWM configured
pwmout_t *obj = (pwmout_t *)gpio_pin_struct[ulPin];
pwmout_period( obj, 1.0/frequency );
pwmout_pulsewidth( obj, 1.0/(frequency * 2));
/* if (g_APinDescription[ulPin].ulPinMode == PWM_MODE_DISABLED) {
HAL_Pwm_Enable( &obj->pwm_hal_adp );
} */
}
if (duration > 0) {
struct _tone_argument *arg = (struct _tone_argument *) malloc ( sizeof(struct _tone_argument) );
arg->ulPin = ulPin;
arg->timer_id = os_timer_create(_tone_timer_handler, 0, arg);
os_timer_start(arg->timer_id, duration);
}
}
void noTone(uint32_t ulPin)
{
pinRemoveMode(ulPin);
}
#ifdef __cplusplus
}
#endif
//#else // #if !defined(BOARD_RTL8710)
#endif // #if !defined(BOARD_RTL8710)

View File

@@ -1,144 +0,0 @@
#include "Arduino.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "gpio_api.h"
#include "gpio_irq_api.h"
#include "gpio_irq_ex_api.h"
#include "pwmout_api.h"
extern void *gpio_pin_struct[PINS_COUNT];
extern void *gpio_irq_handler_list[PINS_COUNT];
bool pinInvalid(pin_size_t pinNumber) {
return pinNumber < 0 || pinNumber >= PINS_COUNT || g_APinDescription[pinNumber].pinname == NC;
}
void pinRemoveMode(pin_size_t pinNumber) {
if (pinInvalid(pinNumber))
return;
if (g_APinDescription[pinNumber].ulPinType == PIO_PWM) {
pwmout_t *obj = (pwmout_t *)gpio_pin_struct[pinNumber];
pwmout_free(obj);
}
if (g_APinDescription[pinNumber].ulPinType == PIO_GPIO) {
gpio_t *obj = (gpio_t *)gpio_pin_struct[pinNumber];
gpio_deinit(obj, g_APinDescription[pinNumber].pinname);
free(obj);
}
if (g_APinDescription[pinNumber].ulPinType == PIO_GPIO_IRQ) {
gpio_irq_t *obj = (gpio_irq_t *)gpio_pin_struct[pinNumber];
gpio_irq_deinit(obj);
free(obj);
}
gpio_pin_struct[pinNumber] = NULL;
g_APinDescription[pinNumber].ulPinType = NOT_INITIAL;
g_APinDescription[pinNumber].ulPinMode = NOT_INITIAL;
}
void pinMode(pin_size_t pinNumber, PinModeArduino pinMode) {
if (pinInvalid(pinNumber))
return;
if (g_APinDescription[pinNumber].ulPinType == PIO_GPIO && g_APinDescription[pinNumber].ulPinMode == pinMode)
// Nothing changes in pin mode
return;
/* if (g_APinDescription[pinNumber].ulPinType == PIO_PWM) {
// If this pin has been configured as PWM, then it cannot change to another mode
return;
} */
if (g_APinDescription[pinNumber].ulPinType != PIO_GPIO)
// pin mode changes; deinit gpio and free memory
pinRemoveMode(pinNumber);
gpio_t *gpio;
if (g_APinDescription[pinNumber].ulPinType == NOT_INITIAL) {
// allocate memory if pin not used before
gpio = malloc(sizeof(gpio_t));
gpio_pin_struct[pinNumber] = gpio;
gpio_init(gpio, g_APinDescription[pinNumber].pinname);
g_APinDescription[pinNumber].ulPinType = PIO_GPIO;
} else {
// pin already used as gpio
gpio = (gpio_t *)gpio_pin_struct[pinNumber];
}
g_APinDescription[pinNumber].ulPinMode = pinMode;
PinDirection dir;
PinMode mode;
switch (pinMode) {
case INPUT:
dir = PIN_INPUT;
mode = PullNone;
break;
case INPUT_PULLDOWN:
dir = PIN_INPUT;
mode = PullDown;
break;
case INPUT_PULLUP:
dir = PIN_INPUT;
mode = PullUp;
break;
case OUTPUT:
dir = PIN_OUTPUT;
mode = PullNone;
break;
case OUTPUT_OPENDRAIN:
dir = PIN_OUTPUT;
mode = OpenDrain;
break;
default:
return;
}
gpio_dir(gpio, dir);
gpio_mode(gpio, mode);
}
void digitalWrite(pin_size_t pinNumber, PinStatus status) {
if (pinInvalid(pinNumber))
return;
if (g_APinDescription[pinNumber].ulPinType != PIO_GPIO)
return;
gpio_t *gpio = (gpio_t *)gpio_pin_struct[pinNumber];
gpio_write(gpio, status);
}
PinStatus digitalRead(pin_size_t pinNumber) {
if (pinInvalid(pinNumber))
return;
if (g_APinDescription[pinNumber].ulPinType != PIO_GPIO)
return;
gpio_t *gpio = (gpio_t *)gpio_pin_struct[pinNumber];
return gpio_read(gpio);
}
/**************************** Extend API by RTK ***********************************/
uint32_t digitalPinToPort(uint32_t pinNumber) {
if (pinInvalid(pinNumber))
return 0xFFFFFFFF;
uint32_t pin_name = HAL_GPIO_GetPinName(g_APinDescription[pinNumber].pinname);
return HAL_GPIO_GET_PORT_BY_NAME(pin_name);
}
uint32_t digitalPinToBitMask(uint32_t pinNumber) {
if (pinInvalid(pinNumber))
return 0xFFFFFFFF;
uint32_t pin_name = HAL_GPIO_GetPinName(g_APinDescription[pinNumber].pinname);
return 1 << (HAL_GPIO_GET_PIN_BY_NAME(pin_name));
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,118 +0,0 @@
#include "Arduino.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "wiring_os.h"
#include "cmsis_os.h"
uint32_t os_thread_create( void (*task)(const void *argument), void *argument, int priority, uint32_t stack_size ) {
osThreadDef_t thread_def;
thread_def.pthread = task;
thread_def.tpriority = (osPriority)priority;
// the underlying freertos implementation on cmsis os divide stack size by 4
thread_def.stacksize = stack_size * 4;
thread_def.name = "ARDUINO";
return (uint32_t)osThreadCreate(&thread_def, argument);
}
uint32_t os_thread_get_id( void ) {
return osThreadGetId();
}
uint32_t os_thread_terminate( uint32_t thread_id ) {
return (uint32_t)osThreadTerminate(thread_id);
}
uint32_t os_thread_yield( void ) {
return (uint32_t)osThreadYield();
}
uint32_t os_thread_set_priority( uint32_t thread_id, int priority ) {
return (uint32_t)osThreadSetPriority(thread_id, (osPriority)priority);
}
int os_thread_get_priority( uint32_t thread_id ) {
return (int)osThreadGetPriority(thread_id);
}
int32_t os_signal_set( uint32_t thread_id, int32_t signals ) {
return osSignalSet(thread_id, signals);
}
int32_t os_signal_clear( uint32_t thread_id, int32_t signals ) {
return osSignalClear(thread_id, signals);
}
os_event_t os_signal_wait( int32_t signals, uint32_t millisec ) {
osEvent evt;
os_event_t ret;
evt = osSignalWait(signals, millisec);
ret.status = (uint32_t)evt.status;
ret.value.signals = evt.value.signals;
ret.def.message_id = evt.def.message_id;
return ret;
}
typedef void (*os_ptimer) (void const *argument);
uint32_t os_timer_create(void (*callback)(void const *argument), uint8_t isPeriodic, void *argument) {
osTimerDef_t *pTimerDef;
pTimerDef = (osTimerDef_t *) malloc ( sizeof(osTimerDef_t) );
pTimerDef->ptimer = callback;
pTimerDef->custom = (struct os_timer_custom *) malloc ( sizeof (struct os_timer_custom) );
return osTimerCreate(pTimerDef, (isPeriodic ? osTimerPeriodic : osTimerOnce), argument);
}
uint32_t os_timer_start (uint32_t timer_id, uint32_t millisec) {
return osTimerStart (timer_id, millisec);
}
uint32_t os_timer_stop (uint32_t timer_id) {
return osTimerStop(timer_id);
}
uint32_t os_timer_delete(uint32_t timer_id) {
osTimerDef_t *pTimerDef;
pTimerDef = (osTimerDef_t *) pvTimerGetTimerID(timer_id);
free (pTimerDef->custom);
free (pTimerDef);
return osTimerDelete(timer_id);
}
uint32_t os_semaphore_create(int32_t count) {
return (uint32_t)osSemaphoreCreate(NULL, count);
}
int32_t os_semaphore_wait(uint32_t semaphore_id, uint32_t millisec) {
if (osSemaphoreWait((osSemaphoreId)semaphore_id, millisec) == 0) {
return 1;
} else {
return 0;
}
}
uint32_t os_semaphore_release(uint32_t semaphore_id) {
return (uint32_t)osSemaphoreRelease((osSemaphoreId)semaphore_id);
}
uint32_t os_semaphore_delete(uint32_t semaphore_id) {
return (uint32_t)osSemaphoreDelete((osSemaphoreId)semaphore_id);
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,310 +0,0 @@
/** @file wiring_os.h */
/**
* @defgroup wiring_os wiring_os
* OS realted function for thread, signal, software timer, semaphore
* @{
*/
#ifndef _WIRING_OS_H_
#define _WIRING_OS_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
/**
* @defgroup os_status os_status
* Redefinition from enum osStatus
* @{
*/
/** function completed; no error or event occurred. */
#define OS_OK 0x00
/** function completed; signal event occurred. */
#define OS_EVENT_SIGNAL 0x08
/** function completed; message event occurred. */
#define OS_EVENT_MESSAGE 0x10
/** function completed; mail event occurred. */
#define OS_EVENT_MAIL 0x20
/** function completed; timeout occurred. */
#define OS_EVENT_TIMEOUT 0x40
/** parameter error: a mandatory parameter was missing or specified an incorrect object. */
#define OS_ERROR_PARAMETER 0x80
/** resource not available: a specified resource was not available. */
#define OS_ERROR_RESOURCE 0x81
/** resource not available within given time: a specified resource was not available within the timeout period. */
#define OS_ERROR_TIMEOUT_RESOURCE 0xC1
/** not allowed in ISR context: the function cannot be called from interrupt service routines. */
#define OS_ERROR_ISR 0x82
/** function called multiple times from ISR with same object. */
#define OS_ERROR_ISR_RECURSIVE 0x83
/** system cannot determine priority or thread has illegal priority. */
#define OS_ERROR_PRIORITY 0x84
/** system is out of memory: it was impossible to allocate or reserve memory for the operation. */
#define OS_ERROR_NO_MEMORY 0x85
/** value of a parameter is out of range. */
#define OS_ERROR_VALUE 0x86
/** unspecified RTOS error: run-time error but no other error message fits. */
#define OS_ERROR_OS 0xFF
/** @} */ // end of group os_status
/**
* @defgroup os_priority os_priority
* Redefinition from enum osPriority
* @{
*/
/** priority: idle (lowest) */
#define OS_PRIORITY_IDLE (-3)
/** priority: low */
#define OS_PRIORITY_LOW (-2)
/** priority: below normal */
#define OS_PRIORITY_BELOW_NORMAL (-1)
/** priority: normal (default) */
#define OS_PRIORITY_NORMAL ( 0)
/** priority: above normal */
#define OS_PRIORITY_ABOVENORMAL (+1)
/** priority: high */
#define OS_PRIORITY_HIGH (+2)
/** priority: realtime (highest) */
#define OS_PRIORITY_REALTIME (+3)
/** @} */ // end of group os_priority
#ifndef DEFAULT_STACK_SIZE
/**
* @ingroup wiring_os
* @brief default stack size
*
* It is suggest that thread is assigned stack size more than DEFAULT_STACK_SIZE
*/
#define DEFAULT_STACK_SIZE 512
#endif
/**
* @ingroup wiring_os
* @struct os_event_t
* Redefine osEvent in cmsis_os.h
*/
typedef struct {
uint32_t status; ///< status code: event or error information
union {
uint32_t v; ///< message as 32-bit value
void *p; ///< message or mail as void pointer
int32_t signals; ///< signal flags
} value; ///< event value
union {
void *mail_id; ///< mail id obtained by osMailCreate
void *message_id; ///< message id obtained by osMessageCreate
} def; ///< event definition
} os_event_t;
/**
* @defgroup thread_management thread_management
* Thread management include create, get thread id, terminate, yield, and set/get priority
**/
/**
* @ingroup thread_management
* @brief Create a thread and add it to Active Threads and set it to state READY.
*
* @param[in] task Function pointer which is the thread body. It should not run into the end of function unless os_thread_terminate is invoked
* @param[in] argument the data pointer which brings to task
* @param[in] priority The underlying os is FreeRTOS. It executes tasks with highest priority which are not in idle state.\n
* If there are more than 2 tasks to be executed, then they share the time slice.
* @param[in] stack_size The stack_size is used as memory heap only for this task. \n
* The local variables and call stacks would occupy this heap. Please make sure the the stack_size is big enough to avoid curroption
* @return The thread id which is used in thread operation and signaling.
*/
extern uint32_t os_thread_create(void (*task)(const void *argument), void *argument, int priority, uint32_t stack_size);
/**
* @ingroup thread_management
* @brief Return the thread ID of the current running thread.
*
* @return Current thread id which calls os_thread_get_id
*/
extern uint32_t os_thread_get_id( void );
/**
* @ingroup thread_management
* @brief Terminate execution of a thread and remove it from Active Threads.
*
* Thread should not ended without terminate first
*
* @param[in] thread_id Terminate the thread with specific thread_id
* @return os_status code
*/
extern uint32_t os_thread_terminate(uint32_t thread_id);
/**
* @ingroup thread_management
* @brief Pass control to next thread that is in state \b READY.
*
* By default the minimal execution unit is 1 millisecond. In a scenario that if a thread with smaller want to handout execution right to a thread with
* higher priority immediately without waiting for the ending of current 1 millisecond, then invoke os_thread_yield can transfer exection right to
* OS's idle task and check which is the next execution thread.
*
* @return os_status code
*/
extern uint32_t os_thread_yield(void);
/**
* @ingroup thread_management
* @brief Change priority of an active thread.
*
* @param[in] thread_id The target thread with the thread id to be changed
* @param[in] priority The updated priority
* @return os_status code
*/
extern uint32_t os_thread_set_priority(uint32_t thread_id, int priority);
/**
* @ingroup thread_management
* @brief Get current priority of an active thread.
*
* @param[in] thread_id The target thread with the thread id to be searched
* @return os_priority
*/
extern int os_thread_get_priority(uint32_t thread_id);
/**
* @defgroup signal_management signal_management
* Signaling between threads include set, clear, and wait
*/
/**
* @ingroup signal_management
* @brief Set the specified Signal Flags of an active thread.
*
* @param[in] thread_id Send signal to a thread with the thread id
* @param[in] signals the signals to be send
* @return os_status code
*/
extern int32_t os_signal_set(uint32_t thread_id, int32_t signals);
/**
* @ingroup signal_management
* @brief Clear the specified Signal Flags of an active thread.
*
* @param[in] thread_id Clear signal to a thread with the thread id
* @param[in] signals The signals to be clear
* @return os_status code
*/
extern int32_t os_signal_clear(uint32_t thread_id, int32_t signals);
/**
* @ingroup signal_management
* @brief Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread.
*
* @param[in] signals the signals to be wait
* @param[in] millisec the timeout value if no signal comes in. Fill in 0xFFFFFFFF for infinite wait.
* @return os_status code
*/
extern os_event_t os_signal_wait(int32_t signals, uint32_t millisec);
/**
* @defgroup timer_management timer_management
* Software timer management include create, start, stop, delete.
*/
/**
* @ingroup timer_management
* @brief specify timer type that invoke only once
*/
#define OS_TIMER_ONCE (0)
/**
* @ingroup timer_management
* @brief specify timer type that invoke periodically
*/
#define OS_TIMER_PERIODIC (1)
/**
* @ingroup timer_management
* @brief Create a timer.
*
* @param[in] callback The function to be invoke when timer timeout
* @param[in] isPeriodic \b OS_TIMER_ONCE or \b OS_TIMER_PERIODIC
* @param[in] argument The argument that is bring into callback function
* @return timer id
*/
extern uint32_t os_timer_create(void (*callback)(void const *argument), uint8_t isPeriodic, void *argument);
/**
* @ingroup timer_management
* @brief Start or restart a timer.
*
* @param[in] timer_id The timer id obtained from by os_timer_create
* @param[in] millisec The delays after timer starts
* @return os_status code
*/
extern uint32_t os_timer_start (uint32_t timer_id, uint32_t millisec);
/**
* @ingroup timer_management
* @brief Stop the timer.
*
* @param[in] timer_id The timer id obtained from by os_timer_create
* @return os_status code
*/
extern uint32_t os_timer_stop (uint32_t timer_id);
/**
* @ingroup timer_management
* @brief Delete a timer that was created by os_timer_create
*
* @param[in] timer_id The timer id obtained from by os_timer_create
* @return os_status code
*/
extern uint32_t os_timer_delete(uint32_t timer_id);
/**
* @defgroup semaphore_management semaphore_management
* Semaphore API between threads include create, wait, release, delete.
*/
/**
* @ingroup semaphore_management
* @brief Create and Initialize a Semaphore object used for managing resources
*
* @param[in] count The number of available resources
* @return semaphore ID
*/
extern uint32_t os_semaphore_create(int32_t count);
/**
* @ingroup semaphore_management
* @brief Wait until a Semaphore token becomes available
*
* @param[in] semaphore_id semaphore id obtained from os_semaphore_create
* @param[in] millisec timeout value
* @return os_status code
*/
extern int32_t os_semaphore_wait(uint32_t semaphore_id, uint32_t millisec);
/**
* @ingroup semaphore_management
* @brief Release a Semaphore token
*
* @param[in] semaphore_id semaphore id obtained from os_semaphore_create
* @return os_status code
*/
extern uint32_t os_semaphore_release(uint32_t semaphore_id);
/**
* @ingroup semaphore_management
* @brief Delete a Semaphore that was created by os_semaphore_create.
*
* @param[in] semaphore_id semaphore id obtained from os_semaphore_create
* @return os_status code
*/
extern uint32_t os_semaphore_delete(uint32_t semaphore_id);
#ifdef __cplusplus
}
#endif
#endif
/** @} */ // end of group wiring_os

View File

@@ -1,71 +0,0 @@
/*
Copyright (c) 2011 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 "Arduino.h"
#ifdef __cplusplus
extern "C"{
#endif
uint8_t shiftIn(pin_size_t dataPin, pin_size_t clockPin, BitOrder bitOrder)
{
uint8_t value = 0 ;
uint8_t i ;
for ( i=0 ; i < 8 ; ++i )
{
digitalWrite( dataPin, HIGH ) ;
if ( bitOrder == LSBFIRST )
{
value |= digitalRead( dataPin ) << i ;
}
else
{
value |= digitalRead( dataPin ) << (7 - i) ;
}
digitalWrite( clockPin, LOW ) ;
}
return value ;
}
void shiftOut(pin_size_t dataPin, pin_size_t clockPin, BitOrder bitOrder, uint8_t val)
{
uint8_t i ;
for ( i=0 ; i < 8 ; i++ )
{
if ( bitOrder == LSBFIRST )
{
digitalWrite( dataPin, !!(val & (1 << i)) ) ;
}
else
{
digitalWrite( dataPin, !!(val & (1 << (7 - i))) ) ;
}
digitalWrite( clockPin, HIGH ) ;
digitalWrite( clockPin, LOW ) ;
}
}
#ifdef __cplusplus
} // extern "C"
#endif

View File

@@ -1,37 +0,0 @@
#include "Arduino.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "wdt_api.h"
extern uint32_t ConfigDebugErr;
void wdt_reset() {
watchdog_refresh();
}
void wdt_enable(uint32_t timeout_ms) {
uint32_t backup_ConfigDebugErr;
backup_ConfigDebugErr = ConfigDebugErr;
ConfigDebugErr = 0x00000000;
if (timeout_ms > 8000) {
timeout_ms = 8000;
}
watchdog_init(timeout_ms);
watchdog_start();
ConfigDebugErr = backup_ConfigDebugErr;
}
void wdt_disable() {
watchdog_stop();
}
#ifdef __cplusplus
} // extern "C"
#endif

View File

@@ -1,46 +0,0 @@
/** @file wiring_watchdog.h */
/**
* @defgroup wiring_watchdog wiring_watchdog
* watchdog is used for reboot system when device hang
* @{
*/
#ifndef _WIRING_WATCHDOG_H_
#define _WIRING_WATCHDOG_H_
#ifdef __cplusplus
extern "C" {
#endif
/** @defgroup watchdog */
/**
* @ingroup watchdog
* Feed watchdog to avoid it barks
*/
extern void wdt_reset();
/**
* @ingroup watchdog
* @brief Enable watchdog
*
* After enbling watchdog, user defined code needs to reset it before watchdog barks. Otherwise it would make system reboot.
*
* @param[in] timeout_ms The timeout value that watchdog barks. The maximum value is 8 seconds.
*/
extern void wdt_enable(uint32_t timeout_ms);
/**
* @ingroup watchdog
* Disable watchdog
*/
extern void wdt_disable();
#ifdef __cplusplus
}
#endif
#endif /* _WIRING_WATCHDOG_H_ */
/** @} */ // end of group wiring_watchdog

View File

@@ -1,98 +0,0 @@
/*
wl_definitions.h - Library for Arduino Wifi shield.
Copyright (c) 2011-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
*/
/*
* wl_definitions.h
*
* Created on: Mar 6, 2011
* Author: dlafauci
*/
#ifndef WL_DEFINITIONS_H_
#define WL_DEFINITIONS_H_
// Maximum size of a SSID
#define WL_SSID_MAX_LENGTH 32
// Length of passphrase. Valid lengths are 8-63.
#define WL_WPA_KEY_MAX_LENGTH 63
// Length of key in bytes. Valid values are 5 and 13.
#define WL_WEP_KEY_MAX_LENGTH 13
// Size of a MAC-address or BSSID
#define WL_MAC_ADDR_LENGTH 6
// Size of a MAC-address or BSSID
#define WL_IPV4_LENGTH 4
// Maximum size of a SSID list
#define WL_NETWORKS_LIST_MAXNUM 50
// Maxmium number of socket
#define MAX_SOCK_NUM 4
// Socket not available constant
#define SOCK_NOT_AVAIL 255
// Default state value for Wifi state field
#define NA_STATE -1
//Maximum number of attempts to establish wifi connection
#define WL_MAX_ATTEMPT_CONNECTION 10
typedef enum {
WL_NO_SHIELD = 255,
WL_IDLE_STATUS = 0,
WL_NO_SSID_AVAIL,
WL_SCAN_COMPLETED,
WL_CONNECTED,
WL_CONNECT_FAILED,
WL_CONNECTION_LOST,
WL_DISCONNECTED
} wl_status_t;
/* Encryption modes */
enum wl_enc_type { /* Values map to 802.11 encryption suites... */
ENC_TYPE_WEP = 5,
ENC_TYPE_TKIP = 2,
ENC_TYPE_CCMP = 4,
/* ... except these two, 7 and 8 are reserved in 802.11-2007 */
ENC_TYPE_NONE = 7,
ENC_TYPE_AUTO = 8
};
/* RTK added type */
#ifndef WEP_ENABLED
#define WEP_ENABLED 0x0001
#define TKIP_ENABLED 0x0002
#define AES_ENABLED 0x0004
#define WSEC_SWFLAG 0x0008
#define SHARED_ENABLED 0x00008000
#define WPA_SECURITY 0x00200000
#define WPA2_SECURITY 0x00400000
#define WPS_ENABLED 0x10000000
#endif // #ifndef WEP_ENABLED
/* redefined from enum rtw_security_t */
#define SECURITY_OPEN ( 0 )
#define SECURITY_WEP_PSK ( WEP_ENABLED )
#define SECURITY_WEP_SHARED ( WEP_ENABLED | SHARED_ENABLED )
#define SECURITY_WPA_TKIP_PSK ( WPA_SECURITY | TKIP_ENABLED )
#define SECURITY_WPA_AES_PSK ( WPA_SECURITY | AES_ENABLED )
#define SECURITY_WPA2_AES_PSK ( WPA2_SECURITY | AES_ENABLED )
#define SECURITY_WPA2_TKIP_PSK ( WPA2_SECURITY | TKIP_ENABLED )
#define SECURITY_WPA2_MIXED_PSK ( WPA2_SECURITY | AES_ENABLED | TKIP_ENABLED )
#define SECURITY_WPA_WPA2_MIXED ( WPA_SECURITY | WPA2_SECURITY )
#endif /* WL_DEFINITIONS_H_ */

View File

@@ -1,49 +0,0 @@
/*
wl_types.h - Library for Arduino Wifi shield.
Copyright (c) 2011-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
*/
/*
* wl_types.h
*
* Created on: Jul 30, 2010
* Author: dlafauci
*/
#ifndef _WL_TYPES_H_
#define _WL_TYPES_H_
#include <inttypes.h>
typedef enum {
WL_FAILURE = -1,
WL_SUCCESS = 1,
} wl_error_code_t;
/* Authentication modes */
enum wl_auth_mode {
AUTH_MODE_INVALID,
AUTH_MODE_AUTO,
AUTH_MODE_OPEN_SYSTEM,
AUTH_MODE_SHARED_KEY,
AUTH_MODE_WPA,
AUTH_MODE_WPA2,
AUTH_MODE_WPA_PSK,
AUTH_MODE_WPA2_PSK
};
#endif //_WL_TYPES_H_

View File

@@ -1,108 +0,0 @@
#ifndef WSCLIENT_H
#define WSCLIENT_H
#include <websocket/libwsclient.h>
/******Define the maximum bytes of data send and receive********/
#define MAX_DATA_LEN 1500
/****************Define if using the polarssl*******************/
#define USING_SSL
/******************Define the function used*********************/
#ifdef USING_SSL
int wss_set_fun_ops(wsclient_context *wsclient);
#define wsclient_set_fun_ops(wsclient) wss_set_fun_ops(wsclient)
#else
int ws_set_fun_ops(wsclient_context *wsclient);
#define wsclient_set_fun_ops(wsclient) ws_set_fun_ops(wsclient)
#endif
/***************************************************************/
/*************************************************************************************************
** Function Name : create_wsclient
** Description : Creating the websocket client context structure
** Input : url:websocket server's url
** port:websocket server's port, if not given, default 80 for "ws", 443 for "wss"
** origin: the address or url of your self
** Return : Created: websocket client context structure
** Failed: NULL
**************************************************************************************************/
wsclient_context *create_wsclient(char *url, int port,char *path, char* origin);
/*************************************************************************************************
** Function Name : ws_connect_url
** Description : Connecting to the websocket server
** Input : wsclient: the websocket client context created by create_wsclientfunction
** Return : Connected: the socket value
** Failed: -1
**************************************************************************************************/
int ws_connect_url(wsclient_context *wsclient);
/*************************************************************************************************
** Function Name : ws_send
** Description : Create the sending string data and copy to tx_buf
** Input : message: the string that send to server(cannot exceeding the MAX_DATA_LEN
** message_len: the length of the string
** use_mask: 0/1; 1 means using mask for bynary
** wsclient: the websocket client context
** Return : None
**************************************************************************************************/
void ws_send(char* message, int message_len, int use_mask, wsclient_context *wsclient);
/*************************************************************************************************
** Function Name : ws_sendBinary
** Description : Create the sending binary data and copy to tx_buf
** Input : message: the binary that send to server(cannot exceeding the MAX_DATA_LEN
** message_len: the length of the binary
** use_mask: 0/1; 1 means using mask for bynary
** wsclient: the websocket client context
** Return : None
**************************************************************************************************/
void ws_sendBinary(uint8_t* message, int message_len, int use_mask, wsclient_context *wsclient);
/*************************************************************************************************
** Function Name : ws_sendPing
** Description : Sending Ping to websocket server
** Input : wsclient: the websocket client context
** Return : None
**************************************************************************************************/
void ws_sendPing(wsclient_context *wsclient);
/*************************************************************************************************
** Function Name : ws_poll
** Description : Receicing data from server and send the data in tx_buf
** Input : timeout(in milliseconds)
wsclient: the websocket client context
** Return : None
**************************************************************************************************/
void ws_poll(int timeout, wsclient_context *wsclient);
/*************************************************************************************************
** Function Name : ws_dispatch
** Description : callback function when getting message from server
** Input : function that resolve the message received and the message length
** Return : None
**************************************************************************************************/
void ws_dispatch(void (*callback)(wsclient_context *, int)) ;
/*************************************************************************************************
** Function Name : ws_getReadyState
** Description : Getting the connection status
** Input : wsclient: the websocket client context
** Return : readyStateValues(4 types:CLOSING, CLOSED, CONNECTING, OPEN)
**************************************************************************************************/
readyStateValues ws_getReadyState(wsclient_context *wsclient);
/*************************************************************************************************
** Function Name : ws_close
** Description : Closing the connection with websocket server
** Input : wsclient: the websocket client context
** Return : None
**************************************************************************************************/
void ws_close(wsclient_context *wsclient);
#endif

View File

@@ -1,69 +0,0 @@
#include "Flash.h"
#include <Arduino.h>
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#include <flash_api.h>
#ifdef __cplusplus
} // extern "C"
#endif
FlashClass::FlashClass() {
flash = NULL;
}
FlashClass::~FlashClass() {
if (!flash)
return;
free(flash);
flash = NULL;
}
void FlashClass::initialize() {
if (flash)
return;
flash = (flash_t *)malloc(sizeof(flash_t));
flash_get_status(flash);
}
FlashId FlashClass::getChipId() {
initialize();
FlashId id;
uint8_t idBytes[3];
flash_read_id(flash, idBytes, 3);
id.manufacturerId = idBytes[0];
id.chipId = idBytes[1];
id.chipSizeId = idBytes[2];
return id;
}
uint32_t FlashClass::getSize() {
initialize();
FlashId id = getChipId();
if (id.chipSizeId >= 0x14 && id.chipSizeId <= 0x19) {
return (1 << id.chipSizeId);
}
return 1024 * 1024;
}
bool FlashClass::eraseSector(uint32_t offset) {
initialize();
flash_erase_sector(flash, offset);
return true;
}
bool FlashClass::readBlock(uint32_t offset, uint8_t *data, size_t size) {
initialize();
return flash_stream_read(flash, offset, size, data);
}
bool FlashClass::writeBlock(uint32_t offset, uint8_t *data, size_t size) {
initialize();
return flash_stream_write(flash, offset, size, data);
}
FlashClass Flash;

View File

@@ -1,25 +0,0 @@
#pragma once
#include "api/Flash.h"
struct flash_s;
typedef struct flash_s flash_t;
class FlashClass : public IFlashClass {
private:
flash_t *flash;
void initialize();
public:
FlashClass();
~FlashClass();
FlashId getChipId();
uint32_t getSize();
bool eraseSector(uint32_t offset);
bool readBlock(uint32_t offset, uint8_t *data, size_t size);
bool writeBlock(uint32_t offset, uint8_t *data, size_t size);
};
extern FlashClass Flash;

View File

@@ -1,94 +0,0 @@
#include "WiFi.h"
#include "WiFiPriv.h"
rtw_network_info_t wifi = {0};
rtw_ap_info_t ap = {0};
rtw_wifi_setting_t wifi_setting;
unsigned char sta_password[65] = {0};
unsigned char ap_password[65] = {0};
void reset_wifi_struct(void) {
memset(wifi.ssid.val, 0, sizeof(wifi.ssid.val));
memset(wifi.bssid.octet, 0, ETH_ALEN);
memset(sta_password, 0, sizeof(sta_password));
memset(ap_password, 0, sizeof(ap_password));
wifi.ssid.len = 0;
wifi.password = NULL;
wifi.password_len = 0;
wifi.key_id = -1;
memset(ap.ssid.val, 0, sizeof(ap.ssid.val));
ap.ssid.len = 0;
ap.password = NULL;
ap.password_len = 0;
ap.channel = 1;
}
WiFiClass::WiFiClass() {
_scanSem = xSemaphoreCreateBinary();
}
WiFiClass::~WiFiClass() {
vSemaphoreDelete(_scanSem);
}
void WiFiClass::printDiag(Print &dest) {
const char *modes[] = {"NULL", "STA", "AP", "STA+AP"};
const char *enc[] = {"Open", "WEP", "WPA PSK", "WPA2 PSK", "WPA/WPA2", "WPA", "WPA2"};
dest.print("Mode: ");
dest.println(modes[getMode()]);
if (wifi_mode & WIFI_MODE_STA) {
dest.println("-- Station --");
dest.print("SSID: ");
dest.println(SSID());
if (isConnected()) {
dest.print("BSSID: ");
dest.println(BSSIDstr());
dest.print("RSSI: ");
dest.println(RSSI());
dest.print("Encryption: ");
dest.println(enc[getEncryption()]);
dest.print("IP: ");
dest.println(localIP());
dest.print("MAC: ");
dest.println(macAddress());
dest.print("Hostname: ");
dest.println(getHostname());
}
}
if (wifi_mode & WIFI_MODE_AP) {
dest.println("-- Access Point --");
dest.print("SSID: ");
dest.println(softAPSSID());
dest.print("IP: ");
dest.println(softAPIP());
dest.print("MAC: ");
dest.println(softAPmacAddress());
dest.print("Hostname: ");
dest.println(softAPgetHostname());
}
}
WiFiAuthMode WiFiClass::securityTypeToAuthMode(uint8_t type) {
switch (wifi_setting.security_type) {
case RTW_SECURITY_OPEN:
return WIFI_AUTH_OPEN;
case RTW_SECURITY_WEP_SHARED:
return WIFI_AUTH_WEP;
case RTW_SECURITY_WPA_TKIP_PSK:
return WIFI_AUTH_WPA_PSK;
case RTW_SECURITY_WPA_AES_PSK:
return WIFI_AUTH_WPA;
case RTW_SECURITY_WPA2_TKIP_PSK:
return WIFI_AUTH_WPA2_PSK;
case RTW_SECURITY_WPA2_AES_PSK:
return WIFI_AUTH_WPA2;
case RTW_SECURITY_WPA_WPA2_MIXED:
return WIFI_AUTH_WPA_WPA2_PSK;
}
return WIFI_AUTH_INVALID;
}
WiFiClass WiFi;

View File

@@ -1,180 +0,0 @@
#pragma once
#include <Arduino.h>
#include <api/WiFi.h>
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#include <FreeRTOS.h>
#include <semphr.h>
#include <wifi_structures.h>
#ifdef __cplusplus
} // extern "C"
#endif
#include "WiFiClient.h"
#include "WiFiServer.h"
class WiFiClass : public IWiFiClass,
public IWiFiGenericClass,
public IWiFiSTAClass,
public IWiFiScanClass,
public IWiFiAPClass {
private:
static WiFiAuthMode securityTypeToAuthMode(uint8_t type);
bool _initialized;
bool _sleep;
bool _scanning = false;
SemaphoreHandle_t _scanSem;
uint8_t _netCount = 0;
char **_netSsid = NULL;
WiFiAuthMode *_netEncr = NULL;
int32_t *_netRssi = NULL;
rtw_mac_t *_netBssid = NULL;
int32_t *_netChannel = NULL;
static rtw_result_t scanHandler(rtw_scan_handler_result_t *result);
public:
// IWiFiClass
WiFiClass();
~WiFiClass();
void printDiag(Print &dest);
public:
// IWiFiGenericClass
int32_t channel(void);
bool mode(WiFiMode mode) override;
WiFiMode getMode();
WiFiStatus status();
bool enableSTA(bool enable);
bool enableAP(bool enable);
bool setSleep(bool enable);
bool getSleep();
bool setTxPower(int power);
int getTxPower();
IPAddress hostByName(const char *hostname);
static IPAddress calculateNetworkID(IPAddress ip, IPAddress subnet);
static IPAddress calculateBroadcast(IPAddress ip, IPAddress subnet);
static uint8_t calculateSubnetCIDR(IPAddress subnetMask);
static String macToString(uint8_t *mac);
public:
// IWiFiSTAClass
WiFiStatus begin(
const char *ssid,
const char *passphrase = NULL,
int32_t channel = 0,
const uint8_t *bssid = NULL,
bool connect = true
) override;
WiFiStatus
begin(char *ssid, char *passphrase = NULL, int32_t channel = 0, const uint8_t *bssid = NULL, bool connect = true);
bool config(
IPAddress localIP,
IPAddress gateway,
IPAddress subnet,
IPAddress dns1 = (uint32_t)0x00000000,
IPAddress dns2 = (uint32_t)0x00000000
);
inline bool reconnect() {
return reconnect(NULL);
}
bool reconnect(const uint8_t *bssid = NULL);
bool disconnect(bool wifiOff = false);
bool isConnected() override;
bool setAutoReconnect(bool autoReconnect);
bool getAutoReconnect();
WiFiStatus waitForConnectResult(unsigned long timeout);
IPAddress localIP();
uint8_t *macAddress(uint8_t *mac);
String macAddress();
IPAddress subnetMask();
IPAddress gatewayIP();
IPAddress dnsIP(uint8_t dns_no);
IPAddress broadcastIP();
IPAddress networkID();
uint8_t subnetCIDR();
bool enableIpV6();
IPv6Address localIPv6();
const char *getHostname();
bool setHostname(const char *hostname);
bool setMacAddress(const uint8_t *mac);
const String SSID();
const String psk();
uint8_t *BSSID();
String BSSIDstr();
int8_t RSSI();
WiFiAuthMode getEncryption();
public:
// IWiFiScanClass
int16_t scanNetworks(
bool async = false,
bool showHidden = false,
bool passive = false,
uint32_t maxMsPerChannel = 300,
uint8_t channel = 0
);
bool getNetworkInfo(
uint8_t networkItem,
String &ssid,
WiFiAuthMode &encryptionType,
int32_t &RSSI,
uint8_t *&BSSID,
int32_t &channel
);
int16_t scanComplete();
void scanDelete();
String SSID(uint8_t networkItem);
WiFiAuthMode encryptionType(uint8_t networkItem);
int32_t RSSI(uint8_t networkItem);
uint8_t *BSSID(uint8_t networkItem);
String BSSIDstr(uint8_t networkItem);
int32_t channel(uint8_t networkItem);
public:
// IWiFiAPClass
bool softAP(
const char *ssid, const char *passphrase = NULL, int channel = 1, bool ssidHidden = false, int maxClients = 4
);
bool softAPConfig(IPAddress localIP, IPAddress gateway, IPAddress subnet);
bool softAPdisconnect(bool wifiOff = false);
uint8_t softAPgetStationNum();
IPAddress softAPIP();
IPAddress softAPBroadcastIP();
IPAddress softAPNetworkID();
uint8_t softAPSubnetCIDR();
bool softAPenableIpV6();
IPv6Address softAPIPv6();
const char *softAPgetHostname();
bool softAPsetHostname(const char *hostname);
uint8_t *softAPmacAddress(uint8_t *mac);
String softAPmacAddress(void);
const String softAPSSID(void);
};
extern WiFiClass WiFi;

View File

@@ -1,162 +0,0 @@
#include "WiFi.h"
#include "WiFiPriv.h"
bool WiFiClass::softAP(const char *ssid, const char *passphrase, int channel, bool ssidHidden, int maxClients) {
if (!enableAP(true))
return false;
vTaskDelay(20);
if (!ssid || *ssid == 0x00 || strlen(ssid) > 32) {
LT_W("SSID not specified or too long");
return false;
}
if (passphrase && strlen(passphrase) < 8) {
LT_W("Passphrase too short");
return false;
}
strcpy((char *)ap.ssid.val, ssid);
ap.ssid.len = strlen(ssid);
ap.channel = channel;
ap.security_type = RTW_SECURITY_OPEN;
ap.password = NULL;
ap.password_len = 0;
if (passphrase) {
strcpy((char *)ap_password, passphrase);
ap.security_type = RTW_SECURITY_WPA2_AES_PSK;
ap.password = ap_password;
ap.password_len = strlen(passphrase);
}
dhcps_deinit();
LT_I("Creating SoftAP %s", ssid);
int ret;
if (!ssidHidden) {
ret = wifi_start_ap(
(char *)ap.ssid.val,
ap.security_type,
(char *)ap.password,
ap.ssid.len,
ap.password_len,
ap.channel
);
} else {
ret = wifi_start_ap_with_hidden_ssid(
(char *)ap.ssid.val,
ap.security_type,
(char *)ap.password,
ap.ssid.len,
ap.password_len,
ap.channel
);
}
if (ret < 0) {
LT_E("SoftAP failed; ret=%d", ret);
return false;
}
uint8_t timeout = 20;
unsigned char essid[33];
const char *ifname = NETNAME_AP;
struct netif *ifs = NETIF_RTW_AP;
while (1) {
if (wext_get_ssid(ifname, essid) > 0) {
if (strcmp((const char *)essid, (const char *)ap.ssid.val) == 0)
break;
}
if (!timeout)
return false;
vTaskDelay(1 * configTICK_RATE_HZ);
timeout--;
}
dhcps_init(ifs);
return true;
}
bool WiFiClass::softAPConfig(IPAddress localIP, IPAddress gateway, IPAddress subnet) {
if (!enableAP(true))
return false;
struct netif *ifs = NETIF_RTW_AP;
struct ip_addr ipaddr, netmask, gw;
ipaddr.addr = localIP;
netmask.addr = subnet;
gw.addr = gateway;
netif_set_addr(ifs, &ipaddr, &netmask, &gw);
return true;
}
bool WiFiClass::softAPdisconnect(bool wifiOff) {
// TODO implement wifi_restart_ap
if (wifiOff)
return enableAP(false);
return true;
}
uint8_t WiFiClass::softAPgetStationNum() {
// TODO
// the struct is at wifi_conf.c:2576
return 0;
}
IPAddress WiFiClass::softAPIP() {
return LwIP_GetIP(NETIF_RTW_AP);
}
IPAddress WiFiClass::softAPBroadcastIP() {
return calculateBroadcast(softAPIP(), LwIP_GetMASK(NETIF_RTW_AP));
}
IPAddress WiFiClass::softAPNetworkID() {
return calculateNetworkID(softAPIP(), LwIP_GetMASK(NETIF_RTW_AP));
}
uint8_t WiFiClass::softAPSubnetCIDR() {
return calculateSubnetCIDR(LwIP_GetMASK(NETIF_RTW_AP));
}
bool WiFiClass::softAPenableIpV6() {
return false;
}
IPv6Address WiFiClass::softAPIPv6() {
return IPv6Address();
}
const char *WiFiClass::softAPgetHostname() {
return netif_get_hostname(NETIF_RTW_AP);
}
bool WiFiClass::softAPsetHostname(const char *hostname) {
netif_set_hostname(NETIF_RTW_AP, (char *)hostname);
return true;
}
uint8_t *WiFiClass::softAPmacAddress(uint8_t *mac) {
uint8_t *macLocal = LwIP_GetMAC(NETIF_RTW_AP);
memcpy(mac, macLocal, ETH_ALEN);
free(macLocal);
return mac;
}
String WiFiClass::softAPmacAddress(void) {
uint8_t mac[ETH_ALEN];
macAddress(mac);
return macToString(mac);
}
const String WiFiClass::softAPSSID(void) {
wifi_get_setting(NETNAME_AP, &wifi_setting);
return (char *)wifi_setting.ssid;
}

View File

@@ -1,153 +0,0 @@
#include "WiFi.h"
#include "WiFiPriv.h"
int32_t WiFiClass::channel() {
int channel;
wifi_get_channel(&channel);
return channel;
}
bool WiFiClass::mode(WiFiMode mode) {
WiFiMode currentMode = getMode();
LT_D_WG("Mode changing %u -> %u", currentMode, mode);
if (mode == currentMode)
return true;
if (!currentMode && mode && !_initialized) {
// initialize wifi first
LT_I("Initializing LwIP");
LwIP_Init();
reset_wifi_struct();
// wifi_manager_init(); // these are events!
_initialized = true;
}
if (currentMode) {
// stop wifi to change mode
LT_D_WG("Stopping WiFi to change mode");
if (wifi_off() != RTW_SUCCESS)
return false;
vTaskDelay(20);
if (mode == WIFI_MODE_NULL)
return false;
}
if (wifi_on((rtw_mode_t)mode) != RTW_SUCCESS) {
LT_E("Error while changing mode(%u)", mode);
return false;
}
return true;
}
WiFiMode WiFiClass::getMode() {
if (!_initialized)
return WIFI_MODE_NULL;
return (WiFiMode)wifi_mode;
}
WiFiStatus WiFiClass::status() {
if (wifi_is_connected_to_ap() == 0) {
return WL_CONNECTED;
} else {
return WL_DISCONNECTED;
}
}
bool WiFiClass::enableSTA(bool enable) {
WiFiMode currentMode = getMode();
if (((currentMode & WIFI_MODE_STA) != 0) != enable) {
return mode((WiFiMode)(currentMode ^ WIFI_MODE_STA));
}
return true;
}
bool WiFiClass::enableAP(bool enable) {
WiFiMode currentMode = getMode();
if (((currentMode & WIFI_MODE_AP) != 0) != enable) {
return mode((WiFiMode)(currentMode ^ WIFI_MODE_AP));
}
return true;
}
bool WiFiClass::setSleep(bool enable) {
LT_D_WG("WiFi sleep mode %u", enable);
if (enable)
if (wifi_enable_powersave() != RTW_SUCCESS)
return false;
else if (wifi_disable_powersave() != RTW_SUCCESS)
return false;
_sleep = enable;
return true;
}
bool WiFiClass::getSleep() {
return _sleep;
}
bool WiFiClass::setTxPower(int power) {
return false; // wifi_set_txpower(power) == RTW_SUCCESS;
}
int WiFiClass::getTxPower() {
return 0;
int power = 0;
wifi_get_txpower(&power);
return power;
}
IPAddress WiFiClass::hostByName(const char *hostname) {
ip_addr_t ip;
int ret = netconn_gethostbyname(hostname, &ip);
if (ret == ERR_OK) {
return ip.addr;
}
return IPAddress();
}
IPAddress WiFiClass::calculateNetworkID(IPAddress ip, IPAddress subnet) {
IPAddress networkID;
for (size_t i = 0; i < 4; i++)
networkID[i] = subnet[i] & ip[i];
return networkID;
}
IPAddress WiFiClass::calculateBroadcast(IPAddress ip, IPAddress subnet) {
IPAddress broadcastIp;
for (int i = 0; i < 4; i++)
broadcastIp[i] = ~subnet[i] | ip[i];
return broadcastIp;
}
uint8_t WiFiClass::calculateSubnetCIDR(IPAddress subnetMask) {
uint8_t CIDR = 0;
for (uint8_t i = 0; i < 4; i++) {
if (subnetMask[i] == 0x80) // 128
CIDR += 1;
else if (subnetMask[i] == 0xC0) // 192
CIDR += 2;
else if (subnetMask[i] == 0xE0) // 224
CIDR += 3;
else if (subnetMask[i] == 0xF0) // 242
CIDR += 4;
else if (subnetMask[i] == 0xF8) // 248
CIDR += 5;
else if (subnetMask[i] == 0xFC) // 252
CIDR += 6;
else if (subnetMask[i] == 0xFE) // 254
CIDR += 7;
else if (subnetMask[i] == 0xFF) // 255
CIDR += 8;
}
return CIDR;
}
String WiFiClass::macToString(uint8_t *mac) {
char macStr[ETH_ALEN * 3];
sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return macStr;
}

View File

@@ -1,66 +0,0 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
// these are defined in PIO builder (for IDE to understand)
#define LWIP_TIMEVAL_PRIVATE 0
#define LWIP_NETIF_HOSTNAME 1
// this should define all errno values, as well as the extern int
#define LWIP_PROVIDE_ERRNO 1
#define LWIP_SO_RCVBUF 1
#define MAX_SOCK_NUM 4
#define WIFI_CLIENT_CONNECT_TIMEOUT 3000
#define WIFI_CLIENT_READ_TIMEOUT 3000
#define WIFI_CLIENT_WRITE_RETRY 10
#define WIFI_CLIENT_SELECT_TIMEOUT 1000
#define WIFI_CLIENT_FLUSH_BUF_SIZE 1024
// I think I don't understand how that works.
// For some reason, LwIP uses a different (extern) errno,
// while this macro refers to a function __errno, which
// reads a totally different variable.
#undef errno
#include <lwip/arch.h>
// disable #defines removing lwip_ prefix
#undef LWIP_COMPAT_SOCKETS
#define LWIP_COMPAT_SOCKETS 0
#include <lwip/sockets.h>
#include <autoconf.h>
#include <dhcp/dhcps.h>
#include <lwip/api.h>
#include <lwip/dns.h>
#include <lwip/err.h>
#include <lwip_netconf.h>
#include <sys/time.h>
#include <wifi_conf.h>
#include <wifi_constants.h>
#include <wifi_structures.h>
extern struct netif xnetif[NET_IF_NUM];
#ifdef __cplusplus
} // extern "C"
#endif
#include <Arduino.h>
#include "WiFi.h"
extern rtw_network_info_t wifi;
extern rtw_ap_info_t ap;
extern rtw_wifi_setting_t wifi_setting;
extern unsigned char sta_password[65];
extern unsigned char ap_password[65];
extern void reset_wifi_struct(void);
extern rtw_mode_t wifi_mode;
#define NETIF_RTW_STA &xnetif[RTW_STA_INTERFACE]
#define NETIF_RTW_AP (wifi_mode == WIFI_MODE_APSTA ? &xnetif[RTW_AP_INTERFACE] : NETIF_RTW_STA)
#define NETNAME_STA WLAN0_NAME
#define NETNAME_AP (wifi_mode == WIFI_MODE_APSTA ? WLAN1_NAME : WLAN0_NAME)

View File

@@ -1,235 +0,0 @@
#include "WiFi.h"
#include "WiFiPriv.h"
WiFiStatus WiFiClass::begin(char *ssid, char *passphrase, int32_t channel, const uint8_t *bssid, bool connect) {
return begin((const char *)ssid, (const char *)passphrase, channel, bssid, connect);
}
WiFiStatus
WiFiClass::begin(const char *ssid, const char *passphrase, int32_t channel, const uint8_t *bssid, bool connect) {
if (!enableSTA(true))
return WL_CONNECT_FAILED;
if (!ssid || *ssid == 0x00 || strlen(ssid) > 32) {
LT_W("SSID not specified or too long");
return WL_CONNECT_FAILED;
}
if (passphrase && strlen(passphrase) > 64) {
LT_W("Passphrase too long");
return WL_CONNECT_FAILED;
}
memset(wifi.bssid.octet, 0, ETH_ALEN);
strcpy((char *)wifi.ssid.val, ssid);
wifi.ssid.len = strlen(ssid);
wifi.security_type = RTW_SECURITY_OPEN;
wifi.password = NULL;
wifi.password_len = 0;
wifi.key_id = 0;
if (passphrase) {
strcpy((char *)sta_password, passphrase);
wifi.security_type = RTW_SECURITY_WPA2_AES_PSK;
wifi.password = sta_password;
wifi.password_len = strlen(passphrase);
}
if (reconnect(bssid))
return WL_CONNECTED;
else
return WL_CONNECT_FAILED;
}
bool WiFiClass::config(IPAddress localIP, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2) {
if (!enableSTA(true))
return false;
struct netif *ifs = NETIF_RTW_STA;
struct ip_addr ipaddr, netmask, gw, d1, d2;
ipaddr.addr = localIP;
netmask.addr = subnet;
gw.addr = gateway;
d1.addr = dns1;
d2.addr = dns2;
netif_set_addr(ifs, &ipaddr, &netmask, &gw);
if (dns1[0])
dns_setserver(0, &d1);
if (dns2[0])
dns_setserver(0, &d2);
return true;
}
bool WiFiClass::reconnect(const uint8_t *bssid) {
int ret;
uint8_t dhcpRet;
LT_I("Connecting to %s", wifi.ssid.val);
if (!bssid) {
ret = wifi_connect(
(char *)wifi.ssid.val,
wifi.security_type,
(char *)wifi.password,
wifi.ssid.len,
wifi.password_len,
wifi.key_id,
NULL
);
} else {
ret = wifi_connect_bssid(
(unsigned char *)bssid,
(char *)wifi.ssid.val,
wifi.security_type,
(char *)wifi.password,
ETH_ALEN,
wifi.ssid.len,
wifi.password_len,
wifi.key_id,
NULL
);
}
if (ret == RTW_SUCCESS) {
dhcpRet = LwIP_DHCP(0, DHCP_START);
if (dhcpRet == DHCP_ADDRESS_ASSIGNED)
return true;
LT_E("DHCP failed; dhcpRet=%d", dhcpRet);
wifi_disconnect();
return false;
}
LT_E("Connection failed; ret=%d", ret);
return false;
}
bool WiFiClass::disconnect(bool wifiOff) {
int ret = wifi_disconnect();
if (wifiOff)
enableSTA(false);
return ret == RTW_SUCCESS;
}
bool WiFiClass::isConnected() {
return status() == WL_CONNECTED;
}
bool WiFiClass::setAutoReconnect(bool autoReconnect) {
return wifi_set_autoreconnect(autoReconnect) == RTW_SUCCESS;
}
bool WiFiClass::getAutoReconnect() {
bool autoReconnect;
wifi_get_autoreconnect((uint8_t *)&autoReconnect);
return autoReconnect;
}
WiFiStatus WiFiClass::waitForConnectResult(unsigned long timeout) {
if ((wifi_mode & WIFI_MODE_STA) == 0) {
return WL_DISCONNECTED;
}
unsigned long start = millis();
while ((!status() || status() >= WL_DISCONNECTED) && (millis() - start) < timeout) {
delay(100);
}
return status();
}
IPAddress WiFiClass::localIP() {
if (!wifi_mode)
return IPAddress();
return LwIP_GetIP(NETIF_RTW_STA);
}
uint8_t *WiFiClass::macAddress(uint8_t *mac) {
uint8_t *macLocal = LwIP_GetMAC(NETIF_RTW_STA);
memcpy(mac, macLocal, ETH_ALEN);
free(macLocal);
return mac;
}
String WiFiClass::macAddress(void) {
uint8_t mac[ETH_ALEN];
macAddress(mac);
return macToString(mac);
}
IPAddress WiFiClass::subnetMask() {
return LwIP_GetMASK(NETIF_RTW_STA);
}
IPAddress WiFiClass::gatewayIP() {
return LwIP_GetGW(NETIF_RTW_STA);
}
IPAddress WiFiClass::dnsIP(uint8_t dns_no) {
struct ip_addr dns;
LwIP_GetDNS(&dns);
return dns.addr;
}
IPAddress WiFiClass::broadcastIP() {
return LwIP_GetBC(NETIF_RTW_STA);
}
IPAddress WiFiClass::networkID() {
return calculateNetworkID(gatewayIP(), subnetMask());
}
uint8_t WiFiClass::subnetCIDR() {
return calculateSubnetCIDR(subnetMask());
}
bool WiFiClass::enableIpV6() {
return false;
}
IPv6Address WiFiClass::localIPv6() {
return IPv6Address();
}
const char *WiFiClass::getHostname() {
return netif_get_hostname(NETIF_RTW_STA);
}
bool WiFiClass::setHostname(const char *hostname) {
netif_set_hostname(NETIF_RTW_STA, (char *)hostname);
return true;
}
bool WiFiClass::setMacAddress(const uint8_t *mac) {
return wifi_set_mac_address((char *)mac) == RTW_SUCCESS;
}
const String WiFiClass::SSID() {
if (!isConnected())
return "";
wifi_get_setting(NETNAME_STA, &wifi_setting);
return (char *)wifi_setting.ssid;
}
const String WiFiClass::psk() {
if (!isConnected() || !wifi.password)
return "";
return (char *)wifi.password;
}
uint8_t *WiFiClass::BSSID() {
uint8_t bssid[ETH_ALEN];
wext_get_bssid(NETNAME_STA, bssid);
return bssid;
}
String WiFiClass::BSSIDstr() {
return macToString(BSSID());
}
int8_t WiFiClass::RSSI() {
int rssi = 0;
wifi_get_rssi(&rssi);
return rssi;
}
WiFiAuthMode WiFiClass::getEncryption() {
wifi_get_setting(NETNAME_STA, &wifi_setting);
return WiFiClass::securityTypeToAuthMode(wifi_setting.security_type);
}

View File

@@ -1,117 +0,0 @@
#include "WiFi.h"
#include "WiFiPriv.h"
rtw_result_t WiFiClass::scanHandler(rtw_scan_handler_result_t *result) {
WiFiClass *cls = (WiFiClass *)result->user_data;
if (result->scan_complete == RTW_TRUE) {
cls->_scanning = false;
xSemaphoreGive(cls->_scanSem);
return RTW_SUCCESS;
}
rtw_scan_result_t *net = &result->ap_details;
net->SSID.val[net->SSID.len] = '\0';
uint8_t newSize = cls->_netCount + 1;
cls->_netSsid = (char **)realloc(cls->_netSsid, newSize * sizeof(char *));
cls->_netEncr = (WiFiAuthMode *)realloc(cls->_netEncr, newSize * sizeof(WiFiAuthMode));
cls->_netRssi = (int32_t *)realloc(cls->_netRssi, newSize * sizeof(int32_t));
cls->_netBssid = (rtw_mac_t *)realloc(cls->_netBssid, newSize * sizeof(rtw_mac_t));
cls->_netChannel = (int32_t *)realloc(cls->_netChannel, newSize * sizeof(int32_t));
cls->_netSsid[cls->_netCount] = (char *)malloc((net->SSID.len + 1) * sizeof(char));
strcpy(cls->_netSsid[cls->_netCount], (char *)net->SSID.val);
cls->_netEncr[cls->_netCount] = WiFiClass::securityTypeToAuthMode(net->security);
cls->_netRssi[cls->_netCount] = net->signal_strength;
memcpy(cls->_netBssid[cls->_netCount].octet, net->BSSID.octet, ETH_ALEN);
cls->_netChannel[cls->_netCount] = net->channel;
cls->_netCount++;
return RTW_SUCCESS;
}
int16_t WiFiClass::scanNetworks(bool async, bool showHidden, bool passive, uint32_t maxMsPerChannel, uint8_t channel) {
if (_scanning)
return WIFI_SCAN_RUNNING;
scanDelete();
if (wifi_scan_networks(scanHandler, this) != RTW_SUCCESS)
return WIFI_SCAN_FAILED;
_scanning = true;
if (!async) {
xSemaphoreTake(_scanSem, 1); // reset the semaphore quickly
xSemaphoreTake(_scanSem, pdMS_TO_TICKS(maxMsPerChannel * 20));
return _netCount;
}
return WIFI_SCAN_RUNNING;
}
bool WiFiClass::getNetworkInfo(
uint8_t networkItem, String &ssid, WiFiAuthMode &encType, int32_t &rssi, uint8_t *&bssid, int32_t &channel
) {
ssid = SSID(networkItem);
encType = encryptionType(networkItem);
rssi = RSSI(networkItem);
bssid = BSSID(networkItem);
channel = this->channel(networkItem);
}
int16_t WiFiClass::scanComplete() {
if (_scanning)
return WIFI_SCAN_RUNNING;
return _netCount;
}
void WiFiClass::scanDelete() {
for (uint8_t i = 0; i < _netCount; i++) {
free(_netSsid[i]);
}
free(_netSsid);
free(_netEncr);
free(_netRssi);
free(_netBssid);
free(_netChannel);
_netCount = 0;
_netSsid = NULL;
_netEncr = NULL;
_netRssi = NULL;
_netBssid = NULL;
_netChannel = NULL;
}
String WiFiClass::SSID(uint8_t networkItem) {
if (networkItem >= _netCount)
return "";
return _netSsid[networkItem];
}
WiFiAuthMode WiFiClass::encryptionType(uint8_t networkItem) {
if (networkItem >= _netCount)
return WIFI_AUTH_INVALID;
return _netEncr[networkItem];
}
int32_t WiFiClass::RSSI(uint8_t networkItem) {
if (networkItem >= _netCount)
return 0;
return _netRssi[networkItem];
}
uint8_t *WiFiClass::BSSID(uint8_t networkItem) {
if (networkItem >= _netCount)
return NULL;
return _netBssid[networkItem].octet;
}
String WiFiClass::BSSIDstr(uint8_t networkItem) {
return macToString(BSSID(networkItem));
}
int32_t WiFiClass::channel(uint8_t networkItem) {
if (networkItem >= _netCount)
return 0;
return _netChannel[networkItem];
}

View File

@@ -1,35 +0,0 @@
#pragma once
#include <api/WiFiServer.h>
#include "WiFiClient.h"
class WiFiServer : public IWiFiServer<WiFiClient> {
private:
int _sock;
int _sockAccepted;
uint16_t _port;
uint8_t _maxClients;
bool _active;
bool _noDelay = false;
public:
WiFiServer(uint16_t port = 80, uint8_t maxClients = 4);
operator bool();
bool begin(uint16_t port = 0, bool reuseAddr = true);
void end();
WiFiClient accept();
size_t write(const uint8_t *buffer, size_t size) {
return 0;
}
void stopAll() {}
int setTimeout(uint32_t seconds);
void setNoDelay(bool noDelay);
bool getNoDelay();
bool hasClient();
};

View File

@@ -1,9 +0,0 @@
name=WiFi
version=1.0.1
author=Realtek
maintainer=Realtek <ameba.arduino@gmail.com>
sentence=Enables network connection (local and Internet).
paragraph=With this library you can instantiate Servers, Clients and send/receive UDP packets through WiFi.
category=Communication
url=http://www.amebaiot.com/ameba-arduino-peripherals-examples/
architectures=Ameba1

View File

@@ -1,203 +0,0 @@
/*
WiFi.cpp - Library for Arduino Wifi shield.
Copyright (c) 2011-2014 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
*/
#include "WiFi.h"
#include <inttypes.h>
#include "wifi_drv.h"
WiFiClass::WiFiClass() {
}
void WiFiClass::init() {
WiFiDrv::wifiDriverInit();
}
char* WiFiClass::firmwareVersion() {
return WiFiDrv::getFwVersion();
}
int WiFiClass::begin(char* ssid) {
uint8_t status = WL_IDLE_STATUS;
WiFiDrv::wifiDriverInit();
if (WiFiDrv::wifiSetNetwork(ssid, strlen(ssid)) != WL_FAILURE) {
status = WiFiDrv::getConnectionStatus();
} else {
status = WL_CONNECT_FAILED;
}
return status;
}
int WiFiClass::begin(char* ssid, uint8_t key_idx, const char *key) {
uint8_t status = WL_IDLE_STATUS;
WiFiDrv::wifiDriverInit();
// set encryption key
if (WiFiDrv::wifiSetKey(ssid, strlen(ssid), key_idx, key, strlen(key)) != WL_FAILURE) {
status = WiFiDrv::getConnectionStatus();
} else {
status = WL_CONNECT_FAILED;
}
return status;
}
int WiFiClass::begin(char* ssid, const char *passphrase) {
uint8_t status = WL_IDLE_STATUS;
WiFiDrv::wifiDriverInit();
// set passphrase
if (WiFiDrv::wifiSetPassphrase(ssid, strlen(ssid), passphrase, strlen(passphrase))!= WL_FAILURE) {
status = WiFiDrv::getConnectionStatus();
} else {
status = WL_CONNECT_FAILED;
}
return status;
}
int WiFiClass::disconnect() {
return WiFiDrv::disconnect();
}
uint8_t* WiFiClass::macAddress(uint8_t* mac) {
uint8_t* _mac = WiFiDrv::getMacAddress();
memcpy(mac, _mac, WL_MAC_ADDR_LENGTH);
return mac;
}
IPAddress WiFiClass::localIP() {
IPAddress ret;
WiFiDrv::getIpAddress(ret);
return ret;
}
IPAddress WiFiClass::subnetMask() {
IPAddress ret;
WiFiDrv::getSubnetMask(ret);
return ret;
}
IPAddress WiFiClass::gatewayIP() {
IPAddress ret;
WiFiDrv::getGatewayIP(ret);
return ret;
}
char* WiFiClass::SSID() {
return WiFiDrv::getCurrentSSID();
}
uint8_t* WiFiClass::BSSID(uint8_t* bssid) {
uint8_t* _bssid = WiFiDrv::getCurrentBSSID();
memcpy(bssid, _bssid, WL_MAC_ADDR_LENGTH);
return bssid;
}
int32_t WiFiClass::RSSI() {
return WiFiDrv::getCurrentRSSI();
}
uint8_t WiFiClass::encryptionType() {
return WiFiDrv::getCurrentEncryptionType();
}
int8_t WiFiClass::scanNetworks() {
uint8_t attempts = 10;
uint8_t numOfNetworks = 0;
if (WiFiDrv::startScanNetworks() == WL_FAILURE) {
return WL_FAILURE;
}
do {
delay(2000);
numOfNetworks = WiFiDrv::getScanNetworks();
} while (( numOfNetworks == 0)&&(--attempts>0));
return numOfNetworks;
}
char* WiFiClass::SSID(uint8_t networkItem) {
return WiFiDrv::getSSIDNetoworks(networkItem);
}
int32_t WiFiClass::RSSI(uint8_t networkItem) {
return WiFiDrv::getRSSINetoworks(networkItem);
}
uint8_t WiFiClass::encryptionType(uint8_t networkItem) {
return WiFiDrv::getEncTypeNetowrks(networkItem);
}
uint32_t WiFiClass::encryptionTypeEx(uint8_t networkItem) {
return WiFiDrv::getEncTypeNetowrksEx(networkItem);
}
uint8_t WiFiClass::status() {
return WiFiDrv::getConnectionStatus();
}
int WiFiClass::hostByName(const char* aHostname, IPAddress& aResult) {
return WiFiDrv::getHostByName(aHostname, aResult);
}
int WiFiClass::apbegin(char* ssid, char* channel) {
uint8_t status = WL_IDLE_STATUS;
if (WiFiDrv::apSetNetwork(ssid, strlen(ssid)) != WL_FAILURE) {
WiFiDrv::apSetChannel(channel);
if (WiFiDrv::apActivate() != WL_FAILURE) {
status = WL_CONNECTED;
} else {
status = WL_CONNECT_FAILED;
}
} else {
status = WL_CONNECT_FAILED;
}
return status;
}
int WiFiClass::apbegin(char* ssid, char* password, char* channel) {
uint8_t status = WL_IDLE_STATUS;
if (WiFiDrv::apSetNetwork(ssid, strlen(ssid)) != WL_FAILURE) {
WiFiDrv::apSetPassphrase(password, strlen(password));
WiFiDrv::apSetChannel(channel);
if(WiFiDrv::apActivate() != WL_FAILURE) {
status = WL_CONNECTED;
} else {
status = WL_CONNECT_FAILED;
}
} else {
status = WL_CONNECT_FAILED;
}
return status;
}
int WiFiClass::disablePowerSave() {
return WiFiDrv::disablePowerSave();
}
WiFiClass WiFi;

View File

@@ -1,255 +0,0 @@
/*
WiFi.h - Library for Arduino Wifi shield.
Copyright (c) 2011-2014 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 WiFi_h
#define WiFi_h
#include "Arduino.h"
#include <inttypes.h>
extern "C" {
#include "wl_definitions.h"
#include "wl_types.h"
}
#include "WiFiClient.h"
#include "WiFiServer.h"
#include "WiFiSSLClient.h"
class WiFiClass
{
private:
static void init();
public:
WiFiClass();
/*
* Get firmware version
*/
static char* firmwareVersion();
/* Start Wifi connection for OPEN networks
*
* param ssid: Pointer to the SSID string.
*/
int begin(char* ssid);
/* Start Wifi connection with WEP encryption.
* Configure a key into the device. The key type (WEP-40, WEP-104)
* is determined by the size of the key (5 bytes for WEP-40, 13 bytes for WEP-104).
*
* param ssid: Pointer to the SSID string.
* param key_idx: The key index to set. Valid values are 0-3.
* param key: Key input buffer.
*/
int begin(char* ssid, uint8_t key_idx, const char* key);
/* Start Wifi connection with passphrase
* the most secure supported mode will be automatically selected
*
* param ssid: Pointer to the SSID string.
* param passphrase: Passphrase. Valid characters in a passphrase
* must be between ASCII 32-126 (decimal).
*/
int begin(char* ssid, const char *passphrase);
/* Change Ip configuration settings disabling the dhcp client
*
* param local_ip: Static ip configuration
*/
void config(IPAddress local_ip);
/* Change Ip configuration settings disabling the dhcp client
*
* param local_ip: Static ip configuration
* param dns_server: IP configuration for DNS server 1
*/
void config(IPAddress local_ip, IPAddress dns_server);
/* Change Ip configuration settings disabling the dhcp client
*
* param local_ip: Static ip configuration
* param dns_server: IP configuration for DNS server 1
* param gateway : Static gateway configuration
*/
void config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway);
/* Change Ip configuration settings disabling the dhcp client
*
* param local_ip: Static ip configuration
* param dns_server: IP configuration for DNS server 1
* param gateway: Static gateway configuration
* param subnet: Static Subnet mask
*/
void config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet);
/* Change DNS Ip configuration
*
* param dns_server1: ip configuration for DNS server 1
*/
void setDNS(IPAddress dns_server1);
/* Change DNS Ip configuration
*
* param dns_server1: ip configuration for DNS server 1
* param dns_server2: ip configuration for DNS server 2
*
*/
void setDNS(IPAddress dns_server1, IPAddress dns_server2);
/*
* Disconnect from the network
*
* return: one value of wl_status_t enum
*/
int disconnect(void);
/*
* Get the interface MAC address.
*
* return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH
*/
uint8_t* macAddress(uint8_t* mac);
/*
* Get the interface IP address.
*
* return: Ip address value
*/
IPAddress localIP();
/*
* Get the interface subnet mask address.
*
* return: subnet mask address value
*/
IPAddress subnetMask();
/*
* Get the gateway ip address.
*
* return: gateway ip address value
*/
IPAddress gatewayIP();
/*
* Return the current SSID associated with the network
*
* return: ssid string
*/
char* SSID();
/*
* Return the current BSSID associated with the network.
* It is the MAC address of the Access Point
*
* return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH
*/
uint8_t* BSSID(uint8_t* bssid);
/*
* Return the current RSSI /Received Signal Strength in dBm)
* associated with the network
*
* return: signed value
*/
int32_t RSSI();
/*
* Return the Encryption Type associated with the network
*
* return: one value of wl_enc_type enum
*/
uint8_t encryptionType();
/*
* Start scan WiFi networks available
*
* return: Number of discovered networks
*/
int8_t scanNetworks();
/*
* Return the SSID discovered during the network scan.
*
* param networkItem: specify from which network item want to get the information
*
* return: ssid string of the specified item on the networks scanned list
*/
char* SSID(uint8_t networkItem);
/*
* Return the encryption type of the networks discovered during the scanNetworks
*
* param networkItem: specify from which network item want to get the information
*
* return: encryption type (enum wl_enc_type) of the specified item on the networks scanned list
*/
uint8_t encryptionType(uint8_t networkItem);
/*
* Return the security type and encryption type of the networks discovered during the scanNetworks
*
* param networkItem: specify from which network item want to get the information
*
* return: security and encryption type of the specified item on the networks scanned list
*/
uint32_t encryptionTypeEx(uint8_t networkItem);
/*
* Return the RSSI of the networks discovered during the scanNetworks
*
* param networkItem: specify from which network item want to get the information
*
* return: signed value of RSSI of the specified item on the networks scanned list
*/
int32_t RSSI(uint8_t networkItem);
/*
* Return Connection status.
*
* return: one of the value defined in wl_status_t
*/
uint8_t status();
/*
* Resolve the given hostname to an IP address.
* param aHostname: Name to be resolved
* param aResult: IPAddress structure to store the returned IP address
* result: 1 if aIPAddrString was successfully converted to an IP address,
* else error code
*/
int hostByName(const char* aHostname, IPAddress& aResult);
int apbegin(char* ssid, char* channel);
int apbegin(char* ssid, char* password, char* channel);
int disablePowerSave();
friend class WiFiClient;
friend class WiFiServer;
friend class WiFiSSLClient;
};
extern WiFiClass WiFi;
#endif

View File

@@ -1,191 +0,0 @@
extern "C" {
#include "wl_definitions.h"
#include "wl_types.h"
#include "string.h"
#include "errno.h"
#include "update.h"
}
#include "WiFi.h"
#include "WiFiClient.h"
#include "WiFiServer.h"
#include "server_drv.h"
WiFiClient::WiFiClient() : _sock(MAX_SOCK_NUM) {
_is_connected = false;
recvTimeout = 3000;
}
WiFiClient::WiFiClient(uint8_t sock) {
_sock = sock;
if(sock >= 0 && sock != 0xFF) {
_is_connected = true;
}
recvTimeout = 3000;
}
uint8_t WiFiClient::connected() {
if ((_sock < 0) || (_sock == 0xFF)) {
_is_connected = false;
return 0;
} else {
if (_is_connected) {
return 1;
} else {
stop();
return 0;
}
}
}
int WiFiClient::available() {
int ret = 0;
int err;
if( !_is_connected) {
return 0;
}
if (_sock >= 0) {
ret = clientdrv.availData(_sock);
if (ret > 0) {
return 1;
} else {
err = clientdrv.getLastErrno(_sock);
if (err != EAGAIN) {
_is_connected = false;
}
return 0;
}
}
}
int WiFiClient::read() {
int ret;
int err;
uint8_t b[1];
if (!available()) {
return -1;
}
ret = clientdrv.getData(_sock, b);
if (ret > 0) {
return b[0];
} else {
err = clientdrv.getLastErrno(_sock);
if (err != EAGAIN) {
_is_connected = false;
}
}
return ret;
}
int WiFiClient::read(uint8_t* buf, size_t size) {
uint16_t _size = size;
int ret;
int err;
ret = clientdrv.getDataBuf(_sock, buf, _size);
if (ret <= 0) {
err = clientdrv.getLastErrno(_sock);
if (err != EAGAIN) {
_is_connected = false;
}
}
return ret;
}
void WiFiClient::stop() {
if (_sock < 0) {
return;
}
clientdrv.stopClient(_sock);
_is_connected = false;
_sock = -1;
}
size_t WiFiClient::write(uint8_t b) {
return write(&b, 1);
}
size_t WiFiClient::write(const uint8_t *buf, size_t size) {
if (_sock < 0) {
setWriteError();
return 0;
}
if (size==0) {
setWriteError();
return 0;
}
if (!clientdrv.sendData(_sock, buf, size)) {
setWriteError();
_is_connected = false;
return 0;
}
return size;
}
WiFiClient::operator bool() {
return _sock >= 0;
}
int WiFiClient::connect(const char* host, uint16_t port) {
IPAddress remote_addr;
if (WiFi.hostByName(host, remote_addr)) {
return connect(remote_addr, port);
}
return 0;
}
int WiFiClient::connect(IPAddress ip, uint16_t port) {
_is_connected = false;
_sock = clientdrv.startClient(ip, port);
if (_sock < 0) {
_is_connected = false;
return 0;
} else {
_is_connected = true;
clientdrv.setSockRecvTimeout(_sock, recvTimeout);
}
return 1;
}
int WiFiClient::peek() {
uint8_t b;
if (!available()) {
return -1;
}
clientdrv.getData(_sock, &b, 1);
return b;
}
void WiFiClient::flush() {
while (available()) {
read();
}
}
// extend API from RTK
int WiFiClient::setRecvTimeout(int timeout) {
if (connected()) {
recvTimeout = timeout;
clientdrv.setSockRecvTimeout(_sock, recvTimeout);
}
}
int WiFiClient::read(char *buf, size_t size) {
read((uint8_t *)buf, size);
}

View File

@@ -1,55 +0,0 @@
#ifndef wificlient_h
#define wificlient_h
#include "Arduino.h"
#include "api/Client.h"
#include "server_drv.h"
class WiFiClient : public Client {
public:
WiFiClient();
WiFiClient(uint8_t sock);
uint8_t status();
virtual int connect(IPAddress ip, uint16_t port);
virtual int connect(const char *host, uint16_t port);
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buf, size_t size);
virtual int available();
virtual int read();
virtual int read(uint8_t *buf, size_t size);
virtual int peek();
virtual void flush();
virtual void stop();
virtual uint8_t connected();
virtual operator bool();
friend class WiFiServer;
using Print::write;
// extend API from RTK
int setRecvTimeout(int timeout);
int read(char *buf, size_t size);
private:
int _sock;
ServerDrv clientdrv;
bool _is_connected;
uint8_t data[DATA_LENTH];
int recvTimeout;
};
#ifdef __cplusplus
extern "C" {
#endif
extern int update_ota_local(char *ip, int port);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,271 +0,0 @@
#include "WiFi.h"
#include "WiFiSSLClient.h"
extern "C" {
#include "wl_definitions.h"
#include "wl_types.h"
#include "string.h"
#include "errno.h"
}
WiFiSSLClient::WiFiSSLClient() {
_is_connected = false;
_sock = -1;
sslclient.socket = -1;
sslclient.ssl = NULL;
sslclient.recvTimeout = 3000;
_rootCABuff = NULL;
_cli_cert = NULL;
_cli_key = NULL;
_psKey = NULL;
_pskIdent = NULL;
_sni_hostname = NULL;
}
WiFiSSLClient::WiFiSSLClient(uint8_t sock) {
_sock = sock;
sslclient.socket = -1;
sslclient.ssl = NULL;
sslclient.recvTimeout = 3000;
// if(sock >= 0) {
// _is_connected = true;
// }
_is_connected = true;
_rootCABuff = NULL;
_cli_cert = NULL;
_cli_key = NULL;
_psKey = NULL;
_pskIdent = NULL;
_sni_hostname = NULL;
}
uint8_t WiFiSSLClient::connected() {
if (sslclient.socket < 0) {
_is_connected = false;
return 0;
} else {
if (_is_connected) {
return 1;
} else {
stop();
return 0;
}
}
}
int WiFiSSLClient::available() {
int ret = 0;
int err;
if (!_is_connected) {
return 0;
}
if (sslclient.socket >= 0) {
ret = ssldrv.availData(&sslclient);
if (ret > 0) {
return 1;
} else {
err = ssldrv.getLastErrno(&sslclient);
if ((err > 0) && (err != EAGAIN)) {
_is_connected = false;
}
}
return 0;
}
return 0;
}
int WiFiSSLClient::read() {
int ret;
int err;
uint8_t b[1];
if (!available()) {
return -1;
}
ret = ssldrv.getData(&sslclient, b);
if (ret > 0) {
return b[0];
} else {
err = ssldrv.getLastErrno(&sslclient);
if ((err > 0) && (err != EAGAIN)) {
_is_connected = false;
}
}
return -1;
}
int WiFiSSLClient::read(uint8_t* buf, size_t size) {
uint16_t _size = size;
int ret;
int err;
ret = ssldrv.getDataBuf(&sslclient, buf, _size);
if (ret <= 0) {
err = ssldrv.getLastErrno(&sslclient);
if ((err > 0) && (err != EAGAIN)) {
_is_connected = false;
}
}
return ret;
}
void WiFiSSLClient::stop() {
if (sslclient.socket < 0) {
return;
}
ssldrv.stopClient(&sslclient);
_is_connected = false;
sslclient.socket = -1;
_sock = -1;
}
size_t WiFiSSLClient::write(uint8_t b) {
return write(&b, 1);
}
size_t WiFiSSLClient::write(const uint8_t *buf, size_t size) {
if (sslclient.socket < 0) {
setWriteError();
return 0;
}
if (size == 0) {
setWriteError();
return 0;
}
if (!ssldrv.sendData(&sslclient, buf, size)) {
setWriteError();
_is_connected = false;
return 0;
}
return size;
}
WiFiSSLClient::operator bool() {
return (sslclient.socket >= 0);
}
int WiFiSSLClient::connect(IPAddress ip, uint16_t port) {
if (_psKey != NULL && _pskIdent != NULL)
return connect(ip, port, _pskIdent, _psKey);
return connect(ip, port, _rootCABuff, _cli_cert, _cli_key);
}
int WiFiSSLClient::connect(const char *host, uint16_t port) {
if (_sni_hostname == NULL) {
_sni_hostname = (char*)host;
}
if (_psKey != NULL && _pskIdent != NULL)
return connect(host, port, _pskIdent, _psKey);
return connect(host, port, _rootCABuff, _cli_cert, _cli_key);
}
int WiFiSSLClient::connect(const char* host, uint16_t port, unsigned char* rootCABuff, unsigned char* cli_cert, unsigned char* cli_key) {
IPAddress remote_addr;
if (_sni_hostname == NULL) {
_sni_hostname = (char*)host;
}
if (WiFi.hostByName(host, remote_addr)) {
return connect(remote_addr, port, rootCABuff, cli_cert, cli_key);
}
return 0;
}
int WiFiSSLClient::connect(IPAddress ip, uint16_t port, unsigned char* rootCABuff, unsigned char* cli_cert, unsigned char* cli_key) {
int ret = 0;
ret = ssldrv.startClient(&sslclient, uint32_t(ip), port, rootCABuff, cli_cert, cli_key, NULL, NULL, _sni_hostname);
if (ret < 0) {
_is_connected = false;
return 0;
} else {
_is_connected = true;
}
return 1;
}
int WiFiSSLClient::connect(const char *host, uint16_t port, unsigned char* pskIdent, unsigned char* psKey) {
IPAddress remote_addr;
if (_sni_hostname == NULL) {
_sni_hostname = (char*)host;
}
if (WiFi.hostByName(host, remote_addr)) {
return connect(remote_addr, port, pskIdent, psKey);
}
return 0;
}
int WiFiSSLClient::connect(IPAddress ip, uint16_t port, unsigned char* pskIdent, unsigned char* psKey) {
int ret = 0;
ret = ssldrv.startClient(&sslclient, uint32_t(ip), port, NULL, NULL, NULL, pskIdent, psKey, _sni_hostname);
if (ret < 0) {
_is_connected = false;
return 0;
} else {
_is_connected = true;
}
return 1;
}
int WiFiSSLClient::peek() {
uint8_t b;
if (!available()) {
return -1;
}
ssldrv.getData(&sslclient, &b, 1);
return b;
}
void WiFiSSLClient::flush() {
while (available()) {
read();
}
}
void WiFiSSLClient::setRootCA(unsigned char *rootCA) {
_rootCABuff = rootCA;
}
void WiFiSSLClient::setClientCertificate(unsigned char *client_ca, unsigned char *private_key) {
_cli_cert = client_ca;
_cli_key = private_key;
}
void WiFiSSLClient::setPreSharedKey(unsigned char *pskIdent, unsigned char *psKey) {
_psKey = psKey;
_pskIdent = pskIdent;
}
int WiFiSSLClient::setRecvTimeout(int timeout) {
sslclient.recvTimeout = timeout;
if (connected()) {
ssldrv.setSockRecvTimeout(sslclient.socket, sslclient.recvTimeout);
}
return 0;
}

View File

@@ -1,55 +0,0 @@
#ifndef wifisslclient_h
#define wifisslclient_h
#include "Arduino.h"
#include "api/Client.h"
#include "ssl_drv.h"
struct mbedtls_ssl_context;
class WiFiSSLClient : public Client {
public:
WiFiSSLClient();
WiFiSSLClient(uint8_t sock);
uint8_t status();
virtual int connect(IPAddress ip, uint16_t port);
virtual int connect(const char *host, uint16_t port);
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buf, size_t size);
virtual int available();
virtual int read();
virtual int read(uint8_t *buf, size_t size);
virtual int peek();
virtual void flush();
virtual void stop();
virtual uint8_t connected();
virtual operator bool();
void setRootCA(unsigned char *rootCA);
void setClientCertificate(unsigned char *client_ca, unsigned char *private_key);
void setPreSharedKey(unsigned char *pskIdent, unsigned char *psKey); // psKey expressed as hexadecimal string
int connect(const char *host, uint16_t port, unsigned char* rootCABuff, unsigned char* cli_cert, unsigned char* cli_key);
int connect(IPAddress ip, uint16_t port, unsigned char* rootCABuff, unsigned char* cli_cert, unsigned char* cli_key);
int connect(const char *host, uint16_t port, unsigned char* pskIdent, unsigned char* psKey);
int connect(IPAddress ip, uint16_t port, unsigned char* pskIdent, unsigned char* psKey);
using Print::write;
int setRecvTimeout(int timeout);
private:
int _sock;
bool _is_connected;
sslclient_context sslclient;
SSLDrv ssldrv;
unsigned char *_rootCABuff;
unsigned char *_cli_cert;
unsigned char *_cli_key;
unsigned char *_psKey;
unsigned char *_pskIdent;
char *_sni_hostname;
};
#endif

View File

@@ -1,88 +0,0 @@
/*
WiFiServer.cpp - Library for Arduino Wifi shield.
Copyright (c) 2011-2014 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
*/
#include <string.h>
#include "server_drv.h"
#include "WiFi.h"
#include "WiFiClient.h"
#include "WiFiServer.h"
WiFiServer::WiFiServer(uint16_t port) {
_port = port;
}
void WiFiServer::begin() {
_sock_ser = serverfd.startServer(_port);
}
WiFiClient WiFiServer::available(uint8_t* status) {
int client_fd;
client_fd = serverfd.getAvailable(_sock_ser);
return WiFiClient(client_fd);
}
size_t WiFiServer::write(uint8_t b) {
return write(&b, 1);
}
size_t WiFiServer::write(const uint8_t *buf, size_t size) {
if (_sock_ser < 0) {
setWriteError();
return 0;
}
if (size == 0) {
setWriteError();
return 0;
}
if (!serverfd.sendData(_sock_ser, buf, size)) {
setWriteError();
return 0;
}
return size;
}
#if 0
uint8_t WiFiServer::status() {
return ServerDrv::getServerState(0);
}
size_t WiFiServer::write(uint8_t b) {
return write(&b, 1);
}
size_t WiFiServer::write(const uint8_t *buffer, size_t size) {
size_t n = 0;
for (int sock = 0; sock < MAX_SOCK_NUM; sock++) {
if (WiFiClass::_server_port[sock] != 0) {
WiFiClient client(sock);
if ((WiFiClass::_server_port[sock] == _port) && (client.status() == ESTABLISHED)) {
n+=client.write(buffer, size);
}
}
}
return n;
}
#endif

View File

@@ -1,29 +0,0 @@
#ifndef wifiserver_h
#define wifiserver_h
#include "Arduino.h"
#include "api/Server.h"
#include "server_drv.h"
class WiFiClient;
class WiFiServer : public Server {
private:
uint16_t _port;
int _sock_ser;
ServerDrv serverfd;
public:
WiFiServer(uint16_t);
WiFiClient available(uint8_t* status = NULL);
void begin();
virtual size_t write(uint8_t b);
virtual size_t write(const uint8_t *buf, size_t size);
//uint8_t status();
using Print::write;
};
#endif

View File

@@ -1,192 +0,0 @@
/*
WiFiUdp.cpp - Library for Arduino Wifi shield.
Copyright (c) 2011-2014 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
*/
#ifdef __cplusplus
extern "C" {
extern int rtl_printf(const char *fmt, ...);
}
#endif
#include <string.h>
#include "server_drv.h"
#include "wifi_drv.h"
#include "WiFi.h"
#include "WiFiUdp.h"
#include "WiFiClient.h"
#include "WiFiServer.h"
/* Constructor */
WiFiUDP::WiFiUDP() : _sock(-1), _client_sock(-1) {}
/* Start WiFiUDP socket, listening at local port PORT */
uint8_t WiFiUDP::begin(uint16_t port) {
if (_port == port && _sock >= 0) {
return 1;
}
_port = port;
_sock = serverDrv.startServer(port, UDP_MODE);
if (_sock >=0 ) {
return 1;
}
return 0;
}
/* return number of bytes available in the current packet,
will return zero if parsePacket hasn't been called yet */
int WiFiUDP::available() {
int ret;
if (_sock >= 0) {
ret = serverDrv.availData(_sock);
if (ret > 0) {
return ret;
} else {
return 0;
}
}
return 0;
}
/* Release any resources being used by this WiFiUDP instance */
void WiFiUDP::stop() {
if (_sock < 0) {
return;
}
serverDrv.stopClient(_sock);
_sock = -1;
}
int WiFiUDP::beginPacket(const char *host, uint16_t port) {
// Look up the host first
int ret = 0;
IPAddress remote_addr;
if (WiFi.hostByName(host, remote_addr)) {
return beginPacket(remote_addr, port);
}
return ret;
}
int WiFiUDP::beginPacket(IPAddress ip, uint16_t port) {
peer_ip = ip;
peer_port = port;
if (_sock >= 0) {
_client_sock = _sock;
} else {
_client_sock = serverDrv.startClient(ip, port, UDP_MODE);
}
if (_client_sock < 0) {
return 0;
} else {
return 1;
}
}
int WiFiUDP::endPacket() {
if (_client_sock >= 0 && _client_sock != _sock) {
serverDrv.stopClient(_client_sock);
}
peer_ip = 0;
peer_port = 0;
_client_sock = -1;
return true;
}
size_t WiFiUDP::write(uint8_t byte) {
return write(&byte, 1);
}
size_t WiFiUDP::write(const uint8_t *buffer, size_t size) {
writeImmediately(buffer, size);
return size;
}
size_t WiFiUDP::writeImmediately(const uint8_t *buffer, size_t size) {
serverDrv.sendtoData(_client_sock, buffer, size, peer_ip, peer_port);
return size;
}
int WiFiUDP::parsePacket() {
return available();
}
int WiFiUDP::read() {
int ret;
uint8_t b;
ret = serverDrv.getData(_sock, &b);
if (ret == 1) {
return b;
} else {
return ret;
}
}
int WiFiUDP::read(unsigned char* buffer, size_t len) {
return serverDrv.getDataBuf(_sock, buffer, len);
}
int WiFiUDP::peek() {
uint8_t b;
if (!available()) {
return -1;
}
serverDrv.getData(_sock, &b, 1);
return b;
}
void WiFiUDP::flush() {
while (read() > 0);
}
IPAddress WiFiUDP::remoteIP() {
uint32_t _remoteIp;
uint16_t _remotePort;
serverDrv.getRemoteData(_sock, &_remoteIp, &_remotePort);
IPAddress ip(_remoteIp);
return ip;
}
uint16_t WiFiUDP::remotePort() {
uint32_t _remoteIp;
uint16_t _remotePort;
serverDrv.getRemoteData(_sock, &_remoteIp, &_remotePort);
return _remotePort;
}
// extend API by RTK
void WiFiUDP::setRecvTimeout(int timeout) {
if (_sock >= 0) {
serverDrv.setSockRecvTimeout(_sock, timeout);
}
}

View File

@@ -1,95 +0,0 @@
/*
WiFiUdp.h - Library for Arduino Wifi shield.
Copyright (c) 2011-2014 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 wifiudp_h
#define wifiudp_h
#include "Arduino.h"
#include <Udp.h>
#include "server_drv.h"
#define UDP_TX_PACKET_MAX_SIZE 24
class WiFiUDP : public UDP {
private:
int _sock; // socket ID
uint16_t _port; // local port to listen on
ServerDrv serverDrv; // socket driver
int _client_sock;
uint32_t peer_ip;
uint32_t peer_port;
public:
WiFiUDP(); // Constructor
virtual uint8_t begin(uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
virtual void stop(); // 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);
// 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);
// Finish off this packet and send it
// Returns 1 if the packet was sent successfully, 0 if there was an error
virtual int endPacket();
// Write a single byte into the packet
virtual size_t write(uint8_t);
// Write size bytes from buffer into the packet
virtual size_t write(const uint8_t *buffer, size_t size);
// Send packet immediately from buffer
size_t writeImmediately(const uint8_t *buffer, size_t size);
using Print::write;
// 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();
// Number of bytes remaining in the current packet
virtual int available();
// Read a single byte from the current packet
virtual int read();
// 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);
// 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) { return read((unsigned char*)buffer, len); };
// Return the next byte from the current packet without moving on to the next byte
virtual int peek();
virtual void flush(); // Finish reading the current packet
// Return the IP address of the host who sent the current incoming packet
virtual IPAddress remoteIP();
// Return the port of the host who sent the current incoming packet
virtual uint16_t remotePort();
friend class WiFiDrv;
// extend API by RTK
void setRecvTimeout(int timeout);
};
#endif

View File

@@ -0,0 +1,8 @@
{
"build": {
"bkcrypt_coeffs": "510fb093a3cbeadc5993a17ec7adeb03"
},
"flash": {
"tuya": "0x1ED000+0x13000"
}
}

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