正在用东山哪吒开发板学习嵌入式linux,边学边做笔记。大侠不要见笑。
linux笔记(1):windows11安装东山哪吒STU板Linux开发环境(全志D1-H)-操作记录
双11买了一块东山哪吒STU学习开发板(韦东山老师出品,教程比较多),还没收到,先配置好环境。win10和win11安装ubuntu的步骤几乎一样。只是win10要高版本。
windows10的版本要求:
- 对于 x64 系统:版本 1903 或更高版本,采用内部版本 18362 或更高版本。
- 对于 ARM64 系统:版本 2004- 或更高版本,采用内部版本 19041 或更高版本。
- 低于 18362 的版本不支持 WSL 2。 使用 Windows Update 助手更新 Windows 版本。
1.windows11配置使能wsl
1.1 打开配置界面
1.2 进入 《应用->可选功能》
1.3 进入《更多功能》
1.4 勾选3个选项
确认后,系统要求重启才能生效。重启windows系统。
2. 安装ubuntu18.0.4系统
2.1在windows自带应用中打开《Microsoft Store》。
2.2搜索并安装ubuntu18.04.5LTS
这个系统只有290多MB,安装很快就完成。可以把它固定到启动页面,方便快捷启动。
3.启动ubunu遇到一个坑:WslRegisterDistribution failed with error: 0x800701bc
在CSDN找到解决方法:
作者:first_Dance,文章:《win10 WSL2问题解决WslRegisterDistribution failed with error: 0x800701bc》。
文章很短,这里引用一下:
造成该问题的原因是WSL版本由原来的WSL1升级到WSL2后,内核没有升级,前往微软WSL官网下载安装适用于 x64 计算机的最新 WSL2 Linux 内核更新包即可。
下载链接:https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi
安装文件才16M,几秒种就安装完毕。接下来可以正常启动ubuntu。
4.安装交叉编译工具链
4.1 获取源码
打开东山派的官方网站 https://dongshanpi.com/DongshanNezhaSTU/05-1_RunHelloword/,按照介绍一步一步执行:
下图显示的是按照上图步骤3命令执行情况:
执行完毕后:
4.2 验证工具链是否可用
进入目录 《eLinuxCore_dongshannezhastu/toolchain/riscv64-glibc-gcc-thead_20200702/bin》,输入命令:
./riscv64-unknown-linux-gnu-gcc -v
至此应该就可以了。测试编译helloword.c的文件。
在下一篇文章《linux笔记(2):vscode插件remote WSL远程使用交叉编译工具链(全志D1-H)》测试交叉编译工具链。
5.windows访问wsl文件权限不足问题
首次安装ubuntu,windows通过地址栏输入 ==\\wsl$== 就可以访问wsl文件:
也可以通过左侧已经自动挂载好的盘符直接访问:
但是无法修改。
5.1 解决修改权限不足的方法
这里抄录网友提供的解决方案:
作者:给岁月Z以文明,文章:《Windows直接访问WSL2路径并直接进行读写操作,权限不足的问题》:
原因分析
在初次安装WSL Ubuntu时,一般都会设置默认登录用户,当你通过windows访问该文件夹时,如果访问的Ubuntu目录的权限用户时你的默认用户,你可以对其进行修改。但是如果你访问的时root权限的用户,则会出现如上报错。
解决方法
如果是这样的话,需要修改默认登录用户为root即可,修改方式如下:
C:\Users\Administrator\AppData\Local\Microsoft\WindowsApps\ubuntu1804.exe config --default-user root
修改完成后,记得重启wsl:先关闭wsl,再启动wsl。
我指定关闭的指令有2种:
第一种:
wsl --shutdown
第二种:
net stop LxssManager
10s后,在执行wsl命令,然后再次测试,看是否可行。
6.将安装位置转移到非系统盘
22-11-19补充:ubuntu默认安装在C盘,随着D1-H不同版本,Tina、buildroot、又是东山的,又是全志社区的,每个版本都要占用几个G的空间,所以最好迁移到非系统盘。
参考文章:作者:断毫残墨,文章《win10 wsl2修改默认安装目录到其他盘》,摘录如下:
整个流程涉及到压缩,移动,解压等操作,我这个文件17G,耗时30分钟以内。
PS C:\Users\Administrator> wsl --shutdown
PS C:\Users\Administrator> net stop LxssManager
LxssManager 服务正在停止.
LxssManager 服务已成功停止。
PS C:\Users\Administrator> wsl -l --all -v
NAME STATE VERSION
* Ubuntu-18.04 Stopped 2
PS C:\Users\Administrator> wsl --export Ubuntu-18.04 h:\wslubuntu\wsl-ubuntu18.04.tar
PS C:\Users\Administrator> wsl --unregister Ubuntu-18.04
正在注销...
PS C:\Users\Administrator> wsl --import Ubuntu-18.04 h:\wslubuntu\wsl-ubuntu18.04 h:\wslubuntu\wsl-ubuntu18.04.tar --version 2
linux笔记(2):vscode插件remote WSL远程使用交叉编译工具链(全志D1-H)
本人linux还没入门,这个只是学习笔记,方便自己查阅。有不对的地方,请大家不吝赐教。
这里使用linux自带的gcc编译器做练习,演示,学习,当然我们的最终目标是编译东山哪吒开发板(D1-H)app应用程序。
1.前期准备
1.1 Windows有对WSL文件读写的权限
从windows的资源浏览器进入ubuntu-18.04的虚拟硬盘:地址栏输入 ==\\wsl$==
然后新建一个文件夹:
在文件夹里面新建一个txt文件。如果成功,说明具备读写权限。这样我们可以非常方便的操作linux的文件。
我的记性差,老忘记linux命令,加上懒,键盘输入不够快,在linux操作非常痛苦。
1.2 WSL的C语言编译环境已经搭建完毕
这里需要的是gcc编译器,make。
2.在windows的vscode安装remoteWSL插件
在vscode的插件管理中心搜索wsl(我这里已经安装好,所以没有安装的按键):
安装完毕后,在第一步的刚刚新建的文件夹 test 里面再新建一个文件夹,把我的测试代码(见文章底部)放进去。
3.从ubuntu启动windows端的vscode
在ubuntu进入 ==/home/hwd/test/hello2==,并输入命令(code 和小数点中间有空格):
code .
此时,windows端会自动开启一个vscode应用:
4.使用vscode编译ubuntu端的c文件
我们看看《hello2》文件夹里面的文件:
4.1 在《tasks.json》指定可视化make命令
我还没有习惯使用命令行编译程序,非常渴望有可视化的编译工具,比较依赖鼠标。
vscode会根据工程目录下的文件夹 ==.vscode== 里面的 文件 ==tasks.json== 生成可视化命令。这里的 ==tasks.json== 非常简单:
{
"tasks": [
{
"type": "shell",//任务类型
"label": "make",//任务名称(在vscode看到的名称)
"command": "make",//命令行:编译器(可执行文件)的路径
}
],
"version": "2.0.0"
}
功能等同于下面的命令make:
4.2编写Makefile文件
这里用一个最简单的Makefile文件:
CROSS_COMPILE = /usr/bin/
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
test : main.c
$(CC) -o test main.c
4.3 开始编译
测试helloword(应该是helloworld),反正韦东山老师的例程是这样的:
#include <stdio.h>
int main(int argc, char* argv[])
{
printf("hello2word!\n");
return 0;
}
4.3.1 打开《终端->运行任务》
4.3.2 点击 make
第一次会弹出一个窗口,选择“从不扫描此任务的任务输出”,下次就不会弹出这个窗口:
此时,如果c代码没有错误,就会正常输出:
根据提示,按任意键关闭终端。
4.3.3 在ubuntu测试刚才编译后的文件
4.3.4 修改一下源码,重复上面的流程,确认编译有效
改动一下打印输出:
printf("hello2word!123\n");
再次编译,运行:
5. 使用D1-H的交叉编译工具链测试
把Makefile的CROSS_COMPILE改成交叉编译工具链的路径:
CROSS_COMPILE = /home/hwd/eLinuxCore_dongshannezhastu/toolchain/riscv64-glibc-gcc-thead_20200702/bin/riscv64-unknown-linux-gnu-
保存,点击 ==终端->运行任务->make== ,编译后,这个文件应该是无法在pc上面运行的,我们使用file命令查看一下信息:
root@SK-JNTINRTMRDZW:/home/hwd/test/hello# file test
test: ELF 64-bit LSB executable, UCB RISC-V, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-riscv64xthead-lp64d.so.1, for GNU/Linux 4.15.0, with debug_info, not stripped
root@SK-JNTINRTMRDZW:/home/hwd/test/hello#
编译完成后,vscode界面的终端就是ubuntu的终端:
这个程序要做开发板上面运行,具体运行过程参考下篇文章《linux笔记(3):东山哪吒STU开发板(全志D-1H)开箱初体验helloworld》。
6.设置快捷键启动运行任务
现在我们测试一下,按下 ==Ctrl+ F8==:
7.测试源码链接
链接:百度网盘 请输入提取码
提取码:f0ho
linux笔记(3):东山哪吒STU开发板(全志D-1H)开箱初体验helloworld
@[TOC]
双11下单后,经过多日的等待,终于在昨天下午收到了开发板。在等待的过程中,看了一下文档和B站东山老师的视频,制作了tf(SD)启动系统。之前也安装过全志的USB驱动,串口芯片CH9102的驱动也不用安装(估计是windows系统自带驱动)。上电后,直接使用《MobaXterm_Personal_20.5.exe》观察输出。
1.开发板上电观察串口
我的板子已经焊接了nand flash,不用插SD卡也可以启动。如果插了SD卡,优先启动SD卡系统。
1.1 从nand flash启动
不插入SD卡,上电就从nand flash 启动,好多信息,现在还看不懂:
1.2 从SD卡启动
插上SD卡,就会优先启动SD卡系统:
2.上传文件到开发板
开发手册介绍了4种连接开发板的方法:
- tftp
- nfs
- 使用FileZilla软件通过ssh连接
- adb(Android Debug Bridge)
我使用前面2种都没有成功。第三种是最方便的,只要修改一下配置文件 ==/etc/ssh/sshd_config==,直接在windows通过鼠标操作就可以完成。
使用vim修改:
>vim /etc/ssh/sshd_config
PermitRootLogin
prohibit-password
改为:
PermitRootLogin yes
PermitEmptyPasswords
no
改为:
PermitEmptyPasswords yes
然后 保存,重启开发板就可以了。
2.1 使用FileZilla软件连接开发板
贴一个《嵌入式Linux应用开发完全手册V5.1_D1H开发板.pdf》上面的图:
先查看开发板的ip(开发板已经插上网上,和windows处于同一个局域网):
输入:
ifconfig
回车:
然后就可以连上了,此时就可以通过拖拽的方式把文件上传到开发板。
这个 ==test==文件是上一篇文章《linux笔记(2):vscode插件remote WSL远程使用交叉编译工具链(全志D1-H)》使用交叉编译工具链编译好的hello程序。
直接运行会出错,要修改一下权限(+x 表示允许用户执行):
# ./test
-sh: ./test: Permission denied
# chmod +x test
# ./test
helloword!
2.2 使用ADB软件
在官网下载ADB软件:https://android-sdk.en.softonic.com/download。
解压后可以直接使用,我只是测试一下,按照网友的介绍,要添加环境变量PATH,我直接使用绝对路径操作。
解压后的路径 ==E:\platform-tools\adb.exe== :
测试一下上传 《1.txt》文件:
PS C:\Users\Administrator> E:\platform-tools\adb.exe version
Android Debug Bridge version 1.0.41
Version 33.0.3-8952118
Installed as E:\platform-tools\adb.exe
PS C:\Users\Administrator> E:\platform-tools\adb.exe devices
* daemon not running; starting now at tcp:5037
* daemon started successfully
List of devices attached
0402101560 device
PS C:\Users\Administrator> E:\platform-tools\adb.exe push D:\nfs\1.txt /root
D:\nfs\1.txt: 1 file pushed, 0 skipped. 0.0 MB/s (10 bytes in 0.048s)
体验结束,下面开始app的学习。
linux笔记(4):东山哪吒开发板(D1-H)测试gpio点亮LED
@[TOC]
参考文档:
1.作者:eydwyz,文章:《用Rust探索RISC-V主板D1之GPIO》
2.全志官方文档:https://open.allwinnertech.com/#/doc?menuID=2&projectId=264
1.控制gpio电平高低的流程
1.1 选PB2控制LED,对应的编号是GPIO34
1.2 进入目录 /sys/class/gpio
cd /sys/class/gpio
查看目录内容:
> ls -l
total 0
--w------- 1 root root 4096 Jan 1 00:00 export
lrwxrwxrwx 1 root root 0 Jan 1 00:00 gpiochip0 -> ../../devi ces/platform/soc@3000000/2000000.pinctrl/gpio/gpiochip0
--w------- 1 root root 4096 Jan 1 00:00 unexport
1.3 生成gpio34目录
> echo 34 > export
> ls
export gpio34 gpiochip0 unexport
1.4 进入gpio34目录
> cd gpio34
> ls
active_low edge uevent
device power value
direction subsystem waiting_for_supplier
1.5 设置IO方向为输出
> echo "out" > direction //控制gpio变为输出功能
1.6 控制gpio34(PB2)电平高低
> echo 1 > value //在output模式下,输出低电平
> echo 0 > value //在output模式下,输出高电平
附录:linux的GPIO编号和D1-H的IO对应关系
首先要挂载调试工具debugfs:
mount -t debugfs none /sys/kernel/debug
然后就可以通过下面的命令获取这个表格:
cat /sys/kernel/debug/pinctrl/2000000.pinctrl/pins
pin 32 (PB0)
pin 33 (PB1)
pin 34 (PB2)
pin 35 (PB3)
pin 36 (PB4)
pin 37 (PB5)
pin 38 (PB6)
pin 39 (PB7)
pin 40 (PB8)
pin 41 (PB9)
pin 42 (PB10)
pin 43 (PB11)
pin 44 (PB12)
pin 64 (PC0)
pin 65 (PC1)
pin 66 (PC2)
pin 67 (PC3)
pin 68 (PC4)
pin 69 (PC5)
pin 70 (PC6)
pin 71 (PC7)
pin 96 (PD0)
pin 97 (PD1)
pin 98 (PD2)
pin 99 (PD3)
pin 100 (PD4)
pin 101 (PD5)
pin 102 (PD6)
pin 103 (PD7)
pin 104 (PD8)
pin 105 (PD9)
pin 106 (PD10)
pin 107 (PD11)
pin 108 (PD12)
pin 109 (PD13)
pin 110 (PD14)
pin 111 (PD15)
pin 112 (PD16)
pin 113 (PD17)
pin 114 (PD18)
pin 115 (PD19)
pin 116 (PD20)
pin 117 (PD21)
pin 118 (PD22)
pin 128 (PE0)
pin 129 (PE1)
pin 130 (PE2)
pin 131 (PE3)
pin 132 (PE4)
pin 133 (PE5)
pin 134 (PE6)
pin 135 (PE7)
pin 136 (PE8)
pin 137 (PE9)
pin 138 (PE10)
pin 139 (PE11)
pin 140 (PE12)
pin 141 (PE13)
pin 142 (PE14)
pin 143 (PE15)
pin 144 (PE16)
pin 145 (PE17)
pin 160 (PF0)
pin 161 (PF1)
pin 162 (PF2)
pin 163 (PF3)
pin 164 (PF4)
pin 165 (PF5)
pin 166 (PF6)
pin 192 (PG0)
pin 193 (PG1)
pin 194 (PG2)
pin 195 (PG3)
pin 196 (PG4)
pin 197 (PG5)
pin 198 (PG6)
pin 199 (PG7)
pin 200 (PG8)
pin 201 (PG9)
pin 202 (PG10)
pin 203 (PG11)
pin 204 (PG12)
pin 205 (PG13)
pin 206 (PG14)
pin 207 (PG15)
pin 208 (PG16)
pin 209 (PG17)
pin 210 (PG18)
linux笔记(5):按照东山派的官方教程编译buildroot(东山哪吒,D1-H)踩坑记录
@[TOC]
整个编译的耗时主要是github的下载速度,很多依赖包都需要从github下载。
这里我以东山派的官方教程为主,根据我的实际情况稍作调整,梳理一下编译buildroot流程。
官方教程链接:使用buildroot-SDK编译构建系统
1.编译流程
1.1获取sdk源码
有2个服务器github和gitee,我使用gitee的源。
依次执行命令:
book@virtual-machine:~$ git clone https://gitee.com/weidognshan/buildroot_dongshannezhastu
book@virtual-machine:~$ cd buildroot_dshannezhastu
book@virtual-machine:~/buildroot_dongshannezhastu$ git submodule update --init --recursive
book@virtual-machine:~/buildroot_dongshannezhastu$ git submodule update --recursive --remote
这个步骤还是比较快的,10分钟以内,取决于网速。
1.2 补充:下载riscv64-glibc-gcc-thead_20200702.tar.xz
这个步骤参考后面的问题2.
1.3 补充:安装mtool工具
这个步骤参考后面的问题3.
1.4 安装必要依赖包
sudo apt-get install -y libncurses5-dev u-boot-tools
1.5 编译sdcard 最小系统镜像
book@virtual-machine:~/buildroot_dongshannezhastu$ cd buildroot-awol/
book@virtual-machine:~/buildroot_dongshannezhastu/buildroot-awol$ make BR2_EXTERNAL="../br2lvgl ../br2qt5 ../br2nezhastu" dongshannezhastu_sdcard_core_defconfig
book@virtual-machine:~/buildroot_dongshannezhastu/buildroot-awol$ make
1.6 烧录最小镜像系统到tf(SD)卡
原文档:东山哪吒快速启动
1.6.1 安装烧录工具
1.6.2 格式化SD卡
1.6.3 烧录镜像到sd卡
1.7 运行系统
把SD卡插到开发板,上电,检查一下是不是最新编译的:
我对比一下原来的一张烧录官方提供的image的文件日期:
2.问题踩坑记录
问题1:make指令不执行
root@SK-JNTINRTMRDZW:/home/hwd/buildroot_dongshannezhastu/buildroot-awol> make
Your PATH contains spaces, TABs, and/or newline (\n) characters.
This doesn't work. Fix you PATH.
support/dependencies/dependencies.mk:27: recipe for target 'dependencies' failed
make: *** [dependencies] Error 1
百度解决方法:《This doesn‘t work. Fix you PATH》
采用这个方法顺利解决(切换环境变量)。
问题2:riscv64-glibc-gcc-thead_20200702.tar.xz File format not recognized
WARNING: no hash file for riscv64-glibc-gcc-thead_20200702.tar.xz
....../riscv64-glibc-gcc-thead_20200702.tar.xz: File format not recognized
tar: This does not look like a tar archive
tar: Exiting with failure status due to previous errors
去到该文件所在目录 ==/home/hwd/buildroot_dongshannezhastu/buildroot-awol/dl/toolchain-external-custom== 看到,文件的大小只有1k,不知道是什么原因导致的。
继续百度搜到《为全志D1/RISCV64设备移植openwrt-22.03系统》,提到要手动下载 ==riscv64-glibc-gcc-thead_20200702.tar.xz==,提供了东山派的官方链接:《快速使用Tina-SDK 指南》:
下载完成后,发现文件名是 ==riscv64-glibc-gcc-thead_20200702tar.xz== :
增加小数点后,不用解压,重新执行make,自动解压成功,往下进行。
问题3: /bin/sh: 1: mcopy: not found
没有安装mtool工具:
apt-get install mtools
重新make,终于完成:
linux笔记(6):东山哪吒D1H测试HDMI显示内置图片-命令行调试
@[TOC]
测试开发板的HDMI输出。
参考文档:全志官方文档。
1.测试流程和结果
测试结果,只显示了约五分之二:
2.测试过程详解
2.1 挂载测试工具
输入命令:
mount -t debugfs none /sys/kernel/debug
查看显示调试节点 ==dispdbg==:
> cd /sys/kernel/debug
> ls
asoc extfrag pwm
bdi fault_around_bytes regmap
block gpio regulator
bluetooth hid sleep_time
clear_warn_once ieee80211 sunxi_leds
clk ion suspend_stats
device_component mmc0 ubi
devices_deferred mmc1 ubifs
dispdbg mtd usb
dma_buf pinctrl wakeup_sources
enc_test pm_qos
进入目录 ==dispdbg==:
> cd dispdbg/
> ls
command dbglvl info name param start
1.2 设置参数
1.2.1设置name
name有3个选项:
- disp0/1/2 – 显示通道
- lcd0/1/2 – LCD
- enhance0/1/2 – 色彩增强模式
- smbl0/1/2 – 背光
目前我还不知道这几个有什么区别,现在选择disp0:
echo disp0 > name
1.2.2选择命令
这里使用的是switch命令:
echo switch > command
官方文档开放的命令有7个:
- switch – 切换显示通道
- blank – 显示开关
- suspend – 显示进入休眠
- resume – 显示从休眠中唤醒
- setbl – 背光调节
- vsync – 消息开关
- getinfo – 查看智能背光的状态
1.2.3 设置命令参数
这个命令的格式是这样的:
echo type mode > param
这里我们选择type = 4,mode = 10。
输入命令:
echo 4 10 > param
每个命令都有自己的参数,switch命令有2个参数:
- type ,HDMI对应 4
typedef enum
{
DISP_OUTPUT_TYPE_NONE = 0,
DISP_OUTPUT_TYPE_LCD = 1,
DISP_OUTPUT_TYPE_TV = 2,
DISP_OUTPUT_TYPE_HDMI = 4,
DISP_OUTPUT_TYPE_VGA = 8,
}disp_output_type;
2.mode,这里我随便选择一个10,对应 DISP_TV_MOD_1080P_60HZ
typedef enum
{
DISP_TV_MOD_480I = 0,
DISP_TV_MOD_576I = 1,
DISP_TV_MOD_480P = 2,
DISP_TV_MOD_576P = 3,
DISP_TV_MOD_720P_50HZ = 4,
DISP_TV_MOD_720P_60HZ = 5,
DISP_TV_MOD_1080I_50HZ = 6,
DISP_TV_MOD_1080I_60HZ = 7,
DISP_TV_MOD_1080P_24HZ = 8,
DISP_TV_MOD_1080P_50HZ = 9,
DISP_TV_MOD_1080P_60HZ = 0xa,
DISP_TV_MOD_1080P_24HZ_3D_FP = 0x17,
DISP_TV_MOD_720P_50HZ_3D_FP = 0x18,
DISP_TV_MOD_720P_60HZ_3D_FP = 0x19,
DISP_TV_MOD_1080P_25HZ = 0x1a,
DISP_TV_MOD_1080P_30HZ = 0x1b,
DISP_TV_MOD_PAL = 0xb,
DISP_TV_MOD_PAL_SVIDEO = 0xc,
DISP_TV_MOD_NTSC = 0xe,
DISP_TV_MOD_NTSC_SVIDEO = 0xf,
DISP_TV_MOD_PAL_M = 0x11,
DISP_TV_MOD_PAL_M_SVIDEO = 0x12,
DISP_TV_MOD_PAL_NC = 0x14,
DISP_TV_MOD_PAL_NC_SVIDEO = 0x15,
DISP_TV_MOD_3840_2160P_30HZ = 0x1c,
DISP_TV_MOD_3840_2160P_25HZ = 0x1d,
DISP_TV_MOD_3840_2160P_24HZ = 0x1e,
DISP_TV_MODE_NUM = 0x1f,
}disp_tv_mode;
1.3 指定显示测试图片
echo 1 > /sys/class/disp/disp/attr/colorbar
1.4开启显示
输入命令:
echo 1 > start
开发板反馈信息:
[ 5059.601019] disp 0, type 4, mode4
[ 5060.623495] [HDMI receive params]: tv mode: 0x4 format:0x1 data bits:0x0 eotf:0x4 cs:0x101 dvi_h dmi:2 range:2 scan:0 aspect_ratio:8
[ 5061.683548] disp_al_manager_apply ouput_type:0
[ 5061.689240] disp_al_hdmi_cfg
[ 5061.802820] HDMI Audio Enable Successfully
[ 5061.807427] [DISP] disp_device_attached_and_enable,line:233:
[ 5061.807432] attached ok, mgr0<-->dev0
[ 5061.818195] [DISP] disp_device_attached_and_enable,line:236:
[ 5061.818205] type:4,mode:4,fmt:yuv444,bits:8bits,eotf:4,cs:257 dvi_hdmi:2, range:2 scan:0 ratio:8
3.还没搞清楚怎么在应用中显示字符
linux笔记(7):东山哪吒D1H使用framebuffer控制HDMI直线
@[TOC]
这部分linux笔记是记录我入门的过程,内容基本都是照着别人的文章,自己操作一遍,重走一次别人走过的路。
参考文章:
1.作者:闪耀大叔,文章《嵌入式Linux入门-Framebuffer应用编程在Linux系统下画个点》。
1.测试流程和结果
1.1 使能HDMI
我前2天想把韦东山老师的《buildroot_dongshannezhastu》工程改成启动时有HDMI输出,结果没有成功。只能先利用上一篇文章的方法启动HDMI《linux笔记(6):东山哪吒D1H测试HDMI显示内置图片-命令行调试》。
1.2 framebuffer操作流程
1.打开设备节点:open("/dev/fb0", O_RDWR)
2.获取LCD参数:ioctl(fd_fb, FBIOGET_VSCREENINFO, &var)
3.映射Framebuffer:mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0)
4.操作Framebuffer
5.取消映射 munmap (fb_base, screen_size)
6.关闭设备节点 close(fd_fb)
1.3 测试结果
在屏幕上描出不同颜色:
2.测试过程详述
2.1 编译源码
把源码fb001 – linux-D1H-test: 东山哪吒开发板(全志D1-H)测试小例程。 - Gitee.com 下载下来,进入工程,直接使用 make 命令编译。
2.2上传可执行文件
我上传应用程序到开发板的步骤是不是太复杂?
2.3修改文件的权限,执行文件
> chmod 777 test
> ./test
1.open /dev/fb0
2.get V Screen INFO
width:800,hight:1280,bits_per_pixel:32
3.get framebuffer base address
fb_base:0xf1f6f000
4.flush screen in different colors
5.draw 30 lines in different colors
3.源码解释
3.1 HDMI使用的颜色格式是ARGB
可以参考这个文章《ARGB与RGB区别及透明度和RGB颜色对照表》。
ARGB从表面看比RGB多了个A,也是一种色彩模式,是在RGB的基础上添加了Alpha(透明度)通道。透明度也是以0到255表示的,所以也是总共有256级,透明是0,不透明是255。
用十六进制的格式来表示ARGB就是:0xAARRGGBB。
东山哪吒开发板的HDMI驱动使用的是ARGB,如果直接使用RGB格式,相当于ARGB的透明格式,显示出来是黑色的。
比如上面的参考文章使用的是RGB格式:
我画30条线使用的30种颜色数据:
举个例子,要正常显示红色(0x00FF0000),要使表示透明度的字节不为0.上面的A=0xFF和A=0x7F都可以正常显示。
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h>
#include <linux/fb.h>
#include <unistd.h>
static int fd_fb;
static struct fb_var_screeninfo var; /* Current var */
static int screen_size;
static unsigned char *fb_base;
static unsigned int line_width;
static unsigned int pixel_width;
void lcd_put_pixel(int x, int y, unsigned int color)
//传入的 color 表示颜色,它的格式永远是 0x00RRGGBB,即 RGB888。
//当 LCD 是 16bpp 时,要把 color 变量中的 R、 G、 B 抽出来再合并成 RGB565 格式。
{
unsigned char *pen_8 = fb_base+y*line_width+x*pixel_width;
//计算(x,y)坐标上像素对应的 Framebuffer 地址。
unsigned short *pen_16;
unsigned int *pen_32;
unsigned int red, green, blue;
pen_16 = (unsigned short *)pen_8;
pen_32 = (unsigned int *)pen_8;
switch (var.bits_per_pixel)
{
//对于 8bpp, color 就不再表示 RBG 三原色了,这涉及调色板的概念, color 是调色板的值。
case 8:
{
*pen_8 = color;
break;
}
case 16:
{
// R5 G6 B5
//先从 color 变量中把 R、 G、 B 抽出来。
red = (color >> 16) & 0xff;
green = (color >> 8) & 0xff;
blue = (color >> 0) & 0xff;
//把 red、 green、 blue 这三种 8 位颜色值,根据 RGB565 的格式,
//只保留 red 中的高 5 位、 green 中的高 6 位、 blue 中的高 5 位,
//组合成一个新的 16 位颜色值。
color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
//把新的 16 位颜色值写入 Framebuffer
*pen_16 = color;
break;
}
case 32:
{
//对于 32bpp,颜色格式跟 color 参数一致,可以直接写入Framebuffer
*pen_32 = color;
break;
}
default:
{
printf("can't surport %dbpp\n",var.bits_per_pixel);
break;
}
}
}
void blushScreen2(unsigned int color)
{// 这里只考虑24色,也就是HDMI的情况
unsigned int * p32=(unsigned int *)fb_base;
unsigned int h,w;
for(h=0;h<var.yres;h++)
for(w=0;w<var.xres;w++){
*p32= color;
p32++;
}
}
int main(int argc,int **argv)
{
int i;
printf("1.open /dev/fb0\n");
fd_fb = open("/dev/fb0", O_RDWR);
if (fd_fb < 0)
{
printf("can't open /dev/fb0\n");
return -1;
}
printf("2.get V Screen INFO\n");
if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))
{
printf("can't get var\n");
return -1;
}
line_width = var.xres * var.bits_per_pixel / 8;
pixel_width = var.bits_per_pixel / 8;
screen_size = var.xres * var.yres * var.bits_per_pixel / 8;
printf("width:%d,hight:%d,bits_per_pixel:%d\n",var.xres,var.yres,var.bits_per_pixel);
printf("3.get framebuffer base address\n");
fb_base = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
if (fb_base == (unsigned char *)-1)
{
printf("can't mmap\n");
return -1;
}else{
printf("fb_base:0x%8x\n",fb_base);
}
unsigned char colorData[10]={0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xff};
unsigned int cData[30] = {0xFFFF0000,0xFF00FF00,0xFF0000FF,
0xFFFFFF00,0xFFFF00FF,0xFF00FFFF,
0xFF7F7F7F,0xFF007F7F,0xFF7F007F,0xFF7F7F00,// 0-9 FF开头
0x7FFF0000,0x7F00FF00,0x7F0000FF,
0x7FFFFF00,0x7FFF00FF,0x7F00FFFF,
0x7F7F7F7F,0x7F007F7F,0x7F7F007F,0x7F7F7F00,// 10-19 7F开头
0x00FF0000,0x0000FF00,0x000000FF,
0x00FFFF00,0x00FF00FF,0x0000FFFF,
0x007F7F7F,0x00007F7F,0x007F007F,0x007F7F00};// 20-29 00开头
printf("4.flush screen in different colors\n");
for(i = 0;i<10;i++)
{
memset(fb_base,colorData[i],screen_size );
sleep(1);//usleep(100*1000);
}
printf("5.draw 30 lines in different colors\n");
for (int j = 0; j < 30;j++){
for (i = 0; i < 100; i++) {
lcd_put_pixel(var.xres/3+i, var.yres/4+20*j+0, cData[j] );
lcd_put_pixel(var.xres/3+i, var.yres/4+20*j+1, cData[j] );
lcd_put_pixel(var.xres/3+i, var.yres/4+20*j+2, cData[j] );
lcd_put_pixel(var.xres/3+i, var.yres/4+20*j+3, cData[j] );
}
}
munmap (fb_base, screen_size);
close(fd_fb);
return 0;
}
4.源码工程链接
源码工程fb001
可以控制显示后,下一步就是移植 ==lvgl== ,请浏览下一篇文章《linux笔记(8):东山哪吒D1H移植lvgl(HDMI输出)》。
linux笔记(8):东山哪吒D1H移植lvgl(HDMI输出)
@[TOC]
我买的东山哪吒开发板是丐中丐板,核心板+基础底板,所以就先用一个闲置的24寸显示器,通过HDMI显示,现在没有输入设备,只能显示。
照这韦东山老师的教程移植了一遍。看看效果(使用了800 x 480 的区域):
韦东山老师出品:《【嵌入式Linux应用开发】移植LVGL到Linux开发板》
这里梳理一下流程和问题点。
1. 下载,修改,编译源码
1.1下载源码
1.1.1新建一个lvgl
目录,在该目录下下载源码
book@100ask:~/lvgl$ git clone https://github.com/lvgl/lvgl.git
book@100ask:~/lvgl$ git clone https://github.com/lvgl/lv_drivers.git
book@100ask:~/lvgl$ git clone https://github.com/lvgl/lv_demos.git
book@100ask:~/lvgl$ git clone https://github.com/lvgl/lv_port_linux_frame_buffer.git
1.1.2 在lvgl
目录下再建一个myspace/lvgl_demo
目录,把参与编译的文件拷贝到本目录
韦东山老师没有使用到lv_demos
,我们是需要lv_demos
的,所以我们的目录下,应该有这些内容:
这4个文件的链接:《lvgl_demo》linux-D1H-test: 东山哪吒开发板(全志D1-H)测试小例程。 - Gitee.com.
1.2 修改源码
韦东山老师的教程很详细的说明了如何修改,虽然有一些行号对应不上,但是不影响操作。还有因为我的开发板没有输入设备,我把main()
函数中的相关代码注释了。
Makefile
修改2个地方:
- 指定编译器
4 CC = /home/hwd/eLinuxCore_dongshannezhastu/toolchain/riscv64-glibc-gcc-thead_20200702/bin/riscv64-unknown-linux-gnu-gcc
这里不能用 CC ?= xxx.
CC ?= xxx
表示如果前面没有指定编译器,现在才指定;如果前面已经有了指定了 CC
的值,这里就无效。
我没有去掉 ?
之前,编译出来的可执行文件运行的结果:
> ./demo
./demo: line 1:ELF: not found
./demo: line 26: syntax error: unexpected word (expecting ")")
实际上是使用ubuntu自带的编译器 /usr/bin/gcc
编译出来的,无法在开发板运行。
2. 注释掉鼠标相关c文件,不参与编译
19 #CSRCS +=$(LVGL_DIR)/mouse_cursor_icon.c
1.3编译源码
进入目录/home/hwd/test/lvgl/workspace/lvgl_demo
,直接make:
/home/hwd/test/lvgl/workspace/lvgl_demo> make
顺利的话就会生成可执行文件 demo
.
2.拷贝到东山哪吒开发板运行
我这里运行demo
之前,也要先手动开启HDMI。
拷贝到开发板,修改 demo
的可执行权限,再运行:
> chmod 777 demo
> ./demo
[ 4654.153462] [SNDCODEC][sunxi_check_hs_detect_status][191]:plugin --> switch:1
[23511.007245] sunxi_set_cur_vol_work()394 WARN: get power supply failed
[23511.095303] android_work: sent uevent USB_STATE=CONNECTED
[23511.156216] configfs-gadget gadget: high-speed config #1: c
[23511.164595] android_work: sent uevent USB_STATE=CONFIGURED
运行结果如文章开头的图片。
3.已移植好的源码链接
需要改动的4个文件的链接:《lvgl_demo》linux-D1H-test: 东山哪吒开发板(全志D1-H)测试小例程。 - Gitee.com.