Risc-V 架构下 Linux SDK 学习笔记
[toc]
前言:
- 由于 Linux 部分内容太多了,因此该文档只是一个框架文档。具体细分还会写别的文档。
- 移植 openssh && sftp 请查阅别的文档。
一、Luban SDK
Luban SDK 是通过 buildroot 编译框架进行裁剪生成的。
二、编译环境准备
-
Linux 环境
-
更换软件源
-
拉取工程文件
git clone https://gitee.com/artinchip/d211.git
-
一键安装编译环境
# 进入下载好的工程文件目录 cd d211 # 一键安装 ./tools/scripts/oneclick.sh quiet
-
-
编译 & 烧录方法
-
使用官方 demo_ 调试板子
-
添加自己的板子进行修改
make add_board
-
-
Windows 环境
-
Vscode
-
adb 调试
-
串口调试
-
三、risc-v 交叉编译环境搭建
前言
- 由于我们需要编译自己的工程文件,因此有必要搭建自己的交叉编译环境。
- 从 A7608E 移植到 D213ECV 中,A7608E 构建工具用的 makefile。
- 参考官方文档的 'LVGL' 的编译环境搭建教程 TODO://
- 在网上搜到的 Risc-V 交叉编译环境搭建教程 todo://备做参考。
pay attention: 克隆 toolchain 仓库速度特别慢! 目前暂不使用该知乎参考文档。
- 构建编译环境。
目前使用到的工具链为: riscv64-unknown-elf-
.
-
如果单纯设置用户变量, 直接写入到
bashrc
就好vim ~/.bashrc
用来指定你当前的用户变量。随后
source ~/.bashrc
应用配置。 -
如果设置为系统变量,就将下载好的编译工具( 以及子文件 )移动到
/usr
路径下。cp ./riscv64-toolchain/* /usr/ -r
检查是否成功, 输入 riscv
后按 tab
键,看看是否能打印出编译工具名字。
- 遇到的坑
-
(小) 官方文档烧录的某个镜像 demo 会报错。而换了另外的 defconfig 就没事。
-
(中)
CMakeLists.txt
文件编写中,设置源文件路径和头文件 路径需要先包含,一定要有一个顺序问题。否则编译报错会莫名其妙。 (后续不采用 CMake, 对于小工程,还是采用 Makefile 来写)
-
(微小) size_t 改为为 unsigned char 或者 uint8_t。
-
(巨坑) 编译器问题?头文件声明之后,别的文件引了头文件会导致多重定义报错。
头文件中不能声明变量。注意声明和定义的关系!!!!
-
解决 make 编译报错问题: 多重定义,但是我的 源码中那个文件中并没有定义那个变量。
方法:该编译器不支持头文件中存放定义( 声明 )。将头文件的声明全部注释,并在需要调用的地方 extern
缺点:这样各类全局变量看着就十分混乱。
优点:能简单解决问题,测试时候就这样快速是解决就好。
改进:专门拉一个头文件进来,需要修改的时候就使用 extern,需要引用的时候就 extern const
四、编译三方程序
引言
由于之前使用到 A7608E 模块写过 Linux 驱动代码。因此当时考虑的是直接构建 Makefile 文件或者其它的方式构建此工程。但,,,存在很多问题: 系统官方的库找不到 suach: mosquitto、json/json-c。
目前而言,不使用该模块上网,因此 mosquitto 库可以暂时不考虑。需要早点实现 Gpio、Uart 的驱动,再研究如何根据 Uart 和模块进行网络通信 ( 拨号、各类网络方面的业务 )。
问题点
官方并未给出编译第三方程序的文档。我这边自己写的 CMake 存在连接方面的报错 (编译源文件通过,但缺失 json-c 库的源文件,需要引入它的c,或者做成动态/静态链接库)。动态链接库: 程序运行时链接 (.dll、.so);静态链接库: 编译时链接 (.a、.lib);
在 ./d211/source/artinchip/test-gpio 中包含了 Gpio 的 CMake 示例工程,但是它无法正常地通过 CMake 编译,因为它报错缺失各类头文件,。以及找不到头文件的宏定义 (头文件选择错误)。
- 自己编写的 CMakeLists.txt 来编译工程 TODO://
- 编译官方的 gpio 例程报错解决
-
编译流程 ( 后面有时间了再使用自己的 CMakeLists.txt 运行 )
# 1. 搭建编译环境,根据文档上方的构建编译环境。 #这里采用用户变量来选择编译工具。 vim ~/.bashrc #添加行 PATH=$PATH:/root/RISC-V/linux-sdk/test/riscv64-linux-x86_64-20210512/bin # 2. 创建编译目录 #创建cmake工程目录 mkdir build apt-get install cmake cmake .. # 3. 编译随后出现下图的错误。 make
-
图示报错解决处理步骤
-
查看芯片官方 CMakeLists.txt 文件
cmake_minimum_required(VERSION 3.0 FATAL_ERROR) project(test-gpio LANGUAGES C) # Suppress cmake unused warning set(ignore ${BUILD_DOC} ${BUILD_DOCS} ${BUILD_EXAMPLE} ${BUILD_EXAMPLES} ${BUILD_SHARED_LIBS}${BUILD_TEST}${BUILD_TESTING}${BUILD_TESTS}) add_compile_options(-Wall) add_executable(test_gpio test_gpio.c) add_executable(test_gpio_output test_gpio_output.c) # Install # install directories if(NOT CMAKE_INSTALL_PREFIX) message(FATAL_ERROR "ERROR: CMAKE_INSTALL_PREFIX is not defined.") endif() include(GNUInstallDirs) message(STATUS "GNUInstallDirs=" ${GNUInstallDirs}) #后续打印 头文件路径。 if(DEFINED CMAKE_INSTALL_FULL_LIBDIR) install(TARGETS test_gpio RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") install(TARGETS test_gpio_output RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") endif() # CMAKE_INSTALL_FULL_LIBDIR
可以发现:
include(GNUInstallDirs)
存在问题,因为cmake ..
时未能打印出其路径随后考虑该路径是不是某种定义或者其它。根据其命名,认定它为编译工具所指向的路径?
-
查看根文件下的 Makefile, 以及 根Makefile 中
include package/Makefile.sdk
的 Makefile.sdk并未找到
-
CMake 后续再研究 TODO: 目前先解决工程问题,是使用 SDK 而不是开发 SDK
还是在 SDK 根路径下使用 make test-gpio 才成功解决的。
TODO:// 下午询问芯片厂家 单独编译 gpio、uart 模块的方法。/而不是编译整个 Linux 系统。
-
- 使用 Makefile 替代 CMake 来实现此工程的编译
使用 make VERBOSE=1 > log.txt 打印出所有日志并分析。
-
在 log.txt 查找
gpio.c
这部分的日志,单独提出来可以看出使用的编译器以及头文件/源文件
路径,以及编译选项和宏定义之类。/root/RISC-V/d211/output/d211_demo88_nand/host/bin/riscv64-unknown-linux-gnu-gcc --sysroot=/root/RISC-V/d211/output/d211_demo88_nand/host/riscv64-linux-gnu/sysroot -Os -g0 -DNDEBUG -Wall -o CMakeFiles/test_gpio.dir/test_gpio.c.o -c /root/RISC-V/d211/source/artinchip/test-gpio/test_gpio.c
-
根据询问厂家得知单独编译
test-gpio
的例程是在跟路径执行make test-gpio
。# 同样,将日志打印出来,来看是如何编译出来的 执行: make test-gpio VERBOSE=1 > log.txt # 查看到有用的信息和 make 编译整个工程一致。因此将此编译信息修改为 makefile 的形式。
自己手动写 Makefile ( 搞定 )
具体参考笔记参考 A7608E 的 makefile,然后再自己重新写。
- Uart 驱动
问题点
使用了 A7608E 的 uart 测试代码,刷的 d211_demo100_nand_defconfig
固件,发现只有 debug 口可以和电脑的 USB 转 TTL 通信。别的 Uart 口则无反应。
-- 官方 defconfig 的 uart demo100 无法收发数据,修改设备树解决。
-
在默认 defconfig 中
d211_demo128_nand_defconfig
能正常运行开发板上所有的 uart。而 demo100 只有debug 的串口有消息。 -
询问厂家技术支持,得到模棱两可的回复。说的修改 pinmux ,实际上根本无从下手,后来 对照了一下 demo100 和 demo128 的 .dts 设备树 后发现了不同点。将 demo100 的修改成 demo128 的引脚映射 就能正常收发 uart 数据了。
# demo128 的路径 ./source/target/d211/fountainhead_demo128_defconfig/board.dts # demo100 的路径 ./source/target/d211/fountainhead_nand100_defconfig/board.dts
-- Uart 官方
- GPIO 驱动
匠心创的方案:在 linux 内核 4.8 之后支持 GPIO 使用字符型接口
采用 /dev/gpiochipx
来实现 GPIO 控制。并采用 ioctrl( ) 函数来控制。
-- 遇到的问题: 官方 test_gpio_output 的 demo 跑不通
-
现象如下:
-
原因猜测:
-
和 uart 一样,匠芯创未专门适配此开发板,并未对 demo 进行调整。由于我使用的是开发板 (PF15) 的一个按键充当 GPIO,因此考虑是 设备树的问题 引脚的问题。
-
之前 Uart 问匠芯创时,他们说可能是 pinmux 的问题,但是并没给具体的问题解决思路... 但是我在 GPIO 这里的 './d211/target/d211/common/d211-pinctrl.dtsi' 文件下发现有 PF15 的复用功能配置
考虑与上述引脚复用有关系.
-
根据串口工具提示的
pin PF15 already requested by 18610000.codec; cannot claim for PF:95
报错 , 而且在 './d211/target/d211/common/d211.dtsi' 文件下发现此路径对应的 codec 设备树点。 -
因此去 './d211/target/d211/fountainhead_demo128/board.dts' 中查找 codec 节点并注释它。
-
重新编译 Linux 镜像并烧录,打开 PF15 官方 demo 就不报错了!!正常运行,且隔 1s 电平反转一次。
-
-- GPIO 驱动流程
TODO: 修改输出电平能力
GPIO 流程
Linux下include/uapi/linux/gpio.h 库官方API文档 https://docs.kernel.org/userspace-api/gpio/chardev.html
-
使用常规的 open( ) 函数获取到 gpio 的 fd。注意
gpiochipx
仅仅表示 gpio 组,例如 PF15 为gpiochip5
,offset 为 15。PD4为gpiochip4
,offset 为 4.// 我这里用到循环遍历所有的 gpiochip。。因此这里是数组。 int fd_gopen[gpiochips]; fd_gopen[i] = open(base_gname, O_RDWR); // base_gname 其实是 "/dev/gpiochipx" x=1,2,3...
-
配置
struct gpio_v2_line_request req;
I/O 口的请求的结构体,用来获取设备的信息// 创建结构体对象 struct gpio_v2_line_request req; // 设置你想要配置的选项 以及偏移量 (你所需要控制的IO) memset(&req, 0, sizeof(req)); req.config.flags |= GPIO_V2_LINE_FLAG_OUTPUT; // 配置 GPIO 方向 req.num_lines = 1; //请求的GPIO数量,一次可以请求多个,以简化管理。 req.offsets[0] = 15; // 设置偏移量,我们配置的 PF15,因此这里设置为15 strcpy(req.consumer, "gpio output pin"); // 用户配置的描述信息,(随便写都行)
-
使用 ioctl( ) 函数获取到设备描述符的信息。
目的: 将 req 的地址传入,用来获取对 GPIO 的
lfd
操作描述符 ( 下一个步骤会提到 )。注意: ioctl 函数属于比较底层的函数,有比他更高级的函数就尽量使用高级一点的。
// 我这里用到遍历所有的 gpiochip 因此 fd_gopen 是一个数组。。。 ret = ioctl(fd_gopen[i], GPIO_V2_GET_LINE_IOCTL, &req);
-
使用 ioctl( ) 函数针对具体的 IO 进行操作 ( 拉高 / 拉低 ),通过
req
获取到的设备信息,得到具体 GPIO 的描述符lfd
方法:通过
struct gpio_v2_line_values value
此结构体对象来进行对 IO 的操作ioctl( ) 中的命令参数为
GPIO_V2_LINE_SET_VALUES_IOCTL
int lfd[gpiochips]; // 创建控制命令的描述符 struct gpio_v2_line_values value; value.mask = 1; // 掩码 value.bits = 1; // 设置 GPIO 输出电平的高低 // 获取具体的 GPIO 描述符。这里我用的遍历,所以 lfd 是数组 lfd[i] = req.fd; // 使用控制命令 GPIO_V2_LINE_SET_VALUES_IOCTL 对 GPIO 的描述符进行写入 ret = ioctl(lfd[i], GPIO_V2_LINE_SET_VALUES_IOCTL, &value); sleep(3); // 对电平进行反转 value.bits ^= 1; ret = ioctl(lfd[i], GPIO_V2_LINE_SET_VALUES_IOCTL, &value);
- I2C 驱动
吐槽:
修改设备树引脚后Linux必须重新编译。。。uboot 或者 内核都要重新编译。费事
目前 i2c0 可以正常驱动。但是 i2c2 无法识别 ( 盲猜还是设备树的问题 )
设备树引脚选择没问题。可能是电源驱动的问题
破案了,外部上拉的问题,如果外接传感器,传感器有上拉电源也能驱动。
- USB 作为 Device 连接电脑显示串口 (虚拟多串口)
Linux 内核启用 Gadget 后接电脑,用来显示串口,并与之通信。
这一部分跟着官方文档上走,注意要屏蔽掉 ADB 调试功能才能虚拟成 USB device
usb 虚拟多串口 TODO:// 暂时不做,网上资料很少。 先搞SSH
mount -t configfs none /sys/kernel/config
cd /sys/kernel/config/usb_gadget
mkdir g1
cd g1
echo "0x6666" > idVendor
echo "0x6666" > idProduct
mkdir strings/0x409
ls strings/0x409/
echo "0123456789" > strings/0x409/serialnumber
echo "AIC Inc." > strings/0x409/manufacturer
echo "Bar Gadget" > strings/0x409/product
mkdir functions/acm.GS0
mkdir configs/c.1
ls configs/c.1
mkdir configs/c.1/strings/0x409
ls configs/c.1/strings/0x409/
echo "ACM" > configs/c.1/strings/0x409/configuration
ln -s functions/acm.GS0 configs/c.1
echo `ls /sys/class/udc` > UDC
mkdir -p /sys/kernel/config/usb_gadget/g1/functions/gser.gs0
chmod 755 /sys/kernel/config/usb_gadget/g1/functions/gser.gs0
mkdir -p /sys/kernel/config/usb_gadget/g1/functions/gser.gs1
chmod 755 /sys/kernel/config/usb_gadget/g1/functions/gser.gs1
mkdir -p /sys/kernel/config/usb_gadget/g1/functions/gser.gs2
chmod 755 /sys/kernel/config/usb_gadget/g1/functions/gser.gs2
ln -s /sys/kernel/config/usb_gadget/g1/functions/gser.gs2 /sys/kernel/config/usb_gadget/g1/configs/c.1/f1
ln -s /sys/kernel/config/usb_gadget/g1/functions/gser.gs0 /sys/kernel/config/usb_gadget/g1/configs/c.1/f2
ln -s /sys/kernel/config/usb_gadget/g1/functions/gser.gs1 /sys/kernel/config/usb_gadget/g1/configs/c.1/f3
chatGPT 给出的提示
执行后的现象:windows下依旧只会多出一个 usb 串行设备,而开发板Linux 下会多出几个 /dev/ttyGS0,1,2
# 创建一个 USB gadget 并配置 Vendor ID 和 Product ID
mount -t configfs none /sys/kernel/config
cd /sys/kernel/config/usb_gadget
mkdir g1
cd g1
echo "0x6666" > idVendor
echo "0x6666" > idProduct
# 配置 USB 字符串描述符
mkdir strings/0x409
echo "0123456789" > strings/0x409/serialnumber
echo "AIC Inc." > strings/0x409/manufacturer
mkdir strings/0x410
echo "0123456787" > strings/0x410/serialnumber
echo "dearl Inc." > strings/0x410/manufacturer
echo "Bar1 Gadget" > strings/0x410/product
mkdir strings/0x411
echo "0123456788" > strings/0x411/serialnumber
echo "dearl2 Inc." > strings/0x411/manufacturer
echo "Bar2 Gadget" > strings/0x411/product
# 创建三个 ACM 功能并为每个功能创建一个配置
mkdir -p functions/acm.GS0
mkdir -p functions/acm.GS1
mkdir -p functions/acm.GS2
mkdir -p configs/c.1
mkdir -p configs/c.2
mkdir -p configs/c.3
# 配置每个配置的字符串描述符
mkdir -p configs/c.1/strings/0x409
mkdir -p configs/c.2/strings/0x410
mkdir -p configs/c.3/strings/0x411
echo "ACM 1" > configs/c.1/strings/0x409/configuration
echo "ACM 2" > configs/c.2/strings/0x410/configuration
echo "ACM 3" > configs/c.3/strings/0x411/configuration
# 将每个 ACM 功能链接到相应的配置
ln -s ./functions/acm.GS0 configs/c.1
ln -s ./functions/acm.GS1 configs/c.2
ln -s ./functions/acm.GS2 configs/c.3
# 将 USB 设备控制器绑定到 USB gadget
echo `ls /sys/class/udc` > UDC
匠芯创 D21X
-
RJ45 网络接口,I2C、GPIO 等外设已验证,开发板插入 USB 调试口可以修改设备名。
-
开发板插入 SD 卡后经过几个小时的 6500 个文件长时间读写测试,SD 卡会生成预期的文件个数和内容。
-
D213 芯片 USBH0 可以虚拟成单个 USB 设备端,与PC主机端通信。
后续将一个物理 USB 口虚拟为多个 USB 设备端,并尝试修改虚拟口的设备名,移植 SSH / SFTP 功能到开发板。
- 遇到的坑
-
引入头文件报错
-
问题描述:
我 main.c 中引入了 config.h 头文件,而且 Makefile 的编译 main.o 的路径理论上是包含了 config.h 的路径的,但是编译依旧报错。
-
临时解决方法。
路径问题~!!!薛定谔的路径 makefile 中宏定义变量使用 makefile 所在的文件夹的相对路径,
-
问题原因:暂未去查找。时间紧,任务重。
-
五、RNDIS 移植 && mosquitto 移植 && json库移植
前言: D213ECV 的目的是实现 RNDIS 功能,它与上网模块连接,实现拨号功能。
TODO: 目前只是验证了它可行,后续还要屏蔽它的 usb 驱动,直接进来就采用 RNDIS 驱动。
- 添加板子 make add_board && 启用 RNDIS 模块
-
在 SDK 根目录下使用
make add_board
选择默认的demo128_nand_defconfig
TIP: 经过后期测试,发现 demo128 才能驱动除 debug 以外的 Uart 设备。
猜测: 可能是设备树之类,亦或者 pinmux 引脚复用未配置。
-
启用 RNDIS 模块
参考文档->4G 模块 LINUX 集成用户手册 ( 域格 )
内核配置部分
-
使用 make km ( make kernel-menuconfig ) 进入图形配置界面
-
进入如下路径并开启内核功能
Device Drivers - [*]Network device support -- <*>USB Network Adapters ---
Multi-purpose USB Networking Framework Host for RNDIS and ActiveSync devices #这里用 M 或者 * 都行。如果用*就不生成 rndis_host.ko 内核模块,而是直接编译进内核 Ask: 使用 M 之后编译好的内核模块也能执行,而 chatGPT 提示需要加载内核才能运行。。。?
-
-
根据上方操作插入 usb 已经可以看到新添加的 usb 设备了,
将 EMC 网卡自动获取 DHCP 的 ip 之类的信息 (如果没有则重新插拔 usb)
udhcpc -i eth0
获取DHCP 之后 ipaddr 查看当前 EMC 网卡信息
测试
ping www.baidu.com
但,教程中提示如果设备不支持的话需要修改内核设备源码 ( 如果需要的话 )
使用
lsusb
查看 VID PID- usb 内核在
linux-5.10/drivers/usb/serial/option.c
添加设备驱动,添加好驱动之后就可以执行modprobe usbserial vendor=1782 product=4e00
来加载设备了。(不确定这一步骤的作用)
但是: 存在根据
域格
的文档,并未在/dev/ttyU*
中找到设备。也许这个模块是合宙的,存在差异。
- usb 内核在
- 移植 mosquitto 库
为什么要移植该库?
因为之前的 A7608E 的代码中使用到了该库,但是 D21x 这个板子的工程中并未包含此库,考虑把它交叉编译成 动态/静态 链接库。
移植流程:Eclipse 的 mosquitto 官网: https://mosquitto.org/
-
官网下载库文件并上传到 linux 交叉编译环境中 下载地址: https://mosquitto.org/files/source/
curl -l https://mosquitto.org/files/source/mosquitto-2.0.18.tar.gz -o mosquitto.sdk.tar.gz
-
复制并解压
tar -xvf mosquitto.sdk.tar.gz
tar -xvf your_tar_file.tar -C /your/target/path #带路径的解压方式
-
在 SDK 根路径下修改 config.mk
-
在文件开始的地方增加 如下交叉编译工具链和生成路径
CC=riscv64-unknown-linux-gnu-gcc CXX=riscv64-unknown-linux-gnu-g++ CPP=riscv64-unknown-linux-gnu-g++ AR=riscv64-unknown-linux-gnu-ar LD=riscv64-unknown-linux-gnu-ld DESTDIR=install_out #设置目标生成路径,但是好像没啥用。。。
-
添加 strip(剥夺、精简、条) 工具 ( 生产部署环境中去除目标文件的符号或者其它调试信息,减少文件大小 )
STRIP?=riscv64-unknown-linux-gnu-strip
-
修改 prefix 定义
prefix=out
-
去除不需要的部分 SSL 之类的
WITH_TLS:=no WITH_TLS_PSK:=no WITH_SRV:=no WITH_UUID:=no
-
编译 make && make install 并查看生成的目标文件
并在
./lib/install_out/lib/
查看到libmosquitto.so
的动态链接库文件。./lib/install_out/include/
查看到mosquitto.h
的头文件。 -
将 libmosquitto.so 移动至开发板,并运行测试程序。
-
-
编译通过后 adb push 推送到 Linux 系统下之后 报错缺少动态链接库。
将动态链接库放入到 Linux 下,需要设置环境变量来让程序找到它。
export LD_LIBRARY_PATH=/path/to/libmosquitto:$LD_LIBRARY_PATH
Ask: 这个路径可以不必是它的真实路径。。它依旧找得到。。。奇了怪了。但是不写又报错。
- 移植 cJSON 库
-
拉取库并在 json-c 同级目录下 创建
toolChain_json.cmake
文件## toolChain_json.cmake set(CMAKE_SYSTEM_NAME Linux) SET(TOOLCHAIN_DIR "/root/RISC-V/linux-sdk/env_toolchain/riscv64-linux-x86_64-20210512") set(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/bin/riscv64-unknown-linux-gnu-gcc) set(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}/bin/riscv64-unknown-linux-gnu-g++) link_libraries(m) set(CMAKE_FIND_ROOT_PATH "/root/RISC-V/linux-sdk/port_lib/json-c") set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
-
进入 json-c 中执行
cmake -DCMAKE_INSTALL_PREFIX=/home/json-c/install -DCMAKE_TOOLCHAIN_FILE=../toolChain_json.cmake .
-
编译并查看生成的目标文件
/home/json-c/install
make make install
-
如果需要
export LD_LIBRARY_PATH=/path/to/libjson-c:$LD_LIBRARY_PATH
- 多线程写入文件,使用互斥锁
部分写入文件的笔记,请看我文档的 A7608E 部分
测试写入文件这部分,我们使用的互斥锁,来保护单次写入文件。
- 遇到的坑
-- 1.使用 demo128_defconfig 的默认配置编译的镜像无法使用 rndis (不是坑,是我的问题。下方忽略。)
短期解决办法 ( 笨办法 )
-
先在内核中选中 rndis,随后在编译路径中找到内核编译的模块
# 编译的时候重定向输出日志,查找到该模块的位置。 make VERBOSE=1 > log.txt
-
从 demo100_defconfig 中编译出内核模块。在编译环境中把此模块提出来。
# 在路径中找到 rndis_host.ko /root/RISC-V/linux-sdk/d211/output/d211_demo100_nand/build/linux-5.10/drivers/net/usb
-
使用
adb push
或者其它方法将其推到开发板中。# 将 rndis_host.ko 移动至内核中。 /lib/modules/5.10.44/kernel/drivers/net/usb/rndis_host.ko
-
随后就能正常使用 rndis 了
本质原因:
尴尬: 我内核配置文件中中选择的是 * 表示直接编译至内核中,所以没有 rndis_host.ko,而且为什么之前没连上网?因为 usb 没插拔导致不识别。
六、将程序制作成 img 的 Linux 镜像。(硬件加密?)
// TODO.
七、其它
-
设备树
-
移植 openssh & sftp 请查阅移植 openssh 文档部分。
总结
思路方面的问题: 要找准目标,明白目前项目的需求,就 d21x 而言目前是实现芯片和 模块进行通信,应当把精力花在业务部分上面。而不是折腾环境。目的是使用 SDK,而不是开发 SDK。这部分也是我的缺点,办事情之前有必要理清思路,大局观的方向先找准,细枝末节是后话。考虑每次做项目时做好思维导图把握方向。
方案与工作内容
- 方向: 先调通 gpio 和 uart 外设。后续 uart 和 合宙模块通信。该芯片不实现上网的功能。但是 MQTT 解析类或者各种业务代码 拨号之类的需要在该芯片上完成。
- 类比: 将合宙模块理解为 usb 接电脑,设备管理器会多出一个网卡,且使用该网卡上网。
- 困难点: uart 如何与模块进行网络信息的交换。可能需要移植网卡驱动?
- 备选: 最后才考虑使用 AT 指令和模块通信,因为 AT 指令字段解析很复杂,但凡涉及字符串的拼接,需要判断的层面就很多。。。 除非做一个中间层,AT在芯片内部消化掉,自动适配不同的上网模块( 工程量巨大 )。
TODO:
五一回来:测试 SDK 稳定性。
-
测试 SD 卡的读写。
多线程读写导致的文件打开冲突,应该使用互斥量机制来避免
-
测试 RNDIS 长时间收发问题。
1-13 15:16 1-14 5:43 9+5 = 14.30 6.30 + 14.30 == 9:00结束 # 使用下方命令行 ls -l | grep "^-" | wc -l
todo: 修改 usb 口,当插入电脑时,识别到 usb 口的名称改为 fountainhead 这种。
// 完成,搜全局设备名,改为 fountainhead。然后插入电脑,如果还是显示之前的,就卸载设备再拔插
// 移植参考教程
https://zhuanlan.zhihu.com/p/387939051
https://www.openssl.org/source/
// 编译openssl 时的配置选项
./Configure linux64-riscv64 no-asm shared no-async --prefix=/root/RISC-V/linux-sdk/port_lib/ssh/openssl-3.2.1/install_dir
// 执行下方的配置选项就可以生成 lib库了
./Configure linux64-riscv64 --prefix=/root/RISC-V/linux-sdk/port_lib/ssh/openssl-3.2.1/install_dir
./Configure linux-generic32 no-asm shared no-async --prefix=/root/RISC-V/linux-sdk/port_lib/ssh/openssl-3.2.1/install_dir
vim Makefile
https://www.openssh.com/portable.html
https://mirrors.aliyun.com/pub/OpenBSD/OpenSSH/portable/
# 编译openssh
/root/RISC-V/linux-sdk/port_lib/ssh/zlib-1.3
./configure --host=riscv64-linux --with-libs --with-zlib=/root/RISC-V/linux-sdk/port_lib/ssh/zlib-1.3/install_dir --with-ssl-dir=/root/RISC-V/linux-sdk/port_lib/ssh/openssl-3.2.1/install_dir --disable-etc-default-login
# 不禁用默认登录
./configure --host=riscv64-linux --with-libs --with-zlib=/root/RISC-V/linux-sdk/port_lib/ssh/zlib-1.3/install_dir --with-ssl-dir=/root/RISC-V/linux-sdk/port_lib/ssh/openssl-3.2.1/install_dir
./configure --host=riscv64-linux --with-libs --with-zlib=/root/RISC-V/linux-sdk/port_lib/ssh/zlib-1.3/install_dir --with-ssl-dir=/root/RISC-V/linux-sdk/port_lib/ssh/openssl-3.2.1/install_dir
--without-openssl-header-check
# 临时存放
.c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -I /root/RISC-V/linux-sdk/port_lib/ssh/openssl-3.2.1/include -c $< -o $@
#
ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS)
$(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -L /root/RISC-V/linux-sdk/port_lib/ssh/openssl-3.2.1/crypto $(LIBS) $(GSSLIBS) $(CHANNELLIBS)
./configure --host=arm-linux-gnueabihf --with-libs --with-zlib=/root/RISC-V/linux-sdk/port_lib/ssh/zlib-1.3/install_dir --with-ssl-dir=/root/RISC-V/linux-sdk/port_lib/ssh/openssl-3.2.1/install_dir --disable-etcdefault-login CC=riscv64-unknown-linux-gnu-gcc AR=riscv64-unknown-linux-gnu-ar
#编译 zlib-1.2.8 流程
cd /home/ssh-code/zlib-1.2.8
mkdir install_dir #创建安装目录
./configure --prefix=/root/RISC-V/linux-sdk/port_lib/ssh-test/zlib-1.2.8/install_dir #执行之后会生成Makefile
vim Makefile #修改Makfile 将其中gcc、g++都修改为交叉编译器的名称。
## 原来代码
# 19: CC=gcc
# ...
# 30: LDSHARED=gcc -shared -Wl,-soname,libz.so.1,--version-script,zlib.map
# 31: CPP=gcc -E
## 修改如下
# 19: CC=arm-linux-gcc
# ...
# 30: LDSHARED=arm-linux-gcc -shared -Wl,-soname,libz.so.1,--version-script,zlib.map
# 31: CPP=arm-linux-gcc -E
make
make install
mount -t configfs none /sys/kernel/config
cd /sys/kernel/config/usb_gadget
mkdir g0
cd g0
echo "0x1d6b" > idVendor
echo "0x0104" > idProduct
mkdir strings/0x409
ls strings/0x409/
echo "0123456789" > strings/0x409/serialnumber
echo "AIC Inc." > strings/0x409/manufacturer
echo "Bar Gadget" > strings/0x409/product
mkdir functions/acm.GS0
mkdir configs/c.1
ls configs/c.1
mkdir configs/c.1/strings/0x409
ls configs/c.1/strings/0x409/
echo "ACM" > configs/c.1/strings/0x409/configuration
ln -s functions/acm.GS0 configs/c.1
echo `ls /sys/class/udc` > UDC