适用场景: AG32 工程需要用 SDK 提供的 GPIO / UART / Timer 等外设,但引脚定义跟默认 board 模板的 board.ve 不一样。
核心概念:
– VE 文件 = 芯片内部信号 ↔ 物理引脚 的路由表
– 不写 Verilog,只配置引脚 — 不算”自定义 logic”
– “非自定义 logic” = platformio.ini 里不设 ip_name / logic_dir,不写 user_ip.v
– 仍然走 pio run -t buildlogic,但 Supra 编译出来是 0 logic slices,只有引脚路由
1. 完整工作流(3 步)
VE 写好 → ASF 写好
↓
pio run -t logic_clean # 清 .pio/logic/ 缓存(sconsign cache 不跟踪 ASF 修改)
↓
pio run -t buildlogic # 编译 VE + ASF → .pio/logic/<ve_name>.bin
↓
pio run -t logic # 烧 bitstream 到 CPLD(含 FCB config)
↓
pio run -t upload # 烧 MCU code 到 0x80000000
↓
ocd_resume.cfg reset + resume # 让 CPU 跑 main()
↓
monitor.py 监听 COM5
2. 写 VE 文件 (my_board.ve)
放在工程根目录(跟 platformio.ini 同级)。
# my_board.ve — AG32 引脚映射
# SYSCLK 跟 SDK 默认 BOARD_PLL_FREQUENCY 一致 (默认 100MHz)
SYSCLK 100
HSECLK 8
# === UART0 (log 打印) ===
UART0_UARTTXD PIN_68
UART0_UARTRXD PIN_69
# === GPIO 任务 ===
GPIO0_0 PIN_16 # input, pull-up (T2)
GPIO1_0 PIN_17 # output, toggle (T1)
GPIO2_0 PIN_23 # input, pull-up, FALLEDGE (T3 中断)
GPIO3_0 PIN_25 # input, pull-up (T4)
GPIO5_0 PIN_26 # input, pull-down (T5)
# === 4 LED (active-low) ===
GPIO4_0 PIN_31 # LED1
GPIO4_1 PIN_32 # LED2
GPIO4_2 PIN_33 # LED3
GPIO4_3 PIN_34 # LED4
重要规则:
1. 同一个物理引脚只能绑一个信号 (例如 SPI0_SI_IO0 和 GPIO0_0 共享硬件)
2. 同一个信号只能绑一个引脚
3. GPIOx_0 bit 0 容易跟其他外设冲突 (官方 board.ve 里 SPI0_SI_IO0 = GPIO0_0 = PIN_2),避开用 GPIO0_0
4. SYSCLK 必须跟 SDK 默认 BOARD_PLL_FREQUENCY 一致 (默认 100MHz)
– 用 200MHz 必须 build 加 -DBOARD_PLL_FREQUENCY=200000000
5. UART0 内部引脚由 chip-level 路由,VE 不需要重复声明
3. 写 ASF 文件 (my_board.asf)
放在工程根目录。设上拉/下拉、驱动电流、OD 模式等。
puts "************ DESIGN ASF — GPIO learning demo ************"
# 内部上拉 / 下拉 / 驱动电流 / OD 模式
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to PIN_16
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to PIN_23
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to PIN_25
set_instance_assignment -name WEAK_PULL_DOWN_RESISTOR ON -to PIN_26
# 可选:驱动电流(默认 8mA,需要驱动 LED 改成 16mA)
# set_instance_assignment -name CURRENT_STRENGTH 16MA -to PIN_31
最后一行必须保留换行符(不能是文件末尾)。
4. 配 platformio.ini
[setup]
board = agrv2k_303 ; 100-pin LQFP, 256KB flash
framework = agrv_sdk
program = my_app
build_src_filter = "-<*> +<./src/**/*.c>"
[setup_logic]
logic_ve = my_board.ve design.asf = ./my_board.asf logic_device = AGRV2KL100 ; *** 关键: 不设 ip_name / logic_dir *** ; *** 关键: 不写 user_ip.v ***
[setup_upload]
protocol = cmsis-dap-openocd debug_tool = ${this.protocol} upload_protocol = ${this.protocol} check_logic = 0 ; 烧 code 前跳过 check_logic(option bytes 没 FCB config 时会报 “No valid logic configuration”)
[setup_monitor]
logger_if = UART0 monitor_port = COM5 monitor_speed = 115200
[setup_batch]
; 空
[env]
platform = AgRV extends = setup setup_logic setup_upload setup_monitor setup_batch
[env:debug]
build_type = debug
[env:release]
build_type = release
关键点:
– check_logic = 0 — 必须加,否则烧 code 时 PIO 会读 option bytes 找 FCB config 失败
– logic_compress 不设(默认 false),256KB flash 用非压缩(100KB)足够
– 没设 ip_name / logic_dir — 走 VE-only 编译路径
5. 烧录 3 步
# 5.1 编译 VE + ASF → bitstream
pio run -e debug -t logic_clean # 清 .pio/logic 缓存(改 ASF 后必须清)
pio run -e debug -t buildlogic # 编译,生成 .pio/logic/my_board.bin
# 5.2 烧 bitstream 到 CPLD
pio run -e debug -t logic # 烧 my_board.bin 到 0x80027000 (256K 非压缩)
# 5.3 烧 MCU code 到 0x80000000
pio run -e debug -t upload # 烧 code.bin 到 0x80000000
注意:
– pio run -t logic_clean 必须每次改 ASF 后跑(sconsign cache 不跟踪 ASF 修改)
– pio run -t buildlogic 失败时,看 Total Pins: 14/128 等是否合理,以及 Processing my_board.asf 出现
6. 跑 main
烧完 code 后,板子 halt,需要 reset + resume:
# ocd_resume.cfg
source [find agrv2k.cfg]
reset
sleep 200
resume
sleep 200
shutdown
# 跑 reset + resume
"C:\Users\wangy\.platformio\packages\tool-agrv_openocd\bin\openocd.exe" \
-s "C:\Users\wangy\.platformio\platforms\AgRV\etc" \
-c "set ADAPTER cmsis-dap" \
-c "set ADAPTER_SPEED 10000" \
-f ocd_resume.cfg
7. 验证 VE + ASF 都生效
pio run -t buildlogic 输出里看 2 个关键行:
Processing C:/Users/wangy/.platformio/platforms/AgRV/boards/agrv2k_303/board.asf ...
Processing E:/AI_AG32/GPIO/my_project/./my_board.asf ...
************ DESIGN ASF - GPIO learning demo ************
第二行 = 你的 ASF 被加载。没看到就说明 design.asf 路径写错了。
Total Pins: 14/128 (10%) 之类的数字 — 跟 VE 里信号数对得上(GPIO + UART + HSE)。
0 logic slices, 0 errors — VE-only 编译特征,不是 user logic 编译。
8. 常见错误
8.1 Source 'logic\my_board.bin' not found, needed by target 'buildlogic'
原因: logic_clean 后没跑 buildlogic,或者 ip_name / logic_dir 设了但目录里没 .v 文件。
修复: 跑 pio run -t buildlogic,确认 Total Pins: ... 出现在日志里。
8.2 Error: syntax error at my_board.vx:40
原因: gen_vlog 生成的 .vx 有语法错。
修复: 检查 my_board.ve 里的引脚名拼写、是否有 pin_xxx 等保留字。
8.3 error: 'APB_MASK_GPIOGPIO_IDX' undeclared
原因: C 代码用了 PERIPHERAL_ENABLE(GPIO, GPIO_IDX) 宏,SDK peripherals.h 拼接成 APB_MASK_GPIOGPIO_IDX 出错。
修复: 改用 SYS_EnableAPBClock(APB_MASK_GPIO4) 直接调。
8.4 COM5 收不到任何数据
排查:
1. 用 openocd halt 看 PC 在哪个函数 → 确认 main loop 在跑
2. mrw 0x0300000C 看 CLK_CNTL bit 0-1 是不是 0b10 (PLL) + bit 6 是不是 1 (PLL_RDY)
3. mrw 0x40000034 看 IWDG 是不是 0(disabled)
4. 最重要: 用 monitor.py 听 15 秒以上,openocd 退出后 DAP-LINK 串口桥接要等几秒恢复
8.5 VE 引脚路由没生效(读到 0)
原因: 没跑 pio run -t logic 烧 bitstream 到 CPLD,或者 VE 文件名跟 platformio.ini 的 logic_ve= 不一致。
修复: 检查 .pio/logic/my_board.bin 是否存在(对应 logic_ve 文件名),重新跑 pio run -t logic 烧。
9. 一键脚本
把 3 步烧录合并成一个 PowerShell 脚本:
# flash_logic.ps1
$env:PLATFORMIO_HOME_DIR = 'C:\Users\wangy\.platformio'
$env:AGM_SUPRA = 'true'
Set-Location "E:\AI_AG32\GPIO\my_project"
& python -m platformio run -e debug -t logic_clean
& python -m platformio run -e debug -t buildlogic
& python -m platformio run -e debug -t logic
& python -m platformio run -e debug -t upload
.