香山CPU(国产开源)的 SoC SDK底层程序编写,以及其它开源SoC芯片介绍

香山CPU(国产开源)的 SoC SDK底层程序编写,以及其它开源SoC芯片介绍

  • 目的是用C语言在以香山开源CPU核为基础的开源SoC芯片的硬件平台上,编写完整的裸机SDK、RTOS驱动、Linux驱动。限于当前香山CPU还没有完整的开源SoC,没有外设模块,前期会借鉴蜂鸟E203、玄铁CH2601、OpenTitan、SiFive Freedom E310等带外设的开源SoC的模块寄存器来编写程序。因为没有香山CPU的开发板,程序都会运行在NEMU或QEMU模拟器上。

  • 香山开源CPU核的开发商是北京开源芯片研究院 ,目标是打造开源RISC-V产业生态,但现在才初步开始,并没有一款带所有外设的开源SoC,也没有开发板出售,当前的主线项目还只有香山CPU核;

作者 将狼才鲸
创建时间 2025-12-18

一、前言

  • 困扰:换过几家公司,用过几种芯片,它们有着不同的CPU核,不同的外设寄存器,不同的协议栈代码(例如8051、ARM Cortex-M、ARM Cortex-A、Xtensa、TI C66x、AVR),总是做一些重复性工作。既然芯片总是换来换去,代码没有延续性,反正都是要换的,为何不干脆针对一款普及最广的开源CPU IP核以及开源SoC芯片写一些底层代码呢?这样利用空余时间还能不断迭代代码,学习一些新思路。

    • 这些底层SDK代码原本是会由芯片厂商提供的,也就是由芯片厂商里的嵌入式软件工程师编写。但是当前并没有专门提供可商用开源SoC芯片的公司,所以我准备选一个CPU核写一点。
    • 因此这个学习型仓库的受众是芯片厂商的嵌入式软件工程师(SDK、中间件、操作系统移植、驱动),一般公司的嵌入式驱动软件工程师,以及对底层工作内容感兴趣的嵌入式应用软件工程师。
  • 基于上述目的搜索了一下可用的硬件平台;

    • 开源的CPU指令集:RISC‑V(使用最多)、OpenRISC、SPARC V8/V9、MIPS开源版本、OpenSPARC、OpenPOWER、MIPS Open、LatticeMico32、WARP‑V、MOR1KX;
    • 开源的CPU核(IP):香山(国产)、玄铁C906/C910(国产)、wujian100_open/玄铁CH2601(国产)、VexRiscv、PicoRV32、Rocket、BlackParrot、OpenRio、CV32E40P、NEORV32、Ibex、CVA6、Ariane、BOOM、CV32E40P、darkriscv、Hummingbirdv2 E203、木心处理器、Sodor、YARVI、Pulpino、GRVI Phalanx、SweRV EH1、PicoRio、RISCY;
      • 里面有很多是用在FPGA上,或者仅供研究无法商用,或者不再更新迭代的;
    • 开源的MCU/SoC(CPU+总线+外设):蜂鸟Hummingbird E203(国产,偏教学)、LiteX(适配多种CPU核,SoC生成器)、Freedom E310、OpenTitan、X-HEEP、Sodor SoC、OpenPiton、NEORV32、IOb-SoC、PicoRV32 + PicoSoC、VexRiscv + Murax、Rocket Chip、PULPino;
      • 基本上都是用在FPGA上,或者仅供研究无法商用,或者不是通用MCU的
    • 最终选定香山CPU核,再融合其它开源SoC里的模块,在QEMU模拟器上运行代码。
  • 香山CPU核资料:

  • 挑战:香山是高性能CPU,本意是为服务器芯片、AI芯片、GPU、DPU、工业控制、能源、医疗、汽车、通信和机器人应用场景设计,而不是为嵌入式场景设计的,所以为了在SoC上集成USB、网络、串口、SPI、I2C、SD、2D等开源IP核,还要想些办法,主要是把开源外设模块的寄存器实现移植到QEMU的模拟器中去

  • 已商用的产品:

  • 阿里达摩院平头哥玄铁开源了E902、E906、C906、C9104四款量产处理器IP核,其中E系列为MCU级别的;

  • 蜂鸟E203 SoC资料:

  • LiteX SoC资料


二、资料阅读

三、NEMU模拟器运行实践

  • 我使用的平台是VMware17.5.2虚拟机 + Ubuntu20.04系统
  • 记住:以下所有export注册环境变量都是临时的!命令行终端关闭后就失效了,如果要永久生效,请手动添加到~/.bashrc中,并source ~/.bashrc
1. NEMU模拟器的安装与香山CPU裸机程序运行
  • 参考:NEMU 使用指南
  • 下载源码:git clone https://gitee.com/OpenXiangShan/NEMU.git
  • 进入NEMU仓库所在位置,执行export NEMU_HOME=$(pwd)
  • make riscv64-xs_defconfig
    • 期间会从GitHub下载子模块
    • 需要先安装SDL2:sudo apt install libsdl2-2.0-0 libsdl2-dev,如果有冲突则使用sudo aptitude install libsdl2-2.0-0 libsdl2-dev,第一步输入N,后续一路输入Y解决冲突
    • 需要先安装readline库:sudo apt install libreadline8 libreadline-dev
    • 需要先安装zstd 库:sudo apt install libzstd1 libzstd-dev
  • make -j4
shell 复制代码
jim@virtual-pc:~/nemu$ make -j4
+ CC src/nemu-main.c
.
+ CXX src/memory/store_queue_wrapper.cpp
+ g++ /home/jim/nemu/build/riscv64-nemu-interpreter
jim@virtual-pc:~/nemu$ 
shell 复制代码
jim@virtual-pc:~/nexus-am/apps/hello$ ~/nemu/build/riscv64-nemu-interpreter ~/nexus-am/apps/hello/build/hello-riscv64-xs.bin
[src/isa/riscv64/init.c:234,init_isa] NEMU will start from pc 0x80000000
[src/device/io/port-io.c:35,add_pio_map_with_diff] Add port-io map 'uartlite' at [0x00000000000003f8, 0x0000000000000404]
[src/device/io/port-io.c:35,add_pio_map_with_diff] Add port-io map 'screen' at [0x0000000000000100, 0x0000000000000107]
[src/device/io/port-io.c:35,add_pio_map_with_diff] Add port-io map 'keyboard' at [0x0000000000000060, 0x0000000000000063]
[src/device/sdcard.c:137,init_sdcard] Can not find sdcard image: 
[src/monitor/image_loader.c:204,load_img] Loading image (checkpoint/bare metal app/bbl) from cmdline: /home/jim/nexus-am/apps/hello/build/hello-riscv64-xs.bin

[src/monitor/image_loader.c:260,load_img] Read 7048 bytes from file /home/jim/nexus-am/apps/hello/build/hello-riscv64-xs.bin to 0x0x776dee614000
[src/monitor/monitor.c:63,welcome] Debug: OFF
[src/monitor/monitor.c:68,welcome] Build time: 01:01:30, Dec 20 2025
Welcome to riscv64-NEMU!
For help, type "help"
(nemu) c
Hello Xiangshan!
这是裸机程序输出的字符串!
[/home/jim/nemu/src/isa/riscv64/include/../instr/special.h:38,execute] nemu_trap case 0
[src/cpu/cpu-exec.c:938,cpu_exec] nemu: HIT GOOD TRAP at pc = 0x0000000080000060
[src/cpu/cpu-exec.c:944,cpu_exec] trap code:0
[src/cpu/cpu-exec.c:155,monitor_statistic] host time spent = 7,328 us
[src/cpu/cpu-exec.c:157,monitor_statistic] total guest instructions = 1,456
[src/cpu/cpu-exec.c:158,monitor_statistic] vst count = 0, vst unit count = 0, vst unit optimized count = 0
[src/cpu/cpu-exec.c:161,monitor_statistic] simulation frequency = 198,689 instr/s
(nemu) q
[src/utils/state.c:30,is_exit_status_bad] NEMU exit with good state: 2, halt ret: 0
jim@virtual-pc:~/nexus-am/apps/hello$ 
2. 交叉编译工具的获取
  • 交叉编译工具链说明

    • riscv64-linux-gnu- 用于Linux
    • riscv64-unknown-linux-gnu- 用于Linux
    • riscv64-unknown-elf- 用于嵌入式,裸机
    • 三款处理器指令集默认均为 RV64GC
    • 香山处理器南湖架构支持 RV64GCBK 扩展
  • 获取预编译好的夜间版本(预编译版本,不需要自行从源码编译)

    • riscv64-elf-ubuntu-20.04-gcc-nightly-2024.04.12-nightly.tar.gz
    • riscv64-glibc-ubuntu-20.04-gcc-nightly-2024.04.12-nightly.tar.gz
  • 将下载到的 2 个 tar.gz 文件解压到 /opt,并把 /opt/riscv/bin 添加到 PATH 中。

    • sudo tar -xzf riscv64-elf-ubuntu-20.04-gcc-nightly-2024.04.12-nightly.tar.gz -C /opt
    • sudo tar -xzf riscv64-glibc-ubuntu-20.04-gcc-nightly-2024.04.12-nightly.tar.gz -C /opt
    • export PATH=/opt/riscv/bin:$PATH
  • 完成后,通过以下命令检查安装是否成功:

    • riscv64-unknown-linux-gnu-gcc --version
    • riscv64-unknown-linux-gnu-g++ --version
    • riscv64-unknown-linux-gnu-gfortran --version
    • riscv64-unknown-linux-gnu-objdump --version
    • riscv64-unknown-linux-gnu-gdb --version
    • riscv64-unknown-elf-gcc --version
    • riscv64-unknown-elf-g++ --version
    • riscv64-unknown-elf-objdump --version
    • riscv64-unknown-elf-gdb --version
3. 使用AM运行时库编译裸机程序
  • 基于 AM 构建自定义裸机工作负载

  • 在~家目录获取AM源码:git clone https://gitee.com/OpenXiangShan/nexus-am.git

  • export AM_HOME=~/nexus-am

  • export CROSS_COMPILE=/opt/riscv/bin/riscv64-unknown-elf- 不知道为什么改了这一步后编译还是提示riscv64-linux-gnu-gcc找不到,因此用蠢办法强行解决:

    • cp /opt/riscv/bin/riscv64-unknown-elf-gcc /opt/riscv/bin/riscv64-linux-gnu-gcc 这是为了解决后面编译时报错,并且要用错误的编译器工具名称编出非Linux系统的裸机程序
    • cp /opt/riscv/bin/riscv64-unknown-elf-ld /opt/riscv/bin/riscv64-linux-gnu-ld
    • cp /opt/riscv/bin/riscv64-unknown-elf-objdump /opt/riscv/bin/riscv64-linux-gnu-objdump
    • cp /opt/riscv/bin/riscv64-unknown-elf-objcopy /opt/riscv/bin/riscv64-linux-gnu-objcopy
  • cd ~/nexus-am/apps

  • mkdir hello

  • cd hello

  • vim Makefile

    • 加入内容:
makefile 复制代码
NAME = hello
SRCS = $(shell find -L ./src/ -name "*.c")
include $(AM_HOME)/Makefile.app
  • mkdir src
  • vim src/hello.c
    • 加入内容:
c 复制代码
#include <klib.h>

int main() {
  printf("Hello Xiangshan!\n");
  printf("这是裸机程序输出的字符串!\n");
  return 0;
}
  • make ARCH=riscv64-xs
shell 复制代码
jim@virtual-pc:~/nexus-am/apps/hello$ make ARCH=riscv64-xs
# Building hello [riscv64-xs] with AM_HOME {/home/jim/nexus-am}
# Building lib-am [riscv64-xs]
+ AS src/nemu/common/mainargs.S
+ AR -> build/am-riscv64-xs.a
# Building lib-klib [riscv64-xs]
# Creating binary image [riscv64-xs]
+ LD -> build/hello-riscv64-xs.elf
+ OBJCOPY -> build/hello-riscv64-xs.bin
jim@virtual-pc:~/nexus-am/apps/hello$ 
  • 如果上面编译流程报错可以参考下面的流程:
  • 用NEMU运行裸机程序的命令 ~/nemu/build/riscv64-nemu-interpreter ~/nexus-am/apps/hello/build/hello-riscv64-xs.bin
4. 编译Linux、rootfs、设备树、OpenSBI获取可执行文件
相关推荐
d111111111d2 小时前
编码器测速详情解释:PID闭环控制
笔记·stm32·单片机·嵌入式硬件·学习·算法
Herbert_hwt2 小时前
C语言文件操作完全指南:从基础读写到错误处理详解
c语言
差点GDP3 小时前
C语言常用编译命令和示例
c语言·开发语言
保护我方头发丶3 小时前
ESP功能介绍
c语言·嵌入式硬件
宵时待雨3 小时前
C语言笔记归纳21:编译与链接
linux·c语言·开发语言·笔记
国科安芯3 小时前
AS32A601型MCU芯片如何进行IAP升级?
网络·单片机·嵌入式硬件·安全·risc-v·安全性测试
啃硬骨头3 小时前
Aurix TC387 Ethernet代码解析之七_MAC的LwIP初始化4
单片机·嵌入式硬件
lingran__3 小时前
C语言内存函数详解
c语言·开发语言
superman超哥3 小时前
仓颉语言中异常捕获机制的深度剖析与工程实践
c语言·开发语言·后端·python·仓颉