diff --git a/boards/SUMMARY.md b/boards/SUMMARY.md
index ac2a8e1..9915ed0 100644
--- a/boards/SUMMARY.md
+++ b/boards/SUMMARY.md
@@ -1,4 +1,5 @@
+- [BW12](../boards/bw12/README.md)
- [WB2L Wi-Fi Module](../boards/wb2l/README.md)
- [WR3 Wi-Fi Module](../boards/wr3/README.md)
diff --git a/boards/_base/pcb/bw12.json b/boards/_base/pcb/bw12.json
new file mode 100644
index 0000000..0161f7b
--- /dev/null
+++ b/boards/_base/pcb/bw12.json
@@ -0,0 +1,81 @@
+{
+ "pcb": {
+ "templates": [
+ "esp12s",
+ "esp12s-shield",
+ "rf-16mm-type1"
+ ],
+ "vars": {
+ "MASK_PRESET": "mask_black",
+ "TRACE_COLOR": "#FAFD9D",
+ "SILK_COLOR": "white",
+ "PINTYPE_VERT": "pin_vert_2mm_cast_nohole"
+ },
+ "pinout_hidden": "I2S,TRIG,WAKE,CTS,RTS,SD",
+ "pinout": {
+ "1": {
+ "IC": 14,
+ "ARD": "D8"
+ },
+ "2": {
+ "NC": null
+ },
+ "3": {
+ "IC": 12
+ },
+ "4": {
+ "IC": 28,
+ "ARD": "D0"
+ },
+ "5": {
+ "IC": 2,
+ "ARD": "D1"
+ },
+ "6": {
+ "IC": 16,
+ "ARD": "D2"
+ },
+ "7": {
+ "IC": 30,
+ "ARD": [
+ "D3",
+ "A0"
+ ]
+ },
+ "8": {
+ "PWR": 3.3
+ },
+ "9": {
+ "GND": null
+ },
+ "10": {
+ "IC": 31,
+ "ARD": "D4"
+ },
+ "11": {
+ "IC": 1,
+ "ARD": "D5"
+ },
+ "12": {
+ "IC": 13,
+ "ARD": "D6"
+ },
+ "13": {
+ "IC": 17,
+ "ARD": "D7"
+ },
+ "14": {
+ "IC": 14,
+ "ARD": "D8"
+ },
+ "15": {
+ "IC": 29,
+ "ARD": "D9"
+ },
+ "16": {
+ "IC": 32,
+ "ARD": "D10"
+ }
+ }
+ }
+}
diff --git a/boards/_base/realtek-ambz-2mb.json b/boards/_base/realtek-ambz-2mb-large.json
similarity index 100%
rename from boards/_base/realtek-ambz-2mb.json
rename to boards/_base/realtek-ambz-2mb-large.json
diff --git a/boards/_base/realtek-ambz-2mb-small.json b/boards/_base/realtek-ambz-2mb-small.json
new file mode 100644
index 0000000..f134d3a
--- /dev/null
+++ b/boards/_base/realtek-ambz-2mb-small.json
@@ -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+0x75000",
+ "ota2": "0x080000+0x75000",
+ "kvs": "0xF5000+0x6000",
+ "userdata": "0xFB000+0x104000",
+ "rdp": "0x1FF000+0x1000"
+ },
+ "upload": {
+ "flash_size": 2097152,
+ "maximum_size": 479232
+ }
+}
diff --git a/boards/bw12.json b/boards/bw12.json
new file mode 100644
index 0000000..6817d27
--- /dev/null
+++ b/boards/bw12.json
@@ -0,0 +1,23 @@
+{
+ "_base": [
+ "realtek-ambz",
+ "realtek-ambz-2mb-small",
+ "pcb/ic-rtl8710bn",
+ "pcb/bw12"
+ ],
+ "build": {
+ "mcu": "rtl8710bx",
+ "variant": "bw12"
+ },
+ "name": "BW12",
+ "url": "http://www.ai-thinker.com/pro_view-13.html",
+ "vendor": "Ai-Thinker Co., Ltd.",
+ "pcb": {
+ "symbol": "BW12"
+ },
+ "doc": {
+ "links": {
+ "Vendor datasheet": "https://docs.ai-thinker.com/_media/rtl8710/hardware/bw12_datasheet_en.pdf"
+ }
+ }
+}
diff --git a/boards/bw12/README.md b/boards/bw12/README.md
new file mode 100644
index 0000000..5855e13
--- /dev/null
+++ b/boards/bw12/README.md
@@ -0,0 +1,66 @@
+# BW12
+
+*by Ai-Thinker Co., Ltd.*
+
+[Product page](http://www.ai-thinker.com/pro_view-13.html)
+
+- [General info](../../docs/platform/realtek/README.md)
+- [Debugging](../../docs/platform/realtek/debugging.md)
+- [Flashing (Tuya manual)](https://developer.tuya.com/en/docs/iot/burn-and-authorize-wr-series-modules?id=Ka789pjc581u8)
+- [Vendor datasheet](https://docs.ai-thinker.com/_media/rtl8710/hardware/bw12_datasheet_en.pdf)
+
+Parameter | Value
+-------------|----------------------------------
+MCU | RTL8710BX
+Manufacturer | Realtek
+Series | AmebaZ
+Frequency | 125 MHz
+Flash size | 2 MiB
+RAM size | 256 KiB
+Voltage | 3.0V - 3.6V
+I/O | 11x GPIO, 6x PWM, 2x UART, 1x ADC
+Wi-Fi | 802.11 b/g/n
+
+## Pinout
+
+
+
+## Arduino Core pin mapping
+
+No. | Pin | UART | I²C | SPI | PWM | Other
+----|------------|-----------|----------|----------------------|------|------
+D0 | PA05 | | | | PWM4 |
+D1 | PA29 | UART2_RX | I2C0_SCL | | PWM4 |
+D2 | PA00 | | | | PWM2 |
+D3 | PA19 | UART0_CTS | I2C0_SDA | SPI0_CS, SPI1_CS | |
+D4 | PA22 | UART0_RTS | I2C0_SCL | SPI0_MISO, SPI1_MISO | PWM5 |
+D5 | PA30 | UART2_TX | I2C0_SDA | | PWM4 |
+D6 | PA14 | | | | PWM0 | SWCLK
+D7 | PA12 | | | | PWM3 |
+D8 | PA15 | | | | PWM1 | SWDIO
+D9 | PA18 | UART0_RX | I2C1_SCL | SPI0_SCK, SPI1_SCK | |
+D10 | PA23 | UART0_TX | I2C1_SDA | SPI0_MOSI, SPI1_MOSI | PWM0 |
+A0 | PA19, ADC1 | | | | |
+
+## Flash memory map
+
+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 | 468 KiB / 0x75000 | 0x080000
+OTA2 Image | 0x080000 | 468 KiB / 0x75000 | 0x0F5000
+Key-Value Store | 0x0F5000 | 24 KiB / 0x6000 | 0x0FB000
+User Data | 0x0FB000 | 1 MiB / 0x104000 | 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.
+
+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.
diff --git a/boards/bw12/pinout_bw12.svg b/boards/bw12/pinout_bw12.svg
new file mode 100644
index 0000000..97456f5
--- /dev/null
+++ b/boards/bw12/pinout_bw12.svg
@@ -0,0 +1,315 @@
+
+
diff --git a/boards/bw12/pins_arduino.h b/boards/bw12/pins_arduino.h
new file mode 100644
index 0000000..1de3ade
--- /dev/null
+++ b/boards/bw12/pins_arduino.h
@@ -0,0 +1 @@
+#include "variant.h"
diff --git a/boards/bw12/variant.cpp b/boards/bw12/variant.cpp
new file mode 100644
index 0000000..035bb33
--- /dev/null
+++ b/boards/bw12/variant.cpp
@@ -0,0 +1,34 @@
+/* This file was auto-generated from bw12.json using boardgen */
+
+#include
+
+extern "C" {
+
+// clang-format off
+PinInfo pinTable[PINS_COUNT] = {
+ // D0: PA05, PWM4, WAKE1
+ {PA_5, PIN_GPIO | PIN_IRQ | PIN_PWM, PIN_NONE, 0},
+ // D1: PA29, UART2_RX, I2C0_SCL, PWM4
+ {PA_29, PIN_GPIO | PIN_IRQ | PIN_PWM | PIN_I2C | PIN_UART, PIN_NONE, 0},
+ // D2: PA00, PWM2
+ {PA_0, PIN_GPIO | PIN_IRQ | PIN_PWM, PIN_NONE, 0},
+ // D3: PA19, ADC1, UART0_CTS, SPI0_CS, SPI1_CS, I2C0_SDA, SD_D3, TMR5_TRIG, I2S0_TX
+ {PA_19, PIN_GPIO | PIN_IRQ | PIN_ADC | PIN_I2C | PIN_I2S | PIN_SPI | PIN_UART, PIN_NONE, 0},
+ // D4: PA22, UART0_RTS, SPI0_MISO, SPI1_MISO, I2C0_SCL, SD_D0, PWM5, I2S0_WS, WAKE2
+ {PA_22, PIN_GPIO | PIN_IRQ | PIN_PWM | PIN_I2C | PIN_I2S | PIN_SPI | PIN_UART, PIN_NONE, 0},
+ // D5: PA30, UART2_TX, I2C0_SDA, PWM4
+ {PA_30, PIN_GPIO | PIN_IRQ | PIN_PWM | PIN_I2C | PIN_UART, PIN_NONE, 0},
+ // D6: PA14, PWM0, SWCLK
+ {PA_14, PIN_GPIO | PIN_IRQ | PIN_PWM | PIN_SWD, PIN_NONE, 0},
+ // D7: PA12, PWM3
+ {PA_12, PIN_GPIO | PIN_IRQ | PIN_PWM, PIN_NONE, 0},
+ // D8: PA15, PWM1, SWDIO
+ {PA_15, PIN_GPIO | PIN_IRQ | PIN_PWM | PIN_SWD, PIN_NONE, 0},
+ // D9: PA18, UART0_RX, SPI0_SCK, SPI1_SCK, I2C1_SCL, SD_D2, TMR4_TRIG, I2S0_MCK, WAKE0
+ {PA_18, PIN_GPIO | PIN_IRQ | PIN_I2C | PIN_I2S | PIN_SPI | PIN_UART, PIN_NONE, 0},
+ // D10: PA23, UART0_TX, SPI0_MOSI, SPI1_MOSI, I2C1_SDA, SD_D1, PWM0, WAKE3
+ {PA_23, PIN_GPIO | PIN_IRQ | PIN_PWM | PIN_I2C | PIN_SPI | PIN_UART, PIN_NONE, 0},
+};
+// clang-format on
+
+} // extern "C"
diff --git a/boards/bw12/variant.h b/boards/bw12/variant.h
new file mode 100644
index 0000000..78fad48
--- /dev/null
+++ b/boards/bw12/variant.h
@@ -0,0 +1,51 @@
+/* This file was auto-generated from bw12.json using boardgen */
+
+#pragma once
+
+#include
+
+// clang-format off
+
+// Pins
+// ----
+#define PINS_COUNT 11
+#define NUM_DIGITAL_PINS 11
+#define NUM_ANALOG_INPUTS 1
+#define NUM_ANALOG_OUTPUTS 0
+
+// Analog pins
+// -----------
+#define PIN_A0 3u // PA_19
+#define A0 PIN_A0
+
+// SPI Interfaces
+// --------------
+#define SPI_INTERFACES_COUNT 2
+#define PIN_SPI0_CS 3u // PA_19
+#define PIN_SPI0_MISO 4u // PA_22
+#define PIN_SPI0_MOSI 10u // PA_23
+#define PIN_SPI0_SCK 9u // PA_18
+#define PIN_SPI1_CS 3u // PA_19
+#define PIN_SPI1_MISO 4u // PA_22
+#define PIN_SPI1_MOSI 10u // PA_23
+#define PIN_SPI1_SCK 9u // PA_18
+
+// Wire Interfaces
+// ---------------
+#define WIRE_INTERFACES_COUNT 2
+#define PIN_WIRE0_SCL_0 1u // PA_29
+#define PIN_WIRE0_SCL_1 4u // PA_22
+#define PIN_WIRE0_SDA_0 3u // PA_19
+#define PIN_WIRE0_SDA_1 5u // PA_30
+#define PIN_WIRE1_SCL 9u // PA_18
+#define PIN_WIRE1_SDA 10u // PA_23
+
+// Serial ports
+// ------------
+#define SERIAL_INTERFACES_COUNT 2
+#define PIN_SERIAL0_CTS 3u // PA_19
+#define PIN_SERIAL0_RTS 4u // PA_22
+#define PIN_SERIAL0_RX 9u // PA_18
+#define PIN_SERIAL0_TX 10u // PA_23
+#define PIN_SERIAL2_RX 1u // PA_29
+#define PIN_SERIAL2_TX 5u // PA_30
diff --git a/boards/wr3.json b/boards/wr3.json
index 256babc..8e4654e 100644
--- a/boards/wr3.json
+++ b/boards/wr3.json
@@ -1,7 +1,7 @@
{
"_base": [
"realtek-ambz",
- "realtek-ambz-2mb",
+ "realtek-ambz-2mb-large",
"pcb/ic-rtl8710bn",
"pcb/wr3"
],
diff --git a/docs/supported_boards.md b/docs/supported_boards.md
index 63551c2..7da7a23 100644
--- a/docs/supported_boards.md
+++ b/docs/supported_boards.md
@@ -2,6 +2,8 @@
Name | MCU | Flash | RAM | Pins* | Wi-Fi | BLE | ZigBee | Family name
---------------------------------|-----------|-------|---------|-------------|-------|-----|--------|---------------
+**Ai-Thinker Co., Ltd.** | | | | | | | |
+[BW12](../boards/bw12/README.md) | RTL8710BX | 2 MiB | 256 KiB | 16 (12 I/O) | ✔️ | ❌ | ❌ | `realtek-ambz`
**Tuya Inc.** | | | | | | | |
[WB2L](../boards/wb2l/README.md) | BK7231T | 2 MiB | 256 KiB | 7 (5 I/O) | ✔️ | ✔️ | ❌ | `beken-7231t`
[WR3](../boards/wr3/README.md) | RTL8710BN | 2 MiB | 256 KiB | 16 (12 I/O) | ✔️ | ❌ | ❌ | `realtek-ambz`
diff --git a/docs/supported_chips.md b/docs/supported_chips.md
index d1c45a0..ff7dbae 100644
--- a/docs/supported_chips.md
+++ b/docs/supported_chips.md
@@ -4,3 +4,4 @@
- BK7231T
- BK7231U
- RTL8710BN
+- RTL8710BX
diff --git a/families.json b/families.json
index 3b4cada..03c4ac4 100644
--- a/families.json
+++ b/families.json
@@ -14,7 +14,8 @@
"sdk": "https://github.com/ambiot/amb1_sdk",
"framework": "framework-realtek-amb1",
"mcus": [
- "RTL8710BN"
+ "RTL8710BN",
+ "RTL8710BX"
]
},
{
diff --git a/platform/realtek-ambz/ld/rlx8711B-symbol-v02-img2_xip1_2M_468k_cpp.ld b/platform/realtek-ambz/ld/rlx8711B-symbol-v02-img2_xip1_2M_468k_cpp.ld
new file mode 100644
index 0000000..be3332d
--- /dev/null
+++ b/platform/realtek-ambz/ld/rlx8711B-symbol-v02-img2_xip1_2M_468k_cpp.ld
@@ -0,0 +1,222 @@
+
+
+ENTRY(Reset_Handler)
+
+INCLUDE "export-rom_symbol_v01.txt"
+
+GROUP (
+ libgcc.a
+ libc.a
+ libg.a
+ libm.a
+ libnosys.a
+)
+
+MEMORY
+{
+ ROM (rx) : ORIGIN = 0x00000000, LENGTH = 0x80000 /* ROM: 512k */
+ ROMBSS_RAM (rw) : ORIGIN = 0x10000000, LENGTH = 0x2000 /* ROM BSS RAM: 8K */
+ BOOTLOADER_RAM (rwx) : ORIGIN = 0x10002000, LENGTH = 0x3000 /* BOOT Loader RAM: 12K */
+ BD_RAM (rwx) : ORIGIN = 0x10005000, LENGTH = 0x38000 /* MAIN RAM: 224k */
+ ROM_BSS_RAM (rwx) : ORIGIN = 0x1003D000, LENGTH = 0x1000 /* ROM BSS RAM: 4K */
+ MSP_RAM (wx) : ORIGIN = 0x1003E000, LENGTH = 0x1000 /* MSP RAM: 4k */
+ RDP_RAM (wx) : ORIGIN = 0x1003F000, LENGTH = 0xFF0 /* RDP RAM: 4k-0x10 */
+
+ XIPBOOT (rx) : ORIGIN = 0x08000000+0x20, LENGTH = 0x04000-0x20 /* XIPBOOT: 16k, 32 Bytes resvd for header*/
+ XIPSYS (r) : ORIGIN = 0x08009000, LENGTH = 0x1000 /* XIPSYS: 4K system data in flash */
+ XIPCAL (r) : ORIGIN = 0x0800A000, LENGTH = 0x1000 /* XIPCAL: 4K calibration data in flash */
+ XIP1 (rx) : ORIGIN = 0x0800B000+0x20, LENGTH = 0x75000-0x20 /* XIP1: 468k, 32 Bytes resvd for header */
+ XIP2 (rx) : ORIGIN = 0x08080000+0x20, LENGTH = 0x75000-0x20 /* XIP2: 468k, 32 Bytes resvd for header */
+}
+
+
+
+SECTIONS
+{
+ .rom.text : { } > ROM
+ .rom.rodata : { } > ROM
+ .ARM.exidx :
+ {
+ __exidx_start = .;
+ *(.ARM.exidx*)
+ *(.gnu.linkonce.armexidx.*)
+ __exidx_end = .;
+ } > ROM
+ .hal.rom.bss : { } > ROMBSS_RAM
+
+ /* image1 entry, this section should in RAM and fixed address for ROM */
+ .ram_image1.entry :
+ {
+ __ram_image1_text_start__ = .;
+ __ram_start_table_start__ = .;
+ KEEP(*(SORT(.image1.entry.data*)))
+ __ram_start_table_end__ = .;
+
+ __image1_validate_code__ = .;
+ KEEP(*(.image1.validate.rodata*))
+ KEEP(*(.image1.export.symb*))
+ } > BOOTLOADER_RAM
+
+ /* Add . to assign the start address of the section */
+ /* to prevent the change of the start address by ld doing section alignment */
+ .ram_image1.text . :
+ {
+ /* image1 text */
+ *(.boot.ram.text*)
+ *(.boot.rodata*)
+ } > BOOTLOADER_RAM
+
+ .ram_image1.data . :
+ {
+ __ram_image1_data_start__ = .;
+ KEEP(*(.boot.ram.data*))
+ __ram_image1_data_end__ = .;
+
+ __ram_image1_text_end__ = .;
+ } > BOOTLOADER_RAM
+
+ .ram_image1.bss . :
+ {
+ __image1_bss_start__ = .;
+ KEEP(*(.boot.ram.bss*))
+ KEEP(*(.boot.ram.end.bss*))
+ __image1_bss_end__ = .;
+ } > BOOTLOADER_RAM
+
+ .ram_image2.entry :
+ {
+ __ram_image2_text_start__ = .;
+ __image2_entry_func__ = .;
+ KEEP(*(SORT(.image2.entry.data*)))
+
+ __image2_validate_code__ = .;
+ KEEP(*(.image2.validate.rodata*))
+
+ } > BD_RAM
+
+ .ram_image2.text :
+ {
+ KEEP(*(.image2.ram.text*))
+ } > BD_RAM
+
+ .ram_image2.data :
+ {
+ __data_start__ = .;
+ *(.data*)
+ __data_end__ = .;
+ __ram_image2_text_end__ = .;
+ . = ALIGN(16);
+ } > BD_RAM
+
+ .ram_image2.bss :
+ {
+ __bss_start__ = .;
+ *(.bss*)
+ *(COMMON)
+ } > BD_RAM
+
+ .ram_image2.skb.bss :
+ {
+ *(.bdsram.data*)
+ __bss_end__ = .;
+ } > BD_RAM
+
+ .ram_heap.data :
+ {
+ *(.bfsram.data*)
+ } > BD_RAM
+
+ . = ALIGN(8);
+ PROVIDE(heap_start = .);
+ PROVIDE(heap_end = 0x1003CFFF);
+ PROVIDE(heap_len = heap_end - heap_start);
+
+ .rom.bss :
+ {
+ *(.heap.stdlib*)
+ } > ROM_BSS_RAM
+
+ .ram_rdp.text :
+ {
+ __rom_top_4k_start_ = .;
+ __rdp_text_start__ = .;
+ KEEP(*(.rdp.ram.text*))
+ KEEP(*(.rdp.ram.data*))
+ __rdp_text_end__ = .;
+ . = ALIGN(16);
+
+ } > RDP_RAM
+
+ .xip_image1.text :
+ {
+ __flash_boot_text_start__ = .;
+
+ *(.flashboot.text*)
+
+ __flash_boot_text_end__ = .;
+
+ . = ALIGN(16);
+ } > XIPBOOT
+
+ .xip_image2.text :
+ {
+ __flash_text_start__ = .;
+
+ *(.img2_custom_signature*)
+ *(.text)
+ *(.text*)
+ *(.rodata)
+ *(.rodata*)
+ *(.debug_trace*)
+
+ /* https://www.embedded.com/building-bare-metal-arm-systems-with-gnu-part-3/ */
+ KEEP(*crtbegin.o(.ctors))
+ KEEP(*(EXCLUDE_FILE (*ctrend.o) .ctors))
+ KEEP(*(SORT(.ctors.*)))
+ KEEP(*crtend.o(.ctors))
+ KEEP(*crtbegin.o(.dtors))
+ KEEP(*(EXCLUDE_FILE (*crtend.o) .dtors))
+ KEEP(*(SORT(.dtors.*)))
+ KEEP(*crtend.o(.dtors))
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+
+ /* Add This for C++ support */
+ /* ambd_arduino/Arduino_package/hardware/variants/rtl8720dn_bw16/linker_scripts/gcc/rlx8721d_img2_is_arduino.ld */
+ . = ALIGN(4);
+ __preinit_array_start = .;
+ KEEP(*(.preinit_array))
+ __preinit_array_end = .;
+ . = ALIGN(4);
+ __init_array_start = .;
+ KEEP(*(SORT(.init_array.*)))
+ KEEP(*(.init_array))
+ __init_array_end = .;
+ . = ALIGN(4);
+ __fini_array_start = .;
+ KEEP(*(SORT(.fini_array.*)))
+ KEEP(*(.fini_array))
+ __fini_array_end = .;
+ /*-----------------*/
+
+ . = ALIGN (4);
+ __cmd_table_start__ = .;
+ KEEP(*(.cmd.table.data*))
+ __cmd_table_end__ = .;
+
+ /* https://community.silabs.com/s/article/understand-the-gnu-linker-script-of-cortex-m4?language=en_US */
+ KEEP(*(.init))
+ KEEP(*(.fini))
+ *(.init)
+ *(.fini)
+
+ __flash_text_end__ = .;
+
+ . = ALIGN (16);
+ } > XIP1
+}
+
+SECTIONS
+{
+ /* Bootloader symbol list */
+ boot_export_symbol = 0x10002020;
+}
diff --git a/platform/realtek-ambz/ld/rlx8711B-symbol-v02-img2_xip2_2M_468k_cpp.ld b/platform/realtek-ambz/ld/rlx8711B-symbol-v02-img2_xip2_2M_468k_cpp.ld
new file mode 100644
index 0000000..9a14106
--- /dev/null
+++ b/platform/realtek-ambz/ld/rlx8711B-symbol-v02-img2_xip2_2M_468k_cpp.ld
@@ -0,0 +1,222 @@
+
+
+ENTRY(Reset_Handler)
+
+INCLUDE "export-rom_symbol_v01.txt"
+
+GROUP (
+ libgcc.a
+ libc.a
+ libg.a
+ libm.a
+ libnosys.a
+)
+
+MEMORY
+{
+ ROM (rx) : ORIGIN = 0x00000000, LENGTH = 0x80000 /* ROM: 512k */
+ ROMBSS_RAM (rw) : ORIGIN = 0x10000000, LENGTH = 0x2000 /* ROM BSS RAM: 8K */
+ BOOTLOADER_RAM (rwx) : ORIGIN = 0x10002000, LENGTH = 0x3000 /* BOOT Loader RAM: 12K */
+ BD_RAM (rwx) : ORIGIN = 0x10005000, LENGTH = 0x38000 /* MAIN RAM: 224k */
+ ROM_BSS_RAM (rwx) : ORIGIN = 0x1003D000, LENGTH = 0x1000 /* ROM BSS RAM: 4K */
+ MSP_RAM (wx) : ORIGIN = 0x1003E000, LENGTH = 0x1000 /* MSP RAM: 4k */
+ RDP_RAM (wx) : ORIGIN = 0x1003F000, LENGTH = 0xFF0 /* RDP RAM: 4k-0x10 */
+
+ XIPBOOT (rx) : ORIGIN = 0x08000000+0x20, LENGTH = 0x04000-0x20 /* XIPBOOT: 16k, 32 Bytes resvd for header*/
+ XIPSYS (r) : ORIGIN = 0x08009000, LENGTH = 0x1000 /* XIPSYS: 4K system data in flash */
+ XIPCAL (r) : ORIGIN = 0x0800A000, LENGTH = 0x1000 /* XIPCAL: 4K calibration data in flash */
+ XIP1 (rx) : ORIGIN = 0x0800B000+0x20, LENGTH = 0x75000-0x20 /* XIP1: 468k, 32 Bytes resvd for header */
+ XIP2 (rx) : ORIGIN = 0x08080000+0x20, LENGTH = 0x75000-0x20 /* XIP2: 468k, 32 Bytes resvd for header */
+}
+
+
+
+SECTIONS
+{
+ .rom.text : { } > ROM
+ .rom.rodata : { } > ROM
+ .ARM.exidx :
+ {
+ __exidx_start = .;
+ *(.ARM.exidx*)
+ *(.gnu.linkonce.armexidx.*)
+ __exidx_end = .;
+ } > ROM
+ .hal.rom.bss : { } > ROMBSS_RAM
+
+ /* image1 entry, this section should in RAM and fixed address for ROM */
+ .ram_image1.entry :
+ {
+ __ram_image1_text_start__ = .;
+ __ram_start_table_start__ = .;
+ KEEP(*(SORT(.image1.entry.data*)))
+ __ram_start_table_end__ = .;
+
+ __image1_validate_code__ = .;
+ KEEP(*(.image1.validate.rodata*))
+ KEEP(*(.image1.export.symb*))
+ } > BOOTLOADER_RAM
+
+ /* Add . to assign the start address of the section */
+ /* to prevent the change of the start address by ld doing section alignment */
+ .ram_image1.text . :
+ {
+ /* image1 text */
+ *(.boot.ram.text*)
+ *(.boot.rodata*)
+ } > BOOTLOADER_RAM
+
+ .ram_image1.data . :
+ {
+ __ram_image1_data_start__ = .;
+ KEEP(*(.boot.ram.data*))
+ __ram_image1_data_end__ = .;
+
+ __ram_image1_text_end__ = .;
+ } > BOOTLOADER_RAM
+
+ .ram_image1.bss . :
+ {
+ __image1_bss_start__ = .;
+ KEEP(*(.boot.ram.bss*))
+ KEEP(*(.boot.ram.end.bss*))
+ __image1_bss_end__ = .;
+ } > BOOTLOADER_RAM
+
+ .ram_image2.entry :
+ {
+ __ram_image2_text_start__ = .;
+ __image2_entry_func__ = .;
+ KEEP(*(SORT(.image2.entry.data*)))
+
+ __image2_validate_code__ = .;
+ KEEP(*(.image2.validate.rodata*))
+
+ } > BD_RAM
+
+ .ram_image2.text :
+ {
+ KEEP(*(.image2.ram.text*))
+ } > BD_RAM
+
+ .ram_image2.data :
+ {
+ __data_start__ = .;
+ *(.data*)
+ __data_end__ = .;
+ __ram_image2_text_end__ = .;
+ . = ALIGN(16);
+ } > BD_RAM
+
+ .ram_image2.bss :
+ {
+ __bss_start__ = .;
+ *(.bss*)
+ *(COMMON)
+ } > BD_RAM
+
+ .ram_image2.skb.bss :
+ {
+ *(.bdsram.data*)
+ __bss_end__ = .;
+ } > BD_RAM
+
+ .ram_heap.data :
+ {
+ *(.bfsram.data*)
+ } > BD_RAM
+
+ . = ALIGN(8);
+ PROVIDE(heap_start = .);
+ PROVIDE(heap_end = 0x1003CFFF);
+ PROVIDE(heap_len = heap_end - heap_start);
+
+ .rom.bss :
+ {
+ *(.heap.stdlib*)
+ } > ROM_BSS_RAM
+
+ .ram_rdp.text :
+ {
+ __rom_top_4k_start_ = .;
+ __rdp_text_start__ = .;
+ KEEP(*(.rdp.ram.text*))
+ KEEP(*(.rdp.ram.data*))
+ __rdp_text_end__ = .;
+ . = ALIGN(16);
+
+ } > RDP_RAM
+
+ .xip_image1.text :
+ {
+ __flash_boot_text_start__ = .;
+
+ *(.flashboot.text*)
+
+ __flash_boot_text_end__ = .;
+
+ . = ALIGN(16);
+ } > XIPBOOT
+
+ .xip_image2.text :
+ {
+ __flash_text_start__ = .;
+
+ *(.img2_custom_signature*)
+ *(.text)
+ *(.text*)
+ *(.rodata)
+ *(.rodata*)
+ *(.debug_trace*)
+
+ /* https://www.embedded.com/building-bare-metal-arm-systems-with-gnu-part-3/ */
+ KEEP(*crtbegin.o(.ctors))
+ KEEP(*(EXCLUDE_FILE (*ctrend.o) .ctors))
+ KEEP(*(SORT(.ctors.*)))
+ KEEP(*crtend.o(.ctors))
+ KEEP(*crtbegin.o(.dtors))
+ KEEP(*(EXCLUDE_FILE (*crtend.o) .dtors))
+ KEEP(*(SORT(.dtors.*)))
+ KEEP(*crtend.o(.dtors))
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+
+ /* Add This for C++ support */
+ /* ambd_arduino/Arduino_package/hardware/variants/rtl8720dn_bw16/linker_scripts/gcc/rlx8721d_img2_is_arduino.ld */
+ . = ALIGN(4);
+ __preinit_array_start = .;
+ KEEP(*(.preinit_array))
+ __preinit_array_end = .;
+ . = ALIGN(4);
+ __init_array_start = .;
+ KEEP(*(SORT(.init_array.*)))
+ KEEP(*(.init_array))
+ __init_array_end = .;
+ . = ALIGN(4);
+ __fini_array_start = .;
+ KEEP(*(SORT(.fini_array.*)))
+ KEEP(*(.fini_array))
+ __fini_array_end = .;
+ /*-----------------*/
+
+ . = ALIGN (4);
+ __cmd_table_start__ = .;
+ KEEP(*(.cmd.table.data*))
+ __cmd_table_end__ = .;
+
+ /* https://community.silabs.com/s/article/understand-the-gnu-linker-script-of-cortex-m4?language=en_US */
+ KEEP(*(.init))
+ KEEP(*(.fini))
+ *(.init)
+ *(.fini)
+
+ __flash_text_end__ = .;
+
+ . = ALIGN (16);
+ } > XIP2
+}
+
+SECTIONS
+{
+ /* Bootloader symbol list */
+ boot_export_symbol = 0x10002020;
+}
diff --git a/tools/boardgen b/tools/boardgen
index 8685902..ee7f7d3 160000
--- a/tools/boardgen
+++ b/tools/boardgen
@@ -1 +1 @@
-Subproject commit 8685902886b9bb4eb42f2f348d64a8d72541d0df
+Subproject commit ee7f7d37c6ab42feffcb974c2f626b79142ae650