summaryrefslogtreecommitdiff
path: root/bsp/ESP/ESP32_C6/SConstruct
blob: 2d877aebd133f016d8965cc5a994ab5c4d0eb924 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
import os
import sys
from esptool.bin_image import ELFFile
from esptool.targets import CHIP_DEFS

def elf2image(target, source, env):
    e = ELFFile("rtthread.elf")

    print("Creating esp32c6 image...")

    image = CHIP_DEFS["esp32c6"].BOOTLOADER_IMAGE()
    image.entrypoint = e.entrypoint
    image.flash_mode = 2  # dio

    image.segments = e.sections
    image.flash_size_freq = image.ROM_LOADER.parse_flash_size_arg("8MB")
    image.flash_size_freq += image.ROM_LOADER.parse_flash_freq_arg("80m")

    image.elf_sha256 = e.sha256()
    image.elf_sha256_offset = 0xb0

    before = len(image.segments)
    image.merge_adjacent_segments()
    if len(image.segments) != before:
        delta = before - len(image.segments)
        print("Merged %d ELF section%s" % (delta, "s" if delta > 1 else ""))

    image.verify()
    image.save("rtthread.bin")
    print("Successfully created esp32c6 image.")

if os.getenv('RTT_ROOT'):
    RTT_ROOT = os.getenv('RTT_ROOT')
else:
    RTT_ROOT = os.path.join(os.getcwd(), '..', '..', '..')

sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
import rtconfig
from building import *

TARGET = 'rtthread.' + rtconfig.TARGET_EXT
SDK_ROOT = os.path.abspath('./')

if os.path.exists(SDK_ROOT + '/libraries'):
    libraries_path_prefix = SDK_ROOT + '/libraries'
else:
    libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/libraries'

SDK_LIB = libraries_path_prefix
Export('SDK_LIB')
DefaultEnvironment(tools=[])
env = Environment(tools = ['mingw'],
    AS   = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
    CC   = rtconfig.CC, CFLAGS = rtconfig.CFLAGS,
    CXX  = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS,
    AR   = rtconfig.AR, ARFLAGS = '-rc',
    LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
env['ASCOM'] = env['ASPPCOM']

Export('RTT_ROOT')
Export('rtconfig')

C6_IDF_COMMIT = '4fa003074a73774369d38123749fe64b7b4acbd3'

def _use_c6_idf_when_official_has_none():
    """CI pkgs --update fetches RT-Thread-packages/esp-idf, which only sets
    CPPDEFINES for ESP32-C3. Swap in one reviewed C6 commit before the package
    SConscript runs. A tree that already has the C6 target is left as-is.
    The package may sit under this BSP's packages/ or under libraries/.
    The replacement is fetched by commit, not by the moving branch tip.
    """
    import shutil
    import subprocess
    from env_package import find_package_path
    dest = os.path.abspath(find_package_path(SDK_ROOT, 'ESP-IDF-latest'))
    sc = os.path.join(dest, 'SConscript')
    if not os.path.isfile(sc):
        return
    with open(sc, 'r', encoding='utf-8', errors='replace') as f:
        text = f.read()
    if 'esp32c6' in text:
        return
    tmp = dest + '.c6'
    if os.path.isdir(tmp):
        shutil.rmtree(tmp)
    subprocess.check_call(['git', 'init', tmp])
    subprocess.check_call([
        'git', '-C', tmp, 'remote', 'add', 'origin',
        'https://github.com/cms19859230182-lang/esp-idf.git',
    ])
    subprocess.check_call([
        'git', '-C', tmp, 'fetch', '--depth', '1', 'origin', C6_IDF_COMMIT,
    ])
    subprocess.check_call(['git', '-C', tmp, 'checkout', '--detach', 'FETCH_HEAD'])
    head = subprocess.check_output(
        ['git', '-C', tmp, 'rev-parse', 'HEAD']).decode().strip()
    if head != C6_IDF_COMMIT:
        shutil.rmtree(tmp)
        raise RuntimeError('fetched esp-idf is %s, this BSP expects %s'
                           % (head, C6_IDF_COMMIT))
    subprocess.check_call([
        'git', '-C', tmp, 'submodule', 'update', '--init', '--depth', '1',
        'components/mbedtls/mbedtls', 'components/heap/tlsf',
    ])
    git_meta = os.path.join(tmp, '.git')
    if os.path.isdir(git_meta):
        shutil.rmtree(git_meta)
    shutil.rmtree(dest)
    os.rename(tmp, dest)

_use_c6_idf_when_official_has_none()

def _match_idf_spi_lock_stub_to_spi_config():
    """components/esp_hw_support/port/esp32c6/spi_lock_stub.c defines
    spicommon_bus_using_iomux() and spi_bus_lock_get_by_id() as
    always-true/always-0, and the package's C6 block compiles it because its
    directory scan takes every .c under that port directory that is not in
    skip_name. It is there because the package does not build
    components/driver/spi_common.c for C6, and components/spi_flash/
    esp_flash_spi_init.c needs those two names: with SPI off this BSP has the
    same hole, so the stub stays.

    idf_port/SConscript compiles spi_common.c itself once BSP_USING_SPI is
    selected, and spi_common.c:726 and :743 define the same two names -- the
    real ones, the second of which hands the master driver a bus lock instead of
    the stub's 0. Two strong definitions of both names in one image is a link
    error, so the scan has to skip the stub in that configuration only. The
    switch is written into the package's own SConscript because that scan lives
    nowhere else; packages/ is not in the repository, so this is redone on every
    build and on every re-fetch of the package, and it is written as bytes to
    keep the file's own line endings.
    """
    import re
    from env_package import find_package_path

    with open(os.path.join(SDK_ROOT, 'rtconfig.h'), 'r',
              encoding='utf-8', errors='replace') as f:
        spi_selected = re.search(r'^[ \t]*#[ \t]*define[ \t]+BSP_USING_SPI[ \t]*$',
                                 f.read(), re.M) is not None

    sc = os.path.join(os.path.abspath(
        find_package_path(SDK_ROOT, 'ESP-IDF-latest')), 'SConscript')
    if not os.path.isfile(sc):
        return
    with open(sc, 'rb') as f:
        text = f.read()
    entry = b"\n        'spi_lock_stub',"
    have = entry in text
    if have == spi_selected:
        return
    if spi_selected:
        marker = b'skip_name = ('
        if marker not in text:
            # In ESP-IDF v6.1+, spi_lock_stub is no longer present; spi_common.c is built directly.
            return
        text = text.replace(marker, marker + entry, 1)
    else:
        text = text.replace(entry, b'', 1)
    with open(sc, 'wb') as f:
        f.write(text)

_match_idf_spi_lock_stub_to_spi_config()

objs = PrepareBuilding(env, RTT_ROOT, remove_components = ['libc'])

objs.extend(SConscript(os.path.join(libraries_path_prefix, 'drivers', 'SConscript'), variant_dir='build/libraries/drivers', duplicate=0))
DoBuilding(TARGET, objs)

env.AddPostAction(TARGET, elf2image)