Merge remote-tracking branch 'adafruit/master' into wdt-nrf
This commit is contained in:
commit
2fd7a43f2f
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-05-27 10:46-0700\n"
|
||||
"POT-Creation-Date: 2020-05-29 10:15-0700\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
42
locale/cs.po
42
locale/cs.po
@ -3,25 +3,28 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-05-27 10:46-0700\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2020-05-29 10:15-0700\n"
|
||||
"PO-Revision-Date: 2020-05-24 03:22+0000\n"
|
||||
"Last-Translator: dronecz <mzuzelka@gmail.com>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"Language: cs\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 4.1-dev\n"
|
||||
|
||||
#: main.c
|
||||
msgid ""
|
||||
"\n"
|
||||
"Code done running. Waiting for reload.\n"
|
||||
msgstr ""
|
||||
"\n"
|
||||
"Kód byl dokončen. Čekám na opětovné načtení.\n"
|
||||
|
||||
#: supervisor/shared/safe_mode.c
|
||||
msgid ""
|
||||
@ -29,65 +32,70 @@ msgid ""
|
||||
"Please file an issue with the contents of your CIRCUITPY drive at \n"
|
||||
"https://github.com/adafruit/circuitpython/issues\n"
|
||||
msgstr ""
|
||||
"\n"
|
||||
"Založte prosím problém s obsahem vaší jednotky CIRCUITPY na adrese\n"
|
||||
"https://github.com/adafruit/circuitpython/issues\n"
|
||||
|
||||
#: supervisor/shared/safe_mode.c
|
||||
msgid ""
|
||||
"\n"
|
||||
"To exit, please reset the board without "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"Pro ukončení, prosím resetujte desku bez "
|
||||
|
||||
#: py/obj.c
|
||||
msgid " File \"%q\""
|
||||
msgstr ""
|
||||
msgstr " Soubor \"% q\""
|
||||
|
||||
#: py/obj.c
|
||||
msgid " File \"%q\", line %d"
|
||||
msgstr ""
|
||||
msgstr " Soubor \"% q\", řádek% d"
|
||||
|
||||
#: main.c
|
||||
msgid " output:\n"
|
||||
msgstr ""
|
||||
msgstr " výstup:\n"
|
||||
|
||||
#: py/objstr.c
|
||||
#, c-format
|
||||
msgid "%%c requires int or char"
|
||||
msgstr ""
|
||||
msgstr "%% c vyžaduje int nebo char"
|
||||
|
||||
#: shared-bindings/rgbmatrix/RGBMatrix.c
|
||||
#, c-format
|
||||
msgid "%d address pins and %d rgb pins indicate a height of %d, not %d"
|
||||
msgstr ""
|
||||
msgstr "%d adresní piny a %d rgb piny označují výšku %d, nikoli %d"
|
||||
|
||||
#: shared-bindings/microcontroller/Pin.c
|
||||
msgid "%q in use"
|
||||
msgstr ""
|
||||
msgstr "%q se nyní používá"
|
||||
|
||||
#: py/obj.c
|
||||
msgid "%q index out of range"
|
||||
msgstr ""
|
||||
msgstr "%q index je mimo rozsah"
|
||||
|
||||
#: py/obj.c
|
||||
msgid "%q indices must be integers, not %s"
|
||||
msgstr ""
|
||||
msgstr "Indexy% q musí být celá čísla, nikoli% s"
|
||||
|
||||
#: shared-bindings/vectorio/Polygon.c
|
||||
msgid "%q list must be a list"
|
||||
msgstr ""
|
||||
msgstr "Seznam% q musí být seznam"
|
||||
|
||||
#: shared-bindings/_bleio/CharacteristicBuffer.c
|
||||
#: shared-bindings/_bleio/PacketBuffer.c shared-bindings/displayio/Group.c
|
||||
#: shared-bindings/displayio/Shape.c shared-bindings/vectorio/Circle.c
|
||||
#: shared-bindings/vectorio/Rectangle.c
|
||||
msgid "%q must be >= 1"
|
||||
msgstr ""
|
||||
msgstr "% q musí být > = 1"
|
||||
|
||||
#: shared-module/vectorio/Polygon.c
|
||||
msgid "%q must be a tuple of length 2"
|
||||
msgstr ""
|
||||
msgstr "% q musí být n-tice délky 2"
|
||||
|
||||
#: shared-bindings/fontio/BuiltinFont.c
|
||||
msgid "%q should be an int"
|
||||
msgstr ""
|
||||
msgstr "% q by měl být int"
|
||||
|
||||
#: py/bc.c py/objnamedtuple.c
|
||||
msgid "%q() takes %d positional arguments but %d were given"
|
||||
|
547
locale/de_DE.po
547
locale/de_DE.po
File diff suppressed because it is too large
Load Diff
715
locale/nl.po
715
locale/nl.po
File diff suppressed because it is too large
Load Diff
2
main.c
2
main.c
@ -185,7 +185,7 @@ bool maybe_run_list(const char ** filenames, pyexec_result_t* exec_result) {
|
||||
}
|
||||
mp_hal_stdout_tx_str(filename);
|
||||
const compressed_string_t* compressed = translate(" output:\n");
|
||||
char decompressed[compressed->length];
|
||||
char decompressed[decompress_length(compressed)];
|
||||
decompress(compressed, decompressed);
|
||||
mp_hal_stdout_tx_str(decompressed);
|
||||
pyexec_file(filename, exec_result);
|
||||
|
@ -134,7 +134,7 @@ else
|
||||
endif
|
||||
endif
|
||||
|
||||
CFLAGS += $(INC) -Wall -Werror -std=gnu11 -nostdlib $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT)
|
||||
CFLAGS += $(INC) -Wall -Werror -std=gnu11 -nostdlib -fshort-enums $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT)
|
||||
|
||||
ifeq ($(CHIP_FAMILY), samd21)
|
||||
CFLAGS += \
|
||||
@ -157,7 +157,7 @@ endif
|
||||
|
||||
|
||||
|
||||
LDFLAGS = $(CFLAGS) -nostartfiles -fshort-enums -Wl,-nostdlib -Wl,-T,$(GENERATED_LD_FILE) -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections -specs=nano.specs
|
||||
LDFLAGS = $(CFLAGS) -nostartfiles -Wl,-nostdlib -Wl,-T,$(GENERATED_LD_FILE) -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections -specs=nano.specs
|
||||
LIBS := -lgcc -lc
|
||||
|
||||
# Use toolchain libm if we're not using our own.
|
||||
|
@ -110,7 +110,7 @@ endif
|
||||
|
||||
CFLAGS += $(INC) -Werror -Wall -mlongcalls -std=gnu11 -Wl,--gc-sections $(BASE_CFLAGS) $(C_DEFS) $(CFLAGS_MOD) $(COPT)
|
||||
|
||||
LDFLAGS = $(CFLAGS) -fshort-enums -Wl,-nostdlib -Wl,-Map=$@.map -Wl,-cref
|
||||
LDFLAGS = $(CFLAGS) -Wl,-nostdlib -Wl,-Map=$@.map -Wl,-cref
|
||||
LDFLAGS += -L$(BUILD)/esp-idf/esp-idf/esp32s2 \
|
||||
-Tesp32s2_out.ld \
|
||||
-L$(BUILD)/esp-idf/esp-idf/esp32s2/ld \
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 0daf6e0e41f95d22d193d08941a00df9525bc405
|
||||
Subproject commit 7aae7f034bab68d2dd6aaa763924c91eb697d87e
|
@ -32,6 +32,7 @@
|
||||
#define MICROPY_NLR_THUMB (0)
|
||||
|
||||
#define MICROPY_PY_UJSON (0)
|
||||
#define MICROPY_USE_INTERNAL_PRINTF (0)
|
||||
|
||||
#include "py/circuitpy_mpconfig.h"
|
||||
|
||||
|
@ -37,6 +37,24 @@ void mp_hal_delay_us(mp_uint_t delay) {
|
||||
mp_hal_delay_ms(delay / 1000);
|
||||
}
|
||||
|
||||
mp_uint_t cpu_get_regs_and_sp(mp_uint_t *regs) {
|
||||
// This is provided by the esp-idf/components/xtensa/esp32s2/libhal.a binary
|
||||
// blob.
|
||||
extern void xthal_window_spill(void);
|
||||
|
||||
mp_uint_t cpu_get_regs_and_sp(mp_uint_t *regs, uint8_t reg_count) {
|
||||
// xtensa has more registers than an instruction can address. The 16 that
|
||||
// can be addressed are called the "window". When a function is called or
|
||||
// returns the window rotates. This allows for more efficient function calls
|
||||
// because ram doesn't need to be used. It's only used if the window wraps
|
||||
// around onto itself. At that point values are "spilled" to empty spots in
|
||||
// the stack that were set aside. When the window rotates back around (on
|
||||
// function return), the values are restored into the register from ram.
|
||||
|
||||
// So, in order to read the values in the stack scan we must make sure all
|
||||
// of the register values we care about have been spilled to RAM. Luckily,
|
||||
// there is a HAL call to do it. There is a bit of a race condition here
|
||||
// because the register value could change after it's been restored but that
|
||||
// is unlikely to happen with a heap pointer while we do a GC.
|
||||
xthal_window_spill();
|
||||
return (mp_uint_t) __builtin_frame_address(0);
|
||||
}
|
||||
|
@ -259,7 +259,7 @@ CONFIG_ESP32S2_RTC_CLK_CAL_CYCLES=576
|
||||
CONFIG_ESP_ERR_TO_NAME_LOOKUP=y
|
||||
CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32
|
||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304
|
||||
CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584
|
||||
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
|
||||
CONFIG_ESP_IPC_TASK_STACK_SIZE=1024
|
||||
CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048
|
||||
CONFIG_ESP_CONSOLE_UART_DEFAULT=y
|
||||
|
@ -100,18 +100,20 @@ mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t lba, uint32
|
||||
_cache_lba = sector_offset;
|
||||
}
|
||||
for (uint8_t b = block_offset; b < blocks_per_sector; b++) {
|
||||
// Stop copying after the last block.
|
||||
if (block >= num_blocks) {
|
||||
break;
|
||||
}
|
||||
memcpy(_cache + b * FILESYSTEM_BLOCK_SIZE,
|
||||
src + block * FILESYSTEM_BLOCK_SIZE,
|
||||
FILESYSTEM_BLOCK_SIZE);
|
||||
block++;
|
||||
}
|
||||
result = esp_partition_erase_range(_partition, sector_offset, SECTOR_SIZE);
|
||||
ESP_EARLY_LOGW(TAG, "erase %d", result);
|
||||
result = esp_partition_write(_partition,
|
||||
sector_offset,
|
||||
_cache,
|
||||
SECTOR_SIZE);
|
||||
ESP_EARLY_LOGW(TAG, "write %d", result);
|
||||
}
|
||||
|
||||
return 0; // success
|
||||
|
@ -152,6 +152,9 @@ void port_sleep_until_interrupt(void) {
|
||||
// FreeRTOS delay here maybe.
|
||||
// Light sleep shuts down BLE and wifi.
|
||||
// esp_light_sleep_start()
|
||||
if (sleep_time_duration == 0) {
|
||||
return;
|
||||
}
|
||||
vTaskDelayUntil(&sleep_time_set, sleep_time_duration);
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,11 @@
|
||||
#include "lib/utils/interrupt_char.h"
|
||||
#include "lib/mp-readline/readline.h"
|
||||
|
||||
#include "esp-idf/components/soc/soc/esp32s2/include/soc/usb_periph.h"
|
||||
#include "esp-idf/components/driver/include/driver/periph_ctrl.h"
|
||||
#include "esp-idf/components/driver/include/driver/gpio.h"
|
||||
#include "esp-idf/components/esp_rom/include/esp32s2/rom/gpio.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
@ -64,16 +69,22 @@ void usb_device_task(void* param)
|
||||
}
|
||||
|
||||
void init_usb_hardware(void) {
|
||||
periph_module_reset(PERIPH_USB_MODULE);
|
||||
periph_module_enable(PERIPH_USB_MODULE);
|
||||
usb_hal_context_t hal = {
|
||||
.use_external_phy = false // use built-in PHY
|
||||
};
|
||||
usb_hal_init(&hal);
|
||||
|
||||
// Initialize the pin drive strength.
|
||||
gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3);
|
||||
gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3);
|
||||
|
||||
(void) xTaskCreateStatic(usb_device_task,
|
||||
"usbd",
|
||||
USBD_STACK_SIZE,
|
||||
NULL,
|
||||
configMAX_PRIORITIES-1,
|
||||
5,
|
||||
usb_device_stack,
|
||||
&usb_device_taskdef);
|
||||
}
|
||||
|
23
ports/esp32s2/tools/decode_backtrace.py
Normal file
23
ports/esp32s2/tools/decode_backtrace.py
Normal file
@ -0,0 +1,23 @@
|
||||
"""Simple script that translates "Backtrace:" lines from the ESP output to files
|
||||
and line numbers.
|
||||
|
||||
Run with: python3 tools/decode_backtrace.py <board>
|
||||
|
||||
Enter the backtrace line at the "? " prompt. CTRL-C to exit the script.
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
board = sys.argv[1]
|
||||
print(board)
|
||||
|
||||
while True:
|
||||
addresses = input("? ")
|
||||
if addresses.startswith("Backtrace:"):
|
||||
addresses = addresses[len("Backtrace:"):]
|
||||
addresses = addresses.strip().split()
|
||||
addresses = [address.split(":")[0] for address in addresses]
|
||||
print('got', addresses)
|
||||
subprocess.run(["xtensa-esp32s2-elf-addr2line",
|
||||
"-e", "build-{}/firmware.elf".format(board)] + addresses)
|
@ -83,14 +83,14 @@ else
|
||||
### CFLAGS += -flto
|
||||
endif
|
||||
|
||||
CFLAGS += $(INC) -Werror -Wall -std=gnu11 -nostdlib $(BASE_CFLAGS) $(C_DEFS) $(CFLAGS_MOD) $(COPT)
|
||||
CFLAGS += $(INC) -Werror -Wall -std=gnu11 -nostdlib -fshort-enums $(BASE_CFLAGS) $(C_DEFS) $(CFLAGS_MOD) $(COPT)
|
||||
|
||||
# TODO: check this
|
||||
CFLAGS += -D__START=main -DFOMU
|
||||
|
||||
LD_FILE := boards/$(BOARD)/$(BOARD)-spi.ld
|
||||
|
||||
LDFLAGS = $(CFLAGS) -fshort-enums -Wl,-nostdlib -Wl,-T,$(LD_FILE) -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections -specs=nano.specs -Wl,-melf32lriscv
|
||||
LDFLAGS = $(CFLAGS) -Wl,-nostdlib -Wl,-T,$(LD_FILE) -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections -specs=nano.specs -Wl,-melf32lriscv
|
||||
LIBS := -lgcc -lc
|
||||
|
||||
|
||||
|
@ -90,7 +90,7 @@ else
|
||||
#CFLAGS += -flto -flto-partition=none
|
||||
endif
|
||||
|
||||
CFLAGS += $(INC) -ggdb -Wall -Wno-cast-align -std=gnu11 -nostdlib $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT)
|
||||
CFLAGS += $(INC) -ggdb -Wall -Wno-cast-align -std=gnu11 -nostdlib -fshort-enums $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT)
|
||||
|
||||
# TODO: add these when -Werror is applied
|
||||
# Disable some warnings, as do most ports. NXP SDK causes undef, tinyusb causes cast-align
|
||||
@ -112,7 +112,7 @@ LD_FILES = $(wildcard boards/$(BOARD)/*.ld) $(addprefix linking/, flash/$(FLASH)
|
||||
|
||||
LD_SCRIPT_FLAG := -Wl,-T,
|
||||
|
||||
LDFLAGS = $(CFLAGS) -nostartfiles -fshort-enums -Wl,-nostdlib $(addprefix $(LD_SCRIPT_FLAG), $(LD_FILES)) -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections -specs=nano.specs
|
||||
LDFLAGS = $(CFLAGS) -nostartfiles -Wl,-nostdlib $(addprefix $(LD_SCRIPT_FLAG), $(LD_FILES)) -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections -specs=nano.specs
|
||||
LIBS := -lgcc -lc -lnosys -lm
|
||||
|
||||
# Use toolchain libm if we're not using our own.
|
||||
|
@ -93,7 +93,7 @@ else
|
||||
endif
|
||||
|
||||
|
||||
CFLAGS += $(INC) -Wall -Werror -std=gnu11 -nostdlib $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT)
|
||||
CFLAGS += $(INC) -Wall -Werror -std=gnu11 -nostdlib -fshort-enums $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT)
|
||||
|
||||
# Undo some warnings.
|
||||
# nrfx uses undefined preprocessor variables quite casually, so we can't do warning checks for these.
|
||||
@ -114,7 +114,7 @@ CFLAGS += \
|
||||
# TODO: check this
|
||||
CFLAGS += -D__START=main
|
||||
|
||||
LDFLAGS = $(CFLAGS) -nostartfiles -fshort-enums -Wl,-nostdlib -Wl,-T,$(GENERATED_LD_FILE) -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections -specs=nano.specs
|
||||
LDFLAGS = $(CFLAGS) -nostartfiles -Wl,-nostdlib -Wl,-T,$(GENERATED_LD_FILE) -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections -specs=nano.specs
|
||||
LIBS := -lgcc -lc
|
||||
|
||||
LDFLAGS += -mthumb -mcpu=cortex-m4
|
||||
|
@ -94,7 +94,7 @@ endif
|
||||
# MCU Series is defined by the HAL package and doesn't need to be specified here
|
||||
C_DEFS = -D$(MCU_PACKAGE) -DUSE_HAL_DRIVER -DUSE_FULL_LL_DRIVER -D$(MCU_VARIANT)
|
||||
|
||||
CFLAGS += $(INC) -Werror -Wall -std=gnu11 $(BASE_CFLAGS) $(C_DEFS) $(CFLAGS_MOD) $(COPT) -nostdlib -nostartfiles
|
||||
CFLAGS += $(INC) -Werror -Wall -std=gnu11 -fshort-enums $(BASE_CFLAGS) $(C_DEFS) $(CFLAGS_MOD) $(COPT) -nostdlib -nostartfiles
|
||||
|
||||
# Undo some warnings.
|
||||
# STM32 HAL uses undefined preprocessor variables, shadowed variables, casts that change alignment reqs
|
||||
@ -136,7 +136,7 @@ ifndef BOOTLOADER_OFFSET
|
||||
BOOTLOADER_OFFSET := 0x8000000
|
||||
endif
|
||||
|
||||
LDFLAGS = $(CFLAGS) -fshort-enums -Wl,-nostdlib -Wl,-T,$(LD_FILE) -Wl,-T,$(LD_COMMON) -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections -specs=nano.specs
|
||||
LDFLAGS = $(CFLAGS) -Wl,-nostdlib -Wl,-T,$(LD_FILE) -Wl,-T,$(LD_COMMON) -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections -specs=nano.specs
|
||||
LIBS := -lgcc -lc
|
||||
|
||||
# Use toolchain libm if we're not using our own.
|
||||
|
@ -135,7 +135,7 @@ STATIC void mp_help_print_modules(void) {
|
||||
|
||||
// let the user know there may be other modules available from the filesystem
|
||||
const compressed_string_t* compressed = translate("Plus any modules on the filesystem\n");
|
||||
char decompressed[compressed->length];
|
||||
char decompressed[decompress_length(compressed)];
|
||||
decompress(compressed, decompressed);
|
||||
mp_print_str(MP_PYTHON_PRINTER, decompressed);
|
||||
}
|
||||
@ -181,7 +181,7 @@ STATIC mp_obj_t mp_builtin_help(size_t n_args, const mp_obj_t *args) {
|
||||
// print a general help message. Translate only works on single strings on one line.
|
||||
const compressed_string_t* compressed =
|
||||
translate("Welcome to Adafruit CircuitPython %s!\n\nPlease visit learn.adafruit.com/category/circuitpython for project guides.\n\nTo list built-in modules please do `help(\"modules\")`.\n");
|
||||
char decompressed[compressed->length];
|
||||
char decompressed[decompress_length(compressed)];
|
||||
decompress(compressed, decompressed);
|
||||
mp_printf(MP_PYTHON_PRINTER, decompressed, MICROPY_GIT_TAG);
|
||||
} else {
|
||||
|
@ -48,7 +48,6 @@ BASE_CFLAGS = \
|
||||
-D__$(CHIP_VARIANT)__ \
|
||||
-ffunction-sections \
|
||||
-fdata-sections \
|
||||
-fshort-enums \
|
||||
-DCIRCUITPY_SOFTWARE_SAFE_MODE=0x0ADABEEF \
|
||||
-DCIRCUITPY_CANARY_WORD=0xADAF00 \
|
||||
-DCIRCUITPY_SAFE_RESTART_WORD=0xDEADBEEF \
|
||||
|
@ -121,7 +121,9 @@
|
||||
#define MICROPY_REPL_EVENT_DRIVEN (0)
|
||||
#define MICROPY_STACK_CHECK (1)
|
||||
#define MICROPY_STREAMS_NON_BLOCK (1)
|
||||
#ifndef MICROPY_USE_INTERNAL_PRINTF
|
||||
#define MICROPY_USE_INTERNAL_PRINTF (1)
|
||||
#endif
|
||||
|
||||
// fatfs configuration used in ffconf.h
|
||||
//
|
||||
|
@ -1,7 +1,10 @@
|
||||
"""
|
||||
Process raw qstr file and output qstr data with length, hash and data bytes.
|
||||
|
||||
This script works with Python 2.6, 2.7, 3.3 and 3.4.
|
||||
This script works with Python 2.7, 3.3 and 3.4.
|
||||
|
||||
For documentation about the format of compressed translated strings, see
|
||||
supervisor/shared/translate.h
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
@ -132,19 +135,37 @@ def compute_huffman_coding(translations, qstrs, compression_filename):
|
||||
print("// estimated total memory size", len(lengths) + 2*len(values) + sum(len(cb[u]) for u in all_strings_concat))
|
||||
print("//", values, lengths)
|
||||
values_type = "uint16_t" if max(ord(u) for u in values) > 255 else "uint8_t"
|
||||
max_translation_encoded_length = max(len(translation.encode("utf-8")) for original,translation in translations)
|
||||
with open(compression_filename, "w") as f:
|
||||
f.write("const uint8_t lengths[] = {{ {} }};\n".format(", ".join(map(str, lengths))))
|
||||
f.write("const {} values[] = {{ {} }};\n".format(values_type, ", ".join(str(ord(u)) for u in values)))
|
||||
f.write("#define compress_max_length_bits ({})\n".format(max_translation_encoded_length.bit_length()))
|
||||
return values, lengths
|
||||
|
||||
def decompress(encoding_table, length, encoded):
|
||||
def decompress(encoding_table, encoded, encoded_length_bits):
|
||||
values, lengths = encoding_table
|
||||
#print(l, encoded)
|
||||
dec = []
|
||||
this_byte = 0
|
||||
this_bit = 7
|
||||
b = encoded[this_byte]
|
||||
for i in range(length):
|
||||
bits = 0
|
||||
for i in range(encoded_length_bits):
|
||||
bits <<= 1
|
||||
if 0x80 & b:
|
||||
bits |= 1
|
||||
|
||||
b <<= 1
|
||||
if this_bit == 0:
|
||||
this_bit = 7
|
||||
this_byte += 1
|
||||
if this_byte < len(encoded):
|
||||
b = encoded[this_byte]
|
||||
else:
|
||||
this_bit -= 1
|
||||
length = bits
|
||||
|
||||
i = 0
|
||||
while i < length:
|
||||
bits = 0
|
||||
bit_length = 0
|
||||
max_code = lengths[0]
|
||||
@ -170,10 +191,11 @@ def decompress(encoding_table, length, encoded):
|
||||
searched_length += lengths[bit_length]
|
||||
|
||||
v = values[searched_length + bits - max_code]
|
||||
i += len(v.encode('utf-8'))
|
||||
dec.append(v)
|
||||
return ''.join(dec)
|
||||
|
||||
def compress(encoding_table, decompressed):
|
||||
def compress(encoding_table, decompressed, encoded_length_bits, len_translation_encoded):
|
||||
if not isinstance(decompressed, str):
|
||||
raise TypeError()
|
||||
values, lengths = encoding_table
|
||||
@ -182,6 +204,19 @@ def compress(encoding_table, decompressed):
|
||||
#print(lengths)
|
||||
current_bit = 7
|
||||
current_byte = 0
|
||||
|
||||
code = len_translation_encoded
|
||||
bits = encoded_length_bits+1
|
||||
for i in range(bits - 1, 0, -1):
|
||||
if len_translation_encoded & (1 << (i - 1)):
|
||||
enc[current_byte] |= 1 << current_bit
|
||||
if current_bit == 0:
|
||||
current_bit = 7
|
||||
#print("packed {0:0{width}b}".format(enc[current_byte], width=8))
|
||||
current_byte += 1
|
||||
else:
|
||||
current_bit -= 1
|
||||
|
||||
for c in decompressed:
|
||||
#print()
|
||||
#print("char", c, values.index(c))
|
||||
@ -342,14 +377,17 @@ def print_qstr_data(encoding_table, qcfgs, qstrs, i18ns):
|
||||
|
||||
total_text_size = 0
|
||||
total_text_compressed_size = 0
|
||||
max_translation_encoded_length = max(len(translation.encode("utf-8")) for original, translation in i18ns)
|
||||
encoded_length_bits = max_translation_encoded_length.bit_length()
|
||||
for original, translation in i18ns:
|
||||
translation_encoded = translation.encode("utf-8")
|
||||
compressed = compress(encoding_table, translation)
|
||||
compressed = compress(encoding_table, translation, encoded_length_bits, len(translation_encoded))
|
||||
total_text_compressed_size += len(compressed)
|
||||
decompressed = decompress(encoding_table, len(translation_encoded), compressed)
|
||||
decompressed = decompress(encoding_table, compressed, encoded_length_bits)
|
||||
assert decompressed == translation
|
||||
for c in C_ESCAPES:
|
||||
decompressed = decompressed.replace(c, C_ESCAPES[c])
|
||||
print("TRANSLATION(\"{}\", {}, {{ {} }}) // {}".format(original, len(translation_encoded)+1, ", ".join(["0x{:02x}".format(x) for x in compressed]), decompressed))
|
||||
print("TRANSLATION(\"{}\", {}) // {}".format(original, ", ".join(["{:d}".format(x) for x in compressed]), decompressed))
|
||||
total_text_size += len(translation.encode("utf-8"))
|
||||
|
||||
print()
|
||||
@ -385,6 +423,7 @@ if __name__ == "__main__":
|
||||
|
||||
qcfgs, qstrs, i18ns = parse_input_headers(args.infiles)
|
||||
if args.translation:
|
||||
i18ns = sorted(i18ns)
|
||||
translations = translate(args.translation, i18ns)
|
||||
encoding_table = compute_huffman_coding(translations, qstrs, args.compression_filename)
|
||||
print_qstr_data(encoding_table, qcfgs, qstrs, translations)
|
||||
|
@ -158,7 +158,7 @@ const char *mp_common_errno_to_str(mp_obj_t errno_val, char *buf, size_t len) {
|
||||
case ENOSPC: desc = translate("No space left on device"); break;
|
||||
case EROFS: desc = translate("Read-only filesystem"); break;
|
||||
}
|
||||
if (desc != NULL && desc->length <= len) {
|
||||
if (desc != NULL && decompress_length(desc) <= len) {
|
||||
decompress(desc, buf);
|
||||
return buf;
|
||||
}
|
||||
|
6
py/obj.c
6
py/obj.c
@ -94,17 +94,17 @@ void mp_obj_print_exception(const mp_print_t *print, mp_obj_t exc) {
|
||||
assert(n % 3 == 0);
|
||||
// Decompress the format strings
|
||||
const compressed_string_t* traceback = translate("Traceback (most recent call last):\n");
|
||||
char decompressed[traceback->length];
|
||||
char decompressed[decompress_length(traceback)];
|
||||
decompress(traceback, decompressed);
|
||||
#if MICROPY_ENABLE_SOURCE_LINE
|
||||
const compressed_string_t* frame = translate(" File \"%q\", line %d");
|
||||
#else
|
||||
const compressed_string_t* frame = translate(" File \"%q\"");
|
||||
#endif
|
||||
char decompressed_frame[frame->length];
|
||||
char decompressed_frame[decompress_length(frame)];
|
||||
decompress(frame, decompressed_frame);
|
||||
const compressed_string_t* block_fmt = translate(", in %q\n");
|
||||
char decompressed_block[block_fmt->length];
|
||||
char decompressed_block[decompress_length(block_fmt)];
|
||||
decompress(block_fmt, decompressed_block);
|
||||
|
||||
// Print the traceback
|
||||
|
@ -400,7 +400,7 @@ mp_obj_t mp_obj_new_exception_msg_vlist(const mp_obj_type_t *exc_type, const com
|
||||
|
||||
// Try to allocate memory for the message
|
||||
mp_obj_str_t *o_str = m_new_obj_maybe(mp_obj_str_t);
|
||||
size_t o_str_alloc = fmt->length + 1;
|
||||
size_t o_str_alloc = decompress_length(fmt);
|
||||
byte *o_str_buf = m_new_maybe(byte, o_str_alloc);
|
||||
|
||||
bool used_emg_buf = false;
|
||||
@ -433,7 +433,7 @@ mp_obj_t mp_obj_new_exception_msg_vlist(const mp_obj_type_t *exc_type, const com
|
||||
// We have some memory to format the string
|
||||
struct _exc_printer_t exc_pr = {!used_emg_buf, o_str_alloc, 0, o_str_buf};
|
||||
mp_print_t print = {&exc_pr, exc_add_strn};
|
||||
char fmt_decompressed[fmt->length];
|
||||
char fmt_decompressed[decompress_length(fmt)];
|
||||
decompress(fmt, fmt_decompressed);
|
||||
mp_vprintf(&print, fmt_decompressed, ap);
|
||||
exc_pr.buf[exc_pr.len] = '\0';
|
||||
|
@ -61,7 +61,7 @@
|
||||
//| length = 8000 // 440
|
||||
//| sine_wave = array.array("H", [0] * length)
|
||||
//| for i in range(length):
|
||||
//| sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15) + 2 ** 15)
|
||||
//| sine_wave[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 15) + 2 ** 15)
|
||||
//|
|
||||
//| sine_wave = audiocore.RawSample(sine_wave, sample_rate=8000)
|
||||
//| i2s = audiobusio.I2SOut(board.D1, board.D0, board.D9)
|
||||
|
@ -61,7 +61,7 @@
|
||||
//| length = 8000 // 440
|
||||
//| sine_wave = array.array("h", [0] * length)
|
||||
//| for i in range(length):
|
||||
//| sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15))
|
||||
//| sine_wave[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 15))
|
||||
//|
|
||||
//| dac = audioio.AudioOut(board.SPEAKER)
|
||||
//| sine_wave = audiocore.RawSample(sine_wave)
|
||||
|
@ -61,7 +61,7 @@
|
||||
//| length = 8000 // 440
|
||||
//| sine_wave = array.array("H", [0] * length)
|
||||
//| for i in range(length):
|
||||
//| sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15) + 2 ** 15)
|
||||
//| sine_wave[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 15) + 2 ** 15)
|
||||
//|
|
||||
//| dac = audioio.AudioOut(board.SPEAKER)
|
||||
//| sine_wave = audiocore.RawSample(sine_wave, sample_rate=8000)
|
||||
|
@ -63,7 +63,7 @@
|
||||
//| length = 8000 // 440
|
||||
//| sine_wave = array.array("H", [0] * length)
|
||||
//| for i in range(length):
|
||||
//| sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15) + 2 ** 15)
|
||||
//| sine_wave[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 15) + 2 ** 15)
|
||||
//|
|
||||
//| dac = audiopwmio.PWMAudioOut(board.SPEAKER)
|
||||
//| sine_wave = audiocore.RawSample(sine_wave, sample_rate=8000)
|
||||
|
@ -37,7 +37,7 @@
|
||||
#include "supervisor/serial.h"
|
||||
|
||||
void serial_write_compressed(const compressed_string_t* compressed) {
|
||||
char decompressed[compressed->length];
|
||||
char decompressed[decompress_length(compressed)];
|
||||
decompress(compressed, decompressed);
|
||||
serial_write(decompressed);
|
||||
}
|
||||
@ -58,12 +58,22 @@ STATIC int put_utf8(char *buf, int u) {
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t decompress_length(const compressed_string_t* compressed) {
|
||||
if (compress_max_length_bits <= 8) {
|
||||
return 1 + (compressed->data >> (8 - compress_max_length_bits));
|
||||
} else {
|
||||
return 1 + ((compressed->data * 256 + compressed->tail[0]) >> (16 - compress_max_length_bits));
|
||||
}
|
||||
}
|
||||
|
||||
char* decompress(const compressed_string_t* compressed, char* decompressed) {
|
||||
uint8_t this_byte = 0;
|
||||
uint8_t this_bit = 7;
|
||||
uint8_t b = compressed->data[this_byte];
|
||||
uint8_t this_byte = compress_max_length_bits / 8;
|
||||
uint8_t this_bit = 7 - compress_max_length_bits % 8;
|
||||
uint8_t b = (&compressed->data)[this_byte];
|
||||
uint16_t length = decompress_length(compressed);
|
||||
|
||||
// Stop one early because the last byte is always NULL.
|
||||
for (uint16_t i = 0; i < compressed->length - 1;) {
|
||||
for (uint16_t i = 0; i < length - 1;) {
|
||||
uint32_t bits = 0;
|
||||
uint8_t bit_length = 0;
|
||||
uint32_t max_code = lengths[0];
|
||||
@ -78,7 +88,7 @@ char* decompress(const compressed_string_t* compressed, char* decompressed) {
|
||||
if (this_bit == 0) {
|
||||
this_bit = 7;
|
||||
this_byte += 1;
|
||||
b = compressed->data[this_byte]; // This may read past the end but its never used.
|
||||
b = (&compressed->data)[this_byte]; // This may read past the end but its never used.
|
||||
} else {
|
||||
this_bit -= 1;
|
||||
}
|
||||
@ -91,14 +101,14 @@ char* decompress(const compressed_string_t* compressed, char* decompressed) {
|
||||
i += put_utf8(decompressed + i, values[searched_length + bits - max_code]);
|
||||
}
|
||||
|
||||
decompressed[compressed->length-1] = '\0';
|
||||
decompressed[length-1] = '\0';
|
||||
return decompressed;
|
||||
}
|
||||
|
||||
inline __attribute__((always_inline)) const compressed_string_t* translate(const char* original) {
|
||||
#ifndef NO_QSTR
|
||||
#define QDEF(id, str)
|
||||
#define TRANSLATION(id, len, compressed...) if (strcmp(original, id) == 0) { static const compressed_string_t v = {.length = len, .data = compressed}; return &v; } else
|
||||
#define TRANSLATION(id, firstbyte, ...) if (strcmp(original, id) == 0) { static const compressed_string_t v = { .data = firstbyte, .tail = { __VA_ARGS__ } }; return &v; } else
|
||||
#include "genhdr/qstrdefs.generated.h"
|
||||
#undef TRANSLATION
|
||||
#undef QDEF
|
||||
|
@ -29,13 +29,41 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// The format of the compressed data is:
|
||||
// - the size of the uncompressed string in UTF-8 bytes, encoded as a
|
||||
// (compress_max_length_bits)-bit number. compress_max_length_bits is
|
||||
// computed during dictionary generation time, and happens to be 8
|
||||
// for all current platforms. However, it'll probably end up being
|
||||
// 9 in some translations sometime in the future. This length excludes
|
||||
// the trailing NUL, though notably decompress_length includes it.
|
||||
//
|
||||
// - followed by the huffman encoding of the individual UTF-16 code
|
||||
// points that make up the string. The trailing "\0" is not
|
||||
// represented by a huffman code, but is implied by the length.
|
||||
// (building the huffman encoding on UTF-16 code points gave better
|
||||
// compression than building it on UTF-8 bytes)
|
||||
//
|
||||
// The "data" / "tail" construct is so that the struct's last member is a
|
||||
// "flexible array". However, the _only_ member is not permitted to be
|
||||
// a flexible member, so we have to declare the first byte as a separte
|
||||
// member of the structure.
|
||||
//
|
||||
// For translations where length needs 8 bits, this saves about 1.5
|
||||
// bytes per string on average compared to a structure of {uint16_t,
|
||||
// flexible array}, but is also future-proofed against strings with
|
||||
// UTF-8 length above 256, with a savings of about 1.375 bytes per
|
||||
// string.
|
||||
typedef struct {
|
||||
uint16_t length;
|
||||
const uint8_t data[];
|
||||
uint8_t data;
|
||||
const uint8_t tail[];
|
||||
} compressed_string_t;
|
||||
|
||||
// Return the compressed, translated version of a source string
|
||||
// Usually, due to LTO, this is optimized into a load of a constant
|
||||
// pointer.
|
||||
const compressed_string_t* translate(const char* c);
|
||||
void serial_write_compressed(const compressed_string_t* compressed);
|
||||
char* decompress(const compressed_string_t* compressed, char* decompressed);
|
||||
uint16_t decompress_length(const compressed_string_t* compressed);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SUPERVISOR_TRANSLATE_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user