Skip to content

Commit 0278853

Browse files
duncandrennanrojer
andauthored
Add bootloader stub generator for ESP32-C3 (#70)
* Ubuntu Groovy -> Impish * Add Windows build instructions * Add ESP32-C3 bootloader stub generator * Hacked wrap_stub.py to accept riscv32-esp ELF * Use duncandrennan/mongoose-os to build the ESP-IDF 4.3-dev docker containter Co-authored-by: Deomid "rojer" Ryabkov <[email protected]>
1 parent b998f2f commit 0278853

12 files changed

+236
-2
lines changed

README.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,10 @@ You will need:
6262
Commands to install all the build dependencies:
6363
* Ubuntu Linux: `sudo apt-get install build-essential git golang-go python3 libftdi-dev libusb-1.0-0-dev pkg-config`
6464
* Mac OS X (via [Homebrew](https://brew.sh/)): `brew install coreutils libftdi libusb-compat pkg-config`
65-
* Windows 10: `TODO`
65+
* Windows 10:
66+
* Install [MSYS2](https://www.msys2.org/)
67+
* `pacman -S --needed base-devel mingw-w64-x86_64-toolchain git mingw-w64-x86_64-go python mingw-w64-x86_64-libftdi mingw-w64-x86_64-libusb pkgconf`
68+
* Use a MSYS MinGW 64-bit shell
6669

6770
Clone the repo (note: doesn't have to be in `GOPATH`):
6871

cli/flash/esp/stub/stub_flasher.c

+43
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@
3333
#include "soc/uart_reg.h"
3434

3535
#include "led.h"
36+
#elif defined(ESP32C3)
37+
#include "esp32c3/rom/efuse.h"
38+
#include "esp32c3/rom/miniz.h"
39+
#include "esp32c3/rom/spi_flash.h"
40+
#include "soc/spi_mem_reg.h"
41+
#include "soc/uart_reg.h"
3642
#endif
3743

3844
#include "slip.h"
@@ -68,6 +74,18 @@ extern uint32_t _bss_start, _bss_end;
6874
#define SPI_USER_REG(i) (REG_SPI_BASE(i) + 0x1C)
6975

7076
#define SPI_W0_REG(i) (REG_SPI_BASE(i) + 0x40)
77+
#elif defined(ESP32C3)
78+
#define SPI_CMD_REG(i) SPI_MEM_CMD_REG(i)
79+
#define SPI_FLASH_WREN SPI_MEM_FLASH_WREN
80+
#define SPI_FLASH_RDID SPI_MEM_FLASH_RDID
81+
#define SPI_FLASH_SE SPI_MEM_FLASH_SE
82+
#define SPI_FLASH_BE SPI_MEM_FLASH_BE
83+
84+
#define SPI_ADDR_REG(i) SPI_MEM_ADDR_REG(i)
85+
86+
#define SPI_USER_REG(i) SPI_MEM_USER_REG(i)
87+
88+
#define SPI_W0_REG(i) SPI_MEM_W0_REG(i)
7189
#endif
7290

7391
enum read_state {
@@ -95,7 +113,11 @@ struct uart_buf {
95113

96114
static inline uint32_t ccount(void) {
97115
uint32_t r;
116+
#if defined(ESP32C3)
117+
__asm volatile ("csrr %0, 0x7e2" : "=r"(r));
118+
#else
98119
__asm volatile("rsr.ccount %0" : "=a"(r));
120+
#endif
99121
return r;
100122
}
101123

@@ -232,6 +254,19 @@ esp_rom_spiflash_result_t esp_rom_spiflash_erase_start(uint32_t addr,
232254

233255
return ESP_ROM_SPIFLASH_RESULT_OK;
234256
}
257+
#elif defined(ESP32C3)
258+
esp_rom_spiflash_result_t esp_rom_spiflash_erase_start(uint32_t addr,
259+
uint32_t cmd) {
260+
uint32_t length = 0;
261+
262+
if (cmd == SPI_FLASH_BE) {
263+
length = FLASH_BLOCK_SIZE;
264+
} else if (cmd == SPI_FLASH_SE) {
265+
length = FLASH_SECTOR_SIZE;
266+
}
267+
268+
return esp_rom_spiflash_erase_area(addr, length);
269+
}
235270
#endif
236271

237272
int do_flash_write(uint32_t addr, uint32_t len, uint32_t erase) {
@@ -570,10 +605,18 @@ uint32_t _stack[3072];
570605
void stub_main(void) {
571606
memset(&_bss_start, 0, (&_bss_end - &_bss_start));
572607
uint32_t *stack_end = &_stack[3071];
608+
#if defined(ESP32C3)
609+
__asm volatile("mv sp, %0\n"
610+
: // output
611+
: "r"(stack_end) // input
612+
: // scratch
613+
);
614+
#else
573615
__asm volatile("mov a1, %0\n"
574616
: // output
575617
: "a"(stack_end) // input
576618
: // scratch
577619
);
620+
#endif
578621
stub_main1();
579622
}

cli/flash/esp/stub/wrap_stub.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def _read_elf_file(self, f):
7878

7979
if ident[0] != 0x7f or ident[1:4] != b'ELF':
8080
raise FatalError("%s has invalid ELF magic header %s" % (self.name, ident))
81-
if machine != 0x5e:
81+
if machine != 0x5e and machine != 0xf3:
8282
raise FatalError("%s does not appear to be an Xtensa ELF file. e_machine=%04x" % (self.name, machine))
8383
self._read_sections(f, shoff, shstrndx)
8484

cli/flash/esp32c3/stub/Makefile

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#
2+
# Copyright (c) 2015 Cesanta Software Limited
3+
# All rights reserved
4+
#
5+
6+
STUB ?= stub.json
7+
COMMON_STUB_DIR = ../../esp/stub
8+
SDK ?= docker.io/mgos/esp32c3-build:4.3-dev
9+
LIBS ?=
10+
11+
SRCS = $(LIBS) $(COMMON_STUB_DIR)/stub_flasher.c $(COMMON_STUB_DIR)/slip.c
12+
13+
.PHONY: all
14+
15+
all: $(STUB)
16+
17+
$(STUB): $(SRCS) $(COMMON_STUB_DIR)/wrap_stub.py
18+
@echo " $(SRCS) -> $@"
19+
docker run --rm -i -v '$(CURDIR)/../..:/src' $(SDK) /bin/bash -c \
20+
"cd /src/esp32c3/stub && \
21+
riscv32-esp-elf-gcc -std=c99 -Wall -Werror -Os -DESP32C3 \
22+
-nostdlib -fno-builtin \
23+
-DCONFIG_IDF_TARGET_ESP32C3 -DCONFIG_IDF_TARGET_ARCH_RISCV \
24+
-I/src/esp32c3/stub \
25+
-I/opt/Espressif/esp-idf/components/esp32c3/include \
26+
-I/opt/Espressif/esp-idf/components/esp_common/include \
27+
-I/opt/Espressif/esp-idf/components/esp_rom/include \
28+
-I/opt/Espressif/esp-idf/components/soc/include \
29+
-I/opt/Espressif/esp-idf/components/soc/esp32c3/include \
30+
-I/opt/Espressif/esp-idf/components/spi_flash/private_include \
31+
-I/opt/Espressif/esp-idf/components/riscv/include \
32+
-L/opt/Espressif/esp-idf \
33+
-ffunction-sections -Wl,-static -Wl,--gc-sections \
34+
-Tstub.ld -o /tmp/stub.elf $(SRCS) && \
35+
$(COMMON_STUB_DIR)/wrap_stub.py --output=$@ /tmp/stub.elf"

cli/flash/esp32c3/stub/genstub.sh

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/bash
2+
3+
scriptdir=$(realpath $(dirname $0))
4+
5+
set -e -x
6+
7+
make -C "$scriptdir" \
8+
LIBS="spi_flash_rom_patch.c uart.c" \
9+
STUB="stub.json"
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#pragma once
2+
3+
#include "soc/spi_mem_reg.h"
4+
5+
#include "esp32c3/rom/ets_sys.h"
6+
#include "esp32c3/rom/spi_flash.h"
7+
#include "esp32c3/rom/md5_hash.h"
8+
#include "esp32c3/rom/uart.h"
9+
#include "esp32c3/rom/rtc.h"

cli/flash/esp32c3/stub/sdkconfig.h

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
#include "sdkconfig.h"
15+
#include "esp32c3/rom/spi_flash.h"
16+
#include "soc/spi_periph.h"
17+
#include "spi_flash_defs.h"
18+
19+
#define SPI_IDX 1
20+
21+
esp_rom_spiflash_result_t esp_rom_spiflash_write_disable(void)
22+
{
23+
REG_WRITE(SPI_MEM_CMD_REG(SPI_IDX), SPI_MEM_FLASH_WRDI);
24+
while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
25+
return ESP_ROM_SPIFLASH_RESULT_OK;
26+
}

cli/flash/esp32c3/stub/stub.json

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"params_start": 1077665792, "code": "9967aa97c207dc4b4111416722c47d1713944700d183798cbd8b3e94b305b4021375f50f06c6b3d5c5029720c4ffe78060052285b240224441018280b7e7cc3f9387070011673e971457056693058600b386b602b697d44363fbc60013861600d0c3b6972384a7005c5785075cd782807971b707006022d456ca37e4cc3f83aa870026d24ece52ccb759cd3f130a0400916406d64ad05ac85ec693890903d294b707006003a9c7011379f90f630e0908814b372bcd3fb707006088438326040091471375f50f63e0d70293972600ce979c4382879307000c6317f50085472320f40023a60402850b93fbfb0fe31579fd45bf9307b00d6316f5008d472320f400ddb79305000c9c541307040013060b006311b506850791466387d7049cd41456856793858700b386b6023697ba97238407005c562322070095eb91472320f400b7070060d847d8c7b2502254b707006023a8570192540259f249624ad24a424bb24b4561828023a4040255bf232004009dbf0547639de600056793068700b387d702d297ba972384a700894785bf7d3599bf9307c00d6309f5009307d00de31ef5f81305b00d19a01305000c413df1bf35714ac97d73056922cd26cb4ec756c35ac1dede7d7406cf52c5930709071a91930984fa8a97be99aa8b4e85ae8a328b9720c4ffe780c042130709070a9733098700130484f981443a9463ed54030567930707077d74930584fa8a97130484f93e94930707078a97be9522859720c4ffe780803f2285c1459720c4ffe78080e70145a9a8338a9a4063734b015a8a5286ca85338574019720c4ffe78020ee0dedd2854a859720c4ffe780c0e491452285232c09f8012f9147631ff502032689f9e3f5c4f8058eca854e859720c4ffe7806039832489f995bf1305300505631a91fa406a44da444a49ba492a4a9a4a0a4bf65b0d61828013054005cdb74d712ace881023229114232a5113232611142324811423202115232e3113232c4113232861132326711323248113232291132320a113232eb111ae8a32c89720c4ffe780203272478567fd177d8f930420036312072ab3f7fa0093043003639c07289720c4ffe780a0e22a849304400363130528b7e4cc3f1166130606038145138504009720c4ffe780c001b769cc3f21668145138509009720c4ffe7808000b7e53b40138604009385850715459720c4ffe780202ab7070060d853130500023ac63707340013074706d8d3d84713671710d8c79720c4ffe780402813064002814568189720c4ffe780c0fb6146814548109720c4ffe780e0fa7c08e14548103ed47d2bf327207e0569138a0400bec6416b330d4901938b0400925763e357038c1088089720c4ffe7804024f327207e3647930540026818998fbec6814449234da2f32d207ec24789c79257ca97636df4047327207ea647b38db741ba9deec4f326207e09675297584b8327cd00b728cd3f138c0800ba970d675297584fba9703274a00ba9711675297832c470203a704003ed4914703268c0263129605e31cf7fe9304700335aab3878a40724563ef6701c167fd17e98f91ebc1659720c4ffe78040d7631d05105a94b5bf85659720c4ffe78020d6631d05144a94adb79147e301f7fc7327207ef257958fba973ede732e207e93078900b387fc0213838700de9783ad4700ca9783c787005e93858b9dc3ee8605471a86a1651385090072ca9720c4ffe780c0c2fd57aa8d6305f510524e138309007327207e86476e869a85b387c741ba978810bec01acc9720c4ffe78080117327207ef327207ea646b697998fbec4f326207e624372456e869a8536ca9720c4ffe78060c069e17327207e9647d246958fba97bec2930789003388fc0283274c02114785075e9823220800638ce7022322fc02f247925613068005ee97ee968c1028193ece36d29720c4ffe78080de2c1968109720c4ffe780000ae1454810f52691b523220c02f1b7930450033247b707006013050002d8d39720c4ffe78060068320c11403248114268503290114832441148329c113032a8113832a4113032b0113832bc112032c8112832c4112032d0112832dc11171618280930460037db79304000465b7930480034db7856763e3c70075be1305200582805171cecfd6cbdec786d7a2d5a6d3cad1d2cddac9e2c57d731a91aa8bae89b28a0dc6856713052006328b63f1c70205631a91be502e549e540e59fe496e4ade4a4e4bbe4b2e4c6d618280056b05697d749307090c930404f58a97be9426859720c4ffe78020fb1307090c130a84fa0a973a9a1307090c0a97330c8700130404f43a94639d090205679307070c7d74930504f58a97130404f43e949307070c8a97be9522859720c4ffe78040f72285c1459720c4ffe780409f014595bf52859720c4ffe78020f54e8963733b015a894a86e2855e859720c4ffe78080a501c513053006b1b74a86e28526859720c4ffe780a0f263850a024a86e28552859720c4ffe78080f1d28522859720c4ffe78000f1c14522859720c4ffe7800099ca9bb389294185b7011106ce02c6b73700603707001098c3984393163700e3cd06febc4f370700017d176800f98f91453ec69720c4ffe7806095f240014505618280797126d24ad09307500581743759cd3f22d406d62305f10037040060fd14130949041c50370702008545d98f1cd01c501305a100e58f1cd0cd2285476311f504fd57a305f1008347a1002547fd1793f7f70f6362f7028a07ca979c438287c1450808652ab1476316f5026246d2454245cd34a305a10085451305b100592a0345a10005479307a5ff93f7f70fe36bf7f88da093071004a305f100f1bfc1450808ad2ab1476317f5006246d2454245dd33c9b793071005c5b7c1450808b92ab1476317f5006246d2454245e13b5db793071006d1b7cd3d71bf9720c4ffe780608e49bf1305b1008545a30501001d220345a100b25022549254025945618280c1450808212aaa8508082922a3050100a5b7c1450808192291476318f500c247914568009c433ec6cdb7930710f9adb7c1450808e520a1476316f500c247524798c3e9b7930710fa81bfb7e73b40011193870700014506ce22cc26cac04384439710c4ffe780c07fc167fd171307001085664166b705000101459720c4ffe780a08502c611cc0965130505719710c4ffe78040762286a6850145eff0eff02ac63165130505359710c4ffe780a074914568008d20b9352a840965130505719710c4ffe780207399476306f4009710c4ffe7804076f2406244d244056182803765cc3f3726cd3f93070500130606031d8e4111098681451305050006c69720c4ffe780809fb757cd3f9387c7023e81b240410125bf1713c4ff67004373797122d44ece52cc06d626d24ad056ca5ac85ec662c42a8aae891304000c9710c4ffe780a06d2a89e31b85fe0144930a000c130bb00d930bc00d130cd00d631734039304000c9710c4ffe780206be31c95fe2285b250225492540259f249624ad24a424bb24b224c456182809710c4ffe780c068aa84e30e55fd631d65019710c4ffe780a067630675016305850101444dbfca84b3078a0023809700050445b7", "code_start": 1077665800, "entry": 1077668158, "data": "dce03b40fae03b40fae03b409ae13b4050e13b40c0e73b40fee73b401ae83b4036e83b403ae83b4044e83b4044e83b4060e83b4072e83b4090e83b40", "data_start": 1070420016, "num_params": 2, "code_size": 2580, "data_size": 60}

cli/flash/esp32c3/stub/stub.ld

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright (c) 2016 Cesanta Software Limited
3+
* All rights reserved
4+
*/
5+
6+
/* See Table 3-­2. Internal Memory Address Mapping in technical manual
7+
* Refer to esp32c3 bootloader.ld for memory reserved for bootloader stages
8+
* Segments are placed before bootloader segments
9+
*/
10+
MEMORY {
11+
iram : org = 0x403BE000, len = 0x10000
12+
dram_bss : org = 0x3FCB6000, len = 0x10000
13+
dram : org = 0x3FCC6000, len = 0x10000
14+
}
15+
16+
ENTRY(stub_main)
17+
18+
SECTIONS {
19+
.params 0x403BE000 : {
20+
_params_start = ABSOLUTE(.);
21+
*(.params)
22+
_params_end = ABSOLUTE(.);
23+
} > iram
24+
25+
.text : ALIGN(4) {
26+
_code_start = ABSOLUTE(.);
27+
*(.literal)
28+
*(.text .text.*)
29+
} > iram
30+
31+
.bss : ALIGN(4) {
32+
_bss_start = ABSOLUTE(.);
33+
*(.bss)
34+
_bss_end = ABSOLUTE(.);
35+
} > dram
36+
37+
.data : ALIGN(4) {
38+
_data_start = ABSOLUTE(.);
39+
*(.data)
40+
*(.rodata .rodata.*)
41+
} > dram
42+
}
43+
44+
INCLUDE "components/esp_rom/esp32c3/ld/esp32c3.rom.ld"
45+
46+
PROVIDE ( memcpy = 0x40000358 );
47+
PROVIDE ( memset = 0x40000354 );
48+
PROVIDE ( MD5Init = 0x40000614 );
49+
PROVIDE ( MD5Update = 0x40000618 );
50+
PROVIDE ( MD5Final = 0x4000061c );
51+
PROVIDE ( ets_isr_mask = 0x40000608 );
52+
PROVIDE ( ets_isr_unmask = 0x4000060c );
53+
PROVIDE ( esp_rom_spiflash_erase_area = 0x400001e4 );

cli/flash/esp32c3/stub/uart.c

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright (c) 2014-2018 Cesanta Software Limited
3+
* All rights reserved
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the ""License"");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an ""AS IS"" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#include "uart.h"
19+
20+
#include "rom_functions.h"
21+
22+
uint32_t set_baud_rate(uint32_t uart_no, uint32_t old_baud_rate,
23+
uint32_t new_baud_rate) {
24+
uint32_t uart_reg = REG_READ(UART_CLKDIV_REG(uart_no));
25+
uint32_t uart_div = uart_reg & UART_CLKDIV_M;
26+
uint32_t fraction = (uart_reg >> UART_CLKDIV_FRAG_S) & UART_CLKDIV_FRAG_V;
27+
uart_div = (uart_div << 4) + fraction;
28+
uint32_t master_freq = uart_div * old_baud_rate;
29+
uart_div_modify(uart_no, master_freq / new_baud_rate);
30+
return uart_div;
31+
}

cli/flash/esp32c3/stub/uart.h

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright (c) 2014-2018 Cesanta Software Limited
3+
* All rights reserved
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#pragma once
19+
20+
#include <stdint.h>
21+
22+
uint32_t set_baud_rate(uint32_t uart_no, uint32_t old_baud_rate,
23+
uint32_t new_baud_rate);

0 commit comments

Comments
 (0)