Skip to content

Commit c20bff3

Browse files
author
meihao@ccy
committed
add students files
1 parent 55c3a8c commit c20bff3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+2663
-1
lines changed

docs/T113s3-SdNand/part3/02-DevelopmentEnvironmentSetup.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ rm /home/ubuntu/tina5sdk-bsp/brandy/brandy-2.0/spl-pub/* -rf
4848

4949
~~~bash
5050
ubuntu@ubuntu1804:~/tina5sdk-bsp$ cd ~/
51-
ubuntu@ubuntu1804:~$ git clone https://github.com/DongshanPI/T113S3-PRO_TinaSDK5.git
51+
ubuntu@ubuntu1804:~$ git clone https://github.com/DongshanPI/100ASK_T113s3-SdNand_TinaSDK5.git
5252
ubuntu@ubuntu1804:~$ cd T113S3-PRO_TinaSDK5
5353
ubuntu@ubuntu1804:~/T113S3-PRO_TinaSDK5$ git submodule update --init
5454
ubuntu@ubuntu1804:~/T113S3-PRO_TinaSDK5$ cp ./* -rfvd ~/tina5sdk-bsp
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"label": "学员案例文档",
3+
"position":7,
4+
"link": {
5+
"type": "generated-index",
6+
"description": "5 minutes to learn the most important Docusaurus concepts."
7+
}
8+
}
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
---
2+
sidebar_position: 1
3+
---
4+
# 交叉编译
5+
6+
## 交叉编译概述
7+
8+
在嵌入式系统开发中,交叉编译是一种关键技术。它允许我们在一种架构上(通常是开发主机,例如 x86)编译代码,以生成能够在另一种架构(通常是嵌入式目标设备,例如 ARM、MIPS 等)上运行的二进制文件。由于嵌入式设备通常具有特定的硬件和系统环境,直接在目标设备上编译往往不切实际,因此交叉编译成为一种必要手段,尤其是对于硬件资源有限、性能要求较高的嵌入式系统,交叉编译能够确保目标平台的架构和操作系统与开发环境相匹配,并且能够在性能更强的主机上生成适合目标平台的二进制文件,从而在开发主机上进行开发和调试,然后将生成的代码部署到目标设备上运行。
9+
10+
## 交叉编译的基本概念
11+
12+
交叉编译涉及以下主要环节:
13+
14+
1. **源代码**
15+
源代码是开发者撰写的程序或库代码,它是交叉编译的起点。
16+
17+
2. **交叉编译工具链**
18+
这是交叉编译的核心。它是在主机平台上运行的工具集合,包括编译器、链接器、调试器和构建工具等,用于将源代码编译为目标平台的可执行文件、库和其他二进制文件。例如,GCC 是一个常用的交叉编译工具链,它能够为 ARM 架构生成可执行文件。
19+
20+
3. **目标平台**
21+
这是代码运行的目标设备,一般是嵌入式系统。编译得到的二进制文件通过文件传输协议(如 SCP)上传到目标设备后即可运行。
22+
23+
## 交叉编译工具链
24+
25+
交叉编译工具链是实现交叉编译的关键,它包含以下组件:
26+
27+
1. **交叉编译器**
28+
这是一种特殊的编译器,能够将源代码编译为目标平台的机器代码。例如,`aarch64-linux-gnu-gcc` 用于生成 ARM64 架构的代码。
29+
30+
2. **链接器**
31+
它将编译生成的目标文件和库文件链接成一个完整的可执行文件。
32+
33+
3. **标准库**
34+
这是与目标平台匹配的 C 库(如 glibc),以确保生成的二进制文件能够在目标平台上正确运行。
35+
36+
4. **调试工具**
37+
如 GDB,它可以在目标平台上进行程序调试。
38+
39+
5. **构建系统**
40+
这些工具(如 make、CMake、Autotools 等)可自动化构建流程,调用交叉编译工具链中的工具来生成目标平台的可执行文件。
41+
42+
## 交叉编译的准备工作
43+
44+
1. **选择交叉编译工具链**
45+
首先要根据目标架构选择合适的工具链。比如针对 ARM 架构的工具链、针对 x86 架构的工具链,或者通过官方发布的工具链,自定义工具链。常见的工具链包括:
46+
47+
> - **GNU 工具链**:包括 `gcc``binutils``glibc` 等。
48+
> - **Yocto 项目工具链**:Yocto 提供了一个强大的交叉编译环境,并且能够自动化构建和配置交叉编译工具链。
49+
> - **Linaro 工具链**:Linaro 提供了针对 ARM 架构优化的工具链。
50+
51+
2. **设置交叉编译环境**
52+
需要为交叉编译设置适当的环境变量。例如,设置交叉编译器路径、目标平台的系统根路径、目标平台的库路径等。
53+
例如:
54+
55+
~~~bash
56+
export CROSS_COMPILE=arm-linux-gnueabihf-
57+
export ARCH=arm
58+
export SYSROOT=/opt/arm-linux-gnueabihf/sysroot
59+
export CC=${CROSS_COMPILE}gcc
60+
export CXX=${CROSS_COMPILE}g++
61+
~~~
62+
63+
3. **选择目标平台的操作系统**
64+
嵌入式平台通常运行精简版的操作系统。例如基于 Linux 的系统或 RTOS(实时操作系统)。交叉编译时需要确保目标平台的操作系统的核心库(如 C 库)和头文件与主机编译时使用的相匹配,以避免兼容性问题。
65+
66+
4. **获取目标平台的工具链**
67+
有时需要从开发板厂商或相关社区获取已经编译好的交叉编译工具链。如果找不到合适的预构建工具链,也可以从开源项目中获取交叉编译工具链。
68+
69+
## 交叉编译的流程
70+
71+
交叉编译的完整流程包括以下几个步骤:
72+
73+
1. **安装交叉编译工具链**
74+
首先在主机平台上安装交叉编译工具链。这可以通过下载预构建工具链包或从源码编译工具链来完成。
75+
76+
2. **配置源代码**
77+
配置源代码以便使用交叉编译工具链进行编译。例如,对于使用 GNU 系列构建系统的项目,可以通过指定交叉编译器和目标平台的 `--host` 参数来完成配置,例如:
78+
79+
~~~bash
80+
./configure --host=arm-linux
81+
~~~
82+
83+
3. **编译源代码**
84+
配置完成后,使用 make 或其他构建工具编译源代码。例如:
85+
86+
~~~bash
87+
make
88+
~~~
89+
90+
此时需要确保构建系统能够调用交叉编译工具链来生成正确的目标平台可执行文件。
91+
92+
4. **传输文件到目标设备**
93+
编译完成后,将生成的二进制文件(如可执行文件、库文件等)传输到目标设备上,可以使用 SSH、SCP 或其他文件传输协议。例如:
94+
95+
~~~bash
96+
scp executable_file user@target_device:/destination_folder
97+
~~~
98+
99+
5. **在目标设备上调试和测试**
100+
在目标设备上运行和调试编译生成的程序,以确保其能够正确工作。如果发现问题,可以通过串口、网络调试或使用 JTAG 调试器等方式进行调试。例如,使用 GDB 进行远程调试:
101+
102+
~~~bash
103+
gdb executable_file
104+
~~~
105+
106+
## 交叉编译的挑战与解决方案
107+
108+
- **不同架构之间的差异**
109+
不同的架构之间可能会存在差异,比如字节序、数据类型的大小等。为避免这些问题,开发者通常需要确保交叉编译时使用的工具链能够正确处理这些差异。例如,选择适合目标架构的工具链。
110+
111+
- **目标平台的依赖库问题**
112+
目标平台可能不具备某些开发环境中已经存在的库或功能。为了解决这个问题,开发者需要为目标平台提供所有必需的依赖库,可以通过静态链接库或交叉编译这些依赖库来解决。
113+
114+
- **调试困难**
115+
在嵌入式系统上进行调试相对较为困难。可以通过串口、网络调试或使用 JTAG 调试器等方式进行调试。例如,使用 GDB 与目标设备进行远程调试:
116+
117+
~~~bash
118+
gdbserver :1234 executable_file
119+
~~~
120+
121+
然后在主机上连接目标设备进行调试:
122+
~~~bash
123+
gdb executable_file
124+
~~~
125+
126+
之后通过远程调试命令连接目标设备。
127+
128+
- **优化目标平台性能**
129+
嵌入式系统通常资源有限,编译时需要对代码进行优化,以减少程序的内存占用和提升执行速度。例如,使用编译器的优化选项(如 `-O2`)来提高程序性能,或者通过减少库依赖来减少程序的体积。
130+
131+
## 常用的交叉编译工具
132+
133+
1. **GNU 工具链**
134+
GNU 提供了多种交叉编译工具,如 GCC(GNU C 编译器)和 Binutils(GNU 二进制工具)。它们是构建交叉编译工具链的基础。
135+
136+
2. **Yocto 项目**
137+
Yocto 是一个开源项目,旨在为嵌入式设备提供定制化的 Linux 系统。Yocto 提供了一个强大的交叉编译环境,并且能够自动化构建和配置交叉编译工具链。
138+
139+
3. **Linaro 工具链**
140+
Linaro 提供了针对 ARM 架构的优化交叉编译工具链,常用于 ARM 设备开发。
141+
142+
4. **Buildroot**
143+
Buildroot 是一个轻量级的构建系统,旨在为嵌入式系统提供交叉编译支持。它能够帮助开发者快速生成交叉编译工具链和目标平台的根文件系统。
144+
145+
## 总结
146+
147+
交叉编译是嵌入式系统开发中不可或缺的一个环节。通过交叉编译,开发者能够在性能更强大的主机上生成适合目标平台的二进制文件,并将其运行在嵌入式设备上。正确配置交叉编译工具链和构建环境是保证嵌入式系统开发顺利进行的关键。尽管交叉编译有一定的难度,但通过熟练掌握交叉编译的流程和常用工具,可以有效提升嵌入式开发的效率和可靠性。
148+
149+
## eg: 实际案例
150+
151+
在 T113s3 的 SDK 中,`tplayerdemo` 的交叉编译需要使用特定的 `Makefile` 进行配置和构建。
152+
153+
**Makefile 示例**
154+
155+
```make
156+
CC = /home/ubuntu/tina5sdk-bsp/out/toolchain/gcc-linaro-5.3.1-2016.05-x86_64_arm-linux-gnueabi/bin/arm-linux-gnueabi-gcc
157+
158+
Target = tplayerdemo
159+
160+
SourceIncludePath := \
161+
-I/home/ubuntu/tina5sdk-bsp/out/t113/evb1_auto/buildroot/buildroot/host/arm-buildroot-linux-gnueabi/sysroot/usr/include/ \
162+
-I/home/ubuntu/tina5sdk-bsp/out/t113/evb1_auto/buildroot/buildroot/host/arm-buildroot-linux-gnueabi/sysroot/usr/include/libcedarx/ \
163+
-I/home/ubuntu/tina5sdk-bsp/out/t113/evb1_auto/buildroot/buildroot/host/arm-buildroot-linux-gnueabi/sysroot/usr/include/libcedarc/ \
164+
-I/home/ubuntu/tina5sdk-bsp/out/t113/evb1_auto/buildroot/buildroot/host/arm-buildroot-linux-gnueabi/sysroot/usr/include
165+
166+
CompileFlags = $(CFLAGS) $(SourceIncludePath)
167+
168+
LibraryPath := \
169+
-L/home/ubuntu/tina5sdk-bsp/out/t113/evb1_auto/buildroot/buildroot/host/arm-buildroot-linux-gnueabi/sysroot/usr/lib \
170+
-L/home/ubuntu/tina5sdk-bsp/out/toolchain/gcc-linaro-5.3.1-2016.05-x86_64_arm-linux-gnueabi/arm-linux-gnueabi/
171+
172+
ifeq ($(ONLY_ENABLE_AUDIO),y)
173+
CompileFlags += -DONLY_ENABLE_AUDIO
174+
endif
175+
176+
ifeq ($(ONLY_DISABLE_AUDIO),y)
177+
CompileFlags += -DONLY_DISABLE_AUDIO
178+
endif
179+
180+
LoadFlags += $(LibraryPath) -ltplayer -lcdx_base -lrt -lstdc++
181+
LoadFlags += -lpthread
182+
183+
$(Target): tplayerdemo.c
184+
$(CC) --sysroot=/home/ubuntu/tina5sdk-bsp/out/t113/evb1_auto/buildroot/buildroot/host/arm-buildroot-linux-gnueabi/sysroot -o $@ $^ $(CompileFlags) $(LDFLAGS) $(LoadFlags)
185+
```
186+
187+
**Makefile 解释**
188+
189+
- `CC`:指定交叉编译器的路径。
190+
- `Target`:定义生成的目标程序名称。
191+
- `SourceIncludePath`:包含目标平台所需的头文件路径。
192+
- `CompileFlags`:编译标志,包含头文件搜索路径 `SourceIncludePath`
193+
- `LibraryPath`:目标平台的库文件搜索路径。
194+
- `LoadFlags`:加载库文件的标志。
195+
- `ONLY_ENABLE_AUDIO``ONLY_DISABLE_AUDIO`:用于条件编译,定义特定功能。
196+
- `$(Target): tplayerdemo.c`:指定目标程序的依赖文件。
197+
- `$(CC) --sysroot ...`:使用交叉编译器进行编译,生成目标程序 `tplayerdemo`
198+
199+
通过这个 `Makefile`,开发者可以方便地对 `tplayerdemo` 进行交叉编译。
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
---
2+
sidebar_position: 2
3+
---
4+
# LinuxFB介绍
5+
6+
## 什么是 Linux Framebuffer?
7+
8+
Linux Framebuffer(简称 LinuxFB)是一个为 Linux 系统提供的显示框架,用于处理图形显示。它为操作系统提供了一个抽象层,使得应用程序能够在不同的硬件上以一致的方式进行图像渲染。Framebuffer 是一个内存区域,通常是物理显示器的图像缓冲区,通过该缓冲区显示图像内容。Framebuffer 直接与显示设备交互,能够提供高效的图像渲染功能,尤其适用于嵌入式系统、裸机应用等没有图形桌面环境的环境。
9+
10+
## 工作原理
11+
12+
Framebuffer 作为一个内存区域,通常由图形硬件映射到物理显示屏上的像素阵列中。图形显示时,操作系统和应用程序可以通过对 framebuffer 内存的操作来控制显示内容。Framebuffer 通常与图形硬件紧密结合,操作系统通过指定显示设备的参数(如分辨率、颜色深度等)来配置 framebuffer。
13+
14+
在 Linux 系统中,Framebuffer 设备通常以 `/dev/fb0`(或其他 `/dev/fbX`)的形式存在。Linux 内核通过驱动程序来提供 framebuffer 设备支持。用户空间的应用程序通过特定的接口(如 ioctl())来操作 framebuffer,从而达到显示图像、更新内容等目的。
15+
16+
## 功能和特性
17+
18+
- **独立于硬件平台**:Framebuffer 为用户提供了一种硬件无关的显示接口,使得应用程序能够以相同的方式处理显示,而不必关心底层硬件的具体实现。无论是基于 x86 架构的个人计算机,还是嵌入式 ARM 系统,Framebuffer 都能提供一致的 API 接口。
19+
- **支持多种颜色格式**:Framebuffer 支持多种颜色深度和颜色格式,常见的颜色深度包括 8-bit、16-bit、24-bit 和 32-bit。用户可以根据实际需求选择合适的颜色深度。例如,在嵌入式系统中,通常使用 16-bit 色深(RGB565 格式)来平衡显示效果和内存消耗。
20+
- **支持像素操作**:通过直接对 framebuffer 内存的操作,用户可以快速进行像素级别的操作。这使得一些低级的图形渲染操作(如自定义图标绘制、屏幕刷新)可以更加高效。
21+
- **兼容性**:Framebuffer 驱动是 Linux 内核的一部分,支持多种不同的硬件平台,包括主流的集成显卡(如 Intel、AMD、NVIDIA)以及嵌入式图形芯片(如 ARM、Mali、Vivante 等)。
22+
- **不依赖桌面环境**:Framebuffer 是一个轻量级的显示技术,它不需要图形桌面环境(如 X Window 或 Wayland)。这种特性使其非常适合嵌入式系统、最小化操作系统或者用于裸机开发的应用程序。
23+
24+
## 核心组成部分
25+
26+
- **Framebuffer 设备(/dev/fbX)**:每个显示设备都由一个 framebuffer 设备节点来表示。在 Linux 中,Framebuffer 设备节点通常位于 `/dev` 目录下,例如 `/dev/fb0`。应用程序可以通过打开该设备节点并对其进行读取、写入操作来控制显示内容。
27+
- **Framebuffer 驱动程序**:每个图形硬件通常需要一个相应的 framebuffer 驱动程序,以便 Linux 内核能够识别并支持该硬件。
28+
- **Framebuffer 字符设备接口**:Framebuffer 提供了一个字符设备接口,应用程序通过读取和写入该设备节点,向 framebuffer 内存中写入图像数据。
29+
- **Framebuffer 内存**:Framebuffer 是一块连续的内存区域,通常映射到显示硬件的显存区域。
30+
- **图像渲染**:渲染图像通常包括像素填充、颜色调整、透明度处理等,应用程序通过设置像素值、绘制图形等方式来更新 framebuffer 中的内容。
31+
32+
## 工作流程
33+
34+
1. **初始化**:当系统启动时,内核会识别并初始化与显示相关的硬件设备,加载相应的 framebuffer 驱动程序,并创建 framebuffer 设备节点。
35+
2. **打开设备**:应用程序通过打开 `/dev/fb0` 或其他 framebuffer 设备节点来与 framebuffer 进行交互。
36+
3. **写入图像数据**:应用程序可以通过写入 framebuffer 设备来更新显示内容,直接操作 framebuffer 内存,更新显示区域的像素数据。
37+
4. **刷新显示**:显示硬件自动或手动将 framebuffer 的数据更新到物理显示器上。
38+
5. **关闭设备**:应用结束时,关闭 framebuffer 设备,释放资源。
39+
40+
## 应用场景
41+
42+
- **嵌入式系统**:Framebuffer 适合在嵌入式系统中使用,嵌入式设备通常具有特定的显示需求(如小屏幕、低功耗显示),使用 framebuffer 可以节省系统资源并提高性能。
43+
- **裸机图形应用**:在一些没有操作系统支持的应用中,Framebuffer 提供了一个直接与显示硬件交互的接口。
44+
- **最小化操作系统**:对于一些最小化的 Linux 发行版,Framebuffer 提供了一个简单有效的图形接口。
45+
- **虚拟化环境**:Framebuffer 也可以在虚拟机中使用,通过虚拟 framebuffer,虚拟机能够以较低的开销提供图形显示。
46+
47+
## T113s3使用案例
48+
49+
c代码:
50+
51+
```c
52+
#include <stdio.h>
53+
#include <sys/types.h> //open需要的头文件
54+
#include <sys/stat.h>
55+
#include <fcntl.h>
56+
#include <unistd.h> //write
57+
#include <sys/types.h>
58+
#include <sys/mman.h> //mmap 内存映射相关函数库
59+
#include <stdlib.h> //malloc free 动态内存申请和释放函数头文件
60+
#include <string.h>
61+
#include <linux/fb.h>
62+
#include <sys/ioctl.h>
63+
64+
//32位的颜色
65+
#define Black 0x00000000
66+
#define White 0xffFFFFFF
67+
#define Red 0xffFF0000
68+
#define Green 0xff00ff00
69+
#define Blue 0xff99ffff
70+
71+
int fd;
72+
unsigned int *fb_mem = NULL; //设置显存的位数为32位
73+
struct fb_var_screeninfo var;
74+
struct fb_fix_screeninfo fix;
75+
76+
int main(void)
77+
{
78+
unsigned int i;
79+
int ret;
80+
81+
/*--------------第一步--------------*/
82+
fd = open("/dev/fb0",O_RDWR); //打开framebuffer设备
83+
if(fd == -1){
84+
perror("Open LCD");
85+
return -1;
86+
}
87+
88+
/*--------------第二步--------------*/
89+
//获取屏幕的可变参数
90+
ioctl(fd, FBIOGET_VSCREENINFO, &var);
91+
//获取屏幕的固定参数
92+
ioctl(fd, FBIOGET_FSCREENINFO, &fix);
93+
94+
//打印分辨率
95+
printf("xres= %d,yres= %d \n",var.xres,var.yres);
96+
//打印总字节数和每行的长度
97+
printf("line_length=%d,smem_len= %d \n",fix.line_length,fix.smem_len);
98+
printf("xpanstep=%d,ypanstep= %d \n",fix.xpanstep,fix.ypanstep);
99+
100+
/*--------------第三步--------------*/
101+
102+
fb_mem = (unsigned int *)mmap(NULL, var.xres*var.yres*4, //获取显存,映射内存
103+
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
104+
105+
if(fb_mem == MAP_FAILED){
106+
perror("Mmap LCD");
107+
return -1;
108+
}
109+
110+
memset(fb_mem,0xff,var.xres*var.yres*4); //清屏
111+
sleep(1);
112+
113+
/*--------------第四步--------------*/
114+
//将屏幕全部设置成蓝色
115+
for(i=0;i< var.xres*var.yres ;i++)
116+
fb_mem[i] = Blue;
117+
sleep(2);
118+
memset(fb_mem,0x00,var.xres*var.yres*4); //清屏
119+
120+
munmap(fb_mem,var.xres*var.yres*4); //映射后的地址,通过mmap返回的值
121+
close(fd); //关闭fb0设备文件
122+
return 0;
123+
}
124+
```
125+
126+
代码运行效果屏幕变成蓝色:
127+
128+
![image-20250303092408471](images/image-20250303092408471.png)

0 commit comments

Comments
 (0)