Milk-V Duo 开发环境搭建
一、准备
Milk-V Duo开发板
1.简介 :
Milk-V Duo 是一个基于 CV1800B 芯片的超紧凑嵌入式开发平台。它可以运行 Linux 和 RTOS ,为专业人士、工业 ODM 、 AIoT 爱好者、 DIY 爱好者和创作者提供了一个可靠、低成本和高性能的平台。
技术规格 :
CVITEK CV1800B (C906@1Ghz + C906@700MHz)
双 RV64 核心,最高 1GHz
64MB 内存
通过可选的附加板提供 10/100Mbps 以太网
技术支持同时运行 Linux 和 RTOS
2.TypeC数据线
3.大于1GB的MicroSD卡
4.SD卡读卡器
二、硬件连接
引脚分布图
硬件连接图
三、系统镜像和烧写工具
- 系统镜像
供应商提供:
在github链接下载milkv-duo-20230616-2232.img.zip文件
- 烧写工具
Flash工具:balenaEtcher
按照以下步骤安装即可:
四、 USBnet 网络驱动设置
烧写到Milk-V Duo开发板的操作系统默认开启了RNDIS,因此在Windows系统上需要设置USB的RNDIS驱动,步骤如下:
此时可通过MobaXterm远程连接Duo的控制台,并通过 cat /proc/version 查看编译器版本
五、交叉编译工具链
通过阅读官方SDK的脚本文件代码可知,交叉编译器存放在host-tools.tar.gz文件中。将其下载并放在开发环境中(WSL-Ubuntu22.04)
该压缩包提供了三个版本的编译器,官方提供镜像所需的编译器为riscv64-unknown-linux-musl-gcc
下载duo-sdk.tar.gz并解压,该压缩包提供了编译所必需的一些库
六、应用示例
点灯程序:每间隔一定时间更改** LED 灯的状态
源码
C
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h> //define O_WRONLY and O_RDONLY
// LED 引脚
#define SYSFS_GPIO_EXPORT "/sys/class/gpio/export"
#define SYSFS_GPIO_UNEXPORT "/sys/class/gpio/unexport"
#define SYSFS_GPIO_RST_PIN_VAL "440"
#define SYSFS_GPIO_RST_DIR "/sys/class/gpio/gpio440/direction"
#define SYSFS_GPIO_RST_DIR_VAL "OUT"
#define SYSFS_GPIO_RST_VAL "/sys/class/gpio/gpio440/value"
#define SYSFS_GPIO_RST_VAL_H "1"
#define SYSFS_GPIO_RST_VAL_L "0"
int main()
{
int fd;
int count = 30;
// 打开端口/sys/class/gpio# echo 440 > export
fd = open(SYSFS_GPIO_EXPORT, O_WRONLY);
if (fd == -1)
{
printf("ERR: export open error.\n");
return EXIT_FAILURE;
}
write(fd, SYSFS_GPIO_RST_PIN_VAL, sizeof(SYSFS_GPIO_RST_PIN_VAL));
close(fd);
// 设置端口方向/sys/class/gpio/gpio440# echo out > direction
fd = open(SYSFS_GPIO_RST_DIR, O_WRONLY);
if (fd == -1)
{
printf("ERR: direction open error.\n");
return EXIT_FAILURE;
}
write(fd, SYSFS_GPIO_RST_DIR_VAL, sizeof(SYSFS_GPIO_RST_DIR_VAL));
close(fd);
// 输出复位信号: 拉高>100ns
fd = open(SYSFS_GPIO_RST_VAL, O_RDWR);
if (fd == -1)
{
printf("ERR: gpio open error.\n");
return EXIT_FAILURE;
}
while (count)
{
count--;
printf("milk:%d\r\n",count);
write(fd, SYSFS_GPIO_RST_VAL_H, sizeof(SYSFS_GPIO_RST_VAL_H));
usleep(1000000);
write(fd, SYSFS_GPIO_RST_VAL_L, sizeof(SYSFS_GPIO_RST_VAL_L));
usleep(1000000);
}
close(fd);
// 打开端口/sys/class/gpio# echo 440 > unexport
fd = open(SYSFS_GPIO_UNEXPORT, O_WRONLY);
if (fd == -1)
{
printf("ERR: unexport open error.\n");
return EXIT_FAILURE;
}
write(fd, SYSFS_GPIO_RST_PIN_VAL, sizeof(SYSFS_GPIO_RST_PIN_VAL));
close(fd);
return 0;
}
makefile编写
根据官方提供例程的makefile并结合自己的开发环境完成makefile
Makefile
TARGET=led
export SYSROOT=~/duo-sdk/rootfs
export TOOLCHAIN_PREFIX = ~/host-tools/gcc/riscv64-linux-musl-x86_64/bin/riscv64-unknown-linux-musl-
export CFLAGS="-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64"
export LDFLAGS="-mcpu=c906fdv -march=rv64imafdcv0p7xthead -mcmodel=medany -mabi=lp64d"
CC = ~/host-tools/gcc/riscv64-linux-musl-x86_64/bin/riscv64-unknown-linux-musl-gcc
CFLAGS += -I$(SYSROOT)/usr/include
LDFLAGS += -L$(SYSROOT)/lib
LDFLAGS += -L$(SYSROOT)/usr/lib
SOURCE = $(wildcard *.c)
OBJS = $(patsubst %.c,%.o,$(SOURCE))
$(TARGET): $(OBJS)
$(CC) -o $@ $(OBJS) $(LDFLAGS)
%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
.PHONY: clean
clean:
@rm *.o -rf
@rm $(OBJS) -rf
@rm $(TARGET)
编译
运行
七、 coremark 测试
基于WSL2(Ubuntu22.04)交叉编译环境,下载coremark源码GitHub - riscv-boom/riscv-coremark: Setup scripts and files needed to compile CoreMark on RISC-V
用一系列git指令将源码更新到最新
Shell
cd ./riscv-coremark
git submodule update --init
cd coremark/
git checkout main
git pull origin main
源码包中的build-coremark.sh脚本并未进行编译,因此需自行编译
进入coremark目录使用指令~/riscv-coremark/coremark$ ~/host-tools/gcc/riscv64-elf-x86_64/bin/riscv64-unknown-elf-gcc -O2 -I …/riscv64 -I . -DITERATIONS=0 core_list_join.c core_main.c core_matrix.c core_state.c core_util.c …/riscv64/core_portme.c -o ./coremark.riscv进行编译
使用scp命令将可执行文件传送给Duo:scp coremark.riscv root@192.168.42.1:~
./coremark.riscv执行该文件