Compare commits
50 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a21c07fa03 | ||
|
|
bdffa7ef53 | ||
|
|
22d40825bb | ||
|
|
50f26f546c | ||
|
|
9c7ea46ec3 | ||
|
|
5b4cf53d8a | ||
|
|
79a701a4d4 | ||
|
|
81897e634c | ||
|
|
3e11da4dd4 | ||
|
|
12aa7fef04 | ||
|
|
1ea6420bbc | ||
|
|
f3f1f36525 | ||
|
|
dee9a98cc3 | ||
|
|
3345ce3fb9 | ||
|
|
de70583838 | ||
|
|
a43a737004 | ||
|
|
1f6899354f | ||
|
|
9110a0c47e | ||
|
|
b549790798 | ||
|
|
5df430f3be | ||
|
|
f3e8bcd74a | ||
|
|
4b050e11cf | ||
|
|
7ddbc09564 | ||
|
|
d3d62f80fd | ||
|
|
bc7dbe6eec | ||
|
|
e625f55353 | ||
|
|
aeebff9d5d | ||
|
|
9a3c077ef1 | ||
|
|
91ae692058 | ||
|
|
ad590d1eb2 | ||
|
|
8b00358901 | ||
|
|
bf4d8bb9be | ||
|
|
157dd2f407 | ||
|
|
1dc47878d4 | ||
|
|
36e4b6fd45 | ||
|
|
36d9a6e7e4 | ||
|
|
b7cceed4d3 | ||
|
|
694c06e7f5 | ||
|
|
12338747bf | ||
|
|
f4f9788f68 | ||
|
|
b9cdcad262 | ||
|
|
e4cd2ddec8 | ||
|
|
1477649a50 | ||
|
|
2e80469ab3 | ||
|
|
ccf63a4cdb | ||
|
|
b464871f73 | ||
|
|
e44834a95e | ||
|
|
4efefc5c6c | ||
|
|
dfd852b2db | ||
|
|
afa7141ceb |
5
.github/workflows/docs.yml
vendored
5
.github/workflows/docs.yml
vendored
@@ -1,11 +1,12 @@
|
||||
name: Deploy docs on GitHub Pages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
docs:
|
||||
name: Deploy docs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -17,5 +18,5 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CONFIG_FILE: mkdocs.yml
|
||||
EXTRA_PACKAGES: build-base
|
||||
EXTRA_PACKAGES: build-base doxygen
|
||||
REQUIREMENTS: docs/requirements.txt
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -252,3 +252,9 @@ cython_debug/
|
||||
# End of https://www.toptal.com/developers/gitignore/api/c,c++,visualstudiocode,python
|
||||
|
||||
.vscode/settings.json
|
||||
|
||||
# mkdocs
|
||||
xml/
|
||||
ltapi/
|
||||
ltambz/
|
||||
hashChanges.yaml
|
||||
|
||||
2
.gitmodules
vendored
Normal file
2
.gitmodules
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
[submodule "tools/boardgen"]
|
||||
url = https://github.com/kuba2k2/boardgen
|
||||
101
README.md
101
README.md
@@ -2,26 +2,26 @@
|
||||
|
||||
<div align="center" markdown>
|
||||
|
||||
[](https://kuba2k2.github.io/libretuya/)
|
||||

|
||||
[](https://kuba2k2.github.io/libretuya/)
|
||||

|
||||
|
||||
[](https://github.com/psf/black)
|
||||
[](.clang-format)
|
||||
[](https://github.com/psf/black)
|
||||
|
||||
[](https://discord.gg/SyGCB9Xwtf)
|
||||
[](https://registry.platformio.org/platforms/kuba2k2/libretuya)
|
||||
|
||||

|
||||
|
||||
<!-- [](https://registry.platformio.org/platforms/kuba2k2/libretuya) -->
|
||||
</div>
|
||||
|
||||
PlatformIO development platform for IoT modules manufactured by Tuya Inc.
|
||||
|
||||
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 Tuya IoT (and 3-rd party) modules.
|
||||
|
||||
LibreTuya also provides a common interface for all platform implementations. The interface is based on ESP32 official libraries.
|
||||
LibreTuya also provides a common interface for all family implementations. The interface is based on ESP32 official libraries.
|
||||
|
||||
**Note:** this project is work-in-progress.
|
||||
|
||||
@@ -36,7 +36,7 @@ LibreTuya also provides a common interface for all platform implementations. The
|
||||
|
||||
A (mostly) complete* list of Tuya wireless module boards.
|
||||
|
||||
| Module Name | MCU | Flash | RAM | Pins** | Wi-Fi | BLE | Platform name
|
||||
| Module Name | MCU | Flash | RAM | Pins** | Wi-Fi | BLE | Family 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) | ✔️ | ✔️ | -
|
||||
@@ -92,78 +92,6 @@ A (mostly) complete* list of Tuya wireless module boards.
|
||||
|
||||
** 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 SoC
|
||||
│ ├─ cores/ Wiring core files
|
||||
│ ├─ libraries/ Supported built-in platform libraries
|
||||
├─ libretuya/
|
||||
│ ├─ api/ LibreTuya API (interfaces + LT class) for Arduino frameworks
|
||||
│ ├─ common/ Units common to all platforms
|
||||
│ ├─ 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
|
||||
├─ utils.py SCons utils used during the build
|
||||
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.
|
||||
@@ -178,22 +106,21 @@ Flash I/O | ❓
|
||||
**CORE LIBRARIES** |
|
||||
SoftwareSerial | ❌
|
||||
SPI | ❌
|
||||
Wire | ❌
|
||||
Wire | ❗
|
||||
**OTHER LIBRARIES** |
|
||||
Wi-Fi STA/AP/Mixed | ✔️
|
||||
Wi-Fi Client (SSL) | ✔️ (✔️)
|
||||
Wi-Fi Server | ✔️
|
||||
Wi-Fi Events | ❌
|
||||
Wi-Fi Events | ✔️
|
||||
IPv6 | ❌
|
||||
HTTP Client (SSL) | ✔️ (❌)
|
||||
HTTP Client (SSL) | ✔️ (✔️)
|
||||
HTTP Server | ✔️
|
||||
NVS / Preferences | ❌
|
||||
NVS / Preferences | ✔️
|
||||
SPIFFS | ❌
|
||||
BLE | -
|
||||
HTTP | ❌
|
||||
NTP | ❌
|
||||
OTA | ❌
|
||||
MDNS | ❌
|
||||
OTA | ❓
|
||||
MDNS | ✔️
|
||||
MQTT | ✅
|
||||
SD | ❌
|
||||
|
||||
|
||||
55
SUMMARY.md
Normal file
55
SUMMARY.md
Normal file
@@ -0,0 +1,55 @@
|
||||
* [Home](README.md)
|
||||
* [💻 Family list](docs/families.md)
|
||||
* [✔️ Implementation status](docs/implementation-status.md)
|
||||
* [🔧 Configuration](docs/config.md)
|
||||
* [📁 Project structure](docs/project-structure.md)
|
||||
* 🔖 Code reference
|
||||
* [LibreTuya API](docs/reference/lt-api.md)
|
||||
* [Class reference](ltapi/class_libre_tuya.md)
|
||||
* [Static functions](ltapi/_libre_tuya_a_p_i_8cpp.md)
|
||||
* [Logger](ltapi/lt__logger_8h.md)
|
||||
* [Chip types & UF2 families](ltapi/_chip_type_8h.md)
|
||||
* [POSIX utilities](ltapi/lt__posix__api_8h.md)
|
||||
* Common API
|
||||
* [Flash](ltapi/class_i_flash_class.md)
|
||||
* [FS](ltapi/classfs_1_1_f_s.md)
|
||||
* [Preferences](ltapi/class_i_preferences.md)
|
||||
* [WiFi API](ltapi/class_i_wi_fi_generic_class.md)
|
||||
* [Station](ltapi/class_i_wi_fi_s_t_a_class.md)
|
||||
* [Access Point](ltapi/class_i_wi_fi_a_p_class.md)
|
||||
* [Scanning](ltapi/class_i_wi_fi_scan_class.md)
|
||||
* [TCP Client](ltapi/class_i_wi_fi_client.md)
|
||||
* [SSL Client](ltapi/class_i_wi_fi_client_secure.md)
|
||||
* [TCP Server](ltapi/class_i_wi_fi_server.md)
|
||||
* [LibreTuya libraries](docs/libs-built-in.md)
|
||||
* [base64](ltapi/classbase64.md)
|
||||
* [HTTPClient](ltapi/class_h_t_t_p_client.md)
|
||||
* [mDNS](ltapi/classm_d_n_s.md)
|
||||
* NetUtils
|
||||
* [ssl/MbedTLSClient](ltapi/class_mbed_t_l_s_client.md)
|
||||
* [IPv6Address](ltapi/classarduino_1_1_i_pv6_address.md)
|
||||
* [LwIPRxBuffer](ltapi/class_lw_i_p_rx_buffer.md)
|
||||
* [Update](ltapi/class_update_class.md)
|
||||
* [WebServer](ltapi/class_web_server.md)
|
||||
* [WiFiMulti](ltapi/class_wi_fi_multi.md)
|
||||
* [Third party libraries](docs/libs-3rd-party.md)
|
||||
* Full documentation
|
||||
* [Classes](ltapi/classes.md)
|
||||
* [Functions](ltapi/functions.md)
|
||||
* [Macros](ltapi/macros.md)
|
||||
* [File list](ltapi/files.md)
|
||||
* [✈️ OTA format](docs/ota/README.md)
|
||||
* [uf2ota.py tool](docs/ota/uf2ota.md)
|
||||
* [uf2ota.h library](docs/ota/library.md)
|
||||
* [uf2ota.h reference](ltapi/uf2ota_8h.md)
|
||||
* Families
|
||||
* [Realtek - notes](docs/platform/realtek/README.md)
|
||||
* Realtek AmebaZ Series
|
||||
* Boards
|
||||
* [WR3](boards/wr3/README.md)
|
||||
* C library
|
||||
* [Built-in functions](docs/platform/realtek-ambz/stdlib.md)
|
||||
* [Memory management](docs/platform/realtek-ambz/memory-management.md)
|
||||
* [Debugging](docs/platform/realtek/debugging.md)
|
||||
* [Exception decoder](docs/platform/realtek/exception-decoder.md)
|
||||
* [🔗 Resources](docs/resources.md)
|
||||
5
arduino/libretuya/api/Events.cpp
Normal file
5
arduino/libretuya/api/Events.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-17. */
|
||||
|
||||
#include "Events.h"
|
||||
|
||||
uint16_t EventHandler_s::lastId = 1;
|
||||
117
arduino/libretuya/api/Events.h
Normal file
117
arduino/libretuya/api/Events.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
ESP8266WiFiGeneric.h - esp8266 Wifi support.
|
||||
Based on WiFi.h from Ardiono WiFi shield library.
|
||||
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
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "WiFiEvents.h"
|
||||
|
||||
typedef enum {
|
||||
ARDUINO_EVENT_WIFI_READY = 0, /**< ESP32 WiFi ready */
|
||||
ARDUINO_EVENT_WIFI_SCAN_DONE, /**< ESP32 finish scanning AP */
|
||||
ARDUINO_EVENT_WIFI_STA_START, /**< ESP32 station start */
|
||||
ARDUINO_EVENT_WIFI_STA_STOP, /**< ESP32 station stop */
|
||||
ARDUINO_EVENT_WIFI_STA_CONNECTED, /**< ESP32 station connected to AP */
|
||||
ARDUINO_EVENT_WIFI_STA_DISCONNECTED, /**< ESP32 station disconnected from AP */
|
||||
ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE, /**< the auth mode of AP connected by ESP32 station changed */
|
||||
ARDUINO_EVENT_WIFI_STA_GOT_IP,
|
||||
ARDUINO_EVENT_WIFI_STA_GOT_IP6,
|
||||
ARDUINO_EVENT_WIFI_STA_LOST_IP,
|
||||
ARDUINO_EVENT_WIFI_AP_START, /**< ESP32 soft-AP start */
|
||||
ARDUINO_EVENT_WIFI_AP_STOP, /**< ESP32 soft-AP stop */
|
||||
ARDUINO_EVENT_WIFI_AP_STACONNECTED, /**< a station connected to ESP32 soft-AP */
|
||||
ARDUINO_EVENT_WIFI_AP_STADISCONNECTED, /**< a station disconnected from ESP32 soft-AP */
|
||||
ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED,
|
||||
ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED, /**< Receive probe request packet in soft-AP interface */
|
||||
ARDUINO_EVENT_WIFI_AP_GOT_IP6,
|
||||
ARDUINO_EVENT_WIFI_FTM_REPORT, /**< Receive report of FTM procedure */
|
||||
ARDUINO_EVENT_ETH_START,
|
||||
ARDUINO_EVENT_ETH_STOP,
|
||||
ARDUINO_EVENT_ETH_CONNECTED,
|
||||
ARDUINO_EVENT_ETH_DISCONNECTED,
|
||||
ARDUINO_EVENT_ETH_GOT_IP,
|
||||
ARDUINO_EVENT_ETH_GOT_IP6,
|
||||
ARDUINO_EVENT_WPS_ER_SUCCESS, /**< ESP32 station wps succeeds in enrollee mode */
|
||||
ARDUINO_EVENT_WPS_ER_FAILED, /**< ESP32 station wps fails in enrollee mode */
|
||||
ARDUINO_EVENT_WPS_ER_TIMEOUT, /**< ESP32 station wps timeout in enrollee mode */
|
||||
ARDUINO_EVENT_WPS_ER_PIN, /**< ESP32 station wps pin code in enrollee mode */
|
||||
ARDUINO_EVENT_WPS_ER_PBC_OVERLAP, /**< ESP32 station wps overlap in enrollee mode */
|
||||
ARDUINO_EVENT_SC_SCAN_DONE,
|
||||
ARDUINO_EVENT_SC_FOUND_CHANNEL,
|
||||
ARDUINO_EVENT_SC_GOT_SSID_PSWD,
|
||||
ARDUINO_EVENT_SC_SEND_ACK_DONE,
|
||||
ARDUINO_EVENT_PROV_INIT,
|
||||
ARDUINO_EVENT_PROV_DEINIT,
|
||||
ARDUINO_EVENT_PROV_START,
|
||||
ARDUINO_EVENT_PROV_END,
|
||||
ARDUINO_EVENT_PROV_CRED_RECV,
|
||||
ARDUINO_EVENT_PROV_CRED_FAIL,
|
||||
ARDUINO_EVENT_PROV_CRED_SUCCESS,
|
||||
ARDUINO_EVENT_MAX
|
||||
} arduino_event_id_t;
|
||||
|
||||
typedef union {
|
||||
wifi_event_sta_scan_done_t wifi_scan_done;
|
||||
wifi_event_sta_authmode_change_t wifi_sta_authmode_change;
|
||||
wifi_event_sta_connected_t wifi_sta_connected;
|
||||
wifi_event_sta_disconnected_t wifi_sta_disconnected;
|
||||
wifi_event_sta_wps_er_pin_t wps_er_pin;
|
||||
wifi_event_sta_wps_fail_reason_t wps_fail_reason;
|
||||
wifi_event_ap_probe_req_rx_t wifi_ap_probereqrecved;
|
||||
wifi_event_ap_staconnected_t wifi_ap_staconnected;
|
||||
wifi_event_ap_stadisconnected_t wifi_ap_stadisconnected;
|
||||
wifi_event_ftm_report_t wifi_ftm_report;
|
||||
ip_event_ap_staipassigned_t wifi_ap_staipassigned;
|
||||
ip_event_got_ip_t got_ip;
|
||||
ip_event_got_ip6_t got_ip6;
|
||||
// smartconfig_event_got_ssid_pswd_t sc_got_ssid_pswd;
|
||||
// esp_eth_handle_t eth_connected;
|
||||
// wifi_sta_config_t prov_cred_recv;
|
||||
// wifi_prov_sta_fail_reason_t prov_fail_reason;
|
||||
} arduino_event_info_t;
|
||||
|
||||
typedef struct {
|
||||
arduino_event_id_t event_id;
|
||||
arduino_event_info_t event_info;
|
||||
} arduino_event_t;
|
||||
|
||||
#define EventId arduino_event_id_t
|
||||
#define EventId_t arduino_event_id_t
|
||||
#define EventInfo arduino_event_info_t
|
||||
#define EventInfo_t arduino_event_info_t
|
||||
#define Event_t arduino_event_t
|
||||
|
||||
typedef void (*EventCb)(EventId event);
|
||||
typedef std::function<void(EventId event, EventInfo info)> EventFuncCb;
|
||||
typedef void (*EventSysCb)(Event_t *event);
|
||||
|
||||
typedef struct EventHandler_s {
|
||||
static uint16_t lastId;
|
||||
uint16_t id;
|
||||
EventCb cb;
|
||||
EventFuncCb fcb;
|
||||
EventSysCb scb;
|
||||
EventId eventId;
|
||||
|
||||
EventHandler_s() : id(lastId++), cb(NULL), fcb(NULL), scb(NULL) {}
|
||||
} EventHandler;
|
||||
@@ -1,17 +0,0 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-29. */
|
||||
|
||||
#include "LibreTuyaAPI.h"
|
||||
|
||||
__weak char *strdup(const char *s) {
|
||||
size_t len = strlen(s) + 1;
|
||||
void *newp = malloc(len);
|
||||
if (newp == NULL)
|
||||
return NULL;
|
||||
return (char *)memcpy(newp, s, len);
|
||||
}
|
||||
|
||||
String ipToString(const IPAddress &ip) {
|
||||
char szRet[16];
|
||||
sprintf(szRet, "%hhu.%hhu.%hhu.%hhu", ip[0], ip[1], ip[2], ip[3]);
|
||||
return String(szRet);
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-28. */
|
||||
|
||||
#pragma once
|
||||
|
||||
// LibreTuya version macros
|
||||
#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)
|
||||
|
||||
// Includes
|
||||
#include "LibreTuyaConfig.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
// C includes
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#include "lt_logger.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
// Functional macros
|
||||
#define LT_BANNER() \
|
||||
LT_LOG( \
|
||||
LT_LEVEL_INFO, \
|
||||
__FUNCTION__, \
|
||||
__LINE__, \
|
||||
"LibreTuya v" LT_VERSION_STR " on " LT_BOARD_STR ", compiled at " __DATE__ " " __TIME__ \
|
||||
)
|
||||
|
||||
// ArduinoCore-API doesn't define these anymore
|
||||
#define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper *>(pstr_pointer))
|
||||
#define PGM_VOID_P const void *
|
||||
|
||||
// C functions
|
||||
extern char *strdup(const char *);
|
||||
|
||||
// C++ only functions
|
||||
#ifdef __cplusplus
|
||||
String ipToString(const IPAddress &ip);
|
||||
#endif
|
||||
@@ -17,7 +17,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "api/String.h"
|
||||
#include <api/String.h>
|
||||
|
||||
typedef enum {
|
||||
PT_I8,
|
||||
|
||||
84
arduino/libretuya/api/WiFi.cpp
Normal file
84
arduino/libretuya/api/WiFi.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-17. */
|
||||
|
||||
#include "WiFi.h"
|
||||
|
||||
std::vector<EventHandler> IWiFiGenericClass::handlers;
|
||||
|
||||
uint16_t IWiFiGenericClass::onEvent(EventCb callback, EventId eventId) {
|
||||
if (!callback)
|
||||
return 0;
|
||||
EventHandler handler;
|
||||
handler.cb = callback;
|
||||
handler.eventId = eventId;
|
||||
handlers.push_back(handler);
|
||||
return handler.id;
|
||||
}
|
||||
|
||||
uint16_t IWiFiGenericClass::onEvent(EventFuncCb callback, EventId eventId) {
|
||||
if (!callback)
|
||||
return 0;
|
||||
EventHandler handler;
|
||||
handler.fcb = callback;
|
||||
handler.eventId = eventId;
|
||||
handlers.push_back(handler);
|
||||
return handler.id;
|
||||
}
|
||||
|
||||
uint16_t IWiFiGenericClass::onEvent(EventSysCb callback, EventId eventId) {
|
||||
if (!callback)
|
||||
return 0;
|
||||
EventHandler handler;
|
||||
handler.scb = callback;
|
||||
handler.eventId = eventId;
|
||||
handlers.push_back(handler);
|
||||
return handler.id;
|
||||
}
|
||||
|
||||
void IWiFiGenericClass::removeEvent(EventCb callback, EventId eventId) {
|
||||
if (!callback)
|
||||
return;
|
||||
for (uint16_t i = 0; i < handlers.size(); i++) {
|
||||
EventHandler handler = handlers[i];
|
||||
if (handler.cb == callback && handler.eventId == eventId) {
|
||||
handlers.erase(handlers.begin() + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IWiFiGenericClass::removeEvent(EventSysCb callback, EventId eventId) {
|
||||
if (!callback)
|
||||
return;
|
||||
for (uint16_t i = 0; i < handlers.size(); i++) {
|
||||
EventHandler handler = handlers[i];
|
||||
if (handler.scb == callback && handler.eventId == eventId) {
|
||||
handlers.erase(handlers.begin() + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IWiFiGenericClass::removeEvent(uint16_t id) {
|
||||
for (uint16_t i = 0; i < handlers.size(); i++) {
|
||||
EventHandler handler = handlers[i];
|
||||
if (handler.id == id) {
|
||||
handlers.erase(handlers.begin() + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IWiFiGenericClass::postEvent(EventId eventId, EventInfo eventInfo) {
|
||||
for (auto handler : handlers) {
|
||||
if (handler.eventId != ARDUINO_EVENT_MAX && handler.eventId != eventId)
|
||||
continue;
|
||||
if (handler.cb) {
|
||||
handler.cb(eventId);
|
||||
} else if (handler.fcb) {
|
||||
handler.fcb(eventId, eventInfo);
|
||||
} else if (handler.scb) {
|
||||
Event_t event = {
|
||||
.event_id = eventId,
|
||||
.event_info = eventInfo,
|
||||
};
|
||||
handler.scb(&event);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,12 +26,11 @@
|
||||
#include <api/IPAddress.h>
|
||||
#include <api/IPv6Address.h>
|
||||
#include <api/Print.h>
|
||||
#include <vector>
|
||||
|
||||
#include "Events.h"
|
||||
#include "WiFiType.h"
|
||||
|
||||
// TODO wifi events
|
||||
// TODO WiFiMulti library
|
||||
|
||||
class IWiFiClass {
|
||||
public:
|
||||
virtual void printDiag(Print &dest) = 0;
|
||||
@@ -64,6 +63,20 @@ class IWiFiGenericClass {
|
||||
static IPAddress calculateBroadcast(IPAddress ip, IPAddress subnet);
|
||||
static uint8_t calculateSubnetCIDR(IPAddress subnetMask);
|
||||
static String macToString(uint8_t *mac);
|
||||
|
||||
protected:
|
||||
static std::vector<EventHandler> handlers;
|
||||
|
||||
public:
|
||||
uint16_t onEvent(EventCb callback, EventId eventId = ARDUINO_EVENT_MAX);
|
||||
uint16_t onEvent(EventFuncCb callback, EventId eventId = ARDUINO_EVENT_MAX);
|
||||
uint16_t onEvent(EventSysCb callback, EventId eventId = ARDUINO_EVENT_MAX);
|
||||
void removeEvent(EventCb callback, EventId eventId);
|
||||
void removeEvent(EventSysCb callback, EventId eventId);
|
||||
void removeEvent(uint16_t id);
|
||||
|
||||
protected:
|
||||
static void postEvent(EventId eventId, EventInfo eventInfo);
|
||||
};
|
||||
|
||||
class IWiFiSTAClass {
|
||||
|
||||
173
arduino/libretuya/api/WiFiEvents.h
Normal file
173
arduino/libretuya/api/WiFiEvents.h
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "WiFiType.h"
|
||||
|
||||
/** Argument structure for WIFI_EVENT_SCAN_DONE event */
|
||||
typedef struct {
|
||||
uint32_t status; /**< status of scanning APs: 0 - success, 1 - failure */
|
||||
uint8_t number; /**< number of scan results */
|
||||
uint8_t scan_id; /**< scan sequence number, used for block scan */
|
||||
} wifi_event_sta_scan_done_t;
|
||||
|
||||
/** Argument structure for WIFI_EVENT_STA_CONNECTED event */
|
||||
typedef struct {
|
||||
uint8_t ssid[32]; /**< SSID of connected AP */
|
||||
uint8_t ssid_len; /**< SSID length of connected AP */
|
||||
uint8_t bssid[6]; /**< BSSID of connected AP*/
|
||||
uint8_t channel; /**< channel of connected AP*/
|
||||
wifi_auth_mode_t authmode; /**< authentication mode used by AP*/
|
||||
} wifi_event_sta_connected_t;
|
||||
|
||||
/** Argument structure for WIFI_EVENT_STA_DISCONNECTED event */
|
||||
typedef struct {
|
||||
uint8_t ssid[32]; /**< SSID of disconnected AP */
|
||||
uint8_t ssid_len; /**< SSID length of disconnected AP */
|
||||
uint8_t bssid[6]; /**< BSSID of disconnected AP */
|
||||
uint8_t reason; /**< reason of disconnection */
|
||||
} wifi_event_sta_disconnected_t;
|
||||
|
||||
/** Argument structure for WIFI_EVENT_STA_AUTHMODE_CHANGE event */
|
||||
typedef struct {
|
||||
wifi_auth_mode_t old_mode; /**< the old auth mode of AP */
|
||||
wifi_auth_mode_t new_mode; /**< the new auth mode of AP */
|
||||
} wifi_event_sta_authmode_change_t;
|
||||
|
||||
/** Argument structure for WIFI_EVENT_STA_WPS_ER_PIN event */
|
||||
typedef struct {
|
||||
uint8_t pin_code[8]; /**< PIN code of station in enrollee mode */
|
||||
} wifi_event_sta_wps_er_pin_t;
|
||||
|
||||
/** Argument structure for WIFI_EVENT_STA_WPS_ER_FAILED event */
|
||||
typedef enum {
|
||||
WPS_FAIL_REASON_NORMAL = 0, /**< ESP32 WPS normal fail reason */
|
||||
WPS_FAIL_REASON_RECV_M2D, /**< ESP32 WPS receive M2D frame */
|
||||
WPS_FAIL_REASON_MAX
|
||||
} wifi_event_sta_wps_fail_reason_t;
|
||||
|
||||
#define MAX_SSID_LEN 32
|
||||
#define MAX_PASSPHRASE_LEN 64
|
||||
#define MAX_WPS_AP_CRED 3
|
||||
|
||||
/** Argument structure for WIFI_EVENT_STA_WPS_ER_SUCCESS event */
|
||||
typedef struct {
|
||||
uint8_t ap_cred_cnt; /**< Number of AP credentials received */
|
||||
|
||||
struct {
|
||||
uint8_t ssid[MAX_SSID_LEN]; /**< SSID of AP */
|
||||
uint8_t passphrase[MAX_PASSPHRASE_LEN]; /**< Passphrase for the AP */
|
||||
} ap_cred[MAX_WPS_AP_CRED]; /**< All AP credentials received from WPS handshake */
|
||||
} wifi_event_sta_wps_er_success_t;
|
||||
|
||||
/** Argument structure for WIFI_EVENT_AP_STACONNECTED event */
|
||||
typedef struct {
|
||||
uint8_t mac[6]; /**< MAC address of the station connected to ESP32 soft-AP */
|
||||
uint8_t aid; /**< the aid that ESP32 soft-AP gives to the station connected to */
|
||||
bool is_mesh_child; /**< flag to identify mesh child */
|
||||
} wifi_event_ap_staconnected_t;
|
||||
|
||||
/** Argument structure for WIFI_EVENT_AP_STADISCONNECTED event */
|
||||
typedef struct {
|
||||
uint8_t mac[6]; /**< MAC address of the station disconnects to ESP32 soft-AP */
|
||||
uint8_t aid; /**< the aid that ESP32 soft-AP gave to the station disconnects to */
|
||||
bool is_mesh_child; /**< flag to identify mesh child */
|
||||
} wifi_event_ap_stadisconnected_t;
|
||||
|
||||
/** Argument structure for WIFI_EVENT_AP_PROBEREQRECVED event */
|
||||
typedef struct {
|
||||
int rssi; /**< Received probe request signal strength */
|
||||
uint8_t mac[6]; /**< MAC address of the station which send probe request */
|
||||
} wifi_event_ap_probe_req_rx_t;
|
||||
|
||||
/**
|
||||
* @brief FTM operation status types
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
FTM_STATUS_SUCCESS = 0, /**< FTM exchange is successful */
|
||||
FTM_STATUS_UNSUPPORTED, /**< Peer does not support FTM */
|
||||
FTM_STATUS_CONF_REJECTED, /**< Peer rejected FTM configuration in FTM Request */
|
||||
FTM_STATUS_NO_RESPONSE, /**< Peer did not respond to FTM Requests */
|
||||
FTM_STATUS_FAIL, /**< Unknown error during FTM exchange */
|
||||
} wifi_ftm_status_t;
|
||||
|
||||
/** Argument structure for */
|
||||
typedef struct {
|
||||
uint8_t dlog_token; /**< Dialog Token of the FTM frame */
|
||||
int8_t rssi; /**< RSSI of the FTM frame received */
|
||||
uint32_t rtt; /**< Round Trip Time in pSec with a peer */
|
||||
uint64_t t1; /**< Time of departure of FTM frame from FTM Responder in pSec */
|
||||
uint64_t t2; /**< Time of arrival of FTM frame at FTM Initiator in pSec */
|
||||
uint64_t t3; /**< Time of departure of ACK from FTM Initiator in pSec */
|
||||
uint64_t t4; /**< Time of arrival of ACK at FTM Responder in pSec */
|
||||
} wifi_ftm_report_entry_t;
|
||||
|
||||
/** Argument structure for WIFI_EVENT_FTM_REPORT event */
|
||||
typedef struct {
|
||||
uint8_t peer_mac[6]; /**< MAC address of the FTM Peer */
|
||||
wifi_ftm_status_t status; /**< Status of the FTM operation */
|
||||
uint32_t rtt_raw; /**< Raw average Round-Trip-Time with peer in Nano-Seconds */
|
||||
uint32_t rtt_est; /**< Estimated Round-Trip-Time with peer in Nano-Seconds */
|
||||
uint32_t dist_est; /**< Estimated one-way distance in Centi-Meters */
|
||||
wifi_ftm_report_entry_t
|
||||
*ftm_report_data; /**< Pointer to FTM Report with multiple entries, should be freed after use */
|
||||
uint8_t ftm_report_num_entries; /**< Number of entries in the FTM Report data */
|
||||
} wifi_event_ftm_report_t;
|
||||
|
||||
#define WIFI_STATIS_BUFFER (1 << 0)
|
||||
#define WIFI_STATIS_RXTX (1 << 1)
|
||||
#define WIFI_STATIS_HW (1 << 2)
|
||||
#define WIFI_STATIS_DIAG (1 << 3)
|
||||
#define WIFI_STATIS_PS (1 << 4)
|
||||
#define WIFI_STATIS_ALL (-1)
|
||||
|
||||
/** Argument structure for WIFI_EVENT_ACTION_TX_STATUS event */
|
||||
typedef struct {
|
||||
int ifx; /**< WiFi interface to send request to */
|
||||
uint32_t context; /**< Context to identify the request */
|
||||
uint8_t da[6]; /**< Destination MAC address */
|
||||
uint8_t status; /**< Status of the operation */
|
||||
} wifi_event_action_tx_status_t;
|
||||
|
||||
/** Argument structure for WIFI_EVENT_ROC_DONE event */
|
||||
typedef struct {
|
||||
uint32_t context; /**< Context to identify the request */
|
||||
} wifi_event_roc_done_t;
|
||||
|
||||
/** Event structure for IP_EVENT_STA_GOT_IP, IP_EVENT_ETH_GOT_IP events */
|
||||
typedef struct {
|
||||
esp_ip4_addr_t ip; /**< Interface IPV4 address */
|
||||
esp_ip4_addr_t netmask; /**< Interface IPV4 netmask */
|
||||
esp_ip4_addr_t gw; /**< Interface IPV4 gateway address */
|
||||
} esp_netif_ip_info_t;
|
||||
|
||||
/** @brief IPV6 IP address information
|
||||
*/
|
||||
typedef struct {
|
||||
esp_ip6_addr_t ip; /**< Interface IPV6 address */
|
||||
} esp_netif_ip6_info_t;
|
||||
|
||||
typedef struct {
|
||||
int if_index; /*!< Interface index for which the event is received (left for legacy compilation) */
|
||||
void *esp_netif; /*!< Pointer to corresponding esp-netif object */
|
||||
esp_netif_ip_info_t ip_info; /*!< IP address, netmask, gatway IP address */
|
||||
bool ip_changed; /*!< Whether the assigned IP has changed or not */
|
||||
} ip_event_got_ip_t;
|
||||
|
||||
/** Event structure for IP_EVENT_GOT_IP6 event */
|
||||
typedef struct {
|
||||
int if_index; /*!< Interface index for which the event is received (left for legacy compilation) */
|
||||
void *esp_netif; /*!< Pointer to corresponding esp-netif object */
|
||||
esp_netif_ip6_info_t ip6_info; /*!< IPv6 address of the interface */
|
||||
int ip_index; /*!< IPv6 address index */
|
||||
} ip_event_got_ip6_t;
|
||||
|
||||
/** Event structure for IP_EVENT_AP_STAIPASSIGNED event */
|
||||
typedef struct {
|
||||
esp_ip4_addr_t ip; /*!< IP address which was assigned to the station */
|
||||
} ip_event_ap_staipassigned_t;
|
||||
@@ -34,12 +34,28 @@
|
||||
#define WIFI_AP WIFI_MODE_AP
|
||||
#define WIFI_AP_STA WIFI_MODE_APSTA
|
||||
|
||||
#define WiFiEvent_t arduino_event_id_t
|
||||
#define WiFiEventInfo_t arduino_event_info_t
|
||||
#define WiFiEventId_t uint16_t
|
||||
|
||||
struct esp_ip6_addr {
|
||||
uint32_t addr[4];
|
||||
uint8_t zone;
|
||||
};
|
||||
|
||||
struct esp_ip4_addr {
|
||||
uint32_t addr;
|
||||
};
|
||||
|
||||
typedef struct esp_ip4_addr esp_ip4_addr_t;
|
||||
typedef struct esp_ip6_addr esp_ip6_addr_t;
|
||||
|
||||
typedef enum {
|
||||
WIFI_MODE_NULL = 0,
|
||||
WIFI_MODE_STA,
|
||||
WIFI_MODE_AP,
|
||||
WIFI_MODE_APSTA,
|
||||
WIFI_MODE_MAX,
|
||||
WIFI_MODE_NULL = 0, /**< null mode */
|
||||
WIFI_MODE_STA, /**< WiFi station mode */
|
||||
WIFI_MODE_AP, /**< WiFi soft-AP mode */
|
||||
WIFI_MODE_APSTA, /**< WiFi station + soft-AP mode */
|
||||
WIFI_MODE_MAX
|
||||
} wifi_mode_t;
|
||||
|
||||
typedef enum {
|
||||
@@ -54,13 +70,54 @@ typedef enum {
|
||||
} 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_OPEN = 0, /**< authenticate mode : open */
|
||||
WIFI_AUTH_WEP, /**< authenticate mode : WEP */
|
||||
WIFI_AUTH_WPA_PSK, /**< authenticate mode : WPA_PSK */
|
||||
WIFI_AUTH_WPA2_PSK, /**< authenticate mode : WPA2_PSK */
|
||||
WIFI_AUTH_WPA_WPA2_PSK, /**< authenticate mode : WPA_WPA2_PSK */
|
||||
WIFI_AUTH_WPA2_ENTERPRISE, /**< authenticate mode : WPA2_ENTERPRISE */
|
||||
WIFI_AUTH_WPA3_PSK, /**< authenticate mode : WPA3_PSK */
|
||||
WIFI_AUTH_WPA2_WPA3_PSK, /**< authenticate mode : WPA2_WPA3_PSK */
|
||||
WIFI_AUTH_WAPI_PSK, /**< authenticate mode : WAPI_PSK */
|
||||
WIFI_AUTH_WPA,
|
||||
WIFI_AUTH_WPA2,
|
||||
WIFI_AUTH_AUTO = 200,
|
||||
WIFI_AUTH_INVALID = 255,
|
||||
WIFI_AUTH_MAX
|
||||
} wifi_auth_mode_t;
|
||||
|
||||
typedef enum {
|
||||
WIFI_REASON_UNSPECIFIED = 1,
|
||||
WIFI_REASON_AUTH_EXPIRE = 2,
|
||||
WIFI_REASON_AUTH_LEAVE = 3,
|
||||
WIFI_REASON_ASSOC_EXPIRE = 4,
|
||||
WIFI_REASON_ASSOC_TOOMANY = 5,
|
||||
WIFI_REASON_NOT_AUTHED = 6,
|
||||
WIFI_REASON_NOT_ASSOCED = 7,
|
||||
WIFI_REASON_ASSOC_LEAVE = 8,
|
||||
WIFI_REASON_ASSOC_NOT_AUTHED = 9,
|
||||
WIFI_REASON_DISASSOC_PWRCAP_BAD = 10,
|
||||
WIFI_REASON_DISASSOC_SUPCHAN_BAD = 11,
|
||||
WIFI_REASON_BSS_TRANSITION_DISASSOC = 12,
|
||||
WIFI_REASON_IE_INVALID = 13,
|
||||
WIFI_REASON_MIC_FAILURE = 14,
|
||||
WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT = 15,
|
||||
WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT = 16,
|
||||
WIFI_REASON_IE_IN_4WAY_DIFFERS = 17,
|
||||
WIFI_REASON_GROUP_CIPHER_INVALID = 18,
|
||||
WIFI_REASON_PAIRWISE_CIPHER_INVALID = 19,
|
||||
WIFI_REASON_AKMP_INVALID = 20,
|
||||
WIFI_REASON_UNSUPP_RSN_IE_VERSION = 21,
|
||||
WIFI_REASON_INVALID_RSN_IE_CAP = 22,
|
||||
WIFI_REASON_802_1X_AUTH_FAILED = 23,
|
||||
WIFI_REASON_CIPHER_SUITE_REJECTED = 24,
|
||||
WIFI_REASON_INVALID_PMKID = 53,
|
||||
WIFI_REASON_BEACON_TIMEOUT = 200,
|
||||
WIFI_REASON_NO_AP_FOUND = 201,
|
||||
WIFI_REASON_AUTH_FAIL = 202,
|
||||
WIFI_REASON_ASSOC_FAIL = 203,
|
||||
WIFI_REASON_HANDSHAKE_TIMEOUT = 204,
|
||||
WIFI_REASON_CONNECTION_FAIL = 205,
|
||||
WIFI_REASON_AP_TSF_RESET = 206,
|
||||
WIFI_REASON_ROAMING = 207,
|
||||
} wifi_err_reason_t;
|
||||
|
||||
66
arduino/libretuya/api/Wire.h
Normal file
66
arduino/libretuya/api/Wire.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-09. */
|
||||
|
||||
#include <api/Stream.h>
|
||||
|
||||
class ITwoWire : public Stream {
|
||||
protected:
|
||||
int8_t _sda = -1;
|
||||
int8_t _scl = -1;
|
||||
uint32_t _freq = 0;
|
||||
|
||||
void (*onRequestCallback)(void);
|
||||
void (*onReceiveCallback)(int);
|
||||
|
||||
public:
|
||||
bool begin() {
|
||||
return begin(_sda, _scl, _freq);
|
||||
}
|
||||
|
||||
bool begin(uint8_t address) {
|
||||
return begin(address, _sda, _scl, _freq);
|
||||
}
|
||||
|
||||
virtual bool setPins(int8_t sda, int8_t scl) = 0;
|
||||
|
||||
virtual bool begin(int8_t sda, int8_t scl, uint32_t frequency = 0) = 0;
|
||||
virtual bool begin(uint8_t address, int8_t sda, int8_t scl, uint32_t frequency = 0) = 0;
|
||||
virtual bool end() = 0;
|
||||
|
||||
virtual bool setClock(uint32_t freq) = 0;
|
||||
|
||||
virtual void beginTransmission(uint8_t address) = 0;
|
||||
virtual uint8_t endTransmission(bool stopBit) = 0;
|
||||
|
||||
virtual size_t requestFrom(uint8_t address, size_t len, bool stopBit) = 0;
|
||||
|
||||
virtual size_t write(const uint8_t *data, size_t len) = 0;
|
||||
|
||||
virtual int available() = 0;
|
||||
virtual int read() = 0;
|
||||
virtual int peek() = 0;
|
||||
virtual void flush() = 0;
|
||||
|
||||
uint32_t getClock() {
|
||||
return _freq;
|
||||
}
|
||||
|
||||
uint8_t endTransmission() {
|
||||
return endTransmission(true);
|
||||
}
|
||||
|
||||
size_t requestFrom(uint8_t address, size_t len) {
|
||||
return requestFrom(address, len, true);
|
||||
}
|
||||
|
||||
virtual size_t write(uint8_t data) {
|
||||
return write(&data, 1);
|
||||
}
|
||||
|
||||
void onReceive(void (*cb)(int)) {
|
||||
onReceiveCallback = cb;
|
||||
}
|
||||
|
||||
void onRequest(void (*cb)(void)) {
|
||||
onRequestCallback = cb;
|
||||
}
|
||||
};
|
||||
23
arduino/libretuya/core/ChipType.h
Normal file
23
arduino/libretuya/core/ChipType.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-28. */
|
||||
|
||||
enum ChipFamily {
|
||||
// used in UF2 Family ID
|
||||
RTL8710A = 0x9FFFD543, // Realtek Ameba1
|
||||
RTL8710B = 0x22E0D6FC, // Realtek AmebaZ (realtek-ambz)
|
||||
RTL8720C = 0xE08F7564, // Realtek AmebaZ2
|
||||
RTL8720D = 0x3379CFE2, // Realtek AmebaD
|
||||
BK7231T = 0x675A40B0, // Beken 7231T
|
||||
BK7231N = 0x7B3EF230, // Beken 7231N
|
||||
BL602 = 0xDE1270B7, // Boufallo 602
|
||||
XR809 = 0x51E903A8, // Xradiotech 809
|
||||
};
|
||||
|
||||
enum ChipType {
|
||||
// IDs copied from rtl8710b_efuse.h
|
||||
RTL8710BL = ((RTL8710B >> 24) << 8) | 0xE0, // ???
|
||||
RTL8710BN = ((RTL8710B >> 24) << 8) | 0xFF, // CHIPID_8710BN / QFN32
|
||||
RTL8710BU = ((RTL8710B >> 24) << 8) | 0xFE, // CHIPID_8710BU / QFN48
|
||||
RTL8710BX = ((RTL8710B >> 24) << 8) | 0xFB, // CHIPID_8710BN_L0 / QFN32
|
||||
RTL8711BN = ((RTL8710B >> 24) << 8) | 0xFD, // CHIPID_8711BN / QFN48
|
||||
RTL8711BU = ((RTL8710B >> 24) << 8) | 0xFC, // CHIPID_8711BG / QFN68
|
||||
};
|
||||
162
arduino/libretuya/core/LibreTuyaAPI.cpp
Normal file
162
arduino/libretuya/core/LibreTuyaAPI.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-29. */
|
||||
|
||||
#include "LibreTuyaAPI.h"
|
||||
|
||||
String ipToString(const IPAddress &ip) {
|
||||
char szRet[16];
|
||||
sprintf(szRet, "%hhu.%hhu.%hhu.%hhu", ip[0], ip[1], ip[2], ip[3]);
|
||||
return String(szRet);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generate random bytes using rand().
|
||||
*
|
||||
* @param buf destination pointer
|
||||
* @param len how many bytes to generate
|
||||
*/
|
||||
void lt_rand_bytes(uint8_t *buf, size_t len) {
|
||||
int *data = (int *)buf;
|
||||
size_t i;
|
||||
for (i = 0; len >= sizeof(int); len -= sizeof(int)) {
|
||||
data[i++] = rand();
|
||||
}
|
||||
if (len) {
|
||||
int rem = rand();
|
||||
unsigned char *pRem = (unsigned char *)&rem;
|
||||
memcpy(buf + i * sizeof(int), pRem, len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Print data pointed to by buf in hexdump-like format (hex+ASCII).
|
||||
*
|
||||
* @param buf source pointer
|
||||
* @param len how many bytes to print
|
||||
* @param offset increment printed offset by this value
|
||||
* @param width how many bytes on a line
|
||||
*/
|
||||
void hexdump(uint8_t *buf, size_t len, uint32_t offset, uint8_t width) {
|
||||
uint16_t pos = 0;
|
||||
while (pos < len) {
|
||||
// print hex offset
|
||||
printf("%06x ", offset + pos);
|
||||
// calculate current line width
|
||||
uint8_t lineWidth = min(width, len - pos);
|
||||
// print hexadecimal representation
|
||||
for (uint8_t i = 0; i < lineWidth; i++) {
|
||||
if (i % 8 == 0) {
|
||||
printf(" ");
|
||||
}
|
||||
printf("%02x ", buf[pos + i]);
|
||||
}
|
||||
// print ascii representation
|
||||
printf(" |");
|
||||
for (uint8_t i = 0; i < lineWidth; i++) {
|
||||
char c = buf[pos + i];
|
||||
printf("%c", isprint(c) ? c : '.');
|
||||
}
|
||||
printf("|\n");
|
||||
pos += lineWidth;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get LibreTuya version string.
|
||||
*/
|
||||
const char *LibreTuya::getVersion() {
|
||||
return LT_VERSION_STR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get board name.
|
||||
*/
|
||||
const char *LibreTuya::getBoard() {
|
||||
return LT_BOARD_STR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get CPU family ID.
|
||||
*/
|
||||
ChipFamily LibreTuya::getChipFamily() {
|
||||
return FAMILY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get CPU family name as string.
|
||||
*/
|
||||
const char *LibreTuya::getChipFamilyName() {
|
||||
return STRINGIFY_MACRO(FAMILY);
|
||||
}
|
||||
|
||||
static char *deviceName = NULL;
|
||||
|
||||
/**
|
||||
* @brief Get device friendly name in format "LT-<board>-<chip id>".
|
||||
* Can be used as hostname.
|
||||
*/
|
||||
const char *LibreTuya::getDeviceName() {
|
||||
if (deviceName)
|
||||
return deviceName;
|
||||
uint32_t chipId = getChipId();
|
||||
uint8_t *id = (uint8_t *)&chipId;
|
||||
|
||||
const char *board = getBoard();
|
||||
uint8_t boardLen = strlen(board);
|
||||
deviceName = (char *)malloc(3 + boardLen + 1 + 6 + 1);
|
||||
|
||||
sprintf(deviceName, "LT-%s-%02x%02x%02x", board, id[0], id[1], id[2]);
|
||||
return deviceName;
|
||||
}
|
||||
|
||||
static uint8_t otaRunningIndex = 0;
|
||||
|
||||
/**
|
||||
* @brief Get the currently running firmware OTA index.
|
||||
*/
|
||||
uint8_t LibreTuya::otaGetRunning() {
|
||||
if (otaRunningIndex)
|
||||
return otaRunningIndex;
|
||||
// otaRunningIndex will be correct even after switchOta()
|
||||
return otaRunningIndex = otaGetStoredIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the OTA index for updated firmware.
|
||||
*
|
||||
* Note: returns 1 for chips without dual-OTA.
|
||||
*/
|
||||
uint8_t LibreTuya::otaGetTarget() {
|
||||
if (!otaSupportsDual())
|
||||
return 1;
|
||||
return otaGetRunning() ^ 0b11;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform OTA rollback.
|
||||
*
|
||||
* @return false if no second image to run, writing failed or dual-OTA not supported
|
||||
*/
|
||||
bool LibreTuya::otaRollback() {
|
||||
if (!otaCanRollback())
|
||||
return false;
|
||||
if (otaGetRunning() != otaGetStoredIndex())
|
||||
// force switching back to current image
|
||||
return otaSwitch(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if OTA rollback is supported and available (there is another image to run).
|
||||
* @return false if no second image to run or dual-OTA not supported
|
||||
*/
|
||||
bool LibreTuya::otaCanRollback() {
|
||||
if (!otaSupportsDual())
|
||||
return false;
|
||||
if (otaGetRunning() == otaGetStoredIndex())
|
||||
return true;
|
||||
if (otaGetRunning() == 1 && otaHasImage1())
|
||||
return true;
|
||||
if (otaGetRunning() == 2 && otaHasImage2())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
181
arduino/libretuya/core/LibreTuyaAPI.h
Normal file
181
arduino/libretuya/core/LibreTuyaAPI.h
Normal file
@@ -0,0 +1,181 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-28. */
|
||||
|
||||
#pragma once
|
||||
|
||||
// LibreTuya version macros
|
||||
#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)
|
||||
|
||||
// Includes
|
||||
#include "LibreTuyaConfig.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
// C includes
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#include "lt_logger.h"
|
||||
#include "lt_posix_api.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
// Functional macros
|
||||
#define LT_BANNER() \
|
||||
LT_LOG( \
|
||||
LT_LEVEL_INFO, \
|
||||
__FUNCTION__, \
|
||||
__LINE__, \
|
||||
"LibreTuya v" LT_VERSION_STR " on " LT_BOARD_STR ", compiled at " __DATE__ " " __TIME__ \
|
||||
)
|
||||
|
||||
// ArduinoCore-API doesn't define these anymore
|
||||
#define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper *>(pstr_pointer))
|
||||
#define PGM_VOID_P const void *
|
||||
|
||||
void lt_rand_bytes(uint8_t *buf, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
String ipToString(const IPAddress &ip);
|
||||
void hexdump(uint8_t *buf, size_t len, uint32_t offset = 0, uint8_t width = 16);
|
||||
#else
|
||||
void hexdump(uint8_t *buf, size_t len, uint32_t offset, uint8_t width);
|
||||
#endif
|
||||
|
||||
// Main class
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <Flash.h> // for flash inline methods
|
||||
#include <core/ChipType.h>
|
||||
|
||||
/**
|
||||
* @brief Main LibreTuya API class.
|
||||
*
|
||||
* This class contains all functions common amongst all families.
|
||||
* Implementations of these methods may vary between families.
|
||||
*
|
||||
* The class is accessible using the `LT` global object (defined by the family).
|
||||
*/
|
||||
class LibreTuya {
|
||||
public: /* Common methods - note: these are documented in LibreTuyaAPI.cpp */
|
||||
const char *getVersion();
|
||||
const char *getBoard();
|
||||
ChipFamily getChipFamily();
|
||||
const char *getChipFamilyName();
|
||||
const char *getDeviceName();
|
||||
uint8_t otaGetRunning();
|
||||
uint8_t otaGetTarget();
|
||||
bool otaRollback();
|
||||
bool otaCanRollback();
|
||||
|
||||
public: /* Inline methods */
|
||||
inline uint32_t getFlashChipSize() {
|
||||
return Flash.getSize();
|
||||
}
|
||||
|
||||
// inline bool flashEraseSector(uint32_t sector) {}
|
||||
// inline bool flashWrite(uint32_t offset, uint32_t *data, size_t size) {}
|
||||
// inline bool flashRead(uint32_t offset, uint32_t *data, size_t size) {}
|
||||
// inline bool partitionEraseRange(const esp_partition_t *partition, uint32_t offset, size_t size) {}
|
||||
// inline bool partitionWrite(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size) {}
|
||||
// inline bool partitionRead(const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size) {}
|
||||
|
||||
public: /* Family-defined methods */
|
||||
/**
|
||||
* @brief Reboot the CPU.
|
||||
*/
|
||||
void restart();
|
||||
|
||||
public: /* CPU-related */
|
||||
/**
|
||||
* @brief Get CPU model ID.
|
||||
*/
|
||||
ChipType getChipType();
|
||||
/**
|
||||
* @brief Get CPU model name as string.
|
||||
*/
|
||||
const char *getChipModel();
|
||||
/**
|
||||
* @brief Get CPU unique ID. This may be based on MAC, eFuse, etc.
|
||||
*/
|
||||
uint32_t getChipId();
|
||||
/**
|
||||
* @brief Get CPU core count.
|
||||
*/
|
||||
uint8_t getChipCores();
|
||||
/**
|
||||
* @brief Get CPU core type name as string.
|
||||
*/
|
||||
const char *getChipCoreType();
|
||||
/**
|
||||
* @brief Get CPU frequency in MHz.
|
||||
*/
|
||||
uint32_t getCpuFreqMHz();
|
||||
/**
|
||||
* @brief Get CPU cycle count.
|
||||
*/
|
||||
inline uint32_t getCycleCount() __attribute__((always_inline));
|
||||
|
||||
public: /* Memory management */
|
||||
/**
|
||||
* @brief Get total RAM size.
|
||||
*/
|
||||
uint32_t getRamSize();
|
||||
/**
|
||||
* @brief Get total heap size.
|
||||
*/
|
||||
uint32_t getHeapSize();
|
||||
/**
|
||||
* @brief Get free heap size.
|
||||
*/
|
||||
uint32_t getFreeHeap();
|
||||
/**
|
||||
* @brief Get lowest level of free heap memory.
|
||||
*/
|
||||
uint32_t getMinFreeHeap();
|
||||
/**
|
||||
* @brief Get largest block of heap that can be allocated at once.
|
||||
*/
|
||||
uint32_t getMaxAllocHeap();
|
||||
|
||||
public: /* OTA-related */
|
||||
/**
|
||||
* @brief Read the currently active OTA index, i.e. the one that will boot upon restart.
|
||||
*/
|
||||
uint8_t otaGetStoredIndex();
|
||||
/**
|
||||
* @brief Check if the chip supports dual-OTA.
|
||||
*/
|
||||
bool otaSupportsDual();
|
||||
/**
|
||||
* @brief Check if OTA1 image is valid.
|
||||
*/
|
||||
bool otaHasImage1();
|
||||
/**
|
||||
* @brief Check if OTA2 image is valid.
|
||||
*/
|
||||
bool otaHasImage2();
|
||||
/**
|
||||
* @brief Try to switch OTA index to the other image.
|
||||
*
|
||||
* Note: should return true for chips without dual-OTA. Should return false if one of two images is not valid.
|
||||
*
|
||||
* @param force switch even if other image already marked as active
|
||||
* @return false if writing failed; true otherwise
|
||||
*/
|
||||
bool otaSwitch(bool force = false);
|
||||
};
|
||||
|
||||
extern LibreTuya LT;
|
||||
extern LibreTuya ESP;
|
||||
#endif
|
||||
@@ -44,6 +44,11 @@
|
||||
#define LT_LOGLEVEL LT_LEVEL_INFO
|
||||
#endif
|
||||
|
||||
// Free heap size debugging
|
||||
#ifndef LT_LOG_HEAP
|
||||
#define LT_LOG_HEAP 0
|
||||
#endif
|
||||
|
||||
// Per-module debugging
|
||||
#ifndef LT_DEBUG_WIFI
|
||||
#define LT_DEBUG_WIFI 0
|
||||
@@ -51,6 +51,12 @@ void lt_log(const uint8_t level, const char *format, ...);
|
||||
#define LT_F(...)
|
||||
#endif
|
||||
|
||||
#if LT_LOG_HEAP
|
||||
#define LT_HEAP_I() LT_I("Free heap: %u", LT_HEAP_FUNC());
|
||||
#else
|
||||
#define LT_HEAP_I()
|
||||
#endif
|
||||
|
||||
// ESP32 compat
|
||||
#define log_printf(...) LT_I(__VA_ARGS__)
|
||||
#define log_v(...) LT_V(__VA_ARGS__)
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
#ifdef HTTPCLIENT_1_1_COMPATIBLE
|
||||
#include <WiFi.h>
|
||||
// #include <WiFiClientSecure.h>
|
||||
#include <WiFiClientSecure.h>
|
||||
#endif
|
||||
|
||||
// #include <StreamString.h>
|
||||
@@ -63,7 +63,7 @@ class TLSTraits : public TransportTraits {
|
||||
TLSTraits(const char *CAcert, const char *clicert = nullptr, const char *clikey = nullptr)
|
||||
: _cacert(CAcert), _clicert(clicert), _clikey(clikey) {}
|
||||
|
||||
/* std::unique_ptr<WiFiClient> create() override {
|
||||
std::unique_ptr<WiFiClient> create() override {
|
||||
return std::unique_ptr<WiFiClient>(new WiFiClientSecure());
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ class TLSTraits : public TransportTraits {
|
||||
wcs.setPrivateKey(_clikey);
|
||||
}
|
||||
return true;
|
||||
} */
|
||||
}
|
||||
|
||||
protected:
|
||||
const char *_cacert;
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <WiFiClient.h>
|
||||
// #include <WiFiClientSecure.h>
|
||||
#include <WiFiClientSecure.h>
|
||||
#include <memory>
|
||||
|
||||
/// Cookie jar support
|
||||
|
||||
@@ -19,9 +19,13 @@ extern "C" {
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
MbedTLSClient::MbedTLSClient() : WiFiClient() {}
|
||||
MbedTLSClient::MbedTLSClient() : WiFiClient() {
|
||||
init(); // ensure the context is zero filled
|
||||
}
|
||||
|
||||
MbedTLSClient::MbedTLSClient(int sock) : WiFiClient(sock) {}
|
||||
MbedTLSClient::MbedTLSClient(int sock) : WiFiClient(sock) {
|
||||
init(); // ensure the context is zero filled
|
||||
}
|
||||
|
||||
void MbedTLSClient::stop() {
|
||||
WiFiClient::stop();
|
||||
@@ -46,46 +50,37 @@ void MbedTLSClient::init() {
|
||||
}
|
||||
|
||||
int MbedTLSClient::connect(IPAddress ip, uint16_t port, int32_t timeout) {
|
||||
return connect(ipToString(ip).c_str(), port, timeout) == 0;
|
||||
return connect(ipToString(ip).c_str(), port, timeout);
|
||||
}
|
||||
|
||||
int MbedTLSClient::connect(const char *host, uint16_t port, int32_t timeout) {
|
||||
if (_pskIdentStr && _pskStr)
|
||||
return connect(host, port, NULL, NULL, NULL, _pskIdentStr, _pskStr, _alpnProtocols) == 0;
|
||||
return connect(host, port, _caCertStr, _clientCertStr, _clientKeyStr, NULL, NULL, _alpnProtocols) == 0;
|
||||
return connect(host, port, timeout, NULL, NULL, NULL, _pskIdentStr, _pskStr) == 0;
|
||||
return connect(host, port, timeout, _caCertStr, _clientCertStr, _clientKeyStr, NULL, NULL) == 0;
|
||||
}
|
||||
|
||||
int MbedTLSClient::connect(
|
||||
IPAddress ip, uint16_t port, const char *rootCABuf, const char *clientCert, const char *clientKey
|
||||
) {
|
||||
return connect(ipToString(ip).c_str(), port, rootCABuf, clientCert, clientKey, NULL, NULL, _alpnProtocols) == 0;
|
||||
return connect(ipToString(ip).c_str(), port, 0, rootCABuf, clientCert, clientKey, NULL, NULL) == 0;
|
||||
}
|
||||
|
||||
int MbedTLSClient::connect(
|
||||
const char *host, uint16_t port, const char *rootCABuf, const char *clientCert, const char *clientKey
|
||||
) {
|
||||
return connect(host, port, rootCABuf, clientCert, clientKey, NULL, NULL, _alpnProtocols) == 0;
|
||||
return connect(host, port, 0, rootCABuf, clientCert, clientKey, NULL, NULL) == 0;
|
||||
}
|
||||
|
||||
int MbedTLSClient::connect(IPAddress ip, uint16_t port, const char *pskIdent, const char *psk) {
|
||||
return connect(ipToString(ip).c_str(), port, NULL, NULL, NULL, pskIdent, psk, _alpnProtocols) == 0;
|
||||
return connect(ipToString(ip).c_str(), port, 0, NULL, NULL, NULL, pskIdent, psk) == 0;
|
||||
}
|
||||
|
||||
int MbedTLSClient::connect(const char *host, uint16_t port, const char *pskIdent, const char *psk) {
|
||||
return connect(host, port, NULL, NULL, NULL, pskIdent, psk, _alpnProtocols) == 0;
|
||||
return connect(host, port, 0, NULL, NULL, NULL, pskIdent, psk) == 0;
|
||||
}
|
||||
|
||||
static int ssl_random(void *data, unsigned char *output, size_t len) {
|
||||
int *buf = (int *)output;
|
||||
size_t i;
|
||||
for (i = 0; len >= sizeof(int); len -= sizeof(int)) {
|
||||
buf[i++] = rand();
|
||||
}
|
||||
if (len) {
|
||||
int rem = rand();
|
||||
unsigned char *pRem = (unsigned char *)&rem;
|
||||
memcpy(output + i * sizeof(int), pRem, len);
|
||||
}
|
||||
lt_rand_bytes((uint8_t *)output, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -96,23 +91,26 @@ void debug_cb(void *ctx, int level, const char *file, int line, const char *str)
|
||||
int MbedTLSClient::connect(
|
||||
const char *host,
|
||||
uint16_t port,
|
||||
int32_t timeout,
|
||||
const char *rootCABuf,
|
||||
const char *clientCert,
|
||||
const char *clientKey,
|
||||
const char *pskIdent,
|
||||
const char *psk,
|
||||
const char **alpnProtocols
|
||||
const char *psk
|
||||
) {
|
||||
LT_D_SSL("Free heap before TLS: TODO");
|
||||
|
||||
if (!rootCABuf && !pskIdent && !psk && !_insecure && !_useRootCA)
|
||||
return -1;
|
||||
|
||||
if (timeout <= 0)
|
||||
timeout = _timeout; // use default when -1 passed as timeout
|
||||
|
||||
IPAddress addr = WiFi.hostByName(host);
|
||||
if (!(uint32_t)addr)
|
||||
return -1;
|
||||
|
||||
int ret = WiFiClient::connect(addr, port, _timeout);
|
||||
int ret = WiFiClient::connect(addr, port, timeout);
|
||||
if (ret < 0) {
|
||||
LT_E("SSL socket failed");
|
||||
return ret;
|
||||
@@ -135,8 +133,8 @@ int MbedTLSClient::connect(
|
||||
LT_RET_NZ(ret);
|
||||
|
||||
#ifdef MBEDTLS_SSL_ALPN
|
||||
if (alpnProtocols) {
|
||||
ret = mbedtls_ssl_conf_alpn_protocols(&_sslCfg, alpnProtocols);
|
||||
if (_alpnProtocols) {
|
||||
ret = mbedtls_ssl_conf_alpn_protocols(&_sslCfg, _alpnProtocols);
|
||||
LT_RET_NZ(ret);
|
||||
}
|
||||
#endif
|
||||
@@ -208,10 +206,11 @@ int MbedTLSClient::connect(
|
||||
|
||||
_sockTls = fd();
|
||||
mbedtls_ssl_set_bio(&_sslCtx, &_sockTls, mbedtls_net_send, mbedtls_net_recv, NULL);
|
||||
mbedtls_net_set_nonblock((mbedtls_net_context *)&_sockTls);
|
||||
|
||||
LT_V_SSL("SSL handshake");
|
||||
if (_handshakeTimeout == 0)
|
||||
_handshakeTimeout = _timeout * 1000;
|
||||
_handshakeTimeout = timeout;
|
||||
unsigned long start = millis();
|
||||
while (ret = mbedtls_ssl_handshake(&_sslCtx)) {
|
||||
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <api/WiFiClient.h>
|
||||
#include <api/WiFiClientSecure.h>
|
||||
|
||||
#include <WiFiClient.h> // extend platform's WiFiClient impl
|
||||
#include <WiFiClient.h> // extend family's WiFiClient impl
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -42,12 +42,12 @@ class MbedTLSClient : public WiFiClient, public IWiFiClientSecure {
|
||||
int connect(
|
||||
const char *host,
|
||||
uint16_t port,
|
||||
int32_t timeout,
|
||||
const char *rootCABuf,
|
||||
const char *clientCert,
|
||||
const char *clientKey,
|
||||
const char *pskIdent,
|
||||
const char *psk,
|
||||
const char **alpnProtocols
|
||||
const char *psk
|
||||
);
|
||||
|
||||
public:
|
||||
|
||||
199
arduino/libretuya/libraries/Update/Update.cpp
Normal file
199
arduino/libretuya/libraries/Update/Update.cpp
Normal file
@@ -0,0 +1,199 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-29. */
|
||||
|
||||
#include "Update.h"
|
||||
|
||||
UpdateClass::UpdateClass() : ctx(NULL), info(NULL), buf(NULL) {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the update process.
|
||||
*
|
||||
* @param size total UF2 file size
|
||||
* @param command must be U_FLASH
|
||||
* @return false if parameters are invalid or update is running, true otherwise
|
||||
*/
|
||||
bool UpdateClass::begin(size_t size, int command, int unused2, uint8_t unused3, const char *unused4) {
|
||||
if (ctx)
|
||||
return false;
|
||||
cleanup();
|
||||
|
||||
ctx = uf2_ctx_init(LT.otaGetTarget(), FAMILY);
|
||||
info = uf2_info_init();
|
||||
|
||||
if (!size)
|
||||
return errorArd(UPDATE_ERROR_SIZE);
|
||||
|
||||
if (command != U_FLASH)
|
||||
return errorArd(UPDATE_ERROR_BAD_ARGUMENT);
|
||||
|
||||
bytesTotal = size;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Finalize the update process. Check for errors and update completion, then activate the new firmware image.
|
||||
*
|
||||
* @param evenIfRemaining no idea
|
||||
* @return false in case of errors or no update running, true otherwise
|
||||
*/
|
||||
bool UpdateClass::end(bool evenIfRemaining) {
|
||||
if (hasError() || !ctx)
|
||||
// false if not running
|
||||
return false;
|
||||
|
||||
if (!isFinished() && !evenIfRemaining) {
|
||||
// abort if not finished
|
||||
return errorArd(UPDATE_ERROR_ABORT);
|
||||
}
|
||||
// TODO what is evenIfRemaining for?
|
||||
if (!LT.otaSwitch())
|
||||
// try to activate the second OTA
|
||||
return errorArd(UPDATE_ERROR_ACTIVATE);
|
||||
|
||||
cleanup();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write a chunk of data to the buffer or flash memory.
|
||||
*
|
||||
* It's advised to write in 512-byte chunks (or its multiples).
|
||||
*
|
||||
* @param data
|
||||
* @param len
|
||||
* @return size_t
|
||||
*/
|
||||
size_t UpdateClass::write(uint8_t *data, size_t len) {
|
||||
size_t written = 0;
|
||||
if (hasError() || !ctx)
|
||||
// 0 if not running
|
||||
return 0;
|
||||
|
||||
/* while (buf == bufPos && len >= UF2_BLOCK_SIZE) {
|
||||
// buffer empty and entire block is in data
|
||||
if (!tryWriteData(data, UF2_BLOCK_SIZE)) {
|
||||
// returns 0 if data contains an invalid block
|
||||
return written;
|
||||
}
|
||||
data += UF2_BLOCK_SIZE;
|
||||
len -= UF2_BLOCK_SIZE;
|
||||
written += UF2_BLOCK_SIZE;
|
||||
} */
|
||||
|
||||
// write until buffer space is available
|
||||
uint16_t toWrite;
|
||||
while (len && (toWrite = min(len, bufLeft()))) {
|
||||
tryWriteData(data, toWrite);
|
||||
if (hasError())
|
||||
// return on errors
|
||||
return written;
|
||||
data += toWrite;
|
||||
len -= toWrite;
|
||||
written += toWrite;
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
size_t UpdateClass::writeStream(Stream &data) {
|
||||
size_t written = 0;
|
||||
if (hasError() || !ctx)
|
||||
// 0 if not running
|
||||
return 0;
|
||||
|
||||
uint32_t lastData = millis();
|
||||
// loop until the update is complete
|
||||
while (remaining()) {
|
||||
// check stream availability
|
||||
int available = data.available();
|
||||
if (available <= 0) {
|
||||
if (millis() - lastData > UPDATE_TIMEOUT_MS) {
|
||||
// waited for data too long; abort with error
|
||||
errorArd(UPDATE_ERROR_STREAM);
|
||||
return written;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// available > 0
|
||||
lastData = millis();
|
||||
|
||||
// read data to fit in the remaining buffer space
|
||||
bufAlloc();
|
||||
uint16_t read = data.readBytes(bufPos, bufLeft());
|
||||
bufPos += read;
|
||||
written += read;
|
||||
tryWriteData();
|
||||
if (hasError())
|
||||
// return on errors
|
||||
return written;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Try to use the buffer as a block to write. In case of UF2 errors,
|
||||
* error codes are set, the update is aborted and 0 is returned
|
||||
*
|
||||
* @param data received data to copy to buffer or NULL if already in buffer
|
||||
* @param len received data length - must be at most bufLeft()
|
||||
* @return size_t "used" data size - 0 or 512
|
||||
*/
|
||||
size_t UpdateClass::tryWriteData(uint8_t *data, size_t len) {
|
||||
uf2_block_t *block = NULL;
|
||||
|
||||
if (len == UF2_BLOCK_SIZE) {
|
||||
// data has a complete block
|
||||
block = (uf2_block_t *)data;
|
||||
} else if (data && len) {
|
||||
// data has a part of a block, copy it to buffer
|
||||
bufAlloc();
|
||||
memcpy(bufPos, data, len);
|
||||
bufPos += len;
|
||||
}
|
||||
|
||||
if (!block && bufSize() == UF2_BLOCK_SIZE) {
|
||||
// use buffer as block (only if not found above)
|
||||
block = (uf2_block_t *)buf;
|
||||
}
|
||||
|
||||
// a complete block has been found
|
||||
if (block) {
|
||||
if (errorUf2(uf2_check_block(ctx, block)))
|
||||
// block is invalid
|
||||
return 0;
|
||||
|
||||
if (errUf2 == UF2_ERR_IGNORE)
|
||||
// treat ignored blocks as valid
|
||||
return UF2_BLOCK_SIZE;
|
||||
|
||||
if (!bytesWritten) {
|
||||
// parse header block to allow retrieving firmware info
|
||||
if (errorUf2(uf2_parse_header(ctx, block, info)))
|
||||
// header is invalid
|
||||
return 0;
|
||||
|
||||
if (bytesTotal == UPDATE_SIZE_UNKNOWN) {
|
||||
// set total update size from block count info
|
||||
bytesTotal = block->block_count * UF2_BLOCK_SIZE;
|
||||
} else if (bytesTotal != block->block_count * UF2_BLOCK_SIZE) {
|
||||
// given update size does not match the block count
|
||||
return errorArd(UPDATE_ERROR_SIZE);
|
||||
}
|
||||
} else {
|
||||
// write data blocks normally
|
||||
if (errorUf2(uf2_write(ctx, block)))
|
||||
// block writing failed
|
||||
return 0;
|
||||
}
|
||||
|
||||
// increment total writing progress
|
||||
bytesWritten += UF2_BLOCK_SIZE;
|
||||
// call progress callback
|
||||
if (callback)
|
||||
callback(bytesWritten, bytesTotal);
|
||||
return UF2_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UpdateClass Update;
|
||||
150
arduino/libretuya/libraries/Update/Update.h
Normal file
150
arduino/libretuya/libraries/Update/Update.h
Normal file
@@ -0,0 +1,150 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <functional>
|
||||
|
||||
#include "uf2ota/uf2ota.h"
|
||||
|
||||
// No Error
|
||||
#define UPDATE_ERROR_OK (0)
|
||||
// Flash Write Failed
|
||||
#define UPDATE_ERROR_WRITE (1)
|
||||
// Flash Erase Failed
|
||||
#define UPDATE_ERROR_ERASE (2)
|
||||
// Flash Read Failed
|
||||
#define UPDATE_ERROR_READ (3)
|
||||
// Not Enough Space
|
||||
#define UPDATE_ERROR_SPACE (4)
|
||||
// Bad Size Given
|
||||
#define UPDATE_ERROR_SIZE (5)
|
||||
// Stream Read Timeout
|
||||
#define UPDATE_ERROR_STREAM (6)
|
||||
// MD5 Check Failed
|
||||
#define UPDATE_ERROR_MD5 (7)
|
||||
// Wrong Magic Byte
|
||||
#define UPDATE_ERROR_MAGIC_BYTE (8)
|
||||
// Could Not Activate The Firmware
|
||||
#define UPDATE_ERROR_ACTIVATE (9)
|
||||
// Partition Could Not be Found
|
||||
#define UPDATE_ERROR_NO_PARTITION (10)
|
||||
// Bad Argument
|
||||
#define UPDATE_ERROR_BAD_ARGUMENT (11)
|
||||
// Aborted
|
||||
#define UPDATE_ERROR_ABORT (12)
|
||||
|
||||
#define UPDATE_SIZE_UNKNOWN 0xFFFFFFFF
|
||||
|
||||
#define U_FLASH 0
|
||||
#define U_SPIFFS 100
|
||||
#define U_AUTH 200
|
||||
|
||||
#define ENCRYPTED_BLOCK_SIZE 16
|
||||
|
||||
#define UPDATE_TIMEOUT_MS 30 * 1000
|
||||
|
||||
class UpdateClass {
|
||||
public:
|
||||
typedef std::function<void(size_t, size_t)> THandlerFunction_Progress;
|
||||
|
||||
public: /* Update.cpp */
|
||||
UpdateClass();
|
||||
bool begin(
|
||||
size_t size = UPDATE_SIZE_UNKNOWN,
|
||||
int command = U_FLASH,
|
||||
int unused2 = -1,
|
||||
uint8_t unused3 = LOW,
|
||||
const char *unused4 = NULL // this is for SPIFFS
|
||||
);
|
||||
bool end(bool evenIfRemaining = false);
|
||||
size_t write(uint8_t *data, size_t len);
|
||||
size_t writeStream(Stream &data);
|
||||
bool canRollBack();
|
||||
bool rollBack();
|
||||
// bool setMD5(const char *expected_md5);
|
||||
|
||||
private: /* Update.cpp */
|
||||
size_t tryWriteData(uint8_t *data = NULL, size_t len = 0);
|
||||
|
||||
public: /* UpdateUtil.cpp */
|
||||
UpdateClass &onProgress(THandlerFunction_Progress callback);
|
||||
void abort();
|
||||
void printError(Print &out);
|
||||
const char *errorString();
|
||||
const char *getFirmwareName();
|
||||
const char *getFirmwareVersion();
|
||||
const char *getLibreTuyaVersion();
|
||||
const char *getBoardName();
|
||||
|
||||
private: /* UpdateUtil.cpp */
|
||||
void cleanup();
|
||||
bool errorUf2(uf2_err_t err);
|
||||
bool errorArd(uint8_t err);
|
||||
void bufAlloc();
|
||||
uint16_t bufLeft();
|
||||
uint16_t bufSize();
|
||||
|
||||
private:
|
||||
// uf2ota context
|
||||
uf2_ota_t *ctx;
|
||||
uf2_info_t *info;
|
||||
// block buffer
|
||||
uint8_t *buf;
|
||||
uint8_t *bufPos;
|
||||
// update progress - multiplies of 512 bytes
|
||||
uint32_t bytesWritten;
|
||||
uint32_t bytesTotal;
|
||||
// errors
|
||||
uf2_err_t errUf2;
|
||||
uint8_t errArd;
|
||||
// progress callback
|
||||
THandlerFunction_Progress callback;
|
||||
// String _target_md5;
|
||||
// MD5Builder _md5;
|
||||
|
||||
public:
|
||||
String md5String(void) {
|
||||
// return _md5.toString();
|
||||
}
|
||||
|
||||
void md5(uint8_t *result) {
|
||||
// return _md5.getBytes(result);
|
||||
}
|
||||
|
||||
uint8_t getError() {
|
||||
return errArd;
|
||||
}
|
||||
|
||||
uf2_err_t getUF2Error() {
|
||||
return errUf2;
|
||||
}
|
||||
|
||||
void clearError() {
|
||||
errorUf2(UF2_ERR_OK);
|
||||
}
|
||||
|
||||
bool hasError() {
|
||||
return errArd != UPDATE_ERROR_OK;
|
||||
}
|
||||
|
||||
bool isRunning() {
|
||||
return ctx != NULL;
|
||||
}
|
||||
|
||||
bool isFinished() {
|
||||
return bytesWritten == bytesTotal;
|
||||
}
|
||||
|
||||
size_t size() {
|
||||
return bytesTotal;
|
||||
}
|
||||
|
||||
size_t progress() {
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
size_t remaining() {
|
||||
return bytesTotal - bytesWritten;
|
||||
}
|
||||
};
|
||||
|
||||
extern UpdateClass Update;
|
||||
162
arduino/libretuya/libraries/Update/UpdateUtil.cpp
Normal file
162
arduino/libretuya/libraries/Update/UpdateUtil.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-30. */
|
||||
|
||||
#include "Update.h"
|
||||
|
||||
static const uint8_t errorMap[] = {
|
||||
UPDATE_ERROR_OK, /* UF2_ERR_OK - no error */
|
||||
UPDATE_ERROR_OK, /* UF2_ERR_IGNORE - block should be ignored */
|
||||
UPDATE_ERROR_MAGIC_BYTE, /* UF2_ERR_MAGIC - wrong magic numbers */
|
||||
UPDATE_ERROR_BAD_ARGUMENT, /* UF2_ERR_FAMILY - family ID mismatched */
|
||||
UPDATE_ERROR_BAD_ARGUMENT, /* UF2_ERR_NOT_HEADER - block is not a header */
|
||||
UPDATE_ERROR_BAD_ARGUMENT, /* UF2_ERR_OTA_VER - unknown/invalid OTA format version */
|
||||
UPDATE_ERROR_MAGIC_BYTE, /* UF2_ERR_OTA_WRONG - no data for current OTA index */
|
||||
UPDATE_ERROR_NO_PARTITION, /* UF2_ERR_PART_404 - no partition with that name */
|
||||
UPDATE_ERROR_BAD_ARGUMENT, /* UF2_ERR_PART_ONE - only one partition tag in a block */
|
||||
UPDATE_ERROR_BAD_ARGUMENT, /* UF2_ERR_PART_UNSET - attempted to write without target partition */
|
||||
UPDATE_ERROR_BAD_ARGUMENT, /* UF2_ERR_DATA_TOO_LONG - data too long - tags won't fit */
|
||||
UPDATE_ERROR_BAD_ARGUMENT, /* UF2_ERR_SEQ_MISMATCH - sequence number mismatched */
|
||||
UPDATE_ERROR_ERASE, /* UF2_ERR_ERASE_FAILED - erasing flash failed */
|
||||
UPDATE_ERROR_WRITE, /* UF2_ERR_WRITE_FAILED - writing to flash failed */
|
||||
UPDATE_ERROR_WRITE /* UF2_ERR_WRITE_LENGTH - wrote fewer data than requested */
|
||||
};
|
||||
|
||||
static char errorStr[14];
|
||||
|
||||
/**
|
||||
* @brief Set the callback invoked after writing data to flash.
|
||||
*/
|
||||
UpdateClass &UpdateClass::onProgress(THandlerFunction_Progress callback) {
|
||||
this->callback = callback;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void UpdateClass::cleanup() {
|
||||
free(ctx); // NULL in constructor
|
||||
ctx = NULL;
|
||||
uf2_info_free(info); // NULL in constructor
|
||||
info = NULL;
|
||||
free(buf); // NULL in constructor
|
||||
buf = bufPos = NULL;
|
||||
|
||||
bytesWritten = 0;
|
||||
bytesTotal = 0;
|
||||
errUf2 = UF2_ERR_OK;
|
||||
errArd = UPDATE_ERROR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check for UF2 errors. Set errArd and errUf2 in case of errors.
|
||||
* Ignored blocks are not reported as errors.
|
||||
* Abort the update.
|
||||
* Use like: "if (errorUf2(...)) return false;"
|
||||
* @return true if err is not OK, false otherwise
|
||||
*/
|
||||
bool UpdateClass::errorUf2(uf2_err_t err) {
|
||||
if (err <= UF2_ERR_IGNORE)
|
||||
return false;
|
||||
cleanup();
|
||||
errUf2 = err;
|
||||
errArd = errorMap[err];
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set errUf2 and errArd according to given Arduino error code.
|
||||
* Abort the update.
|
||||
* Use like: "return errorArd(...);"
|
||||
* @return false - always
|
||||
*/
|
||||
bool UpdateClass::errorArd(uint8_t err) {
|
||||
cleanup();
|
||||
errUf2 = UF2_ERR_OK;
|
||||
errArd = err;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort the update with UPDATE_ERROR_ABORT reason.
|
||||
*/
|
||||
void UpdateClass::abort() {
|
||||
errorArd(UPDATE_ERROR_ABORT);
|
||||
}
|
||||
|
||||
void UpdateClass::bufAlloc() {
|
||||
if (!buf)
|
||||
buf = bufPos = (uint8_t *)malloc(UF2_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
uint16_t UpdateClass::bufLeft() {
|
||||
return buf + UF2_BLOCK_SIZE - bufPos;
|
||||
}
|
||||
|
||||
uint16_t UpdateClass::bufSize() {
|
||||
return bufPos - buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Print string error info to the stream.
|
||||
*/
|
||||
void UpdateClass::printError(Print &out) {
|
||||
out.println(errorString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get string representation of the error in format
|
||||
* "ard=..,uf2=..". Returns "" if no error.
|
||||
*/
|
||||
const char *UpdateClass::errorString() {
|
||||
if (!errArd)
|
||||
return "";
|
||||
sprintf(errorStr, "ard=%u,uf2=%u", errArd, errUf2);
|
||||
return errorStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get firmware name from UF2 info.
|
||||
*/
|
||||
const char *UpdateClass::getFirmwareName() {
|
||||
if (info)
|
||||
return info->fw_name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get firmware version from UF2 info.
|
||||
*/
|
||||
const char *UpdateClass::getFirmwareVersion() {
|
||||
if (info)
|
||||
return info->fw_version;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get LibreTuya version from UF2 info.
|
||||
*/
|
||||
const char *UpdateClass::getLibreTuyaVersion() {
|
||||
if (info)
|
||||
return info->lt_version;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get target board name from UF2 info.
|
||||
*/
|
||||
const char *UpdateClass::getBoardName() {
|
||||
if (info)
|
||||
return info->board;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief See LT.otaCanRollback() for more info.
|
||||
*/
|
||||
bool UpdateClass::canRollBack() {
|
||||
return LT.otaCanRollback();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief See LT.otaRollback() for more info.
|
||||
*/
|
||||
bool UpdateClass::rollBack() {
|
||||
return LT.otaRollback();
|
||||
}
|
||||
32
arduino/libretuya/libraries/Update/uf2ota/uf2binpatch.c
Normal file
32
arduino/libretuya/libraries/Update/uf2ota/uf2binpatch.c
Normal file
@@ -0,0 +1,32 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-29. */
|
||||
|
||||
#include "uf2priv.h"
|
||||
|
||||
uf2_err_t uf2_binpatch(uint8_t *data, const uint8_t *binpatch, uint8_t binpatch_len) {
|
||||
const uint8_t *binpatch_end = binpatch + binpatch_len;
|
||||
// +2 to make sure opcode and length is present
|
||||
while ((binpatch + 2) < binpatch_end) {
|
||||
uf2_opcode_t opcode = binpatch[0];
|
||||
uint8_t len = binpatch[1];
|
||||
switch (opcode) {
|
||||
case UF2_OPC_DIFF32:
|
||||
uf2_binpatch_diff32(data, binpatch + 1);
|
||||
break;
|
||||
}
|
||||
// advance by opcode + length + data
|
||||
binpatch += len + 2;
|
||||
}
|
||||
return UF2_ERR_OK;
|
||||
}
|
||||
|
||||
void uf2_binpatch_diff32(uint8_t *data, const uint8_t *patch) {
|
||||
uint8_t num_offs = patch[0] - 4; // read offset count
|
||||
uint32_t diff = *((uint32_t *)(patch + 1)); // read diff value
|
||||
patch += 5; // skip num_offs and diff value
|
||||
for (uint8_t i = 0; i < num_offs; i++) {
|
||||
// patch the data
|
||||
uint8_t offs = patch[i];
|
||||
uint32_t *value = (uint32_t *)(data + offs);
|
||||
*(value) += diff;
|
||||
}
|
||||
}
|
||||
26
arduino/libretuya/libraries/Update/uf2ota/uf2binpatch.h
Normal file
26
arduino/libretuya/libraries/Update/uf2ota/uf2binpatch.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-29. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "uf2types.h"
|
||||
|
||||
/**
|
||||
* @brief Apply binary patch to data.
|
||||
*
|
||||
* @param data input data
|
||||
* @param data_len input data length
|
||||
* @param binpatch binary patch data
|
||||
* @param binpatch_len binary patch data length
|
||||
* @return uf2_err_t error code
|
||||
*/
|
||||
uf2_err_t uf2_binpatch(uint8_t *data, const uint8_t *binpatch, uint8_t binpatch_len);
|
||||
|
||||
/**
|
||||
* Apply DIFF32 binary patch.
|
||||
*
|
||||
* @param data input data
|
||||
* @param len input data length
|
||||
* @param patch patch data, incl. length byte
|
||||
* @return uf2_err_t error code
|
||||
*/
|
||||
void uf2_binpatch_diff32(uint8_t *data, const uint8_t *patch);
|
||||
100
arduino/libretuya/libraries/Update/uf2ota/uf2ota.c
Normal file
100
arduino/libretuya/libraries/Update/uf2ota/uf2ota.c
Normal file
@@ -0,0 +1,100 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-29. */
|
||||
|
||||
#include "uf2priv.h"
|
||||
|
||||
uf2_ota_t *uf2_ctx_init(uint8_t ota_idx, uint32_t family_id) {
|
||||
uf2_ota_t *ctx = (uf2_ota_t *)zalloc(sizeof(uf2_ota_t));
|
||||
ctx->ota_idx = ota_idx;
|
||||
ctx->family_id = family_id;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
uf2_info_t *uf2_info_init() {
|
||||
uf2_info_t *info = (uf2_info_t *)zalloc(sizeof(uf2_info_t));
|
||||
return info;
|
||||
}
|
||||
|
||||
void uf2_info_free(uf2_info_t *info) {
|
||||
if (!info)
|
||||
return;
|
||||
free(info->fw_name);
|
||||
free(info->fw_version);
|
||||
free(info->lt_version);
|
||||
free(info->board);
|
||||
free(info);
|
||||
}
|
||||
|
||||
uf2_err_t uf2_check_block(uf2_ota_t *ctx, uf2_block_t *block) {
|
||||
if (block->magic1 != UF2_MAGIC_1)
|
||||
return UF2_ERR_MAGIC;
|
||||
if (block->magic2 != UF2_MAGIC_2)
|
||||
return UF2_ERR_MAGIC;
|
||||
if (block->magic3 != UF2_MAGIC_3)
|
||||
return UF2_ERR_MAGIC;
|
||||
if (block->file_container)
|
||||
// ignore file containers, for now
|
||||
return UF2_ERR_IGNORE;
|
||||
if (!block->has_family_id || block->file_size != ctx->family_id)
|
||||
// require family_id
|
||||
return UF2_ERR_FAMILY;
|
||||
return UF2_ERR_OK;
|
||||
}
|
||||
|
||||
uf2_err_t uf2_parse_header(uf2_ota_t *ctx, uf2_block_t *block, uf2_info_t *info) {
|
||||
if (!block->has_tags || block->file_container || block->len)
|
||||
// header must have tags and no data
|
||||
return UF2_ERR_NOT_HEADER;
|
||||
|
||||
uf2_err_t err = uf2_parse_block(ctx, block, info);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if ((ctx->ota_idx == 1 && !ctx->has_ota1) || !ctx->has_ota2)
|
||||
return UF2_ERR_OTA_WRONG;
|
||||
return UF2_ERR_OK;
|
||||
}
|
||||
|
||||
uf2_err_t uf2_write(uf2_ota_t *ctx, uf2_block_t *block) {
|
||||
if (ctx->seq == 0)
|
||||
return uf2_parse_header(ctx, block, NULL);
|
||||
if (block->not_main_flash || !block->len)
|
||||
// ignore blocks not meant for flashing
|
||||
return UF2_ERR_IGNORE;
|
||||
|
||||
uf2_err_t err = uf2_parse_block(ctx, block, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!ctx->part1 && !ctx->part2)
|
||||
// no partitions set at all
|
||||
return UF2_ERR_PART_UNSET;
|
||||
|
||||
fal_partition_t part = uf2_get_target_part(ctx);
|
||||
if (!part)
|
||||
// image is not for current OTA scheme
|
||||
return UF2_ERR_IGNORE;
|
||||
|
||||
if (ctx->ota_idx == 2 && ctx->binpatch_len) {
|
||||
// apply binpatch
|
||||
err = uf2_binpatch(block->data, ctx->binpatch, ctx->binpatch_len);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
int ret;
|
||||
// erase sectors if needed
|
||||
if (!uf2_is_erased(ctx, block->addr, block->len)) {
|
||||
ret = fal_partition_erase(part, block->addr, block->len);
|
||||
if (ret < 0)
|
||||
return UF2_ERR_ERASE_FAILED;
|
||||
ctx->erased_offset = block->addr;
|
||||
ctx->erased_length = ret;
|
||||
}
|
||||
// write data to flash
|
||||
ret = fal_partition_write(part, block->addr, block->data, block->len);
|
||||
if (ret < 0)
|
||||
return UF2_ERR_WRITE_FAILED;
|
||||
if (ret != block->len)
|
||||
return UF2_ERR_WRITE_LENGTH;
|
||||
return UF2_ERR_OK;
|
||||
}
|
||||
68
arduino/libretuya/libraries/Update/uf2ota/uf2ota.h
Normal file
68
arduino/libretuya/libraries/Update/uf2ota/uf2ota.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-28. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#include "uf2types.h"
|
||||
|
||||
/**
|
||||
* @brief Create an UF2 OTA context.
|
||||
*
|
||||
* @param ota_idx target OTA index
|
||||
* @param family_id expected family ID
|
||||
* @return uf2_ota_t* heap-allocated structure
|
||||
*/
|
||||
uf2_ota_t *uf2_ctx_init(uint8_t ota_idx, uint32_t family_id);
|
||||
|
||||
/**
|
||||
* @brief Create an UF2 Info structure.
|
||||
*
|
||||
* @return uf2_info_t* heap-allocated structure
|
||||
*/
|
||||
uf2_info_t *uf2_info_init();
|
||||
|
||||
/**
|
||||
* @brief Free values in the info structure AND the structure itself.
|
||||
*
|
||||
* @param info structure to free; may be NULL
|
||||
*/
|
||||
void uf2_info_free(uf2_info_t *info);
|
||||
|
||||
/**
|
||||
* @brief Check if block is valid.
|
||||
*
|
||||
* @param ctx context
|
||||
* @param block block to check
|
||||
* @return uf2_err_t error code; UF2_ERR_OK and UF2_ERR_IGNORE denote valid blocks
|
||||
*/
|
||||
uf2_err_t uf2_check_block(uf2_ota_t *ctx, uf2_block_t *block);
|
||||
|
||||
/**
|
||||
* @brief Parse header block (LibreTuya UF2 first block).
|
||||
*
|
||||
* Note: caller should call uf2_check_block() first.
|
||||
*
|
||||
* @param ctx context
|
||||
* @param block block to parse
|
||||
* @param info structure to write firmware info, NULL if not used
|
||||
* @return uf2_err_t error code
|
||||
*/
|
||||
uf2_err_t uf2_parse_header(uf2_ota_t *ctx, uf2_block_t *block, uf2_info_t *info);
|
||||
|
||||
/**
|
||||
* @brief Write the block to flash memory.
|
||||
*
|
||||
* Note: caller should call uf2_check_block() first.
|
||||
*
|
||||
* @param ctx context
|
||||
* @param block block to write
|
||||
* @return uf2_err_t error code
|
||||
*/
|
||||
uf2_err_t uf2_write(uf2_ota_t *ctx, uf2_block_t *block);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
146
arduino/libretuya/libraries/Update/uf2ota/uf2priv.c
Normal file
146
arduino/libretuya/libraries/Update/uf2ota/uf2priv.c
Normal file
@@ -0,0 +1,146 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-29. */
|
||||
|
||||
#include "uf2priv.h"
|
||||
|
||||
uf2_err_t uf2_parse_block(uf2_ota_t *ctx, uf2_block_t *block, uf2_info_t *info) {
|
||||
if (block->block_seq != ctx->seq)
|
||||
// sequence number must match
|
||||
return UF2_ERR_SEQ_MISMATCH;
|
||||
ctx->seq++; // increment sequence number after checking it
|
||||
|
||||
if (!block->has_tags)
|
||||
// no tags in this block, no further processing needed
|
||||
return UF2_ERR_OK;
|
||||
|
||||
if (block->len > (476 - 4 - 4))
|
||||
// at least one tag + last tag must fit
|
||||
return UF2_ERR_DATA_TOO_LONG;
|
||||
|
||||
uint8_t *tags_start = block->data + block->len;
|
||||
uint8_t tags_len = 476 - block->len;
|
||||
uint8_t tags_pos = 0;
|
||||
if (block->has_md5)
|
||||
tags_len -= 24;
|
||||
|
||||
ctx->binpatch_len = 0; // binpatch applies to one block only
|
||||
char *part1 = NULL;
|
||||
char *part2 = NULL;
|
||||
|
||||
uf2_tag_type_t type;
|
||||
while (tags_pos < tags_len) {
|
||||
uint8_t len = uf2_read_tag(tags_start + tags_pos, &type);
|
||||
if (!len)
|
||||
break;
|
||||
tags_pos += 4; // skip tag header
|
||||
uint8_t *tag = tags_start + tags_pos;
|
||||
|
||||
char **str_dest = NULL; // char* to copy the tag into
|
||||
|
||||
switch (type) {
|
||||
case UF2_TAG_OTA_VERSION:
|
||||
if (tag[0] != 1)
|
||||
return UF2_ERR_OTA_VER;
|
||||
break;
|
||||
case UF2_TAG_FIRMWARE:
|
||||
if (info)
|
||||
str_dest = &(info->fw_name);
|
||||
break;
|
||||
case UF2_TAG_VERSION:
|
||||
if (info)
|
||||
str_dest = &(info->fw_version);
|
||||
break;
|
||||
case UF2_TAG_LT_VERSION:
|
||||
if (info)
|
||||
str_dest = &(info->lt_version);
|
||||
break;
|
||||
case UF2_TAG_BOARD:
|
||||
if (info)
|
||||
str_dest = &(info->board);
|
||||
break;
|
||||
case UF2_TAG_HAS_OTA1:
|
||||
ctx->has_ota1 = tag[0];
|
||||
break;
|
||||
case UF2_TAG_HAS_OTA2:
|
||||
ctx->has_ota2 = tag[0];
|
||||
break;
|
||||
case UF2_TAG_PART_1:
|
||||
str_dest = &(part1);
|
||||
break;
|
||||
case UF2_TAG_PART_2:
|
||||
str_dest = &(part2);
|
||||
break;
|
||||
case UF2_TAG_BINPATCH:
|
||||
ctx->binpatch = tag;
|
||||
ctx->binpatch_len = len;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (str_dest) {
|
||||
*str_dest = (char *)zalloc(len + 1);
|
||||
memcpy(*str_dest, tag, len);
|
||||
}
|
||||
// align position to 4 bytes
|
||||
tags_pos += (((len - 1) / 4) + 1) * 4;
|
||||
}
|
||||
|
||||
if (part1 && part2) {
|
||||
// update current target partition
|
||||
uf2_err_t err = uf2_update_parts(ctx, part1, part2);
|
||||
if (err)
|
||||
return err;
|
||||
} else if (part1 || part2) {
|
||||
// only none or both partitions can be specified
|
||||
return UF2_ERR_PART_ONE;
|
||||
}
|
||||
|
||||
return UF2_ERR_OK;
|
||||
}
|
||||
|
||||
uint8_t uf2_read_tag(const uint8_t *data, uf2_tag_type_t *type) {
|
||||
uint8_t len = data[0];
|
||||
if (!len)
|
||||
return 0;
|
||||
uint32_t tag_type = *((uint32_t *)data);
|
||||
if (!tag_type)
|
||||
return 0;
|
||||
*type = tag_type >> 8; // remove tag length byte
|
||||
return len - 4;
|
||||
}
|
||||
|
||||
uf2_err_t uf2_update_parts(uf2_ota_t *ctx, char *part1, char *part2) {
|
||||
// reset both target partitions
|
||||
ctx->part1 = NULL;
|
||||
ctx->part2 = NULL;
|
||||
// reset offsets as they probably don't apply to this partition
|
||||
ctx->erased_offset = 0;
|
||||
ctx->erased_length = 0;
|
||||
|
||||
if (part1[0]) {
|
||||
ctx->part1 = fal_partition_find(part1);
|
||||
if (!ctx->part1)
|
||||
return UF2_ERR_PART_404;
|
||||
}
|
||||
if (part2[0]) {
|
||||
ctx->part2 = fal_partition_find(part2);
|
||||
if (!ctx->part2)
|
||||
return UF2_ERR_PART_404;
|
||||
}
|
||||
|
||||
return UF2_ERR_OK;
|
||||
}
|
||||
|
||||
fal_partition_t uf2_get_target_part(uf2_ota_t *ctx) {
|
||||
if (ctx->ota_idx == 1)
|
||||
return ctx->part1;
|
||||
if (ctx->ota_idx == 2)
|
||||
return ctx->part2;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool uf2_is_erased(uf2_ota_t *ctx, uint32_t offset, uint32_t length) {
|
||||
uint32_t erased_end = ctx->erased_offset + ctx->erased_length;
|
||||
uint32_t end = offset + length;
|
||||
return (offset >= ctx->erased_offset) && (end <= erased_end);
|
||||
}
|
||||
61
arduino/libretuya/libraries/Update/uf2ota/uf2priv.h
Normal file
61
arduino/libretuya/libraries/Update/uf2ota/uf2priv.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-28. */
|
||||
|
||||
#pragma once
|
||||
|
||||
// include family stdlib APIs
|
||||
#include <WVariant.h>
|
||||
|
||||
#include "uf2binpatch.h"
|
||||
#include "uf2types.h"
|
||||
|
||||
/**
|
||||
* @brief Parse a block and extract information from tags.
|
||||
*
|
||||
* @param ctx context
|
||||
* @param block block to parse
|
||||
* @param info structure to write firmware info, NULL if not used
|
||||
* @return uf2_err_t error code
|
||||
*/
|
||||
uf2_err_t uf2_parse_block(uf2_ota_t *ctx, uf2_block_t *block, uf2_info_t *info);
|
||||
|
||||
/**
|
||||
* @brief Parse a tag.
|
||||
*
|
||||
* @param data pointer to tag header beginning
|
||||
* @param type [out] parsed tag type
|
||||
* @return uint8_t parsed tag data length (excl. header); 0 if invalid/last tag
|
||||
*/
|
||||
uint8_t uf2_read_tag(const uint8_t *data, uf2_tag_type_t *type);
|
||||
|
||||
/**
|
||||
* @brief Update destination partitions in context.
|
||||
*
|
||||
* Partition names cannot be NULL.
|
||||
*
|
||||
* Returns UF2_ERR_IGNORE if specified partitions don't match the
|
||||
* current OTA index.
|
||||
*
|
||||
* @param ctx context
|
||||
* @param part1 partition 1 name or empty string
|
||||
* @param part2 partition 2 name or empty string
|
||||
* @return uf2_err_t error code
|
||||
*/
|
||||
uf2_err_t uf2_update_parts(uf2_ota_t *ctx, char *part1, char *part2);
|
||||
|
||||
/**
|
||||
* @brief Get target flashing partition, depending on OTA index.
|
||||
*
|
||||
* @param ctx context
|
||||
* @return fal_partition_t target partition or NULL if not set
|
||||
*/
|
||||
fal_partition_t uf2_get_target_part(uf2_ota_t *ctx);
|
||||
|
||||
/**
|
||||
* Check if specified flash memory region was already erased during update.
|
||||
*
|
||||
* @param ctx context
|
||||
* @param offset offset to check
|
||||
* @param length length to check
|
||||
* @return bool true/false
|
||||
*/
|
||||
bool uf2_is_erased(uf2_ota_t *ctx, uint32_t offset, uint32_t length);
|
||||
104
arduino/libretuya/libraries/Update/uf2ota/uf2types.h
Normal file
104
arduino/libretuya/libraries/Update/uf2ota/uf2types.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-28. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <fal.h>
|
||||
|
||||
#define UF2_MAGIC_1 0x0A324655
|
||||
#define UF2_MAGIC_2 0x9E5D5157
|
||||
#define UF2_MAGIC_3 0x0AB16F30
|
||||
|
||||
#define UF2_BLOCK_SIZE sizeof(uf2_block_t)
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
// 32 byte header
|
||||
uint32_t magic1;
|
||||
uint32_t magic2;
|
||||
|
||||
// flags split as bitfields
|
||||
bool not_main_flash : 1;
|
||||
uint16_t dummy1 : 11;
|
||||
bool file_container : 1;
|
||||
bool has_family_id : 1;
|
||||
bool has_md5 : 1;
|
||||
bool has_tags : 1;
|
||||
uint16_t dummy2 : 16;
|
||||
|
||||
uint32_t addr;
|
||||
uint32_t len;
|
||||
uint32_t block_seq;
|
||||
uint32_t block_count;
|
||||
uint32_t file_size; // or familyID;
|
||||
uint8_t data[476];
|
||||
uint32_t magic3;
|
||||
} uf2_block_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t seq; // current block sequence number
|
||||
|
||||
uint8_t *binpatch; // current block's binpatch (if any) -> pointer inside block->data
|
||||
uint8_t binpatch_len; // binpatch length
|
||||
|
||||
bool has_ota1; // image has any data for OTA1
|
||||
bool has_ota2; // image has any data for OTA2
|
||||
|
||||
uint8_t ota_idx; // target OTA index
|
||||
uint32_t family_id; // expected family ID
|
||||
|
||||
uint32_t erased_offset; // offset of region erased during update
|
||||
uint32_t erased_length; // length of erased region
|
||||
|
||||
fal_partition_t part1; // OTA1 target partition
|
||||
fal_partition_t part2; // OTA2 target partition
|
||||
} uf2_ota_t;
|
||||
|
||||
typedef struct {
|
||||
char *fw_name;
|
||||
char *fw_version;
|
||||
char *lt_version;
|
||||
char *board;
|
||||
} uf2_info_t;
|
||||
|
||||
typedef enum {
|
||||
UF2_TAG_VERSION = 0x9FC7BC, // version of firmware file - UTF8 semver string
|
||||
UF2_TAG_PAGE_SIZE = 0x0BE9F7, // page size of target device (32 bit unsigned number)
|
||||
UF2_TAG_SHA2 = 0xB46DB0, // SHA-2 checksum of firmware (can be of various size)
|
||||
UF2_TAG_DEVICE = 0x650D9D, // description of device (UTF8)
|
||||
UF2_TAG_DEVICE_ID = 0xC8A729, // device type identifier
|
||||
// LibreTuya custom, tags
|
||||
UF2_TAG_OTA_VERSION = 0x5D57D0, // format version
|
||||
UF2_TAG_BOARD = 0xCA25C8, // board name (lowercase code)
|
||||
UF2_TAG_FIRMWARE = 0x00DE43, // firmware description / name
|
||||
UF2_TAG_BUILD_DATE = 0x822F30, // build date/time as Unix timestamp
|
||||
UF2_TAG_LT_VERSION = 0x59563D, // LT version (semver)
|
||||
UF2_TAG_PART_1 = 0x805946, // OTA1 partition name
|
||||
UF2_TAG_PART_2 = 0xA1E4D7, // OTA2 partition name
|
||||
UF2_TAG_HAS_OTA1 = 0xBBD965, // image has any data for OTA1
|
||||
UF2_TAG_HAS_OTA2 = 0x92280E, // image has any data for OTA2
|
||||
UF2_TAG_BINPATCH = 0xB948DE, // binary patch to convert OTA1->OTA2
|
||||
} uf2_tag_type_t;
|
||||
|
||||
typedef enum {
|
||||
UF2_OPC_DIFF32 = 0xFE,
|
||||
} uf2_opcode_t;
|
||||
|
||||
typedef enum {
|
||||
UF2_ERR_OK = 0,
|
||||
UF2_ERR_IGNORE, // block should be ignored
|
||||
UF2_ERR_MAGIC, // wrong magic numbers
|
||||
UF2_ERR_FAMILY, // family ID mismatched
|
||||
UF2_ERR_NOT_HEADER, // block is not a header
|
||||
UF2_ERR_OTA_VER, // unknown/invalid OTA format version
|
||||
UF2_ERR_OTA_WRONG, // no data for current OTA index
|
||||
UF2_ERR_PART_404, // no partition with that name
|
||||
UF2_ERR_PART_ONE, // only one partition tag in a block
|
||||
UF2_ERR_PART_UNSET, // image broken - attempted to write without target partition
|
||||
UF2_ERR_DATA_TOO_LONG, // data too long - tags won't fit
|
||||
UF2_ERR_SEQ_MISMATCH, // sequence number mismatched
|
||||
UF2_ERR_ERASE_FAILED, // erasing flash failed
|
||||
UF2_ERR_WRITE_FAILED, // writing to flash failed
|
||||
UF2_ERR_WRITE_LENGTH, // wrote fewer data than requested
|
||||
} uf2_err_t;
|
||||
5
arduino/libretuya/libraries/mDNS/ESPmDNS.h
Normal file
5
arduino/libretuya/libraries/mDNS/ESPmDNS.h
Normal file
@@ -0,0 +1,5 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-23. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "mDNS.h"
|
||||
153
arduino/libretuya/libraries/mDNS/LwIPmDNS.cpp
Normal file
153
arduino/libretuya/libraries/mDNS/LwIPmDNS.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-23. */
|
||||
|
||||
#ifdef LT_HAS_LWIP2
|
||||
|
||||
#include "mDNS.h"
|
||||
|
||||
extern "C" {
|
||||
#include <lwip/apps/mdns.h>
|
||||
#include <lwip/netif.h>
|
||||
}
|
||||
|
||||
static u8_t mdns_netif_client_id = 0; // TODO fix this
|
||||
|
||||
struct mdns_domain {
|
||||
/* Encoded domain name */
|
||||
u8_t name[256];
|
||||
/* Total length of domain name, including zero */
|
||||
u16_t length;
|
||||
/* Set if compression of this domain is not allowed */
|
||||
u8_t skip_compression;
|
||||
};
|
||||
|
||||
/** Description of a service */
|
||||
struct mdns_service {
|
||||
/** TXT record to answer with */
|
||||
struct mdns_domain txtdata;
|
||||
/** Name of service, like 'myweb' */
|
||||
char name[MDNS_LABEL_MAXLEN + 1];
|
||||
/** Type of service, like '_http' */
|
||||
char service[MDNS_LABEL_MAXLEN + 1];
|
||||
/** Callback function and userdata
|
||||
* to update txtdata buffer */
|
||||
service_get_txt_fn_t txt_fn;
|
||||
void *txt_userdata;
|
||||
/** TTL in seconds of SRV/TXT replies */
|
||||
u32_t dns_ttl;
|
||||
/** Protocol, TCP or UDP */
|
||||
u16_t proto;
|
||||
/** Port of the service */
|
||||
u16_t port;
|
||||
};
|
||||
|
||||
/** Description of a host/netif */
|
||||
struct mdns_host {
|
||||
/** Hostname */
|
||||
char name[MDNS_LABEL_MAXLEN + 1];
|
||||
/** Pointer to services */
|
||||
struct mdns_service *services[MDNS_MAX_SERVICES];
|
||||
/** TTL in seconds of A/AAAA/PTR replies */
|
||||
u32_t dns_ttl;
|
||||
};
|
||||
|
||||
static String mdnsInstanceName = "default_instance";
|
||||
|
||||
mDNS::mDNS() {}
|
||||
|
||||
mDNS::~mDNS() {}
|
||||
|
||||
bool mDNS::begin(const char *hostname) {
|
||||
mdns_resp_init();
|
||||
struct netif *netif = netif_list;
|
||||
while (netif != NULL) {
|
||||
// TODO: detect mdns_netif_client_id by checking netif_get_client_data()
|
||||
// and finding the requested hostname in struct mdns_host
|
||||
if (netif_is_up(netif) && mdns_resp_add_netif(netif, hostname, 255) != ERR_OK) {
|
||||
return false;
|
||||
}
|
||||
netif = netif->next;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void mDNS::end() {
|
||||
struct netif *netif = netif_list;
|
||||
while (netif != NULL) {
|
||||
if (netif_is_up(netif))
|
||||
mdns_resp_remove_netif(netif);
|
||||
netif = netif->next;
|
||||
}
|
||||
}
|
||||
|
||||
void mDNS::setInstanceName(String name) {
|
||||
mdnsInstanceName = name;
|
||||
}
|
||||
|
||||
bool mDNS::addService(char *service, char *proto, uint16_t port) {
|
||||
char _service[strlen(service) + 2];
|
||||
char _proto[strlen(proto) + 2];
|
||||
_service[0] = '_';
|
||||
_proto[0] = '_';
|
||||
// prepend names with _
|
||||
strcpy(_service + 1, service + (service[0] == '_'));
|
||||
strcpy(_proto + 1, proto + (proto[0] == '_'));
|
||||
|
||||
mdns_sd_proto protocol = DNSSD_PROTO_UDP;
|
||||
if (strncmp(_proto + 1, "tcp", 3) == 0)
|
||||
protocol = DNSSD_PROTO_TCP;
|
||||
|
||||
struct netif *netif = netif_list;
|
||||
while (netif != NULL) {
|
||||
if (netif_is_up(netif)) {
|
||||
mdns_resp_add_service(netif, mdnsInstanceName.c_str(), service, protocol, port, 255, NULL, NULL);
|
||||
}
|
||||
netif = netif->next;
|
||||
}
|
||||
}
|
||||
|
||||
bool mDNS::addServiceTxt(char *name, char *proto, char *key, char *value) {
|
||||
char _name[strlen(name) + 2];
|
||||
char _proto[strlen(proto) + 2];
|
||||
_name[0] = '_';
|
||||
_proto[0] = '_';
|
||||
// prepend names with _
|
||||
strcpy(_name + 1, name + (name[0] == '_'));
|
||||
strcpy(_proto + 1, proto + (proto[0] == '_'));
|
||||
|
||||
mdns_sd_proto protocol = DNSSD_PROTO_UDP;
|
||||
if (strncmp(_proto + 1, "tcp", 3) == 0)
|
||||
protocol = DNSSD_PROTO_TCP;
|
||||
|
||||
struct netif *netif = netif_list;
|
||||
struct mdns_host *mdns;
|
||||
struct mdns_service *service;
|
||||
|
||||
uint8_t txt_len = strlen(key) + strlen(value) + 1;
|
||||
char *txt = (char *)malloc(txt_len + 1);
|
||||
sprintf(txt, "%s=%s", key, value);
|
||||
|
||||
while (netif != NULL) {
|
||||
if (netif_is_up(netif)) {
|
||||
mdns = (struct mdns_host *)netif_get_client_data(netif, mdns_netif_client_id);
|
||||
|
||||
for (uint8_t i = 0; i < MDNS_MAX_SERVICES; i++) {
|
||||
service = mdns->services[i];
|
||||
if (service == NULL)
|
||||
continue;
|
||||
if (strcmp(service->service, _name) || service->proto != protocol)
|
||||
continue;
|
||||
if (mdns_resp_add_service_txtitem(service, txt, txt_len) != ERR_OK) {
|
||||
free(txt);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
netif = netif->next;
|
||||
}
|
||||
free(txt);
|
||||
return true;
|
||||
}
|
||||
|
||||
MDNSResponder MDNS;
|
||||
|
||||
#endif
|
||||
119
arduino/libretuya/libraries/mDNS/mDNS.h
Normal file
119
arduino/libretuya/libraries/mDNS/mDNS.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
ESP8266 Multicast DNS (port of CC3000 Multicast DNS library)
|
||||
Version 1.1
|
||||
Copyright (c) 2013 Tony DiCola (tony@tonydicola.com)
|
||||
ESP8266 port (c) 2015 Ivan Grokhotkov (ivan@esp8266.com)
|
||||
MDNS-SD Suport 2015 Hristo Gochkov (hristo@espressif.com)
|
||||
Extended MDNS-SD support 2016 Lars Englund (lars.englund@gmail.com)
|
||||
Rewritten for ESP32 by Hristo Gochkov (hristo@espressif.com)
|
||||
|
||||
This is a simple implementation of multicast DNS query support for an Arduino
|
||||
running on ESP32 chip.
|
||||
|
||||
Usage:
|
||||
- Include the ESP32 Multicast DNS library in the sketch.
|
||||
- Call the begin method in the sketch's setup and provide a domain name (without
|
||||
the '.local' suffix, i.e. just provide 'foo' to resolve 'foo.local'), and the
|
||||
Adafruit CC3000 class instance. Optionally provide a time to live (in seconds)
|
||||
for the DNS record--the default is 1 hour.
|
||||
- Call the update method in each iteration of the sketch's loop function.
|
||||
|
||||
License (MIT license):
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <api/IPv6Address.h>
|
||||
|
||||
class mDNS {
|
||||
public:
|
||||
mDNS();
|
||||
~mDNS();
|
||||
|
||||
bool begin(const char *hostname);
|
||||
void end();
|
||||
|
||||
void setInstanceName(String name);
|
||||
bool addService(char *service, char *proto, uint16_t port);
|
||||
bool addServiceTxt(char *name, char *proto, char *key, char *value);
|
||||
// void enableArduino(uint16_t port = 3232, bool auth = false);
|
||||
// void disableArduino();
|
||||
// void enableWorkstation(esp_interface_t interface = ESP_IF_WIFI_STA);
|
||||
// void disableWorkstation();
|
||||
|
||||
IPAddress queryHost(char *host, uint32_t timeout = 2000);
|
||||
int queryService(char *service, char *proto);
|
||||
|
||||
String hostname(int idx);
|
||||
IPAddress IP(int idx);
|
||||
IPv6Address IPv6(int idx);
|
||||
uint16_t port(int idx);
|
||||
int numTxt(int idx);
|
||||
bool hasTxt(int idx, const char *key);
|
||||
String txt(int idx, const char *key);
|
||||
String txt(int idx, int txtIdx);
|
||||
String txtKey(int idx, int txtIdx);
|
||||
|
||||
void setInstanceName(const char *name) {
|
||||
setInstanceName(String(name));
|
||||
}
|
||||
|
||||
void setInstanceName(char *name) {
|
||||
setInstanceName(String(name));
|
||||
}
|
||||
|
||||
bool addService(const char *service, const char *proto, uint16_t port) {
|
||||
return addService((char *)service, (char *)proto, port);
|
||||
}
|
||||
|
||||
bool addService(String service, String proto, uint16_t port) {
|
||||
return addService(service.c_str(), proto.c_str(), port);
|
||||
}
|
||||
|
||||
void addServiceTxt(const char *name, const char *proto, const char *key, const char *value) {
|
||||
addServiceTxt((char *)name, (char *)proto, (char *)key, (char *)value);
|
||||
}
|
||||
|
||||
void addServiceTxt(String name, String proto, String key, String value) {
|
||||
addServiceTxt(name.c_str(), proto.c_str(), key.c_str(), value.c_str());
|
||||
}
|
||||
|
||||
IPAddress queryHost(const char *host, uint32_t timeout = 2000) {
|
||||
return queryHost((char *)host, timeout);
|
||||
}
|
||||
|
||||
IPAddress queryHost(String host, uint32_t timeout = 2000) {
|
||||
return queryHost(host.c_str(), timeout);
|
||||
}
|
||||
|
||||
int queryService(const char *service, const char *proto) {
|
||||
return queryService((char *)service, (char *)proto);
|
||||
}
|
||||
|
||||
int queryService(String service, String proto) {
|
||||
return queryService(service.c_str(), proto.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
typedef mDNS MDNSResponder;
|
||||
|
||||
extern MDNSResponder MDNS;
|
||||
25
arduino/libretuya/port/flashdb/fal_cfg.h
Normal file
25
arduino/libretuya/port/flashdb/fal_cfg.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-24. */
|
||||
|
||||
#pragma once
|
||||
|
||||
// Flash device configuration
|
||||
extern const struct fal_flash_dev flash0;
|
||||
|
||||
#define FAL_FLASH_DEV_NAME "flash0"
|
||||
|
||||
#define FAL_FLASH_DEV_TABLE \
|
||||
{ &flash0, }
|
||||
|
||||
#define FAL_DEV_NAME_MAX 16 // no need for 24 chars (default)
|
||||
|
||||
// Partition table
|
||||
#define FAL_PART_HAS_TABLE_CFG
|
||||
|
||||
#define FAL_PART_TABLE_ITEM(part_lower, part_upper) \
|
||||
{ \
|
||||
.magic_word = FAL_PART_MAGIC_WORD, /* magic word */ \
|
||||
.name = #part_lower, /* lowercase name as string */ \
|
||||
.flash_name = FAL_FLASH_DEV_NAME, /* flash device name */ \
|
||||
.offset = FLASH_##part_upper##_OFFSET, /* partition offset macro as uppercase string */ \
|
||||
.len = FLASH_##part_upper##_LENGTH, /* partition length macro as uppercase string */ \
|
||||
},
|
||||
45
arduino/libretuya/port/flashdb/fdb_cfg.h
Normal file
45
arduino/libretuya/port/flashdb/fdb_cfg.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _FDB_CFG_H_
|
||||
#define _FDB_CFG_H_
|
||||
|
||||
/* using KVDB feature */
|
||||
#define FDB_USING_KVDB
|
||||
|
||||
#ifdef FDB_USING_KVDB
|
||||
/* Auto update KV to latest default when current KVDB version number is changed. @see fdb_kvdb.ver_num */
|
||||
// #define FDB_KV_AUTO_UPDATE
|
||||
#endif
|
||||
|
||||
/* using TSDB (Time series database) feature */
|
||||
// #define FDB_USING_TSDB
|
||||
|
||||
/* Using FAL storage mode */
|
||||
#define FDB_USING_FAL_MODE
|
||||
|
||||
#ifdef FDB_USING_FAL_MODE
|
||||
/* the flash write granularity, unit: bit
|
||||
* only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1) */
|
||||
#define FDB_WRITE_GRAN 8
|
||||
#endif
|
||||
|
||||
/* Using file storage mode by LIBC file API, like fopen/fread/fwrte/fclose */
|
||||
// #define FDB_USING_FILE_LIBC_MODE
|
||||
|
||||
/* Using file storage mode by POSIX file API, like open/read/write/close */
|
||||
// #define FDB_USING_FILE_POSIX_MODE
|
||||
|
||||
/* MCU Endian Configuration, default is Little Endian Order. */
|
||||
// #define FDB_BIG_ENDIAN
|
||||
|
||||
/* log print macro. default EF_PRINT macro is printf() */
|
||||
#define FDB_PRINT(...)
|
||||
|
||||
/* print debug information */
|
||||
// #define FDB_DEBUG_ENABLE
|
||||
|
||||
#endif /* _FDB_CFG_H_ */
|
||||
2
arduino/libretuya/posix/.clang-format
Normal file
2
arduino/libretuya/posix/.clang-format
Normal file
@@ -0,0 +1,2 @@
|
||||
DisableFormat: true
|
||||
SortIncludes: Never
|
||||
5
arduino/libretuya/posix/lt_posix_api.h
Normal file
5
arduino/libretuya/posix/lt_posix_api.h
Normal file
@@ -0,0 +1,5 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-16. */
|
||||
|
||||
extern char *strdup(const char *);
|
||||
extern int strcasecmp(const char *s1, const char *s2);
|
||||
extern int strncasecmp(const char *s1, const char *s2, size_t n);
|
||||
97
arduino/libretuya/posix/strcasecmp.c
Normal file
97
arduino/libretuya/posix/strcasecmp.c
Normal file
@@ -0,0 +1,97 @@
|
||||
/* $OpenBSD: strcasecmp.c,v 1.6 2005/08/08 08:05:37 espie Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1987, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#include <string.h>
|
||||
typedef unsigned char u_char;
|
||||
/*
|
||||
* This array is designed for mapping upper and lower case letter
|
||||
* together for a case independent comparison. The mappings are
|
||||
* based upon ascii character sequences.
|
||||
*/
|
||||
static const u_char charmap[] = {
|
||||
'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
|
||||
'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
|
||||
'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
|
||||
'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
|
||||
'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
|
||||
'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
|
||||
'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
|
||||
'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
|
||||
'\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
|
||||
'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
|
||||
'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
|
||||
'\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
|
||||
'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
|
||||
'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
|
||||
'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
|
||||
'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
|
||||
'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
|
||||
'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
|
||||
'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
|
||||
'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
|
||||
'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
|
||||
'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
|
||||
'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
|
||||
'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
|
||||
'\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
|
||||
'\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
|
||||
'\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
|
||||
'\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
|
||||
'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
|
||||
'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
|
||||
'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
|
||||
'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
|
||||
};
|
||||
int
|
||||
strcasecmp(const char *s1, const char *s2)
|
||||
{
|
||||
const u_char *cm = charmap;
|
||||
const u_char *us1 = (const u_char *)s1;
|
||||
const u_char *us2 = (const u_char *)s2;
|
||||
while (cm[*us1] == cm[*us2++])
|
||||
if (*us1++ == '\0')
|
||||
return (0);
|
||||
return (cm[*us1] - cm[*--us2]);
|
||||
}
|
||||
int
|
||||
strncasecmp(const char *s1, const char *s2, size_t n)
|
||||
{
|
||||
if (n != 0) {
|
||||
const u_char *cm = charmap;
|
||||
const u_char *us1 = (const u_char *)s1;
|
||||
const u_char *us2 = (const u_char *)s2;
|
||||
do {
|
||||
if (cm[*us1] != cm[*us2++])
|
||||
return (cm[*us1] - cm[*--us2]);
|
||||
if (*us1++ == '\0')
|
||||
break;
|
||||
} while (--n != 0);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
11
arduino/libretuya/posix/strdup.c
Normal file
11
arduino/libretuya/posix/strdup.c
Normal file
@@ -0,0 +1,11 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-16. */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
__attribute__((weak)) char *strdup(const char *s) {
|
||||
size_t len = strlen(s) + 1;
|
||||
void *newp = malloc(len);
|
||||
if (newp == NULL)
|
||||
return NULL;
|
||||
return (char *)memcpy(newp, s, len);
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#define PinMode PinModeArduino // this conflicts with SDK enum
|
||||
#include <api/ArduinoAPI.h>
|
||||
#include <api/LibreTuyaAPI.h>
|
||||
#include <core/LibreTuyaAPI.h>
|
||||
#undef PinMode
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -23,7 +23,7 @@ extern uint32_t SystemCoreClock;
|
||||
#define interrupts() vPortClearInterruptMask(0)
|
||||
#define noInterrupts() ulPortSetInterruptMask()
|
||||
|
||||
// Include platform-specific code
|
||||
// Include family-specific code
|
||||
#include "WVariant.h"
|
||||
// Include board variant
|
||||
#include "variant.h"
|
||||
|
||||
145
arduino/realtek-ambz/cores/arduino/LibreTuyaAPI.cpp
Normal file
145
arduino/realtek-ambz/cores/arduino/LibreTuyaAPI.cpp
Normal file
@@ -0,0 +1,145 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-28. */
|
||||
|
||||
#include <LibreTuyaAPI.h>
|
||||
|
||||
extern "C" {
|
||||
#include <flash_api.h>
|
||||
#include <rtl8710b.h>
|
||||
#include <sys_api.h>
|
||||
}
|
||||
|
||||
void LibreTuya::restart() {
|
||||
sys_reset();
|
||||
}
|
||||
|
||||
/* CPU-related */
|
||||
|
||||
ChipType LibreTuya::getChipType() {
|
||||
uint8_t chipId;
|
||||
EFUSE_OneByteReadROM(9902, 0xF8, &chipId, L25EOUTVOLTAGE);
|
||||
return (ChipType)(((RTL8710B >> 24) << 8) | chipId);
|
||||
}
|
||||
|
||||
const char *LibreTuya::getChipModel() {
|
||||
return STRINGIFY_MACRO(MCU);
|
||||
}
|
||||
|
||||
uint32_t LibreTuya::getChipId() {
|
||||
uint32_t chipId = 0;
|
||||
uint8_t *id = (uint8_t *)&chipId;
|
||||
// 9902 was extracted from ROM disassembly, probably not needed
|
||||
EFUSE_OneByteReadROM(9902, 0x3B, id + 0, L25EOUTVOLTAGE);
|
||||
EFUSE_OneByteReadROM(9902, 0x3C, id + 1, L25EOUTVOLTAGE);
|
||||
EFUSE_OneByteReadROM(9902, 0x3D, id + 2, L25EOUTVOLTAGE);
|
||||
return chipId;
|
||||
}
|
||||
|
||||
uint8_t LibreTuya::getChipCores() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *LibreTuya::getChipCoreType() {
|
||||
return "ARM Cortex-M4F";
|
||||
}
|
||||
|
||||
uint32_t LibreTuya::getCpuFreqMHz() {
|
||||
return CPU_ClkGet(false) / 1000000;
|
||||
}
|
||||
|
||||
inline uint32_t LibreTuya::getCycleCount() {
|
||||
return microsecondsToClockCycles(micros());
|
||||
}
|
||||
|
||||
/* Memory management */
|
||||
|
||||
uint32_t LibreTuya::getRamSize() {
|
||||
return 256 * 1024;
|
||||
}
|
||||
|
||||
uint32_t LibreTuya::getHeapSize() {
|
||||
return configTOTAL_HEAP_SIZE;
|
||||
}
|
||||
|
||||
uint32_t LibreTuya::getFreeHeap() {
|
||||
return xPortGetFreeHeapSize();
|
||||
}
|
||||
|
||||
uint32_t LibreTuya::getMinFreeHeap() {
|
||||
return xPortGetMinimumEverFreeHeapSize();
|
||||
}
|
||||
|
||||
uint32_t LibreTuya::getMaxAllocHeap() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* OTA-related */
|
||||
|
||||
uint8_t LibreTuya::otaGetStoredIndex() {
|
||||
uint32_t *otaAddress = (uint32_t *)0x8009000;
|
||||
if (*otaAddress == 0xFFFFFFFF)
|
||||
return 1;
|
||||
uint32_t otaCounter = *((uint32_t *)0x8009004);
|
||||
// even count of zero-bits means OTA1, odd count means OTA2
|
||||
// this allows to switch OTA images by simply clearing next bits,
|
||||
// without needing to erase the flash
|
||||
uint8_t count = 0;
|
||||
for (uint8_t i = 0; i < 32; i++) {
|
||||
if ((otaCounter & (1 << i)) == 0)
|
||||
count++;
|
||||
}
|
||||
return 1 + (count % 2);
|
||||
}
|
||||
|
||||
bool LibreTuya::otaSupportsDual() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LibreTuya::otaHasImage1() {
|
||||
uint8_t *ota1Addr = (uint8_t *)(SPI_FLASH_BASE + FLASH_OTA1_OFFSET);
|
||||
return memcmp(ota1Addr, "81958711", 8) == 0;
|
||||
}
|
||||
|
||||
bool LibreTuya::otaHasImage2() {
|
||||
uint8_t *ota2Addr = (uint8_t *)(SPI_FLASH_BASE + FLASH_OTA2_OFFSET);
|
||||
return memcmp(ota2Addr, "81958711", 8) == 0;
|
||||
}
|
||||
|
||||
bool LibreTuya::otaSwitch(bool force) {
|
||||
if (!force && otaGetRunning() != otaGetStoredIndex())
|
||||
// OTA has already been switched
|
||||
return true;
|
||||
// this function does:
|
||||
// - read OTA1 firmware magic from 0xB000
|
||||
// - read OTA2 address from 0x9000
|
||||
// - read OTA2 firmware magic from that address
|
||||
// - read current OTA switch value from 0x9004
|
||||
// - reset OTA switch to 0xFFFFFFFF if it's 0x0
|
||||
// - check first non-zero bit of OTA switch
|
||||
// - write OTA switch with first non-zero bit cleared
|
||||
// sys_clear_ota_signature();
|
||||
// ok, this function is broken (crashes with HardFault)
|
||||
|
||||
if (!otaHasImage1() || !otaHasImage2())
|
||||
return false;
|
||||
|
||||
uint32_t value = HAL_READ32(SPI_FLASH_BASE, FLASH_SYSTEM_OFFSET + 4);
|
||||
if (value == 0) {
|
||||
// TODO does this work at all?
|
||||
FLASH_EreaseDwordsXIP(FLASH_SYSTEM_OFFSET + 4, 1);
|
||||
}
|
||||
uint8_t i;
|
||||
// find first non-zero bit
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (value & (1 << i))
|
||||
break;
|
||||
}
|
||||
// clear the bit
|
||||
value &= ~(1 << i);
|
||||
// write OTA switch to flash
|
||||
flash_write_word(NULL, FLASH_SYSTEM_OFFSET + 4, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Global instance */
|
||||
|
||||
LibreTuya LT;
|
||||
@@ -6,13 +6,27 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// disable typedef in basic_types.h
|
||||
#define boolean boolean_rtl
|
||||
|
||||
#include <strproc.h> // define string macros first
|
||||
#undef isdigit // then remove them, as they conflict
|
||||
#undef islower // with ctype.h macros
|
||||
#undef isprint
|
||||
#undef isspace
|
||||
#undef isxdigit
|
||||
#undef strtol
|
||||
#undef strtoul
|
||||
|
||||
#include <ameba_soc.h>
|
||||
#include <gpio_api.h>
|
||||
#include <main.h>
|
||||
#include <rand.h>
|
||||
#include <rt_lib_rom.h>
|
||||
#include <rtl_lib.h>
|
||||
#include <wait_api.h>
|
||||
|
||||
// remove previously defined workaround
|
||||
#undef boolean
|
||||
|
||||
// stdio.h
|
||||
@@ -35,3 +49,5 @@ extern void wait_us(int us);
|
||||
extern int LOGUART_SetBaud(uint32_t BaudRate); // from fixups/log_uart.c
|
||||
extern void DumpForOneBytes(void *addr, int cnt); // cnt max 0x70!
|
||||
extern void SystemCoreClockUpdate(void);
|
||||
|
||||
extern int _sscanf_patch(const char *buf, const char *fmt, ...);
|
||||
|
||||
@@ -17,3 +17,5 @@ extern void vPortFree(void *pv);
|
||||
#define calloc pvPortCalloc
|
||||
#define realloc pvPortReAlloc
|
||||
#define free vPortFree
|
||||
|
||||
#define LT_HEAP_FUNC xPortGetFreeHeapSize
|
||||
|
||||
@@ -31,7 +31,7 @@ static __inline uint32_t __get_ipsr__(void) {
|
||||
return (__regIPSR);
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
__attribute__((weak)) void init(void) {
|
||||
// nop
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ uint32_t millis(void) {
|
||||
uint32_t micros(void) {
|
||||
uint32_t tick1, tick2;
|
||||
uint32_t us;
|
||||
uint32_t tick_per_us = 166666;
|
||||
uint32_t tick_per_us = F_CPU / 1000;
|
||||
|
||||
if (__get_ipsr__() == 0) {
|
||||
tick1 = xTaskGetTickCount();
|
||||
|
||||
@@ -4,15 +4,12 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#include <flash_api.h>
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
// Global Flash object.
|
||||
FlashClass Flash;
|
||||
|
||||
FlashClass::FlashClass() {
|
||||
flash = NULL;
|
||||
@@ -67,5 +64,3 @@ bool FlashClass::writeBlock(uint32_t offset, uint8_t *data, size_t size) {
|
||||
initialize();
|
||||
return flash_stream_write(flash, offset, size, data);
|
||||
}
|
||||
|
||||
FlashClass Flash;
|
||||
|
||||
@@ -74,21 +74,20 @@ void WiFiClass::printDiag(Print &dest) {
|
||||
}
|
||||
|
||||
WiFiAuthMode WiFiClass::securityTypeToAuthMode(uint8_t type) {
|
||||
switch (wifi_setting.security_type) {
|
||||
case RTW_SECURITY_OPEN:
|
||||
// the value reported in rtw_scan_result is rtw_encryption_t, even though it's rtw_security_t in the header file
|
||||
switch (type) {
|
||||
case RTW_ENCRYPTION_OPEN:
|
||||
return WIFI_AUTH_OPEN;
|
||||
case RTW_SECURITY_WEP_SHARED:
|
||||
case RTW_ENCRYPTION_WEP40:
|
||||
case RTW_ENCRYPTION_WEP104:
|
||||
return WIFI_AUTH_WEP;
|
||||
case RTW_SECURITY_WPA_TKIP_PSK:
|
||||
case RTW_ENCRYPTION_WPA_TKIP:
|
||||
case RTW_ENCRYPTION_WPA_AES:
|
||||
return WIFI_AUTH_WPA_PSK;
|
||||
case RTW_SECURITY_WPA_AES_PSK:
|
||||
return WIFI_AUTH_WPA;
|
||||
case RTW_SECURITY_WPA2_TKIP_PSK:
|
||||
case RTW_ENCRYPTION_WPA2_TKIP:
|
||||
case RTW_ENCRYPTION_WPA2_AES:
|
||||
case RTW_ENCRYPTION_WPA2_MIXED:
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#include "WiFiClient.h"
|
||||
#include "WiFiClientSecure.h"
|
||||
#include "WiFiServer.h"
|
||||
|
||||
class WiFiClass : public IWiFiClass,
|
||||
@@ -72,6 +73,8 @@ class WiFiClass : public IWiFiClass,
|
||||
static uint8_t calculateSubnetCIDR(IPAddress subnetMask);
|
||||
static String macToString(uint8_t *mac);
|
||||
|
||||
static void handleRtwEvent(uint16_t event, char *data, int len, int flags);
|
||||
|
||||
public:
|
||||
// IWiFiSTAClass
|
||||
WiFiStatus begin(
|
||||
|
||||
@@ -7,6 +7,8 @@ bool WiFiClass::softAP(const char *ssid, const char *passphrase, int channel, bo
|
||||
if (!enableAP(true))
|
||||
return false;
|
||||
|
||||
LT_HEAP_I();
|
||||
|
||||
vTaskDelay(20);
|
||||
|
||||
if (!ssid || *ssid == 0x00 || strlen(ssid) > 32) {
|
||||
|
||||
@@ -68,6 +68,9 @@ int WiFiClient::connect(IPAddress ip, uint16_t port, int32_t timeout) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (timeout <= 0)
|
||||
timeout = _timeout; // use default when -1 passed as timeout
|
||||
|
||||
lwip_fcntl(sock, F_SETFL, lwip_fcntl(sock, F_GETFL, 0) | O_NONBLOCK);
|
||||
|
||||
struct sockaddr_in addr;
|
||||
@@ -80,7 +83,7 @@ int WiFiClient::connect(IPAddress ip, uint16_t port, int32_t timeout) {
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(sock, &fdset);
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = timeout * 1000;
|
||||
tv.tv_usec = timeout * 1000; // millis -> micros
|
||||
|
||||
int res = lwip_connect(sock, (struct sockaddr *)&addr, sizeof(addr));
|
||||
if (res < 0 && errno != EINPROGRESS) {
|
||||
|
||||
209
arduino/realtek-ambz/libraries/WiFi/WiFiEvents.cpp
Normal file
209
arduino/realtek-ambz/libraries/WiFi/WiFiEvents.cpp
Normal file
@@ -0,0 +1,209 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-16. */
|
||||
|
||||
#include "WiFi.h"
|
||||
#include "WiFiPriv.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#define WIFI_EVENT_MAX_ROW 3
|
||||
|
||||
static xQueueHandle wifiEventQueueHandle = NULL;
|
||||
static xTaskHandle wifiEventTaskHandle = NULL;
|
||||
|
||||
WiFiClass *pWiFi = NULL;
|
||||
|
||||
// C code to support SDK-defined events (in wifi_conf.c)
|
||||
extern "C" {
|
||||
// SDK events
|
||||
static event_list_elem_t event_callback_list[WIFI_EVENT_MAX][WIFI_EVENT_MAX_ROW];
|
||||
|
||||
typedef struct {
|
||||
rtw_event_indicate_t event;
|
||||
char *buf;
|
||||
int buf_len;
|
||||
int flags;
|
||||
} rtw_event_t;
|
||||
|
||||
// reset callbacks
|
||||
void init_event_callback_list() {
|
||||
memset(event_callback_list, 0, sizeof(event_callback_list));
|
||||
}
|
||||
|
||||
// dummy
|
||||
int wifi_manager_init() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wifi_reg_event_handler(unsigned int event_cmds, rtw_event_handler_t handler_func, void *handler_user_data) {
|
||||
int i = 0, j = 0;
|
||||
if (event_cmds < WIFI_EVENT_MAX) {
|
||||
for (i = 0; i < WIFI_EVENT_MAX_ROW; i++) {
|
||||
if (event_callback_list[event_cmds][i].handler == NULL) {
|
||||
for (j = 0; j < WIFI_EVENT_MAX_ROW; j++) {
|
||||
if (event_callback_list[event_cmds][j].handler == handler_func) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
event_callback_list[event_cmds][i].handler = handler_func;
|
||||
event_callback_list[event_cmds][i].handler_user_data = handler_user_data;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wifi_unreg_event_handler(unsigned int event_cmds, rtw_event_handler_t handler_func) {
|
||||
int i;
|
||||
if (event_cmds < WIFI_EVENT_MAX) {
|
||||
for (i = 0; i < WIFI_EVENT_MAX_ROW; i++) {
|
||||
if (event_callback_list[event_cmds][i].handler == handler_func) {
|
||||
event_callback_list[event_cmds][i].handler = NULL;
|
||||
event_callback_list[event_cmds][i].handler_user_data = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
// function called by wext_wlan_indicate
|
||||
void wifi_indication(rtw_event_indicate_t event, char *buf, int buf_len, int flags) {
|
||||
LT_HEAP_I();
|
||||
if (event >= WIFI_EVENT_MAX)
|
||||
return;
|
||||
if (wifiEventQueueHandle && wifiEventTaskHandle) {
|
||||
rtw_event_t *ev = (rtw_event_t *)malloc(sizeof(rtw_event_t));
|
||||
if (buf_len > 0) {
|
||||
// copy data to allow freeing from calling scopes
|
||||
char *bufCopy = (char *)malloc(buf_len);
|
||||
memcpy(bufCopy, buf, buf_len);
|
||||
ev->buf = bufCopy;
|
||||
} else {
|
||||
ev->buf = NULL;
|
||||
}
|
||||
ev->event = event;
|
||||
ev->buf_len = buf_len;
|
||||
ev->flags = flags;
|
||||
xQueueSend(wifiEventQueueHandle, &ev, portMAX_DELAY);
|
||||
} else {
|
||||
WiFiClass::handleRtwEvent(event, buf, buf_len, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static void wifiEventTask(void *arg) {
|
||||
rtw_event_t *data = NULL;
|
||||
for (;;) {
|
||||
if (xQueueReceive(wifiEventQueueHandle, &data, portMAX_DELAY) == pdTRUE) {
|
||||
WiFiClass::handleRtwEvent(data->event, data->buf, data->buf_len, data->flags);
|
||||
if (data->buf) {
|
||||
// free memory allocated in wifi_indication
|
||||
free(data->buf);
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void startWifiTask() {
|
||||
if (!wifiEventQueueHandle) {
|
||||
LT_HEAP_I();
|
||||
wifiEventQueueHandle = xQueueCreate(32, sizeof(Event_t *));
|
||||
LT_HEAP_I();
|
||||
}
|
||||
if (!wifiEventTaskHandle) {
|
||||
LT_HEAP_I();
|
||||
xTaskCreate(wifiEventTask, "wifievent", 512, NULL, 4, &wifiEventTaskHandle);
|
||||
LT_HEAP_I();
|
||||
}
|
||||
}
|
||||
|
||||
void WiFiClass::handleRtwEvent(uint16_t event, char *data, int len, int flags) {
|
||||
if (flags == -2) {
|
||||
// already an Arduino event, just pass it
|
||||
EventId eventId = (EventId)len;
|
||||
EventInfo *eventInfo = (EventInfo *)data;
|
||||
postEvent(eventId, *eventInfo);
|
||||
free(eventInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
// send to SDK listeners
|
||||
for (uint8_t i = 0; i < WIFI_EVENT_MAX_ROW; i++) {
|
||||
rtw_event_handler_t handler = event_callback_list[event][i].handler;
|
||||
if (!handler)
|
||||
continue;
|
||||
handler(data, len, flags, event_callback_list[event][i].handler_user_data);
|
||||
}
|
||||
|
||||
if (pWiFi == NULL)
|
||||
return;
|
||||
|
||||
EventId eventId;
|
||||
EventInfo eventInfo;
|
||||
String ssid;
|
||||
|
||||
memset(&eventInfo, 0, sizeof(EventInfo));
|
||||
|
||||
switch (event) {
|
||||
case WIFI_EVENT_CONNECT:
|
||||
eventId = ARDUINO_EVENT_WIFI_STA_START;
|
||||
break;
|
||||
|
||||
case WIFI_EVENT_DISCONNECT:
|
||||
case WIFI_EVENT_RECONNECTION_FAIL:
|
||||
eventId = ARDUINO_EVENT_WIFI_STA_DISCONNECTED;
|
||||
eventInfo.wifi_sta_disconnected.ssid_len = 0;
|
||||
eventInfo.wifi_sta_disconnected.reason = WIFI_REASON_UNSPECIFIED;
|
||||
if (event == WIFI_EVENT_RECONNECTION_FAIL)
|
||||
eventInfo.wifi_sta_disconnected.reason = WIFI_REASON_CONNECTION_FAIL;
|
||||
break;
|
||||
|
||||
case WIFI_EVENT_FOURWAY_HANDSHAKE_DONE:
|
||||
eventId = ARDUINO_EVENT_WIFI_STA_CONNECTED;
|
||||
ssid = pWiFi->SSID();
|
||||
eventInfo.wifi_sta_connected.ssid_len = ssid.length();
|
||||
eventInfo.wifi_sta_connected.channel = pWiFi->channel();
|
||||
eventInfo.wifi_sta_connected.authmode = pWiFi->getEncryption();
|
||||
memcpy(eventInfo.wifi_sta_connected.ssid, ssid.c_str(), eventInfo.wifi_sta_connected.ssid_len + 1);
|
||||
memcpy(eventInfo.wifi_sta_connected.bssid, pWiFi->BSSID(), 6);
|
||||
break;
|
||||
|
||||
case WIFI_EVENT_SCAN_DONE:
|
||||
eventId = ARDUINO_EVENT_WIFI_SCAN_DONE;
|
||||
eventInfo.wifi_scan_done.status = 0;
|
||||
eventInfo.wifi_scan_done.number = pWiFi->_netCount;
|
||||
eventInfo.wifi_scan_done.scan_id = 0;
|
||||
break;
|
||||
|
||||
case WIFI_EVENT_STA_ASSOC:
|
||||
// data(124) has MAC at 0x0A
|
||||
if (len != 124)
|
||||
return;
|
||||
eventId = ARDUINO_EVENT_WIFI_AP_STACONNECTED;
|
||||
memcpy(eventInfo.wifi_ap_staconnected.mac, (const char *)data[10], 6);
|
||||
break;
|
||||
|
||||
case WIFI_EVENT_STA_DISASSOC:
|
||||
// data(6) is MAC
|
||||
eventId = ARDUINO_EVENT_WIFI_AP_STADISCONNECTED;
|
||||
memcpy(eventInfo.wifi_ap_stadisconnected.mac, (const char *)data, 6);
|
||||
break;
|
||||
|
||||
// case WIFI_EVENT_SCAN_RESULT_REPORT:
|
||||
// case WIFI_EVENT_SEND_ACTION_DONE:
|
||||
// case WIFI_EVENT_RX_MGNT:
|
||||
// case WIFI_EVENT_STA_WPS_START:
|
||||
// case WIFI_EVENT_WPS_FINISH:
|
||||
// case WIFI_EVENT_EAPOL_START:
|
||||
// case WIFI_EVENT_EAPOL_RECVD:
|
||||
// case WIFI_EVENT_NO_NETWORK:
|
||||
// case WIFI_EVENT_BEACON_AFTER_DHCP:
|
||||
// case WIFI_EVENT_IP_CHANGED:
|
||||
// case WIFI_EVENT_ICV_ERROR:
|
||||
// case WIFI_EVENT_CHALLENGE_FAIL:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
postEvent(eventId, eventInfo);
|
||||
}
|
||||
@@ -9,20 +9,28 @@ int32_t WiFiClass::channel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
extern WiFiClass *pWiFi;
|
||||
extern void startWifiTask();
|
||||
|
||||
bool WiFiClass::mode(WiFiMode mode) {
|
||||
// store a pointer to WiFi for WiFiEvents.cpp
|
||||
pWiFi = this;
|
||||
|
||||
WiFiMode currentMode = getMode();
|
||||
LT_D_WG("Mode changing %u -> %u", currentMode, mode);
|
||||
if (mode == currentMode)
|
||||
return true;
|
||||
LT_HEAP_I();
|
||||
startWifiTask();
|
||||
|
||||
if (!currentMode && mode && !_initialized) {
|
||||
// initialize wifi first
|
||||
LT_I("Initializing LwIP");
|
||||
LwIP_Init();
|
||||
reset_wifi_struct();
|
||||
// wifi_manager_init(); // these are events!
|
||||
_initialized = true;
|
||||
}
|
||||
LT_HEAP_I();
|
||||
if (currentMode) {
|
||||
// stop wifi to change mode
|
||||
LT_D_WG("Stopping WiFi to change mode");
|
||||
@@ -37,6 +45,7 @@ bool WiFiClass::mode(WiFiMode mode) {
|
||||
LT_E("Error while changing mode(%u)", mode);
|
||||
return false;
|
||||
}
|
||||
LT_HEAP_I();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,6 @@ extern "C" {
|
||||
// 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
|
||||
@@ -20,13 +18,6 @@ extern "C" {
|
||||
#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
|
||||
|
||||
@@ -12,6 +12,8 @@ WiFiClass::begin(const char *ssid, const char *passphrase, int32_t channel, cons
|
||||
if (!enableSTA(true))
|
||||
return WL_CONNECT_FAILED;
|
||||
|
||||
LT_HEAP_I();
|
||||
|
||||
if (!ssid || *ssid == 0x00 || strlen(ssid) > 32) {
|
||||
LT_W("SSID not specified or too long");
|
||||
return WL_CONNECT_FAILED;
|
||||
@@ -47,18 +49,26 @@ WiFiClass::begin(const char *ssid, const char *passphrase, int32_t channel, cons
|
||||
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);
|
||||
|
||||
struct ip_addr d1, d2;
|
||||
d1.addr = dns1;
|
||||
d2.addr = dns2;
|
||||
if (dns1[0])
|
||||
dns_setserver(0, &d1);
|
||||
if (dns2[0])
|
||||
dns_setserver(0, &d2);
|
||||
|
||||
if (!localIP[0]) {
|
||||
LwIP_DHCP(0, DHCP_START);
|
||||
return true;
|
||||
}
|
||||
struct netif *ifs = NETIF_RTW_STA;
|
||||
struct ip_addr ipaddr, netmask, gw;
|
||||
ipaddr.addr = localIP;
|
||||
netmask.addr = subnet;
|
||||
gw.addr = gateway;
|
||||
netif_set_addr(ifs, &ipaddr, &netmask, &gw);
|
||||
LwIP_DHCP(0, DHCP_STOP);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -94,8 +104,21 @@ bool WiFiClass::reconnect(const uint8_t *bssid) {
|
||||
|
||||
if (ret == RTW_SUCCESS) {
|
||||
dhcpRet = LwIP_DHCP(0, DHCP_START);
|
||||
if (dhcpRet == DHCP_ADDRESS_ASSIGNED)
|
||||
if (dhcpRet == DHCP_ADDRESS_ASSIGNED) {
|
||||
LT_HEAP_I();
|
||||
EventInfo *eventInfo = (EventInfo *)zalloc(sizeof(EventInfo));
|
||||
eventInfo->got_ip.if_index = 0;
|
||||
eventInfo->got_ip.esp_netif = NULL;
|
||||
eventInfo->got_ip.ip_info.ip.addr = localIP();
|
||||
eventInfo->got_ip.ip_info.gw.addr = gatewayIP();
|
||||
eventInfo->got_ip.ip_info.netmask.addr = subnetMask();
|
||||
eventInfo->got_ip.ip_changed = true;
|
||||
// pass the event through the queue
|
||||
wifi_indication(WIFI_EVENT_CONNECT, (char *)eventInfo, ARDUINO_EVENT_WIFI_STA_GOT_IP, -2);
|
||||
// free memory as wifi_indication creates a copy
|
||||
free(eventInfo);
|
||||
return true;
|
||||
}
|
||||
LT_E("DHCP failed; dhcpRet=%d", dhcpRet);
|
||||
wifi_disconnect();
|
||||
return false;
|
||||
|
||||
192
arduino/realtek-ambz/libraries/Wire/Wire.cpp
Normal file
192
arduino/realtek-ambz/libraries/Wire/Wire.cpp
Normal file
@@ -0,0 +1,192 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-08. */
|
||||
|
||||
#include "Wire.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
extern "C" {
|
||||
#include <i2c_api.h>
|
||||
extern int i2c_write_timeout(i2c_t *obj, int address, char *data, int length, int stop, int timeout_ms);
|
||||
}
|
||||
|
||||
#ifdef PIN_WIRE0_SDA
|
||||
// Wire object associated to I2C0 interface.
|
||||
TwoWire Wire(PIN_WIRE0_SDA, PIN_WIRE0_SCL);
|
||||
#endif
|
||||
|
||||
#if defined(PIN_WIRE0_SDA) && defined(PIN_WIRE1_SDA)
|
||||
// Wire object associated to I2C1 interface.
|
||||
TwoWire Wire1(PIN_WIRE1_SDA, PIN_WIRE1_SCL);
|
||||
#endif
|
||||
|
||||
#if !defined(PIN_WIRE0_SDA) && defined(PIN_WIRE1_SDA)
|
||||
// Wire object associated to I2C1 interface. The board doesn't support I2C0.
|
||||
TwoWire Wire(PIN_WIRE1_SDA, PIN_WIRE1_SCL);
|
||||
#endif
|
||||
|
||||
TwoWire::TwoWire() {
|
||||
_timeout = 50;
|
||||
}
|
||||
|
||||
TwoWire::TwoWire(int8_t sda, int8_t scl) {
|
||||
_timeout = 50;
|
||||
_sda = sda;
|
||||
_scl = scl;
|
||||
}
|
||||
|
||||
TwoWire::~TwoWire() {}
|
||||
|
||||
bool TwoWire::setPins(int8_t sda, int8_t scl) {
|
||||
// return true when changing pins on initialized I2C
|
||||
if (_inSetPins)
|
||||
return true;
|
||||
// check if pins are provided
|
||||
if (sda == -1 || scl == -1)
|
||||
return false;
|
||||
// set private pins
|
||||
_sda = sda;
|
||||
_scl = scl;
|
||||
sda = g_APinDescription[sda].pinname;
|
||||
scl = g_APinDescription[scl].pinname;
|
||||
|
||||
// check if pins are valid
|
||||
if ((sda == PA_4 || sda == PA_19 || sda == PA_30) && (scl == PA_1 || scl == PA_22 || scl == PA_29)) {
|
||||
// I2C index 0
|
||||
_idx = 0;
|
||||
} else if ((sda == PA_27 || sda == PA_2 || sda == PA_23) && (scl == PA_28 || scl == PA_3 || scl == PA_18)) {
|
||||
// I2C index 1
|
||||
_idx = 1;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// restart I2C if changing pins
|
||||
// this will never be called from begin()
|
||||
if (_i2c) {
|
||||
_inSetPins = true;
|
||||
end();
|
||||
begin();
|
||||
_inSetPins = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwoWire::begin(int8_t sda, int8_t scl, uint32_t frequency) {
|
||||
if (_i2c)
|
||||
return true;
|
||||
// set private i2c pins
|
||||
if (!setPins(sda, scl))
|
||||
return false;
|
||||
// use default frequency
|
||||
if (!frequency)
|
||||
frequency = WIRE_DEFAULT_FREQ;
|
||||
|
||||
_i2c = new i2c_t;
|
||||
i2c_init(_i2c, (PinName)g_APinDescription[_sda].pinname, (PinName)g_APinDescription[_scl].pinname);
|
||||
i2c_frequency(_i2c, frequency);
|
||||
_freq = frequency;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwoWire::begin(uint8_t address, int8_t sda, int8_t scl, uint32_t frequency) {
|
||||
if (_i2c)
|
||||
return true;
|
||||
// init master bus first, return if failed (wrong pins)
|
||||
if (!begin(sda, scl, frequency))
|
||||
return false;
|
||||
|
||||
i2c_slave_address(_i2c, _idx, address, 0xff);
|
||||
i2c_slave_mode(_i2c, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwoWire::end() {
|
||||
i2c_reset(_i2c);
|
||||
delete _i2c;
|
||||
_i2c = NULL;
|
||||
}
|
||||
|
||||
bool TwoWire::setClock(uint32_t freq) {
|
||||
if (_i2c) {
|
||||
i2c_frequency(_i2c, freq);
|
||||
}
|
||||
_freq = freq;
|
||||
}
|
||||
|
||||
void TwoWire::beginTransmission(uint8_t address) {
|
||||
_txAddr = address;
|
||||
_txBuf.clear();
|
||||
}
|
||||
|
||||
// Errors:
|
||||
// 0 : Success
|
||||
// 1 : Data too long
|
||||
// 2 : NACK on transmit of address
|
||||
// 3 : NACK on transmit of data
|
||||
// 4 : Other error
|
||||
uint8_t TwoWire::endTransmission(bool stopBit) {
|
||||
if (!_i2c || !_txAddr)
|
||||
return 4;
|
||||
char *buf = (char *)malloc(_txBuf.available());
|
||||
uint8_t i = 0;
|
||||
while (_txBuf.available()) {
|
||||
buf[i++] = _txBuf.read_char();
|
||||
}
|
||||
int len = i2c_write_timeout(_i2c, _txAddr, buf, i, stopBit, _timeout);
|
||||
free(buf);
|
||||
_txAddr = 0;
|
||||
if (len == -1)
|
||||
return 2; // slave not available (if tx length == 0)
|
||||
if (len != i)
|
||||
return 3; // less bytes written
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t TwoWire::requestFrom(uint8_t address, size_t len, bool stopBit) {
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
if (len > SERIAL_BUFFER_SIZE)
|
||||
len = SERIAL_BUFFER_SIZE;
|
||||
|
||||
_rxBuf.clear();
|
||||
|
||||
char *buf = (char *)malloc(_txBuf.available());
|
||||
i2c_read(_i2c, address, buf, len, stopBit);
|
||||
uint8_t i = 0;
|
||||
while (len) {
|
||||
_rxBuf.store_char(buf[i++]);
|
||||
len--;
|
||||
}
|
||||
free(buf);
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t TwoWire::write(uint8_t data) {
|
||||
if (!_txAddr || _txBuf.isFull())
|
||||
return 0;
|
||||
_txBuf.store_char(data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t TwoWire::write(const uint8_t *data, size_t len) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (!write(data[i]))
|
||||
return i;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int TwoWire::available() {
|
||||
return _rxBuf.available();
|
||||
}
|
||||
|
||||
int TwoWire::read() {
|
||||
return _rxBuf.read_char();
|
||||
}
|
||||
|
||||
int TwoWire::peek() {
|
||||
return _rxBuf.peek();
|
||||
}
|
||||
|
||||
void TwoWire::flush() {}
|
||||
75
arduino/realtek-ambz/libraries/Wire/Wire.h
Normal file
75
arduino/realtek-ambz/libraries/Wire/Wire.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-08. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <api/RingBuffer.h>
|
||||
#include <api/Wire.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
// #include <i2c_api.h>
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(PIN_WIRE0_SDA) && defined(PIN_WIRE1_SDA)
|
||||
#define Wire1 Wire
|
||||
#endif
|
||||
|
||||
#define WIRE_HAS_END 1
|
||||
#define WIRE_DEFAULT_FREQ 100000
|
||||
|
||||
struct i2c_s;
|
||||
typedef struct i2c_s i2c_t;
|
||||
|
||||
using arduino::RingBuffer;
|
||||
|
||||
class TwoWire : public ITwoWire {
|
||||
private:
|
||||
i2c_t *_i2c = NULL;
|
||||
uint8_t _idx = 0;
|
||||
|
||||
RingBuffer _rxBuf;
|
||||
RingBuffer _txBuf;
|
||||
uint8_t _txAddr = 0;
|
||||
bool _inSetPins = false;
|
||||
|
||||
public:
|
||||
TwoWire();
|
||||
TwoWire(int8_t sda, int8_t scl);
|
||||
~TwoWire();
|
||||
|
||||
bool setPins(int8_t sda, int8_t scl);
|
||||
|
||||
bool begin(int8_t sda, int8_t scl, uint32_t frequency = 0);
|
||||
bool begin(uint8_t address, int8_t sda, int8_t scl, uint32_t frequency = 0);
|
||||
bool end();
|
||||
|
||||
bool setClock(uint32_t freq);
|
||||
|
||||
void beginTransmission(uint8_t address);
|
||||
uint8_t endTransmission(bool stopBit);
|
||||
|
||||
size_t requestFrom(uint8_t address, size_t len, bool stopBit);
|
||||
size_t write(uint8_t data);
|
||||
size_t write(const uint8_t *data, size_t len);
|
||||
|
||||
int available();
|
||||
int read();
|
||||
int peek();
|
||||
void flush();
|
||||
|
||||
using ITwoWire::begin;
|
||||
using ITwoWire::endTransmission;
|
||||
using ITwoWire::requestFrom;
|
||||
using ITwoWire::write;
|
||||
using Print::write;
|
||||
};
|
||||
|
||||
#ifdef PIN_WIRE0_SDA
|
||||
extern TwoWire Wire;
|
||||
#endif
|
||||
#ifdef PIN_WIRE1_SDA
|
||||
extern TwoWire Wire1;
|
||||
#endif
|
||||
31
arduino/realtek-ambz/port/flashdb/fal_flash_ambz_port.c
Normal file
31
arduino/realtek-ambz/port/flashdb/fal_flash_ambz_port.c
Normal file
@@ -0,0 +1,31 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-24. */
|
||||
|
||||
#include <fal.h>
|
||||
#include <flash_api.h>
|
||||
|
||||
#define FLASH_ERASE_MIN_SIZE (4 * 1024)
|
||||
|
||||
static int read(long offset, uint8_t *buf, size_t size) {
|
||||
return size * flash_stream_read(NULL, offset, size, buf);
|
||||
}
|
||||
|
||||
static int write(long offset, const uint8_t *buf, size_t size) {
|
||||
return size * flash_stream_write(NULL, offset, size, buf);
|
||||
}
|
||||
|
||||
static int erase(long offset, size_t size) {
|
||||
size = ((size - 1) / FLASH_ERASE_MIN_SIZE) + 1;
|
||||
for (uint16_t i = 0; i < size; i++) {
|
||||
flash_erase_sector(NULL, offset + i * FLASH_ERASE_MIN_SIZE);
|
||||
}
|
||||
return size * FLASH_ERASE_MIN_SIZE;
|
||||
}
|
||||
|
||||
const struct fal_flash_dev flash0 = {
|
||||
.name = FAL_FLASH_DEV_NAME,
|
||||
.addr = 0x0,
|
||||
.len = FLASH_LENGTH,
|
||||
.blk_size = FLASH_ERASE_MIN_SIZE,
|
||||
.ops = {NULL, read, write, erase},
|
||||
.write_gran = 1,
|
||||
};
|
||||
22
boards/_base/realtek-ambz-2mb.json
Normal file
22
boards/_base/realtek-ambz-2mb.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"build": {
|
||||
"ldscript_sdk": "rlx8711B-symbol-v02-img2_xip1_2M_cpp.ld",
|
||||
"ldscript_arduino": "rlx8711B-symbol-v02-img2_xip1_2M_cpp.ld",
|
||||
"amb_boot_all": "boot_all_77F7.bin"
|
||||
},
|
||||
"flash": {
|
||||
"boot_xip": "0x000000+0x4000",
|
||||
"boot_ram": "0x004000+0x4000",
|
||||
"system": "0x009000+0x1000",
|
||||
"calibration": "0x00A000+0x1000",
|
||||
"ota1": "0x00B000+0xC5000",
|
||||
"ota2": "0x0D0000+0xC5000",
|
||||
"kvs": "0x195000+0x6000",
|
||||
"userdata": "0x19B000+0x64000",
|
||||
"rdp": "0x1FF000+0x1000"
|
||||
},
|
||||
"upload": {
|
||||
"flash_size": 2097152,
|
||||
"maximum_size": 806912
|
||||
}
|
||||
}
|
||||
151
boards/_base/realtek-ambz-tuya3-alt.json
Normal file
151
boards/_base/realtek-ambz-tuya3-alt.json
Normal file
@@ -0,0 +1,151 @@
|
||||
{
|
||||
"pcb": {
|
||||
"templates": [
|
||||
"esp12s",
|
||||
"esp12s-shield",
|
||||
"tuya-16x24",
|
||||
"tuya-16x24-rf1"
|
||||
],
|
||||
"vars": {
|
||||
"MASK_PRESET": "mask_black",
|
||||
"TRACE_COLOR": "#505050",
|
||||
"SILK_COLOR": "white",
|
||||
"PINTYPE_VERT": "pin_vert_2mm_cast_nohole"
|
||||
},
|
||||
"pinout_hidden": "I2S,TRIG,WAKE,CTS,RTS,SD",
|
||||
"pinout": {
|
||||
"1": {
|
||||
"NC": null
|
||||
},
|
||||
"2": {
|
||||
"IC": 27,
|
||||
"IO": "I",
|
||||
"ADC": 2,
|
||||
"ARD": "A1"
|
||||
},
|
||||
"3": {
|
||||
"IC": 12,
|
||||
"IO": "I",
|
||||
"CTRL": "CEN"
|
||||
},
|
||||
"4": {
|
||||
"IC": 2,
|
||||
"GPIO": "PA29",
|
||||
"ARD": "D5",
|
||||
"UART": "2_RX",
|
||||
"I2C": "0_SCL",
|
||||
"PWM": 4
|
||||
},
|
||||
"5": {
|
||||
"IC": 13,
|
||||
"GPIO": "PA14",
|
||||
"ARD": "D2",
|
||||
"PWM": 0,
|
||||
"SWD": "CLK"
|
||||
},
|
||||
"6": {
|
||||
"IC": 14,
|
||||
"GPIO": "PA15",
|
||||
"ARD": "D3",
|
||||
"PWM": 1,
|
||||
"SWD": "DIO"
|
||||
},
|
||||
"7": {
|
||||
"IC": 31,
|
||||
"GPIO": "PA22",
|
||||
"ARD": "D0",
|
||||
"UART": "0_RTS",
|
||||
"SPI": [
|
||||
"0_MISO",
|
||||
"1_MISO"
|
||||
],
|
||||
"I2C": "0_SCL",
|
||||
"SD": "D0",
|
||||
"PWM": 5,
|
||||
"I2S": "0_WS",
|
||||
"WAKE": 2
|
||||
},
|
||||
"8": {
|
||||
"PWR": 3.3
|
||||
},
|
||||
"9": {
|
||||
"GND": null
|
||||
},
|
||||
"10": {
|
||||
"IC": 16,
|
||||
"GPIO": "PA00",
|
||||
"ARD": "D4",
|
||||
"PWM": 2
|
||||
},
|
||||
"11": {
|
||||
"IC": 1,
|
||||
"GPIO": "PA30",
|
||||
"ARD": "D6",
|
||||
"UART": "2_TX",
|
||||
"I2C": "0_SDA",
|
||||
"PWM": 4,
|
||||
"RTC": "OUT"
|
||||
},
|
||||
"12": {
|
||||
"IC": 30,
|
||||
"GPIO": "PA19",
|
||||
"ARD": [
|
||||
"D1",
|
||||
"A0"
|
||||
],
|
||||
"ADC": 1,
|
||||
"UART": "0_CTS",
|
||||
"SPI": [
|
||||
"0_CS",
|
||||
"1_CS"
|
||||
],
|
||||
"I2C": "0_SDA",
|
||||
"SD": "D3",
|
||||
"TMR": "5_TRIG",
|
||||
"I2S": "0_TX"
|
||||
},
|
||||
"13": {
|
||||
"IC": 28,
|
||||
"GPIO": "PA05",
|
||||
"ARD": "D7",
|
||||
"PWM": 4,
|
||||
"WAKE": 1
|
||||
},
|
||||
"14": {
|
||||
"IC": 17,
|
||||
"GPIO": "PA12",
|
||||
"ARD": "D8",
|
||||
"PWM": 3
|
||||
},
|
||||
"15": {
|
||||
"IC": 29,
|
||||
"GPIO": "PA18",
|
||||
"ARD": "D9",
|
||||
"UART": "0_RX",
|
||||
"SPI": [
|
||||
"0_SCK",
|
||||
"1_SCK"
|
||||
],
|
||||
"I2C": "1_SCL",
|
||||
"SD": "D2",
|
||||
"TMR": "4_TRIG",
|
||||
"I2S": "0_MCK",
|
||||
"WAKE": 0
|
||||
},
|
||||
"16": {
|
||||
"IC": 32,
|
||||
"GPIO": "PA23",
|
||||
"ARD": "D10",
|
||||
"UART": "0_TX",
|
||||
"SPI": [
|
||||
"0_MOSI",
|
||||
"1_MOSI"
|
||||
],
|
||||
"I2C": "1_SDA",
|
||||
"SD": "D1",
|
||||
"PWM": 0,
|
||||
"WAKE": 3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
151
boards/_base/realtek-ambz-tuya3.json
Normal file
151
boards/_base/realtek-ambz-tuya3.json
Normal file
@@ -0,0 +1,151 @@
|
||||
{
|
||||
"pcb": {
|
||||
"templates": [
|
||||
"esp12s",
|
||||
"esp12s-shield",
|
||||
"tuya-16x24",
|
||||
"tuya-16x24-rf1"
|
||||
],
|
||||
"vars": {
|
||||
"MASK_PRESET": "mask_black",
|
||||
"TRACE_COLOR": "#505050",
|
||||
"SILK_COLOR": "white",
|
||||
"PINTYPE_VERT": "pin_vert_2mm_cast_nohole"
|
||||
},
|
||||
"pinout_hidden": "I2S,TRIG,WAKE,CTS,RTS,SD",
|
||||
"pinout": {
|
||||
"1": {
|
||||
"NC": null
|
||||
},
|
||||
"2": {
|
||||
"IC": 31,
|
||||
"GPIO": "PA22",
|
||||
"ARD": "D0",
|
||||
"UART": "0_RTS",
|
||||
"SPI": [
|
||||
"0_MISO",
|
||||
"1_MISO"
|
||||
],
|
||||
"I2C": "0_SCL",
|
||||
"SD": "D0",
|
||||
"PWM": 5,
|
||||
"I2S": "0_WS",
|
||||
"WAKE": 2
|
||||
},
|
||||
"3": {
|
||||
"IC": 12,
|
||||
"IO": "I",
|
||||
"CTRL": "CEN"
|
||||
},
|
||||
"4": {
|
||||
"IC": 30,
|
||||
"GPIO": "PA19",
|
||||
"ARD": [
|
||||
"D1",
|
||||
"A0"
|
||||
],
|
||||
"ADC": 1,
|
||||
"UART": "0_CTS",
|
||||
"SPI": [
|
||||
"0_CS",
|
||||
"1_CS"
|
||||
],
|
||||
"I2C": "0_SDA",
|
||||
"SD": "D3",
|
||||
"TMR": "5_TRIG",
|
||||
"I2S": "0_TX"
|
||||
},
|
||||
"5": {
|
||||
"IC": 13,
|
||||
"GPIO": "PA14",
|
||||
"ARD": "D2",
|
||||
"PWM": 0,
|
||||
"SWD": "CLK"
|
||||
},
|
||||
"6": {
|
||||
"IC": 14,
|
||||
"GPIO": "PA15",
|
||||
"ARD": "D3",
|
||||
"PWM": 1,
|
||||
"SWD": "DIO"
|
||||
},
|
||||
"7": {
|
||||
"IC": 16,
|
||||
"GPIO": "PA00",
|
||||
"ARD": "D4",
|
||||
"PWM": 2
|
||||
},
|
||||
"8": {
|
||||
"PWR": 3.3
|
||||
},
|
||||
"9": {
|
||||
"GND": null
|
||||
},
|
||||
"10": {
|
||||
"IC": 27,
|
||||
"IO": "I",
|
||||
"ADC": 2,
|
||||
"ARD": "A1"
|
||||
},
|
||||
"11": {
|
||||
"IC": 2,
|
||||
"GPIO": "PA29",
|
||||
"ARD": "D5",
|
||||
"UART": "2_RX",
|
||||
"I2C": "0_SCL",
|
||||
"PWM": 4
|
||||
},
|
||||
"12": {
|
||||
"IC": 1,
|
||||
"GPIO": "PA30",
|
||||
"ARD": "D6",
|
||||
"UART": "2_TX",
|
||||
"I2C": "0_SDA",
|
||||
"PWM": 4,
|
||||
"RTC": "OUT"
|
||||
},
|
||||
"13": {
|
||||
"IC": 28,
|
||||
"GPIO": "PA05",
|
||||
"ARD": "D7",
|
||||
"PWM": 4,
|
||||
"WAKE": 1
|
||||
},
|
||||
"14": {
|
||||
"IC": 17,
|
||||
"GPIO": "PA12",
|
||||
"ARD": "D8",
|
||||
"PWM": 3
|
||||
},
|
||||
"15": {
|
||||
"IC": 29,
|
||||
"GPIO": "PA18",
|
||||
"ARD": "D9",
|
||||
"UART": "0_RX",
|
||||
"SPI": [
|
||||
"0_SCK",
|
||||
"1_SCK"
|
||||
],
|
||||
"I2C": "1_SCL",
|
||||
"SD": "D2",
|
||||
"TMR": "4_TRIG",
|
||||
"I2S": "0_MCK",
|
||||
"WAKE": 0
|
||||
},
|
||||
"16": {
|
||||
"IC": 32,
|
||||
"GPIO": "PA23",
|
||||
"ARD": "D10",
|
||||
"UART": "0_TX",
|
||||
"SPI": [
|
||||
"0_MOSI",
|
||||
"1_MOSI"
|
||||
],
|
||||
"I2C": "1_SDA",
|
||||
"SD": "D1",
|
||||
"PWM": 0,
|
||||
"WAKE": 3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
51
boards/_base/realtek-ambz.json
Normal file
51
boards/_base/realtek-ambz.json
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"build": {
|
||||
"family": "RTL8710B",
|
||||
"f_cpu": "125000000L",
|
||||
"amb_flash_addr": "0x08000000"
|
||||
},
|
||||
"connectivity": [
|
||||
"wifi"
|
||||
],
|
||||
"debug": {
|
||||
"protocol": "openocd",
|
||||
"protocols": [
|
||||
"openocd"
|
||||
],
|
||||
"openocd_config": "amebaz.cfg",
|
||||
"gdb_init": [
|
||||
"mem 0x8000000 0x8200000 ro"
|
||||
]
|
||||
},
|
||||
"frameworks": [
|
||||
"realtek-ambz-sdk",
|
||||
"realtek-ambz-arduino"
|
||||
],
|
||||
"upload": {
|
||||
"maximum_ram_size": 262144,
|
||||
"require_upload_port": true,
|
||||
"speed": 1500000,
|
||||
"protocol": "uart",
|
||||
"protocols": [
|
||||
"uart"
|
||||
]
|
||||
},
|
||||
"doc": {
|
||||
"params": {
|
||||
"manufacturer": "Realtek",
|
||||
"series": "AmebaZ",
|
||||
"voltage": "3.0V - 3.6V",
|
||||
"extra": {
|
||||
"Wi-Fi": "802.11 b/g/n"
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"Debugging": "../../docs/platform/realtek/debugging.md",
|
||||
"Flashing (Tuya manual)": "https://developer.tuya.com/en/docs/iot/burn-and-authorize-wr-series-modules?id=Ka789pjc581u8"
|
||||
},
|
||||
"extra": [
|
||||
"RDP is most likely not used in Tuya firmwares, as the System Data partition contains an incorrect offset 0xFF000 for RDP, which is in the middle of OTA2 image.",
|
||||
"Additionally, Tuya firmware uses an encrypted KV or file storage, which resides at the end of flash memory. This seems to overlap system RDP area."
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,53 +1,21 @@
|
||||
{
|
||||
"_base": [
|
||||
"realtek-ambz",
|
||||
"realtek-ambz-2mb",
|
||||
"realtek-ambz-tuya3"
|
||||
],
|
||||
"build": {
|
||||
"mcu": "rtl8710bn",
|
||||
"family": "rtl8710",
|
||||
"variant": "wr3",
|
||||
"ldscript_sdk": "rlx8711B-symbol-v02-img2_xip1_2M_cpp.ld",
|
||||
"ldscript_arduino": "rlx8711B-symbol-v02-img2_xip1_2M_cpp.ld",
|
||||
"f_cpu": "125000000L",
|
||||
"amb_flash_addr": "0x08000000",
|
||||
"amb_boot_all": "boot_all_77F7.bin"
|
||||
},
|
||||
"connectivity": [
|
||||
"wifi"
|
||||
],
|
||||
"debug": {
|
||||
"protocol": "openocd",
|
||||
"protocols": [
|
||||
"openocd"
|
||||
],
|
||||
"openocd_config": "amebaz.cfg",
|
||||
"gdb_init": [
|
||||
"mem 0x8000000 0x8200000 ro"
|
||||
]
|
||||
},
|
||||
"flash": {
|
||||
"boot_xip": "0x000000+0x4000",
|
||||
"boot_ram": "0x004000+0x4000",
|
||||
"system": "0x009000+0x1000",
|
||||
"calibration": "0x00A000+0x1000",
|
||||
"ota1": "0x00B000+0xC5000",
|
||||
"ota2": "0x0D0000+0xC5000",
|
||||
"userdata": "0x195000+0x6A000",
|
||||
"rdp": "0x1FF000+0x1000"
|
||||
},
|
||||
"frameworks": [
|
||||
"realtek-ambz-sdk",
|
||||
"realtek-ambz-arduino"
|
||||
],
|
||||
"upload": {
|
||||
"flash_size": "2MB",
|
||||
"maximum_size": 806912,
|
||||
"maximum_ram_size": 262144,
|
||||
"require_upload_port": true,
|
||||
"speed": 1500000,
|
||||
"protocol": "uart",
|
||||
"protocols": [
|
||||
"uart"
|
||||
]
|
||||
"variant": "wr3"
|
||||
},
|
||||
"name": "WR3 Wi-Fi Module",
|
||||
"url": "https://developer.tuya.com/en/docs/iot/wr3-module-datasheet?id=K9g3ainzbj9z1",
|
||||
"vendor": "Tuya Inc."
|
||||
"vendor": "Tuya Inc.",
|
||||
"pcb": {
|
||||
"symbol": "WR3",
|
||||
"vars": {
|
||||
"MASK_PRESET": "mask_black",
|
||||
"TRACE_COLOR": "#505050"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +1,45 @@
|
||||
# WR3 Wi-Fi Module
|
||||
|
||||
[Product page](https://developer.tuya.com/en/docs/iot/wifiwr1module?id=K9605tc0k90t3)
|
||||
*by Tuya Inc.*
|
||||
|
||||
[Product page](https://developer.tuya.com/en/docs/iot/wr3-module-datasheet?id=K9g3ainzbj9z1)
|
||||
|
||||
- [Debugging](../../docs/platform/realtek/debugging.md)
|
||||
- [Flashing (Tuya manual)](https://developer.tuya.com/en/docs/iot/burn-and-authorize-wr-series-modules?id=Ka789pjc581u8)
|
||||
|
||||
Parameter | Value
|
||||
-------------|-------------------------
|
||||
-------------|----------------------------------
|
||||
MCU | RTL8710BN
|
||||
Manufacturer | Realtek
|
||||
Series | AmebaZ
|
||||
Max. clock | 125 MHz
|
||||
Frequency | 125 MHz
|
||||
Flash size | 2 MiB
|
||||
RAM size | 256 KiB
|
||||
Voltage | 3.0V - 3.6V
|
||||
I/O | 7x GPIO, 2x UART, 1x ADC
|
||||
I/O | 11x GPIO, 6x PWM, 2x UART, 2x ADC
|
||||
Wi-Fi | 802.11 b/g/n
|
||||
|
||||
## Pinout
|
||||
|
||||

|
||||

|
||||
|
||||
## Arduino core pin map
|
||||
## Arduino Core pin mapping
|
||||
|
||||
No. | Pin | Alt. function | PWM
|
||||
----|-------|---------------|-----
|
||||
D0 | PA_22 | | PWM5
|
||||
D1 | PA_19 | |
|
||||
D2 | PA_14 | SWCLK | PWM0
|
||||
D3 | PA_15 | SWDAT | PWM1
|
||||
D4 | PA_0 | | PWM2
|
||||
D5 | PA_20 | |
|
||||
D6 | PA_29 | UART_Log_RXD | PWM4
|
||||
D7 | PA_30 | UART_Log_TXD | PWM3
|
||||
D8 | PA_5 | | PWM4
|
||||
D9 | PA_12 | | PWM3
|
||||
D10 | PA_18 | UART0_RXD |
|
||||
D11 | PA_23 | UART0_TXD | PWM0
|
||||
A0 | PA_19 | |
|
||||
A1 | - | |
|
||||
A2 | PA_20 | |
|
||||
No. | Pin | UART | I²C | SPI | PWM | Other
|
||||
----|------------|-----------|----------|----------------------|------|------
|
||||
D0 | PA22 | UART0_RTS | I2C0_SCL | SPI0_MISO, SPI1_MISO | PWM5 |
|
||||
D1 | PA19 | UART0_CTS | I2C0_SDA | SPI0_CS, SPI1_CS | |
|
||||
D2 | PA14 | | | | PWM0 | SWCLK
|
||||
D3 | PA15 | | | | PWM1 | SWDIO
|
||||
D4 | PA00 | | | | PWM2 |
|
||||
D5 | PA29 | UART2_RX | I2C0_SCL | | PWM4 |
|
||||
D6 | PA30 | UART2_TX | I2C0_SDA | | PWM4 |
|
||||
D7 | PA05 | | | | PWM4 |
|
||||
D8 | PA12 | | | | PWM3 |
|
||||
D9 | PA18 | UART0_RX | I2C1_SCL | SPI0_SCK, SPI1_SCK | |
|
||||
D10 | PA23 | UART0_TX | I2C1_SDA | SPI0_MOSI, SPI1_MOSI | PWM0 |
|
||||
A0 | PA19, ADC1 | | | | |
|
||||
A1 | ADC2 | | | | |
|
||||
|
||||
## Flash memory map
|
||||
|
||||
@@ -46,19 +47,19 @@ Flash size: 2 MiB / 2,097,152 B / 0x200000
|
||||
|
||||
Hex values are in bytes.
|
||||
|
||||
Name | Start | Length | End
|
||||
------------|----------|-------------------|---------
|
||||
Boot XIP | 0x000000 | 16 KiB / 0x4000 | 0x004000
|
||||
Boot RAM | 0x004000 | 16 KiB / 0x4000 | 0x008000
|
||||
(reserved) | 0x008000 | 4 KiB / 0x1000 | 0x009000
|
||||
System Data | 0x009000 | 4 KiB / 0x1000 | 0x00A000
|
||||
Calibration | 0x00A000 | 4 KiB / 0x1000 | 0x00B000
|
||||
OTA1 Image | 0x00B000 | 788 KiB / 0xC5000 | 0x0D0000
|
||||
OTA2 Image | 0x0D0000 | 788 KiB / 0xC5000 | 0x195000
|
||||
User Data | 0x195000 | 424 KiB / 0x6A000 | 0x1FF000
|
||||
RDP | 0x1FF000 | 4 KiB / 0x1000 | 0x200000
|
||||
Name | Start | Length | End
|
||||
----------------|----------|-------------------|---------
|
||||
Boot XIP | 0x000000 | 16 KiB / 0x4000 | 0x004000
|
||||
Boot RAM | 0x004000 | 16 KiB / 0x4000 | 0x008000
|
||||
(reserved) | 0x008000 | 4 KiB / 0x1000 | 0x009000
|
||||
System Data | 0x009000 | 4 KiB / 0x1000 | 0x00A000
|
||||
Calibration | 0x00A000 | 4 KiB / 0x1000 | 0x00B000
|
||||
OTA1 Image | 0x00B000 | 788 KiB / 0xC5000 | 0x0D0000
|
||||
OTA2 Image | 0x0D0000 | 788 KiB / 0xC5000 | 0x195000
|
||||
Key-Value Store | 0x195000 | 24 KiB / 0x6000 | 0x19B000
|
||||
User Data | 0x19B000 | 400 KiB / 0x64000 | 0x1FF000
|
||||
RDP | 0x1FF000 | 4 KiB / 0x1000 | 0x200000
|
||||
|
||||
RDP is most likely not used in Tuya firmwares, as the System Data partition contains
|
||||
an incorrect offset 0xFF000 for RDP, which is in the middle of OTA2 image.
|
||||
RDP is most likely not used in Tuya firmwares, as the System Data partition contains an incorrect offset 0xFF000 for RDP, which is in the middle of OTA2 image.
|
||||
|
||||
Additionally, Tuya firmware uses an encrypted KV or file storage, which resides at the end of flash memory. This seems to overlap system RDP area.
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 29 KiB |
309
boards/wr3/pinout_wr3.svg
Normal file
309
boards/wr3/pinout_wr3.svg
Normal file
@@ -0,0 +1,309 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink" baseProfile="full" height="500" version="1.1" viewBox="0,0,85.33333333333333,41.666666666666664" width="1024">
|
||||
<defs/>
|
||||
<rect fill="white" height="41.666666666666664" stroke="black" stroke-width="0.1" width="85.33333333333333" x="0" y="0"/>
|
||||
<linearGradient gradientUnits="objectBoundingBox" id="id1" x1="1.0" x2="0.0" y1="0.0" y2="1.0">
|
||||
<stop offset="0%" stop-color="#4d4d4d"/>
|
||||
<stop offset="100%" stop-color="#0f0f0f"/>
|
||||
</linearGradient>
|
||||
<rect fill="url(#id1) none" height="23.9" stroke="#b5a739" stroke-width="0.1" width="15.9" x="34.36666666666666" y="8.883333333333333"/>
|
||||
<rect fill="#e5b472" height="1.2" id="esp12s.front.left.pin1.trace" width="0.7" x="34.31666666666666" y="16.583333333333332"/>
|
||||
<circle cx="34.31666666666666" cy="17.18333333333333" fill="#fff" id="esp12s.front.left.pin1.cast" r="0.35"/>
|
||||
<rect fill="#e5b472" height="1.2" id="esp12s.front.left.pin2.trace" width="0.7" x="34.31666666666666" y="18.583333333333332"/>
|
||||
<circle cx="34.31666666666666" cy="19.18333333333333" fill="#fff" id="esp12s.front.left.pin2.cast" r="0.35"/>
|
||||
<rect fill="#e5b472" height="1.2" id="esp12s.front.left.pin3.trace" width="0.7" x="34.31666666666666" y="20.583333333333332"/>
|
||||
<circle cx="34.31666666666666" cy="21.18333333333333" fill="#fff" id="esp12s.front.left.pin3.cast" r="0.35"/>
|
||||
<rect fill="#e5b472" height="1.2" id="esp12s.front.left.pin4.trace" width="0.7" x="34.31666666666666" y="22.583333333333332"/>
|
||||
<circle cx="34.31666666666666" cy="23.18333333333333" fill="#fff" id="esp12s.front.left.pin4.cast" r="0.35"/>
|
||||
<rect fill="#e5b472" height="1.2" id="esp12s.front.left.pin5.trace" width="0.7" x="34.31666666666666" y="24.583333333333332"/>
|
||||
<circle cx="34.31666666666666" cy="25.183333333333334" fill="#fff" id="esp12s.front.left.pin5.cast" r="0.35"/>
|
||||
<rect fill="#e5b472" height="1.2" id="esp12s.front.left.pin6.trace" width="0.7" x="34.31666666666666" y="26.583333333333332"/>
|
||||
<circle cx="34.31666666666666" cy="27.183333333333334" fill="#fff" id="esp12s.front.left.pin6.cast" r="0.35"/>
|
||||
<rect fill="#e5b472" height="1.2" id="esp12s.front.left.pin7.trace" width="0.7" x="34.31666666666666" y="28.583333333333332"/>
|
||||
<circle cx="34.31666666666666" cy="29.183333333333334" fill="#fff" id="esp12s.front.left.pin7.cast" r="0.35"/>
|
||||
<rect fill="#e5b472" height="1.2" id="esp12s.front.left.pin8.trace" width="0.7" x="34.31666666666666" y="30.583333333333332"/>
|
||||
<circle cx="34.31666666666666" cy="31.183333333333334" fill="#fff" id="esp12s.front.left.pin8.cast" r="0.35"/>
|
||||
<rect fill="#e5b472" height="1.2" id="esp12s.front.right.pin1.trace" width="0.7" x="49.61666666666666" y="16.583333333333332"/>
|
||||
<circle cx="50.31666666666666" cy="17.18333333333333" fill="#fff" id="esp12s.front.right.pin1.cast" r="0.35"/>
|
||||
<rect fill="#e5b472" height="1.2" id="esp12s.front.right.pin2.trace" width="0.7" x="49.61666666666666" y="18.583333333333332"/>
|
||||
<circle cx="50.31666666666666" cy="19.18333333333333" fill="#fff" id="esp12s.front.right.pin2.cast" r="0.35"/>
|
||||
<rect fill="#e5b472" height="1.2" id="esp12s.front.right.pin3.trace" width="0.7" x="49.61666666666666" y="20.583333333333332"/>
|
||||
<circle cx="50.31666666666666" cy="21.18333333333333" fill="#fff" id="esp12s.front.right.pin3.cast" r="0.35"/>
|
||||
<rect fill="#e5b472" height="1.2" id="esp12s.front.right.pin4.trace" width="0.7" x="49.61666666666666" y="22.583333333333332"/>
|
||||
<circle cx="50.31666666666666" cy="23.18333333333333" fill="#fff" id="esp12s.front.right.pin4.cast" r="0.35"/>
|
||||
<rect fill="#e5b472" height="1.2" id="esp12s.front.right.pin5.trace" width="0.7" x="49.61666666666666" y="24.583333333333332"/>
|
||||
<circle cx="50.31666666666666" cy="25.183333333333334" fill="#fff" id="esp12s.front.right.pin5.cast" r="0.35"/>
|
||||
<rect fill="#e5b472" height="1.2" id="esp12s.front.right.pin6.trace" width="0.7" x="49.61666666666666" y="26.583333333333332"/>
|
||||
<circle cx="50.31666666666666" cy="27.183333333333334" fill="#fff" id="esp12s.front.right.pin6.cast" r="0.35"/>
|
||||
<rect fill="#e5b472" height="1.2" id="esp12s.front.right.pin7.trace" width="0.7" x="49.61666666666666" y="28.583333333333332"/>
|
||||
<circle cx="50.31666666666666" cy="29.183333333333334" fill="#fff" id="esp12s.front.right.pin7.cast" r="0.35"/>
|
||||
<rect fill="#e5b472" height="1.2" id="esp12s.front.right.pin8.trace" width="0.7" x="49.61666666666666" y="30.583333333333332"/>
|
||||
<circle cx="50.31666666666666" cy="31.183333333333334" fill="#fff" id="esp12s.front.right.pin8.cast" r="0.35"/>
|
||||
<linearGradient gradientUnits="objectBoundingBox" id="id2" x1="1.0" x2="0.0" y1="0.0" y2="1.0">
|
||||
<stop offset="0%" stop-color="whitesmoke"/>
|
||||
<stop offset="100%" stop-color="#999"/>
|
||||
</linearGradient>
|
||||
<rect fill="url(#id2) none" height="16.8" rx="0.5" ry="0.5" width="13.6" x="35.516666666666666" y="15.783333333333331"/>
|
||||
<rect fill="#fff" height="0.15" width="15.0" x="34.81666666666666" y="15.033333333333331"/>
|
||||
<text fill="#fff" font-family="Consolas" font-size="1.0" x="41.31666666666666" y="14.333333333333332">WR3</text>
|
||||
<rect fill="#505050" height="5.2" width="0.5" x="35.416666666666664" y="9.633333333333333"/>
|
||||
<rect fill="#505050" height="0.5" width="4.6" x="35.416666666666664" y="9.633333333333333"/>
|
||||
<rect fill="#505050" height="5.2" width="0.5" x="37.61666666666666" y="9.633333333333333"/>
|
||||
<rect fill="#505050" height="3.0" width="0.5" x="39.516666666666666" y="9.633333333333333"/>
|
||||
<rect fill="#505050" height="0.5" width="3.0" x="39.516666666666666" y="12.133333333333333"/>
|
||||
<rect fill="#505050" height="3.0" width="0.5" x="42.016666666666666" y="9.633333333333333"/>
|
||||
<rect fill="#505050" height="0.5" width="2.7" x="42.016666666666666" y="9.633333333333333"/>
|
||||
<rect fill="#505050" height="3.0" width="0.5" x="44.21666666666666" y="9.633333333333333"/>
|
||||
<rect fill="#505050" height="0.5" width="3.0" x="44.21666666666666" y="12.133333333333333"/>
|
||||
<rect fill="#505050" height="3.0" width="0.5" x="46.71666666666666" y="9.633333333333333"/>
|
||||
<rect fill="#505050" height="0.5" width="2.5" x="46.71666666666666" y="9.633333333333333"/>
|
||||
<rect fill="#505050" height="4.4" width="0.5" x="48.71666666666666" y="9.633333333333333"/>
|
||||
<rect fill="#4e4c4c" height="0.2" width="2.6" x="31.21666666666666" y="17.08333333333333"/>
|
||||
<rect fill="#4e4c4c" height="0.2" width="2.6" x="31.21666666666666" y="19.08333333333333"/>
|
||||
<g transform="translate(27.431026020611558,18.38333333333333)">
|
||||
<rect fill="#800000" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="28.91666666666666" y="19.18333333333333">PA22</text>
|
||||
<g transform="translate(24.43102602061156,18.38333333333333)">
|
||||
<rect fill="#99188d" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="2.8" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="25.616666666666664" y="19.18333333333333">D0</text>
|
||||
<g transform="translate(20.83102602061156,18.38333333333333)">
|
||||
<rect fill="#f95" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="22.316666666666663" y="19.18333333333333">SCL0</text>
|
||||
<g transform="translate(17.231026020611562,18.38333333333333)">
|
||||
<rect fill="#e9ba33" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="18.716666666666665" y="19.18333333333333">MISO0</text>
|
||||
<g transform="translate(13.631026020611563,18.38333333333333)">
|
||||
<rect fill="#e9ba33" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="15.116666666666664" y="19.18333333333333">MISO1</text>
|
||||
<g transform="translate(10.031026020611561,18.38333333333333)">
|
||||
<rect fill="#afa35e" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="11.516666666666662" y="19.18333333333333">PWM5</text>
|
||||
<rect fill="#4e4c4c" height="0.2" width="2.6" x="31.21666666666666" y="21.08333333333333"/>
|
||||
<g transform="translate(27.431026020611558,20.38333333333333)">
|
||||
<rect fill="#ed602e" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="28.91666666666666" y="21.18333333333333">CEN</text>
|
||||
<rect fill="#4e4c4c" height="0.2" width="2.6" x="31.21666666666666" y="23.08333333333333"/>
|
||||
<g transform="translate(27.431026020611558,22.38333333333333)">
|
||||
<rect fill="#800000" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="28.91666666666666" y="23.18333333333333">PA19</text>
|
||||
<g transform="translate(23.83102602061156,22.38333333333333)">
|
||||
<rect fill="#8ad039" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="25.316666666666663" y="23.18333333333333">ADC1</text>
|
||||
<g transform="translate(20.83102602061156,22.38333333333333)">
|
||||
<rect fill="#99188d" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="2.8" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="22.016666666666662" y="23.18333333333333">D1</text>
|
||||
<g transform="translate(17.83102602061156,22.38333333333333)">
|
||||
<rect fill="#16a352" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="2.8" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="19.016666666666662" y="23.18333333333333">A0</text>
|
||||
<g transform="translate(14.23102602061156,22.38333333333333)">
|
||||
<rect fill="#f95" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="15.716666666666661" y="23.18333333333333">SDA0</text>
|
||||
<g transform="translate(10.631026020611559,22.38333333333333)">
|
||||
<rect fill="#e9ba33" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="12.11666666666666" y="23.18333333333333">CS0</text>
|
||||
<g transform="translate(7.031026020611558,22.38333333333333)">
|
||||
<rect fill="#e9ba33" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="8.516666666666659" y="23.18333333333333">CS1</text>
|
||||
<rect fill="#4e4c4c" height="0.2" width="2.6" x="31.21666666666666" y="25.083333333333332"/>
|
||||
<g transform="translate(27.431026020611558,24.383333333333333)">
|
||||
<rect fill="#800000" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="28.91666666666666" y="25.183333333333334">PA14</text>
|
||||
<g transform="translate(24.43102602061156,24.383333333333333)">
|
||||
<rect fill="#99188d" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="2.8" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="25.616666666666664" y="25.183333333333334">D2</text>
|
||||
<g transform="translate(20.83102602061156,24.383333333333333)">
|
||||
<rect fill="#afa35e" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="22.316666666666663" y="25.183333333333334">PWM0</text>
|
||||
<g transform="translate(17.231026020611562,24.383333333333333)">
|
||||
<rect fill="#ffe680" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="18.716666666666665" y="25.183333333333334">SWCLK</text>
|
||||
<rect fill="#4e4c4c" height="0.2" width="2.6" x="31.21666666666666" y="27.083333333333332"/>
|
||||
<g transform="translate(27.431026020611558,26.383333333333333)">
|
||||
<rect fill="#800000" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="28.91666666666666" y="27.183333333333334">PA15</text>
|
||||
<g transform="translate(24.43102602061156,26.383333333333333)">
|
||||
<rect fill="#99188d" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="2.8" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="25.616666666666664" y="27.183333333333334">D3</text>
|
||||
<g transform="translate(20.83102602061156,26.383333333333333)">
|
||||
<rect fill="#afa35e" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="22.316666666666663" y="27.183333333333334">PWM1</text>
|
||||
<g transform="translate(17.231026020611562,26.383333333333333)">
|
||||
<rect fill="#ffe680" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="18.716666666666665" y="27.183333333333334">SWDIO</text>
|
||||
<rect fill="#4e4c4c" height="0.2" width="2.6" x="31.21666666666666" y="29.083333333333332"/>
|
||||
<g transform="translate(27.431026020611558,28.383333333333333)">
|
||||
<rect fill="#800000" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="28.91666666666666" y="29.183333333333334">PA00</text>
|
||||
<g transform="translate(24.43102602061156,28.383333333333333)">
|
||||
<rect fill="#99188d" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="2.8" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="25.616666666666664" y="29.183333333333334">D4</text>
|
||||
<g transform="translate(20.83102602061156,28.383333333333333)">
|
||||
<rect fill="#afa35e" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="22.316666666666663" y="29.183333333333334">PWM2</text>
|
||||
<rect fill="#4e4c4c" height="0.2" width="2.6" x="31.21666666666666" y="31.083333333333332"/>
|
||||
<g transform="translate(27.431026020611558,30.383333333333333)">
|
||||
<rect fill="#cd3c24" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="28.91666666666666" y="31.183333333333334">3V3</text>
|
||||
<rect fill="#4e4c4c" height="0.2" width="2.6" x="50.81666666666666" y="31.083333333333332"/>
|
||||
<g transform="translate(54.231026020611566,30.383333333333333)">
|
||||
<rect fill="#000" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="55.71666666666667" y="31.183333333333334">GND</text>
|
||||
<rect fill="#4e4c4c" height="0.2" width="2.6" x="50.81666666666666" y="29.083333333333332"/>
|
||||
<g transform="translate(54.231026020611566,28.383333333333333)">
|
||||
<rect fill="#8ad039" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="55.71666666666667" y="29.183333333333334">ADC2</text>
|
||||
<g transform="translate(57.83102602061157,28.383333333333333)">
|
||||
<rect fill="#16a352" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="2.8" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="59.016666666666666" y="29.183333333333334">A1</text>
|
||||
<rect fill="#4e4c4c" height="0.2" width="2.6" x="50.81666666666666" y="27.083333333333332"/>
|
||||
<g transform="translate(54.231026020611566,26.383333333333333)">
|
||||
<rect fill="#800000" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="55.71666666666667" y="27.183333333333334">PA29</text>
|
||||
<g transform="translate(57.83102602061157,26.383333333333333)">
|
||||
<rect fill="#99188d" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="2.8" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="59.016666666666666" y="27.183333333333334">D5</text>
|
||||
<g transform="translate(60.83102602061157,26.383333333333333)">
|
||||
<rect fill="#dcd4ee" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="62.31666666666667" y="27.183333333333334">RX2</text>
|
||||
<g transform="translate(64.43102602061157,26.383333333333333)">
|
||||
<rect fill="#f95" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="65.91666666666667" y="27.183333333333334">SCL0</text>
|
||||
<g transform="translate(68.03102602061156,26.383333333333333)">
|
||||
<rect fill="#afa35e" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="69.51666666666667" y="27.183333333333334">PWM4</text>
|
||||
<rect fill="#4e4c4c" height="0.2" width="2.6" x="50.81666666666666" y="25.083333333333332"/>
|
||||
<g transform="translate(54.231026020611566,24.383333333333333)">
|
||||
<rect fill="#800000" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="55.71666666666667" y="25.183333333333334">PA30</text>
|
||||
<g transform="translate(57.83102602061157,24.383333333333333)">
|
||||
<rect fill="#99188d" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="2.8" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="59.016666666666666" y="25.183333333333334">D6</text>
|
||||
<g transform="translate(60.83102602061157,24.383333333333333)">
|
||||
<rect fill="#dcd4ee" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="62.31666666666667" y="25.183333333333334">TX2</text>
|
||||
<g transform="translate(64.43102602061157,24.383333333333333)">
|
||||
<rect fill="#f95" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="65.91666666666667" y="25.183333333333334">SDA0</text>
|
||||
<g transform="translate(68.03102602061156,24.383333333333333)">
|
||||
<rect fill="#afa35e" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="69.51666666666667" y="25.183333333333334">PWM4</text>
|
||||
<rect fill="#4e4c4c" height="0.2" width="2.6" x="50.81666666666666" y="23.08333333333333"/>
|
||||
<g transform="translate(54.231026020611566,22.38333333333333)">
|
||||
<rect fill="#800000" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="55.71666666666667" y="23.18333333333333">PA05</text>
|
||||
<g transform="translate(57.83102602061157,22.38333333333333)">
|
||||
<rect fill="#99188d" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="2.8" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="59.016666666666666" y="23.18333333333333">D7</text>
|
||||
<g transform="translate(60.83102602061157,22.38333333333333)">
|
||||
<rect fill="#afa35e" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="62.31666666666667" y="23.18333333333333">PWM4</text>
|
||||
<rect fill="#4e4c4c" height="0.2" width="2.6" x="50.81666666666666" y="21.08333333333333"/>
|
||||
<g transform="translate(54.231026020611566,20.38333333333333)">
|
||||
<rect fill="#800000" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="55.71666666666667" y="21.18333333333333">PA12</text>
|
||||
<g transform="translate(57.83102602061157,20.38333333333333)">
|
||||
<rect fill="#99188d" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="2.8" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="59.016666666666666" y="21.18333333333333">D8</text>
|
||||
<g transform="translate(60.83102602061157,20.38333333333333)">
|
||||
<rect fill="#afa35e" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="62.31666666666667" y="21.18333333333333">PWM3</text>
|
||||
<rect fill="#4e4c4c" height="0.2" width="2.6" x="50.81666666666666" y="19.08333333333333"/>
|
||||
<g transform="translate(54.231026020611566,18.38333333333333)">
|
||||
<rect fill="#800000" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="55.71666666666667" y="19.18333333333333">PA18</text>
|
||||
<g transform="translate(57.83102602061157,18.38333333333333)">
|
||||
<rect fill="#99188d" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="2.8" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="59.016666666666666" y="19.18333333333333">D9</text>
|
||||
<g transform="translate(60.83102602061157,18.38333333333333)">
|
||||
<rect fill="#dcd4ee" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="62.31666666666667" y="19.18333333333333">RX0</text>
|
||||
<g transform="translate(64.43102602061157,18.38333333333333)">
|
||||
<rect fill="#f95" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="65.91666666666667" y="19.18333333333333">SCL1</text>
|
||||
<g transform="translate(68.03102602061156,18.38333333333333)">
|
||||
<rect fill="#e9ba33" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="69.51666666666667" y="19.18333333333333">SCK0</text>
|
||||
<g transform="translate(71.63102602061156,18.38333333333333)">
|
||||
<rect fill="#e9ba33" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="73.11666666666666" y="19.18333333333333">SCK1</text>
|
||||
<rect fill="#4e4c4c" height="0.2" width="2.6" x="50.81666666666666" y="17.08333333333333"/>
|
||||
<g transform="translate(54.231026020611566,16.38333333333333)">
|
||||
<rect fill="#800000" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="55.71666666666667" y="17.18333333333333">PA23</text>
|
||||
<g transform="translate(57.83102602061157,16.38333333333333)">
|
||||
<rect fill="#99188d" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="2.8" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="white" font-family="Consolas" font-size="1.2" text-anchor="middle" x="59.016666666666666" y="17.18333333333333">D10</text>
|
||||
<g transform="translate(60.83102602061157,16.38333333333333)">
|
||||
<rect fill="#dcd4ee" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="62.31666666666667" y="17.18333333333333">TX0</text>
|
||||
<g transform="translate(64.43102602061157,16.38333333333333)">
|
||||
<rect fill="#f95" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="65.91666666666667" y="17.18333333333333">SDA1</text>
|
||||
<g transform="translate(68.03102602061156,16.38333333333333)">
|
||||
<rect fill="#e9ba33" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="69.51666666666667" y="17.18333333333333">MOSI0</text>
|
||||
<g transform="translate(71.63102602061156,16.38333333333333)">
|
||||
<rect fill="#e9ba33" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="73.11666666666666" y="17.18333333333333">MOSI1</text>
|
||||
<g transform="translate(75.23102602061157,16.38333333333333)">
|
||||
<rect fill="#afa35e" height="1.6" rx="0.3" ry="0.3" transform="skewX(-15)" width="3.4" x="0" y="0"/>
|
||||
</g>
|
||||
<text dominant-baseline="central" fill="#423F42" font-family="Consolas" font-size="1.2" text-anchor="middle" x="76.71666666666667" y="17.18333333333333">PWM0</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 28 KiB |
@@ -19,8 +19,6 @@ PinDescription g_APinDescription[PINS_COUNT] = {
|
||||
{PA_15, NOT_INITIAL, PIO_GPIO | PIO_GPIO_IRQ | PIO_PWM, NOT_INITIAL},
|
||||
// D4: PWM2, ext_32K
|
||||
{PA_0, NOT_INITIAL, PIO_GPIO | PIO_GPIO_IRQ | PIO_PWM, NOT_INITIAL},
|
||||
// D5: SD_CMD, I2S_SD_RX, ADC3
|
||||
{PA_20, NOT_INITIAL, PIO_GPIO | PIO_GPIO_IRQ, NOT_INITIAL},
|
||||
// D6: UART2_log_RXD, I2C0_SCL, PWM4
|
||||
{PA_29, NOT_INITIAL, PIO_GPIO | PIO_GPIO_IRQ | PIO_PWM, NOT_INITIAL},
|
||||
// D7: UART2_log_TXD, I2C0_SDA, PWM3, RTC_OUT
|
||||
@@ -33,6 +31,8 @@ PinDescription g_APinDescription[PINS_COUNT] = {
|
||||
{PA_18, NOT_INITIAL, PIO_GPIO | PIO_GPIO_IRQ, NOT_INITIAL},
|
||||
// D11: UART0_TXD, SPI1_MOSI, SPI0_MOSI, I2C1_SDA, SD_D1, PWM0, WAKEUP_3
|
||||
{PA_23, NOT_INITIAL, PIO_GPIO | PIO_GPIO_IRQ | PIO_PWM, NOT_INITIAL},
|
||||
// A1: VBAT_MEAS, ADC2
|
||||
{AD_2, NOT_INITIAL, PIO_ADC, NOT_INITIAL},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
// ----
|
||||
|
||||
// Number of pins defined in PinDescription array
|
||||
#define PINS_COUNT (12u)
|
||||
#define NUM_DIGITAL_PINS (12u)
|
||||
#define NUM_ANALOG_INPUTS (2u)
|
||||
#define NUM_ANALOG_OUTPUTS (0u)
|
||||
#define PINS_COUNT 12
|
||||
#define NUM_DIGITAL_PINS 11
|
||||
#define NUM_ANALOG_INPUTS 2
|
||||
#define NUM_ANALOG_OUTPUTS 0
|
||||
|
||||
// Low-level pin register query macros
|
||||
// -----------------------------------
|
||||
@@ -21,14 +21,14 @@
|
||||
|
||||
// LEDs
|
||||
// ----
|
||||
#define PIN_LED (4u)
|
||||
#define LED_BUILTIN PIN_LED
|
||||
#define PIN_LED 4u // PA_0
|
||||
#define LED_BUILTIN PIN_LED // PA_0
|
||||
|
||||
// Analog pins
|
||||
// -----------
|
||||
#define PIN_A0 (1u) // PA_19
|
||||
#define PIN_A1 (0u) // dummy, this is NOT usable
|
||||
#define PIN_A2 (5u) // PA_20
|
||||
#define PIN_A0 1u // PA_19
|
||||
#define PIN_A1 11u // VBAT_MEAS
|
||||
#define PIN_A2 0u // dummy, this is NOT usable
|
||||
|
||||
static const uint8_t A0 = PIN_A0;
|
||||
static const uint8_t A1 = PIN_A1;
|
||||
@@ -40,22 +40,27 @@ static const uint8_t A2 = PIN_A2;
|
||||
|
||||
// Wire Interfaces
|
||||
// ---------------
|
||||
#define WIRE_INTERFACES_COUNT 0
|
||||
#define WIRE_INTERFACES_COUNT 2
|
||||
#define PIN_WIRE0_SDA 1u // PA_19
|
||||
#define PIN_WIRE0_SCL 0u // PA_22
|
||||
#define PIN_WIRE1_SDA 10u // PA_23
|
||||
#define PIN_WIRE1_SCL 9u // PA_18
|
||||
|
||||
// Serial ports
|
||||
// ------------
|
||||
#ifdef __cplusplus
|
||||
#include "LOGUARTClass.h"
|
||||
extern LOGUARTClass Serial;
|
||||
// LOGUARTClass
|
||||
#define PIN_SERIAL2_RX PA_29
|
||||
#define PIN_SERIAL2_TX PA_30
|
||||
#define PIN_SERIAL2_RX 5u // PA_29
|
||||
#define PIN_SERIAL2_TX 6u // PA_30
|
||||
// UARTClassOne
|
||||
#define PIN_SERIAL0_RX PA_18
|
||||
#define PIN_SERIAL0_TX PA_23
|
||||
#endif // __cplusplus
|
||||
#define PIN_SERIAL0_RX 9u // PA_18
|
||||
#define PIN_SERIAL0_TX 10u // PA_23
|
||||
|
||||
#define SERIAL_PORT_USBVIRTUAL Serial
|
||||
#define SERIAL_PORT_MONITOR Serial
|
||||
#define SERIAL_PORT_HARDWARE Serial
|
||||
#define SERIAL_PORT_HARDWARE_OPEN Serial
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "LOGUARTClass.h"
|
||||
extern LOGUARTClass Serial;
|
||||
#endif // __cplusplus
|
||||
|
||||
@@ -8,9 +8,9 @@ env = DefaultEnvironment()
|
||||
platform = env.PioPlatform()
|
||||
|
||||
API_DIR = platform.get_package_dir("framework-arduino-api")
|
||||
LT_API_DIR = join(platform.get_dir(), "arduino", "libretuya")
|
||||
LT_ARDUINO_DIR = join(platform.get_dir(), "arduino", "libretuya")
|
||||
assert isdir(API_DIR)
|
||||
assert isdir(LT_API_DIR)
|
||||
assert isdir(LT_ARDUINO_DIR)
|
||||
|
||||
# Sources - ArduinoCore-API
|
||||
env.AddLibrary(
|
||||
@@ -33,18 +33,27 @@ env.AddLibrary(
|
||||
# Sources - LibreTuya API
|
||||
env.AddLibrary(
|
||||
name="libretuya_api",
|
||||
base_dir=LT_API_DIR,
|
||||
base_dir=LT_ARDUINO_DIR,
|
||||
srcs=[
|
||||
"+<api/*.c*>",
|
||||
"+<common/*.c*>",
|
||||
"+<core/*.c*>",
|
||||
"+<libraries/**/*.c*>",
|
||||
"+<port/**/*.c*>",
|
||||
"+<posix/*.c>",
|
||||
],
|
||||
includes=[
|
||||
"!<.>",
|
||||
"!<compat>",
|
||||
"!<core>",
|
||||
"!<libraries/*>",
|
||||
"!<port/*>",
|
||||
"!<posix>",
|
||||
],
|
||||
)
|
||||
|
||||
# Sources - external library ports
|
||||
env.AddLibraryFlashDB(version="03500fa")
|
||||
|
||||
# Build all libraries
|
||||
env.BuildLibraries(safe=False)
|
||||
|
||||
14
builder/frameworks/arduino.py
Normal file
14
builder/frameworks/arduino.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# Copyright (c) Kuba Szczodrzyński 2022-05-16.
|
||||
|
||||
from SCons.Script import DefaultEnvironment
|
||||
|
||||
env = DefaultEnvironment()
|
||||
board = env.BoardConfig()
|
||||
platform = env.PioPlatform()
|
||||
|
||||
# support passing "arduino" as framework
|
||||
frameworks = board.get("frameworks")
|
||||
framework = next(fw for fw in frameworks if "arduino" in fw)
|
||||
builder = platform.frameworks[framework]["script"]
|
||||
builder = builder.rpartition("/")[2]
|
||||
env.SConscript(builder, exports="env")
|
||||
@@ -6,7 +6,13 @@ from SCons.Script import DefaultEnvironment
|
||||
|
||||
env = DefaultEnvironment()
|
||||
|
||||
# SDK options
|
||||
env.Replace(AMBZ_NO_POLARSSL=True)
|
||||
env.Replace(
|
||||
LIB_AMBZ_SDK_SKIP=[
|
||||
"component/common/api/wifi/wifi_ind.c",
|
||||
]
|
||||
)
|
||||
|
||||
env.SConscript("realtek-ambz-sdk.py", exports="env")
|
||||
env.SConscript("../arduino-common.py", exports="env")
|
||||
@@ -39,16 +45,15 @@ env.Append(
|
||||
"ARDUINO_AMEBA",
|
||||
"ARDUINO_SDK",
|
||||
"ARDUINO_ARCH_AMBZ",
|
||||
"BOARD_${FAMILY}",
|
||||
# the SDK declares bool if not defined before
|
||||
# which conflicts with C++ built-in bool
|
||||
# so it's either -fpermissive or this:
|
||||
("bool", "bool"),
|
||||
# enable LwIPRxBuffer
|
||||
"LT_HAS_LWIP",
|
||||
("LT_HAS_LWIP", "1"),
|
||||
# enable LwIPmDNS
|
||||
("LT_HAS_LWIP2", "1"),
|
||||
("LT_PRINTF_BROKEN", "1"), # printf does not handle %.3f properly
|
||||
"MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED", # enable PSK in mbedTLS
|
||||
# "MBEDTLS_DEBUG_C",
|
||||
],
|
||||
LINKFLAGS=[
|
||||
"--specs=nosys.specs",
|
||||
@@ -94,32 +99,6 @@ env.AddLibrary(
|
||||
],
|
||||
)
|
||||
|
||||
# Sources - mbedTLS
|
||||
env.AddLibrary(
|
||||
name="ambz_mbedtls",
|
||||
base_dir="$SDK_DIR",
|
||||
srcs=[
|
||||
# mbedTLS from SDK
|
||||
"+<component/common/network/ssl/mbedtls-2.4.0/library/*.c>",
|
||||
# skip ssl_tls.c for a fixup
|
||||
"-<component/common/network/ssl/mbedtls-2.4.0/library/ssl_tls.c>",
|
||||
],
|
||||
includes=[
|
||||
"+<component/common/network/ssl/mbedtls-2.4.0/include>",
|
||||
# remove polarssl
|
||||
"-<component/common/network/ssl/polarssl-1.3.8/include>",
|
||||
],
|
||||
)
|
||||
|
||||
# Sources - platform fixups
|
||||
env.AddLibrary(
|
||||
name="ambz_arduino_fixups",
|
||||
base_dir="$FIXUPS_DIR",
|
||||
srcs=[
|
||||
"+<ssl_tls.c>", # rtl sdk defines S1 and S2 which conflicts here
|
||||
],
|
||||
)
|
||||
|
||||
# Sources - Arduino libraries
|
||||
env.AddLibrary(
|
||||
name="ambz_arduino_libs",
|
||||
@@ -132,6 +111,18 @@ env.AddLibrary(
|
||||
],
|
||||
)
|
||||
|
||||
# Sources - external library ports
|
||||
env.AddLibrary(
|
||||
name="ambz_arduino_port",
|
||||
base_dir="$ARDUINO_DIR",
|
||||
srcs=[
|
||||
"+<port/**/*.c*>",
|
||||
],
|
||||
includes=[
|
||||
"+<port/*>",
|
||||
],
|
||||
)
|
||||
|
||||
# Libs & linker config
|
||||
env.Append(
|
||||
LIBS=[
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
# Copyright (c) Kuba Szczodrzyński 2022-04-20.
|
||||
|
||||
import sys
|
||||
from os.path import join
|
||||
|
||||
from SCons.Script import Builder, DefaultEnvironment
|
||||
@@ -10,30 +9,6 @@ board = env.BoardConfig()
|
||||
|
||||
env.AddDefaults("realtek-ambz", "framework-realtek-amb1")
|
||||
|
||||
flash_addr = board.get("build.amb_flash_addr")
|
||||
flash_ota1_offset = env.subst("$FLASH_OTA1_OFFSET")
|
||||
flash_ota2_offset = env.subst("$FLASH_OTA2_OFFSET")
|
||||
boot_all = board.get("build.amb_boot_all")
|
||||
ota1_offset = hex(int(flash_addr, 16) + int(flash_ota1_offset, 16))
|
||||
ota2_offset = hex(int(flash_addr, 16) + int(flash_ota2_offset, 16))
|
||||
|
||||
# Outputs
|
||||
env.Replace(
|
||||
IMG_FW="image2_all_ota1.bin",
|
||||
IMG_OTA="ota_all.bin",
|
||||
)
|
||||
|
||||
# Tools
|
||||
# fmt: off
|
||||
TOOL_DIR = join("$SDK_DIR", "component", "soc", "realtek", "8711b", "misc", "iar_utility", "common", "tools")
|
||||
# fmt: on
|
||||
env.Replace(
|
||||
PICK=join(TOOL_DIR, "pick"),
|
||||
PAD=join(TOOL_DIR, "pad"),
|
||||
CHECKSUM=join(TOOL_DIR, "checksum"),
|
||||
OTA=join(TOOL_DIR, "ota"),
|
||||
)
|
||||
|
||||
# Flags
|
||||
env.Append(
|
||||
CFLAGS=[
|
||||
@@ -57,14 +32,19 @@ env.Append(
|
||||
CPPDEFINES=[
|
||||
"M3",
|
||||
"CONFIG_PLATFORM_8711B",
|
||||
("F_CPU", "166000000L"),
|
||||
# LwIP options
|
||||
("LWIP_TIMEVAL_PRIVATE", "0"),
|
||||
("LWIP_NETIF_HOSTNAME", "1"), # to support hostname changing
|
||||
("LWIP_PROVIDE_ERRNO", "1"), # for extern int errno and codes
|
||||
("LWIP_SO_RCVBUF", "1"), # for ioctl(FIONREAD)
|
||||
("ip_addr", "ip4_addr"), # LwIP 2.0.x compatibility
|
||||
("ip_addr_t", "ip4_addr_t"), # LwIP 2.0.x compatibility
|
||||
("IN_ADDR_T_DEFINED", "1"),
|
||||
("in_addr_t", "u32_t"),
|
||||
("INT_MAX", "2147483647"), # for RECV_BUFSIZE_DEFAULT
|
||||
("ERRNO", "1"), # for LwIP
|
||||
("vprintf", "rtl_vprintf"),
|
||||
"MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED", # enable PSK in mbedTLS
|
||||
# "MBEDTLS_DEBUG_C",
|
||||
],
|
||||
LINKFLAGS=[
|
||||
"-mcpu=cortex-m4",
|
||||
@@ -115,42 +95,7 @@ env.AddLibrary(
|
||||
"+<component/common/api/wifi/wifi_simple_config.c>",
|
||||
"+<component/common/api/wifi/wifi_util.c>",
|
||||
"+<component/common/api/lwip_netconf.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/api/api_lib.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/api/api_msg.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/api/err.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/api/netbuf.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/api/netdb.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/api/netifapi.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/api/sockets.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/api/tcpip.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/autoip.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/icmp.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/igmp.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/inet.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/inet_chksum.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/ip.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/ip_addr.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/ip_frag.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/def.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/dhcp.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/dns.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/init.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/lwip_timers.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/mem.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/memp.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/netif.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/pbuf.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/raw.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/stats.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/sys.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/tcp.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/tcp_in.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/tcp_out.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/core/udp.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/netif/etharp.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/port/realtek/freertos/ethernetif.c>",
|
||||
"+<component/common/drivers/wlan/realtek/src/osdep/lwip_intf.c>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/port/realtek/freertos/sys_arch.c>",
|
||||
"+<component/common/network/dhcp/dhcps.c>",
|
||||
"+<component/common/network/sntp/sntp.c>",
|
||||
"+<component/common/network/ssl/ssl_ram_map/ssl_ram_map.c>",
|
||||
@@ -218,12 +163,7 @@ env.AddLibrary(
|
||||
"+<component/common/drivers/wlan/realtek/wlan_ram_map/rom>",
|
||||
"+<component/common/file_system>",
|
||||
"+<component/common/network>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/port/realtek/freertos>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/include>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/include/lwip>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/src/include/ipv4>",
|
||||
"+<component/common/network/lwip/lwip_v1.4.1/port/realtek>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/include>",
|
||||
"+<component/common/network/ssl/mbedtls-2.4.0/include>",
|
||||
"+<component/common/network/ssl/ssl_ram_map/rom>",
|
||||
"+<component/common/utilities>",
|
||||
"+<component/soc/realtek/8711b/app/monitor/include>",
|
||||
@@ -243,59 +183,26 @@ env.AddLibrary(
|
||||
],
|
||||
)
|
||||
|
||||
# Sources - PolarSSL library
|
||||
if "AMBZ_NO_POLARSSL" not in env or not env["AMBZ_NO_POLARSSL"]:
|
||||
env.AddLibrary(
|
||||
name="ambz_polarssl",
|
||||
base_dir="$SDK_DIR",
|
||||
srcs=[
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/aesni.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/blowfish.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/camellia.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/ccm.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/certs.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/cipher.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/cipher_wrap.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/debug.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/ecp_ram.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/entropy.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/entropy_poll.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/error.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/gcm.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/havege.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/md2.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/md4.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/memory_buffer_alloc.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/net.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/padlock.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/pbkdf2.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/pkcs11.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/pkcs12.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/pkcs5.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/pkparse.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/platform.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/ripemd160.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/ssl_cache.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/ssl_ciphersuites.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/ssl_cli.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/ssl_srv.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/ssl_tls.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/threading.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/timing.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/version.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/version_features.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/x509.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/x509_create.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/x509_crl.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/x509_crt.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/x509_csr.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/x509write_crt.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/x509write_csr.c>",
|
||||
"+<component/common/network/ssl/polarssl-1.3.8/library/xtea.c>",
|
||||
],
|
||||
)
|
||||
# Sources - lwIP 2.0.0
|
||||
env.AddLibraryLwIP(version="2.0.0", port="amb1")
|
||||
|
||||
# Sources - platform fixups
|
||||
# Sources - mbedTLS
|
||||
env.AddLibrary(
|
||||
name="ambz_mbedtls",
|
||||
base_dir="$SDK_DIR",
|
||||
srcs=[
|
||||
# mbedTLS from SDK
|
||||
"+<component/common/network/ssl/mbedtls-2.4.0/library/*.c>",
|
||||
# replace these with fixups
|
||||
"-<component/common/network/ssl/mbedtls-2.4.0/library/net_sockets.c>",
|
||||
"-<component/common/network/ssl/mbedtls-2.4.0/library/ssl_tls.c>",
|
||||
],
|
||||
includes=[
|
||||
"+<component/common/network/ssl/mbedtls-2.4.0/include>",
|
||||
],
|
||||
)
|
||||
|
||||
# Sources - family fixups
|
||||
env.AddLibrary(
|
||||
name="ambz_fixups",
|
||||
base_dir="$FIXUPS_DIR",
|
||||
@@ -303,6 +210,8 @@ env.AddLibrary(
|
||||
"+<app_start_patch.c>",
|
||||
"+<cmsis_ipsr.c>",
|
||||
"+<log_uart.c>",
|
||||
"+<net_sockets.c>", # fix non-blocking sockets (Realtek disabled this for unknown reason)
|
||||
"+<ssl_tls.c>", # rtl sdk defines S1 and S2 which conflicts here
|
||||
"+<wifi_mode.c>",
|
||||
],
|
||||
)
|
||||
@@ -344,65 +253,6 @@ env.Replace(
|
||||
SIZEPRINTCMD="$SIZETOOL -B -d $SOURCES",
|
||||
)
|
||||
|
||||
# Image conversion
|
||||
def pick_tool(target, source, env):
|
||||
sections = [
|
||||
"__ram_image2_text_start__",
|
||||
"__ram_image2_text_end__",
|
||||
"__xip_image2_start__",
|
||||
]
|
||||
addrs = [None] * len(sections)
|
||||
with open(env.subst("${BUILD_DIR}/${PROGNAME}.nmap")) as f:
|
||||
for line in f:
|
||||
for i, section in enumerate(sections):
|
||||
if section not in line:
|
||||
continue
|
||||
addrs[i] = line.split()[0]
|
||||
files = [
|
||||
join("$BUILD_DIR", "ram_2.r.bin"), # RAM image with padding
|
||||
join("$BUILD_DIR", "ram_2.bin"), # RAM image, stripped
|
||||
join("$BUILD_DIR", "ram_2.p.bin"), # RAM image, stripped, with header
|
||||
join("$BUILD_DIR", "xip_image2.bin"), # raw firmware image
|
||||
join("$BUILD_DIR", "xip_image2.p.bin"), # firmware with header
|
||||
]
|
||||
commands = [
|
||||
f"$PICK 0x{addrs[0]} 0x{addrs[1]} {files[0]} {files[1]} raw",
|
||||
f"$PICK 0x{addrs[0]} 0x{addrs[1]} {files[1]} {files[2]}",
|
||||
f"$PICK 0x{addrs[2]} 0x{addrs[2]} {files[3]} {files[4]}",
|
||||
]
|
||||
for command in commands:
|
||||
status = env.Execute("@" + command + " > " + join("$BUILD_DIR", "pick.txt"))
|
||||
if status:
|
||||
return status
|
||||
|
||||
|
||||
def concat_xip_ram(target, source, env):
|
||||
with open(env.subst("${BUILD_DIR}/xip_image2.p.bin"), "rb") as f:
|
||||
xip = f.read()
|
||||
with open(env.subst("${BUILD_DIR}/ram_2.p.bin"), "rb") as f:
|
||||
ram = f.read()
|
||||
with open(env.subst("${BUILD_DIR}/${IMG_FW}"), "wb") as f:
|
||||
f.write(xip)
|
||||
f.write(ram)
|
||||
|
||||
|
||||
def checksum_img(target, source, env):
|
||||
source = join("$BUILD_DIR", "$IMG_FW")
|
||||
status = env.Execute(f"@$CHECKSUM {source}")
|
||||
if status:
|
||||
return status
|
||||
|
||||
|
||||
def package_ota(target, source, env):
|
||||
source = join("$BUILD_DIR", "$IMG_FW")
|
||||
target = join("$BUILD_DIR", "$IMG_OTA")
|
||||
status = env.Execute(
|
||||
f"@$OTA {source} {ota1_offset} {source} {ota2_offset} 0x20170111 {target}"
|
||||
)
|
||||
if status:
|
||||
return status
|
||||
|
||||
|
||||
env.Append(
|
||||
BUILDERS=dict(
|
||||
BinToObj=Builder(
|
||||
@@ -419,90 +269,9 @@ env.Append(
|
||||
)
|
||||
),
|
||||
)
|
||||
commands = [
|
||||
(
|
||||
"${PROGNAME}.nmap",
|
||||
[
|
||||
"$NM",
|
||||
"$SOURCE",
|
||||
"> $BIN",
|
||||
],
|
||||
),
|
||||
(
|
||||
"ram_2.r.bin",
|
||||
[
|
||||
"$OBJCOPY",
|
||||
"-j .ram_image2.entry",
|
||||
"-j .ram_image2.data",
|
||||
"-j .ram_image2.bss",
|
||||
"-j .ram_image2.skb.bss",
|
||||
"-j .ram_heap.data",
|
||||
"-O binary",
|
||||
"$SOURCE",
|
||||
"$BIN",
|
||||
],
|
||||
),
|
||||
(
|
||||
"xip_image2.bin",
|
||||
[
|
||||
"$OBJCOPY",
|
||||
"-j .xip_image2.text",
|
||||
"-O binary",
|
||||
"$SOURCE",
|
||||
"$BIN",
|
||||
],
|
||||
),
|
||||
(
|
||||
"rdp.bin",
|
||||
[
|
||||
"$OBJCOPY",
|
||||
"-j .ram_rdp.text",
|
||||
"-O binary",
|
||||
"$SOURCE",
|
||||
"$BIN",
|
||||
],
|
||||
),
|
||||
]
|
||||
actions = [
|
||||
env.VerboseAction(
|
||||
" ".join(command).replace("$BIN", join("$BUILD_DIR", target)),
|
||||
f"Generating {target}",
|
||||
)
|
||||
for target, command in commands
|
||||
]
|
||||
actions.append(env.VerboseAction(pick_tool, "Wrapping binary images"))
|
||||
actions.append(env.VerboseAction(concat_xip_ram, "Packaging firmware image - $IMG_FW"))
|
||||
# actions.append(env.VerboseAction(checksum_img, "Generating checksum"))
|
||||
actions.append(env.VerboseAction(package_ota, "Packaging OTA image - $IMG_OTA"))
|
||||
actions.append(env.VerboseAction("true", f"- OTA1 flash offset: $FLASH_OTA1_OFFSET"))
|
||||
actions.append(env.VerboseAction("true", f"- OTA2 flash offset: $FLASH_OTA2_OFFSET"))
|
||||
|
||||
# Uploader
|
||||
upload_protocol = env.subst("$UPLOAD_PROTOCOL")
|
||||
upload_source = ""
|
||||
upload_actions = []
|
||||
# from platform-espressif32/builder/main.py
|
||||
if upload_protocol == "uart":
|
||||
env.Replace(
|
||||
UPLOADER=join("$TOOLS_DIR", "rtltool.py"),
|
||||
UPLOADERFLAGS=[
|
||||
"--port",
|
||||
"$UPLOAD_PORT",
|
||||
"--go", # run firmware after uploading
|
||||
"wf", # Write a binary file to Flash data
|
||||
],
|
||||
UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $FLASH_OTA1_OFFSET "$BUILD_DIR/$IMG_FW"',
|
||||
)
|
||||
upload_actions = [
|
||||
env.VerboseAction(env.AutodetectUploadPort, "Looking for upload port..."),
|
||||
env.VerboseAction("$UPLOADCMD", "Uploading $IMG_FW"),
|
||||
]
|
||||
elif upload_protocol == "custom":
|
||||
upload_actions = [env.VerboseAction("$UPLOADCMD", "Uploading $IMG_FW")]
|
||||
else:
|
||||
sys.stderr.write("Warning! Unknown upload protocol %s\n" % upload_protocol)
|
||||
|
||||
# Bootloader library
|
||||
boot_all = board.get("build.amb_boot_all")
|
||||
target_boot = env.StaticLibrary(
|
||||
join("$BUILD_DIR", "boot_all"),
|
||||
env.BinToObj(
|
||||
@@ -515,10 +284,19 @@ env.Prepend(LIBS=[target_boot])
|
||||
# Build all libraries
|
||||
env.BuildLibraries()
|
||||
|
||||
# Main firmware binary builder
|
||||
env.Append(
|
||||
BUILDERS=dict(
|
||||
DumpFirmwareBinary=Builder(action=actions),
|
||||
),
|
||||
UPLOAD_ACTIONS=upload_actions,
|
||||
# Main firmware outputs and actions
|
||||
env.Replace(
|
||||
# linker command (dual .bin outputs)
|
||||
LINK="${LINK2BIN} AMBZ xip1 xip2",
|
||||
# default output .bin name
|
||||
IMG_FW="image_${FLASH_OTA1_OFFSET}.ota1.bin",
|
||||
# UF2OTA input list
|
||||
UF2OTA=[
|
||||
(
|
||||
"ota1",
|
||||
"${BUILD_DIR}/image_${FLASH_OTA1_OFFSET}.ota1.bin",
|
||||
"ota2",
|
||||
"${BUILD_DIR}/image_${FLASH_OTA2_OFFSET}.ota2.bin",
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
29
builder/libs/flashdb.py
Normal file
29
builder/libs/flashdb.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# Copyright (c) Kuba Szczodrzyński 2022-05-24.
|
||||
|
||||
from SCons.Script import DefaultEnvironment
|
||||
|
||||
env = DefaultEnvironment()
|
||||
platform = env.PioPlatform()
|
||||
|
||||
|
||||
def env_add_flashdb(
|
||||
env,
|
||||
version: str,
|
||||
):
|
||||
package_dir = platform.get_package_dir(f"library-flashdb@{version}")
|
||||
|
||||
env.AddLibrary(
|
||||
name=f"flashdb{version}",
|
||||
base_dir=package_dir,
|
||||
srcs=[
|
||||
"+<src/*.c>",
|
||||
"+<port/fal/src/*.c>",
|
||||
],
|
||||
includes=[
|
||||
"+<inc>",
|
||||
"+<port/fal/inc>",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
env.AddMethod(env_add_flashdb, "AddLibraryFlashDB")
|
||||
49
builder/libs/lwip.py
Normal file
49
builder/libs/lwip.py
Normal file
@@ -0,0 +1,49 @@
|
||||
# Copyright (c) Kuba Szczodrzyński 2022-05-18.
|
||||
|
||||
from SCons.Script import DefaultEnvironment
|
||||
|
||||
env = DefaultEnvironment()
|
||||
platform = env.PioPlatform()
|
||||
|
||||
|
||||
def env_add_lwip(
|
||||
env,
|
||||
version: str,
|
||||
port: str,
|
||||
):
|
||||
# version = env["LIB_LWIP_VERSION"] if "LIB_LWIP_VERSION" in env else version_default
|
||||
package_dir = platform.get_package_dir(f"library-lwip@{version}-{port}")
|
||||
port_srcs = []
|
||||
port_includes = []
|
||||
|
||||
if port in ["amb1"]:
|
||||
port_srcs = [
|
||||
"+<port/realtek/freertos/ethernetif.c>",
|
||||
"+<port/realtek/freertos/sys_arch.c>",
|
||||
]
|
||||
port_includes = [
|
||||
"+<port/realtek>",
|
||||
"+<port/realtek/freertos>",
|
||||
]
|
||||
|
||||
env.AddLibrary(
|
||||
name=f"lwip{version}_{port}",
|
||||
base_dir=package_dir,
|
||||
srcs=[
|
||||
"+<src/api/*.c>",
|
||||
"+<src/core/*.c>",
|
||||
"+<src/core/ipv4/*.c>",
|
||||
"+<src/netif/ethernet.c>", # 2.0.x
|
||||
"+<src/netif/etharp.c>", # 1.4.x
|
||||
"+<src/apps/mdns/mdns.c>",
|
||||
*port_srcs,
|
||||
],
|
||||
includes=[
|
||||
"+<src/include>",
|
||||
"+<src/include/ipv4>",
|
||||
*port_includes,
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
env.AddMethod(env_add_lwip, "AddLibraryLwIP")
|
||||
@@ -1,5 +1,7 @@
|
||||
# Copyright (c) Kuba Szczodrzyński 2022-04-20.
|
||||
|
||||
import sys
|
||||
|
||||
from SCons.Script import Default, DefaultEnvironment
|
||||
|
||||
env = DefaultEnvironment()
|
||||
@@ -7,6 +9,10 @@ board = env.BoardConfig()
|
||||
|
||||
# Utilities
|
||||
env.SConscript("utils.py", exports="env")
|
||||
env.SConscript("uf2.py", exports="env")
|
||||
# Vendor-specific library ports
|
||||
env.SConscript("libs/lwip.py", exports="env")
|
||||
env.SConscript("libs/flashdb.py", exports="env")
|
||||
|
||||
# Firmware name
|
||||
if env.get("PROGNAME", "program") == "program":
|
||||
@@ -22,7 +28,6 @@ env.Replace(
|
||||
GDB="arm-none-eabi-gdb",
|
||||
NM="arm-none-eabi-gcc-nm",
|
||||
LINK="arm-none-eabi-gcc",
|
||||
LD="arm-none-eabi-gcc",
|
||||
OBJCOPY="arm-none-eabi-objcopy",
|
||||
OBJDUMP="arm-none-eabi-objdump",
|
||||
# RANLIB="arm-none-eabi-gcc-ranlib",
|
||||
@@ -33,34 +38,48 @@ env.Replace(
|
||||
flash_layout: dict = board.get("flash")
|
||||
if flash_layout:
|
||||
defines = {}
|
||||
flash_size = 0
|
||||
fal_items = ""
|
||||
for name, layout in flash_layout.items():
|
||||
name = name.upper()
|
||||
(offset, _, length) = layout.partition("+")
|
||||
defines[f"FLASH_{name}_OFFSET"] = offset
|
||||
defines[f"FLASH_{name}_LENGTH"] = length
|
||||
fal_items += f"FAL_PART_TABLE_ITEM({name.lower()}, {name})"
|
||||
flash_size = max(flash_size, int(offset, 16) + int(length, 16))
|
||||
defines["FLASH_LENGTH"] = flash_size
|
||||
defines["FAL_PART_TABLE"] = "{" + fal_items + "}"
|
||||
env.Append(CPPDEFINES=defines.items())
|
||||
env.Replace(**defines)
|
||||
|
||||
# Platform builders details:
|
||||
# - call env.AddDefaults("platform name", "sdk name") to add dir paths
|
||||
# Family builders details:
|
||||
# - call env.AddDefaults("family name", "sdk name") to add dir paths
|
||||
# - call env.AddLibrary("lib name", "base dir", [sources]) to add lib sources
|
||||
# - output main firmware image binary as $IMG_FW
|
||||
# - call env.BuildLibraries() to build lib targets with safe envs
|
||||
# - configure LINK, UF2OTA and UPLOAD_ACTIONS
|
||||
# - script code ordering:
|
||||
# - global vars
|
||||
# - # Outputs
|
||||
# - # Tools
|
||||
# - # Flags (C(XX)FLAGS / CPPDEFINES / LINKFLAGS)
|
||||
# - sources (env.AddLibrary)
|
||||
# - # Libs & linker config (LIBPATH / LIBS / LDSCRIPT_PATH)
|
||||
# - # Misc options
|
||||
# - # Image conversion (tools, functions, builders, actions, etc.)
|
||||
# - # Uploader
|
||||
# - # Library targets
|
||||
# - # Bootloader library
|
||||
# - env.BuildLibraries()
|
||||
# - # Main firmware binary builder
|
||||
# - # Main firmware outputs and actions
|
||||
|
||||
target_elf = env.BuildProgram()
|
||||
target_fw = env.DumpFirmwareBinary("$IMG_FW", target_elf)
|
||||
env.AddPlatformTarget("upload", target_fw, env["UPLOAD_ACTIONS"], "Upload")
|
||||
Default(target_fw)
|
||||
targets = [target_elf]
|
||||
|
||||
if "UF2OTA" in env:
|
||||
target_uf2 = env.BuildUF2OTA(target_elf)
|
||||
targets.append(target_uf2)
|
||||
env.AddUF2Uploader(target_uf2)
|
||||
elif "IMG_FW" in env:
|
||||
target_fw = env.subst("$IMG_FW")
|
||||
env.AddPlatformTarget("upload", target_fw, env["UPLOAD_ACTIONS"], "Upload")
|
||||
else:
|
||||
sys.stderr.write("Warning! Firmware outputs not specified.\n")
|
||||
|
||||
Default(targets)
|
||||
|
||||
85
builder/uf2.py
Normal file
85
builder/uf2.py
Normal file
@@ -0,0 +1,85 @@
|
||||
# Copyright (c) Kuba Szczodrzyński 2022-06-02.
|
||||
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from os.path import basename, join, normpath
|
||||
|
||||
from SCons.Script import Builder, DefaultEnvironment
|
||||
|
||||
env = DefaultEnvironment()
|
||||
platform = env.PioPlatform()
|
||||
|
||||
|
||||
def env_uf2ota(env, *args, **kwargs):
|
||||
now = datetime.now()
|
||||
project_dir = env.subst("$PROJECT_DIR")
|
||||
project_name = basename(normpath(project_dir))
|
||||
# TODO support specifying custom version
|
||||
project_version = now.strftime("%y.%m.%d")
|
||||
lt_version = platform.version
|
||||
|
||||
inputs = " ".join(f'"{";".join(input)}"' for input in env["UF2OTA"])
|
||||
output = [
|
||||
project_name,
|
||||
project_version,
|
||||
"${VARIANT}",
|
||||
"${FAMILY}",
|
||||
f"lt{lt_version}",
|
||||
]
|
||||
output = join("${BUILD_DIR}", "_".join(output)) + ".uf2"
|
||||
env["UF2OUT"] = output
|
||||
env["UF2OUT_BASE"] = basename(output)
|
||||
|
||||
cmd = [
|
||||
"@${UF2OTA_PY}",
|
||||
f'--output "{output}"',
|
||||
"--family ${FAMILY}",
|
||||
"--board ${VARIANT}",
|
||||
f"--version {lt_version}",
|
||||
f'--fw "{project_name}:{project_version}"',
|
||||
f"--date {int(now.timestamp())}",
|
||||
"write",
|
||||
inputs,
|
||||
]
|
||||
|
||||
print(f"|-- {basename(env.subst(output))}")
|
||||
|
||||
env.Execute(" ".join(cmd))
|
||||
|
||||
|
||||
def env_uf2upload(env, target):
|
||||
protocol = env.subst("${UPLOAD_PROTOCOL}")
|
||||
actions = []
|
||||
# from platform-espressif32/builder/main.py
|
||||
if protocol == "uart":
|
||||
# upload via UART
|
||||
env["UPLOADERFLAGS"] = [
|
||||
"${UF2OUT}",
|
||||
"uart",
|
||||
"${UPLOAD_PORT}",
|
||||
]
|
||||
actions = [
|
||||
env.VerboseAction(env.AutodetectUploadPort, "Looking for upload port..."),
|
||||
]
|
||||
elif protocol == "custom":
|
||||
actions = [
|
||||
env.VerboseAction("${UPLOADCMD}", "Uploading firmware"),
|
||||
]
|
||||
else:
|
||||
sys.stderr.write("Warning! Unknown upload protocol %s\n" % protocol)
|
||||
return
|
||||
|
||||
# add main upload target
|
||||
env.Replace(UPLOADER="${UF2UPLOAD_PY}", UPLOADCMD="${UPLOADER} ${UPLOADERFLAGS}")
|
||||
actions.append(env.VerboseAction("${UPLOADCMD}", "Uploading ${UF2OUT_BASE}"))
|
||||
env.AddPlatformTarget("upload", target, actions, "Upload")
|
||||
|
||||
|
||||
env.Append(
|
||||
BUILDERS=dict(
|
||||
BuildUF2OTA=Builder(
|
||||
action=[env.VerboseAction(env_uf2ota, "Building UF2 OTA image")]
|
||||
)
|
||||
)
|
||||
)
|
||||
env.AddMethod(env_uf2upload, "AddUF2Uploader")
|
||||
@@ -12,26 +12,30 @@ platform = env.PioPlatform()
|
||||
board = env.BoardConfig()
|
||||
|
||||
|
||||
def env_add_defaults(env, platform_name: str, sdk_name: str):
|
||||
def env_add_defaults(env, family_name: str, sdk_name: str):
|
||||
vars = dict(
|
||||
SDK_DIR=platform.get_package_dir(sdk_name),
|
||||
LT_DIR=platform.get_dir(),
|
||||
# Root dirs
|
||||
BOARD_DIR=join("${LT_DIR}", "boards", "${VARIANT}"),
|
||||
ARDUINO_DIR=join("${LT_DIR}", "arduino", platform_name),
|
||||
PLATFORM_DIR=join("${LT_DIR}", "platform", platform_name),
|
||||
ARDUINO_DIR=join("${LT_DIR}", "arduino", family_name),
|
||||
FAMILY_DIR=join("${LT_DIR}", "platform", family_name),
|
||||
TOOLS_DIR=join("${LT_DIR}", "tools"),
|
||||
# Platform-specific dirs
|
||||
BIN_DIR=join("${PLATFORM_DIR}", "bin"),
|
||||
FIXUPS_DIR=join("${PLATFORM_DIR}", "fixups"),
|
||||
LD_DIR=join("${PLATFORM_DIR}", "ld"),
|
||||
OPENOCD_DIR=join("${PLATFORM_DIR}", "openocd"),
|
||||
# Family-specific dirs
|
||||
BIN_DIR=join("${FAMILY_DIR}", "bin"),
|
||||
FIXUPS_DIR=join("${FAMILY_DIR}", "fixups"),
|
||||
LD_DIR=join("${FAMILY_DIR}", "ld"),
|
||||
OPENOCD_DIR=join("${FAMILY_DIR}", "openocd"),
|
||||
# Board config variables
|
||||
MCU=board.get("build.mcu").upper(),
|
||||
FAMILY=board.get("build.family").upper(),
|
||||
FAMILY=board.get("build.family"),
|
||||
VARIANT=board.get("build.variant"),
|
||||
LDSCRIPT_SDK=board.get("build.ldscript_sdk"),
|
||||
LDSCRIPT_ARDUINO=board.get("build.ldscript_arduino"),
|
||||
# Link2Bin tool
|
||||
LINK2BIN='"${PYTHONEXE}" "${LT_DIR}/tools/link2bin.py"',
|
||||
UF2OTA_PY='"${PYTHONEXE}" "${LT_DIR}/tools/uf2ota/uf2ota.py"',
|
||||
UF2UPLOAD_PY='"${PYTHONEXE}" "${LT_DIR}/tools/upload/uf2upload.py"',
|
||||
)
|
||||
env.Replace(**vars)
|
||||
for k, v in vars.items():
|
||||
@@ -41,6 +45,7 @@ def env_add_defaults(env, platform_name: str, sdk_name: str):
|
||||
CPPPATH=[
|
||||
"$BOARD_DIR",
|
||||
"$FIXUPS_DIR",
|
||||
"$FIXUPS_DIR/inc",
|
||||
],
|
||||
LIBPATH=[
|
||||
"$LD_DIR",
|
||||
@@ -48,6 +53,9 @@ def env_add_defaults(env, platform_name: str, sdk_name: str):
|
||||
CPPDEFINES=[
|
||||
("LT_VERSION", platform.version),
|
||||
("LT_BOARD", board.get("build.variant")),
|
||||
("F_CPU", board.get("build.f_cpu")),
|
||||
("MCU", board.get("build.mcu").upper()),
|
||||
("FAMILY", board.get("build.family")),
|
||||
],
|
||||
)
|
||||
|
||||
@@ -72,6 +80,13 @@ def env_add_library(
|
||||
expr = join(base_dir, src[2:-1])
|
||||
|
||||
sources.append(src[0] + "<" + expr + ">")
|
||||
|
||||
# allow removing sources from parent builders
|
||||
key = f"LIB_{name.upper()}_SKIP"
|
||||
if key in env:
|
||||
for expr in env[key]:
|
||||
sources.append("-<" + expr + ">")
|
||||
|
||||
# queue library for further env clone and build
|
||||
env.Prepend(LIBQUEUE=[[join("$BUILD_DIR", name), base_dir, sources]])
|
||||
|
||||
|
||||
7
docs/README.md
Normal file
7
docs/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Documentation
|
||||
|
||||
This documentation is best suited for rendering with MkDocs. Some elements may not display correctly in the GitHub markdown reader.
|
||||
|
||||
Please visit [https://kuba2k2.github.io/libretuya/](https://kuba2k2.github.io/libretuya) for the full experience.
|
||||
|
||||
If you still want to read the docs on GitHub, visit [SUMMARY.md](../SUMMARY.md).
|
||||
@@ -1,6 +1,6 @@
|
||||
# LibreTuya API Configuration
|
||||
|
||||
Note: see [LibreTuyaConfig.h](../arduino/libretuya/api/LibreTuyaConfig.h) for most options and their defaults.
|
||||
Note: see [LibreTuyaConfig.h](../arduino/libretuya/core/LibreTuyaConfig.h) for most options and their defaults.
|
||||
|
||||
All options are configurable via C++ defines in PlatformIO project file. For example:
|
||||
```ini
|
||||
@@ -29,7 +29,7 @@ build_flags =
|
||||
|
||||
The following options enable library-specific debugging messages. They are only effective if `LT_LOGLEVEL` is set below INFO. All of them are disabled by default.
|
||||
|
||||
Platforms should generally call i.e. WiFiClient debugging for client-related code, even if the `WiFiClient.cpp` file is physically absent.
|
||||
Families should generally call i.e. WiFiClient debugging for client-related code, even if the `WiFiClient.cpp` file is physically absent.
|
||||
|
||||
- LT_DEBUG_WIFI - `WiFi.cpp`
|
||||
- LT_DEBUG_WIFI_CLIENT - `WiFiClient.cpp`
|
||||
@@ -37,6 +37,7 @@ Platforms should generally call i.e. WiFiClient debugging for client-related cod
|
||||
- LT_DEBUG_WIFI_STA - `WiFiSTA.cpp`
|
||||
- LT_DEBUG_WIFI_AP - `WiFiAP.cpp`
|
||||
|
||||
## Platform options
|
||||
## Family options
|
||||
|
||||
- LT_HAS_LWIP - whether platform SDK has LwIP. This causes `LwIPRxBuffer.cpp` to be compiled for platform libraries to use.
|
||||
- LT_HAS_LWIP - whether family SDK has LwIP. This causes `LwIPRxBuffer.cpp` to be compiled for family libraries to use.
|
||||
- LT_HAS_LWIP2 - whether family has LwIP v2.0.0 or newer. This causes `LwIPmDNS.cpp` to be compiled.
|
||||
|
||||
18
docs/families.md
Normal file
18
docs/families.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Families
|
||||
|
||||
A list of families currently available in this project.
|
||||
|
||||
**Note:** the term *family* was chosen over *platform*, in order to reduce possible confusion between LibreTuya supported "platforms" and PlatformIO's "platform", as an entire package. *Family* is also more compatible with the UF2 term.
|
||||
|
||||
The following list corresponds to UF2 OTA format family names, and is also [available as JSON](../uf2families.json). The IDs are also present in [ChipType.h](../arduino/libretuya/core/ChipType.h).
|
||||
|
||||
Full name | Code | Short name & ID | Supported MCU(s) | Arduino Core | Source SDK
|
||||
-----------------------------------------------------------------------|--------|-------------------------|------------------|--------------|--------------------------------------------------------------------------
|
||||
Realtek Ameba1 | `-` | `RTL8710A` (0x9FFFD543) | - | ❌ | -
|
||||
[Realtek AmebaZ](https://www.amebaiot.com/en/amebaz/) (`realtek-ambz`) | `ambz` | `RTL8710B` (0x22E0D6FC) | RTL87xxB | ✔️ | `framework-realtek-amb1` ([amb1_sdk](https://github.com/ambiot/amb1_sdk))
|
||||
Realtek AmebaZ2 | `-` | `RTL8720C` (0xE08F7564) | - | ❌ | -
|
||||
Realtek AmebaD | `-` | `RTL8720D` (0x3379CFE2) | - | ❌ | -
|
||||
Beken 7231T | `-` | `BK7231T` (0x675A40B0) | - | ❌ | -
|
||||
Beken 7231N | `-` | `BK7231N` (0x7B3EF230) | - | ❌ | -
|
||||
Boufallo 602 | `-` | `BL602` (0xDE1270B7) | - | ❌ | -
|
||||
Xradiotech 809 | `-` | `XR809` (0x51E903A8) | - | ❌ | -
|
||||
77
docs/families.py
Normal file
77
docs/families.py
Normal file
@@ -0,0 +1,77 @@
|
||||
# Copyright (c) Kuba Szczodrzyński 2022-05-31.
|
||||
|
||||
import json
|
||||
from os.path import dirname, isdir, join
|
||||
|
||||
HEADER = """\
|
||||
# Families
|
||||
|
||||
A list of families currently available in this project.
|
||||
|
||||
**Note:** the term *family* was chosen over *platform*, in order to reduce possible confusion between LibreTuya supported "platforms" and PlatformIO's "platform", as an entire package. *Family* is also more compatible with the UF2 term.
|
||||
|
||||
The following list corresponds to UF2 OTA format family names, and is also [available as JSON](../uf2families.json). The IDs are also present in [ChipType.h](../arduino/libretuya/core/ChipType.h).
|
||||
"""
|
||||
|
||||
|
||||
def format_row(row: list, lengths: list) -> str:
|
||||
row = [col + " " * (lengths[i] - len(col)) for i, col in enumerate(row)]
|
||||
return " | ".join(row).rstrip()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
data = join(dirname(__file__), "..", "families.json")
|
||||
out = join(dirname(__file__), "families.md")
|
||||
with open(data, "r") as f:
|
||||
data = json.load(f)
|
||||
|
||||
md = [HEADER]
|
||||
|
||||
lengths = [0, 0, 0, 0, 0, 0]
|
||||
header = [
|
||||
"Full name",
|
||||
"Code",
|
||||
"Short name & ID",
|
||||
"Supported MCU(s)",
|
||||
"Arduino Core",
|
||||
"Source SDK",
|
||||
]
|
||||
rows = []
|
||||
|
||||
for family in data:
|
||||
id = family["id"]
|
||||
short_name = family["short_name"]
|
||||
description = family["description"]
|
||||
name = family.get("name", "")
|
||||
code = family.get("code", "-")
|
||||
url = family.get("url", "-")
|
||||
sdk = family.get("sdk", "-")
|
||||
framework = family.get("framework", "-")
|
||||
mcus = family.get("mcus", "-")
|
||||
sdk_name = sdk.rpartition("/")[2]
|
||||
arduino = (
|
||||
isdir(join(dirname(__file__), "..", "arduino", name)) if name else False
|
||||
)
|
||||
row = [
|
||||
f"[{description}]({url}) (`{name}`)" if name else description,
|
||||
f"`{code}`",
|
||||
f"`{short_name}` ({id})",
|
||||
", ".join(mcus),
|
||||
"✔️" if arduino else "❌",
|
||||
f"`{framework}` ([{sdk_name}]({sdk}))" if name else "-",
|
||||
]
|
||||
rows.append(row)
|
||||
|
||||
for row in [header] + rows:
|
||||
for i, col in enumerate(row):
|
||||
lengths[i] = max(lengths[i], len(col))
|
||||
|
||||
md.append(format_row(header, lengths))
|
||||
md.append("-|-".join(length * "-" for length in lengths))
|
||||
for row in rows:
|
||||
md.append(format_row(row, lengths))
|
||||
|
||||
md.append("")
|
||||
|
||||
with open(out, "w", encoding="utf-8") as f:
|
||||
f.write("\n".join(md))
|
||||
7
docs/implementation-status.md
Normal file
7
docs/implementation-status.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Implementation status
|
||||
|
||||
{%
|
||||
include-markdown "../README.md"
|
||||
start="\n## Arduino Core support status\n"
|
||||
end="\n## License\n"
|
||||
%}
|
||||
@@ -3,20 +3,35 @@
|
||||
|
||||
## base64
|
||||
- [Source](https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/base64.cpp): ESP32 Arduino Core
|
||||
- [API](../arduino/libretuya/libraries/base64/base64.h)
|
||||
- [Reference](../ltapi/classbase64.md)
|
||||
|
||||
Helper base64 encoder used in some libs taken from ESP32.
|
||||
|
||||
## HTTPClient
|
||||
- [Source](https://github.com/espressif/arduino-esp32/tree/master/libraries/HTTPClient): ESP32 Arduino Core
|
||||
- [API](../arduino/libretuya/libraries/HTTPClient/HTTPClient.h)
|
||||
- [Reference](../ltapi/class_h_t_t_p_client.md)
|
||||
- [Examples](https://github.com/espressif/arduino-esp32/tree/master/libraries/HTTPClient/examples)
|
||||
|
||||
HTTP(S) client. Some reference may be found here: [https://links2004.github.io/Arduino/dd/d8d/class_h_t_t_p_client.html](https://links2004.github.io/Arduino/dd/d8d/class_h_t_t_p_client.html).
|
||||
HTTP(S) client.
|
||||
|
||||
## NetUtils
|
||||
|
||||
Utilities and common classes related to network.
|
||||
|
||||
- [ssl/MbedTLSClient.cpp](../ltapi/class_mbed_t_l_s_client.md) ([source](https://github.com/espressif/arduino-esp32/tree/master/libraries/WiFiClientSecure/src): ESP32 WiFiClientSecure)
|
||||
- [IPv6Address.cpp](../ltapi/classarduino_1_1_i_pv6_address.md) ([source](https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/IPv6Address.cpp): ESP32 IPv6Address)
|
||||
- [LwIPRxBuffer.cpp](../ltapi/class_lw_i_p_rx_buffer.md) ([source](https://github.com/espressif/arduino-esp32/blob/master/libraries/WiFi/src/WiFiClient.cpp): ESP32 WiFiClient)
|
||||
|
||||
## WebServer
|
||||
- [Source](https://github.com/espressif/arduino-esp32/tree/master/libraries/WebServer/src): ESP32 Arduino Core
|
||||
- [Reference](../ltapi/class_web_server.md)
|
||||
- Examples:
|
||||
- [HelloServer](https://github.com/espressif/arduino-esp32/blob/master/libraries/WebServer/examples/HelloServer/HelloServer.ino)
|
||||
- [MultiHomedServers](https://github.com/espressif/arduino-esp32/blob/master/libraries/WebServer/examples/MultiHomedServers/MultiHomedServers.ino)
|
||||
|
||||
## WiFiMulti
|
||||
- [Source](https://github.com/espressif/arduino-esp32/tree/master/libraries/WiFi/src): ESP32 Arduino Core
|
||||
- [API](../arduino/libretuya/libraries/WiFiMulti/WiFiMulti.h)
|
||||
- [Reference](../ltapi/class_wi_fi_multi.md)
|
||||
- [Docs](https://docs.espressif.com/projects/arduino-esp32/en/latest/api/wifi.html#wifimulti)
|
||||
- Examples:
|
||||
- [WiFiMulti](https://github.com/espressif/arduino-esp32/blob/master/libraries/WiFi/examples/WiFiMulti/WiFiMulti.ino)
|
||||
|
||||
157
docs/ota/README.md
Normal file
157
docs/ota/README.md
Normal file
@@ -0,0 +1,157 @@
|
||||
# UF2-based OTA
|
||||
|
||||
LibreTuya's OTA updating is based on [Microsoft's UF2 specification](https://microsoft.github.io/uf2/). Some aspects of the process, such as OTA1/2 support and target partition selection, have been customized with extension tags.
|
||||
|
||||
Note: just like in UF2, all values in this format are little-endian.
|
||||
|
||||
## Firmware images
|
||||
|
||||
UF2 files may contain multiple firmware images that are to be flashed, i.e. main firmware + bootloader + some config partition.
|
||||
|
||||
Some CPUs support dual-OTA schemes: firmware runs from one image, while the other one is reserved for updated firmware. After applying the update, a reboot causes to run the other image instead.
|
||||
|
||||
Each firmware image may be either applicable:
|
||||
|
||||
1. only when flashing OTA1 (`part;file;;`)
|
||||
2. only when flashing OTA2 (`;;part;file`)
|
||||
3. for both schemes to a single partition (`part;file`)
|
||||
4. for both schemes but different partitions (`part1;file;part2;file`)
|
||||
5. for both schemes but with a different binary (`part;file1;part;file2`)
|
||||
6. for both schemes, with different binaries and target partitions (`part1;file1;part2;file2`)
|
||||
|
||||
\* *`part` means partition here*
|
||||
|
||||
\*\* values in parentheses show the input format to use for [`uf2ota.py`](uf2ota.md)
|
||||
|
||||
For easier understanding, these update types will be referred to in this document using the numbers.
|
||||
|
||||
## Custom family IDs
|
||||
|
||||
Name | ID | Description
|
||||
-----------|------------|----------------
|
||||
`RTL8710A` | 0x9FFFD543 | Realtek Ameba1
|
||||
`RTL8710B` | 0x22E0D6FC | Realtek AmebaZ
|
||||
`RTL8720C` | 0xE08F7564 | Realtek AmebaZ2
|
||||
`RTL8720D` | 0x3379CFE2 | Realtek AmebaD
|
||||
`BK7231T` | 0x675A40B0 | Beken 7231T
|
||||
`BK7231N` | 0x7B3EF230 | Beken 7231N
|
||||
`BL602` | 0xDE1270B7 | Boufallo 602
|
||||
`XR809` | 0x51E903A8 | Xradiotech 809
|
||||
|
||||
## Extension tags
|
||||
|
||||
Standard tags are used: `VERSION`, `DEVICE` and `DEVICE_ID`.
|
||||
|
||||
Additionally, custom tags are defined:
|
||||
|
||||
Name | ID | Type | Description
|
||||
--------------|----------|------------|-------------------------------------------------
|
||||
`OTA_VERSION` | 0x5D57D0 | int 8-bit | format version (for simple compatibility checks)
|
||||
`BOARD` | 0xCA25C8 | string | board name / code (lowercase)
|
||||
`FIRMWARE` | 0x00DE43 | string | firmware description / name
|
||||
`BUILD_DATE` | 0x822F30 | int 32-bit | build date/time as Unix timestamp
|
||||
`LT_VERSION` | 0x59563D | semver | LT version
|
||||
`LT_PART_1` | 0x805946 | string | OTA1 partition name
|
||||
`LT_PART_2` | 0xA1E4D7 | string | OTA2 partition name
|
||||
`LT_HAS_OTA1` | 0xBBD965 | bool 8-bit | image has any data for OTA1
|
||||
`LT_HAS_OTA2` | 0x92280E | bool 8-bit | image has any data for OTA2
|
||||
`LT_BINPATCH` | 0xB948DE | bytes | binary patch to convert OTA1->OTA2
|
||||
|
||||
## Update types
|
||||
|
||||
### Single OTA scheme (1, 2)
|
||||
|
||||
Image is ignored if the OTA scheme does not match. UF2 has `LT_PART_1` or `LT_PART_2` set to target partition name. The other partition tag is present, but empty (0 bytes).
|
||||
|
||||
```
|
||||
08 46 59 80 6f 74 61 31 | .FY.ota1 | LT_PART_1
|
||||
04 d7 e4 a1 | .... | LT_PART_2
|
||||
```
|
||||
|
||||
### Dual-OTA/single-file scheme (3, 4)
|
||||
|
||||
One image is used for both OTA schemes. UF2 has `LT_PART_1` and `LT_PART_2` tags set. For type `3` these two tags contain the same partition name.
|
||||
|
||||
```
|
||||
08 46 59 80 6f 74 61 31 | .FY.ota1 | LT_PART_1
|
||||
08 d7 e4 a1 6f 74 61 32 | ....ota2 | LT_PART_2
|
||||
```
|
||||
|
||||
### Dual-OTA/dual-file scheme (5, 6)
|
||||
|
||||
Just like types `3` and `4`, UF2 has two partition tags set. For type `5` they have the same name.
|
||||
|
||||
The image stored in UF2 is meant for OTA1 scheme. There is an additional tag `LT_BINPATCH` present. In OTA1 flashing scheme, it is ignored.
|
||||
|
||||
## Binary patching
|
||||
|
||||
OTA2 images are not stored directly, as that would needlessly double the UF2 file size. Instead, binary patching instructions, embedded into the extension tags area, allow the CPU to convert the OTA1 image from UF2 into OTA2 image.
|
||||
|
||||
There can be at most one binpatch tag in a UF2 block. It has the following format:
|
||||
|
||||
- opcode (1 byte) - operation type:
|
||||
|
||||
- `DIFF32` (0xFE) - difference between 32-bit values
|
||||
|
||||
- length (1 byte) - data length
|
||||
- data (`length` bytes)
|
||||
|
||||
- for `DIFF32`:
|
||||
|
||||
- difference value (signed int 32-bit)
|
||||
|
||||
- offset table (`length-4` bytes)
|
||||
|
||||
The presented structure can be repeated in a single binpatch tag.
|
||||
|
||||
### DIFF32
|
||||
|
||||
This method works by adding the difference value to a 32-bit integer. It allows to save the most space in OTA1/2 image scenarios, where the only different values are, for example, flash memory addresses. The offset table contains positions within the 256-byte block, to which the difference value should be mathematically added.
|
||||
|
||||
For a block like:
|
||||
```
|
||||
000 72 71 73 61 76 65 00 00 5f 66 72 65 65 72 74 6f |rqsave.._freerto|
|
||||
010 73 5f 6d 75 74 65 78 5f 67 65 74 5f 74 69 6d 65 |s_mutex_get_time|
|
||||
020 6f 75 74 00 5d a4 03 08 61 a4 03 08 85 a4 03 08 |out.]...a.......|
|
||||
030 5d a4 03 08 61 a4 03 08 85 a4 03 08 81 a9 03 08 |]...a...........|
|
||||
040 6d a9 03 08 7d a4 03 08 d9 a8 03 08 05 a7 03 08 |m...}...........|
|
||||
050 bd a4 03 08 ad a8 03 08 59 a7 03 08 9d a8 03 08 |........Y.......|
|
||||
060 01 a7 03 08 51 a8 03 08 21 aa 03 08 b9 a4 03 08 |....Q...!.......|
|
||||
070 85 a3 03 08 89 a3 03 08 4d a4 03 08 a1 a8 03 08 |........M.......|
|
||||
080 00 00 00 00 00 00 00 00 19 a8 03 08 c1 a4 03 08 |................|
|
||||
090 8d a8 03 08 ed a6 03 08 dd a7 03 08 ad a4 03 08 |................|
|
||||
0a0 9d a7 03 08 95 a4 03 08 81 a7 03 08 09 a7 03 08 |................|
|
||||
0b0 31 a7 03 08 d1 a6 03 08 dd a5 03 08 61 aa 03 08 |1...........a...|
|
||||
0c0 c5 a2 03 08 d5 a2 03 08 d9 a2 03 08 b1 a6 03 08 |................|
|
||||
0d0 65 aa 03 08 ad a6 03 08 a9 a6 03 08 8d a6 03 08 |e...............|
|
||||
0e0 e5 a2 03 08 e9 a2 03 08 1d a4 03 08 ed a3 03 08 |................|
|
||||
0f0 35 a4 03 08 05 a4 03 08 bd a3 03 08 8d a3 03 08 |5...............|
|
||||
```
|
||||
|
||||
a DIFF32 patch containing:
|
||||
```
|
||||
fe 39 00 50 0c 00 24 28 2c 30 34 38 3c 40 44 48 |.9.P..$(,048<@DH|
|
||||
4c 50 54 58 5c 60 64 68 6c 70 74 78 7c 88 8c 90 |LPTX\`dhlptx|...|
|
||||
94 98 9c a0 a4 a8 ac b0 b4 b8 bc c0 c4 c8 cc d0 |................|
|
||||
d4 d8 dc e0 e4 e8 ec f0 f4 f8 fc |........... |
|
||||
```
|
||||
|
||||
adds 0x000C5000 to 53 values, producing OTA2 output like this:
|
||||
```
|
||||
000 72 71 73 61 76 65 00 00 5f 66 72 65 65 72 74 6f |rqsave.._freerto|
|
||||
010 73 5f 6d 75 74 65 78 5f 67 65 74 5f 74 69 6d 65 |s_mutex_get_time|
|
||||
020 6f 75 74 00 5d f4 0f 08 61 f4 0f 08 85 f4 0f 08 |out.]...a.......|
|
||||
030 5d f4 0f 08 61 f4 0f 08 85 f4 0f 08 81 f9 0f 08 |]...a...........|
|
||||
040 6d f9 0f 08 7d f4 0f 08 d9 f8 0f 08 05 f7 0f 08 |m...}...........|
|
||||
050 bd f4 0f 08 ad f8 0f 08 59 f7 0f 08 9d f8 0f 08 |........Y.......|
|
||||
060 01 f7 0f 08 51 f8 0f 08 21 fa 0f 08 b9 f4 0f 08 |....Q...!.......|
|
||||
070 85 f3 0f 08 89 f3 0f 08 4d f4 0f 08 a1 f8 0f 08 |........M.......|
|
||||
080 00 00 00 00 00 00 00 00 19 f8 0f 08 c1 f4 0f 08 |................|
|
||||
090 8d f8 0f 08 ed f6 0f 08 dd f7 0f 08 ad f4 0f 08 |................|
|
||||
0a0 9d f7 0f 08 95 f4 0f 08 81 f7 0f 08 09 f7 0f 08 |................|
|
||||
0b0 31 f7 0f 08 d1 f6 0f 08 dd f5 0f 08 61 fa 0f 08 |1...........a...|
|
||||
0c0 c5 f2 0f 08 d5 f2 0f 08 d9 f2 0f 08 b1 f6 0f 08 |................|
|
||||
0d0 65 fa 0f 08 ad f6 0f 08 a9 f6 0f 08 8d f6 0f 08 |e...............|
|
||||
0e0 e5 f2 0f 08 e9 f2 0f 08 1d f4 0f 08 ed f3 0f 08 |................|
|
||||
0f0 35 f4 0f 08 05 f4 0f 08 bd f3 0f 08 8d f3 0f 08 |5...............|
|
||||
```
|
||||
58
docs/ota/library.md
Normal file
58
docs/ota/library.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# uf2ota library
|
||||
|
||||
uf2ota library allows to write a LibreTuya UF2 file to the flash, while parsing all the necessary tags. It manages the target partitions, compatibility checks, and works on top of the FAL provided by FlashDB.
|
||||
|
||||
## Usage example
|
||||
|
||||
```c
|
||||
uint8_t target = 1; // target OTA scheme - 1 or 2
|
||||
uint32_t family = RTL8710B; // chip's UF2 family ID
|
||||
uf2_ota_t *ctx = uf2_ctx_init(target, family);
|
||||
uf2_info_t *info = uf2_info_init(); // optional, for getting firmware info
|
||||
uf2_block_t *block = (uf2_block_t *)malloc(UF2_BLOCK_SIZE);
|
||||
uf2_err_t err;
|
||||
|
||||
// ... // read the first header block (512 bytes) into *block
|
||||
|
||||
// check the block for validity
|
||||
err = uf2_check_block(ctx, block);
|
||||
if (err > UF2_ERR_IGNORE)
|
||||
// handle the error
|
||||
return;
|
||||
|
||||
// parse the header block
|
||||
// note: if you don't need info, you can skip this step and call uf2_write() directly
|
||||
err = uf2_parse_header(ctx, block, info);
|
||||
if (err)
|
||||
// handle the error
|
||||
return;
|
||||
|
||||
while (/* have input data */) {
|
||||
|
||||
// ... // read the next block into *block
|
||||
|
||||
// check the block for validity
|
||||
err = uf2_check_block(ctx, block);
|
||||
if (err == UF2_ERR_IGNORE)
|
||||
// skip this block
|
||||
continue;
|
||||
if (err)
|
||||
// handle the error
|
||||
return;
|
||||
|
||||
// write the block to flash
|
||||
err = uf2_write(ctx, block);
|
||||
if (err > UF2_ERR_IGNORE)
|
||||
// handle the error
|
||||
return;
|
||||
}
|
||||
|
||||
// finish the update process
|
||||
|
||||
// ... // activate your new OTA partition
|
||||
|
||||
// cleanup
|
||||
free(ctx);
|
||||
free(block);
|
||||
uf2_info_free(info);
|
||||
```
|
||||
73
docs/ota/uf2ota.md
Normal file
73
docs/ota/uf2ota.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# uf2ota.py
|
||||
|
||||
This is a tool for converting LibreTuya firmware images to UF2 format for OTA updates.
|
||||
|
||||
```bash
|
||||
$ python uf2ota.py
|
||||
usage: uf2ota [-h] [--output OUTPUT] [--family FAMILY] [--board BOARD] [--version VERSION] [--fw FW] {info,dump,write} inputs [inputs ...]
|
||||
uf2ota: error: the following arguments are required: action, inputs
|
||||
```
|
||||
|
||||
# write
|
||||
|
||||
Generate a UF2 file from a firmware image or several images.
|
||||
|
||||
```bash
|
||||
$ python uf2ota.py write --family RTL8710B --board wr3 --version 0.4.0 --fw esphome:2022.6.0-dev "ota1;xip1.bin;ota2;xip2.bin"
|
||||
|
||||
$ ls -l out.uf2
|
||||
-rw-r--r-- 1 Kuba None 605696 May 28 14:35 out.uf2
|
||||
```
|
||||
|
||||
## inputs format
|
||||
|
||||
Format for `inputs` parameter is `part;file[;part;file]` (square brackets mean optional). First two (colon separated) values correspond to flashing OTA1 region, second two to OTA2.
|
||||
|
||||
Partition name can be suffixed by `+offset`, which causes writing the image file to the partition after some byte offset. Both files and/or partition names can be equal. Values can be empty (like `part;file;;` or `;;part;file`) if OTA1/2 images are not present in this file.
|
||||
|
||||
When using two different firmware binaries, they need to have the same `offset` and be of the same size.
|
||||
|
||||
`inputs` parameter can be repeated in order to embed multiple files in the UF2. For example:
|
||||
```bash
|
||||
"bootloader;boot.bin" "ota1;xip1.bin;ota2;xip2.bin" "config;config1.bin;config;config2.bin"
|
||||
```
|
||||
will:
|
||||
- flash the bootloader in both OTA schemes
|
||||
- flash `xip1.bin` or `xip2.bin` to `ota1` or `ota2` partitions
|
||||
- flash `config1.bin` or `config2.bin` to `config` partition
|
||||
|
||||
# info
|
||||
|
||||
This command shows some basic parameters of a UF2 image.
|
||||
|
||||
```bash
|
||||
$ python uf2ota.py info out.uf2
|
||||
Family: RTL8710B
|
||||
Tags:
|
||||
- BOARD: wr3
|
||||
- DEVICE_ID: 312d5ec5
|
||||
- LT_VERSION: 0.4.0
|
||||
- FIRMWARE: esphome
|
||||
- VERSION: 2022.6.0-dev
|
||||
- OTA_VERSION: 01
|
||||
- DEVICE: LibreTuya
|
||||
- LT_HAS_OTA1: 01
|
||||
- LT_HAS_OTA2: 01
|
||||
- LT_PART_1: ota1
|
||||
- LT_PART_2: ota2
|
||||
- LT_BINPATCH: fe0900500c009094989ca0
|
||||
Data chunks: 1182
|
||||
Total binary size: 302448
|
||||
```
|
||||
|
||||
# dump
|
||||
|
||||
Dump UF2 file (only LibreTuya format) into separate firmware binaries.
|
||||
|
||||
```bash
|
||||
$ python uf2ota.py dump out.uf2
|
||||
|
||||
$ ls -1 out.uf2_dump/
|
||||
esphome_2022.6.0-dev_lt0.4.0_wr3_1_ota1_0x0.bin
|
||||
esphome_2022.6.0-dev_lt0.4.0_wr3_2_ota2_0x0.bin
|
||||
```
|
||||
26
docs/platform/realtek/README.md
Normal file
26
docs/platform/realtek/README.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Realtek Ameba - notes
|
||||
|
||||
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.
|
||||
38
docs/project-structure.md
Normal file
38
docs/project-structure.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Project structure
|
||||
|
||||
```
|
||||
arduino/
|
||||
├─ <family name>/ Arduino Core for specific SoC
|
||||
│ ├─ cores/ Wiring core files
|
||||
│ ├─ libraries/ Supported built-in family libraries
|
||||
├─ libretuya/
|
||||
│ ├─ api/ Library interfaces
|
||||
│ ├─ common/ Units common to all families
|
||||
│ ├─ compat/ Fixes for compatibility with ESP32 framework
|
||||
│ ├─ core/ LibreTuya API for Arduino cores
|
||||
│ ├─ libraries/ Built-in family-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
|
||||
│ ├─ <family name>-sdk.py Vanilla SDK build system
|
||||
│ ├─ <family name>-arduino.py Arduino Core build system
|
||||
├─ arduino-common.py Builder to provide ArduinoCore-API and LibreTuya APIs
|
||||
├─ main.py Main PlatformIO builder
|
||||
├─ utils.py SCons utils used during the build
|
||||
docs/ Project documentation, guides, tips, etc.
|
||||
platform/
|
||||
├─ <family name>/ Family-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
|
||||
families.json List of supported device families
|
||||
platform.json PlatformIO manifest
|
||||
platform.py Custom PlatformIO script
|
||||
```
|
||||
41
docs/reference/lt-api.md
Normal file
41
docs/reference/lt-api.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# LibreTuya API
|
||||
|
||||
## Class functions
|
||||
|
||||
{%
|
||||
include-markdown "../../ltapi/class_libre_tuya.md"
|
||||
start="(class_libre_tuya.md)\n"
|
||||
end="[More...]"
|
||||
%}
|
||||
|
||||
{%
|
||||
include-markdown "../../ltapi/class_libre_tuya.md"
|
||||
start="# Detailed Description\n"
|
||||
end="## Public Functions Documentation\n"
|
||||
%}
|
||||
|
||||
{%
|
||||
include-markdown "../../ltapi/class_libre_tuya.md"
|
||||
start="## Public Functions\n"
|
||||
end="# Detailed Description\n"
|
||||
%}
|
||||
|
||||
## Static
|
||||
|
||||
### Public Attributes
|
||||
|
||||
{%
|
||||
include-markdown "../../ltapi/_libre_tuya_a_p_i_8h.md"
|
||||
start="## Public Attributes\n"
|
||||
end="## Public Attributes Documentation\n"
|
||||
heading-offset=1
|
||||
%}
|
||||
|
||||
## Logger
|
||||
|
||||
{%
|
||||
include-markdown "../../ltapi/lt__logger_8h.md"
|
||||
start="## Public Functions\n"
|
||||
end="## Public Functions Documentation\n"
|
||||
heading-offset=1
|
||||
%}
|
||||
@@ -1 +1,5 @@
|
||||
mkdocs-same-dir
|
||||
mkdocs-literate-nav
|
||||
mkdocs-section-index
|
||||
mkdocs-include-markdown-plugin
|
||||
-e git+https://github.com/kuba2k2/mkdoxy#egg=mkdoxy
|
||||
|
||||
54
docs/resources.md
Normal file
54
docs/resources.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Resources
|
||||
|
||||
## Realtek
|
||||
|
||||
Code | Name
|
||||
-------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
| From **amb1_sdk**
|
||||
AN0004 | [Realtek low power wi-fi mp user guide](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/AN0004%20Realtek%20low%20power%20wi-fi%20mp%20user%20guide.pdf)
|
||||
AN0011 | [Realtek wlan simple configuration](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/AN0011%20Realtek%20wlan%20simple%20configuration.pdf)
|
||||
AN0012 | [Realtek secure socket layer(ssl)](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/AN0012%20Realtek%20secure%20socket%20layer(ssl).pdf)
|
||||
AN0025 | [Realtek at command](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/AN0025%20Realtek%20at%20command.pdf)
|
||||
AN0033 | [Realtek Ameba-1 over the air firmware update](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/AN0033%20Realtek%20Ameba-1%20over%20the%20air%20firmware%20update.pdf)
|
||||
AN0045 | [Realtek Ameba-1 power modes](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/AN0045%20Realtek%20Ameba-1%20power%20modes.pdf)
|
||||
AN0046 | [Realtek Ameba uart adapter](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/AN0046%20Realtek%20Ameba%20uart%20adapter.pdf)
|
||||
AN0060 | [Realtek UART update user manual](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/AN0060%20Realtek%20UART%20update%20user%20manual.pdf)
|
||||
AN0075 | [Realtek Ameba-all at command v2.0](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/AN0075%20Realtek%20Ameba-all%20at%20command%20v2.0.pdf)
|
||||
AN0096 | [Realtek xmodem UART update user manual](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/AN0096%20Realtek%20xmodem%20UART%20update%20user%20manual.pdf)
|
||||
AN0110 | [Realtek Ameba-Z over the air firmware update](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/AN0110%20Realtek%20Ameba-Z%20over%20the%20air%20firmware%20update.pdf)
|
||||
AN0111 | [Realtek Ameba-Z FreeRTOS tickless](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/AN0111%20Realtek%20Ameba-Z%20FreeRTOS%20tickless.pdf)
|
||||
UM0006 | [Realtek wificonf application programming interface](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/UM0006%20Realtek%20wificonf%20application%20programming%20interface.pdf)
|
||||
UM0014 | [Realtek web server user guide](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/UM0014%20Realtek%20web%20server%20user%20guide.pdf)
|
||||
UM0023 | [Realtek Ameba-1 build environment setup - iar](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/UM0023%20Realtek%20Ameba-1%20build%20environment%20setup%20-%20iar.pdf)
|
||||
UM0027 | [Realtek Ameba-1 crypto engine](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/UM0027%20Realtek%20Ameba-1%20crypto%20engine.pdf)
|
||||
UM0034 | [Realtek Ameba-1 memory layout](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/UM0034%20Realtek%20Ameba-1%20memory%20layout.pdf)
|
||||
UM0039 | [Realtek Ameba-1 SDK quick start](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/UM0039%20Realtek%20Ameba-1%20SDK%20quick%20start.pdf)
|
||||
UM0048 | [Realtek Ameba1 DEV 1v0 User Manual_1v8_20160328](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/UM0048%20Realtek%20Ameba1%20DEV%201v0%20User%20Manual_1v8_20160328.pdf)
|
||||
UM0060 | [Realtek Ameba-1 mqtt user guide](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/UM0060%20Realtek%20Ameba-1%20mqtt%20user%20guide.pdf)
|
||||
UM0096 | [Realtek Ameba build environment setup - gcc](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/UM0096%20Realtek%20Ameba%20build%20environment%20setup%20-%20gcc.pdf)
|
||||
UM0096 | [Realtek Ameba-1 build environment setup - gcc](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/UM0096%20Realtek%20Ameba-1%20build%20environment%20setup%20-%20gcc.pdf)
|
||||
UM0101 | [Realtek Ameba-1 peripheral developerment user manual](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/UM0101%20Realtek%20Ameba-1%20peripheral%20developerment%20user%20manual.pdf)
|
||||
UM0110 | [Realtek Ameba-Z build environment setup - iar](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/UM0110%20Realtek%20Ameba-Z%20build%20environment%20setup%20-%20iar.pdf)
|
||||
UM0111 | [Realtek Ameba-Z memory layout](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/UM0111%20Realtek%20Ameba-Z%20memory%20layout.pdf)
|
||||
UM0112 | [Realtek Ameba-Z SDK quick start](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/UM0112%20Realtek%20Ameba-Z%20SDK%20quick%20start.pdf)
|
||||
UM0113 | [Realtek Ameba-Z DEV 1v0 User Manual](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/UM0113%20Realtek%20Ameba-Z%20DEV%201v0%20User%20Manual.pdf)
|
||||
UM0115 | [Realtek Ameba-Z Introduction](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/UM0115%20Realtek%20Ameba-Z%20Introduction.pdf)
|
||||
UM0116 | [Realtek Ameba-Z SDK change](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/UM0116%20Realtek%20Ameba-Z%20SDK%20change.pdf)
|
||||
UM0120 | [Realtek Ameba-Z User Configuration](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/UM0120%20Realtek%20Ameba-Z%20User%20Configuration.pdf)
|
||||
UM0121 | [Realtek Ameba-Z suspend resume api](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/UM0121%20Realtek%20Ameba-Z%20suspend%20resume%20api.pdf)
|
||||
UM0123 | [Realtek Ameba-Z power modes](https://raw.githubusercontent.com/ambiot/amb1_sdk/0c8da639b097f01c60e419405aecfafab1d08e43/doc/UM0123%20Realtek%20Ameba-Z%20power%20modes.pdf)
|
||||
| From **ambd_sdk**
|
||||
AN0004 | [Realtek low power wi-fi mp user guide](https://raw.githubusercontent.com/ambiot/ambd_sdk/12dab4363fd0087eb4874461f8d3f6094110595f/doc/AN0004%20Realtek%20low%20power%20wi-fi%20mp%20user%20guide.pdf)
|
||||
AN0011 | [Realtek wlan simple configuration](https://raw.githubusercontent.com/ambiot/ambd_sdk/12dab4363fd0087eb4874461f8d3f6094110595f/doc/AN0011%20Realtek%20wlan%20simple%20configuration.pdf)
|
||||
AN0012 | [Realtek secure socket layer(ssl)](https://raw.githubusercontent.com/ambiot/ambd_sdk/12dab4363fd0087eb4874461f8d3f6094110595f/doc/AN0012%20Realtek%20secure%20socket%20layer(ssl).pdf)
|
||||
AN0025 | [Realtek at command](https://raw.githubusercontent.com/ambiot/ambd_sdk/12dab4363fd0087eb4874461f8d3f6094110595f/doc/AN0025%20Realtek%20at%20command.pdf)
|
||||
AN0075 | [Realtek Ameba-all at command v2.0](https://raw.githubusercontent.com/ambiot/ambd_sdk/12dab4363fd0087eb4874461f8d3f6094110595f/doc/AN0075%20Realtek%20Ameba-all%20at%20command%20v2.0.pdf)
|
||||
AN0096 | [Realtek Ameba-all xmodem uart update firmware](https://raw.githubusercontent.com/ambiot/ambd_sdk/12dab4363fd0087eb4874461f8d3f6094110595f/doc/AN0096%20Realtek%20Ameba-all%20xmodem%20uart%20update%20firmware.pdf)
|
||||
AN0400 | [Ameba-D Application Note](https://raw.githubusercontent.com/ambiot/ambd_sdk/12dab4363fd0087eb4874461f8d3f6094110595f/doc/AN0400%20Ameba-D%20Application%20Note.pdf)
|
||||
UM0150 | [Realtek Ameba CoAP User Guide](https://raw.githubusercontent.com/ambiot/ambd_sdk/12dab4363fd0087eb4874461f8d3f6094110595f/doc/UM0150%20Realtek%20Ameba%20CoAP%20User%20Guide.pdf)
|
||||
UM0201 | [Ameba Common BT Application User Manual EN](https://raw.githubusercontent.com/ambiot/ambd_sdk/12dab4363fd0087eb4874461f8d3f6094110595f/doc/UM0201%20Ameba%20Common%20BT%20Application%20User%20Manual%20EN.pdf)
|
||||
| Found elsewhere
|
||||
AN0400 | [Ameba-D Application Note_v3_watermark](https://files.seeedstudio.com/products/102110419/Basic%20documents/AN0400%20Ameba-D%20Application%20Note_v3_watermark.pdf)
|
||||
AN0500 | [Realtek Ameba-ZII application note](https://www.e-paper-display.com/99IOT/00015797-AN0500-Realtek-Ameba-ZII-application-note.en_233850.pdf)
|
||||
UM0114 | [Realtek Ameba-Z datasheet v3.4](https://adelectronicsru.files.wordpress.com/2018/10/um0114-realtek-ameba-z-data-sheet-v3-4.pdf)
|
||||
| [Product pages / realtek.com](https://www.realtek.com/en/products/communications-network-ics/category/802-11b-g-n)
|
||||
50
families.json
Normal file
50
families.json
Normal file
@@ -0,0 +1,50 @@
|
||||
[
|
||||
{
|
||||
"id": "0x9FFFD543",
|
||||
"short_name": "RTL8710A",
|
||||
"description": "Realtek Ameba1"
|
||||
},
|
||||
{
|
||||
"id": "0x22E0D6FC",
|
||||
"short_name": "RTL8710B",
|
||||
"description": "Realtek AmebaZ",
|
||||
"name": "realtek-ambz",
|
||||
"code": "ambz",
|
||||
"url": "https://www.amebaiot.com/en/amebaz/",
|
||||
"sdk": "https://github.com/ambiot/amb1_sdk",
|
||||
"framework": "framework-realtek-amb1",
|
||||
"mcus": [
|
||||
"RTL87xxB"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "0xE08F7564",
|
||||
"short_name": "RTL8720C",
|
||||
"description": "Realtek AmebaZ2"
|
||||
},
|
||||
{
|
||||
"id": "0x3379CFE2",
|
||||
"short_name": "RTL8720D",
|
||||
"description": "Realtek AmebaD"
|
||||
},
|
||||
{
|
||||
"id": "0x675A40B0",
|
||||
"short_name": "BK7231T",
|
||||
"description": "Beken 7231T"
|
||||
},
|
||||
{
|
||||
"id": "0x7B3EF230",
|
||||
"short_name": "BK7231N",
|
||||
"description": "Beken 7231N"
|
||||
},
|
||||
{
|
||||
"id": "0xDE1270B7",
|
||||
"short_name": "BL602",
|
||||
"description": "Boufallo 602"
|
||||
},
|
||||
{
|
||||
"id": "0x51E903A8",
|
||||
"short_name": "XR809",
|
||||
"description": "Xradiotech 809"
|
||||
}
|
||||
]
|
||||
38
mkdocs.yml
38
mkdocs.yml
@@ -1,26 +1,32 @@
|
||||
site_name: LibreTuya
|
||||
docs_dir: .
|
||||
|
||||
site_url: https://kuba2k2.github.io/libretuya/
|
||||
repo_url: https://github.com/kuba2k2/libretuya
|
||||
|
||||
theme:
|
||||
name: material
|
||||
|
||||
plugins:
|
||||
- same-dir
|
||||
- mkdoxy:
|
||||
projects:
|
||||
# project names must be alphanumeric, else snippets won't work
|
||||
ltapi:
|
||||
src-dirs: arduino/libretuya/
|
||||
doxy-cfg:
|
||||
PREDEFINED: __cplusplus
|
||||
CASE_SENSE_NAMES: NO
|
||||
ltambz:
|
||||
src-dirs: arduino/realtek-ambz/
|
||||
doxy-cfg:
|
||||
PREDEFINED: __cplusplus
|
||||
CASE_SENSE_NAMES: NO
|
||||
save-api: .
|
||||
- literate-nav:
|
||||
nav_file: SUMMARY.md
|
||||
- section-index
|
||||
- include-markdown
|
||||
|
||||
markdown_extensions:
|
||||
- md_in_html
|
||||
|
||||
nav:
|
||||
- "Home": "README.md"
|
||||
- "Configuration": "docs/config.md"
|
||||
- "Libraries":
|
||||
- "Built-in": "docs/libs-built-in.md"
|
||||
- "Third party": "docs/libs-3rd-party.md"
|
||||
- "Platforms":
|
||||
- "Realtek AmebaZ Series":
|
||||
- "Boards":
|
||||
- "WR3": "boards/wr3/README.md"
|
||||
- "C library":
|
||||
- "Built-in functions": "docs/platform/realtek-ambz/stdlib.md"
|
||||
- "Memory management": "docs/platform/realtek-ambz/memory-management.md"
|
||||
- "Debugging": "docs/platform/realtek/debugging.md"
|
||||
- "Exception decoder": "docs/platform/realtek/exception-decoder.md"
|
||||
|
||||
@@ -6,8 +6,12 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/kuba2k2/platformio-libretuya"
|
||||
},
|
||||
"version": "0.3.0",
|
||||
"version": "0.5.0",
|
||||
"frameworks": {
|
||||
"arduino": {
|
||||
"title": "Generic Arduino framework",
|
||||
"script": "builder/frameworks/arduino.py"
|
||||
},
|
||||
"realtek-ambz-sdk": {
|
||||
"tilte": "Realtek AmebaZ - SDK",
|
||||
"package": "framework-realtek-amb1",
|
||||
@@ -26,6 +30,11 @@
|
||||
"version": "https://github.com/ambiot/amb1_sdk",
|
||||
"manifest": {
|
||||
"description": "SDK for Ameba1"
|
||||
},
|
||||
"libraries": {
|
||||
"lwip": [
|
||||
"v2.0.0-amb1"
|
||||
]
|
||||
}
|
||||
},
|
||||
"framework-arduino-api": {
|
||||
@@ -34,6 +43,27 @@
|
||||
"version": "https://github.com/arduino/ArduinoCore-API",
|
||||
"manifest": {
|
||||
"description": "Hardware independent layer of the Arduino cores"
|
||||
},
|
||||
"libraries": {
|
||||
"flashdb": [
|
||||
"03500fa"
|
||||
]
|
||||
}
|
||||
},
|
||||
"library-lwip": {
|
||||
"type": "framework",
|
||||
"optional": true,
|
||||
"base_url": "https://github.com/libretuya/lwip",
|
||||
"manifest": {
|
||||
"description": "lwIP - A Lightweight TCPIP stack"
|
||||
}
|
||||
},
|
||||
"library-flashdb": {
|
||||
"type": "framework",
|
||||
"optional": true,
|
||||
"base_url": "https://github.com/armink/FlashDB",
|
||||
"manifest": {
|
||||
"description": "An ultra-lightweight database that supports key-value and time series data"
|
||||
}
|
||||
},
|
||||
"toolchain-gccarmnoneeabi": {
|
||||
|
||||
96
platform.py
96
platform.py
@@ -1,7 +1,10 @@
|
||||
# Copyright (c) Kuba Szczodrzyński 2022-04-20.
|
||||
|
||||
from os.path import dirname
|
||||
import json
|
||||
from os.path import dirname, join
|
||||
from typing import Dict
|
||||
|
||||
from platformio import util
|
||||
from platformio.debug.config.base import DebugConfigBase
|
||||
from platformio.debug.exception import DebugInvalidOptionsError
|
||||
from platformio.managers.platform import PlatformBase
|
||||
@@ -35,13 +38,17 @@ def load_manifest(self, src):
|
||||
manifest: dict = libretuya_packages[spec.name]
|
||||
# find additional manifest info
|
||||
manifest = manifest.get("manifest", manifest_default)
|
||||
# extract tag version
|
||||
url = getattr(spec, "url", None) or getattr(spec, "uri", None) or ""
|
||||
if "#" in url:
|
||||
manifest["version"] = url.rpartition("#")[2].lstrip("v")
|
||||
# put info from spec
|
||||
manifest.update(
|
||||
{
|
||||
"name": spec.name,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": spec.url,
|
||||
"url": url,
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -49,6 +56,8 @@ def load_manifest(self, src):
|
||||
cache_key = "load_manifest-%s" % path
|
||||
self.memcache_set(cache_key, manifest)
|
||||
# result = ManifestParserFactory.new(json.dumps(manifest), ManifestFileType.PACKAGE_JSON).as_dict()
|
||||
with open(join(path, self.manifest_names[0]), "w") as f:
|
||||
json.dump(manifest, f)
|
||||
return manifest
|
||||
|
||||
|
||||
@@ -67,6 +76,8 @@ def find_pkg_root(self, path: str, spec: PackageSpec):
|
||||
|
||||
|
||||
class LibretuyaPlatform(PlatformBase):
|
||||
boards_base: Dict[str, dict] = {}
|
||||
|
||||
def configure_default_packages(self, options, targets):
|
||||
framework = options.get("pioframework")[0]
|
||||
# patch find_pkg root to ignore missing manifests and save PackageSpec
|
||||
@@ -78,6 +89,15 @@ class LibretuyaPlatform(PlatformBase):
|
||||
BasePackageManager._load_manifest = BasePackageManager.load_manifest
|
||||
BasePackageManager.load_manifest = load_manifest
|
||||
|
||||
# allow using "arduino" as framework
|
||||
if framework == "arduino":
|
||||
board = self.get_boards(options.get("board"))
|
||||
frameworks = board.get("frameworks")
|
||||
framework = next(fw for fw in frameworks if framework in fw)
|
||||
options.get("pioframework")[0] = framework
|
||||
|
||||
framework_obj = self.frameworks[framework]
|
||||
|
||||
# set specific compiler versions
|
||||
if framework.startswith("realtek-ambz"):
|
||||
self.packages["toolchain-gccarmnoneeabi"]["version"] = "~1.50401.0"
|
||||
@@ -86,6 +106,37 @@ class LibretuyaPlatform(PlatformBase):
|
||||
if "arduino" in framework:
|
||||
self.packages["framework-arduino-api"]["optional"] = False
|
||||
|
||||
# mark framework SDK as required
|
||||
self.packages[framework_obj["package"]]["optional"] = False
|
||||
|
||||
# gather library dependencies
|
||||
libraries = framework_obj["libraries"] if "libraries" in framework_obj else {}
|
||||
for name, package in self.packages.items():
|
||||
if "optional" in package and package["optional"]:
|
||||
continue
|
||||
if "libraries" not in package:
|
||||
continue
|
||||
libraries.update(package["libraries"])
|
||||
|
||||
# use appropriate vendor library versions
|
||||
packages_new = {}
|
||||
for name, package in self.packages.items():
|
||||
if not name.startswith("library-"):
|
||||
continue
|
||||
name = name[8:] # strip "library-"
|
||||
if name not in libraries:
|
||||
continue
|
||||
lib_version = libraries[name][-1] # get latest version tag
|
||||
package = dict(**package) # clone the base package
|
||||
package["version"] = (
|
||||
package["base_url"] + "#" + lib_version
|
||||
) # use the specific version
|
||||
package["optional"] = False # make it required
|
||||
lib_version = lib_version.lstrip("v") # strip "v" in target name
|
||||
name = f"library-{name}@{lib_version}"
|
||||
packages_new[name] = package # put the package under a new name
|
||||
self.packages.update(packages_new)
|
||||
|
||||
# save platform packages for later
|
||||
global libretuya_packages
|
||||
libretuya_packages = self.packages
|
||||
@@ -97,13 +148,40 @@ class LibretuyaPlatform(PlatformBase):
|
||||
if not result:
|
||||
return result
|
||||
if id_:
|
||||
return self._add_default_debug_tools(result)
|
||||
return self.update_board(result)
|
||||
else:
|
||||
for key, value in result.items():
|
||||
result[key] = self._add_default_debug_tools(value)
|
||||
result[key] = self.update_board(value)
|
||||
return result
|
||||
|
||||
def _add_default_debug_tools(self, board: PlatformBoardConfig):
|
||||
def update_board(self, board: PlatformBoardConfig):
|
||||
|
||||
if "_base" in board:
|
||||
base = board.get("_base")
|
||||
if not isinstance(base, list):
|
||||
base = [base]
|
||||
|
||||
result = None
|
||||
for base_name in base:
|
||||
if base_name not in self.boards_base:
|
||||
file = join(
|
||||
dirname(__file__), "boards", "_base", f"{base_name}.json"
|
||||
)
|
||||
with open(file, encoding="utf-8") as f:
|
||||
self.boards_base[base_name] = json.load(f)
|
||||
|
||||
if not result:
|
||||
result = self.boards_base[base_name]
|
||||
else:
|
||||
util.merge_dicts(result, self.boards_base[base_name])
|
||||
util.merge_dicts(result, board._manifest)
|
||||
board._manifest = result
|
||||
|
||||
# add "arduino" framework
|
||||
has_arduino = any("arduino" in fw for fw in board.manifest["frameworks"])
|
||||
if has_arduino:
|
||||
board.manifest["frameworks"].append("arduino")
|
||||
|
||||
# inspired by platform-ststm32/platform.py
|
||||
debug = board.manifest.get("debug", {})
|
||||
if not debug:
|
||||
@@ -123,7 +201,7 @@ class LibretuyaPlatform(PlatformBase):
|
||||
args.extend(
|
||||
[
|
||||
"-f",
|
||||
"$LTPATH/platform/$LTPLATFORM/openocd/%s"
|
||||
"$LTPATH/platform/$LTFAMILY/openocd/%s"
|
||||
% debug.get("openocd_config"),
|
||||
]
|
||||
)
|
||||
@@ -148,7 +226,7 @@ class LibretuyaPlatform(PlatformBase):
|
||||
opts = debug_config.env_options
|
||||
server = debug_config.server
|
||||
lt_path = dirname(__file__)
|
||||
lt_platform = opts["framework"][0].rpartition("-")[0]
|
||||
lt_family = opts["framework"][0].rpartition("-")[0]
|
||||
if not server:
|
||||
debug_tool = opts.get("debug_tool", "custom")
|
||||
board = opts.get("board", "<unknown>")
|
||||
@@ -166,8 +244,8 @@ class LibretuyaPlatform(PlatformBase):
|
||||
"-f",
|
||||
"interface/%s.cfg" % opts.get("openocd_interface"),
|
||||
] + server["arguments"]
|
||||
# replace $LTPLATFORM with actual name
|
||||
# replace $LTFAMILY with actual name
|
||||
server["arguments"] = [
|
||||
arg.replace("$LTPLATFORM", lt_platform).replace("$LTPATH", lt_path)
|
||||
arg.replace("$LTFAMILY", lt_family).replace("$LTPATH", lt_path)
|
||||
for arg in server["arguments"]
|
||||
]
|
||||
|
||||
207
platform/realtek-ambz/fixups/inc/FreeRTOSConfig.h
Normal file
207
platform/realtek-ambz/fixups/inc/FreeRTOSConfig.h
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
FreeRTOS V7.3.0 - Copyright (C) 2012 Real Time Engineers Ltd.
|
||||
|
||||
FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT
|
||||
http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS tutorial books are available in pdf and paperback. *
|
||||
* Complete, revised, and edited pdf reference manuals are also *
|
||||
* available. *
|
||||
* *
|
||||
* Purchasing FreeRTOS documentation will not only help you, by *
|
||||
* ensuring you get running as quickly as possible and with an *
|
||||
* in-depth knowledge of how to use FreeRTOS, it will also help *
|
||||
* the FreeRTOS project to continue with its mission of providing *
|
||||
* professional grade, cross platform, de facto standard solutions *
|
||||
* for microcontrollers - completely free of charge! *
|
||||
* *
|
||||
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
|
||||
* *
|
||||
* Thank you for using FreeRTOS, and thank you for your support! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
||||
>>>NOTE<<< The modification to the GPL is included to allow you to
|
||||
distribute a combined work that includes FreeRTOS without being obliged to
|
||||
provide the source code for proprietary components outside of the FreeRTOS
|
||||
kernel. FreeRTOS 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 General Public License for
|
||||
more details. You should have received a copy of the GNU General Public
|
||||
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
||||
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
||||
by writing to Richard Barry, contact details for whom are available on the
|
||||
FreeRTOS WEB site.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* Having a problem? Start by reading the FAQ "My application does *
|
||||
* not run, what could be wrong?" *
|
||||
* *
|
||||
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, training, latest versions, license
|
||||
and contact details.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool.
|
||||
|
||||
Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
|
||||
the code with commercial support, indemnification, and middleware, under
|
||||
the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
|
||||
provide a safety engineered and independently SIL3 certified version under
|
||||
the SafeRTOS brand: http://www.SafeRTOS.com.
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_CONFIG_H
|
||||
#define FREERTOS_CONFIG_H
|
||||
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
|
||||
#include <stdint.h>
|
||||
extern uint32_t SystemCoreClock;
|
||||
#endif
|
||||
#include "platform_autoconf.h"
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Application specific definitions.
|
||||
*
|
||||
* These definitions should be adjusted for your particular hardware and
|
||||
* application requirements.
|
||||
*
|
||||
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
|
||||
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
|
||||
*
|
||||
* See http://www.freertos.org/a00110.html.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
#define configUSE_PREEMPTION 1
|
||||
#define configUSE_IDLE_HOOK 1
|
||||
#define configUSE_TICK_HOOK 0
|
||||
#define configCPU_CLOCK_HZ ( SystemCoreClock )
|
||||
#define configTICK_RATE_HZ ( ( uint32_t ) 1000 )
|
||||
#define configSYSTICK_CLOCK_HZ 32768
|
||||
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 512 )
|
||||
#ifdef CONFIG_WIFI_EN
|
||||
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 160 * 1024 ) )
|
||||
#else
|
||||
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 20 * 1024 ) )
|
||||
#endif
|
||||
#define configMAX_TASK_NAME_LEN ( 10 )
|
||||
#define configUSE_TRACE_FACILITY 0
|
||||
#define configUSE_16_BIT_TICKS 0
|
||||
#define configIDLE_SHOULD_YIELD 0
|
||||
#define configUSE_CO_ROUTINES 1
|
||||
#define configUSE_MUTEXES 1
|
||||
#define configUSE_TIMERS 1
|
||||
|
||||
#define configMAX_PRIORITIES ( 11 )
|
||||
#define PRIORITIE_OFFSET ( 4 )
|
||||
|
||||
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
|
||||
|
||||
#define configUSE_COUNTING_SEMAPHORES 1
|
||||
#define configUSE_ALTERNATIVE_API 0
|
||||
#define configCHECK_FOR_STACK_OVERFLOW 2
|
||||
#define configUSE_RECURSIVE_MUTEXES 1
|
||||
#define configQUEUE_REGISTRY_SIZE 0
|
||||
#define configGENERATE_RUN_TIME_STATS 0
|
||||
#if configGENERATE_RUN_TIME_STATS
|
||||
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() //( ulHighFrequencyTimerTicks = 0UL )
|
||||
#define portGET_RUN_TIME_COUNTER_VALUE() xTickCount //ulHighFrequencyTimerTicks
|
||||
#undef configUSE_TRACE_FACILITY
|
||||
#define configUSE_TRACE_FACILITY 1
|
||||
#define portCONFIGURE_STATS_PEROID_VALUE 1000 //unit Ticks
|
||||
#endif
|
||||
|
||||
#define configTIMER_TASK_PRIORITY ( 1 )
|
||||
#define configTIMER_QUEUE_LENGTH ( 10 )
|
||||
#define configTIMER_TASK_STACK_DEPTH ( 512 ) //USE_MIN_STACK_SIZE modify from 512 to 256
|
||||
|
||||
#if (__IASMARM__ != 1)
|
||||
|
||||
extern void freertos_pre_sleep_processing(unsigned int *expected_idle_time);
|
||||
extern void freertos_post_sleep_processing(unsigned int *expected_idle_time);
|
||||
extern int freertos_ready_to_sleep();
|
||||
|
||||
/* Enable tickless power saving. */
|
||||
#define configUSE_TICKLESS_IDLE 1
|
||||
|
||||
/* In wlan usage, this value is suggested to use value less than 80 milliseconds */
|
||||
#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2
|
||||
|
||||
/* It's magic trick that let us can use our own sleep function */
|
||||
#define configPRE_SLEEP_PROCESSING( x ) ( freertos_pre_sleep_processing(&x) )
|
||||
|
||||
#define configPOST_SLEEP_PROCESSING( x ) ( freertos_post_sleep_processing(&x) )
|
||||
|
||||
/* It's magic trick that let us can enable/disable tickless dynamically */
|
||||
#define traceLOW_POWER_IDLE_BEGIN(); do { \
|
||||
if (!freertos_ready_to_sleep()) { \
|
||||
mtCOVERAGE_TEST_MARKER(); \
|
||||
break; \
|
||||
}
|
||||
|
||||
// portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
|
||||
|
||||
#define traceLOW_POWER_IDLE_END(); } while (0);
|
||||
|
||||
/* It's FreeRTOS related feature but it's not included in FreeRTOS design. */
|
||||
#define configUSE_WAKELOCK_PMU 1
|
||||
|
||||
#endif // #if (__IASMARM__ != 1)
|
||||
|
||||
/* Set the following definitions to 1 to include the API function, or zero
|
||||
to exclude the API function. */
|
||||
#define INCLUDE_vTaskPrioritySet 1
|
||||
#define INCLUDE_uxTaskPriorityGet 1
|
||||
#define INCLUDE_vTaskDelete 1
|
||||
#define INCLUDE_vTaskCleanUpResources 0
|
||||
#define INCLUDE_vTaskSuspend 1
|
||||
#define INCLUDE_vTaskDelayUntil 1
|
||||
#define INCLUDE_vTaskDelay 1
|
||||
#define INCLUDE_pcTaskGetTaskName 1
|
||||
#define INCLUDE_xTimerPendFunctionCall 1
|
||||
|
||||
/* Cortex-M specific definitions. */
|
||||
#ifdef __NVIC_PRIO_BITS
|
||||
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
|
||||
#define configPRIO_BITS __NVIC_PRIO_BITS
|
||||
#else
|
||||
#define configPRIO_BITS 4 /* 15 priority levels */
|
||||
#endif
|
||||
|
||||
|
||||
/* The lowest interrupt priority that can be used in a call to a "set priority"
|
||||
function. */
|
||||
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x0f
|
||||
|
||||
/* The highest interrupt priority that can be used by any interrupt service
|
||||
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
|
||||
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
|
||||
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
|
||||
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
|
||||
|
||||
|
||||
/* Interrupt priorities used by the kernel port layer itself. These are generic
|
||||
to all Cortex-M ports, and do not rely on any particular library functions. */
|
||||
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
|
||||
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
|
||||
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
|
||||
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
|
||||
|
||||
//#define RTK_MODE_TIMER
|
||||
|
||||
|
||||
#endif /* FREERTOS_CONFIG_H */
|
||||
508
platform/realtek-ambz/fixups/inc/autoconf.h
Normal file
508
platform/realtek-ambz/fixups/inc/autoconf.h
Normal file
@@ -0,0 +1,508 @@
|
||||
#ifndef WLANCONFIG_H
|
||||
#define WLANCONFIG_H
|
||||
|
||||
/*
|
||||
* Include user defined options first. Anything not defined in these files
|
||||
* will be set to standard values. Override anything you dont like!
|
||||
*/
|
||||
#if defined(CONFIG_PLATFORM_8195A) || defined(CONFIG_PLATFORM_8711B) || defined(CONFIG_HARDWARE_8188F)
|
||||
#include "platform_opts.h"
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PLATFORM_8195A) || defined(CONFIG_PLATFORM_8711B)
|
||||
#define CONFIG_PLATFORM_AMEBA_X
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_PLATFORM_AMEBA_X)
|
||||
#define PLATFORM_FREERTOS 1
|
||||
#define CONFIG_GSPI_HCI
|
||||
#else
|
||||
#define CONFIG_LX_HCI
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_INIC_EN
|
||||
#define CONFIG_INIC_EN 0 //For iNIC project
|
||||
#endif
|
||||
|
||||
#if CONFIG_INIC_EN
|
||||
#define CONFIG_LWIP_LAYER 0
|
||||
#endif
|
||||
|
||||
#define CONFIG_LITTLE_ENDIAN
|
||||
#define CONFIG_80211N_HT
|
||||
//#define CONFIG_RECV_REORDERING_CTRL
|
||||
#define RTW_NOTCH_FILTER 0
|
||||
#define CONFIG_EMBEDDED_FWIMG
|
||||
#define CONFIG_PHY_SETTING_WITH_ODM
|
||||
#if !defined(CONFIG_PLATFORM_AMEBA_X)
|
||||
#define CONFIG_ODM_REFRESH_RAMASK
|
||||
#define HAL_MAC_ENABLE 1
|
||||
#define HAL_BB_ENABLE 1
|
||||
#define HAL_RF_ENABLE 1
|
||||
#endif
|
||||
#if defined(CONFIG_PLATFORM_AMEBA_X)
|
||||
/* Patch when dynamic mechanism is not ready */
|
||||
//#define CONFIG_DM_PATCH
|
||||
#endif
|
||||
|
||||
//#define CONFIG_DEBUG
|
||||
//#define CONFIG_DEBUG_RTL871X
|
||||
#if defined(CONFIG_PLATFORM_AMEBA_X)
|
||||
#define CONFIG_MEM_MONITOR MEM_MONITOR_SIMPLE
|
||||
#define WLAN_INTF_DBG 0
|
||||
//#define CONFIG_DEBUG_DYNAMIC
|
||||
//#define DBG_TX 1
|
||||
//#define DBG_XMIT_BUF 1
|
||||
//#define DBG_XMIT_BUF_EXT 1
|
||||
#define DBG_TX_DROP_FRAME
|
||||
#else
|
||||
#define CONFIG_MEM_MONITOR MEM_MONITOR_LEAK
|
||||
//#define CONFIG_TRACE_SKB
|
||||
//#define WLAN_INTF_DBG
|
||||
#endif // CONFIG_PLATFORM_AMEBA_X
|
||||
|
||||
//#define CONFIG_DONT_CARE_TP
|
||||
//#define CONFIG_HIGH_TP
|
||||
//#define CONFIG_MEMORY_ACCESS_ALIGNED
|
||||
#define CONFIG_POWER_SAVING
|
||||
#ifdef CONFIG_POWER_SAVING
|
||||
#define CONFIG_IPS
|
||||
#define CONFIG_LPS
|
||||
//#define CONFIG_LPS_LCLK
|
||||
#define CONFIG_LPS_32K
|
||||
#define TDMA_POWER_SAVING
|
||||
#define CONFIG_WAIT_PS_ACK
|
||||
#endif
|
||||
|
||||
#define BAD_MIC_COUNTERMEASURE 1
|
||||
#define DEFRAGMENTATION 1
|
||||
|
||||
#define WIFI_LOGO_CERTIFICATION 0
|
||||
#if WIFI_LOGO_CERTIFICATION
|
||||
#define RX_AGGREGATION 1
|
||||
#define RX_AMSDU 1
|
||||
#else
|
||||
#define RX_AGGREGATION 0
|
||||
#define RX_AMSDU 0
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PLATFORM_AMEBA_X)
|
||||
#if !defined(CONFIG_PLATFORM_8711B)
|
||||
#define CONFIG_USE_TCM_HEAP 1 /* USE TCM HEAP */
|
||||
#endif
|
||||
#define CONFIG_RECV_TASKLET_THREAD
|
||||
#define CONFIG_XMIT_TASKLET_THREAD
|
||||
#else
|
||||
#define CONFIG_XMIT_THREAD_MODE
|
||||
#endif // CONFIG_PLATFORM_AMEBA_X
|
||||
//#define CONFIG_RECV_THREAD_MODE /* Wlan IRQ Polling Mode*/
|
||||
//#define CONFIG_ISR_THREAD_MODE_POLLING /* Wlan IRQ Polling Mode*/
|
||||
|
||||
//1 Chris
|
||||
#ifndef CONFIG_SDIO_HCI
|
||||
#define CONFIG_ISR_THREAD_MODE_INTERRUPT /* Wlan IRQ Interrupt Mode*/
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ISR_THREAD_MODE_POLLING) && defined(CONFIG_ISR_THREAD_MODE_INTERRUPT)
|
||||
#error "CONFIG_ISR_THREAD_MODE_POLLING and CONFIG_ISR_THREAD_MODE_INTERRUPT are mutually exclusive. "
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PLATFORM_AMEBA_X)
|
||||
/* CRC DMEM optimized mode consume 1k less SRM memory consumption */
|
||||
#define CRC_IMPLEMENTATION_MODE CRC_IMPLEMENTATION_DMEM_OPTIMIZED
|
||||
#endif
|
||||
|
||||
/* AES DMEM optimized mode comsume 10k less memory compare to
|
||||
IMEM optimized mode AES_IMPLEMENTATION_IMEM_OPTIMIZED */
|
||||
#define AES_IMPLEMENTATION_MODE AES_IMPLEMENTATION_DMEM_OPTIMIZED
|
||||
|
||||
#define USE_SKB_AS_XMITBUF 1
|
||||
#if defined(CONFIG_PLATFORM_AMEBA_X)
|
||||
#define USE_XMIT_EXTBUFF 1
|
||||
#else
|
||||
#define USE_XMIT_EXTBUFF 0
|
||||
#endif
|
||||
#define USE_MUTEX_FOR_SPINLOCK 1
|
||||
|
||||
// remove function to reduce code
|
||||
#define NOT_SUPPORT_5G
|
||||
#define NOT_SUPPORT_RF_MULTIPATH
|
||||
#define NOT_SUPPORT_VHT
|
||||
#define NOT_SUPPORT_40M
|
||||
#define NOT_SUPPORT_80M
|
||||
#ifndef CONFIG_PLATFORM_8711B
|
||||
#define NOT_SUPPORT_BBSWING
|
||||
#endif
|
||||
#define NOT_SUPPORT_OLD_CHANNEL_PLAN
|
||||
#define NOT_SUPPORT_BT
|
||||
|
||||
#define CONFIG_WIFI_SPEC 0
|
||||
#define CONFIG_FAKE_EFUSE 0
|
||||
#if CONFIG_FAKE_EFUSE
|
||||
#define FAKE_CHIPID CHIPID_8710BN
|
||||
#endif
|
||||
|
||||
#define CONFIG_AUTO_RECONNECT 1
|
||||
#define ENABLE_HWPDN_PIN
|
||||
#define SUPPORT_SCAN_BUF 1
|
||||
#if !defined(CONFIG_PLATFORM_AMEBA_X)
|
||||
#define BE_I_CUT 1
|
||||
#endif
|
||||
|
||||
/* For WPA2 */
|
||||
#define CONFIG_INCLUDE_WPA_PSK
|
||||
#ifdef CONFIG_INCLUDE_WPA_PSK
|
||||
#define CONFIG_MULTIPLE_WPA_STA
|
||||
//#define CONFIG_WPA2_PREAUTH
|
||||
#define PSK_SUPPORT_TKIP 1
|
||||
#endif
|
||||
//#define AP_PSK_SUPPORT_TKIP
|
||||
|
||||
/* For promiscuous mode */
|
||||
#define CONFIG_PROMISC
|
||||
|
||||
#define PROMISC_DENY_PAIRWISE 0
|
||||
|
||||
/* For Simple Link */
|
||||
#ifndef CONFIG_INCLUDE_SIMPLE_CONFIG
|
||||
//#define CONFIG_INCLUDE_SIMPLE_CONFIG 1
|
||||
#endif
|
||||
|
||||
// for probe request with custom vendor specific IE
|
||||
#define CONFIG_CUSTOM_IE
|
||||
|
||||
#if !defined(CONFIG_PLATFORM_AMEBA_X)
|
||||
/* For multicast */
|
||||
#define CONFIG_MULTICAST
|
||||
#endif
|
||||
|
||||
/* For STA+AP Concurrent MODE */
|
||||
#define CONFIG_CONCURRENT_MODE
|
||||
#ifdef CONFIG_CONCURRENT_MODE
|
||||
#if defined(CONFIG_PLATFORM_8195A)
|
||||
#define CONFIG_RUNTIME_PORT_SWITCH
|
||||
#endif
|
||||
#if defined(CONFIG_HARDWARE_8188F)
|
||||
#define NET_IF_NUM 2
|
||||
#else
|
||||
#define NET_IF_NUM ((CONFIG_ETHERNET) + (CONFIG_WLAN) + 1)
|
||||
#endif
|
||||
#else
|
||||
#if defined(CONFIG_HARDWARE_8188F)
|
||||
#define NET_IF_NUM 1
|
||||
#else
|
||||
#define NET_IF_NUM ((CONFIG_ETHERNET) + (CONFIG_WLAN))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/****************** For EAP auth configurations *******************/
|
||||
#define CONFIG_TLS 0
|
||||
#define CONFIG_PEAP 0
|
||||
#define CONFIG_TTLS 0
|
||||
|
||||
// DO NOT change the below config of EAP
|
||||
#ifdef PRE_CONFIG_EAP
|
||||
#undef CONFIG_TLS
|
||||
#define CONFIG_TLS 1
|
||||
#undef CONFIG_PEAP
|
||||
#define CONFIG_PEAP 1
|
||||
#undef CONFIG_TTLS
|
||||
#define CONFIG_TTLS 1
|
||||
#endif
|
||||
|
||||
// enable 1X code in lib_wlan as default (increase 380 bytes)
|
||||
#define CONFIG_EAP
|
||||
|
||||
#if CONFIG_TLS || CONFIG_PEAP || CONFIG_TTLS
|
||||
#define EAP_REMOVE_UNUSED_CODE 1
|
||||
#endif
|
||||
|
||||
#define EAP_SSL_VERIFY_SERVER
|
||||
|
||||
#if CONFIG_TLS
|
||||
#define EAP_SSL_VERIFY_CLIENT
|
||||
#endif
|
||||
|
||||
#if CONFIG_TTLS
|
||||
#define EAP_MSCHAPv2
|
||||
#define EAP_TTLS_MSCHAPv2
|
||||
//#define EAP_TTLS_EAP
|
||||
//#define EAP_TTLS_MSCHAP
|
||||
//#define EAP_TTLS_PAP
|
||||
//#define EAP_TTLS_CHAP
|
||||
#endif
|
||||
/****************** End of EAP configurations *******************/
|
||||
|
||||
/* For WPS and P2P */
|
||||
#define CONFIG_WPS
|
||||
#if 0
|
||||
#define CONFIG_WPS_AP
|
||||
#define CONFIG_P2P_NEW
|
||||
#if (!defined(SUPPORT_SCAN_BUF)||!defined(CONFIG_WPS_AP)) && defined(CONFIG_P2P_NEW)
|
||||
#error "If CONFIG_P2P_NEW, need to SUPPORT_SCAN_BUF"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define CONFIG_NEW_SIGNAL_STAT_PROCESS
|
||||
#define CONFIG_SKIP_SIGNAL_SCALE_MAPPING
|
||||
|
||||
/* For AP_MODE */
|
||||
#define CONFIG_AP_MODE
|
||||
extern unsigned char g_user_ap_sta_num;
|
||||
#define USER_AP_STA_NUM g_user_ap_sta_num
|
||||
#if defined(CONFIG_PLATFORM_AMEBA_X)
|
||||
#define AP_STA_NUM 3 //2014/10/27 modify to 3
|
||||
#define USE_DEDICATED_BCN_TX 0
|
||||
#if USE_DEDICATED_BCN_TX
|
||||
#error "WLAN driver for Ameba should not enable USE_DEDICATED_BCN_TX"
|
||||
#endif
|
||||
#else
|
||||
extern unsigned int g_ap_sta_num;
|
||||
#define AP_STA_NUM 3//g_ap_sta_num
|
||||
#endif
|
||||
#ifdef CONFIG_AP_MODE
|
||||
#if defined(CONFIG_PLATFORM_8195A)
|
||||
//softap sent qos null0 polling client alive or not
|
||||
#define CONFIG_AP_POLLING_CLIENT_ALIVE
|
||||
#endif
|
||||
#define CONFIG_NATIVEAP_MLME
|
||||
#if defined(CONFIG_PLATFORM_AMEBA_X)
|
||||
#define CONFIG_INTERRUPT_BASED_TXBCN
|
||||
#endif
|
||||
#ifdef CONFIG_INTERRUPT_BASED_TXBCN
|
||||
//#define CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT
|
||||
#define CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR
|
||||
#endif
|
||||
// #define CONFIG_GK_REKEY
|
||||
#if !defined(CONFIG_PLATFORM_AMEBA_X)
|
||||
#define USE_DEDICATED_BCN_TX 1
|
||||
#endif
|
||||
#if CONFIG_INIC_EN
|
||||
// #define REPORT_STA_EVENT //useless
|
||||
#endif
|
||||
#else
|
||||
#if !defined(CONFIG_PLATFORM_AMEBA_X)
|
||||
#define USE_DEDICATED_BCN_TX 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_AP_MODE) && defined(CONFIG_GK_REKEY) && !defined(CONFIG_MULTIPLE_WPA_STA)
|
||||
#error "If CONFIG_GK_REKEY when CONFIG_AP_MODE, need to CONFIG_MULTIPLE_WPA_STA"
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_PLATFORM_AMEBA_X)
|
||||
#if !defined(CONFIG_AP_MODE) && defined(CONFIG_CONCURRENT_MODE)
|
||||
#error "If CONFIG_CONCURRENT_MODEE, need to CONFIG_AP_MODE"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* For efuse or flash config */
|
||||
#if defined(CONFIG_PLATFORM_AMEBA_X)
|
||||
#define CONFIG_RW_PHYSICAL_EFUSE 0 // Mask efuse user blocks
|
||||
#define CONFIG_HIDE_PROTECT_EFUSE 1
|
||||
#define CONFIG_ADAPTOR_INFO_CACHING_FLASH 1
|
||||
#define CHECK_FLASH_VALID_MASK 1
|
||||
#define CHECK_EFUSE_VALID_MASK 1
|
||||
/* For K-free */
|
||||
// #if !defined(CONFIG_PLATFORM_8711B)
|
||||
#define CONFIG_RF_GAIN_OFFSET
|
||||
// #endif
|
||||
#endif // CONFIG_PLATFORM_AMEBA_X
|
||||
|
||||
/* For MP_MODE */
|
||||
//#define CONFIG_MP_INCLUDED
|
||||
#ifdef CONFIG_MP_INCLUDED
|
||||
#define MP_DRIVER 1
|
||||
#define CONFIG_MP_IWPRIV_SUPPORT
|
||||
// #define HAL_EFUSE_MEMORY
|
||||
#if defined(CONFIG_PLATFORM_AMEBA_X)
|
||||
#define MP_REG_TEST
|
||||
#endif
|
||||
#else
|
||||
#define MP_DRIVER 0
|
||||
#if defined(CONFIG_PLATFORM_8195A)
|
||||
//Control wifi mcu function
|
||||
#define CONFIG_LITTLE_WIFI_MCU_FUNCTION_THREAD
|
||||
#define CONFIG_ODM_REFRESH_RAMASK
|
||||
//#define CONFIG_ANTENNA_DIVERSITY
|
||||
//#define CONFIG_BT_COEXIST
|
||||
#endif
|
||||
#endif // #ifdef CONFIG_MP_INCLUDED
|
||||
|
||||
#ifdef CONFIG_BT_COEXIST
|
||||
#undef NOT_SUPPORT_BT
|
||||
#define CONFIG_BT_MAILBOX
|
||||
//#define CONFIG_BT_TWO_ANTENNA
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PLATFORM_AMEBA_X)
|
||||
#if defined(CONFIG_PLATFORM_8195A)
|
||||
#undef CONFIG_RTL8195A
|
||||
#define CONFIG_RTL8195A
|
||||
#endif
|
||||
#if defined(CONFIG_PLATFORM_8711B)
|
||||
#ifndef CONFIG_RTL8711B
|
||||
#define CONFIG_RTL8711B
|
||||
#endif
|
||||
#undef CONFIG_ADAPTOR_INFO_CACHING_FLASH
|
||||
#define CONFIG_ADAPTOR_INFO_CACHING_FLASH 0
|
||||
//#undef CONFIG_EAP
|
||||
//#undef CONFIG_IPS
|
||||
#define CONFIG_8710B_MOVE_TO_ROM
|
||||
#define CONFIG_EFUSE_SEPARATE
|
||||
#define CONFIG_MOVE_PSK_TO_ROM
|
||||
#define CONFIG_WOWLAN
|
||||
#define CONFIG_TRAFFIC_PROTECT
|
||||
#ifdef CONFIG_LPS
|
||||
#define REKEY_LEAVE_LPS
|
||||
#endif
|
||||
#endif
|
||||
#elif defined(CONFIG_HARDWARE_8188F)
|
||||
#define CONFIG_RTL8188F
|
||||
#else
|
||||
#define CONFIG_RTL8188E
|
||||
#endif
|
||||
#define RTL8192C_SUPPORT 0
|
||||
#define RTL8192CE_SUPPORT 0
|
||||
#define RTL8192CU_SUPPORT 0
|
||||
#define RTL8192D_SUPPORT 0
|
||||
#define RTL8192DE_SUPPORT 0
|
||||
#define RTL8192DU_SUPPORT 0
|
||||
#define RTL8723A_SUPPORT 0
|
||||
#define RTL8723AU_SUPPORT 0
|
||||
#define RTL8723AS_SUPPORT 0
|
||||
#define RTL8192E_SUPPORT 0
|
||||
#define RTL8812A_SUPPORT 0
|
||||
#define RTL8821A_SUPPORT 0
|
||||
#define RTL8723B_SUPPORT 0
|
||||
#define RTL8195A_SUPPORT 0
|
||||
#define RTL8188E_SUPPORT 0
|
||||
#define RTL8188F_SUPPORT 0
|
||||
#define RTL8711B_SUPPORT 0
|
||||
#if defined(CONFIG_PLATFORM_8195A)
|
||||
#undef RTL8195A_SUPPORT
|
||||
#define RTL8195A_SUPPORT 1
|
||||
#elif defined(CONFIG_PLATFORM_8711B)
|
||||
#undef RTL8711B_SUPPORT
|
||||
#define RTL8711B_SUPPORT 1
|
||||
#elif defined(CONFIG_HARDWARE_8188F)
|
||||
#undef RTL8188F_SUPPORT
|
||||
#define RTL8188F_SUPPORT 1
|
||||
#else
|
||||
#undef RTL8188E_SUPPORT
|
||||
#define RTL8188E_SUPPORT 1
|
||||
#endif
|
||||
|
||||
#define TEST_CHIP_SUPPORT 0
|
||||
|
||||
#define RTL8188E_FOR_TEST_CHIP 0
|
||||
#define RTL8188E_FPGA_TRUE_PHY_VERIFICATION 0
|
||||
|
||||
// for Debug message
|
||||
#define DBG 0
|
||||
#if defined(CONFIG_PLATFORM_AMEBA_X)
|
||||
#if(DBG == 0)
|
||||
#define ROM_E_RTW_MSG 1
|
||||
#define ROM_F_RTW_MSG 1
|
||||
/* For DM debug*/
|
||||
// BB
|
||||
#define DBG_RX_INFO 1
|
||||
#define DBG_DM_DIG 1 // DebugComponents: bit0
|
||||
#define DBG_DM_RA_MASK 1 // DebugComponents: bit1
|
||||
#define DBG_DM_ANT_DIV 1 // DebugComponents: bit6
|
||||
#define DBG_TX_RATE 1 // DebugComponents: bit9
|
||||
#define DBG_DM_RA 1 // DebugComponents: bit9
|
||||
#define DBG_DM_ADAPTIVITY 1 // DebugComponents: bit17
|
||||
// RF
|
||||
#define DBG_PWR_TRACKING 1 // DebugComponents: bit24
|
||||
#define DBG_RF_IQK 1 // DebugComponents: bit26
|
||||
// Common
|
||||
#define DBG_PWR_INDEX 1 // DebugComponents: bit30
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* For DM support */
|
||||
#if defined(CONFIG_RTL8188F)
|
||||
#define RATE_ADAPTIVE_SUPPORT 0
|
||||
#elif defined(CONFIG_PLATFORM_8711B)
|
||||
#define RATE_ADAPTIVE_SUPPORT 0
|
||||
#define CONFIG_ODM_REFRESH_RAMASK
|
||||
#else
|
||||
#define RATE_ADAPTIVE_SUPPORT 1
|
||||
#endif
|
||||
// adaptivity
|
||||
#define RTW_ADAPTIVITY_EN_DISABLE 0
|
||||
#define RTW_ADAPTIVITY_EN_ENABLE 1
|
||||
#define CONFIG_RTW_ADAPTIVITY_EN RTW_ADAPTIVITY_EN_DISABLE
|
||||
#define RTW_ADAPTIVITY_MODE_NORMAL 0
|
||||
#define RTW_ADAPTIVITY_MODE_CARRIER_SENSE 1
|
||||
#define CONFIG_RTW_ADAPTIVITY_MODE RTW_ADAPTIVITY_MODE_CARRIER_SENSE
|
||||
#define CONFIG_RTW_ADAPTIVITY_DML 0
|
||||
|
||||
|
||||
#if defined(CONFIG_PLATFORM_AMEBA_X)
|
||||
#define CONFIG_POWER_TRAINING_WIL 0 // in RA
|
||||
#else
|
||||
#define POWER_BY_RATE_SUPPORT 0
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PLATFORM_AMEBA_X)
|
||||
#define RTL8195A_FOR_TEST_CHIP 0
|
||||
|
||||
//#define CONFIG_WIFI_TEST 1
|
||||
//#define CONFIG_MAC_LOOPBACK_DRIVER 1
|
||||
//#define CONFIG_WLAN_HAL_TEST 1
|
||||
//#define SKB_PRE_ALLOCATE_TX 1
|
||||
#define SKB_PRE_ALLOCATE_RX 0
|
||||
#define TX_CHECK_DSEC_ALWAYS 1
|
||||
#define CONFIG_DBG_DISABLE_RDU_INTERRUPT
|
||||
//#define CONFIG_WLAN_HAL_RX_TASK
|
||||
#if (SKB_PRE_ALLOCATE_RX == 1)
|
||||
#define EXCHANGE_LXBUS_RX_SKB 0
|
||||
#endif
|
||||
#ifdef CONFIG_FPGA
|
||||
//Enable mac loopback for test mode (Ameba)
|
||||
#define CONFIG_TWO_MAC_DRIVER // for test mode
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MAC_LB_FOR_TEST_MODE
|
||||
#define CONFIG_SUDO_PHY_SETTING
|
||||
#define INT_HANDLE_IN_ISR 1
|
||||
#define CONFIG_LWIP_LAYER 0
|
||||
#define CONFIG_WLAN_HAL_TEST
|
||||
#define CONFIG_WLAN_HAL_RX_TASK
|
||||
#define CONFIG_MAC_LOOPBACK_DRIVER_RTL8711B 1
|
||||
#define HAL_MAC_ENABLE 1
|
||||
#define CONFIG_TWO_MAC_TEST_MODE
|
||||
#define DISABLE_BB_RF 1
|
||||
#else
|
||||
//#define CONFIG_TWO_MAC_DRIVER //for mornal driver; two mac
|
||||
#ifdef CONFIG_TWO_MAC_DRIVER
|
||||
#define CONFIG_SUDO_PHY_SETTING
|
||||
#define HAL_MAC_ENABLE 1
|
||||
#define DISABLE_BB_RF 1
|
||||
#else
|
||||
#define HAL_MAC_ENABLE 1
|
||||
#define HAL_BB_ENABLE 1
|
||||
#define HAL_RF_ENABLE 1
|
||||
#define DISABLE_BB_RF 0
|
||||
#endif
|
||||
//#define INT_HANDLE_IN_ISR 1
|
||||
#endif
|
||||
#endif // CONFIG_PLATFORM_AMEBA_X
|
||||
|
||||
#ifndef CONFIG_LWIP_LAYER
|
||||
#define CONFIG_LWIP_LAYER 1
|
||||
#endif
|
||||
#define CONFIG_MAC_ADDRESS 0
|
||||
//fast reconnection
|
||||
//#define CONFIG_FAST_RECONNECTION 1
|
||||
#if defined(CONFIG_INIC_EN)&&(CONFIG_INIC_EN==1)
|
||||
#define CONFIG_RECV_REORDERING_CTRL //enable reordering for iNIC high throughput
|
||||
#undef RX_AGGREGATION
|
||||
#define RX_AGGREGATION 1
|
||||
#undef NOT_SUPPORT_40M
|
||||
#undef CONFIG_CONCURRENT_MODE
|
||||
#endif
|
||||
#endif //WLANCONFIG_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user