[realtek-ambz2] Fix C++ support, implement SerialClass
This commit is contained in:
@@ -53,7 +53,7 @@ queue.AppendPublic(
|
||||
"-mthumb",
|
||||
"-mcmse",
|
||||
"-mfloat-abi=soft",
|
||||
"--specs=nosys.specs",
|
||||
"--specs=nano.specs",
|
||||
"-Wl,--use-blx",
|
||||
"-Wl,--undefined=gRamStartFun",
|
||||
"-Wl,-wrap,aesccmp_construct_mic_iv",
|
||||
|
||||
94
cores/realtek-ambz2/arduino/libraries/Serial/Serial.cpp
Normal file
94
cores/realtek-ambz2/arduino/libraries/Serial/Serial.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2023-05-24. */
|
||||
|
||||
#include "SerialPrivate.h"
|
||||
|
||||
#if HAS_SERIAL0
|
||||
SerialClass Serial0(0, PIN_SERIAL0_RX, PIN_SERIAL0_TX);
|
||||
#endif
|
||||
#if HAS_SERIAL1
|
||||
SerialClass Serial1(1, PIN_SERIAL1_RX, PIN_SERIAL1_TX);
|
||||
#endif
|
||||
#if HAS_SERIAL2
|
||||
SerialClass Serial2(2, PIN_SERIAL2_RX, PIN_SERIAL2_TX);
|
||||
#endif
|
||||
|
||||
static void callback(uint32_t param, uint32_t event) {
|
||||
if (event != RxIrq)
|
||||
return;
|
||||
hal_uart_adapter_t *uart = &pdUART;
|
||||
|
||||
uint8_t c;
|
||||
while (hal_uart_rgetc(uart, (char *)&c)) {
|
||||
#if LT_AUTO_DOWNLOAD_REBOOT && defined(LT_UART_ADR_PATTERN) && PIN_SERIAL2_RX != PIN_INVALID
|
||||
// parse UART protocol commands on UART2
|
||||
if (uart->base_addr == UART2)
|
||||
SerialClass::adrParse(c);
|
||||
#endif
|
||||
pdBUF.store_char(c);
|
||||
}
|
||||
}
|
||||
|
||||
void SerialClass::begin(unsigned long baudrate, uint16_t config) {
|
||||
if (!this->data) {
|
||||
this->data = new SerialData();
|
||||
this->buf = &BUF;
|
||||
|
||||
if (this->port == 2) {
|
||||
hal_uart_deinit(&log_uart);
|
||||
}
|
||||
|
||||
// TODO handle PIN_INVALID
|
||||
hal_uart_init(&UART, this->tx, this->rx, NULL);
|
||||
|
||||
if (this->rx != PIN_INVALID) {
|
||||
hal_uart_enter_critical();
|
||||
hal_uart_rxind_hook(&UART, callback, (uint32_t)this->data, RxIrq);
|
||||
UART.base_addr->ier_b.erbi = 1;
|
||||
UART.base_addr->ier_b.etbei = 0;
|
||||
hal_uart_exit_critical();
|
||||
}
|
||||
}
|
||||
|
||||
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) == SERIAL_DATA_7 ? 7 : 8;
|
||||
uint8_t parity = (config & SERIAL_PARITY_MASK) ^ 0b11;
|
||||
uint8_t stopBits = (config & SERIAL_STOP_BIT_MASK) == SERIAL_STOP_BIT_2 ? 2 : 1;
|
||||
|
||||
hal_uart_set_baudrate(&UART, baudrate);
|
||||
hal_uart_set_format(&UART, dataWidth, parity, stopBits);
|
||||
|
||||
this->baudrate = baudrate;
|
||||
this->config = config;
|
||||
}
|
||||
|
||||
void SerialClass::end() {
|
||||
if (!this->data)
|
||||
return;
|
||||
|
||||
hal_uart_deinit(&UART);
|
||||
|
||||
this->buf = NULL;
|
||||
this->baudrate = 0;
|
||||
delete DATA;
|
||||
}
|
||||
|
||||
void SerialClass::flush() {
|
||||
if (!this->data)
|
||||
return;
|
||||
while (UART.base_addr->tflvr_b.tx_fifo_lv != 0) {}
|
||||
}
|
||||
|
||||
size_t SerialClass::write(uint8_t c) {
|
||||
if (!this->data)
|
||||
return 0;
|
||||
while (!hal_uart_writeable(&UART)) {}
|
||||
hal_uart_putc(&UART, c);
|
||||
return 1;
|
||||
}
|
||||
18
cores/realtek-ambz2/arduino/libraries/Serial/SerialPrivate.h
Normal file
18
cores/realtek-ambz2/arduino/libraries/Serial/SerialPrivate.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2023-05-24. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <sdk_private.h>
|
||||
|
||||
typedef struct {
|
||||
hal_uart_adapter_t uart;
|
||||
RingBuffer buf;
|
||||
} SerialData;
|
||||
|
||||
#define DATA ((SerialData *)data)
|
||||
#define pDATA ((SerialData *)param)
|
||||
#define BUF (DATA->buf)
|
||||
#define pdBUF (pDATA->buf)
|
||||
#define UART (DATA->uart)
|
||||
#define pdUART (pDATA->uart)
|
||||
7
cores/realtek-ambz2/arduino/src/lt_defs.h
Normal file
7
cores/realtek-ambz2/arduino/src/lt_defs.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#error "Don't include this file directly"
|
||||
|
||||
#define LT_ARD_HAS_SERIAL 1
|
||||
|
||||
#define LT_ARD_MD5_MBEDTLS 1
|
||||
@@ -16,3 +16,7 @@
|
||||
#error "No serial port is available"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Auto-download-reboot detection pattern
|
||||
// "ping" command for BootROM
|
||||
#define LT_UART_ADR_PATTERN 'p', 'i', 'n', 'g', '\n'
|
||||
|
||||
@@ -19,7 +19,7 @@ void putchar_(char c) {
|
||||
}
|
||||
|
||||
void putchar_p(char c, unsigned long port) {
|
||||
while ((uart_dev[port]->tflvr & 0x1F) > 15) {}
|
||||
while (uart_dev[port]->tflvr_b.tx_fifo_lv >= Uart_Tx_FIFO_Size) {}
|
||||
uart_dev[port]->thr = c;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
// SDK
|
||||
extern hal_uart_adapter_t log_uart;
|
||||
void software_reset();
|
||||
void sys_swd_off();
|
||||
void sys_uart_download_mode();
|
||||
|
||||
@@ -134,26 +134,6 @@ SECTIONS
|
||||
*(.sram.data*)
|
||||
*(.data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP(*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP(*(SORT(.init_array.*)))
|
||||
KEEP(*(.init_array))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP(*(SORT(.fini_array.*)))
|
||||
KEEP(*(.fini_array))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
KEEP(*(.jcr*))
|
||||
. = ALIGN(4);
|
||||
/* All data end */
|
||||
@@ -282,29 +262,6 @@ SECTIONS
|
||||
/* put RO data sections need to be encrypted here */
|
||||
*(.xip.sec_rodata*)
|
||||
|
||||
/* 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 = .;
|
||||
/*-----------------*/
|
||||
/* https://community.silabs.com/s/article/understand-the-gnu-linker-script-of-cortex-m4?language=en_US */
|
||||
KEEP(*(.init))
|
||||
KEEP(*(.fini))
|
||||
*(.init)
|
||||
*(.fini)
|
||||
|
||||
__xip_code_text_end__ = .;
|
||||
} > XIP_FLASH_C
|
||||
|
||||
@@ -330,6 +287,30 @@ SECTIONS
|
||||
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 = .;
|
||||
/*-----------------*/
|
||||
|
||||
/* https://community.silabs.com/s/article/understand-the-gnu-linker-script-of-cortex-m4?language=en_US */
|
||||
KEEP(*(.init))
|
||||
KEEP(*(.fini))
|
||||
*(.init)
|
||||
*(.fini)
|
||||
|
||||
. = ALIGN(4);
|
||||
__xip_code_rodata_end__ = .;
|
||||
} > XIP_FLASH_P
|
||||
|
||||
@@ -50,6 +50,7 @@ Here's what has to be done to make that work:
|
||||
- Make sure not to make a mess in the `CCFLAGS`/`CPPDEFINES`, and only include what's needed there. Some flags are project-wide (family-independent) in `builder/frameworks/base.py`.
|
||||
- Use a **pure PlatformIO** project - **not ESPHome!**. Pass one of the generic boards you created before, and `framework = base` in `platformio.ini`. Generally, try to get the thing to compile.
|
||||
- Use a simple Hello World program - C, not C++. Only add `main()` function with a `printf()` and a `while(1)` loop.
|
||||
- I've noticed that using `nano.specs` instead of `nosys.specs` produces smaller binaries.
|
||||
|
||||
9. When you get it to link successfully, build a UF2 file.
|
||||
|
||||
@@ -91,3 +92,9 @@ Here's what has to be done to make that work:
|
||||
5. Write LibreTiny C APIs - in `lt_api.c`.
|
||||
|
||||
6. At this point, your Hello World code should work fine.
|
||||
|
||||
## Porting Arduino Core - C++ support
|
||||
|
||||
1. Add main.cpp and write wiring_*.c ports. GPIOs and stuff should work even without proper C++ support.
|
||||
|
||||
2. Port Serial library first. This should already show whether C++ works fine or if it doesn't. For example, calling `Serial.println()` refers to the virtual function `Print::write`, which will probably crash the chip if C++ is not being linked properly.
|
||||
|
||||
@@ -16,3 +16,7 @@ The code listens on UART1 for a link-check command (`01 E0 FC 01 00`). The baudr
|
||||
## Realtek AmebaZ
|
||||
|
||||
This only works when using [ltchiptool](ltchiptool.md) for flashing. Upon starting UART communication, the tool sends `55 AA 22 E0 D6 FC` (0x55AA followed by the `realtek-ambz` family ID). After detecting that pattern, the chip proceeds to reboot into UART download mode (using [`lt_reboot_download_mode()`](../../../ltapi/lt__device_8h.md))
|
||||
|
||||
## Realtek AmebaZ2
|
||||
|
||||
The code listens on UART2 for a `ping\n` command, that is sent by [ltchiptool](ltchiptool.md) (and possibly by the vendor flasher, too). The device is then rebooted to download mode.
|
||||
|
||||
Reference in New Issue
Block a user