From 2730ef20f0fbcd6e51761a904591a36cdfe7f339 Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Thu, 19 Dec 2024 17:03:00 +0900 Subject: [PATCH] Refactor --- microcontroller/ports/esp32/main/ble.c | 2 -- .../ports/esp32/main/include/cmd.h | 1 - microcontroller/ports/esp32/main/shell.c | 21 +++++++++---------- notebook/src/hooks/repl-context.tsx | 7 ++----- notebook/src/services/network.ts | 2 +- notebook/src/utils/bytecode.ts | 17 +++------------ server/src/compiler/compiler.ts | 17 +++++++-------- server/src/compiler/linker-script.ts | 8 ------- server/src/compiler/shadow-memory.ts | 10 +++++---- server/tests/compiler/compiler.test.ts | 3 ++- 10 files changed, 32 insertions(+), 56 deletions(-) diff --git a/microcontroller/ports/esp32/main/ble.c b/microcontroller/ports/esp32/main/ble.c index b241e43..15a482c 100644 --- a/microcontroller/ports/esp32/main/ble.c +++ b/microcontroller/ports/esp32/main/ble.c @@ -412,9 +412,7 @@ static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_ } static void write_action_handler(uint8_t *value, int value_len) { - puts("write action handler"); bs_shell_receptionist(value, value_len); - // esp_log_buffer_hex(GATTS_TAG, value, value_len); } void bs_ble_init(void) diff --git a/microcontroller/ports/esp32/main/include/cmd.h b/microcontroller/ports/esp32/main/include/cmd.h index 92076b0..ecf03e8 100644 --- a/microcontroller/ports/esp32/main/include/cmd.h +++ b/microcontroller/ports/esp32/main/include/cmd.h @@ -6,7 +6,6 @@ typedef enum { BS_CMD_NONE = 0x00, BS_CMD_LOAD, - BS_CMD_FLOAD, BS_CMD_JUMP, BS_CMD_RESET, diff --git a/microcontroller/ports/esp32/main/shell.c b/microcontroller/ports/esp32/main/shell.c index 687a6d0..c321774 100644 --- a/microcontroller/ports/esp32/main/shell.c +++ b/microcontroller/ports/esp32/main/shell.c @@ -59,7 +59,7 @@ static void ram_reset() { memset(dram, 0, dram_size); } -static void ram_memcpy(uint32_t* ram_dest, uint8_t *src, size_t len) { +static void ram_memcpy(uint8_t* ram_dest, uint8_t *src, size_t len) { memcpy(ram_dest, src, len); } @@ -89,6 +89,13 @@ static void flash_memcpy(uint8_t* flash_dest, uint8_t *src, size_t len) { ESP_ERROR_CHECK(esp_partition_write(text_partition, offset, src, len)); } +static void bs_memcpy(uint8_t* dest, uint8_t *src, size_t len) { + if (virtual_flash_ptr <= dest && dest <= virtual_flash_ptr + flash_read_size()) { + flash_memcpy(dest, src, len); + } else { + ram_memcpy(dest, src, len); + } +} void bs_shell_register_sender(void (* sender)(uint8_t*, uint32_t)) { result_sender = sender; @@ -104,16 +111,8 @@ void bs_shell_receptionist(uint8_t *task_data, int data_len) { { uint32_t address = *(uint32_t*)(task_data + (idx+1)); uint32_t size = *(uint32_t*)(task_data + (idx+5)); - ram_memcpy(address, task_data + (idx+9), size); - idx += (9 + size); - break; - } - case BS_CMD_FLOAD: - // | cmd(1byte) | address(4byte) | size(4byte) | data(size) | - { - uint32_t address = *(uint32_t*)(task_data + (idx+1)); - uint32_t size = *(uint32_t*)(task_data + (idx+5)); - flash_memcpy((uint8_t*)address, task_data + (idx+9), size); + ESP_LOGI(BS_SHELL_TAG, "Load %d bytes to %x", (int)size, (int)address); + bs_memcpy(address, task_data + (idx+9), size); idx += (9 + size); break; } diff --git a/notebook/src/hooks/repl-context.tsx b/notebook/src/hooks/repl-context.tsx index 7cb9b60..b376216 100644 --- a/notebook/src/hooks/repl-context.tsx +++ b/notebook/src/hooks/repl-context.tsx @@ -98,10 +98,7 @@ export default function ReplProvider({children}: {children: ReactNode}) { const sendCompileResult = async (compileResult: network.CompileResult) => { const bytecodeBuilder = new BytecodeBufferBuilder(MAX_MTU) for (const block of compileResult.result.blocks) { - if (block.isFlash) - bytecodeBuilder.loadToFlash(block.address, Buffer.from(block.data, "hex")); - else - bytecodeBuilder.loadToRAM(block.address, Buffer.from(block.data, "hex")); + bytecodeBuilder.load(block.address, Buffer.from(block.data, "hex")); } for (const entryPoint of compileResult.result.entryPoints) { bytecodeBuilder.jump(entryPoint); @@ -116,7 +113,7 @@ export default function ReplProvider({children}: {children: ReactNode}) { iram.actions.setUsedSegment(block.address, Buffer.from(block.data, "hex").length) else if (block.address >= dram.state.address && block.address < dram.state.address + dram.state.size) dram.actions.setUsedSegment(block.address, Buffer.from(block.data, "hex").length) - else if (block.isFlash) + else if (block.address >= flash.state.address && block.address < flash.state.address + flash.state.size) flash.actions.setUsedSegment(block.address, Buffer.from(block.data, "hex").length) } } diff --git a/notebook/src/services/network.ts b/notebook/src/services/network.ts index 8466590..18b1e57 100644 --- a/notebook/src/services/network.ts +++ b/notebook/src/services/network.ts @@ -3,7 +3,7 @@ import { CompileError, InternalError } from "../utils/error"; import { MemInfo } from "../utils/type"; export type MemoryUpdate = { - blocks: {address: number, data: string, isFlash: boolean}[], + blocks: {address: number, data: string}[], entryPoints: number[] } diff --git a/notebook/src/utils/bytecode.ts b/notebook/src/utils/bytecode.ts index de6f337..83cf7a6 100644 --- a/notebook/src/utils/bytecode.ts +++ b/notebook/src/utils/bytecode.ts @@ -4,7 +4,6 @@ import { MemInfo } from "./type"; export enum BYTECODE { NONE, LOAD, - FLOAD, JUMP, RESET, RESULT_LOG, @@ -28,30 +27,20 @@ export class BytecodeBufferBuilder { this.lastUnit = Buffer.alloc(0); } - public loadToRAM(address: number, data: Buffer) { - this.load(BYTECODE.LOAD, address, data); - return this - } - - public loadToFlash(address: number, data: Buffer) { - this.load(BYTECODE.FLOAD, address, data); - return this - } - - private load(loadCmd: number, address: number, data: Buffer) { + public load(address: number, data: Buffer) { let dataRemain = data.length; let offset = 0; let loadAddress = address; while (true) { if (LOAD_HEADER_SIZE + dataRemain <= this.lastUnitRemain) { - const header = this.createLoadHeader(loadCmd, loadAddress, dataRemain); + const header = this.createLoadHeader(BYTECODE.LOAD, loadAddress, dataRemain); const body = data.subarray(offset); this.lastUnit = Buffer.concat([this.lastUnit, header, body]); this.lastUnitRemain -= LOAD_HEADER_SIZE + dataRemain break; } else if (LOAD_HEADER_SIZE < this.lastUnitRemain) { const loadSize = (this.lastUnitRemain - LOAD_HEADER_SIZE) & ~0b11; // 4 byte align - const header = this.createLoadHeader(loadCmd, loadAddress, loadSize); + const header = this.createLoadHeader(BYTECODE.LOAD, loadAddress, loadSize); const body = data.subarray(offset, offset+loadSize); this.lastUnit = Buffer.concat([this.lastUnit, header, body]); diff --git a/server/src/compiler/compiler.ts b/server/src/compiler/compiler.ts index 03b68b9..b2b5a59 100644 --- a/server/src/compiler/compiler.ts +++ b/server/src/compiler/compiler.ts @@ -1,5 +1,5 @@ import {MemoryBlock, ShadowMemory} from "./shadow-memory"; -import {ElfReader, SECTION_TYPE, Symbol} from "./elf-reader"; +import {ElfReader, Section, SECTION_TYPE, Symbol} from "./elf-reader"; import * as fs from "fs"; import {execSync} from "child_process"; import { @@ -53,17 +53,16 @@ export class Compiler { } private load(shadowMemory: ShadowMemory, linkedElf: ElfReader, entryPointName: string) { - const blocks = linkedElf + const sections = linkedElf .readAllSections() - .filter(section => section.name !== EXTERNAL_SYMBOL_SECTION) - .map(section => ({address: section.address, data: section.value.toString("hex"), isFlash: false})); + .filter(section => section.name !== EXTERNAL_SYMBOL_SECTION && section.size !== 0); linkedElf.readDefinedSymbols().forEach(symbol => { shadowMemory.symbols.set(symbol.name, symbol); }); const entryPoint = shadowMemory.symbols.get(entryPointName)?.address; if (entryPoint === undefined) throw new Error(`Cannot find entry point: ${entryPointName}`); - shadowMemory.setUpdate(blocks, entryPoint); + shadowMemory.load(sections, entryPoint); } private readExternalSymbols(shadowMemory: ShadowMemory, objFile: ElfReader) { @@ -180,18 +179,18 @@ export class ModuleCompiler { private load(shadowMemory: ShadowMemory, linkedElf: ElfReader, entryPointName: string) { const dramSection = linkedElf.readSectionByName(this.DRAM_SECTION_NAME); const flashSection = linkedElf.readSectionByName(this.FLASH_SECTION_NAME); - const blocks: {address: number, data: string, isFlash: boolean}[] = [] + const sections: Section[] = [] if (dramSection !== undefined) - blocks.push({address: dramSection.address, data: dramSection.value.toString("hex"), isFlash: false}); + sections.push(dramSection); if (flashSection !== undefined) - blocks.push({address: flashSection.address, data: flashSection.value.toString("hex"), isFlash: true}); + sections.push(flashSection); linkedElf.readDefinedSymbols().forEach(symbol => { shadowMemory.symbols.set(symbol.name, symbol); }); const entryPoint = shadowMemory.symbols.get(entryPointName)?.address; if (entryPoint === undefined) throw new Error(`Cannot find entry point: ${entryPointName}`); - shadowMemory.setUpdate(blocks, entryPoint); + shadowMemory.load(sections, entryPoint); } private allocate(shadowMemory: ShadowMemory, linkedElf: ElfReader) { diff --git a/server/src/compiler/linker-script.ts b/server/src/compiler/linker-script.ts index df3166b..813a52a 100644 --- a/server/src/compiler/linker-script.ts +++ b/server/src/compiler/linker-script.ts @@ -120,15 +120,7 @@ export class LinkerScriptSection implements LinkerScriptCommand { toString(indent: number = 0) { return `\ ${'\t'.repeat(indent)}${this.name} : { -${'\t'.repeat(indent + 1)}. = 0x00000000; ${this.commands.map(comm => `${'\t'.repeat(indent + 1)}${comm}`).join('\n')} ${'\t'.repeat(indent)}} > ${this.memory.getName()}` } } - -class LinkerScriptFormatError extends Error { - constructor(message: string) { - super(message); - } -} - diff --git a/server/src/compiler/shadow-memory.ts b/server/src/compiler/shadow-memory.ts index c8c3fa3..c413c23 100644 --- a/server/src/compiler/shadow-memory.ts +++ b/server/src/compiler/shadow-memory.ts @@ -10,7 +10,7 @@ export type MemoryAddresses = { } type MemoryUpdate = { - blocks: {address: number, data: string, isFlash: boolean}[], + blocks: {name: string, address: number, data: string}[], entryPoints: number[] } @@ -30,9 +30,11 @@ export class ShadowMemory { this.flash = new MemoryRegion('Flash', addresses.flash.address, addresses.flash.size); } - setUpdate(blocks: {address: number, data: string, isFlash: boolean}[], entryPoint: number) { - this.updates.blocks = this.updates.blocks.concat(blocks); - this.updates.entryPoints.push(entryPoint) + load(sections: Section[], entryPoint: number) { + sections.forEach(section => { + this.updates.blocks.push({name: section.name, address: section.address, data: section.value.toString('hex')}); + }); + this.updates.entryPoints.push(entryPoint); } getUpdates() { diff --git a/server/tests/compiler/compiler.test.ts b/server/tests/compiler/compiler.test.ts index e656791..fe68959 100644 --- a/server/tests/compiler/compiler.test.ts +++ b/server/tests/compiler/compiler.test.ts @@ -1,5 +1,6 @@ import {FILE_PATH} from "../../src/constants"; -import {Compiler, ModuleCompiler, ShadowMemory} from "../../src/compiler/compiler"; +import {Compiler, ModuleCompiler} from "../../src/compiler/compiler"; +import {ShadowMemory} from "../../src/compiler/shadow-memory"; const COMPILER_PATH = '~/.espressif/tools/xtensa-esp32-elf/esp-2022r1-11.2.0/xtensa-esp32-elf/bin/'