OrangePi KunPengPro
| 开发板开箱测评之学习与使用
时间:2024年5月23日20:51:12
文章目录

概述
概述
非常荣幸能够参与优快云举办的
OrangePi KunPengPro
开发板开箱测评与学习使用活动。作为一位对嵌入式开发充满热情的探索者,我深感这次机会难得。OrangePi KunPengPro
以其精致的外观和强大的功能,给我留下了深刻的印象。开箱初体验
开箱后,我发现了主板(配置有8GB内存)、一张预装系统的32GB内存卡、散热风扇以及电源。整个开箱过程简单顺畅,几乎没有任何难度,真正实现了“开箱即用”。连接电源后,设备迅速启动,让我对后续的学习与使用充满了期待。
丰富的接口与强大的扩展性
OrangePi KunPengPro汇聚了MIPI DSI、MIPI CSI、USB3.0、Type-C3.0、HDMI2.0、千兆以太网以及支持SATA/NVMe SSD 2280的M.2插槽等多种流行接口,为外部设备的控制和扩展提供了极大的便利。特别是板载的M.2接口,支持接入SATA/NVMe SSD 2280硬盘,极大地增加了数据存储空间,满足了快速读写和大容量存储的需求。
多通道输出与高清显示
该开发板支持双HDMI视频输出,支持双4K高清显示,同时还支持一个MIPI DSI视频输出和两个MIPI接口摄像头输入。这样的设计使得OrangePi KunPengPro在多媒体处理和高清显示方面表现出色,为开发者提供了更多的应用场景和可能性。
类PC桌面环境,简化上手难度
OrangePi KunPengPro预装了图形化桌面环境(gnome)、浏览器(firefox)、文本编辑器(gedit)以及中文输入法等常用软件,极大地降低了用户的上手难度。无论是对于初学者还是资深开发者来说,都能够迅速适应并投入到开发工作中去。
操作系统与硬件支持
OrangePi KunPengPro采用openEuler操作系统,该系统高效、稳定、安全,支持多种硬件架构和虚拟化技术,可广泛应用于企业级边缘计算场景等。同时,该开发板还配备了4核64位处理器+AI处理器,集成图形处理器,支持8TOPS AI算力,拥有8GB/16GB LPDDR4X内存,为AI算法原型验证、推理应用开发等提供了强大的算力支持。
学习与实践
在测评过程中,我首先通过MicroUSB连接电脑,并通过串口进入系统终端进行调试和交互。这一过程简单快捷,无需额外的USB转串口工具。随后,我学习了如何通过SSH登录系统、安装交叉编译工具链、传输文件到系统以及编译运行自己的第一个程序(hello)。最后,我还利用IIC接口点亮了一个IIC OLED屏幕,详细演示了在Linux平台下进行IIC调试和开发的过程。
问题与展望
在使用过程中,我也遇到了一些问题。例如,使用256GB的SD卡烧录系统时出现了启动卡住的情况;MicroUSB调试串口能够连上电脑但无法输出调试信息。这些问题虽然暂时未能解决,但并未影响我对
OrangePi KunPengPro
的整体评价。我相信在后续的学习和探索中,我能够找到解决这些问题的方法。总结
OrangePi KunPengPro
是一款功能强大、易于上手的嵌入式开发板。它拥有丰富的接口和强大的扩展性,支持多通道输出和高清显示,预装了类PC桌面环境和多种常用软件,为开发者提供了极大的便利。通过本次开箱测评与学习使用活动,我不仅掌握了基本的开发技能,还对嵌入式系统有了更深入的了解。我相信在未来的日子里,OrangePi KunPengPro
将成为我开发道路上不可或缺的得力助手。
附件
希望这份指南能够为您的OrangePi KunPengPro开发之旅提供有价值的参考和帮助!
1.参考
1.OrangePi Kunpeng Pro Orange Pi官网-香橙派(Orange Pi)开发板,开源硬件,开源软件,开源芯片,电脑键盘
3.鲲鹏社区-官网丨凝心聚力 共创行业新价值 (hikunpeng.com)
2.资料、工具
1.官方资料和工具:
root@ThinkPad-FLY:/mnt/d/Download/OrangePiKunpengPro# tree . ├── 外壳及散热器安装资料 │ ├── OPi Kunpeng pro外壳装配说明.mp4 │ ├── OPi kunpeng Pro开发板+散热器组件装配说明-20240429.pptx │ └── Opi Kunpeng pro开发板+散热器.mp4 ├── 官方工具 │ ├── FileZilla-SFTP软件 │ │ └── FileZilla_3.62.2_win64_sponsored2-setup.exe │ ├── Linux镜像烧录工具-balenEther │ │ ├── Linux_X64版本 │ │ │ ├── balena-etcher_1.18.8_amd64.deb │ │ │ └── balenaEtcher-1.18.4-x64.AppImage │ │ ├── MACOS_X64版本 │ │ │ └── balenaEtcher-1.18.4.dmg │ │ ├── Windows_X64版本 │ │ │ ├── balenaEtcher-Portable-1.18.4.exe │ │ │ └── balenaEtcher-Setup-1.18.4.exe │ │ └── 开发板安装的arm64版本 │ │ ├── balena-etcher-electron_1.7.9+5945ab1f_arm64.deb │ │ └── balenaEtcher-1.7.9+5945ab1f-arm64.AppImage │ ├── MobaXterm │ │ └── MobaXterm_Portable_v22.2.zip │ ├── Windows-格式化软件-SDCardFormatter │ │ └── SDCardFormatterv5_WinEN.zip │ ├── 交叉编译工具链 │ │ └── toolchain.tar.gz │ └── 查看YUV图片的软件 │ └── SuperImage.rar └── 用户手册 └── OrangePi_KunPeng_Pro_用户手册_v0.1.pdf
3.使用
3-1.通过串口登录系统
首先需要下载驱动(驱动下载主页见上面的连接),然后安装驱动;
通过
Micro USB
连接电脑和开发板,查看com
口,然后通过串口工具登录系统;为什么一开始选择串口登录?因为通过串口调试是最简单的方式。虽然有网口,但一开始也不知道
ip
,也没法登录。手边有显示器,可以通过
HDMI
连接,但是没有USB
键盘,因此也没法好好交互。所以先通过串口登录系统交互。
3-2.通过SSH登录系统
上面通过串口进入系统后,通过连接网线(同一网络下),查看设备
IP
,即可通过SSH
登录系统;也可以参考文档:OrangePi_KunPeng_Pro_用户手册_v0.1.pdf,使用
WIFI
连接网络,就可以减少网线或者串口线的连接来登录终端;
3-3.安装交叉编译工具链
# 新建目录
sudo mkdir /opt/OrangePiKunpengPro
# 解压文件
sudo tar -zxvf toolchain.tar.gz -C /opt/OrangePiKunpengPro/
# 设置环境变量
sudo vim /etc/profile
# 使环境变量生效
source /etc/profile
# 查看编译器版本
aarch64-target-linux-gnu-gcc --version
# 写源码
vim hello.c
# 编译源码
aarch64-target-linux-gnu-gcc hello.c -o hello
3-4.复制文件到设备
首先电脑上需要安装
WinSCP
软件。WinSCP :: Official Site :: Free SFTP and FTP client for Windows将编译的之前交叉编译的
hello
可执行程序复制到设备上,修改可执行权限,就可以在设备上执行自己编译的程序。
3-5.第一个程序hello
代码
/*******************************************************************
* > File Name: hello.c
* > Author: fly
* > Mail:
* > Create Time: Fri 17 May 2024 02:14:11 PM CST
******************************************************************/
#include <stdio.h>
int main(int argc, char* argv[])
{
printf("hello\n\n");
printf("__FILE__: %s\n", __FILE__);
printf("__FUNC__: %s\n", __func__);
printf("__LINE__: %d\n", __LINE__);
return 0;
}
makefile
.PHONY:all
SRC=hello.c
BIN=hello
#CC=gcc
CC=aarch64-target-linux-gnu-gcc
all:
@echo "预处理"
$(CC) -E hello.c -o hello.i
@echo "编译"
$(CC) -S hello.i -o hello.s
@echo "汇编"
$(CC) -c hello.s -o hello.o
@echo "链接"
$(CC) hello.o -o hello
clean:
$(RM) *.i *.s *.o hello
编译
编译是在一个
Ubuntu docker
中进行的,需要提前安装、配置好交叉编译工具链(命令行操作如下);
[fly@752fac4b02e9 02-hello]$ ls
hello.c Makefile
[fly@752fac4b02e9 02-hello]$ make
预处理
aarch64-target-linux-gnu-gcc -E hello.c -o hello.i
编译
aarch64-target-linux-gnu-gcc -S hello.i -o hello.s
汇编
aarch64-target-linux-gnu-gcc -c hello.s -o hello.o
链接
aarch64-target-linux-gnu-gcc hello.o -o hello
[fly@752fac4b02e9 02-hello]$ ls
hello hello.c hello.i hello.o hello.s Makefile
[fly@752fac4b02e9 02-hello]$ file hello
hello: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, not stripped
运行
通过
WinSCP
将编译后的程序上传到板子上,检测板子上程序的可执行权限,然后运行(如下命令行操作)。
[root@openEuler ~]# ls -l
总用量 24
drwxr-x--- 2 root root 4096 1月 1 1970 hdc_ppc
-rw------- 1 root root 12728 5月 26 01:15 hello
drwxr-xr-x 2 root root 4096 5月 6 04:34 tmp
[root@openEuler ~]# chmod +x hello
[root@openEuler ~]# ./hello
hello
__FILE__: hello.c
__FUNC__: main
__LINE__: 16
3-6.I2C
的测试和使用
资料
1.linux下i2c调试神器i2c-tools安装及使用_i2c调试助手-优快云博客
2.0.91inch IIC OLED Module SSD1306 SKU:MC091GX - LCD wiki
在嵌入式开发中,有时候需要确认硬件是否正常连接,设备是否正常工作,设备的地址是多少等等,这里我们就需要使用一个用于测试
I2C
总线的工具——i2c-tools
。
i2c-tools
工具是一个专门调试i2c
的,开源,可获取挂载的设备及设备地址,还可以读写I2C
设备寄存器。命令介绍: i2cdetect:检测i2c芯片 i2cdump:查看寄存器值 i2cget:获取单个寄存器值(8位寄存器) i2cset:设置单个寄存器值(8位寄存器) 参数介绍: -y:禁用交互模式。 -f:强制访问设备。 -r:写入后立即读回该值。
演示
3-7.i2c点亮OLED
屏实验
硬件连线示意图
检测i2c
从设备
通过输入如下命令,可知从设备地址为0x3C;
# 未连接I2C从设备前检测
[root@openEuler /]# i2cdetect -y -r 7
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
# 连接I2C从设备后检测
[root@openEuler /]# i2cdetect -y -r 7
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- 3c -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
# 查看i2c设备所有寄存器的值
[root@openEuler /]# i2cdump -y -f 7 0x3c
No size specified (using byte-data access)
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
10: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
20: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
30: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
40: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
50: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
60: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
70: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
80: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
90: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
a0: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
b0: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
c0: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
d0: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
e0: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
f0: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
数据手册
0.91寸屏驱动i2c数据手册:
8.1.5 MCU I2C接口
I2C
通信接口包括从机地址位SA0
、I2C
总线数据信号SDA
(输出为SDAOUT/D2
,输入为SDAIN/D1
)和I2C
总线时钟信号SCL
(D0
)。数据信号和时钟信号都必须连接到上拉电阻。RES#
用于设备的初始化。a) 从机地址位(
SA0
)SSD1306在通过I2C总线发送或接收任何信息之前,必须先识别从机地址。设备将响应由从机地址位(“
SA0
”位)和读写选择位(“R/W#
”位)跟随的从机地址,其字节格式如下:b7 b6 b5 b4 b3 b2 b1 b0
0 1 1 1 1 0 SA0 R/W#“
SA0
”位为从机地址提供扩展位。可以选择“0111100
”或“0111101
”作为SSD1306的从机地址。D/C#
引脚作为SA0
用于从机地址选择。“
R/W#
”位用于确定I2C总线接口的操作模式。R/W#=1
,处于读取模式;R/W#=0
,处于写入模式。b) I2C总线数据信号(
SDA
)
SDA
作为发射器和接收器之间的通信通道。数据和确认都是通过SDA
发送的。应该注意的是,“
SDA
”引脚上的ITO
轨道电阻和上拉电阻形成了一个电压分压器。因此,确认信号在“SDA
”上可能无法达到有效的逻辑0电平。“
SDAIN
”和“SDAOUT
”连接在一起作为SDA
使用。“SDAIN
”引脚必须连接以作为SDA
使用。“SDAOUT
”引脚可以断开。当“SDAOUT
”引脚断开时,I2C
总线中的确认信号将被忽略。c) I2C总线时钟信号(
SCL
)
I2C
总线中的信息传输遵循时钟信号SCL
。每个数据位的传输都在SCL
的一个时钟周期内发生。8.1.5.1
I2C
总线写数据
I2C
总线接口允许向设备写入数据和命令。请参考图8-7,了解I2C
总线写模式按照时间顺序的流程。
8.1.5.2
I2C
总线写数据的流程
主设备通过起始条件启动数据通信。起始条件的定义如图8-8所示(详见数据手册)。起始条件是通过在SCL保持高电平时,将
SDA
从高电平拉至低电平来建立的。紧随起始条件之后的是从设备地址,用于识别。对于SSD1306,通过将SA0设置为低电平或高电平(D/C引脚作为SA0使用),从设备地址是“
b0111100
”或“b0111101
”。通过将R/W#位设置为逻辑“0”来建立写模式。
在接收到一个字节的数据(包括从设备地址和
R/W#
位)后,将生成一个应答信号。请参考图8-9了解应答信号的图形表示。应答位定义为在应答相关时钟脉冲的高电平期间,SDA
线被拉低。在发送从设备地址后,可以通过
SDA
发送控制字节或数据字节。控制字节主要由Co
和D/C#
位组成,后面跟着六个“0”。
a. 如果Co
位设置为逻辑“0”,则后续传输的信息将仅包含数据字节。
b.D/C#
位确定下一个数据字节是作为命令还是数据。如果D/C#
位设置为逻辑“0”,则定义下一个数据字节为命令。如果D/C#
位设置为逻辑“1”,则定义下一个数据字节为要存储在GDDRAM
中的数据。在每次数据写入后,GDDRAM
列地址指针将自动增加1。在接收到每个控制字节或数据字节后,将生成应答位。
当应用停止条件时,写模式将结束。停止条件也在( [图8-8中定义(详见数据手册)SSD1306-Revision 1.5.pdf ](http://www.lcdwiki.com/res/MC091GX/SSD1306-Revision 1.5.pdf) )。停止条件是通过在
SCL
保持高电平时,将“SDA输入
”从低电平拉至高电平来建立的。请注意,数据位的传输有一些限制。
- 在每个
SCL
脉冲期间传输的数据位必须在时钟脉冲的“HIGH
”周期内保持稳定状态。请参考图8-10以获得图形表示。除了在开始或停止条件下,数据线只能在SCL
为LOW
时切换。- 数据线(SDA)和时钟线(SCL)都应该通过外部电阻上拉。
8.2. 命令解码器
此模块确定输入数据是被解释为数据还是命令。数据的解释基于
D/C#
引脚的输入。如果
D/C#
引脚为高电平,D[7:0]
将被解释为写入图形显示数据RAM(GDDRAM)
的显示数据。如果
D/C#
引脚为低电平,D[7:0]
的输入将被解释为命令。然后,数据输入将被解码并写入相应的命令寄存器。
Demo实例代码
1.kernel.org/doc/Documentation/i2c/dev-interface
[fly@752fac4b02e9 i2c_oled]$ tree
.
├── demo_iic_oled.c
├── inc
│ ├── bmp.h
│ ├── delay.h
│ ├── gui.h
│ ├── iic.h
│ ├── oledfont.h
│ ├── oled.h
│ ├── test.h
│ └── type.h
├── lib
├── Makefile
└── src
├── delay.c
├── gui.c
├── iic.c
├── oled.c
└── test.c
3 directories, 15 files
用户态读写IIC
//
static int iic_open(int adapter_nr)
{
int fd;
char filename[20];
snprintf(filename, 19, "/dev/i2c-%d", adapter_nr);
fd = open(filename, O_RDWR);
if(fd < 0){
perror("I2C Device open");
return -1;
}
return fd;
}
static int i2c_write(int fd, unsigned int slave_addr, unsigned char reg_addr, unsigned char value)
{
unsigned char outbuf[2];
struct i2c_rdwr_ioctl_data packets;
struct i2c_msg messages[1];
messages[0].addr = slave_addr;
messages[0].flags = 0;
messages[0].len = sizeof(outbuf);
messages[0].buf = outbuf;
/* The first byte indicates which register we‘ll write */
outbuf[0] = reg_addr;
/*
* The second byte indicates the value to write. Note that for many
* devices, we can write multiple, sequential registers at once by
* simply making outbuf bigger.
*/
outbuf[1] = value;
/* Transfer the i2c packets to the kernel and verify it worked */
packets.msgs = messages;
packets.nmsgs = 1;
if(ioctl(fd, I2C_RDWR, &packets) < 0){
perror("Unable to send data");
return 1;
}
return 0;
}
static int i2c_read(int fd, unsigned char slave_addr, unsigned char reg_addr, unsigned char *value)
{
unsigned char inbuf, outbuf;
struct i2c_rdwr_ioctl_data packets;
struct i2c_msg messages[2];
/*
* In order to read a register, we first do a "dummy write" by writing
* 0 bytes to the register we want to read from. This is similar to
* the packet in set_i2c_register, except it‘s 1 byte rather than 2.
*/
outbuf = reg_addr;
messages[0].addr = slave_addr;
messages[0].flags = 0;
messages[0].len = sizeof(outbuf);
messages[0].buf = &outbuf;
/* The data will get returned in this structure */
messages[1].addr = slave_addr;
messages[1].flags = I2C_M_RD/* | I2C_M_NOSTART*/;
messages[1].len = sizeof(inbuf);
messages[1].buf = &inbuf;
/* Send the request to the kernel and get the result back */
packets.msgs = messages;
packets.nmsgs = 2;
if(ioctl(fd, I2C_RDWR, &packets) < 0){
perror("Unable to send data");
return 1;
}
*value = inbuf;
return 0;
}
//
uint32_t iic_fd;
uint32_t IIC_init(void)
{
uint32_t fd;
fd = iic_open(IIC_ADAPTER_NR);
return fd;
}
/*****************************************************************************
* @name :void IIC_WriteCmd(uint8_t I2C_Command)
* @date :2018-09-14
* @function :write a byte of command with iic bus
* @parameters :I2C_Command:command to be writen
* @retvalue :None
******************************************************************************/
void IIC_WriteCmd(uint8_t I2C_Command)
{
i2c_write(iic_fd, IIC_SLAVE_ADDR, IIC_COMMAND, I2C_Command);
}
/*****************************************************************************
* @name :void IIC_WriteDat(uint8_t I2C_Data)
* @date :2018-09-14
* @function :write a byte of data with iic bus
* @parameters :I2C_Data:data to be writen
* @retvalue :None
******************************************************************************/
void IIC_WriteDat(uint8_t I2C_Data)
{
i2c_write(iic_fd, IIC_SLAVE_ADDR, IIC_DATA, I2C_Data);
}
Makefil文件
#CC = gcc
CC=aarch64-target-linux-gnu-gcc
CFLAGS = -g -Wall -O0
OBJS = demo_iic_oled
INCDIRS :=
INCDIRS = -I./inc
SRC = \
demo_iic_oled.c
SRC += \
src/iic.c \
src/oled.c \
src/gui.c \
src/delay.c \
src/test.c
$(OBJS) : $(SRC)
$(CC) $(CFLAGS) -o $@ $^ $(INCDIRS)
clean:
$(RM) $(OBJS) .*.sw?
演示(点亮效果)
后记
后续可能,还会继续探究各硬件模块和接口的功能和能力。再继续深入了解的情况,深入软件功能的探究,赋予这个丰富/强大的硬件,更灵活的软件使用。
同时,也希望和各位试用者多多交流,实现更有创意的想法。