添加汇编器的测试资源

This commit is contained in:
chai2010
2025-11-17 11:59:04 +08:00
parent 50749bce97
commit c608aa7082
11 changed files with 232 additions and 7 deletions

View File

@@ -90,7 +90,7 @@ func RunCountCodeLines(c *cli.Context) {
}
func needSkip(path string, data []byte) bool {
if !hasExt(path, ".wa", ".go", ".ws") {
if !hasExt(path, ".wa", ".wz", ".go", ".ws") {
return true
}
if strings.Contains(path, "3rdparty") {

View File

@@ -0,0 +1,116 @@
package main
import (
"fmt"
"io"
"log"
"os"
"time"
"go.bug.st/serial"
)
// 烧写配置
const (
portName = "/dev/ttyUSB0" // 根据您的系统修改为正确的串口名称 (e.g., COM3 on Windows)
baudRate = 115200
dataFile = "your_firmware.bin" // 假设这是你的汇编器生成的固件
flashAddr = 0x42000000 // ESP32-C3 Flash的典型起始地址之一
)
func main() {
// 1. 打开串口
mode := &serial.Mode{
BaudRate: baudRate,
DataBits: 8,
Parity: serial.NoParity,
StopBits: serial.OneStopBit,
}
port, err := serial.Open(portName, mode)
if err != nil {
log.Fatalf("无法打开串口 %s: %v", portName, err)
}
defer port.Close()
log.Printf("成功打开串口 %s", portName)
// 2. 模拟 ROM Bootloader 握手 (SYNC)
// 实际操作中,你需要发送一个复杂的命令序列,这里仅模拟发送
fmt.Println("--- 模拟 ROM Bootloader 握手 ---")
// 假设的同步命令(实际请查阅文档)
syncCmd := []byte{0x07, 0x07, 0x12, 0x20}
n, err := port.Write(syncCmd)
if err != nil {
log.Fatal(err)
}
log.Printf("发送了 %d 字节的同步命令。", n)
// 等待设备响应 (实际需要解析响应,这里只是等待)
time.Sleep(100 * time.Millisecond)
// 3. 模拟发送固件
fmt.Println("--- 模拟发送固件数据 ---")
firmware, err := os.ReadFile(dataFile)
if err != nil {
log.Fatalf("无法读取固件文件 %s: %v", dataFile, err)
}
// 假设的写入 Flash 命令头 (实际会包含地址、长度、校验和等)
// 在实际烧写中,会是 (Command Header + Data Segment Header + Firmware Chunk)
dataChunkSize := 256 // 假设每次发送256字节
for i := 0; i < len(firmware); i += dataChunkSize {
end := i + dataChunkSize
if end > len(firmware) {
end = len(firmware)
}
chunk := firmware[i:end]
// 实际烧写时,需要在发送数据块前发送一个带有目标地址和长度的命令包
// 模拟发送数据块
n, err := port.Write(chunk)
if err != nil {
log.Fatal(err)
}
log.Printf("发送数据块: 地址 0x%X, 长度 %d 字节", flashAddr+i, n)
// 实际烧写中,每发送一个块都需要等待设备的 ACK 确认
time.Sleep(1 * time.Millisecond)
}
// 4. 模拟运行命令 (RUN)
fmt.Println("--- 模拟 RUN 命令 ---")
// 实际操作中,你需要发送一个 RUN 命令,指定程序入口地址
// 5. 切换到串口监视模式
fmt.Println("--- 切换到串口监视模式,等待设备输出 ---")
// 启动一个 goroutine 来持续读取串口数据
go func() {
buf := make([]byte, 128)
for {
n, err := port.Read(buf)
if err != nil {
if err != io.EOF {
fmt.Printf("\n串口读取错误: %v\n", err)
}
return
}
if n > 0 {
fmt.Printf("%s", buf[:n])
}
}
}()
// 保持主程序运行,直到用户按下 Enter
fmt.Println("烧写和监视器已启动。按下 Enter 键退出...")
fmt.Scanln()
}

View File

@@ -0,0 +1,10 @@
module github.com/wa-lang/wa/internal/native/examples/esp32-c3-hello
go 1.17
require go.bug.st/serial v1.6.4
require (
github.com/creack/goselect v0.1.2 // indirect
golang.org/x/sys v0.19.0 // indirect
)

View File

@@ -0,0 +1,22 @@
github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0=
github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
go.bug.st/serial v1.6.4 h1:7FmqNPgVp3pu2Jz5PoPtbZ9jJO5gnEnZIvnI1lzve8A=
go.bug.st/serial v1.6.4/go.mod h1:nofMJxTeNVny/m6+KaafC6vJGj3miwQZ6vW4BZUGJPI=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@@ -0,0 +1,41 @@
// ESP32-C3
.section .text
.globl _start
_start:
// 1. (!)
// RAM 0x3FC80000 使
li sp, 0x3FC8FFFF
// 2. UART0 t0 (UART_BASE)
// !!! 0x60000000
li t0, 0x60000000
// 3.
call main
//
main:
li t1, msg // t1 =
loop:
lb t2, 0(t1) // t2 = *t1 ()
beqz t2, done // (), done
// UART0 0
// UART FIFO
sb t2, 0(t0) // t2 UART0 ( t0 + 0)
addi t1, t1, 1 // t1++ ()
j loop
done:
// /
wfi // Wait For Interrupt ()
j done
.section .rodata
msg:
.string "Hello from RISC-V Naked Assembly!\n"

View File

@@ -0,0 +1,35 @@
package main
// ESP32-C3 固件映像头 (Image Header)
// 结构体字段顺序和大小必须与硬件文档严格匹配
type ImageHeader struct {
Magic uint32 // 魔术字:必须是 0xE9
SegmentCount byte // 段的数量 (对于单段程序为 1)
SpiMode byte // SPI Flash 模式 (通常为 0x02)
SpiSpeed byte // SPI Flash 速度 (通常为 0x01)
SpiSize byte // SPI Flash 大小 (通常为 0x20)
EntryAddr uint32 // 程序入口点地址 (例如: 0x42000000)
Reserved [16]byte // 保留字段
Checksum byte // 映像头和所有段头的校验和(通常放在最后计算)
}
// 段头 (Segment Header)
type SegmentHeader struct {
LoadAddr uint32 // 该段数据将被加载到的 RAM/IRAM 地址
DataLen uint32 // 该段数据的字节长度
}
const (
ESP_IMAGE_MAGIC = 0xE9 // ESP32-C3 固件映像魔术字
// 假设的程序入口点地址 (Flash 地址)
// ROM Bootloader 会将它作为入口点执行
DEFAULT_ENTRY_ADDR = 0x42000000
)
// 假设这是您的 Go 汇编器生成的原始机器指令
var rawMachineCode = []byte{
// 假设这是 RISC-V 指令的机器码序列
0x13, 0x05, 0x00, 0x00, // li a0, 0
0x67, 0x80, 0x00, 0x00, // ret
// 实际代码会更长,包括 UART 操作
}

View File

@@ -0,0 +1,3 @@
# ESP32-C3 例子
TODO

View File

@@ -64,8 +64,6 @@ func (p *watPrinter) printFuncs_body(fn *ast.Func) {
for _, ins := range fn.Body.Insts {
p.printFuncs_body_ins(ins, 0)
}
return
}
func watPrinter_printFuncs_indent(w io.Writer, indent string, blkLevel int) {

View File

@@ -32,7 +32,7 @@ func (p *watPrinter) printImport() error {
fmt.Fprintf(p.w, "(import %q %q", importSpec.ObjModule, importSpec.ObjName)
fmt.Fprintf(p.w, " (memory")
if s := importSpec.Memory.Name; s != "" {
fmt.Fprintf(p.w, " $"+s)
fmt.Fprint(p.w, " $"+s)
}
fmt.Fprintf(p.w, " %d", importSpec.Memory.Pages)
if importSpec.Memory.MaxPages != 0 {
@@ -55,7 +55,6 @@ func (p *watPrinter) printImport_global(importSpec *ast.ImportSpec) {
watPrinter_identOrIndex(importSpec.GlobalName),
importSpec.GlobalType,
)
return
}
func (p *watPrinter) printImport_func(importSpec *ast.ImportSpec) {
@@ -76,5 +75,4 @@ func (p *watPrinter) printImport_func(importSpec *ast.ImportSpec) {
}
fmt.Fprint(p.w, ")")
return
}

View File

@@ -43,5 +43,4 @@ func (p *watPrinter) printType_func(typ *ast.TypeSection) {
}
fmt.Fprintln(p.w, "))")
return
}

View File

@@ -1,6 +1,9 @@
# 版本日志
- dev (2025-??-??)
- 完善中文版的支持, 修复中英文错误接口不能互通的问题
- 标准库增加中文版的“万国码/码八方”包
- 凹语言RISCV汇编器支持中文指令集
- v1.4.0 (2025-11-10)
- 修复 `wa init` 命令会卡死的问题
- 凹语言中文版技术平权继续, 双向导出了错误接口, 增加了多个中文包