51 Commits

Author SHA1 Message Date
Kuba Szczodrzyński
159ffa76fd [release] v1.3.0
Some checks failed
Release / Run Clang lint (push) Has been cancelled
Release / Publish PlatformIO platform (push) Has been cancelled
Release / Publish GitHub release (push) Has been cancelled
2023-08-29 19:21:09 +02:00
Kuba Szczodrzyński
1ac3d30d84 [libs] Implement Update MD5 2023-08-29 19:19:28 +02:00
Kuba Szczodrzyński
631ef6ba59 [github] Reuse GitHub workflows 2023-08-29 14:39:39 +02:00
Kuba Szczodrzyński
27393e47c3 [beken-72xx] Initialize UART to fix deep sleep 2023-08-23 16:08:03 +02:00
Péter Sárközi
bd47772c04 [beken-72xx] Fix GPIO deep sleep wakeup edge (#159)
Manufacturer docs: https://docs-bekencorp-com.translate.goog/sdk_3.0.x/bk7238/html/developer-guide/power_save/sleep_test.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=hu&_x_tr_pto=wapp

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

* Reformat lt_defs.h

---------

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

* Global functions

* Remove unnecessary override

* clang-format

* Support for multiple pins

* Fix math

* Add a way to unset GPIOs

* Clang format

* Update brief

---------

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

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

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

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

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

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

* Move test pads to separate files, update variants

* Update wiring guide

---------

Signed-off-by: Pavel Fedin <pavel_fedin@mail.ru>
Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2023-07-11 11:46:36 +02:00
Kuba Szczodrzyński
e38e53bac0 [core] Split lt_api.c into separate units 2023-06-22 18:30:14 +02:00
Kuba Szczodrzyński
b38a4d5d46 [core] Add hardware peripheral availability defines 2023-06-21 17:02:48 +02:00
Kuba Szczodrzyński
96412624d9 Merge branch 'master' into family/ambz2 2023-06-21 13:35:52 +02:00
Kuba Szczodrzyński
74659901c0 [boards] Fix BW15 PCB template name 2023-06-20 19:09:46 +02:00
Kuba Szczodrzyński
73ede2838c Merge branch 'master' into family/ambz2 2023-06-20 18:53:46 +02:00
Kuba Szczodrzyński
e2794d5f84 [builder] Fix running ltchiptool with no baudrate 2023-05-31 12:38:15 +02:00
Kuba Szczodrzyński
e7f35c584b [realtek-ambz2] Reuse Log UART for Serial 2023-05-31 12:37:34 +02:00
Kuba Szczodrzyński
1e49c3ff6f [realtek-ambz2] Fix missing flash API resource lock unit 2023-05-31 12:36:46 +02:00
Kuba Szczodrzyński
e256ac8e46 [builder] Fix ltchiptool empty quotes on Windows 2023-05-30 18:49:58 +02:00
Kuba Szczodrzyński
9c6e9d1525 [realtek-ambz2] Disable SoftwareSerial and Wire 2023-05-30 18:15:44 +02:00
Kuba Szczodrzyński
41985e5743 [core] Move common flags to base.py 2023-05-29 22:26:33 +02:00
Kuba Szczodrzyński
f1e41f7cc1 [realtek-ambz2] Add GDB init command 2023-05-29 22:25:23 +02:00
Kuba Szczodrzyński
6135e4f7b0 [boards] Update flash layouts, add W302 chip 2023-05-29 16:16:58 +02:00
Kuba Szczodrzyński
af8c7417b3 [realtek-ambz2] Keep LOG UART enabled, wipe OTA2 in UF2 2023-05-28 19:18:54 +02:00
Kuba Szczodrzyński
babdb1287f [realtek-ambz2] Replace lwIP with external port 2023-05-27 20:54:40 +02:00
Kuba Szczodrzyński
4532c88873 [core] Add lt_set_debug_mode() function, update core types 2023-05-27 16:03:46 +02:00
Kuba Szczodrzyński
bc1b83d931 Merge branch 'master' into family/ambz2 2023-05-27 15:43:35 +02:00
Kuba Szczodrzyński
87ad0798e4 [realtek-ambz2] Adapt WiFi library to ambz2_sdk 2023-05-27 15:41:07 +02:00
Kuba Szczodrzyński
a80032d46c [core] Move Wiring common core to wiring/, reset watchdog in yield() 2023-05-26 15:29:33 +02:00
Kuba Szczodrzyński
4dae304f51 [core] Add lt_get_device_mac() function 2023-05-25 20:43:00 +02:00
Kuba Szczodrzyński
9b7d34fa65 [realtek-ambz2] Fix C++ support, implement SerialClass 2023-05-25 14:35:41 +02:00
Kuba Szczodrzyński
c0cc602c9a [core] Add configure() for SerialClass 2023-05-25 14:29:35 +02:00
Kuba Szczodrzyński
e5f98ff41f [core] Refactor Wiring, use PinData for parameters 2023-05-24 22:01:05 +02:00
Kuba Szczodrzyński
bc74c21599 [realtek-ambz2] Enable compilation of Arduino core 2023-05-24 13:02:33 +02:00
Kuba Szczodrzyński
3836ad20b7 [core] Refactor SerialClass as API library 2023-05-24 11:55:07 +02:00
Kuba Szczodrzyński
b073290989 [realtek-ambz2] Implement base C API 2023-05-23 19:54:00 +02:00
Kuba Szczodrzyński
43c9d0db10 [docs] Add Porting new families guide 2023-05-23 15:58:11 +02:00
Kuba Szczodrzyński
c40bdd68af [realtek-ambz2] Use external FreeRTOS port 2023-05-23 15:14:59 +02:00
Kuba Szczodrzyński
620e457eb6 [realtek-ambz2] Fix C++ linker support 2023-05-23 12:56:42 +02:00
Kuba Szczodrzyński
8c636e44f7 [realtek-ambz2] Add initial SDK fixups and API layer 2023-05-23 12:11:17 +02:00
Kuba Szczodrzyński
07e9aa1ded [realtek-ambz2] Make compiling base core possible 2023-05-19 10:42:59 +02:00
253 changed files with 4359 additions and 2617 deletions

View File

@@ -1,35 +0,0 @@
name: Lint check
on: [push, pull_request]
jobs:
lint-clang-format:
name: Lint with clang-format
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Check code with clang-format
uses: jidicula/clang-format-action@v4.5.0
with:
clang-format-version: "14"
lint-black:
name: Lint with black
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: "3.9"
- name: Install test dependencies
uses: BSFishy/pip-action@v1
with:
packages: |
black
isort
- name: Check code with black
run: black --check .
- name: Check code with isort
run: isort --profile black . --check-only

View File

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

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

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

View File

@@ -1,10 +1,8 @@
name: Deploy docs on GitHub Pages
name: Push (master)
on:
push:
branches:
- master
branches: ["master"]
workflow_dispatch:
jobs:
docs:
name: Deploy docs
@@ -25,7 +23,8 @@ jobs:
run: |
mkdir -p site/
boardgen ltci
python docs/scripts/update_docs.py
python docs/scripts/write_boards.py
python docs/scripts/write_apis.py
python docs/scripts/prepare_doxygen.py
python docs/scripts/build_json.py
cp *.json site/

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

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

2
.gitignore vendored
View File

@@ -264,3 +264,5 @@ docs/status/supported_*.md
docs/status/unsupported_boards_*.md
boards/**/*.svg
boards/**/*.md
# other generated files
docs/contrib/lt-api-functions.md

View File

@@ -1,8 +1,10 @@
# LibreTiny
<small>(formerly LibreTuya)</small>
<div align="center" markdown>
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/kuba2k2/libretiny/Deploy%20docs%20on%20GitHub%20Pages?label=docs&logo=markdown)](https://kuba2k2.github.io/libretiny/)
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/kuba2k2/libretiny/push-master.yml?label=docs&logo=markdown)](https://docs.libretiny.eu/)
![GitHub last commit](https://img.shields.io/github/last-commit/kuba2k2/libretiny?logo=github)
[![Code style: clang-format](https://img.shields.io/badge/code%20style-clang--format-purple.svg)](.clang-format)
@@ -16,12 +18,6 @@
</div>
## LibreTuya is now LibreTiny! 🎉
We have [renamed the project](https://github.com/kuba2k2/libretiny/issues/92) to LibreTiny, also marking the very first v1.0.0 release, along with a huge structure refactor. While some care has been taken to ensure that things don't break, you may still need to update some references in your code to use the new name.
---
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,
@@ -32,62 +28,11 @@ which should make it easier to port/run existing ESP apps on less-common, unsupp
**Note:** this project is work-in-progress.
## Usage
<div align="center" markdown>
1. [Install PlatformIO](https://platformio.org/platformio-ide)
2. `platformio platform install -f https://github.com/kuba2k2/libretiny`
3. Create a project, build it and upload!
4. See the [docs](https://docs.libretiny.eu/) for any questions/problems.
## [⭐ Getting started ⭐](https://docs.libretiny.eu/docs/getting-started/)
<!--
## Arduino Core support status
Note: this list will probably change with each functionality update.
&nbsp; | `realtek-ambz` | `beken-72xx`
--------------------|----------------|-------------
Core functions | ✔️ | ✔️
GPIO/PWM/IRQ | ✔️/✔️/✔️ | ✔️/✔️/✔️
Analog input (ADC) | ✔️ | ✔️
Serial | ✔️ | ✔️
Serial (extra) | 0, 1, 2 | 1, 2
Flash I/O | ✔️ | ✔️
**CORE LIBRARIES** | |
SoftwareSerial | ✔️ | ❌
SPI | ❌ | ❌
Wire | ❗ | ❌
**OTHER LIBRARIES** | |
Wi-Fi STA/AP/Mixed | ✔️ | ✔️
Wi-Fi Events | ✔️ | ✔️
TCP Client (SSL) | ✔️ (✔️) | ✔️ (❗)
TCP Server | ✔️ | ✔️
IPv6 | ❌ | ❌
HTTP Client (SSL) | ✔️ (✔️) | ❓
HTTP Server | ✔️ | ✔️
NVS / Preferences | ✔️ | ✔️
SPIFFS | ❌ | ❌
BLE | - | ❌
NTP | ✔️ | ✔️
OTA | ✔️ | ✔️
MDNS | ✔️ | ✔️
MQTT | ✅ | ❌
SD | ❌ | ❌
Symbols:
- ✔️ working
- ✅ tested, external library
- ❓ untested
- ❗ broken
- ❌ not implemented (yet?)
- \- not applicable
Names:
- Core functions - stuff like delay(), millis(), yield(), etc.
- **CORE LIBRARIES** - included normally in all Arduino cores
- **OTHER LIBRARIES** - included in ESP32 core or downloadable
-->
</div>
## License

View File

@@ -1,11 +1,15 @@
* [Home](README.md)
* [](SUMMARY.md)
* [😊 Getting started](docs/getting-started/README.md)
* [➡️ Info on accessing GPIOs](docs/getting-started/gpio.md)
* [](SUMMARY.md)
* [📺 Cloudcutter & ESPHome video guide](https://www.youtube.com/watch?v=sSj8f-HCHQ0)
* [💡 ESPHome setup guide](docs/projects/esphome.md)
* [🛖 ESPHome Hassio Add-On](https://github.com/libretiny-eu/esphome-hass-addon/pkgs/container/libretiny-esphome-hassio)
* [](SUMMARY.md)
* [📲 Flashing/dumping guide](docs/flashing/)
* [🔌 How to connect the chip in download mode?](docs/flashing/chip-connection/)
* [💻 Supported chips](docs/status/supported.md)
* [🔌 How to flash/enter download mode?](docs/platform/)
* [](SUMMARY.md)
* [💻 Chips, boards, features](docs/status/supported.md)
* [All boards](boards/)
* [](SUMMARY.md)
* 🍪 Chip family docs & info
@@ -47,10 +51,13 @@
* [Macros](ltapi/macros.md)
* [File list](ltapi/files.md)
* 👷 Contributor's manual (WIP)
* [📁 Project structure](docs/dev/project-structure.md)
* [✈️ OTA format](docs/dev/ota/README.md)
* [uf2ota.py tool](docs/dev/ota/uf2ota.md)
* [uf2ota.h library](docs/dev/ota/library.md)
* [Porting new families](docs/contrib/porting.md)
* [API functions guide](docs/contrib/lt-api.md)
* [C standard library](docs/contrib/stdlib.md)
* [📁 Project structure](docs/contrib/project-structure.md)
* [✈️ OTA format](docs/contrib/ota/README.md)
* [uf2ota.py tool](docs/contrib/ota/uf2ota.md)
* [uf2ota.h library](docs/contrib/ota/library.md)
* [📓 TODO](docs/TODO.md)
* [](SUMMARY.md)
* [🔗 Resources](docs/resources/)

View File

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

View File

@@ -41,8 +41,7 @@
}
},
"links": {
"General info": "../../docs/platform/beken-72xx/README.md",
"Flashing guide": "../../docs/platform/beken-72xx/flashing.md"
"Info & flashing guide": "../../docs/platform/beken-72xx/README.md"
},
"extra": [
"Bootloader and app partitions contain CRC16 sums every 32 bytes. That results in the actual flash offsets/sizes not aligned to sector boundaries. To simplify calculations, the values shown in the table (extracted from bootloader's partition table) were aligned to 4096 bytes."

View File

@@ -2,14 +2,9 @@
"pcb": {
"templates": [
"esp12s",
"esp12s-shield",
"pcb-black",
"rf-type1"
],
"vars": {
"MASK_PRESET": "mask_black",
"TRACE_COLOR": "#FAFD9D",
"SILK_COLOR": "white"
},
"pinout_hidden": "I2S,TRIG,WAKE,CTS,RTS,SD",
"pinout": {
"1": {

View File

@@ -0,0 +1,44 @@
{
"pcb": {
"back": [
{
"comment": "RXD Pad",
"name": "test_pad_1mm",
"pos": "5.4,14.5"
},
{
"comment": "TXD Pad",
"name": "test_pad_1mm",
"pos": "5.4,13.2"
},
{
"comment": "RXD Pad label",
"id": "rxd",
"name": "label_line_up",
"pos": "4.6,14.6",
"vars": {
"DIR": "left",
"RASTER": 2,
"W": 2.1,
"H": 0
}
},
{
"comment": "TXD Pad label",
"id": "txd",
"name": "label_line_up",
"pos": "5.4,12.4",
"vars": {
"DIR": "left",
"RASTER": 2,
"W": 2.7,
"H": 0.5
}
}
],
"test_pads": {
"TRX2": "wr2.back.rxd.anchor",
"TTX2": "wr2.back.txd.anchor"
}
}
}

View File

@@ -43,6 +43,14 @@
"11": {
"IC": 14,
"ARD": "D7"
},
"TTX2": {
"IC": 1,
"ARD": "D8"
},
"TRX2": {
"IC": 2,
"ARD": "D9"
}
}
}

View File

@@ -0,0 +1,44 @@
{
"pcb": {
"back": [
{
"comment": "RXD Pad",
"name": "test_pad_1mm",
"pos": "5.4,14.5"
},
{
"comment": "TXD Pad",
"name": "test_pad_1mm",
"pos": "5.4,13.2"
},
{
"comment": "RXD Pad label",
"id": "rxd",
"name": "label_line_up",
"pos": "4.6,14.6",
"vars": {
"DIR": "left",
"RASTER": 2,
"W": 2.1,
"H": 0
}
},
{
"comment": "TXD Pad label",
"id": "txd",
"name": "label_line_up",
"pos": "5.4,12.4",
"vars": {
"DIR": "left",
"RASTER": 2,
"W": 2.7,
"H": 0.5
}
}
],
"test_pads": {
"TRX2": "wr2e.back.rxd.anchor",
"TTX2": "wr2e.back.txd.anchor"
}
}
}

View File

@@ -46,6 +46,14 @@
"11": {
"IC": 14,
"ARD": "D6"
},
"TTX2": {
"IC": 1,
"ARD": "D7"
},
"TRX2": {
"IC": 2,
"ARD": "D8"
}
}
}

View File

@@ -5,9 +5,8 @@
"flash": {
"ota1": "0x00B000+0x75000",
"ota2": "0x080000+0x75000",
"kvs": "0xF5000+0x6000",
"userdata": "0xFB000+0x104000",
"rdp": "0x1FF000+0x1000"
"kvs": "0x0F5000+0x8000",
"userdata": "0x0FD000+0x102000"
},
"upload": {
"flash_size": 2097152,

View File

@@ -5,9 +5,8 @@
"flash": {
"ota1": "0x00B000+0xC5000",
"ota2": "0x0D0000+0xC5000",
"kvs": "0x195000+0x6000",
"userdata": "0x19B000+0x64000",
"rdp": "0x1FF000+0x1000"
"kvs": "0x195000+0x8000",
"userdata": "0x19D000+0x62000"
},
"upload": {
"flash_size": 2097152,

View File

@@ -6,8 +6,7 @@
"ota1": "0x00B000+0xF5000",
"ota2": "0x100000+0xF5000",
"kvs": "0x1F5000+0x8000",
"userdata": "0x1FD000+0x202000",
"rdp": "0x3FF000+0x1000"
"userdata": "0x1FD000+0x202000"
},
"upload": {
"flash_size": 4194304,

View File

@@ -0,0 +1,5 @@
{
"flash": {
"tuya": "0x1EB000+0x15000"
}
}

View File

@@ -10,7 +10,8 @@
"boot_xip": "0x000000+0x4000",
"boot_ram": "0x004000+0x4000",
"system": "0x009000+0x1000",
"calibration": "0x00A000+0x1000"
"calibration": "0x00A000+0x1000",
"rdp": "0x1FF000+0x1000"
},
"connectivity": [
"wifi"
@@ -44,13 +45,8 @@
}
},
"links": {
"General info": "../../docs/platform/realtek-amb/README.md",
"Flashing guide": "../../docs/platform/realtek-ambz/flashing.md",
"Info & flashing guide": "../../docs/platform/realtek-ambz/README.md",
"Debugging": "../../docs/platform/realtek-ambz/debugging.md"
},
"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."
]
}
}
}

View File

@@ -0,0 +1,12 @@
{
"flash": {
"ota1": "0x010000+0xE0000",
"ota2": "0x0F0000+0xE0000",
"kvs": "0x1D0000+0x8000",
"userdata": "0x1D8000+0x28000"
},
"upload": {
"flash_size": 2097152,
"maximum_size": 917504
}
}

View File

@@ -2,8 +2,7 @@
"flash": {
"ota1": "0x00C000+0xF8000",
"ota2": "0x104000+0xF8000",
"kvs": "0x1FC000+0x2000",
"userdata": "0x1FE000+0x2000"
"kvs": "0x1FC000+0x4000"
},
"upload": {
"flash_size": 2097152,

View File

@@ -0,0 +1,96 @@
{
"image": {
"keys": {
"decryption": "a0d6dae7e062ca94cbb294bf896b9f68cf8438774256ac7403ca4fd9a1c9564f",
"keyblock": {
"part_table": "882aa16c8c44a7760aa8c9ab22e3568c6fa16c2afa4f0cea29a10abcdf60e44f",
"boot": "882aa16c8c44a7760aa8c9ab22e3568c6fa16c2afa4f0cea29a10abcdf60e44f"
},
"hash_keys": {
"part_table": "47e5661335a4c5e0a94d69f3c737d54f2383791332939753ef24279608f6d72b",
"boot": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"ota1": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e5f",
"ota2": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e5f"
},
"user_keys": {
"boot": "aa0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
"ota1": "bb0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
"ota2": "bb0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
},
"xip_sce_key": "a0d6dae7e062ca94cbb294bf896b9f68",
"xip_sce_iv": "94879487948794879487948794879487"
},
"ptable": {
"boot": "BOOT",
"ota1": "FW1",
"ota2": "FW2"
},
"boot": {
"name": "boot.sram",
"type": "SRAM",
"entry": "__ram_start_table_start__",
"elf": [
".ram.func.table",
".data",
".ram.code_text",
".ram.code_rodata"
],
"is_boot": true
},
"fw": [
{
"type": "FWHS_S",
"sections": [
{
"name": "fwhs.sram",
"type": "SRAM",
"entry": "__ram_start_table_start__",
"elf": [
".ram.img.signature",
".ram.func.table",
".data",
".ram.code_text",
".ram.code_rodata"
]
},
{
"name": "fwhs.psram",
"type": "PSRAM",
"entry": "__psram_start__",
"elf": [
".psram.data",
".psram.code_text",
".psram.code_rodata"
]
}
]
},
{
"type": "XIP",
"sections": [
{
"name": "fwhs.xip_c",
"entry": "XIP_RamImgSignature_s",
"type": "XIP",
"elf": [
".xip.code_c"
]
}
]
},
{
"type": "XIP",
"sections": [
{
"name": "fwhs.xip_p",
"entry": "__xip_code_rodata_start__",
"type": "XIP",
"elf": [
".xip.code_p"
]
}
]
}
]
}
}

View File

@@ -0,0 +1,5 @@
{
"flash": {
"tuya": "0x1D5000+0x10000"
}
}

View File

@@ -13,10 +13,20 @@
},
"debug": {
"protocol": "openocd",
"protocols": []
"protocols": [
"openocd"
],
"openocd_config": "amebaz2.cfg",
"gdb_init": [
"mem 0x9b000000 0x9c000000 ro"
]
},
"upload": {
"maximum_ram_size": 262144
"maximum_ram_size": 262144,
"protocol": "uart",
"protocols": [
"uart"
]
},
"doc": {
"params": {

26
boards/bw15.json Normal file
View File

@@ -0,0 +1,26 @@
{
"_base": [
"realtek-ambz2",
"realtek-ambz2-8720",
"realtek-ambz2-image",
"realtek-ambz2-2mb-992k",
"ic/rtl8720cf",
"pcb/bw15"
],
"build": {
"mcu": "rtl8720cf",
"variant": "bw15"
},
"name": "BW15",
"url": "https://docs.ai-thinker.com/_media/rtl8710/docs/bw15_datasheet_en.pdf",
"vendor": "Ai-Thinker Co., Ltd.",
"pcb": {
"symbol": "BW15"
},
"doc": {
"fccid": "2AXVG-BW15",
"links": {
"Vendor datasheet": "https://docs.ai-thinker.com/_media/rtl8710/docs/bw15_datasheet_en.pdf"
}
}
}

View File

@@ -2,7 +2,7 @@
"_base": [
"beken-72xx",
"beken-7231n",
"beken-7231-crypt-tuya",
"beken-7231-tuya",
"ic/bk7231-qfn32",
"pcb/cb1s",
"pcb/cb1s-test"

View File

@@ -2,7 +2,7 @@
"_base": [
"beken-72xx",
"beken-7231n",
"beken-7231-crypt-tuya",
"beken-7231-tuya",
"ic/bk7231-qfn32",
"pcb/cb2l",
"pcb/cb2l-test"

View File

@@ -2,7 +2,7 @@
"_base": [
"beken-72xx",
"beken-7231n",
"beken-7231-crypt-tuya",
"beken-7231-tuya",
"ic/bk7231-qfn32",
"pcb/cb2s",
"pcb/cb2s-test"

View File

@@ -2,7 +2,7 @@
"_base": [
"beken-72xx",
"beken-7231n",
"beken-7231-crypt-tuya",
"beken-7231-tuya",
"ic/bk7231-qfn32",
"pcb/cb3l"
],

View File

@@ -2,7 +2,7 @@
"_base": [
"beken-72xx",
"beken-7231n",
"beken-7231-crypt-tuya",
"beken-7231-tuya",
"ic/bk7231-qfn32",
"pcb/cb3s"
],

View File

@@ -2,7 +2,7 @@
"_base": [
"beken-72xx",
"beken-7231n",
"beken-7231-crypt-tuya",
"beken-7231-tuya",
"ic/bk7231-qfn32",
"pcb/cb3se"
],

View File

@@ -2,7 +2,7 @@
"_base": [
"beken-72xx",
"beken-7231n",
"beken-7231-crypt-tuya",
"beken-7231-tuya",
"ic/bk7231-qfn32",
"pcb/cblc5",
"pcb/cblc5-test"

View File

@@ -2,7 +2,7 @@
"_base": [
"beken-72xx",
"beken-7231n",
"beken-7231-crypt-tuya",
"beken-7231-tuya",
"ic/bk7231-qfn32",
"pcb/cbu",
"pcb/cbu-test"

View File

@@ -3,7 +3,7 @@
"generic",
"beken-72xx",
"beken-7231n",
"beken-7231-crypt-tuya",
"beken-7231-tuya",
"ic/bk7231-qfn32"
],
"build": {

View File

@@ -4,7 +4,7 @@
"beken-72xx",
"beken-7231",
"beken-7231t",
"beken-7231-crypt-tuya",
"beken-7231-tuya",
"ic/bk7231-qfn32"
],
"build": {

View File

@@ -0,0 +1,102 @@
{
"_base": [
"generic",
"realtek-ambz2",
"realtek-ambz2-8720",
"realtek-ambz2-image",
"realtek-ambz2-2mb-992k",
"ic/rtl8720cf"
],
"build": {
"mcu": "rtl8720cf",
"variant": "generic-rtl8720cf-2mb-992k"
},
"name": "Generic - RTL8720CF (2M/992k)",
"symbol": "RTL8720CF (2M/992k)",
"url": "https://docs.libretiny.eu/boards/generic-rtl8720cf-2mb-992k/",
"vendor": "Generic",
"pcb": {
"pinout": {
"1": {
"IC": 15,
"ARD": "D0"
},
"2": {
"IC": 16,
"ARD": "D1"
},
"3": {
"IC": 18,
"ARD": "D2"
},
"4": {
"IC": 19,
"ARD": "D3"
},
"5": {
"IC": 20,
"ARD": "D4"
},
"6": {
"IC": 21,
"ARD": "D5"
},
"7": {
"IC": 22,
"ARD": "D6"
},
"8": {
"IC": 23,
"ARD": "D7"
},
"9": {
"IC": 24,
"ARD": "D8"
},
"10": {
"IC": 25,
"ARD": "D9"
},
"11": {
"IC": 26,
"ARD": "D10"
},
"12": {
"IC": 33,
"ARD": "D11"
},
"13": {
"IC": 34,
"ARD": "D12"
},
"14": {
"IC": 36,
"ARD": "D13"
},
"15": {
"IC": 37,
"ARD": "D14"
},
"16": {
"IC": 38,
"ARD": "D15"
},
"17": {
"IC": 39,
"ARD": "D16"
},
"18": {
"IC": 40,
"ARD": "D17"
},
"19": {
"IC": 1,
"ARD": "D18"
},
"20": {
"IC": 3,
"ARD": "D19"
}
}
}
}

View File

@@ -3,7 +3,7 @@
"beken-72xx",
"beken-7231",
"beken-7231t",
"beken-7231-crypt-tuya",
"beken-7231-tuya",
"ic/bk7231-qfn32",
"pcb/lsc-lma35"
],

View File

@@ -2,7 +2,7 @@
"_base": [
"beken-72xx",
"beken-7231n",
"beken-7231-crypt-tuya",
"beken-7231-tuya",
"ic/bk7231-qfn32",
"pcb/lsc-lma35"
],

View File

@@ -22,6 +22,10 @@ PinInfo lt_arduino_pin_info_list[PINS_COUNT] = {
{PA_14, PIN_GPIO | PIN_IRQ | PIN_PWM | PIN_SWD, PIN_NONE, 0},
// D7: PA15, PWM1, SWDIO
{PA_15, PIN_GPIO | PIN_IRQ | PIN_PWM | PIN_SWD, PIN_NONE, 0},
// D8: PA30, UART2_TX, I2C0_SDA, PWM4
{PA_30, PIN_GPIO | PIN_IRQ | PIN_PWM | PIN_I2C | PIN_UART, PIN_NONE, 0},
// D9: PA29, UART2_RX, I2C0_SCL, PWM4
{PA_29, PIN_GPIO | PIN_IRQ | PIN_PWM | PIN_I2C | PIN_UART, PIN_NONE, 0},
// A1: ADC2
{AD_2, PIN_ADC, PIN_NONE, 0},
};
@@ -34,6 +38,8 @@ PinInfo *lt_arduino_pin_gpio_map[] = {
[15] = &(lt_arduino_pin_info_list[6]), // PA_15 (D7)
[18] = &(lt_arduino_pin_info_list[3]), // PA_18 (D4)
[23] = &(lt_arduino_pin_info_list[4]), // PA_23 (D5)
[41] = &(lt_arduino_pin_info_list[7]), // AD_2 (A1)
[29] = &(lt_arduino_pin_info_list[8]), // PA_29 (D9)
[30] = &(lt_arduino_pin_info_list[7]), // PA_30 (D8)
[41] = &(lt_arduino_pin_info_list[9]), // AD_2 (A1)
};
// clang-format on

View File

@@ -6,14 +6,16 @@
// Pins
// ----
#define PINS_COUNT 8 // Total GPIO count
#define NUM_DIGITAL_PINS 7 // Digital inputs/outputs
#define PINS_COUNT 10 // Total GPIO count
#define NUM_DIGITAL_PINS 9 // Digital inputs/outputs
#define NUM_ANALOG_INPUTS 1 // ADC inputs
#define NUM_ANALOG_OUTPUTS 6 // PWM & DAC outputs
#define NUM_ANALOG_OUTPUTS 8 // PWM & DAC outputs
#define PINS_GPIO_MAX 41 // Last usable GPIO number
// Wire Interfaces
// ---------------
#define PIN_WIRE0_SCL 29u // PA_29
#define PIN_WIRE0_SDA 30u // PA_30
#define PIN_WIRE1_SCL 18u // PA_18
#define PIN_WIRE1_SDA 23u // PA_23
@@ -21,6 +23,8 @@
// ------------
#define PIN_SERIAL0_RX 18u // PA_18
#define PIN_SERIAL0_TX 23u // PA_23
#define PIN_SERIAL2_RX 29u // PA_29
#define PIN_SERIAL2_TX 30u // PA_30
// Pin function macros
// -------------------
@@ -34,24 +38,32 @@
#define PIN_PA15 15u // PA_15
#define PIN_PA18 18u // PA_18
#define PIN_PA23 23u // PA_23
#define PIN_PA29 29u // PA_29
#define PIN_PA30 30u // PA_30
#define PIN_PWM0 14u // PA_14
#define PIN_PWM1 15u // PA_15
#define PIN_PWM2 0u // PA_0
#define PIN_PWM3 12u // PA_12
#define PIN_PWM4 5u // PA_5
#define PIN_PWM4 29u // PA_29
#define PIN_RX0 18u // PA_18
#define PIN_RX2 29u // PA_29
#define PIN_SCK0 18u // PA_18
#define PIN_SCK1 18u // PA_18
#define PIN_SCL0 29u // PA_29
#define PIN_SCL1 18u // PA_18
#define PIN_SDA0 30u // PA_30
#define PIN_SDA1 23u // PA_23
#define PIN_TX0 23u // PA_23
#define PIN_TX2 30u // PA_30
// Port availability
// -----------------
#define HAS_SERIAL0 1
#define HAS_SERIAL2 1
#define HAS_WIRE0 1
#define HAS_WIRE1 1
#define SERIAL_INTERFACES_COUNT 1
#define WIRE_INTERFACES_COUNT 1
#define SERIAL_INTERFACES_COUNT 2
#define WIRE_INTERFACES_COUNT 2
// Arduino pin names
// -----------------
@@ -62,6 +74,8 @@
#define PIN_D5 23u // PA_23
#define PIN_D6 14u // PA_14
#define PIN_D7 15u // PA_15
#define PIN_D8 30u // PA_30
#define PIN_D9 29u // PA_29
#define PIN_A1 41u // AD_2
// Static pin names
@@ -74,3 +88,5 @@ static const unsigned char D4 = PIN_D4;
static const unsigned char D5 = PIN_D5;
static const unsigned char D6 = PIN_D6;
static const unsigned char D7 = PIN_D7;
static const unsigned char D8 = PIN_D8;
static const unsigned char D9 = PIN_D9;

View File

@@ -22,6 +22,10 @@ PinInfo lt_arduino_pin_info_list[PINS_COUNT] = {
{PA_14, PIN_GPIO | PIN_IRQ | PIN_PWM | PIN_SWD, PIN_NONE, 0},
// D6: PA15, PWM1, SWDIO
{PA_15, PIN_GPIO | PIN_IRQ | PIN_PWM | PIN_SWD, PIN_NONE, 0},
// D7: PA30, UART2_TX, I2C0_SDA, PWM4
{PA_30, PIN_GPIO | PIN_IRQ | PIN_PWM | PIN_I2C | PIN_UART, PIN_NONE, 0},
// D8: PA29, UART2_RX, I2C0_SCL, PWM4
{PA_29, PIN_GPIO | PIN_IRQ | PIN_PWM | PIN_I2C | PIN_UART, PIN_NONE, 0},
// A1: ADC2
{AD_2, PIN_ADC, PIN_NONE, 0},
};
@@ -34,6 +38,8 @@ PinInfo *lt_arduino_pin_gpio_map[] = {
[18] = &(lt_arduino_pin_info_list[3]), // PA_18 (D3)
[19] = &(lt_arduino_pin_info_list[1]), // PA_19 (D1)
[23] = &(lt_arduino_pin_info_list[4]), // PA_23 (D4)
[41] = &(lt_arduino_pin_info_list[7]), // AD_2 (A1)
[29] = &(lt_arduino_pin_info_list[8]), // PA_29 (D8)
[30] = &(lt_arduino_pin_info_list[7]), // PA_30 (D7)
[41] = &(lt_arduino_pin_info_list[9]), // AD_2 (A1)
};
// clang-format on

View File

@@ -6,22 +6,27 @@
// Pins
// ----
#define PINS_COUNT 8 // Total GPIO count
#define NUM_DIGITAL_PINS 7 // Digital inputs/outputs
#define PINS_COUNT 10 // Total GPIO count
#define NUM_DIGITAL_PINS 9 // Digital inputs/outputs
#define NUM_ANALOG_INPUTS 2 // ADC inputs
#define NUM_ANALOG_OUTPUTS 5 // PWM & DAC outputs
#define NUM_ANALOG_OUTPUTS 7 // PWM & DAC outputs
#define PINS_GPIO_MAX 41 // Last usable GPIO number
// Wire Interfaces
// ---------------
#define PIN_WIRE1_SCL 18u // PA_18
#define PIN_WIRE1_SDA 23u // PA_23
#define PIN_WIRE0_SCL 29u // PA_29
#define PIN_WIRE0_SDA_0 19u // PA_19
#define PIN_WIRE0_SDA_1 30u // PA_30
#define PIN_WIRE1_SCL 18u // PA_18
#define PIN_WIRE1_SDA 23u // PA_23
// Serial ports
// ------------
#define PIN_SERIAL0_CTS 19u // PA_19
#define PIN_SERIAL0_RX 18u // PA_18
#define PIN_SERIAL0_TX 23u // PA_23
#define PIN_SERIAL2_RX 29u // PA_29
#define PIN_SERIAL2_TX 30u // PA_30
// Pin function macros
// -------------------
@@ -39,24 +44,31 @@
#define PIN_PA18 18u // PA_18
#define PIN_PA19 19u // PA_19
#define PIN_PA23 23u // PA_23
#define PIN_PA29 29u // PA_29
#define PIN_PA30 30u // PA_30
#define PIN_PWM0 14u // PA_14
#define PIN_PWM1 15u // PA_15
#define PIN_PWM3 12u // PA_12
#define PIN_PWM4 5u // PA_5
#define PIN_PWM4 29u // PA_29
#define PIN_RX0 18u // PA_18
#define PIN_RX2 29u // PA_29
#define PIN_SCK0 18u // PA_18
#define PIN_SCK1 18u // PA_18
#define PIN_SCL0 29u // PA_29
#define PIN_SCL1 18u // PA_18
#define PIN_SDA0 19u // PA_19
#define PIN_SDA0 30u // PA_30
#define PIN_SDA1 23u // PA_23
#define PIN_TX0 23u // PA_23
#define PIN_TX2 30u // PA_30
// Port availability
// -----------------
#define HAS_SERIAL0 1
#define HAS_SERIAL2 1
#define HAS_WIRE0 1
#define HAS_WIRE1 1
#define SERIAL_INTERFACES_COUNT 1
#define WIRE_INTERFACES_COUNT 1
#define SERIAL_INTERFACES_COUNT 2
#define WIRE_INTERFACES_COUNT 2
// Arduino pin names
// -----------------
@@ -67,6 +79,8 @@
#define PIN_D4 23u // PA_23
#define PIN_D5 14u // PA_14
#define PIN_D6 15u // PA_15
#define PIN_D7 30u // PA_30
#define PIN_D8 29u // PA_29
#define PIN_A0 19u // PA_19
#define PIN_A1 41u // AD_2
@@ -81,3 +95,5 @@ static const unsigned char D3 = PIN_D3;
static const unsigned char D4 = PIN_D4;
static const unsigned char D5 = PIN_D5;
static const unsigned char D6 = PIN_D6;
static const unsigned char D7 = PIN_D7;
static const unsigned char D8 = PIN_D8;

View File

@@ -3,7 +3,7 @@
"beken-72xx",
"beken-7231",
"beken-7231t",
"beken-7231-crypt-tuya",
"beken-7231-tuya",
"ic/bk7231-qfn32",
"pcb/wb1s"
],

View File

@@ -2,7 +2,7 @@
"_base": [
"beken-72xx",
"beken-7231n",
"beken-7231-crypt-tuya",
"beken-7231-tuya",
"ic/bk7231-qfn32",
"pcb/wb2l",
"pcb/wb2l-test",

View File

@@ -3,7 +3,7 @@
"beken-72xx",
"beken-7231",
"beken-7231t",
"beken-7231-crypt-tuya",
"beken-7231-tuya",
"ic/bk7231-qfn32",
"pcb/wb2l",
"pcb/wb2l-test"

View File

@@ -3,7 +3,7 @@
"beken-72xx",
"beken-7231",
"beken-7231t",
"beken-7231-crypt-tuya",
"beken-7231-tuya",
"ic/bk7231-qfn32",
"pcb/wb2s",
"pcb/wb2s-test"

View File

@@ -3,7 +3,7 @@
"beken-72xx",
"beken-7231",
"beken-7231t",
"beken-7231-crypt-tuya",
"beken-7231-tuya",
"ic/bk7231-qfn32",
"pcb/wb3l"
],

View File

@@ -3,7 +3,7 @@
"beken-72xx",
"beken-7231",
"beken-7231t",
"beken-7231-crypt-tuya",
"beken-7231-tuya",
"ic/bk7231-qfn32",
"pcb/wb3s"
],

View File

@@ -3,7 +3,7 @@
"beken-72xx",
"beken-7231",
"beken-7231t",
"beken-7231-crypt-tuya",
"beken-7231-tuya",
"ic/bk7231-qfn32",
"pcb/wblc5",
"pcb/wblc5-test"

View File

@@ -1,10 +1,12 @@
{
"_base": [
"realtek-ambz",
"realtek-ambz-tuya",
"realtek-ambz-2mb-788k",
"ic/rtl8710bn",
"pcb/wr2-base",
"pcb/wr2"
"pcb/wr2",
"pcb/wr2-test"
],
"build": {
"mcu": "rtl8710bn",

View File

@@ -1,10 +1,12 @@
{
"_base": [
"realtek-ambz",
"realtek-ambz-tuya",
"realtek-ambz-2mb-788k",
"ic/rtl8710bn",
"pcb/wr2-base",
"pcb/wr2e"
"pcb/wr2e",
"pcb/wr2e-test"
],
"build": {
"mcu": "rtl8710bn",

View File

@@ -1,6 +1,7 @@
{
"_base": [
"realtek-ambz",
"realtek-ambz-tuya",
"realtek-ambz-2mb-788k",
"realtek-ambz-bx",
"ic/rtl8710bn",

View File

@@ -1,6 +1,7 @@
{
"_base": [
"realtek-ambz",
"realtek-ambz-tuya",
"realtek-ambz-2mb-788k",
"realtek-ambz-bx",
"ic/rtl8710bn",

View File

@@ -1,6 +1,7 @@
{
"_base": [
"realtek-ambz",
"realtek-ambz-tuya",
"realtek-ambz-2mb-788k",
"ic/rtl8710bn",
"pcb/wr3-base",

View File

@@ -1,6 +1,7 @@
{
"_base": [
"realtek-ambz",
"realtek-ambz-tuya",
"realtek-ambz-2mb-788k",
"ic/rtl8710bn",
"pcb/wr3-base",

View File

@@ -1,6 +1,7 @@
{
"_base": [
"realtek-ambz",
"realtek-ambz-tuya",
"realtek-ambz-2mb-788k",
"realtek-ambz-bx",
"ic/rtl8710bn",

View File

@@ -1,6 +1,7 @@
{
"_base": [
"realtek-ambz",
"realtek-ambz-tuya",
"realtek-ambz-2mb-788k",
"realtek-ambz-bx",
"ic/rtl8710bn",

View File

@@ -1,6 +1,7 @@
{
"_base": [
"realtek-ambz",
"realtek-ambz-tuya",
"realtek-ambz-2mb-788k",
"ic/rtl8710bn",
"pcb/wr3-base",

View File

@@ -538,7 +538,7 @@ image_app_rblh = "${BUILD_DIR}/image_${MCULC}_app.${FLASH_RBL_OFFSET}.rblh"
image_ota_rbl = "${BUILD_DIR}/image_${MCULC}_app.ota.rbl"
env.Replace(
# linker command (encryption + packaging)
LINK="${LTCHIPTOOL} link2bin ${BOARD_JSON} '' ''",
LINK='${LTCHIPTOOL} link2bin ${BOARD_JSON} "" ""',
# UF2OTA input list
UF2OTA=[
# app binary image (enc+crc) for flasher

View File

@@ -1,6 +1,7 @@
# Copyright (c) Kuba Szczodrzyński 2022-07-20.
from os.path import join
from os.path import isfile, join
from shutil import copyfile
from platformio.platform.base import PlatformBase
from platformio.platform.board import PlatformBoardConfig
@@ -52,9 +53,10 @@ queue.AppendPublic(
"-mthumb",
"-mcmse",
"-mfloat-abi=soft",
"--specs=nosys.specs",
"--specs=nano.specs",
"-Wl,--use-blx",
"-Wl,--undefined=gRamStartFun",
"-Wl,--warn-section-align",
"-Wl,-wrap,aesccmp_construct_mic_iv",
"-Wl,-wrap,aesccmp_construct_mic_header1",
"-Wl,-wrap,aesccmp_construct_ctr_preload",
@@ -91,6 +93,7 @@ queue.AppendPublic(
"-Wl,-wrap,memset",
# TODO remove this if possible
"-Wl,-wrap,putc",
# rt_printf wrappers are not here, as they're just changing code using #defines
],
)
@@ -103,17 +106,7 @@ queue.AddLibrary(
# cmsis
"+<soc/realtek/8710c/cmsis/rtl8710c/source/ram/*.c>",
"+<soc/realtek/8710c/cmsis/rtl8710c/source/ram_s/app_start.c>",
# console
"+<common/api/at_cmd/atcmd_bt.c>",
"+<common/api/at_cmd/atcmd_lwip.c>",
"+<common/api/at_cmd/atcmd_mp_ext2.c>",
"+<common/api/at_cmd/atcmd_mp.c>",
"+<common/api/at_cmd/atcmd_sys.c>",
"+<common/api/at_cmd/atcmd_wifi.c>",
"+<common/api/at_cmd/log_service.c>",
"+<soc/realtek/8710c/app/shell/cmd_shell.c>",
"+<soc/realtek/8710c/app/shell/ram_s/consol_cmds.c>",
"+<soc/realtek/8710c/misc/driver/rtl_console.c>",
"+<soc/realtek/8710c/misc/driver/flash_api_ext.c>",
# utilities
"+<common/utilities/cJSON.c>",
"+<common/utilities/http_client.c>",
@@ -125,11 +118,6 @@ queue.AddLibrary(
"+<os/freertos/freertos_service.c>",
"+<os/os_dep/device_lock.c>",
"+<os/os_dep/osdep_service.c>",
# os - freertos
"+<os/freertos/freertos_v10.0.1/Source/*.c>",
# os - freertos - portable
"+<os/freertos/freertos_v10.0.1/Source/portable/MemMang/heap_5.c>",
"+<os/freertos/freertos_v10.0.1/Source/portable/GCC/ARM_RTL8710C/port.c>",
# peripheral - api
"+<common/mbed/targets/hal/rtl8710c/*.c>",
# peripheral - hal
@@ -146,13 +134,9 @@ queue.AddLibrary(
"+<common/file_system/fatfs/r0.10c/src/ff.c>",
"+<common/file_system/fatfs/r0.10c/src/option/ccsbcs.c>",
"+<common/file_system/ftl/ftl.c>",
# TODO remove this
"+<common/example/example_entry.c>",
"+<common/example/wlan_fast_connect/example_wlan_fast_connect.c>",
],
includes=[
"+<$SDK_DIR/project/realtek_amebaz2_v0_example/inc>",
"+<common/api/at_cmd>",
"+<common/api/platform>",
"+<common/api>",
"+<common/application>",
@@ -170,11 +154,8 @@ queue.AddLibrary(
"+<common/test>",
"+<common/utilities>",
"+<os/freertos>",
"+<os/freertos/freertos_v10.0.1/Source/include>",
"+<os/freertos/freertos_v10.0.1/Source/portable/GCC/ARM_RTL8710C>",
"+<os/os_dep/include>",
"+<soc/realtek/8710c/app/rtl_printf/include>",
"+<soc/realtek/8710c/app/shell>",
"+<soc/realtek/8710c/app/stdio_port>",
"+<soc/realtek/8710c/cmsis/cmsis-core/include>",
"+<soc/realtek/8710c/cmsis/rtl8710c/include>",
@@ -205,6 +186,14 @@ queue.AddLibrary(
),
)
# Sources - FreeRTOS
env.Replace(FREERTOS_PORT=env["FAMILY_NAME"], FREERTOS_PORT_DEFINE="REALTEK_AMBZ2")
queue.AddExternalLibrary("freertos")
queue.AddExternalLibrary("freertos-port")
# Sources - lwIP
queue.AddExternalLibrary("lwip", port="ambz2")
# Sources - network utilities
queue.AddLibrary(
name="ambz2_net",
@@ -214,6 +203,7 @@ queue.AddLibrary(
"+<common/api/lwip_netconf.c>",
# network - api - wifi
"+<common/api/wifi/*.c>",
"ARDUINO" in "ENV" and "-<common/api/wifi/wifi_ind.c>",
# network - api - wifi - rtw_wpa_supplicant
"+<common/api/wifi/rtw_wpa_supplicant/src/crypto/tls_polarssl.c>",
"+<common/api/wifi/rtw_wpa_supplicant/wpa_supplicant/*.c>",
@@ -231,7 +221,6 @@ queue.AddLibrary(
"+<common/network/httpd/httpd_tls.c>",
# network
"+<common/network/dhcp/dhcps.c>",
"+<common/network/sntp/sntp.c>",
# network - websocket
"+<common/network/websocket/*.c>",
# network - mdns
@@ -285,6 +274,7 @@ queue.AddLibrary(
# "+<src/ble/profile/server/hids_rmc.c>",
"+<src/ble/profile/server/simple_ble_service.c>",
"+<src/mcu/module/data_uart_cmd/user_cmd_parse.c>",
"-<board/common/src/bt_uart_bridge.c>",
],
includes=[
"+<.>",
@@ -315,34 +305,6 @@ queue.AddLibrary(
),
)
# Sources - lwIP 2.0.2
queue.AddLibrary(
name="ambz2_lwip",
base_dir=join(COMPONENT_DIR, "common", "network", "lwip", "lwip_v2.0.2"),
srcs=[
"+<port/realtek/freertos/*.c>",
"+<src/api/*.c>",
"+<src/apps/ping/*.c>",
"+<src/apps/mdns/*.c>",
"+<src/core/*.c>",
"+<src/core/ipv4/*.c>",
"+<src/core/ipv6/*.c>",
"+<src/netif/ethernet.c>",
],
includes=[
"+<port/realtek>",
"+<port/realtek/freertos>",
"+<src/include>",
"+<src/include/netif>",
],
options=dict(
CFLAGS=[
"-Wno-implicit-function-declaration",
],
),
)
# Sources - mbedTLS
queue.AddLibrary(
name="ambz2_mbedtls",
@@ -436,10 +398,38 @@ env.Replace(
SIZEPRINTCMD="$SIZETOOL -B -d $SOURCES",
)
# Bootloader - copy for linking
# fmt: off
bootloader_src = env.subst("${SDK_DIR}/component/soc/realtek/8710c/misc/bsp/image/bootloader.axf")
bootloader_dst = env.subst("${BUILD_DIR}/bootloader.axf")
# fmt: on
if not isfile(bootloader_dst):
copyfile(bootloader_src, bootloader_dst)
# OTA2 clearing - 4096 bytes of 0xFF
image_ota_clear = env.subst("${BUILD_DIR}/raw_ota_clear.bin")
if not isfile(image_ota_clear):
with open(image_ota_clear, "wb") as f:
f.write(b"\xFF" * 4096)
# Build all libraries
queue.BuildLibraries()
# Main firmware outputs and actions
image_part_table = "${BUILD_DIR}/image_part_table.${FLASH_PART_TABLE_OFFSET}.bin"
image_bootloader = "${BUILD_DIR}/image_bootloader.${FLASH_BOOT_OFFSET}.bin"
image_firmware_is = "${BUILD_DIR}/image_firmware_is.${FLASH_OTA1_OFFSET}.bin"
env.Replace(
# TODO
# linker command (dual .bin outputs)
LINK='${LTCHIPTOOL} link2bin ${BOARD_JSON} "" ""',
# UF2OTA input list
UF2OTA=[
# same OTA images for flasher and device
f"{image_firmware_is},{image_firmware_is}=device:ota1,ota2;flasher:ota1,ota2",
# having flashed an application image, update the bootloader and partition table (incl. keys)
f"{image_bootloader}=device:boot;flasher:boot",
f"{image_part_table}=device:part_table;flasher:part_table",
# clearing headers of the "other" OTA image (hence the indexes are swapped)
f"{image_ota_clear},{image_ota_clear}=device:ota2,ota1;flasher:ota2,ota1",
],
)

View File

@@ -34,7 +34,7 @@ for f in family.inheritance:
code = f"{f.code}_arduino"
path = join("$CORES_DIR", f.name, "arduino")
found = found or env.AddCoreSources(queue, name=code, path=join(path, "src"))
found = env.AddCoreSources(queue, name=code, path=join(path, "src")) or found
env.AddArduinoLibraries(queue, name=code, path=join(path, "libraries"))
if f.short_name:
@@ -73,13 +73,6 @@ queue.AppendPublic(
("ARDUINO_SDK", 1),
],
LINKFLAGS=[
"--specs=nosys.specs",
"-Wl,--as-needed",
"-Wl,--build-id=none",
"-Wl,--cref",
"-Wl,--no-enum-size-warning",
"-Wl,--no-undefined",
"-Wl,--warn-common",
# wrappers from posix/time.c
"-Wl,-wrap,gettimeofday",
"-Wl,-wrap,settimeofday",

View File

@@ -95,7 +95,7 @@ for f in family.inheritance:
env.Prepend(CPPDEFINES=[(f"LT_{f.code.upper()}", "1")])
# Sources - external libraries
queue.AddExternalLibrary("ltchiptool") # uf2ota source code
queue.AddExternalLibrary("uf2ota")
queue.AddExternalLibrary("flashdb")
queue.AddExternalLibrary("printf")
@@ -138,11 +138,14 @@ queue.AppendPublic(
LINKFLAGS=[
"-g2",
"-Os",
"-Wl,--as-needed",
"-Wl,--build-id=none",
"-Wl,--cref",
"-Wl,--gc-sections",
"-Wl,--no-enum-size-warning",
"-Wl,--no-wchar-size-warning",
"-Wl,--no-undefined",
"-Wl,--warn-common",
# malloc.c wrappers
"-Wl,-wrap,malloc",
"-Wl,-wrap,calloc",

View File

@@ -20,13 +20,21 @@ def env_load_defines(env: Environment, path: str):
line = line[7:].strip()
line = line.split(None, 2)
if len(line) == 1:
env.Append(CPPDEFINES=[(line[0], 1)])
config[line[0]] = 1
key, value = line[0], 1
elif len(line) == 2:
env.Append(CPPDEFINES=[(line[0], line[1])])
config[line[0]] = line[1]
key, value = line[0], line[1]
else:
raise ValueError(f"Unknown directive: {line}")
for tpl in env["CPPDEFINES"]:
if isinstance(tpl, tuple):
k = tpl[0]
else:
k = tpl
if k == key:
env["CPPDEFINES"].remove(tpl)
break
env.Append(CPPDEFINES=[(key, value)])
config[key] = value
env.Append(
CONFIG=config,
)

View File

@@ -46,10 +46,12 @@ def env_add_core_sources(env: Environment, queue, name: str, path: str) -> bool:
base_dir=path,
srcs=[
"+<*.c*>",
"+<api/*.c>",
"+<common/*.c*>",
"+<compat/*.c*>",
"+<port/*.c*>",
"+<posix/*.c>",
"+<wiring/*.c>",
"+<wraps/*.c>",
],
includes=[
@@ -58,6 +60,7 @@ def env_add_core_sources(env: Environment, queue, name: str, path: str) -> bool:
"!<compat>",
"!<config>",
"!<port>",
"!<wiring>",
],
)
queue.AddLibrary(

View File

@@ -59,14 +59,23 @@ def env_uf2ota(env: Environment, *args, **kwargs):
def env_flash_write(env: Environment):
# UPLOAD_PROTOCOL = upload_protocol or board->upload.protocol
# UPLOAD_PORT = upload_port (PIO can choose this automatically I guess)
# UPLOAD_SPEED = upload_speed or board->upload.speed (**can be empty**)
protocol = env.subst("${UPLOAD_PROTOCOL}")
speed = env.subst("${UPLOAD_SPEED}")
if protocol == "uart":
# upload via UART
if speed:
return [
"-d",
"${UPLOAD_PORT}",
"-b",
"${UPLOAD_SPEED}",
]
return [
"-d",
"${UPLOAD_PORT}",
"-b",
"${UPLOAD_SPEED}",
]
else:
# can't upload via ltchiptool

View File

@@ -0,0 +1,5 @@
#pragma once
#error "Don't include this file directly"
#define LT_HW_BLE 1

View File

@@ -0,0 +1,5 @@
#pragma once
#error "Don't include this file directly"
#define LT_HW_BLE 1

View File

@@ -0,0 +1,5 @@
#pragma once
#error "Don't include this file directly"
#define LT_HW_BLE 1

View File

@@ -1,59 +1,40 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-23. */
#include "Serial.h"
#include "SerialPrivate.h"
#include <Arduino.h>
extern "C" {
#include <uart_pub.h>
extern void bk_send_byte(uint8_t uport, uint8_t data);
extern void uart_hw_set_change(uint8_t uport, bk_uart_config_t *uart_config);
extern int uart_rx_callback_set(int uport, uart_callback callback, void *param);
} // extern "C"
#if HAS_SERIAL1
#if LT_HW_UART1
SerialClass Serial1(UART1_PORT);
#endif
#if HAS_SERIAL2
#if LT_HW_UART2
SerialClass Serial2(UART2_PORT);
#endif
SerialClass::SerialClass(uint8_t port) {
this->port = port;
this->buf = NULL;
}
#if LT_AUTO_DOWNLOAD_REBOOT
static uint8_t adrState = 0;
static const uint8_t adrCmd[] = {0x01, 0xE0, 0xFC, 0x01, 0x00};
static void adrParse(uint8_t c) {
// parse and respond to link check command (CMD_LinkCheck=0)
adrState = (adrState + 1) * (c == adrCmd[adrState]);
if (adrState == 5) {
LT_I("Auto download mode: rebooting");
LT.restart();
}
}
#endif
static void callback(int port, void *param) {
RingBuffer *buf = (RingBuffer *)param;
int ch;
while ((ch = uart_read_byte(port)) != -1) {
#if LT_AUTO_DOWNLOAD_REBOOT && defined(PIN_SERIAL1_RX)
#if LT_AUTO_DOWNLOAD_REBOOT && defined(LT_UART_ADR_PATTERN) && PIN_SERIAL1_RX != PIN_INVALID
// parse UART protocol commands on UART1
if (port == UART1_PORT)
adrParse(ch);
SerialClass::adrParse(ch);
#endif
buf->store_char(ch);
pBUF->store_char(ch);
}
}
void SerialClass::begin(unsigned long baudrate, uint16_t config) {
if (!this->data) {
this->data = new SerialData();
this->buf = &BUF;
}
if (this->baudrate != baudrate || this->config != config)
this->configure(baudrate, config);
}
void SerialClass::configure(unsigned long baudrate, uint16_t config) {
if (!this->data)
return;
uint8_t dataWidth = ((config & SERIAL_DATA_MASK) >> 8) - 1; // 0x100..0x400 -> 0..3
uint8_t parity = 3 - (config & SERIAL_PARITY_MASK); // 0x3..0x1 -> 0..2
uint8_t stopBits = (config & SERIAL_STOP_BIT_MASK) == SERIAL_STOP_BIT_2; // 0x10..0x30 -> 0..1
@@ -66,17 +47,21 @@ void SerialClass::begin(unsigned long baudrate, uint16_t config) {
.flow_control = FLOW_CTRL_DISABLED,
};
if (this->buf) {
this->buf->clear();
} else {
this->buf = new RingBuffer();
}
if (port == 1)
uart1_init();
else if (port == 2)
uart2_init();
uart_hw_set_change(port, &cfg);
uart_rx_callback_set(port, callback, this->buf);
uart_rx_callback_set(port, callback, &BUF);
this->baudrate = baudrate;
this->config = config;
}
void SerialClass::end() {
if (!this->data)
return;
uart_rx_callback_set(port, NULL, NULL);
switch (port) {
case 1:
@@ -86,26 +71,22 @@ void SerialClass::end() {
uart2_exit();
break;
}
delete this->buf;
}
int SerialClass::available() {
return buf->available();
}
int SerialClass::peek() {
return buf->peek();
}
int SerialClass::read() {
return buf->read_char();
delete DATA;
this->data = NULL;
this->buf = NULL;
this->baudrate = 0;
}
void SerialClass::flush() {
if (!this->data)
return;
uart_wait_tx_over();
}
size_t SerialClass::write(uint8_t c) {
if (!this->data)
return 0;
bk_send_byte(port, c);
return 1;
}

View File

@@ -0,0 +1,14 @@
/* Copyright (c) Kuba Szczodrzyński 2023-05-24. */
#pragma once
#include <Arduino.h>
#include <sdk_private.h>
typedef struct {
RingBuffer buf;
} SerialData;
#define DATA ((SerialData *)data)
#define BUF (DATA->buf)
#define pBUF ((RingBuffer *)param)

View File

@@ -2,7 +2,6 @@
#error "Don't include this file directly"
#define LT_ARD_HAS_WIFI 1
#define LT_ARD_HAS_SERIAL 1
#define LT_ARD_HAS_WIFI 1
#define LT_ARD_HAS_SERIAL 1
#define LT_ARD_MD5_HOSTAPD 1

View File

@@ -1,13 +1,6 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-19. */
#include <Arduino.h>
#include <include.h>
#include <arm_arch.h>
#include <bk_timer.h>
#include <bk_timer_pub.h>
#include <rtos_pub.h>
#include <sys_rtos.h>
#include "wiring_private.h"
#if LT_BK7231Q
#undef LT_MICROS_HIGH_RES
@@ -18,10 +11,6 @@
#define US_PER_OVERFLOW (portTICK_PERIOD_MS * 1000)
#define TICKS_PER_OVERFLOW (TICKS_PER_US * US_PER_OVERFLOW)
void delayMilliseconds(unsigned long ms) {
rtos_delay_milliseconds(ms);
}
#if LT_MICROS_HIGH_RES
static uint32_t getTicksCount() {
// copied from bk_timer_ctrl(), for speeds
@@ -107,8 +96,22 @@ unsigned long micros() {
#endif
}
void yield() {
runPeriodicTasks();
vTaskDelay(1);
taskYIELD();
void pinRemoveMode(PinInfo *pin, uint32_t mask) {
PinData *data = pinData(pin);
if ((mask & PIN_GPIO) && (pin->enabled & PIN_GPIO)) {
gpio_config(pin->gpio, GMODE_INPUT_PULLDOWN);
pinDisable(pin, PIN_GPIO);
}
if ((mask & PIN_IRQ) && (pin->enabled & PIN_IRQ)) {
data->irqHandler = NULL;
gpio_int_disable(pin->gpio);
pinDisable(pin, PIN_IRQ);
}
if ((mask & PIN_PWM) && (pin->enabled & PIN_PWM)) {
data->pwm->cfg.bits.en = PWM_DISABLE;
__wrap_bk_printf_disable();
sddev_control(PWM_DEV_NAME, CMD_PWM_DEINIT_PARAM, data->pwm);
__wrap_bk_printf_enable();
pinDisable(pin, PIN_PWM);
}
}

View File

@@ -1,10 +1,6 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-20. */
#include <Arduino.h>
#include <gpio_pub.h>
#include <pwm_pub.h>
#include <saradc_pub.h>
#include "wiring_private.h"
static GPIO_INDEX pwmToGpio[] = {
GPIO6, // PWM0
@@ -59,11 +55,7 @@ static pwm_param_t pwm;
static uint16_t adcData[1];
uint16_t analogReadVoltage(pin_size_t pinNumber) {
PinInfo *pin = pinInfo(pinNumber);
if (!pin)
return 0;
if (!pinSupported(pin, PIN_ADC))
return 0;
pinCheckGetInfo(pinNumber, PIN_ADC, 0);
UINT32 status;
saradc_desc_t adc;
@@ -90,11 +82,10 @@ uint16_t analogReadMaxVoltage(pin_size_t pinNumber) {
}
void analogWrite(pin_size_t pinNumber, int value) {
PinInfo *pin = pinInfo(pinNumber);
if (!pin)
return;
if (!pinSupported(pin, PIN_PWM))
return;
pinCheckGetData(pinNumber, PIN_PWM, );
// GPIO can't be used together with PWM
pinRemoveMode(pin, PIN_GPIO | PIN_IRQ);
float percent = value * 1.0 / ((1 << _analogWriteResolution) - 1);
uint32_t frequency = 26 * _analogWritePeriod - 1;
@@ -122,8 +113,9 @@ void analogWrite(pin_size_t pinNumber, int value) {
sddev_control(PWM_DEV_NAME, CMD_PWM_INIT_LEVL_SET_HIGH, &pwm.channel);
sddev_control(PWM_DEV_NAME, CMD_PWM_UNIT_ENABLE, &pwm.channel);
__wrap_bk_printf_enable();
pin->enabled &= ~PIN_GPIO;
pin->enabled |= PIN_PWM;
// pass global PWM object pointer
data->pwm = &pwm;
pinEnable(pin, PIN_PWM);
} else {
// update duty cycle
sddev_control(PWM_DEV_NAME, CMD_PWM_SET_DUTY_CYCLE, &pwm);
@@ -131,11 +123,7 @@ void analogWrite(pin_size_t pinNumber, int value) {
} else {
if (pinEnabled(pin, PIN_PWM)) {
// disable PWM
pwm.cfg.bits.en = PWM_DISABLE;
__wrap_bk_printf_disable();
sddev_control(PWM_DEV_NAME, CMD_PWM_DEINIT_PARAM, &pwm);
__wrap_bk_printf_enable();
pin->enabled &= ~PIN_PWM;
pinRemoveMode(pin, PIN_PWM);
}
// force level as LOW
pinMode(pinNumber, OUTPUT);

View File

@@ -0,0 +1,23 @@
/* Copyright (c) Kuba Szczodrzyński 2023-05-24. */
#pragma once
#include <Arduino.h>
#include <sdk_private.h>
#ifdef __cplusplus
extern "C" {
#endif
struct PinData_s {
pwm_param_t *pwm;
PinMode gpioMode;
PinStatus irqMode;
void *irqHandler;
void *irqParam;
bool irqChange;
};
#ifdef __cplusplus
} // extern "C"
#endif

View File

@@ -1,20 +1,16 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-20. */
#include <Arduino.h>
#include <gpio_pub.h>
#include "wiring_private.h"
void pinMode(pin_size_t pinNumber, PinMode pinMode) {
PinInfo *pin = pinInfo(pinNumber);
if (!pin)
return;
if (!pinSupported(pin, PIN_GPIO))
return;
if (pinEnabled(pin, PIN_PWM))
// disable PWM before using the pin
analogWrite(pinNumber, 0);
if (pinEnabled(pin, PIN_GPIO) && pin->mode == pinMode)
pinCheckGetData(pinNumber, PIN_GPIO, );
if (pinEnabled(pin, PIN_GPIO) && data->gpioMode == pinMode)
return;
// GPIO can't be used together with PWM
pinRemoveMode(pin, PIN_PWM);
switch (pinMode) {
case INPUT:
gpio_config(pin->gpio, GMODE_INPUT);
@@ -31,34 +27,21 @@ void pinMode(pin_size_t pinNumber, PinMode pinMode) {
case OUTPUT_OPENDRAIN:
gpio_config(pin->gpio, GMODE_SET_HIGH_IMPENDANCE);
break;
default:
return;
}
pin->enabled |= PIN_GPIO;
pin->mode = pinMode;
pinEnable(pin, PIN_GPIO);
data->gpioMode = pinMode;
}
void digitalWrite(pin_size_t pinNumber, PinStatus status) {
// verify level is 0 or 1
if (status > HIGH)
return;
PinInfo *pin = pinInfo(pinNumber);
if (!pin)
return;
// pin is not GPIO yet or not OUTPUT; enable or disable input pullup
if (!pinEnabled(pin, PIN_GPIO) || !pinIsOutput(pin)) {
pinMode(pinNumber, status * INPUT_PULLUP);
return;
}
// write the new state
gpio_output(pin->gpio, status);
pinCheckGetData(pinNumber, PIN_GPIO, );
pinSetOutputPull(pin, data, pinNumber, status);
gpio_output(pin->gpio, !!status);
}
PinStatus digitalRead(pin_size_t pinNumber) {
PinInfo *pin = pinInfo(pinNumber);
if (!pin)
return 0;
// pin is not GPIO yet or not INPUT; change the mode
if (!pinEnabled(pin, PIN_GPIO) || !pinIsInput(pin))
pinMode(pinNumber, INPUT);
// read the value
pinCheckGetData(pinNumber, PIN_GPIO, LOW);
pinSetInputMode(pin, data, pinNumber);
return gpio_input(pin->gpio);
}

View File

@@ -1,98 +1,70 @@
/* Copyright (c) Kuba Szczodrzyński 2022-07-31. */
#include <Arduino.h>
#include <gpio_pub.h>
static void *irqHandlerList[PINS_COUNT] = {NULL};
static void *irqHandlerArgs[PINS_COUNT] = {NULL};
static bool irqChangeList[PINS_COUNT];
#include "wiring_private.h"
static void irqHandler(unsigned char gpio) {
PinInfo *pin = pinByGpio(gpio);
if (pin == NULL)
return;
uint32_t index = pinIndex(pin);
if (!irqHandlerList[index])
PinData *data = pinData(pin);
if (!data->irqHandler)
return;
if (irqChangeList[index]) {
if (pin->mode == INPUT_PULLDOWN) {
pin->mode = INPUT_PULLUP;
if (data->irqChange) {
if (data->gpioMode == INPUT_PULLDOWN) {
data->gpioMode = INPUT_PULLUP;
gpio_int_enable(pin->gpio, GPIO_INT_LEVEL_FALLING, irqHandler);
} else if (pin->mode == INPUT_PULLUP) {
pin->mode = INPUT_PULLDOWN;
} else if (data->gpioMode == INPUT_PULLUP) {
data->gpioMode = INPUT_PULLDOWN;
gpio_int_enable(pin->gpio, GPIO_INT_LEVEL_RISING, irqHandler);
}
}
if (irqHandlerArgs[index] == NULL) {
((voidFuncPtr)irqHandlerList[index])();
} else {
((voidFuncPtrParam)irqHandlerList[index])(irqHandlerArgs[index]);
}
}
void attachInterrupt(pin_size_t interruptNumber, voidFuncPtr callback, PinStatus mode) {
attachInterruptParam(interruptNumber, (voidFuncPtrParam)callback, mode, NULL);
if (!data->irqParam)
((voidFuncPtr)data->irqHandler)();
else
((voidFuncPtrParam)data->irqHandler)(data->irqParam);
}
void attachInterruptParam(pin_size_t interruptNumber, voidFuncPtrParam callback, PinStatus mode, void *param) {
PinInfo *pin = pinInfo(interruptNumber);
if (!pin)
return;
if (!pinSupported(pin, PIN_IRQ))
return;
uint32_t index = pinIndex(pin);
uint32_t event = 0;
PinMode modeNew = 0;
bool change = 0;
pinCheckGetData(interruptNumber, PIN_IRQ, );
data->irqHandler = callback;
data->irqParam = param;
if (pinEnabled(pin, PIN_IRQ) && data->irqMode == mode)
return;
// GPIO can't be used together with PWM
pinRemoveMode(pin, PIN_PWM);
uint32_t event = 0;
bool change = false;
switch (mode) {
case LOW:
event = GPIO_INT_LEVEL_LOW;
modeNew = INPUT_PULLUP;
change = false;
event = GPIO_INT_LEVEL_LOW;
break;
case HIGH:
event = GPIO_INT_LEVEL_HIGH;
modeNew = INPUT_PULLDOWN;
change = false;
event = GPIO_INT_LEVEL_HIGH;
break;
case FALLING:
event = GPIO_INT_LEVEL_FALLING;
modeNew = INPUT_PULLUP;
change = false;
event = GPIO_INT_LEVEL_FALLING;
break;
case RISING:
event = GPIO_INT_LEVEL_RISING;
modeNew = INPUT_PULLDOWN;
change = false;
event = GPIO_INT_LEVEL_RISING;
break;
case CHANGE:
event = GPIO_INT_LEVEL_FALLING;
modeNew = INPUT_PULLUP;
change = true;
event = GPIO_INT_LEVEL_FALLING;
change = true;
break;
default:
return;
}
irqHandlerList[index] = callback;
irqHandlerArgs[index] = param;
irqChangeList[index] = change;
pinEnable(pin, PIN_IRQ);
data->irqMode = mode;
data->irqChange = change;
gpio_int_enable(pin->gpio, event, irqHandler);
pin->enabled |= PIN_IRQ | PIN_GPIO;
pin->mode = modeNew;
}
void detachInterrupt(pin_size_t interruptNumber) {
PinInfo *pin = pinInfo(interruptNumber);
if (!pin)
return;
if (!pinSupported(pin, PIN_IRQ))
return;
uint32_t index = pinIndex(pin);
irqHandlerList[index] = NULL;
irqHandlerArgs[index] = NULL;
irqChangeList[index] = false;
gpio_int_disable(pin->gpio);
pin->enabled &= ~PIN_IRQ;
pinModeRemove(interruptNumber, PIN_IRQ);
}

View File

@@ -0,0 +1,13 @@
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
#include <libretiny.h>
#include <sdk_private.h>
lt_cpu_model_t lt_cpu_get_model() {
uint8_t chipId = *(uint8_t *)(SCTRL_CHIP_ID);
return CPU_MODEL_ENUM(FAMILY, chipId);
}
const char *lt_cpu_get_core_type() {
return "ARM968E-S (ARMv5TE)";
}

View File

@@ -0,0 +1,41 @@
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
#include <libretiny.h>
#include <sdk_private.h>
void lt_get_device_mac(uint8_t *mac) {
cfg_load_mac(mac);
}
void lt_reboot() {
bk_reboot();
}
bool lt_reboot_download_mode() {
bk_reboot();
return true;
}
lt_reboot_reason_t lt_get_reboot_reason() {
switch (bk_misc_get_start_type()) {
case RESET_SOURCE_POWERON:
return REBOOT_REASON_POWER;
case RESET_SOURCE_REBOOT:
return REBOOT_REASON_SOFTWARE;
case RESET_SOURCE_WATCHDOG:
return REBOOT_REASON_WATCHDOG;
case RESET_SOURCE_CRASH_XAT0:
case RESET_SOURCE_CRASH_UNDEFINED:
case RESET_SOURCE_CRASH_PREFETCH_ABORT:
case RESET_SOURCE_CRASH_DATA_ABORT:
case RESET_SOURCE_CRASH_UNUSED:
case RESET_SOURCE_CRASH_PER_XAT0:
return REBOOT_REASON_CRASH;
case RESET_SOURCE_DEEPPS_GPIO:
case RESET_SOURCE_DEEPPS_RTC:
case RESET_SOURCE_DEEPPS_USB:
return REBOOT_REASON_SLEEP;
default:
return REBOOT_REASON_UNKNOWN;
}
}

View File

@@ -0,0 +1,26 @@
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
#include <libretiny.h>
#include <sdk_private.h>
// can't include <flash.h> as it collides with <Flash.h> on Windows -_-
#define REG_FLASH_BASE 0x00803000
#define REG_FLASH_OPERATE_SW (REG_FLASH_BASE + 0 * 4)
#define REG_FLASH_RDID (REG_FLASH_BASE + 4 * 4)
#define FLASH_BUSY_SW (0x01UL << 31)
#define FLASH_WP_VALUE (0x01UL << 30)
#define FLASH_OP_SW (0x01UL << 29)
#define FLASH_OP_TYPE_POS 24
#define FLASH_OP_RDID 20
lt_flash_id_t lt_flash_get_id() {
uint32_t data = (FLASH_OP_RDID << FLASH_OP_TYPE_POS) | FLASH_OP_SW | FLASH_WP_VALUE;
REG_WRITE(REG_FLASH_OPERATE_SW, data);
while (REG_READ(REG_FLASH_OPERATE_SW) & FLASH_BUSY_SW) {}
lt_flash_id_t id = {
.manufacturer_id = REG_RD8(REG_FLASH_RDID, 2),
.chip_id = REG_RD8(REG_FLASH_RDID, 1),
.chip_size_id = REG_RD8(REG_FLASH_RDID, 0),
};
return id;
}

View File

@@ -0,0 +1,14 @@
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
#include <libretiny.h>
#include <sdk_private.h>
void lt_init_family() {
// set default UART output port
uart_print_port = LT_UART_DEFAULT_PORT - 1;
// initialize the UART (needed e.g. after deep sleep)
if (uart_print_port == 1)
uart1_init();
else if (uart_print_port == 2)
uart2_init();
}

View File

@@ -0,0 +1,21 @@
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
#include <libretiny.h>
#include <sdk_private.h>
uint32_t lt_ram_get_size() {
return 256 * 1024;
}
uint32_t lt_heap_get_size() {
#if configDYNAMIC_HEAP_SIZE
extern unsigned char _empty_ram;
#if CFG_SOC_NAME == SOC_BK7231N
return (0x00400000 + 192 * 1024) - (uint32_t)(&_empty_ram);
#else
return (0x00400000 + 256 * 1024) - (uint32_t)(&_empty_ram);
#endif
#else
return configTOTAL_HEAP_SIZE;
#endif
}

View File

@@ -0,0 +1,39 @@
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
#include <libretiny.h>
#include <sdk_private.h>
lt_ota_type_t lt_ota_get_type() {
return OTA_TYPE_SINGLE;
}
bool lt_ota_is_valid(uint8_t index) {
if (index != 0)
return false;
// check download RBL
// TODO: maybe check header CRC or even binary hashes
uint32_t magic;
lt_flash_read(FLASH_DOWNLOAD_OFFSET, (uint8_t *)&magic, 4);
return magic == 0x004C4252; // "RBL\0", little-endian
}
uint8_t lt_ota_dual_get_current() {
return 0;
}
uint8_t lt_ota_dual_get_stored() {
return 0;
}
bool lt_ota_switch(bool revert) {
if (!lt_ota_is_valid(0))
// no valid "download" image
// - return false when trying to activate
// - return true when trying to revert
return revert;
if (revert) {
// there's a valid "download" image, which has to be removed
return lt_flash_erase_block(FLASH_DOWNLOAD_OFFSET);
}
return true;
}

View File

@@ -0,0 +1,40 @@
/* Copyright (c) Peter Sarkozi 2023-06-17. */
#include <libretiny.h>
#include <sdk_private.h>
static PS_DEEP_CTRL_PARAM deep_sleep_param;
void lt_deep_sleep_config_gpio(uint32_t gpio_index_map, bool on_high) {
deep_sleep_param.wake_up_way |= PS_DEEP_WAKEUP_GPIO;
deep_sleep_param.gpio_index_map |= gpio_index_map;
if (on_high) {
deep_sleep_param.gpio_edge_map |= gpio_index_map;
} else {
deep_sleep_param.gpio_edge_map &= (~gpio_index_map);
}
}
void lt_deep_sleep_unset_gpio(uint32_t gpio_index_map) {
deep_sleep_param.gpio_index_map &= (~gpio_index_map);
}
void lt_deep_sleep_config_timer(uint32_t sleep_duration) {
deep_sleep_param.wake_up_way |= PS_DEEP_WAKEUP_RTC;
uint64_t duration_math = 32768 * sleep_duration;
if (duration_math / 1000 > 0xFFFFFFFF) {
// Sleep forever
deep_sleep_param.sleep_time = 0xFFFFFFFF;
} else {
deep_sleep_param.sleep_time = (duration_math / 1000) & 0xFFFFFFFF;
}
}
void lt_deep_sleep_enter() {
bk_misc_update_set_type(RESET_SOURCE_DEEPPS_GPIO);
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
sctrl_enter_rtos_deep_sleep((PS_DEEP_CTRL_PARAM *)&deep_sleep_param);
ps_delay(500);
GLOBAL_INT_RESTORE();
}

View File

@@ -0,0 +1,18 @@
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
#include <libretiny.h>
#include <sdk_private.h>
bool lt_wdt_enable(uint32_t timeout) {
wdt_ctrl(WCMD_SET_PERIOD, &timeout);
wdt_ctrl(WCMD_POWER_UP, NULL);
return true;
}
void lt_wdt_disable() {
wdt_ctrl(WCMD_POWER_DOWN, NULL);
}
void lt_wdt_feed() {
wdt_ctrl(WCMD_RELOAD_PERIOD, NULL);
}

View File

@@ -1,190 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2023-02-27. */
#include <libretiny.h>
#include <sdk_private.h>
// can't include <flash.h> as it collides with <Flash.h> on Windows -_-
#define REG_FLASH_BASE 0x00803000
#define REG_FLASH_OPERATE_SW (REG_FLASH_BASE + 0 * 4)
#define REG_FLASH_RDID (REG_FLASH_BASE + 4 * 4)
#define FLASH_BUSY_SW (0x01UL << 31)
#define FLASH_WP_VALUE (0x01UL << 30)
#define FLASH_OP_SW (0x01UL << 29)
#define FLASH_OP_TYPE_POS 24
#define FLASH_OP_RDID 20
void lt_init_family() {
// set default UART output port
uart_print_port = LT_UART_DEFAULT_PORT - 1;
}
/* _____ _____ _ _
/ ____| __ \| | | |
| | | |__) | | | |
| | | ___/| | | |
| |____| | | |__| |
\_____|_| \____*/
lt_cpu_model_t lt_cpu_get_model() {
uint8_t chipId = *(uint8_t *)(SCTRL_CHIP_ID);
return CPU_MODEL_ENUM(FAMILY, chipId);
}
uint32_t lt_cpu_get_unique_id() {
return lt_cpu_get_mac_id();
}
uint32_t lt_cpu_get_mac_id() {
uint8_t mac[6];
cfg_load_mac(mac); // force loading MAC from TLV (ignore user-set WiFi MAC)
return (mac[3]) | (mac[4] << 8) | (mac[5] << 16);
}
const char *lt_cpu_get_core_type() {
return "ARM968E-S";
}
/*_____ _
| __ \ (_)
| | | | _____ ___ ___ ___
| | | |/ _ \ \ / / |/ __/ _ \
| |__| | __/\ V /| | (_| __/
|_____/ \___| \_/ |_|\___\__*/
void lt_reboot() {
bk_reboot();
}
bool lt_reboot_download_mode() {
bk_reboot();
return true;
}
lt_reboot_reason_t lt_get_reboot_reason() {
switch (bk_misc_get_start_type()) {
case RESET_SOURCE_POWERON:
return REBOOT_REASON_POWER;
case RESET_SOURCE_REBOOT:
return REBOOT_REASON_SOFTWARE;
case RESET_SOURCE_WATCHDOG:
return REBOOT_REASON_WATCHDOG;
case RESET_SOURCE_CRASH_XAT0:
case RESET_SOURCE_CRASH_UNDEFINED:
case RESET_SOURCE_CRASH_PREFETCH_ABORT:
case RESET_SOURCE_CRASH_DATA_ABORT:
case RESET_SOURCE_CRASH_UNUSED:
case RESET_SOURCE_CRASH_PER_XAT0:
return REBOOT_REASON_CRASH;
case RESET_SOURCE_DEEPPS_GPIO:
case RESET_SOURCE_DEEPPS_RTC:
case RESET_SOURCE_DEEPPS_USB:
return REBOOT_REASON_SLEEP;
default:
return REBOOT_REASON_UNKNOWN;
}
}
/*______ _ _
| ____| | | |
| |__ | | __ _ ___| |__
| __| | |/ _` / __| '_ \
| | | | (_| \__ \ | | |
|_| |_|\__,_|___/_| |*/
lt_flash_id_t lt_flash_get_id() {
uint32_t data = (FLASH_OP_RDID << FLASH_OP_TYPE_POS) | FLASH_OP_SW | FLASH_WP_VALUE;
REG_WRITE(REG_FLASH_OPERATE_SW, data);
while (REG_READ(REG_FLASH_OPERATE_SW) & FLASH_BUSY_SW) {}
lt_flash_id_t id = {
.manufacturer_id = REG_RD8(REG_FLASH_RDID, 2),
.chip_id = REG_RD8(REG_FLASH_RDID, 1),
.chip_size_id = REG_RD8(REG_FLASH_RDID, 0),
};
return id;
}
/*__ __
| \/ |
| \ / | ___ _ __ ___ ___ _ __ _ _
| |\/| |/ _ \ '_ ` _ \ / _ \| '__| | | |
| | | | __/ | | | | | (_) | | | |_| |
|_| |_|\___|_| |_| |_|\___/|_| \__, |
__/ |
|__*/
uint32_t lt_ram_get_size() {
return 256 * 1024;
}
uint32_t lt_heap_get_size() {
#if configDYNAMIC_HEAP_SIZE
extern unsigned char _empty_ram;
#if CFG_SOC_NAME == SOC_BK7231N
return (0x00400000 + 192 * 1024) - (uint32_t)(&_empty_ram);
#else
return (0x00400000 + 256 * 1024) - (uint32_t)(&_empty_ram);
#endif
#else
return configTOTAL_HEAP_SIZE;
#endif
}
/* ____ _______
/ __ \__ __|/\
| | | | | | / \
| | | | | | / /\ \
| |__| | | |/ ____ \
\____/ |_/_/ \*/
lt_ota_type_t lt_ota_get_type() {
return OTA_TYPE_SINGLE;
}
bool lt_ota_is_valid(uint8_t index) {
if (index != 0)
return false;
// check download RBL
// TODO: maybe check header CRC or even binary hashes
uint32_t magic;
lt_flash_read(FLASH_DOWNLOAD_OFFSET, (uint8_t *)&magic, 4);
return magic == 0x004C4252; // "RBL\0", little-endian
}
uint8_t lt_ota_dual_get_current() {
return 0;
}
uint8_t lt_ota_dual_get_stored() {
return 0;
}
bool lt_ota_switch(bool revert) {
if (!lt_ota_is_valid(0))
// no valid "download" image
// - return false when trying to activate
// - return true when trying to revert
return revert;
if (revert) {
// there's a valid "download" image, which has to be removed
return lt_flash_erase_block(FLASH_DOWNLOAD_OFFSET);
}
return true;
}
/*_ __ _ _ _
\ \ / / | | | | | |
\ \ /\ / /_ _| |_ ___| |__ __| | ___ __ _
\ \/ \/ / _` | __/ __| '_ \ / _` |/ _ \ / _` |
\ /\ / (_| | || (__| | | | (_| | (_) | (_| |
\/ \/ \__,_|\__\___|_| |_|\__,_|\___/ \__, |
__/ |
|___*/
bool lt_wdt_enable(uint32_t timeout) {
wdt_ctrl(WCMD_SET_PERIOD, &timeout);
wdt_ctrl(WCMD_POWER_UP, NULL);
return true;
}
void lt_wdt_disable() {
wdt_ctrl(WCMD_POWER_DOWN, NULL);
}
void lt_wdt_feed() {
wdt_ctrl(WCMD_RELOAD_PERIOD, NULL);
}

View File

@@ -2,11 +2,16 @@
#error "Don't include this file directly"
#define LT_HAS_PRINTF 1
#define LT_HAS_LWIP 1
#define LT_HAS_LWIP2 1
#define LT_HAS_FREERTOS 1
#define LT_HAS_MBEDTLS 1
#define LT_HAS_FLASH 1
#define LT_HAS_FREERTOS 1
#define LT_HAS_LWIP 1
#define LT_HAS_LWIP2 1
#define LT_HAS_MBEDTLS 1
#define LT_HAS_OTA 1
#define LT_HAS_PRINTF 1
#define LT_HW_DEEP_SLEEP 1
#define LT_HW_WATCHDOG 1
#define LT_HW_WIFI 1
#define LT_HEAP_FUNC xPortGetFreeHeapSize
#define LT_REALLOC_FUNC pvPortRealloc

View File

@@ -2,15 +2,19 @@
#pragma once
#include LT_VARIANT_H
#include <lt_pins.h>
// Choose the main UART output port
#ifndef LT_UART_DEFAULT_PORT
#if HAS_SERIAL2
#if LT_HW_UART2
#define LT_UART_DEFAULT_PORT 2
#elif HAS_SERIAL1
#elif LT_HW_UART1
#define LT_UART_DEFAULT_PORT 1
#else
#error "No serial port is available"
#endif
#endif
// Auto-download-reboot detection pattern
// Link check command (CMD_LinkCheck=0)
#define LT_UART_ADR_PATTERN 0x01, 0xE0, 0xFC, 0x01, 0x00

View File

@@ -0,0 +1,26 @@
/* Copyright (c) Kuba Szczodrzyński 2023-05-24. */
#pragma once
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#include <uart_pub.h>
// SDK
extern uint8_t system_mac[];
extern int uart_print_port;
uint32_t wdt_ctrl(uint32_t cmd, void *param);
void bk_send_byte(uint8_t uport, uint8_t data);
void uart_hw_set_change(uint8_t uport, bk_uart_config_t *uart_config);
int uart_rx_callback_set(int uport, uart_callback callback, void *param);
void sctrl_enter_rtos_deep_sleep(PS_DEEP_CTRL_PARAM *deep_param);
void ps_delay(volatile UINT16 times);
#ifdef __cplusplus
} // extern "C"
#endif

View File

@@ -6,12 +6,19 @@
extern "C" {
#endif // __cplusplus
// most stuff is here
// most stuff is here - this has to be before other includes!
#include <include.h>
// other includes
#include <arm_arch.h>
#include <bk_timer.h>
#include <bk_timer_pub.h>
#include <flash_pub.h>
#include <gpio_pub.h>
#include <manual_ps_pub.h>
#include <param_config.h>
#include <pwm_pub.h>
#include <rtos_pub.h>
#include <saradc_pub.h>
#include <start_type_pub.h>
#include <sys_ctrl.h>
#include <sys_rtos.h>
@@ -19,9 +26,7 @@ extern "C" {
#include <wdt_pub.h>
#include <wlan_ui_pub.h>
extern uint8_t system_mac[];
extern uint32_t wdt_ctrl(uint32_t cmd, void *param);
extern int uart_print_port;
#include <sdk_extern.h>
// conflict with stl_algobase.h
#undef min

View File

@@ -0,0 +1,36 @@
/* Copyright (c) Kuba Szczodrzyński 2023-05-23. */
#include "Serial.h"
SerialClass::SerialClass(uint32_t port, pin_size_t rx, pin_size_t tx) {
this->port = port;
this->rx = rx;
this->tx = tx;
this->buf = NULL;
this->data = NULL;
}
#if LT_AUTO_DOWNLOAD_REBOOT && defined(LT_UART_ADR_PATTERN)
static uint8_t adrState = 0;
static uint8_t adrCmd[] = {LT_UART_ADR_PATTERN};
void SerialClass::adrParse(uint8_t c) {
adrState = (adrState + 1) * (c == adrCmd[adrState]);
if (adrState == sizeof(adrCmd) / sizeof(uint8_t)) {
LT_I("Auto download mode: rebooting");
LT.restartDownloadMode();
}
}
#endif
int SerialClass::available() {
return this->buf && this->buf->available();
}
int SerialClass::peek() {
return this->buf ? this->buf->peek() : -1;
}
int SerialClass::read() {
return this->buf ? this->buf->read_char() : -1;
}

View File

@@ -2,7 +2,7 @@
#pragma once
#include <api/ArduinoAPI.h>
#include <Arduino.h>
#include <api/HardwareSerial.h>
#include <api/RingBuffer.h>
@@ -10,17 +10,31 @@ using namespace arduino;
class SerialClass : public HardwareSerial {
private:
uint8_t port;
RingBuffer *buf;
uint32_t port;
pin_size_t rx;
pin_size_t tx;
public:
SerialClass(uint8_t port);
void *data;
private:
RingBuffer *buf;
uint32_t baudrate;
uint16_t config;
public:
SerialClass(uint32_t port, pin_size_t rx = PIN_INVALID, pin_size_t tx = PIN_INVALID);
inline void begin(unsigned long baudrate) {
begin(baudrate, SERIAL_8N1);
}
inline void configure(unsigned long baudrate) {
configure(baudrate, SERIAL_8N1);
}
void begin(unsigned long baudrate, uint16_t config);
void configure(unsigned long baudrate, uint16_t config);
void end();
int available();
int peek();
@@ -32,5 +46,12 @@ class SerialClass : public HardwareSerial {
return !!buf;
}
public:
#if LT_AUTO_DOWNLOAD_REBOOT
static void adrParse(uint8_t c);
#endif
using Print::write;
};
#define HAS_SERIAL_CLASS 1

View File

@@ -3,11 +3,11 @@
#include "WiFi.h"
void WiFiClass::printDiag(Print &dest) {
const char *modes[] = {"NULL", "STA", "AP", "STA+AP"};
const char *enc[] = {"Open", "WEP", "WPA PSK", "WPA2 PSK", "WPA/WPA2", "WPA", "WPA2"};
dest.print("Mode: ");
dest.println(modes[getMode()]);
dest.println(WiFiModeText[getMode()]);
dest.print("Status: ");
dest.println(WiFiStatusText[status()]);
if (getMode() & WIFI_MODE_STA) {
dest.println("-- Station --");
@@ -21,7 +21,7 @@ void WiFiClass::printDiag(Print &dest) {
dest.print("RSSI: ");
dest.println(RSSI());
dest.print("Encryption: ");
dest.println(enc[getEncryption()]);
dest.println(WiFiAuthModeText[getEncryption()]);
dest.print("IP: ");
dest.println(localIP());
dest.print("MAC: ");

View File

@@ -11,7 +11,7 @@ bool WiFiClass::mode(WiFiMode mode) {
pWiFi = this;
WiFiMode currentMode = getMode();
LT_DM(WIFI, "Mode changing %u -> %u", currentMode, mode);
LT_DM(WIFI, "Mode changing %s -> %s", WiFiModeText[currentMode], WiFiModeText[mode]);
if (mode == currentMode)
return true;

View File

@@ -162,3 +162,28 @@ typedef enum {
WLMODE_DISABLE = 1,
WLMODE_ENABLE = 2,
} WiFiModeAction;
static const char *WiFiModeText[] = {"NULL", "STA", "AP", "AP+STA"};
static const char *WiFiStatusText[] = {
"Idle",
"No SSID",
"Scan Completed",
"Connected",
"Connect failed",
"Connection lost",
"Disconnected",
};
static const char *WiFiAuthModeText[] = {
"Open",
"WEP",
"WPA PSK",
"WPA2 PSK",
"WPA/WPA2 PSK",
"WPA2 EAP",
"WPA3 PSK",
"WPA2/WPA3 PSK",
"WAPI PSK",
"WPA",
"WPA2",
"Auto",
};

View File

@@ -5,9 +5,6 @@
#include <Arduino.h>
// available built-in implementations
#if LT_ARD_MD5_POLARSSL
#include "MD5PolarSSLImpl.h"
#endif
#if LT_ARD_MD5_MBEDTLS
#include "MD5MbedTLSImpl.h"
#endif

View File

@@ -1,24 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-03. */
#if LT_ARD_MD5_POLARSSL
extern "C" {
#include <polarssl/md5.h>
void MD5Init(md5_context *context) {
md5_init(context);
md5_starts(context);
}
void MD5Update(md5_context *context, const unsigned char *buf, unsigned len) {
md5_update(context, buf, len);
}
void MD5Final(unsigned char digest[16], md5_context *context) {
md5_finish(context, digest);
}
} // extern "C"
#endif // LT_ARD_MD5_POLARSSL

View File

@@ -1,19 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-03. */
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
unsigned long total[2]; /*!< number of bytes processed */
unsigned long state[4]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
} md5_context;
#define LT_MD5_CTX_T md5_context
#ifdef __cplusplus
} // extern "C"
#endif

View File

@@ -2,9 +2,25 @@
#include "Update.h"
UpdateClass::UpdateClass() : ctx(NULL), info(NULL), buf(NULL) {
cleanup();
}
static const UpdateError 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 scheme */
UPDATE_ERROR_NO_PARTITION, /* UF2_ERR_PART_404 - no partition with that name */
UPDATE_ERROR_BAD_ARGUMENT, /* UF2_ERR_PART_INVALID - invalid partition info tag */
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 */
UPDATE_ERROR_WRITE, /* UF2_ERR_WRITE_PROTECT - target area is write-protected */
UPDATE_ERROR_WRITE, /* UF2_ERR_ALLOC_FAILED - dynamic memory allocation failed */
};
/**
* @brief Initialize the update process.
@@ -13,55 +29,110 @@ UpdateClass::UpdateClass() : ctx(NULL), info(NULL), buf(NULL) {
* @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();
LT_DM(OTA, "begin(%u, ...) / OTA curr: %u, scheme: %u", size, lt_ota_dual_get_current(), lt_ota_get_uf2_scheme());
ctx = uf2_ctx_init(lt_ota_get_uf2_scheme(), FAMILY);
info = uf2_info_init();
if (!size) {
cleanup(UPDATE_ERROR_SIZE);
bool UpdateClass::begin(
size_t size,
int command,
__attribute__((unused)) int ledPin,
__attribute__((unused)) uint8_t ledOn,
__attribute__((unused)) const char *label
) {
#if !LT_HAS_OTA
LT_E("OTA is not yet supported on this chip!");
this->errArd = UPDATE_ERROR_BAD_ARGUMENT;
return false;
#endif
if (this->ctx) {
return false;
}
this->clearError();
if (size == 0) {
this->errArd = UPDATE_ERROR_SIZE;
return false;
}
if (command != U_FLASH) {
cleanup(UPDATE_ERROR_BAD_ARGUMENT);
this->errArd = UPDATE_ERROR_BAD_ARGUMENT;
return false;
}
if (size == UPDATE_SIZE_UNKNOWN) {
size = 0;
}
this->ctx = static_cast<lt_ota_ctx_t *>(malloc(sizeof(lt_ota_ctx_t)));
lt_ota_begin(this->ctx, size);
this->ctx->callback = reinterpret_cast<void (*)(void *)>(progressHandler);
this->ctx->callback_param = this;
this->md5Ctx = static_cast<LT_MD5_CTX_T *>(malloc(sizeof(LT_MD5_CTX_T)));
MD5Init(this->md5Ctx);
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
* @param evenIfRemaining don't raise errors if still in progress
* @return false in case of errors or no update running; true otherwise
*/
bool UpdateClass::end(bool evenIfRemaining) {
if (hasError() || !ctx)
// false if not running
if (!this->ctx)
return false;
if (!isFinished() && !evenIfRemaining) {
// update is running or finished; cleanup and end it
if (!isFinished() && !evenIfRemaining)
// abort if not finished
cleanup(UPDATE_ERROR_ABORT);
return false;
}
// TODO what is evenIfRemaining for?
// try to activate the second OTA
if (!lt_ota_switch(/* revert= */ false)) {
cleanup(UPDATE_ERROR_ACTIVATE);
return false;
this->errArd = UPDATE_ERROR_ABORT;
this->md5Digest = static_cast<uint8_t *>(malloc(16));
MD5Final(this->md5Digest, this->md5Ctx);
this->cleanup(/* clearError= */ evenIfRemaining);
return !this->hasError();
}
/**
* @brief Cleanup (free) the update context.
* Try activating the firmware if possible, set local error codes.
*
* @param clearError assume successful finish after correct activation
*/
void UpdateClass::cleanup(bool clearError) {
if (!this->ctx)
return;
if (!lt_ota_end(this->ctx)) {
// activating firmware failed
this->errArd = UPDATE_ERROR_ACTIVATE;
this->errUf2 = UF2_ERR_OK;
} else if (this->md5Digest && this->md5Expected && memcmp(this->md5Digest, this->md5Expected, 16) != 0) {
// MD5 doesn't match
this->errArd = UPDATE_ERROR_MD5;
this->errUf2 = UF2_ERR_OK;
} else if (clearError) {
// successful finish and activation, clear error codes
this->clearError();
} else if (this->ctx->error > UF2_ERR_IGNORE) {
// make error code based on UF2OTA code
this->errArd = errorMap[this->ctx->error];
this->errUf2 = this->ctx->error;
} else {
// only keep Arduino error code (set by the caller)
this->errUf2 = UF2_ERR_OK;
}
cleanup();
return true;
#if LT_DEBUG_OTA
if (this->hasError())
this->printErrorContext();
#endif
free(this->ctx);
this->ctx = nullptr;
free(this->md5Ctx);
this->md5Ctx = nullptr;
free(this->md5Digest);
this->md5Digest = nullptr;
free(this->md5Expected);
this->md5Expected = nullptr;
}
/**
@@ -69,60 +140,45 @@ bool UpdateClass::end(bool evenIfRemaining) {
*
* It's advised to write in 512-byte chunks (or its multiples).
*
* @param data
* @param len
* @return size_t
* @param data chunk of data
* @param len length of the chunk
* @return size_t amount of bytes written
*/
size_t UpdateClass::write(uint8_t *data, size_t len) {
size_t written = 0;
if (hasError() || !ctx)
// 0 if not running
size_t UpdateClass::write(const uint8_t *data, size_t len) {
if (!this->ctx)
return 0;
LT_VM(OTA, "write(%u) / buf %u/512", len, bufSize());
/* 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; // 1..512
while (len && (toWrite = min(len, bufLeft()))) {
tryWriteData(data, toWrite);
if (hasError()) {
// return on errors
printErrorContext2(data, toWrite);
return written;
}
data += toWrite;
len -= toWrite;
written += toWrite;
}
size_t written = lt_ota_write(ctx, data, len);
MD5Update(this->md5Ctx, data, len);
if (written != len)
this->cleanup(/* clearError= */ false);
return written;
}
/**
* @brief Write all data remaining in the given stream.
*
* If the stream doesn't produce any data within UPDATE_TIMEOUT_MS,
* the update process will be aborted.
*
* @param data stream to read from
* @return size_t amount of bytes written
*/
size_t UpdateClass::writeStream(Stream &data) {
size_t written = 0;
if (hasError() || !ctx)
// 0 if not running
if (!this->ctx)
return 0;
size_t written = 0;
uint32_t lastData = millis();
// loop until the update is complete
while (remaining()) {
// check stream availability
int available = data.available();
auto available = data.available();
if (available <= 0) {
if (millis() - lastData > UPDATE_TIMEOUT_MS) {
// waited for data too long; abort with error
cleanup(UPDATE_ERROR_STREAM);
this->errArd = UPDATE_ERROR_STREAM;
this->cleanup(/* clearError= */ false);
return written;
}
continue;
@@ -131,94 +187,23 @@ size_t UpdateClass::writeStream(Stream &data) {
lastData = millis();
// read data to fit in the remaining buffer space
bufAlloc();
uint16_t read = data.readBytes(bufPos, bufLeft());
bufPos += read;
written += read;
tryWriteData();
auto bufSize = this->ctx->buf_pos - this->ctx->buf;
auto read = data.readBytes(this->ctx->buf_pos, UF2_BLOCK_SIZE - bufSize);
// update MD5
MD5Update(this->md5Ctx, this->ctx->buf_pos, read);
// increment buffer writing head
this->ctx->buf_pos += read;
// process the block if complete
if (bufSize + read == UF2_BLOCK_SIZE)
lt_ota_write_block(this->ctx, reinterpret_cast<uf2_block_t *>(this->ctx->buf));
// abort on errors
if (hasError()) {
// return on errors
printErrorContext2(NULL, read); // buf is not valid anymore
this->cleanup(/* clearError= */ false);
return written;
}
written += read;
}
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;
LT_VM(OTA, "Writing %u to buffer (%u/512)", len, bufSize());
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 (checkUf2Error(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 (checkUf2Error(uf2_parse_header(ctx, block, info)))
// header is invalid
return 0;
LT_IM(OTA, "%s v%s - LT v%s @ %s", info->fw_name, info->fw_version, info->lt_version, info->board);
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
LT_EM(OTA, "Image size wrong; got %u, calculated %u", bytesTotal, block->block_count * UF2_BLOCK_SIZE);
cleanup(UPDATE_ERROR_SIZE);
return 0;
}
} else {
// write data blocks normally
if (checkUf2Error(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);
// reset the buffer as it's used already
if (bufSize() == UF2_BLOCK_SIZE)
bufPos = buf;
return UF2_BLOCK_SIZE;
}
return 0;
}
UpdateClass Update;

View File

@@ -1,42 +1,34 @@
#pragma once
#include <Arduino.h>
#include <MD5.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)
typedef enum {
UPDATE_ERROR_OK = 0, //!< No Error
UPDATE_ERROR_WRITE = 1, //!< Flash Write Failed
UPDATE_ERROR_ERASE = 2, //!< Flash Erase Failed
UPDATE_ERROR_READ = 3, //!< Flash Read Failed
UPDATE_ERROR_SPACE = 4, //!< Not Enough Space
UPDATE_ERROR_SIZE = 5, //!< Bad Size Given
UPDATE_ERROR_STREAM = 6, //!< Stream Read Timeout
UPDATE_ERROR_MD5 = 7, //!< MD5 Check Failed
UPDATE_ERROR_MAGIC_BYTE = 8, //!< Wrong Magic Byte
UPDATE_ERROR_ACTIVATE = 9, //!< Could Not Activate The Firmware
UPDATE_ERROR_NO_PARTITION = 10, //!< Partition Could Not be Found
UPDATE_ERROR_BAD_ARGUMENT = 11, //!< Bad Argument
UPDATE_ERROR_ABORT = 12, //!< Aborted
} UpdateError;
typedef enum {
U_FLASH = 0,
U_SPIFFS = 100,
U_AUTH = 200,
} UpdateCommand;
#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
@@ -46,109 +38,138 @@ class UpdateClass {
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
size_t size = UPDATE_SIZE_UNKNOWN,
int command = U_FLASH,
int ledPin = -1,
uint8_t ledOn = LOW,
const char *label = nullptr
);
bool end(bool evenIfRemaining = false);
size_t write(uint8_t *data, size_t len);
size_t write(const 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);
void cleanup(bool clearError = false);
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 *getLibreTinyVersion();
const char *getBoardName();
UpdateClass &onProgress(THandlerFunction_Progress handler);
static bool canRollBack();
static bool rollBack();
bool setMD5(const char *md5);
String md5String();
void md5(uint8_t *result);
uint16_t getErrorCode() const;
bool hasError() const;
void clearError();
const char *errorString() const;
void printError(Print &out) const;
private: /* UpdateUtil.cpp */
void cleanup(uint8_t ardErr = UPDATE_ERROR_OK, uf2_err_t uf2Err = UF2_ERR_OK);
bool checkUf2Error(uf2_err_t err);
void bufAlloc();
void printErrorContext1();
void printErrorContext2(const uint8_t *data, size_t len);
uint16_t bufLeft();
uint16_t bufSize();
static void progressHandler(UpdateClass *self);
void printErrorContext();
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;
lt_ota_ctx_t *ctx{nullptr};
uf2_err_t errUf2{UF2_ERR_OK};
UpdateError errArd{UPDATE_ERROR_OK};
THandlerFunction_Progress callback{nullptr};
LT_MD5_CTX_T *md5Ctx{nullptr};
uint8_t *md5Digest{nullptr};
uint8_t *md5Expected{nullptr};
public:
String md5String(void) {
// return _md5.toString();
return "";
/**
* @brief Get Arduino error code of the update.
*/
inline UpdateError getError() const {
return this->errArd;
}
void md5(uint8_t *result) {
// return _md5.getBytes(result);
/**
* @brief Get UF2OTA error code of the update.
*/
inline uf2_err_t getUF2Error() const {
return this->ctx ? this->ctx->error : this->errUf2;
}
uint8_t getError() {
return errArd;
/**
* @brief Same as end().
*/
inline void abort() {
this->end();
}
uf2_err_t getUF2Error() {
return errUf2;
/**
* @brief Check if the update process has been started.
*/
inline bool isRunning() {
return this->ctx;
}
uint16_t getErrorCode() {
return (errArd << 8) | errUf2;
/**
* @brief Check if the update process hasn't been started or has been completed.
*/
inline bool isFinished() {
return !(this->ctx && this->ctx->bytes_written != this->ctx->bytes_total);
}
void clearError() {
cleanup(UPDATE_ERROR_OK);
/**
* @brief Return complete update image size.
*/
inline size_t size() {
return this->ctx ? this->ctx->bytes_total : 0;
}
bool hasError() {
return errArd != UPDATE_ERROR_OK;
/**
* @brief Return amount of bytes already written.
*/
inline size_t progress() {
return this->ctx ? this->ctx->bytes_written : 0;
}
bool isRunning() {
return ctx != NULL;
/**
* @brief Return amount of bytes remaining to write.
*/
inline size_t remaining() {
return this->size() - this->progress();
}
bool isFinished() {
return bytesWritten == bytesTotal;
/**
* @brief Get firmware name from UF2 info.
*/
inline const char *getFirmwareName() {
if (this->ctx)
return this->ctx->info.fw_name;
return nullptr;
}
size_t size() {
return bytesTotal;
/**
* @brief Get firmware version from UF2 info.
*/
inline const char *getFirmwareVersion() {
if (this->ctx)
return this->ctx->info.fw_version;
return nullptr;
}
size_t progress() {
return bytesWritten;
/**
* @brief Get LibreTiny version from UF2 info.
*/
inline const char *getLibreTinyVersion() {
if (this->ctx)
return this->ctx->info.lt_version;
return nullptr;
}
size_t remaining() {
return bytesTotal - bytesWritten;
/**
* @brief Get target board name from UF2 info.
*/
inline const char *getBoardName() {
if (this->ctx)
return this->ctx->info.board;
return nullptr;
}
};

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