
Unit-01 XenonCore 初号机·氙光芯髓
简介
名为「XenonCore」的多形态智能终端。 作为一个像Switch手柄一样可拆卸的模块化设备,核心连手柄变掌机,拆开就是独立高性能平板,实现游戏与平板体验的随心切换。
简介:名为「XenonCore」的多形态智能终端。 作为一个像Switch手柄一样可拆卸的模块化设备,核心连手柄变掌机,拆开就是独立高性能平板,实现游戏与平板体验的随心切换。开源协议
:CC BY-NC-SA 3.0
描述
呼 陆陆续续搞了十个月,终于是把项目赶出来了
演示视频链接
哔哩哔哩
硬件设计部分讲解视频链接
软件MIPI屏幕适配部分讲解视频
请加入QQ交流群:2155031988
温馨提示:为了更好的阅读体验,请下载附件的pdf文档
主机展示



手柄拓展展示

铝合金散热模组
以下是项目基本信息介绍
一、项目背景与核心理念
针对当前电子设备难以兼顾扩展性、可开发性和便携性的痛点,本项目创新性地采用模块化架构设计,打造了一款名为「XenonCore」的多形态智能终端。
作为一个像Switch手柄一样可拆卸的模块化设备,核心连接手柄变掌机,拆开就是独立高性能平板,实现游戏与平板体验的随心切换。
二、硬件系统设计
1. 核心架构:
- 主控芯片:瑞芯微RK3566 SOC(与立创"泰山派"同平台)
- 四核Cortex-A55@1.8GHz / Mali-G52 GPU
- 支持4K60Hz解码及双系统运行
2. 模块化外设矩阵:
- 运动控制:LSM6DS3TR-C
- 无线连接:AP6256 WiFi6+BT5.0模块 双频2.4G/5GHz,峰值速率600Mbps
- 快充系统:BQ25890+CW2015+Fusb302 30W PD3.0协议,智能电量监测
- 交互显示:TPM0551002P触摸屏+S3351控制器 5.5寸MIPI屏,10点触控
- 扩展接口:1.27mm高密度连接器x2 集成USB3.0/GPIO/SDIO等信号
三、结构设计思路
1. 模块化架构:
- 磁吸式快拆结构,支持热插拔
2. 形态转换机制:
- 掌机模式:核心+控制手柄模块
- 工控模式:核心+工业外设模块
- 开发板模式:核心+调试接口
四、软件生态系统
1. 双系统架构:
- Android 13
- Ubuntu 22.04/OpenKylin/Debian
2. 关键特性:
- 系统级外设控制面板
- 完整GPIO/PWM/I2C控制
软件适配部分
RK3566 Android13 软件适配笔记
基于Unit-01 XenonCore 3566/初号机 氙光芯髓项目
感谢本项目开发者和为此付出的大佬们
啊这/Han 著
序言
本笔记作为自己(啊这)在适配RK3566软件过程中的记录,包括实际遇到的一些问题的解决方法,以便自己以及同好查询或作为入门的参考。本笔记将由内核展开,不深入uboot,同时记录安卓frameworks文件夹内的一些系统优化措施,大部分解决方法来自相当长时间的技术积累。
为了获取更好的阅读体验,我推荐读者下载附件中的PDF版本
章节一 编译环境的配置-WSL
-
安装Ubuntu系统 FunKey-OS需在Linux系统下进行编译,推荐选择Ubuntu
22.04 LTS,您可选择:
使用轻量级容器系统,如Docker,并在其中运行Ubuntu。 对于Windows
用户安装双系统。 使用VM(虚拟机),并在其中运行Ubuntu。
使用WSL2(Windows System for Linux 2)子系统并在其中运行Ubuntu
Linux发行版。 WSL2安装方法, -
完成Linux的基础环境配置后,下载SDK压缩包,大约24GB,并且保证SSD中还剩余300GB空间和16GB+30GB
swap,swap配置请百度方法。进行SDK的解压与编译所需工具的安装。
> 请确保已熟悉linux命令行的基本操作命令,之后再进行操作。
- 复制SDK包到你的任意文件夹,我使用/root文件夹
> 因此命令为 cp xxx.tgz /root或cp xxx.tgz .
- 解压sdk,使用tar -xzvf
xxxx.tgz命令解压SDK包,得到.git文件夹,由于"."开头的文件在linux中默认隐藏,因此一般情况下是看不到它的,但无需担心,这并不会影响解压过程。接下来,使用
> git reset ---hard 来提取sdk。
>
> 这个过程较慢,具体速度受内存大小和SSD读写速度限制,不如去喝杯咖啡。
- 解压完成后,你理应得到如下的文件目录,如图:
接下来,执行以下命令,安装所需的工具
sudo apt-get install git bc bison build-essential curl flex
g++-multilib gcc-multilib \\
gnupg gperf imagemagick lib32ncurses5-dev lib32readline-dev
lib32z1-dev liblz4-tool libncurses5-dev \\
libsdl1.2-dev libssl-dev libwxgtk3.0-dev libxml2 libxml2-utils lzop
pngcrush rsync schedtool \\
squashfs-tools xsltproc yasm zip zlib1g-dev python
device-tree-compiler python-pip
如果出现报错,尝试一个一个排除,这是因为ubuntu版本差异引起的。
- 进行第一次编译的适配
执行./build.sh init,你将看到图形化的选择界面
>
>
请选择platform5 即RK356x
>
接下来选择第一个,DR4-RK3566
>
回车后,程序将自动运行,不出意外,程序会完成SDK的lunch等配置,接下来执行./build.sh
进行SDK的全量编译。在全量编译完后,你将得到完整的update固件,可直接烧录测试,由于没有进行板级适配,你只能在adb中投屏或者·HDMI接口进入系统。
5.在编译过程中,可能会遇到很多种报错,需要具有查找资料,解决报错的能力。如报错xxx
command not found,应该联想到去安装相应的软件包。
经本人实测,ubuntu22.04
20.04均可在解决错误后正常编译,因此不要遇到报错就放弃,寻找充装系统等没有真正解决问题的逃避方法。编译笔记毕竟是根据我个人电脑的情况而言,只有亲自解决报错,才能掌握接下来章节的学习节奏和过程。
- 这一章的最后,请尝试独立完成新建产品lunch,添加至./build.sh中,当然,在任何修改前,请别忘了备份,以应对任何突发情况。
章节二 添加掌机源码
- 复制patch文件到sdk根目录,执行
> git apply xxx.patch
- 确保解决所有报错后,重新进行全量编译,即可
接下来的部分,将详细介绍各部分硬件的单独适配教程。
如果想对系统进行深度定制,或使用拓展接口接更多有意思的外设,这部分将进行介绍。
章节三 RK3566超压·超频
- cpu的配置在设备树中更改。设备树,即DeviceTree,文件后缀为dts与dtsi,后文所说在dts中修改,默认指修改设备树。以下是从网络摘来的对dts的介绍,也可以参考立创泰山派的教程,更加详细。
1. 什么是DTS,DTC 和DTB?
dts(device tree source 设备树源文件)
dts文件是一种ASCII文本格式的设备树描述文件,此文件适合人类阅读主要是给用户看的。一个dts文件对应一个ARM的设备,一般放置在arch/arm/boot/dts/中。由于dts中包含了很多公共部分,linux内核为了简化,将Soc公共部分提炼为.dtsi文件,类似c语言中的.h文件。我以imx6为例
#include
#include "imx6ul.dtsi"
/ {
model = "Freescale i.MX6 UltraLite 14x14 EVK Board";
compatible = "fsl,imx6ul-14x14-evk", "fsl,imx6ul";
chosen {
stdout-path = &uart1;
};
memory {
reg = <0x80000000 0x20000000>;
};
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges;
linux,cma {
compatible = "shared-dma-pool";
reusable;
size = <0x14000000>;
linux,cma-default;
};
};
这是imx6ul-14x14-evk.dts中的一部分,其中imx6ul.dtsi 就是公共部分,使用include包含。
DTC
DTC 是将dts文件编译成dtb的工具,
dtb(dtb - device tree blob设备树二进制文件)
dts通过dtc编译成dtb文件,被编译后的设备树文件与内核一同放入到存储介质中,当内核启动时读取设备树文件,就可以动态的将板级信息写入到内核中。
2. DTS格式
Devicetree node格式:
[label:] node-name[@unit-address] {
[properties definitions]
[child nodes]
};
Property格式1:
[label:] property-name = value;
Property格式2(没有值):
[label:] property-name;
Property取值只有3种:
arrays of cells(1个或多个32位数据, 64位数据使用2个32位数据表示),
string(字符串),
bytestring(1个或多个字节)
例子:
a. Arrays of cells : cell就是一个32位的数据
interrupts = <17 0xc>;
b. 64bit数据使用2个cell来表示:
clock-frequency = <0x00000001 0x00000000>;
c. A null-terminated string (有结束符的字符串):
compatible = "simple-bus";
d. A bytestring(字节序列) :
local-mac-address = [00 00 12 34 56 78]; // 每个byte使用2个16进制数来表示
local-mac-address = [000012345678]; // 每个byte使用2个16进制数来表示
e. 可以是各种值的组合, 用逗号隔开:
compatible = "ns16550", "ns8250";
example = <0xf00f0000 19>, "a strange property format";
dts组成
标准属性
- compatible
每一个dts文件都有一个root根节点,使用"/" 内核通过"/"
找到设备。例如上面给出的imx6的设备树文件
model = "Freescale i.MX6 UltraLite 14x14 EVK Board";
compatible = "fsl,imx6ul-14x14-evk", "fsl,imx6ul";
- address-cells和#size-cells
address-cells = <1>: 基地址、片选号等绝对起始地址所占字长,单位uint32
size-cells = <1>: 长度所占字长,单位uint32
本项目设备树存放在该目录:
kernel-5.10/arch/arm64/boot/dts/rockchip/rk356x/
该目录也有其他项目的dts,不必理会,本项目只与这几个文件相关:
dr4-rk3566.dts SingleJoy.dtsi rk3566-evb-rpdzkj-rk809-tcs4525.dtsi
rp-lcd-hdmi.dtsi lcd-gpio-dr4-rk3566.dtsi BQ25890-CHARGE-IC.dtsi
AAA-TPM0551002P.dtsi ../rk3568.dtsi
进入正题,修改cpu超频。
来到../rk3568.dtsi,在节点cpu0_opp_table: cpu0-opp-table {
中可看到如下配置
/* RK3568 && RK3568M cpu OPPs */
opp-408000000 {
opp-supported-hw = <0xfb 0xffff>;
opp-hz = /bits/ 64 <408000000>;
opp-microvolt = <850000 850000 1150000>;
clock-latency-ns = <40000>;
};
opp-600000000 {
opp-supported-hw = <0xfb 0xffff>;
opp-hz = /bits/ 64 <600000000>;
opp-microvolt = <850000 850000 1150000>;
clock-latency-ns = <40000>;
};
opp-816000000 {
opp-supported-hw = <0xfb 0xffff>;
opp-hz = /bits/ 64 <816000000>;
opp-microvolt = <850000 850000 1150000>;
clock-latency-ns = <40000>;
opp-suspend;
};
opp-1104000000 {
opp-supported-hw = <0xfb 0xffff>;
opp-hz = /bits/ 64 <1104000000>;
opp-microvolt = <900000 900000 1150000>;
opp-microvolt-L0 = <900000 900000 1150000>;
opp-microvolt-L1 = <900000 900000 1150000>;
opp-microvolt-L2 = <900000 900000 1150000>;
opp-microvolt-L3 = <900000 900000 1150000>;
clock-latency-ns = <40000>;
};
opp-1416000000 {
opp-supported-hw = <0xfb 0xffff>;
opp-hz = /bits/ 64 <1416000000>;
opp-microvolt = <1025000 1025000 1150000>;
opp-microvolt-L0 = <1025000 1025000 1150000>;
opp-microvolt-L1 = <975000 975000 1150000>;
opp-microvolt-L2 = <975000 975000 1150000>;
opp-microvolt-L3 = <975000 975000 1150000>;
clock-latency-ns = <40000>;
};
opp-1608000000 {
opp-supported-hw = <0xf9 0xffff>;
opp-hz = /bits/ 64 <1608000000>;
opp-microvolt = <1100000 1100000 1150000>;
opp-microvolt-L0 = <1100000 1100000 1150000>;
opp-microvolt-L1 = <1050000 1050000 1150000>;
opp-microvolt-L2 = <1050000 1050000 1150000>;
opp-microvolt-L3 = <1050000 1050000 1150000>;
clock-latency-ns = <40000>;
};
opp-1800000000 {
opp-supported-hw = <0xf9 0xffff>;
opp-hz = /bits/ 64 <1800000000>;
opp-microvolt = <1150000 1150000 1150000>;
opp-microvolt-L0 = <1150000 1150000 1150000>;
opp-microvolt-L1 = <1100000 1100000 1150000>;
opp-microvolt-L2 = <1100000 1100000 1150000>;
opp-microvolt-L3 = <1100000 1100000 1150000>;
clock-latency-ns = <40000>;
};
opp-1992000000 {
opp-supported-hw = <0xf9 0xffff>;
opp-hz = /bits/ 64 <1992000000>;
opp-microvolt = <1150000 1150000 1150000>;
opp-microvolt-L0 = <1150000 1150000 1150000>;
opp-microvolt-L1 = <1150000 1150000 1150000>;
opp-microvolt-L2 = <1125000 1125000 1150000>;
opp-microvolt-L3 = <1125000 1125000 1150000>;
clock-latency-ns = <40000>;
};
不用理会33568-J/-M,这是特殊版本芯片。
拿这个举例
opp-1608000000 {
opp-supported-hw = <0xf9 0xffff>;
opp-hz = /bits/ 64 <1608000000>;
opp-microvolt = <1100000 1100000 1150000>;
opp-microvolt-L0 = <1100000 1100000 1150000>;
opp-microvolt-L1 = <1050000 1050000 1150000>;
opp-microvolt-L2 = <1050000 1050000 1150000>;
opp-microvolt-L3 = <1050000 1050000 1150000>;
clock-latency-ns = <40000>;
};
opp-supported-hw :表示对芯片的支持,不用修改
opp-hz 表示频率,单位hz
opp-microvolt 表示电压 单位mv
如果在当前频率cpu不稳定,可以尝试增加cpu电压。
注意 超频没事,超压属于危险操作,只要超压就存在存在烧U的风险,谨慎行事
在上面,可以看到这一段
mbist-vmin = <825000 900000 950000>;
nvmem-cells = <&cpu_leakage>, <&core_pvtm>, <&mbist_vmin>, <&cpu_opp_info>,
<&specification_serial_number>, <&remark_spec_serial_number>;
nvmem-cell-names = "leakage", "pvtm", "mbist-vmin", "opp-info",
"specification_serial_number", "remark_spec_serial_number";
rockchip,supported-hw;
rockchip,max-volt = <1200000>;
rockchip,pvtm-voltage-sel = <
0 84000 0
84001 87000 1
87001 91000 2
91001 100000 3
>;
rockchip,pvtm-freq = <408000>;
rockchip,pvtm-volt = <900000>;
rockchip,pvtm-ch = <0 5>;
rockchip,pvtm-sample-time = <1000>;
rockchip,pvtm-number = <10>;
rockchip,pvtm-error = <1000>;
rockchip,pvtm-ref-temp = <40>;
rockchip,pvtm-temp-prop = <26 26>;
rockchip,thermal-zone = "soc-thermal";
rockchip,temp-hysteresis = <5000>;
rockchip,low-temp = <0>;
rockchip,low-temp-adjust-volt = <
/* MHz MHz uV */
0 1992 75000
>;
rockchip,max-volt 表示最大电压限制
rockchip,pvtm-voltage-sel 最小频率 最大频率 (单位khz)
section表,对应上文opp-xxx
rockchip,pvtm-ref-temp 参考温度
章节四 MIPI屏幕配置
本章节适用于想给项目换屏的开发者,理论上支持所有4lane内的MIPI屏幕,包括OLED
对于RK平台,MIPI屏幕的适配极其简单。只需要在设备树中更改好timings,delay,initial-code即可点亮屏幕
那么话不多说,直接看dsi节点来讲
对应项目源码AAA-TPM0551002P.dtsi
&dsi1 {
status = "okay";
//rockchip,lane-rate = <480>;
dsi1_panel: panel@0 {
status = "okay";
compatible = "simple-panel-dsi";
reg = <0>;
power-supply = <&vcc3v3_lcd0_n>;
reset-gpios = <&gpio2 RK_PC6 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&lcd_rst_gpio>;
backlight = <&backlight5>;
reset-delay-ms = <35>;
enable-delay-ms = <100>;
prepare-delay-ms = <35>;
unprepare-delay-ms = <35>;
disable-delay-ms = <35>;
init-delay-ms = <20>;
dsi,flags = <(MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET)>;
dsi,format = ;
dsi,lanes = <4>;
/**
* power-supply = <>;
* reset-gpios = <>;
*
* lcd reset pin and power supply
* please refer to ***-lcd-gpio.dtsisss
* that included in main dts.
*/
# 不可改动,这是最简初始化序列
panel-init-sequence = [
15 00 02 51 00
15 00 02 53 0C
15 00 02 55 00
05 00 01 11
05 0A 01 29
];
panel-exit-sequence = [
05 00 01 28
05 78 01 10
];
disp_timings1: display-timings {
native-mode = <&dsi1_timing0>;
dsi1_timing0: timing0 {
clock-frequency = <142000000>;// (1920+4+3+1)*(1080+96+33+12)*60=134800000
hactive = <1080>;
hfront-porch = <96>;
hback-porch = <33>;
hsync-len = <12>;
vactive = <1920>;
vfront-porch = <4>;
vback-porch = <3>;
vsync-len = <1>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
};
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
panel_in_dsi1: endpoint {
remote-endpoint = <&dsi1_out_panel>;
};
};
};
};
ports {
#address-cells = <1>;
#size-cells = <0>;
port@1 {
reg = <1>;
dsi1_out_panel: endpoint {
remote-endpoint = <&panel_in_dsi1>;
};
};
};
};
//rockchip,lane-rate = <480>;
给到注释,是因为系统可以自动根据屏幕参数计算rate,因此不必配置
backlight = <&backlight5>; 此处需挂载到你的背光节点,eg:
backlight5: backlight {
compatible = "pwm-backlight";
pwms = <&pwm5 0 25000 0>;
brightness-levels = <
0 20 20 21 21 22 22 23
23 24 24 25 25 26 26 27
27 28 28 29 29 30 30 31
31 32 32 33 33 34 34 35
35 36 36 37 37 38 38 39
40 41 42 43 44 45 46 47
48 49 50 51 52 53 54 55
56 57 58 59 60 61 62 63
64 65 66 67 68 69 70 71
72 73 74 75 76 77 78 79
80 81 82 83 84 85 86 87
88 89 90 91 92 93 94 95
96 97 98 99 100 101 102 103
104 105 106 107 108 109 110 111
112 113 114 115 116 117 118 119
120 121 122 123 124 125 126 127
128 129 130 131 132 133 134 135
136 137 138 139 140 141 142 143
144 145 146 147 148 149 150 151
152 153 154 155 156 157 158 159
160 161 162 163 164 165 166 167
168 169 170 171 172 173 174 175
176 177 178 179 180 181 182 183
184 185 186 187 188 189 190 191
192 193 194 195 196 197 198 199
200 201 202 203 204 205 206 207
208 209 210 211 212 213 214 215
216 217 218 219 220 221 222 223
224 225 226 227 228 229 230 231
232 233 234 235 236 237 238 239
240 241 242 243 244 245 246 247
248 249 250 251 252 253 254 255
>;
default-brightness-level = <100>;
};
这是一个背光映射表,可以在此进行背光到pwm的细分映射。
dsi,flags = <(MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET)>;
dsi,format = ;
dsi,lanes = <4>;
这些是MIPI色彩格式,lane数,cmd/video模式的配置,其中大部分情况只需要更改lane'数,其他的看具体情况,请参考附件RK
DRM调试文档。
panel-init-sequence = [
15 00 02 51 00
15 00 02 53 0C
15 00 02 55 00
05 00 01 11
05 0A 01 29
];
panel-exit-sequence = [
05 00 01 28
05 78 01 10
];
这是屏幕最重要的部分之一,即初始化/exit序列。
序列起到与IC通讯,协商显示模式,gamma等重要参数。
屏幕不同,序列也会天差地别,这块屏幕的序列很短,是因为大厂的屏幕一般都将序列写入了IC之中,只需要配置一点点即可。
在此说一下所谓的"免初始化屏幕",其实并不是不需要初始化序列,最少也需要11
29,即上文最后两行。对于OLED屏幕,还需要在0X51地址发送亮度数据调光。
重点:RK平台DSI数据格式撰写
对于RK平台的数据,应当这样处理
数据格式 延时(ms转16进制) 地址+数据的量 地址 数据
打个比分,我需要在0x51寄存器发送FF,延时120ms
那么代码如下: 15 78 02 51 FF
前面的数据格式,请参考RK平台DRM调试文档,一般常用05 15
39,同时也存在29等特殊类型。
转写完代码,接下来看这一部分
disp_timings1: display-timings {
native-mode = <&dsi1_timing0>;
dsi1_timing0: timing0 {
clock-frequency = <142000000>;// (1920+4+3+1)*(1080+96+33+12)*60=134800000
hactive = <1080>;
hfront-porch = <96>;
hback-porch = <33>;
hsync-len = <12>;
vactive = <1920>;
vfront-porch = <4>;
vback-porch = <3>;
vsync-len = <1>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
};
这就是timings配置,请在此配置好屏幕手册中写好的屏幕参数。
Clock时钟频率请根据旁边的公式计算。
疑难解答:如果排除所有问题,屏幕依然不显示(有背光),请检查delay参数是否到位,过短或过长的delay都会导致控制器无响应,造成初始化失败,请参考屏幕手册所给的上电sequence表来编写。
&dsi1_in_vp0 {
status = "disabled";
};
&dsi1_in_vp1 {
status = "okay";
};
&video_phy1{
status = "okay";
};
&route_dsi1 {
status = "okay";
connect = <&vp1_out_dsi1>;
};
这一部分,分开来讲。
节点一/二,表示dsi1在VOP0中不使能,在VOP1中使能
节点三 表示使能VOP1
节点四,开启后才能显示uboot/kernel启动画面。
至于pinctrl,触摸的配置,请直接查看dtsi源码,并不复杂,不再赘述
章节五 SDIO设备 详见附件
设计图
未生成预览图,请在编辑器重新保存一次BOM
暂无BOM
克隆工程知识产权声明&复刻说明
本项目为开源硬件项目,其相关的知识产权归创作者所有。创作者在本平台上传该硬件项目仅供平台用户用于学习交流及研究,不包括任何商业性使用,请勿用于商业售卖或其他盈利性的用途;如您认为本项目涉嫌侵犯了您的相关权益,请点击上方“侵权投诉”按钮,我们将按照嘉立创《侵权投诉与申诉规则》进行处理。
请在进行项目复刻时自行验证电路的可行性,并自行辨别该项目是否对您适用。您对复刻项目的任何后果负责,无论何种情况,本平台将不对您在复刻项目时,遇到的任何因开源项目电路设计问题所导致的直接、间接等损害负责。











