-
2022-03-12 19:35:58
基于正点原子Linux开发板(ALIENTEK I.MX6U ALPHA V2.2)的个人自学记录
硬件环境
正点原子Linux开发板(ALIENTEK I.MX6U ALPHA V2.2) 底板+核心板(EMMC版)+7寸RGB屏1024*600'
软件环境
VirtualBox Ubuntu
学习计划
开始于2022/03/12 第一步,看完所有的视频教程并做好记录
正点原子Linux视频教程_B站
正点原子资料下载中心_opendev视频教程目录
视频 选集 时长 时长 【第一期】手把手教你学Linux之Ubuntu入门篇 20 8小时58分 8秒 0天 8小时58分 8秒 【第二期】手把手教你学Linux之ARM(MX6U)裸机篇 76 39小时57分 2秒 1天15小时57分 2秒 【第三期】手把手教你学Linux之系统移植和根文件系统构建 56 29小时23分22秒 1天 5小时23分22秒 【第四期】手把手教你学 Linux之驱动开发篇 146 69小时44分38秒 2天21小时44分38秒 一共298集视频,总时长148小时 3分10秒,即6天 4小时 3分10秒
正点原子【第一期】手把手教你学Linux之Ubuntu入门篇
视频 选集 时间 P1 第1讲 开发电脑的选择 22:35 P2 第2讲 VMware软件安装和虚拟机创建 29:36 P3 第3讲 Ubuntu操作系统的安装 32:13 P4 第4讲 Ubuntu初次体验 27:25 P5 第5讲 虚拟机连接USB设备 09:21 P6 第6.1讲 Ubuntu终端操作与Shell命令1 30:41 P7 第6.2讲 Ubuntu终端操作与Shell命令2 29:41 P8 第7讲 Ubuntu软件安装 31:15 P9 第8讲 Ubuntu文件系统结构 18:21 P10 第9讲 Ubuntu下的磁盘管理 36:17 P11 第10讲 Ubuntu下压缩与解压缩 33:58 P12 第11讲 Ubuntu用户与用户组 22:50 P13 第12讲 Ubuntu文件权限管理 23:13 P14 第13讲 Linux连接文件 20:33 P15 第14讲 vim编辑器 22:00 P16 第15讲 Linux C编程 23:55 P17 第16讲 make工具和Makefile的引入 28:12 P18 第17讲 Makefile基本语法 33:47 P19 第18讲 shell脚本入门 33:11 P20 第19讲 shell脚本条件判断、函数和循环 29:04 正点原子【第二期】手把手教你学Linux之ARM(MX6U)裸机篇
视频 选集 时间 P1 第1.1讲 开发环境搭建 28:15 P2 第1.2讲 交叉编译器的安装 13:44 P3 第2讲 vscode软件的安装与使用 34:39 P4 第3讲 I.MX6U-ALPHA开发板简介 26:08 P5 第5讲 I.MX6U芯片简介 35:52 P6 第6.1讲 汇编LED驱动实验-原理分析 35:31 P7 第6.2讲 汇编LED驱动实验-汇编基本语法 28:07 P8 第6.3讲 汇编LED驱动实验-驱动编写 30:55 P9 第6.4讲 汇编LED驱动实验-编译程序 22:45 P10 第6.5讲 汇编LED驱动实验-烧写bin文件到SD卡中并运行 27:43 P11 第7.1讲 IMX启动方式-启动设备的选择 36:06 P12 第7.2讲 IMX启动方式-IVT表和BootData详解 31:17 P13 第7.3讲 IMX启动方式-DCD数据详解 20:40 P14 第8.1讲 C语言版本LED驱动实验-实验原理分析 26:53 P15 第8.2讲 C语言版本LED驱动实验-程序编写与验证 39:57 P16 第9.1讲 模仿STM32驱动开发实验-实验程序编写 31:43 P17 第9.2讲 模仿STM32驱动开发实验-主函数编写与下载验证 18:10 P18 第10.1讲 NXP官方SDK使用实验-SDK移植 25:42 P19 第10.2讲 NXP官方SDK使用实验-程序编写验证 36:59 P20 第11.1讲 BSP工程管理实验-工程整理与程序编写 31:16 P21 第11.2讲 BSP工程管理实验-编写测试通用Makefile 34:04 P22 第12讲 蜂鸣器实验 25:29 P23 第13.1讲 按键输入实验-实验程序编写 32:42 P24 第13.2讲 按键输入实验-驱动验证与调试 14:26 P25 第13.3讲 按键输入实验-通用GPIO驱动编写与验证 24:43 P26 第14.1讲 主频和时钟配置实验-时钟树详解 38:06 P27 第14.2讲 主频和时钟配置实验-主频修改 41:16 P28 第14.3讲 主频和时钟配置实验-8路PLL和8路PFD时钟设置 20:02 P29 第14.4讲 主频和时钟配置实验-其他时钟源设置 44:10 P30 第15.1讲 GPIO中断实验-Cortex-A中断原理 41:50 P31 第15.2讲 GPIO中断实验-6U中断向量表的编写 35:05 P32 第15.3讲 GPIO中断实验-6U复位中断服务函数的编写 23:13 P33 第15.4讲 GPIO中断实验-IRQ中断服务函数详解 28:04 P34 第15.5讲 GPIO中断实验-通用中断驱动编写 43:16 P35 第15.6讲 GPIO中断实验-向GPIO驱动添加中断处理函数 29:55 P36 第15.7讲 GPIO中断实验-编写按键中断驱动 30:12 P37 第16.1讲 EPIT定时器实验-EPIT原理详解 23:43 P38 第16.2讲 EPIT定时器实验-实验程序编写与验证 28:38 P39 第17讲 定时器按键消抖实验 32:24 P40 第18.1讲 高精度延时实验-GPT定时器原理 32:31 P41 第18.2讲 高精度延时实验-实验代码编写与测试 37:33 P42 第19.1讲 串口实验-串口原理详解 36:59 P43 第19.2讲 串口实验-串口驱动实验编写与验证1 29:55 P44 第19.3讲 串口实验-串口驱动实验编写与验证2 30:01 P45 第19.4讲 串口实验-printf格式化函数移植与测试 29:10 P46 第20.1讲 DDR3实验-RAM发展历史简介 41:47 P47 第20.2讲 DDR3实验-DDR3重要时间参数、时钟配置与原理图简析 27:53 P48 第20.3讲 DDR3实验-DDR3初始化、校准、超频测试 38:20 P49 第21.1讲 RGBLCD实验-LCD显示原理详解 41:18 P50 第21.2讲 RGBLCD实验-LCD时序与时间参数 28:52 P51 第21.3讲 RGBLCD实验-6ULL LCDIF接口寄存器详解 36:14 P52 第21.4讲 RGBLCD实验-6ULL像素时钟配置详解 24:34 P53 第21.5讲 RGBLCD实验-LCDID读取以及IO初始化程序编写 45:12 P54 第21.6讲 RGBLCD实验-LCD时间参数和像素时钟设置程序编写 44:40 P55 第21.7讲 RGBLCD实验-LCDIF控制器接口初始化程序编写 31:31 P56 第21.8讲 RGBLCD实验-LCDIF驱动以及API函数测试 28:56 P57 第22.1讲 RTC实验-6U内部RTC详解 28:29 P58 第22.2讲 RTC实验-驱动编写与测试 44:21 P59 第22.3讲 RTC实验-时间错误问题调试 22:06 P60 第23.1讲 I2C实验-I2C协议和6U的I2C控制器详解 36:46 P61 第23.2讲 I2C实验-AP3216C简介与程序编写 27:19 P62 第23.3讲 I2C实验-I2C主机控制器驱动程序编写1 38:36 P63 第23.4讲 I2C实验-I2C主机控制器驱动程序编写2 33:21 P64 第23.5讲 I2C实验-AP3216C程序编写 21:20 P65 第23.6讲 I2C实验-AP3216C程序调试及bug解决 21:00 P66 第24.1讲 SPI实验-SPI以及ICM20608详解 37:25 P67 第24.2讲 SPI实验-6ULL SPI控制器寄存器详解 35:26 P68 第24.3讲 SPI实验-6ULL SPI控制器驱动程序编写 33:39 P69 第24.4讲 SPI实验-ICM20608驱动程序编写 37:03 P70 第24.5讲 SPI实验-ICM20608实际测量值计算与6ULL硬件浮点的开启 28:33 P71 第25.1讲 多点电容触摸屏实验-电容触摸屏与FT系列触摸芯片详解 33:15 P72 第25.2讲 多点电容触摸屏实验-电容触摸屏幕驱动编写1 35:52 P73 第25.3讲 多点电容触摸屏实验-电容触摸屏幕驱动编写2 31:05 P74 第25.4讲 多点电容触摸屏实验-电容触摸驱动测试 16:01 P75 第26.1讲 PWM背光实验-6ULL PWM详解 33:07 P76 第26.2讲 PWM背光实验-PWM背光驱动程序编写 43:12 正点原子【第三期】手把手教你学Linux之系统移植和根文件系统构建
视频 选集 时间 P1 第1.1讲 正点原子官方系统镜像烧写实验-Windows下OTG烧写 23:23 P2 第1.2讲 正点原子官方系统镜像烧写实验-Ubuntu下脚本烧写 29:04 P3 第2.1讲 正点原子官方Uboot编译-什么是uboot 29:23 P4 第2.2讲 正点原子官方Uboot编译-uboot初次编译 30:08 P5 第3.1讲 Uboot命令使用-uboot启动log信息分析与基础命令使用 33:25 P6 第3.2讲 Uboot命令使用-uboot内存与网络命令 46:10 P7 第3.3讲 Uboot命令使用-MMC和文件操作命令 25:04 P8 第3.4讲 Uboot命令使用-NAND和BOOT命令 34:10 P9 第4讲 Uboot源码目录分析 37:19 P10 第5.1讲 Uboot顶层Makefile分析-vscode工程创建 23:20 P11 第5.2讲 Uboot顶层Makefile分析-Makefile前期所作的内容 42:51 P12 第5.3讲 Uboot顶层Makefile分析-make xxx_defconfig过程 43:53 P13 第5.4讲 Uboot顶层Makefile分析-make过程 28:48 P14 第6.1讲 Uboot启动流程详解-Uboot链接脚本到_start的处理过程 33:36 P15 第6.2讲 Uboot启动流程详解-lowlevel_init、s_init及_main函数执行过程 35:50 P16 第6.3讲 Uboot启动流程详解-board_init_f函数执行过程 43:11 P17 第6.4讲 Uboot启动流程详解-uboot内存分配 42:39 P18 第6.5讲 Uboot启动流程详解-uboot代码重定位 47:49 P19 第6.6讲 Uboot启动流程详解-中断向量表重定位与board_init_r函数执行过程 25:46 P20 第6.7讲 Uboot启动流程详解-main_loop到cmd_process处理过程 38:51 P21 第6.8讲 Uboot启动流程详解-bootz启动Linux过程详解1 26:40 P22 第6.9讲 Uboot启动流程详解-bootz启动Linux过程详解2 31:02 P23 第7.1讲 Uboot移植实验-NXP官方开发板uboot编译与测试 35:31 P24 第7.2讲 Uboot移植实验-在Uboot中添加ALPHA开发板 38:43 P25 第7.3讲 Uboot移植实验-Uboot LCD驱动修改 28:01 P26 第7.4讲 Uboot移植实验-Uboot 网络驱动原理简介 18:18 P27 第7.5讲 Uboot移植实验-Uboot 网络驱动修改 37:38 P28 第7.6讲 Uboot移植实验-Uboot启动Linux内核测试 17:57 P29 第7.7讲 Uboot移植实验-mx6ull_alientek_emmc.h文件详解 30:54 P30 第7.8讲 Uboot移植实验-bootcmd和bootargs详解 33:59 P31 第7.9讲 Uboot移植实验-DDR初始化参数修改 18:00 P32 第8.1讲 Uboot图形化界面配置-图形化配置操作 30:53 P33 第8.2讲 Uboot图形化界面配置-Kconfig语法简介 36:57 P34 第9讲 正点原子官方Linux内核编译与体验 39:03 P35 第10讲 Linux内核源码目录分析 21:17 P36 第11.1讲 Linux内核顶层Makefile分析-make xxx_defconfig和make过程 38:01 P37 第11.2讲 Linux内核顶层Makefile分析-built-in.o和zImage生成过程简介 17:42 P38 第12.1讲 Linux内核启动流程简介-第一阶段汇编流程简介 23:37 P39 第12.2讲 Linux内核启动流程简介-第二阶段start_kernel简介 26:06 P40 第13.1讲 Linux内核移植-向NXP官方Linux内核添加ALPHA开发板 40:29 P41 第13.2讲 Linux内核移植-主频设置以及超频测试 31:01 P42 第13.3讲 Linux内核移植-网络驱动修改 38:08 P43 第14.1讲 根文件系统构建-根文件系统简介 28:10 P44 第14.2讲 根文件系统构建-busybox配置、中文支持与编译 36:47 P45 第14.3讲 根文件系统构建-根文件系统lib库文件添加与初步测试 36:54 P46 第14.4讲 根文件系统构建-根文件系统完善 28:41 P47 第14.5讲 根文件系统构建-根文件系统其他功能测试 27:01 P48 第15.1讲 MfgTool烧写工具详解-MfgTool工具详解(上) 17:49 P49 第15.2讲 MfgTool烧写工具详解-MfgTool工具详解(下) 25:41 P50 第15.3讲 MfgTool烧写工具详解-烧写自制的系统文件 28:33 P51 第15.4讲 MfgTool烧写工具详解-定制化mfgtool工具 29:58 P52 第16.1讲 Uboot移植实验(NAND版本)-向Uboot中添加NAND版开发板-补录 30:12 P53 第16.2讲 Uboot移植实验(NAND版本)-Uboot中LCD及网络驱动修改-补录 31:29 P54 第16.3讲 Uboot移植实验(NAND版本)-Uboot启动内核测试与DDR初始化代码修改-补录 27:15 P55 第17讲 Linux内核移植(NAND版本)-补录 21:16 P56 第18讲 MfgTool烧写(NAND版本)-补录 38:59 正点原子【第四期】手把手教你学 Linux之驱动开发篇
视频 选集 时间 P1 第1讲 Linux驱动开发与裸机开发区别 20:52 P2 第2讲 字符设备驱动开发基础实验 21:55 P3 第3.1讲 我的第一个Linux驱动-字符设备驱动框架 36:14 P4 第3.2讲 我的第一个Linux驱动-驱动模块加载与卸载实验 31:57 P5 第3.3讲 我的第一个Linux驱动-字符设备驱动框架搭建实验 39:01 P6 第3.4讲 我的第一个Linux驱动-应用程序编写 36:32 P7 第3.5讲 我的第一个Linux驱动-完善chrdevbase驱动 32:41 P8 第4.1讲 Linux LED灯驱动实验(直接操作寄存器)-地址映射 20:34 P9 第4.2讲 Linux LED灯驱动实验(直接操作寄存器)-驱动框架搭建以及网络问题解决方法 35:14 P10 第4.3讲 Linux LED灯驱动实验(直接操作寄存器)-LED灯初始化 34:02 P11 第4.4讲 Linux LED灯驱动实验(直接操作寄存器)-完善驱动与应用程序编写测试 25:07 P12 第5.1讲 Linux新字符设备驱动实验-新驱动框架的搭建 39:57 P13 第5.2讲 Linux新字符设备驱动实验-完善驱动 26:57 P14 第5.3讲 Linux新字符设备驱动实验-自动创建设备节点 31:32 P15 第5.4讲 Linux新字符设备驱动实验-私有数据以及goto对于错误的处理方法 34:29 P16 第6.1讲 Linux设备树详解-什么是设备树? 28:17 P17 第6.2讲 Linux设备树详解-DTS文件以及组织形式 41:40 P18 第6.3讲 Linux设备树详解-6ULL设备树节点信息 35:56 P19 第6.4讲 Linux设备树详解-设备树在根文件系统中的体现以及添加自定义节点 38:42 P20 第6.5讲 Linux设备树详解-设备树特殊节点 23:58 P21 第6.6讲 Linux设备树详解-设备树中的标准属性 27:56 P22 第6.7讲 Linux设备树详解-根节点下的compatible属性作用 27:27 P23 第6.8讲 Linux设备树详解-绑定文档以及OF函数 42:35 P24 第6.9讲 Linux设备树详解-OF函数操作实验 50:18 P25 第7.1讲 设备树下的LED驱动试验-实验驱动框架搭建 38:52 P26 第7.2讲 设备树下的LED驱动试验-实验驱动完善 45:17 P27 第8.1讲 pinctrl和gpio子系统试验-pincrl子系统详解 40:57 P28 第8.2讲 pinctrl和gpio子系统试验-pincrl子系统驱动分析 35:50 P29 第8.3讲 pinctrl和gpio子系统试验-gpio子系统详解和驱动分析 42:25 P30 第8.4讲 pinctrl和gpio子系统试验-设备树节点创建与驱动框架编写 47:11 P31 第8.5讲 pinctrl和gpio子系统试验-完善驱动 35:21 P32 第9讲 beep蜂鸣器实验 42:24 P33 第10.1讲 Linux并发与竞争试验-并发与竞争基础概念与原子操作 30:31 P34 第10.2讲 Linux并发与竞争试验-自旋锁、信号量与互斥体 30:56 P35 第10.3讲 Linux并发与竞争试验-原子操作实验 27:28 P36 第10.4讲 Linux并发与竞争试验-自旋锁、信号量以及互斥体操作实验 34:45 P37 第11讲 Linux按键输入试验 40:03 P38 第12.1讲 Linux内核定时器实验-内核时间管理简介 25:44 P39 第12.2讲 Linux内核定时器实验-内核定时器简介以及实验编写 40:04 P40 第12.3讲 Linux内核定时器实验-使用ioctl控制定时器 42:17 P41 第13.1讲 Linux中断实验-Linux内核中断框架简介 22:28 P42 第13.2讲 Linux中断实验-Linux内核中断上半部和下半部 25:07 P43 第13.3讲 Linux中断实验-如何在设备树中描述中断信息 20:49 P44 第13.4讲 Linux中断实验-按键中断实验驱动编写(上) 22:25 P45 第13.5讲 Linux中断实验-按键中断实验驱动编写(下) 27:45 P46 第13.6讲 Linux中断实验-使用定时器实现按键消抖处理 31:34 P47 第13.7讲 Linux中断实验-中断下半部处理实验 26:07 P48 第14.1讲 Linux阻塞和非阻塞IO实验-阻塞与非阻塞简介 39:29 P49 第14.2讲 Linux阻塞和非阻塞IO实验-阻塞IO实验 29:54 P50 第14.3讲 Linux阻塞和非阻塞IO实验-非阻塞IO实验 29:49 P51 第15.1讲 Linux异步通知实验-异步通知简介 26:49 P52 第15.2讲 Linux异步通知实验-驱动程序编写 40:17 P53 第16.1讲 platform设备驱动实验-驱动的分离与分层 23:24 P54 第16.2讲 platform设备驱动实验-驱动、总线和设备 32:42 P55 第16.3讲 platform设备驱动实验-platform总线简介1 31:09 P56 第16.4讲 platform设备驱动实验-platform总线简介2 19:54 P57 第16.5讲 platform设备驱动实验-无设备树platform设备注册实验 31:33 P58 第16.6讲 platform设备驱动实验-无设备树platform驱动注册实验 39:06 P59 第16.7讲 platform设备驱动实验-设备树下的platform驱动注册实验 34:22 P60 第17.1讲 Linux自带LED驱动实验-linux自带LED驱动简析 29:13 P61 第17.2讲 Linux自带LED驱动实验-设备树节点创建与测试 18:28 P62 第18.1讲 Linux杂项(MISC)驱动实验-MISC驱动框架简介 27:28 P63 第18.2讲 Linux杂项(MISC)驱动实验-misc蜂鸣器驱动编写与测试 28:11 P64 第19.1讲 Linux INPUT子系统驱动实验-INPUT驱动框架简介 35:39 P65 第19.2讲 Linux INPUT子系统驱动实验-实验驱动编写 34:28 P66 第19.3讲 Linux INPUT子系统驱动实验-input_event详解 20:34 P67 第19.4讲 Linux INPUT子系统驱动实验-应用编写 19:22 P68 第19.5讲 Linux INPUT子系统驱动实验-内核自带按键驱动程序 22:31 P69 第20.1讲 Linux LCD驱动实验-Framebuffer简介 21:14 P70 第20.2讲 Linux LCD驱动实验-LCD驱动源码简析 39:52 P71 第20.3讲 Linux LCD驱动实验-LCD驱动编写 25:47 P72 第20.4讲 Linux LCD驱动实验-LCD屏幕测试 24:24 P73 第21.1讲 Linux RTC驱动实验-RTC驱动框架简介 23:22 P74 第21.2讲 Linux RTC驱动实验-RTC驱动源码简析与测试 26:30 P75 第22.1讲 Linux IIC驱动实验-Linux IIC适配器驱动框架简析 38:15 P76 第22.2讲 Linux IIC驱动实验-Linux IIC设备驱动框架简析 26:29 P77 第22.3讲 Linux IIC驱动实验-Linux IIC驱动编写之驱动框架搭建(上) 39:19 P78 第22.4讲 Linux IIC驱动实验-Linux IIC驱动编写之驱动框架搭建(下) 26:43 P79 第22.5讲 Linux IIC驱动实验-Linux IIC驱动编写之AP3216C寄存器数据读写函数编写 37:14 P80 第22.6讲 Linux IIC驱动实验-Linux IIC驱动编写之AP3216C驱动完善与测试 34:25 P81 第23.1讲 Linux SPI驱动实验-SPI控制器驱动详解(上) 15:01 P82 第23.2讲 Linux SPI驱动实验-SPI控制器驱动详解(下) 27:38 P83 第23.3讲 Linux SPI驱动实验-SPI设备驱动框架详解与设备树修改 36:57 P84 第23.4讲 Linux SPI驱动实验-SPI驱动编写之ICM20608驱动框架搭建 28:18 P85 第23.5讲 Linux SPI驱动实验-SPI驱动编写之ICM20608寄存器数据读写函数编写 41:35 P86 第23.6讲 Linux SPI驱动实验-SPI驱动编写之ICM20608驱动完善与测试APP编写 17:57 P87 第23.7讲 Linux SPI驱动实验-SPI驱动片选引脚讲解错误声明(修改讲解错误的地方) 21:46 P88 第24.1讲 Linux 串口实验-串口驱动框架详解与驱动分析 33:34 P89 第24.2讲 Linux 串口实验-使能UART3 12:10 P90 第24.3讲 Linux 串口实验-minicom移植 32:23 P91 第24.4讲 Linux 串口实验-使用minicom测试串口 15:51 P92 第25.1讲 Linux 多点电容触摸屏实验-Linux多点电容触摸TypeA协议 19:22 P93 第25.2讲 Linux 多点电容触摸屏实验-Linux多点电容触摸TypeB协议 24:35 P94 第25.3讲 Linux 多点电容触摸屏实验-驱动编写之FT5426驱动框架搭建 32:34 P95 第25.4讲 Linux 多点电容触摸屏实验-驱动编写之FT5426中断以及芯片初始化 24:27 P96 第25.5讲 Linux 多点电容触摸屏实验-驱动编写之FT5426驱动完善与触摸测试 44:24 P97 第25.6讲 Linux 多点电容触摸屏实验-tslib移植与测试 19:22 P98 第25.7讲 Linux 多点电容触摸屏实验-触摸驱动文件添加到Linux内核中 13:08 P99 第26.1讲 Linux音频驱动实验-音频基础知识 35:04 P100 第26.2讲 Linux音频驱动实验-IIS协议以及原理图分析 25:14 P101 第26.3讲 Linux音频驱动实验-ALSA和ASOC驱动框架简析 35:28 P102 第26.4讲 Linux音频驱动实验-音频驱动使能 07:10 P103 第26.5讲 Linux音频驱动实验-alsa-lib与alsa-utils移植 20:40 P104 第26.6讲 Linux音频驱动实验-播放与录音测试 38:04 P105 第26.7讲 Linux音频驱动实验-开机自动配置声卡与mplayer移植 24:08 P106 第26.8讲 Linux音频驱动实验-alsamixer介绍 13:35 P107 第27.1讲 Linux CAN驱动实验-CAN简介 24:07 P108 第27.2讲 Linux CAN驱动实验-CAN驱动使能 18:45 P109 第27.3讲 Linux CAN驱动实验-can-utils移植 15:17 P110 第27.4讲 Linux CAN驱动实验-CAN数据收发测试 11:16 P111 第28.1讲 Linux USB驱动实验-USB基础知识 32:16 P112 第28.2讲 Linux USB驱动实验-6UL USB控制器简析与硬件原理分析 29:06 P113 第28.3讲 Linux USB驱动实验-USB HOST测试实验 30:44 P114 第28.4讲 Linux USB驱动实验-USB OTG测试实验 30:31 P115 第29.1讲 Linux块设备驱动实验-块设备驱动框架分析1 24:26 P116 第29.2讲 Linux块设备驱动实验-块设备驱动框架分析2 23:11 P117 第29.3讲 Linux块设备驱动实验-使用请求队列驱动编写之驱动框架搭建 35:37 P118 第29.4讲 Linux块设备驱动实验-使用请求队列驱动编写之驱动完善与测试 33:34 P119 第29.5讲 Linux块设备驱动实验-使用制造请求函数驱动编写与测试 25:02 P120 第30.1讲 Linux网络驱动实验-嵌入式网络硬件方案介绍 17:43 P121 第30.2讲 Linux网络驱动实验-MII&RMII接口详解 14:21 P122 第30.3讲 Linux网络驱动实验-PHY芯片详解 27:31 P123 第30.4讲 Linux网络驱动实验-Linux驱动框架详解之net_device 14:22 P124 第30.5讲 Linux网络驱动实验-Linux驱动框架详解之net_device_ops&sk_buff&NAPI2 17:14 P125 第30.6讲 Linux网络驱动实验-I.MX6ULL网络驱动之设备树编写 17:45 P126 第30.7讲 Linux网络驱动实验-I.MX6ULL网络驱动之fec_probe函数简析 28:04 P127 第30.8讲 Linux网络驱动实验-I.MX6ULL网络驱动之通用PHY以及LAN8720驱动详解 29:11 P128 第30.9讲 Linux网络驱动实验-I.MX6ULL网络测试 19:26 P129 第31.1讲 Linux WIFI驱动实验-WIFI驱动移植编译 26:07 P130 第31.2讲 Linux WIFI驱动实验-WIFI测试工具移植 24:00 P131 第31.3讲 Linux WIFI驱动实验-WIFI联网测试 11:50 P132 第32.1讲 Linux 4G驱动实验-4G模块驱动修改 18:15 P133 第32.2讲 Linux 4G驱动实验-4G联网测试 28:06 P134 第33讲 Linux RGB转HDMI驱动实验 38:13 P135 第34.1讲 Linux PWM驱动实验-PWM驱动源码详解 22:08 P136 第34.2讲 Linux PWM驱动实验-PWM驱动测试 16:03 P137 第35.1讲 Linux Regmap API实验-Regmap驱动框架详解 28:15 P138 第35.2讲 Linux Regmap API实验-驱动编写测试 22:33 P139 第36.1讲 Linux IIO驱动实验-为什么要用IIO框架 31:00 P140 第36.2讲 Linux IIO驱动实验-IIO驱动框架详解 41:50 P141 第36.3讲 Linux IIO驱动实验-IIO驱动程序编写之框架搭建 25:40 P142 第36.4讲 Linux IIO驱动实验-IIO驱动程序编写之通道配置 22:59 P143 第36.5讲 Linux IIO驱动实验-IIO驱动程序编写之iio_info编写 31:10 P144 第36.6讲 Linux IIO驱动实验-IIO驱动程序编写之传感器数据读写 35:00 P145 第36.7讲 Linux IIO驱动实验-IIO驱动程序编写之应用程序编写 20:17 P146 第37讲 Linux ADC驱动实验 23:09 #coding=utf-8 import os import re import sys import time if len(sys.argv) < 2: print("Please input file!") #time.sleep(3) #sys.exit() #FILE=sys.argv[1] FILE="test.txt" def list_merge(): with open(FILE, 'rb') as fp_read: cnt = 0; while 1: buf = fp_read.readline() if len(buf) > 0: print(buf.decode("utf-8").strip("\r\n")+'|', end="") else: break if (cnt + 1) % 3 == 0: print() cnt = cnt + 1 pattern_time = '(\d+:\d+)' def time_calc(): with open(FILE, 'rb') as fp_read: cnt = 0 days= 0 hour= 0 min = 0 sec = 0 while 1: buf = fp_read.readline().decode("utf-8") if len(buf) > 0: if len(buf.strip("\r\n")) == 0: min = min + int(sec / 60) sec = sec % 60 hour=hour + int(min / 60) min = min % 60 days=days + int(hour/ 24) hour=hour % 24 print(str(cnt), str(days), str(hour), str(min), str(sec)) cnt = 0 days= 0 hour= 0 min = 0 sec = 0 else: searchObj = re.search(pattern_time,buf,re.I) if searchObj: tmp_min = buf[searchObj.span()[0]:searchObj.span()[0]+2] min = min + int(tmp_min) tmp_sec = buf[searchObj.span()[1]-2:searchObj.span()[1]] sec = sec + int(tmp_sec) cnt = cnt + 1 else: min = min + int(sec / 60) sec = sec % 60 hour=hour + int(min / 60) min = min % 60 days=days + int(hour/ 24) hour=hour % 24 print(str(cnt), str(days), str(hour), str(min), str(sec)) #days= 0 #hour= 0 #min = 0 #sec = 0 break if __name__ == "__main__": #list_merge() time_calc() time.sleep(3) sys.exit()
更多相关内容 -
使用笔记本电脑作为正点原子linux开发板的屏幕使用
2022-02-26 17:31:03使用笔记本电脑作为正点原子linux开发板的屏幕使用 -
移植正点原子linux内核
2022-01-12 13:40:09提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、创建VSCODE移植工程 二、修改根目录下Makefile 三、添加自己的linux开发板 ...学习正点原子I.MX6ULL移植内...目录
前言
学习正点原子I.MX6ULL移植内核
一、创建VSCODE移植工程
将NXP官方的压缩文件linux-imx-rel_imx_4.1.15_2.1.0_ga.tar.bz2利用Filezilla传导ubuntu虚拟机中,解压后修改成自己的命名文件夹,如下图所示:
并用vscode打开。
二、修改根目录下Makefile
将根目录下的Makefile的arm架构交叉编译器固定方便以后的编译。如下图所示:
三、添加自己的linux开发板
1、创建linux开发板配置文件
将NXP官方的linux配置文件复制并命名为自己的名字,方便以后的修改:arch/arm/configs 目 录 下 的 imx_v7_mfg_defconfig 重 新 复 制 一 份 , 命 名 为imx_alientek_emmc_defconfig
2、创建linux开发板设备树文件
添加适合正点原子 EMMC 版开发板的设备树文件,进入目录 arch/arm/boot/dts 中,复制一
份 imx6ull-14x14-evk.dts,然后将其重命名为 imx6ull-alientek-emmc.dts3、修改编译文件
.dts文件在linux编译的时候会生成.dtb文件,因此需要在配置项中加入新创建的设备树文件,修改arch/arm/boot/dts/Makefile,如下图所示添加自己的开发板配置项:
四、编译并通过网络验证移植
1、配置uboot环境变量bootargs
Linux 内核启动以后是需要根文件系统的,根文件系统存在哪里是由 uboot 的 bootargs 环境
变 量 指 定 , bootargs 会 传 递 给 Linux 内 核 作 为 命 令 行 参 数。本根文件系统采用正点原子早已烧好到emmc中的系统bootargs='console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
其中mmcblk1=emmc设备,p2=第二个分区
2、修改bootcmd变量
设置变量bootcmd=tftp 80800000 zImage;tftp 83000000 imx6ull-alientek-emmc.dtb;bootz 80800000 - 83000000,则可以验证成功启动linux,说明成功移植自己的开发板,如下图所示:
五、修改网络驱动
1、修改EMMC模式
Linux 内核驱动里面 EMMC 默认是 4 线模式的, 4 线模式肯定没有 8 线模式的速度快,所
以本节我们将 EMMC 的驱动修改为 8 线模式。修改方法很简单,直接修改设备树即可,打开文
件 imx6ull-alientek-emmc.dts,找到并修改其中的emmc网络驱动usdhc2部分如下图所示:2、修改 LAN8720 的复位以及网络时钟引脚驱动
正点原子开发板采用的LAN8720复位引脚与默认配置IO不同,故需要修改内容:
ENET1 复位引脚 ENET1_RST 连接在 I.M6ULL 的 SNVS_TAMPER7 这个引脚上。 ENET2
的复位引脚 ENET2_RST 连接在 I.MX6ULL 的 SNVS_TAMPER8 上。故需要将SPI4的配置注释。添加ENET1和ENET2复位管脚配置
由于linux内核默认的网络驱动地址ENET1是2,ENET2是1,而正点原子开发板对应的地址ENET1是0,ENET2是1故需要做出修改:
修改设备树,添加复位管脚IO,设置复位时间:
修改完复位IO和通用PHY ID以后,linux内核通用PHY可以正常工作测试如图所示:
要在 I.MX6ULL 上使能专用 LAN8720A ,需要修改一下Linux内核源码 ,打开drivers/net/ethernet/freescale/fec_main.c,找到函数 fec_probe,在 fec_probe 中加入如下代码
使ENET1 和 ENET2 的 TX_CLK 引脚复位寄存器的SION位为1
3、使能LAN8720驱动
输入命令:make menuconfig通过图形化界面配置使能LAN8720驱动,路径如下
-> Device Drivers
-> Network device support
-> PHY Device support and infrastructure
-> Drivers for SMSC PHYs重新编译并启动可以观察到网络驱动变为 LAN8720
并且能成功ping同ubuntu虚拟机
4、修改smsc.c文件
由于在linux也需要对LAN8720进行1次软复位,而在默认复位条件是LAN8720处于POWERDOWN模式,而在Uboot中使用了网络启动,故LAN8720不肯能处于此模式故要修改复位条件,如图所示。
static int smsc_phy_reset(struct phy_device *phydev) { int timeout = 50000; int rc = phy_read(phydev, MII_LAN83C185_SPECIAL_MODES); if (rc < 0) return rc; /* If the SMSC PHY is in power down mode, then set it * in all capable mode before using it. */ if ((rc & MII_LAN83C185_MODE_MASK) == MII_LAN83C185_MODE_POWERDOWN) { /* set "all capable" mode and reset the phy */ rc |= MII_LAN83C185_MODE_ALL; phy_write(phydev, MII_LAN83C185_SPECIAL_MODES, rc); } phy_write(phydev, MII_BMCR, BMCR_RESET); /* wait end of reset (max 500 ms) */ do { udelay(10); if (timeout-- == 0) return -1; rc = phy_read(phydev, MII_BMCR); } while (rc & BMCR_RESET); return 0; }
总结
移植成功!
移植linux内核,一步一步来
-
【正点原子Linux连载】第一章 应用编程概念-摘自【正点原子】I.MX6U嵌入式Linux C应用编程指南V1.1
2021-08-11 12:24:443)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新 第一章 应用编程概念 对于大多数首次接触Linux应用编程的读者来说,可能对应用编程(也可称为系统编程)这1)实验平台:正点原子阿尔法Linux开发板
2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434
2)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-300792-1-1.html
3)对正点原子Linux感兴趣的同学可以加群讨论:935446741
4)关注正点原子公众号,获取最新资料更新
第一章 应用编程概念
对于大多数首次接触Linux应用编程的读者来说,可能对应用编程(也可称为系统编程)这个概念并不太了解,所以在正式学习Linux应用编程之前,笔者有必要向大家介绍这些简单基本的概念,从整体上认识到应用编程为何物?与驱动编程、裸机编程有何不同?
了解本章所介绍的内容是掌握应用编程的先决条件,所以本章主要内容便是对Linux应用编程进行一个简单地介绍,让读者对此有一个基本的认识。本章将会讨论如下主题内容。
何为系统调用;
何为库函数;
应用程序的main()函数;
应用程序开发环境的介绍。1.1系统调用
系统调用(system call)其实是Linux内核提供给应用层的应用编程接口(API),是Linux应用层进入内核的入口。不止Linux系统,所有的操作系统都会向应用层提供系统调用,应用程序通过系统调用来使用操作系统提供的各种服务。
通过系统调用,Linux应用程序可以请求内核以自己的名义执行某些事情,譬如打开磁盘中的文件、读写文件、关闭文件以及控制其它硬件外设。
通过系统调用API,应用层可以实现与内核的交互,其关系可通过下图简单描述:
图 1.1.1 内核、系统调用与应用程序
内核提供了一系列的服务、资源、支持一系列功能,应用程序通过调用系统调用API函数来使用内核提供的服务、资源以及各种各样的功能,如果大家接触过其它操作系统编程,想必对此并不陌生,譬如Windows应用编程,操作系统内核一般都会向应用程序提供应用编程接口API,否则我们将我无法使用操作系统。
应用编程与裸机编程、驱动编程有什么区别?
在学习应用编程之前,相信大家都有过软件开发经验,譬如51、STM32等单片机软件开发、以及嵌入式Linux硬件平台下的驱动开发等,51、STM32这类单片机的软件开发通常是裸机程序开发,并不会涉及到操作系统的概念,那应用编程与裸机编程以及驱动开发有什么区别呢?
就拿嵌入式Linux硬件平台下的软件开发来说,我们大可将编程分为三种,分别为裸机编程、Linux驱动编程以及Linux应用编程。首先对于裸机编程这个概念来说很好理解,一般把没有操作系统支持的编程环境称为裸机编程环境,譬如单片机上的编程开发,编写直接在硬件上运行的程序,没有操作系统支持;狭义上Linux驱动编程指的是基于内核驱动框架开发驱动程序,驱动开发工程师通过调用Linux内核提供的接口完成设备驱动的注册,驱动程序负责底层硬件操作相关逻辑,如果学习过Linux驱动开发的读者,想必对此并不陌生;而Linux应用编程(系统编程)则指的是基于Linux操作系统的应用编程,在应用程序中通过调用系统调用API完成应用程序的功能和逻辑,应用程序运行于操作系统之上。通常在操作系统下有两种不同的状态:内核态和用户态,应用程序运行在用户态、而内核则运行在内核态。
关于应用编程这个概念,以上给大家解释得很清楚了,笔者以实现点亮一个LED功能为例,给大家简单地说明三者之间的区别,LED裸机程序如下所示:
示例代码 1.1.1 LED裸机程序static void led_on(void) { /* 点亮LED硬件操作代码 */ } static void led_off(void) { /* 熄灭LED硬件操作代码 */ } int main(void) { /* 用户逻辑 */ for ( ; ; ) { led_on(); //点亮LED delay(); //延时 led_off(); //熄灭LED delay(); //延时 } }
可以看到在裸机程序当中,LED硬件操作代码与用户逻辑代码全部都是在同一个源文件(同一个工程)中实现的,硬件操作代码与用户逻辑代码没有隔离,没有操作系统支持,代码编译之后直接在硬件平台运行,俗称“裸跑”。我们再来看一个Linux系统下的LED驱动程序示例代码,如下所示:
示例代码 1.1.2 Linux下LED驱动程序#include <linux/module.h> #include <linux/platform_device.h> #include <linux/of_gpio.h> #include <linux/delay.h> #include <linux/cdev.h> #include <linux/uaccess.h> static void led_on(void) { /* 点亮LED硬件操作代码 */ } static void led_off(void) { /* 熄灭LED硬件操作代码 */ } static int led_open(struct inode *inode, struct file *filp) { /* 打开设备时需要做的事情 */ } static ssize_t led_write(struct file *filp, const char __user *buf, size_t size, loff_t *offt) { int flag;
/* 获取应用层write的数据,存放在flag变量 */
if (copy_from_user(&flag, buf, size)) return -EFAULT; /* 判断用户写入的数据,如果是0则熄灭LED,如果是非0则点亮LED */ if (flag) led_on(); else led_off(); return 0; } static int led_release(struct inode *inode, struct file *filp) { /* 关闭设备时需要做的事情 */ } static struct file_operations led_fops = { .owner = THIS_MODULE, .open = led_open, .write = led_write, .release = led_release, }; static int led_probe(struct platform_device *pdev) { /* 驱动加载时需要做的事情 */ } static int led_remove(struct platform_device *pdev) { /* 驱动卸载时需要做的事情 */ } static const struct of_device_id led_of_match[] = { { .compatible = "alientek,led", }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, led_of_match); static struct platform_driver led_driver = { .driver = { .owner = THIS_MODULE, .name = "led", .of_match_table = led_of_match, }, .probe = led_probe, .remove = led_remove, }; module_platform_driver(led_driver); MODULE_DESCRIPTION("LED Driver"); MODULE_LICENSE("GPL");
以上并不是一个完整的LED驱动代码,如果没有接触过Linux驱动开发的读者,看不懂也没有关系,并无大碍,此驱动程序使用了最基本的字符设备驱动框架编写而成,非常简单;led_fops对象中提供了open、write、release方法,当应用程序调用open系统调用打开此LED设备时会执行到led_open函数,当调用close系统调用关闭LED设备时会执行到led_release函数,而调用write系统调用时会执行到led_write函数,此驱动程序的设定是当应用层调用write写入0时熄灭LED,write写入非0时点亮LED。
驱动程序属于内核的一部分,当操作系统启动的时候会加载驱动程序,可以看到LED驱动程序中仅仅实现了点亮/熄灭LED硬件操作相关逻辑代码,应用程序可通过write这个系统调用API函数控制LED亮灭;接下来我们看看Linux系统下的LED应用程序示例代码,如下所示:
示例代码 1.1.3 Linux下LED应用程序#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int main(int argc, char **argv) { int fd; int data; fd = open("/dev/led", O_WRONLY);//打开LED设备(假定LED的设备文件为/dev/led) if (0 > fd) return -1; for ( ; ; ) { data = 1; write(fd, &data, sizeof(data)); //写1点亮LED sleep(1); //延时1秒 data = 0; write(fd, &data, sizeof(data)); //写0熄灭LED sleep(1); //延时1秒 } close(fd); return 0; }
此应用程序也非常简单,仅只需实现用户逻辑代码即可,循环点亮、熄灭LED,并不需要实现硬件操作相关,示例代码中调用了open、write、close这三个系统调用API接口,open和close分别用于打开/关闭LED设备,write写入数据传给LED驱动,传入0熄灭LED,传入非0点亮LED。
LED应用程序与LED驱动程序是分隔、分离的,它们单独编译,它们并不是整合在一起的,应用程序运行在操作系统之上,有操作系统支持,应用程序处于用户态,而驱动程序处于内核态,与纯粹的裸机程序存在着质的区别。Linux应用开发与驱动开发是两个不同的方向,将来在工作当中也会负责不同的任务、解决不同的问题。
关于本小节系统调用概念相关的内容就介绍到这里了,接下来向大家介绍库函数。
1.2库函数
前面给大家介绍了系统调用,系统调用是内核直接向应用层提供的应用编程接口,譬如open、write、read、close等,关于这些系统调用后面会给大家进行详细介绍。编写应用程序除了使用系统调用之外,我们还可以使用库函数,本小节来聊一聊库函数。
库函数也就是C语言库函数,C语言库是应用层使用的一套函数库,在Linux下,通常以动态(.so)库文件的形式提供,存放在根文件系统/lib目录下,C语言库函数构建于系统调用之上,也就是说库函数其实是由系统调用封装而来的,当然也不能完全这么说,原因在于有些库函数并不调用任何系统调用,譬如一些字符串处理函数strlen()、strcat()、memcpy()、memset()、strchr()等等;而有些库函数则会使用系统调用来帮它完成实际的操作,譬如库函数fopen内部调用了系统调用open()来帮它打开文件、库函数fread()就利用了系统调用read()来完成读文件操作、fwrite()就利用了系统调用write()来完成写文件操作。
Linux系统内核提供了一系列的系统调用供应用层使用,我们直接使用系统调用就可以了呀,那为何还要设计出库函数呢?事实上,有些系统调用使用起来并不是很方便,于是就出现了C语言库,这些C语言库函数的设计是为了提供比底层系统调用更为方便、更为好用、且更具有可移植性的调用接口。
来看一看它们之间的区别:
库函数是属于应用层,而系统调用是内核提供给应用层的编程接口,属于系统内核的一部分;
库函数运行在用户空间,调用系统调用会由用户空间(用户态)陷入到内核空间(内核态);
库函数通常是有缓存的,而系统调用是无缓存的,所以在性能、效率上,库函数通常要优于系统调用;
可移植性:库函数相比于系统调用具有更好的可移植性,通常对于不同的操作系统,其内核向应用层提供的系统调用往往都是不同,譬如系统调用的定义、功能、参数列表、返回值等往往都是不一样的;而对于C语言库函数来说,由于很多操作系统都实现了C语言库,C语言库在不同的操作系统之间其接口定义几乎是一样的,所以库函数在不同操作系统之间相比于系统调用具有更好的可移植性。
以上便上它们之间一个大致的区别,从实现者的角度来看,系统调用与库函数之间有根本的区别,但从用户使用角度来看,其区别并不重要,它们都是C语言函数。在实际应用编程中,库函数和系统调用都会使用到,所以对于我们来说,直接把它们当做是C函数即可,知道你自己调用的函数是系统调用还是库函数即可,不用太过于区分它们之间的差别。
所以应用编程简单点来说就是:开发Linux应用程序,通过调用内核提供的系统调用或使用C库函数来开发具有相应功能的应用程序。
1.3标准C语言函数库
在Linux系统下,使用的C语言库为GNU C语言函数库(也叫作glibc,其网址为http://www.gnu.org/software/libc/),作为Linux下的标准C语言函数库。
进入到http://www.gnu.org/software/libc/网址,如下所示:
图 1.3.1 glibc官网
点击上面的Sources选项可以查看它的源码实现:
图 1.3.2 获取源码的方式
glibc源码的获取方式很简单,直接直接从git仓库下载,也可以通过ftp下载,如果大家有兴趣、或者想要了解某一个库函数它的具体实现,那么就可以获取到它源码来进行分析,好了,这里就不再多说了!
确定Linux系统的glibc版本
前面提到过了,C语言库是以动态库文件的形式提供的,通常存放在/lib目录,它的命名方式通常是libc.so.6,不过这个是一个软链接文件,它会链接到真正的库文件。
进入到Ubuntu系统的/lib目录下,笔者使用的Ubuntu版本为16.04,在我的/lib目录下并没有发现libc.so.6这个文件,其实是在/lib/x86_64-linux-gnu目录下,进入到该目录:
图 1.3.3 libc.so.6文件
可以看到libc.so.6链接到了libc-2.23.so库文件,2.23表示的就是这个glibc库的版本号为2.23。除此之外,我们还可以直接运行该共享库来获取到它的信息,如下所示:图 1.3.4 确定glibc版本号
从打印信息可以看到,笔者所使用的Ubuntu系统对应的glibc版本号为2.23。
1.4main函数
对学习过C语言编程的读者来说,譬如单片机编程、Windows应用编程等,main函数想必大家再熟悉不过了,很多编程开发都是以main函数作为程序的入口函数,同样在Linux应用程序中,main函数也是作为应用程序的入口函数存在,main函数的形参一般会有两种写法,如果执行应用程序无需传参,则可以写成如下形式:
示例代码 1.4.1 main函数写法之无传参int main(void) { /* 代码 */ }
如果在执行应用程序的时候需要向应用程序传递参数,则写法如下:
示例代码 1.4.2 main函数写法之有传参
int main(int argc, char **argv){ /* 代码 */ }
argc形参表示传入参数的个数,包括应用程序自身路径和程序名,譬如运行当前目录下的hello可执行文件,并且传入参数,如下所示:
./hello 112233
那么此时参数个数为2,并且这些参数都是作为字符串的形式传递给main函数:
argv[0]等于"./hello"
argv[1]等于"112233"
有传参时main函数的写法并不只有这一种,只是这种写法最常用,对于其它的写法,后面学习过程中如果遇到了再给大家进行讲解,这里暂时先不去管。
1.5本书使用的开发环境
对于编程开发,大家可能都比较关心开发环境的问题,譬如本书将使用什么IDE编写应用程序之类的问题,本小节将对开发环境的问题进行一个简单介绍。
首先,本书分为三篇内容,在前言部分已经向各位读者介绍了本书的内容规划,分为入门篇、提高篇以及进阶篇。因为是Linux应用编程,所以本书将会在Linux操作系统环境下编写示例代码,为了同正点原子的其它开发文档保持一致,选择Ubuntu操作系统,推荐大家使用16.04或14.04版本的Ubuntu系统,个人觉得这两个版本比较稳定;除了使用Ubuntu系统外,大家还可以选择其它Linux发行版,譬如CentOS、Redhat(红帽)等。
在Linux操作系统下,也有很多比较好用的IDE软件,可以帮助我们更为轻松的进行软件开发,譬如Eclipse、vscode等,如果你会使用Eclipse,可以在Ubuntu系统下安装Eclipse进行Linux应用开发,1.5.1小节介绍了如何在Ubuntu系统下安装Eclipse;如果你不会使用Eclipse,那就建议你使用vscode,同样本书也是使用vscode,与正点原子的驱动开发文档保持一致;vscode的安装方法和使用方法本书不再介绍,相信大家在自己的Ubuntu系统下已经安装好了,如果没有安装的,直接参考“开发板光盘资料A-基础资料/【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.pdf”文档第四章的4.5小节内容进行安装即可!
Tips:注意,本文档并不介绍Eclipse IDE的使用方法,笔者也用的不多,只是告诉大家可以在Ubuntu使用这个IDE,并且后面给出了安装方法,如果你以前经常使用它开发软件,你可以尝试使用它在Ubuntu下开发Linux应用程序,如果你没用过就不要去碰了。用什么IDE都不重要,哪怕你直接使用vi编写程序都可以,我们的重点是学习应用编程!而不是学习IDE怎么用。
vscode是一个代码编辑器,提供了很多好用的插件,譬如语法检测、高亮显示、智能补全等,大家可以根据自己的选择安装插件,在驱动开发指南文档中也都有介绍。
入门篇章节内容中,主要向大家介绍了Linux应用编程所涉及到的各个知识点以及各种系统调用和库函数,本部分内容所编写的示例代码,均是在Ubuntu系统下进行测试、验证,也就是在Ubuntu系统下执行测试程序以验证所学知识内容。所以在该部分内容中,本书使用vscode+gcc的方式开发应用程序,vscode作为代码编辑器、gcc作为编译器,使用vscode编写完代码之后再用gcc编译源码,得到可在PC端Ubuntu系统下运行的可执行文件。gcc的使用方法在驱动开发指南中有介绍,参考“开发板光盘资料A-基础资料/【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.pdf”文档第三章的内容。
提高篇章节内容中,将会以正点原子阿尔法I.MX6U Linux开发板为例,向大家介绍如何编写应用程序控制开发板上的各种硬件外设,所以编写的应用程序是需要在开发板上运行的,阿尔法I.MX6U开发板是ARM架构硬件平台,所以源码需要使用交叉编译工具(ARM架构下的gcc编译器)进行编译,得到可在开发板上运行的可执行文件。所以在第二篇章节内容中,本书使用vscode+ARM gcc(交叉编译工具)的方式开发应用程序。
入门篇和提高篇章节内容中所编写的示例代码只有单个.c源文件,但是对于一个真正的Linux应用程序项目来说,其原文件的个数肯定不止一个,可能有几十上百个,这个时候可能就需要用到Makefile来组织工程源文件。直接通过Makefile来组织工程,对于一个大型软件工程来说通常是比较困难的,需要程序员对Makefile能够熟练使用,譬如Linux内核源码、U-Boot源码等都是直接使用Makefile进行管理。对于一般程序员来说,很难做到熟练使用Makefile。在第三篇(进阶篇)章节内容中,会向大家介绍cmake工具,使用cmake来管理我们的源码工程,相比于直接使用Makefile,使用cmake会打打降低难度,提高我们的开发效率!
进阶篇章节内容中,会给大家介绍一些Linux实战小项目,通过学习进一步提升Linux应用编程能力,本部内容将会使用cmake+vscode进行开发,其实cmake在实际的项目当中用的还是比较多的,譬如很多的开源软件都会选择使用cmake来构建、配置工程源码,学习了之后,相信大家在今后的工作当中也会用到。
关于本小节的内容到这里就结束了,下一章开始将正式进入到应用编程学习之路,大家加油!
1.5.1Ubuntu系统下安装Eclipse
本小节介绍如何在Ubuntu系统下安装Eclipse,笔者使用的Ubuntu系统版本号为16.04.5,其它版本笔者未进行验证,不过大家试一试,如果出现了问题,再根据提示找到相应的解决办法!
Eclipse是一个开源的IDE,基于java语言开发的可扩展开发平台,支持很多插件,可用于诸如java、C/C++、PHP、Android等编程语言的软件开发,关于更加详细的介绍大家自己去了解,本书不再介绍!
㈠下载Eclipse
开发板资料包中提供了Eclipse安装包,路径为:开发板光盘->3、软件->eclipse-cpp-2020-12-R-linux-gtk-x86_64.tar.gz。
首先我们要下载Eclipse安装包,进入到Eclipse官网:https://www.eclipse.org/,如下所示:
图 1.5.1 Eclipse官网
点击右上角“Download”按钮进入到下载页面:
图 1.5.2 Download页面
点击下边的“Download Package”选项:
图 1.5.3 package列表
当前页面显示的是最新版本的软件包,可以看到Eclipse的最新版本是2021-03,上图右下角列出了其它的版本软件包的链接地址,这里笔者选择2020-12,也就是4.18版本作为演示,其它版本笔者没测试过,理论上都是可以的。
点击4.18版本链接地址,页面跟上图一样,因为是使用Eclipse进行C语言应用程序开发,所以选择“Eclipse IDE for C/C++ Developers”软件包,选择Linux系统的安装包,点击下图红框中的x86_64链接:
图 1.5.4 C/C++ IDE
点击之后会进入到下载界面,点击下图中的“Download”即可下载:
![(https://img-blog.csdnimg.cn/54c6c37654bc4059ace99903831ac0cf.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81NTc5NjU2NA==,size_16,color_FFFFFF,t_70)
图 1.5.5 下载
下载完之后会得到压缩包文件“eclipse-cpp-2020-12-R-linux-gtk-x86_64.tar,gz”:
图 1.5.6 Eclipse压缩包文件
㈡、下载jdk
开发板资料包中提供了jdk,路径为:开发板光盘->3、软件->jdk-8u291-linux-x64.tar.gz。
因为Eclipse是基于java语言开发的,所以它依赖于java jdk,所以我们要下载,进入到https://www.oracle.com/cn/java/technologies/javase-downloads.html网页,如下所示:
图 1.5.7 jdk下载主页
我们往下翻找到Java SE8,如下所示:
图 1.5.8 Java SE8
点击JDK Download进入到jdk8下载页面,往下翻找到软件包下载列表:
图 1.5.9 jdk8下载页面
可以看到上图列举出了很多不同操作系统以及硬件平台的jdk包,操作系统包括Linux、macOS以及Windows等,还有不同的硬件平台,笔者用的是64位的Ubuntu系统,所以选择“Linux x64 Compressed Archive”,点击后边“jdk-8u291-linux-x64.tar.gz”下载。之后会弹出如下界面:
图 1.5.10 下载
勾选图中所示的选项,之后点击进行下载。下载需要登录Oracle账户,譬如下图所示,填写用户名、密码点击登录之后才能下载;没有账户的读者需要点击下面的“创景账户”进行创建。
图 1.5.11 登录Oracle账户
下载完之后得到一个压缩包文件:
图 1.5.12 jdk压缩包文件
㈢、安装Eclipse
首先把前面下载好的两个压缩包文件拷贝到Ubuntu系统用户家目录下,如下所示:
图 1.5.13 将压缩包文件拷贝到Ubuntu系统
接着将eclipse-cpp-2020-12-R-linux-gtk-x86_64.tar.gz压缩包文件解压到/opt目录下,如下所示:
sudo tar -xzf eclipse-cpp-2020-12-R-linux-gtk-x86_64.tar.gz -C /opt/
图 1.5.14 解压eclipse-cpp-2020-12-R-linux-gtk-x86_64.tar.gz文件
执行解压命令的时候,需要加上sudo,这样才能有权限将压缩文件解压到/opt目录下,解压之后会在/opt目录下生成eclipse文件夹,如下所示:
图 1.5.15 eclipse文件夹
这样Eclipse就安装完成了,我们下载的这个压缩包是一个免安装的,直接解压就可以了,eclipse目录就是软件的安装目录了,如下所示:
图 1.5.16 Eclipse安装目录
接下来创建一个桌面快捷方式,可以通过双击桌面图标来打开Eclipse软件。首先进入到桌面目录下,如下所示:
图 1.5.17 进入桌面目录
笔者的Ubuntu系统配置的是中文语言环境,如果你的是英文环境,那么对应的应该是Desktop目录。在该目录下创建一个名为eclipse.desktop的文件,将以下内容写入到该文件中:
[Desktop Entry]
Encoding=UTF-8
Name=Eclipse
Comment=Eclipse
Exec=/opt/eclipse/eclipse
Icon=/opt/eclipse/icon.xpm
Terminal=false
StartupNotify=true
Type=Application
Categories=Application;Development;
图 1.5.18 eclipse.desktop文件中的内容
其中“Exec=”后面为eclipse安装目录下的eclipse可执行文件的路径,“Icon=”后面为eclipse安装目录下的图标图片的路径,编辑完成之后保存退出。最后为eclipse.desktop文件添加上可执行权限:
chmod u+x eclipse.desktop
完成之后,Ubuntu系统桌面上会出现Eclipse软件图标快捷方式:
图 1.5.19 桌面图标
㈣、安装jdk
将jdk压缩包jdk-8u291-linux-x64.tar.gz解压到/opt目录下:
sudo tar -xzf jdk-8u291-linux-x64.tar.gz -C /opt/
图 1.5.20 解压jdk-8u291-linux-x64.tar.gz文件
解压完成之后会在/opt目录下生成jdk1.8.0_291文件夹,如下所示:
图 1.5.21 jdk1.8.0_291文件夹
接下来需要配置环境变量,打开用户家目录下的.bashrc(vi ~/.bashrc)文件,在该文件末尾添加如下内容:jdk环境配置
export JDK_HOME=/opt/jdk1.8.0_291 export JRE_HOME=${JDK_HOME}/jre export CLASSPATH=.:${JDK_HOME}/lib:${JRE_HOME}/lib:$CLASSPATH export PATH=${JDK_HOME}/bin:$PATH
图 1.5.22 配置.bashrc文件
环境变量JDK_HOME指定了jdk的路径。文件内容编辑完成之后保存退出,接着使用source命令运行.bashrc脚本使我们的配置生效:
source ~/.bashrc
jdk到这里就安装完成了,可以检查看看jdk有没有安装成功,在终端下执行java -version命令:
图 1.5.23 验证jdk安装是否成功
还有最好一个步骤需要完成,将eclipse与jdk联系起来,进入到Eclipse安装目录下,在该目录下创建一个名为jre的文件夹:
图 1.5.24 创建jre目录
进入到jre目录下,创建一个软链接文件指向jdk目录下的bin目录,如下所示:
图 1.5.25 创建软链接文件
㈤、测试
接下来打开Eclipse软件,创建一个简单的C语言工程进行测试,在Ubuntu系统桌面上双击Eclipse图标打开Eclipse:
图 1.5.26 启动界面
Eclipse启动之后会首先让用户设置一个工作目录,如下所示:
图 1.5.27 设置工作目录
直接使用默认的路径即可,点击Launch。
图 1.5.28 软件的欢迎界面
点击“Create a new C/C++ project”可以创建一个C语言应用工程,具体的步骤的就不再演示了。
本小节内容到此结束。 -
【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.4.pdf
2020-05-15 10:24:04正点原子团队基于IMX6U Alpha/Mini开发板推出的教程。 v1.4版本。 很详细,适合作为初学者入门,以及相关问题来查询使用。 本着原子自身开源分享的精神的,我设置的所需下载积分是0。(可能系统会自动改成1或者其他... -
正点原子linux开发板无屏幕,使用笔记本屏幕显示
2022-02-26 16:08:06买个正点原子linux板子用,发现屏幕和正点原子stm32的屏幕不通用,另购买一块屏幕还是贵,思考如何通过不购买屏幕也可以体验它到显示。可以通过一根网线来解决 解决思路,linux开发板运行应用程序,使用网线将的...买个正点原子linux板子用,发现屏幕和正点原子stm32的屏幕不通用,另购买一块屏幕还是贵,思考如何通过不购买屏幕也可以体验它到显示。可以通过一根网线来解决
解决思路,linux开发板运行应用程序,使用网线将的数据通过网线传至笔记本电脑的屏幕,在window界面编写程序将图像显示出来。
所需工具:笔记本一台,一根网线,正点原子linux开发板
1.linux程序
1.打开linux的显存,将显存映射到到一个地址,通过此地址可以修改和观察显存数据,通过udp协议将数据传送至电脑端
编译使用虚拟机交叉编译,具体方法参考正点原子手册学习
#include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <unistd.h> #include <netdb.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/types.h> #include <arpa/inet.h> #include <linux/fb.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <linux/fb.h> #define SERVER_PORT 8888 //定义端口号:(0-1024为保留端口号,最好不要用) #define MAX_BUF_SIZE 1024*3 long ceshi ; int ceshi1 = 0; char buffer[MAX_BUF_SIZE]; char buffer1[MAX_BUF_SIZE]; #define display_width 1024 #define display_high 600 #define send_size 50+4 int sockfd; //socket描述符 struct sockaddr_in addr; //定义服务器起地址 void set_adress(int adress,unsigned char *temp)//adress 代表显存下标,buffer表传输的数值 { temp[0] = adress >>24; temp[1] = adress >>16; temp[2] = adress >>8; temp[3] = adress; temp[0] = 55; } void send_date(int temp,int color) //只发送一个颜色 { int n; int i; int repeat = 0; int len; struct sockaddr *appaddr; len = sizeof(struct sockaddr_in); //while(1) { /* 从键盘读入,写到服务端 */ #if 0 printf("Please input char:\n"); fgets(buffer1,MAX_BUF_SIZE,stdin); #endif i = 0; //temp = y*display_width+x; buffer[i] = (unsigned char)(temp/1000000%100); i++; buffer[i] = (unsigned char)(temp/10000%100); i++; buffer[i] = (unsigned char)(temp/100%100); i++; buffer[i] = (unsigned char)(temp%100); i++; buffer[i] = (unsigned char )((color>>8)); i++; buffer[i] = (unsigned char )((color)); i++; buffer[i] = 0; appaddr = (struct sockaddr *)&addr; sendto(sockfd,buffer,10,0,(struct sockaddr*)appaddr,len); bzero(buffer,MAX_BUF_SIZE); } } void send_date_1(int temp,int length,unsigned short *p) //发送一串颜色1024×2 个长度,使用2个字节作为行数 { int n; int i; int j; int k = 0; int repeat = 0; int color; int len; struct sockaddr *appaddr; len = sizeof(struct sockaddr_in); //while(1) { /* 从键盘读入,写到服务端 */ #if 0 printf("Please input char:\n"); fgets(buffer1,MAX_BUF_SIZE,stdin); #endif i = 0; //地址从0开始 //temp = ceshi++; j = temp; buffer[i] = (unsigned char)(temp/1000000%100); i++; buffer[i] = (unsigned char)(temp/10000%100); i++; buffer[i] = (unsigned char)(temp/100%100); i++; buffer[i] = (unsigned char)(temp%100); i++; buffer[i] = (unsigned char)(length>>8); i++; buffer[i] = (unsigned char)(length&0xff); i++; for(k = 0;k < length;k++) { color = p[j++]; buffer[i++] = (unsigned char )((color>>8)); buffer[i++] = (unsigned char )((color)); } //buffer[i++] = 0;//结束符号 appaddr = (struct sockaddr *)&addr; sendto(sockfd,buffer,i,0,(struct sockaddr*)appaddr,len); //bzero(buffer,MAX_BUF_SIZE); //sleep(1); } } void draw_point(int x,int y,int color) { int n; int i; int repeat = 0; int temp; int len; struct sockaddr *appaddr; len = sizeof(struct sockaddr_in); //while(1) { /* 从键盘读入,写到服务端 */ #if 0 printf("Please input char:\n"); fgets(buffer1,MAX_BUF_SIZE,stdin); #endif i = 0; temp = y*display_width+x; buffer[i] = (unsigned char)(temp/1000000%100); buffer[i]+= 1; i++; buffer[i] = (unsigned char)(temp/10000%100); buffer[i]+= 1; i++; buffer[i] = (unsigned char)(temp/100%100); buffer[i]+= 1; i++; buffer[i] = (unsigned char)(temp%100); buffer[i]+= 1; i++; buffer[i] = (unsigned char )((color>>16)+1); i++; buffer[i] = (unsigned char )((color>>8)+1); i++; buffer[i] = (unsigned char )((color)+1); i++; buffer[i] = 0; appaddr = (struct sockaddr *)&addr; sendto(sockfd,buffer,strlen(buffer),0,(struct sockaddr*)appaddr,len); bzero(buffer,MAX_BUF_SIZE); } } void dra_line(int x1,int y1,int x2,int y2,int color) { int i; for(i = x1;i<x2;i++) draw_point(i,y1,color); } void dra_rct(int x1,int y1,int x2,int y2,int color)//k代表是横还是竖 { int i ; for(i = x1;i< x2;i++) { draw_point(i,y1,color); draw_point(i,y2,color); } for(i=y1;i<y2;i++) { draw_point(x1,i,color); draw_point(x2,i,color); } } void udpc_requ(int sockfd,const struct sockaddr_in *addr,int len) { int n; int i; int repeat = 0; while(1) { /* 从键盘读入,写到服务端 */ #if 0 printf("Please input char:\n"); fgets(buffer1,MAX_BUF_SIZE,stdin); #endif i = 0; #if 0 buffer[i] = (unsigned char)(ceshi/1000000%100); buffer[i]+= 1; i++; buffer[i] = (unsigned char)(ceshi/10000%100); buffer[i]+= 1; i++; buffer[i] = (unsigned char)(ceshi/100%100); buffer[i]+= 1; i++; buffer[i] = (unsigned char)(ceshi%100); buffer[i]+= 1; i++; buffer[i] = ceshi1; i++; buffer[i] = ceshi1; i++; buffer[i] = ceshi1; i++; buffer[i] = 0; #endif dra_rct(50,50,200,200,ceshi); sendto(sockfd,buffer,strlen(buffer),0,(struct sockaddr*)addr,len); bzero(buffer,MAX_BUF_SIZE); sleep(1); } } int main(int argc,char **argv) { int i,j,k; struct fb_fix_screeninfo fb_fix; struct fb_var_screeninfo fb_var; unsigned int screen_size; int fd; int temp = 0; static int width; //LCD X分辨率 static int height; //LCD Y分辨率 unsigned short *screen_base = NULL; //映射后的显存基地址 struct sockaddr *appaddr; int len; len = sizeof(struct sockaddr_in); if(argc!=2) { fprintf(stderr,"Usage:%s server_ip\n",argv[0]); exit(1); } /* 建立 sockfd描述符 */ sockfd=socket(AF_INET,SOCK_DGRAM,0); if(sockfd<0) { fprintf(stderr,"Socket Error:%s\n",strerror(errno)); exit(1); } /* 打开framebuffer设备 */ if (0 > (fd = open("/dev/fb0", O_RDWR))) { perror("open error"); exit(EXIT_FAILURE); } ioctl(fd, FBIOGET_VSCREENINFO, &fb_var); ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix); screen_size = fb_fix.line_length * fb_var.yres; width = fb_var.xres; height = fb_var.yres; fprintf(stderr,"width = %d,height = %d,size_int = %d\n",width,height,sizeof(short)); //printf("width = %d,height = %d\n",width,height); screen_base = mmap(NULL, screen_size, PROT_WRITE, MAP_SHARED, fd, 0); if (MAP_FAILED == (void *)screen_base) { perror("mmap error"); close(fd); exit(EXIT_FAILURE); } /* 填充服务端的资料 */ bzero(&addr,sizeof(struct sockaddr_in)); // 初始化,置0 addr.sin_family=AF_INET; // Internet addr.sin_port=htons(SERVER_PORT);// (将本机器上的short数据转化为网络上的short数据)端口号 if(inet_aton(argv[1],&addr.sin_addr)<0) /*inet_aton函数用于把字符串型的IP地址转化成网络2进制数字*/ { fprintf(stderr,"Ip error:%s\n",strerror(errno)); exit(1); } if (0 > (fd = open("/dev/fb0", O_RDWR))) { //perror("open error"); fprintf(stderr,"open error:%s\n",strerror(errno)); exit(EXIT_FAILURE); } //udpc_requ(sockfd,&addr,sizeof(struct sockaddr_in)); // i = 0; while(1) { int changdu = 300;//长度为像素点长度,不是待发送数组的长度; if(i >= width*height) { changdu = width*height - i; send_date_1(i,changdu,screen_base); i = 0;//重新开始 } else { send_date_1(i, changdu, screen_base); } i += changdu; } close(sockfd); }
2.window程序
此程序以默认地址IPaddr[18] ="192.168.10.200",端口为8888,此处需要将以太网的ipv4地址固定,防止每次都要修改ip,
程序
// linux_screen.cpp : 定义应用程序的入口点。 // #include "stdafx.h" #include "linux_screen.h" #include <WINSOCK2.H> #include <string> #include <winsock2.h> using namespace std; #pragma comment(lib, "ws2_32.lib ") #define MAX_LOADSTRING 100 #define max_size 1024*3 // 全局变量: HINSTANCE hInst; // 当前实例 TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本 TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名 int sta,stb,stc,std1; static int i = 0; LPCWSTR sum2[20]; int ceshi; int port = 8888; char IPaddr[18] ="192.168.10.200"; int ceshi1,ceshi2,ceshi3,ceshi4; #define dis_high 600 #define dis_width 1024 #define dlt_x 300 #define dlt_y 700 unsigned short display[dis_high*dis_width]={0}; unsigned short display_1[dis_high*dis_width]={0};//之前的屏幕,为减少刷新 unsigned long position = 0; unsigned int pisition_num = 0; // 此代码模块中包含的函数的前向声明: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); bool BindSocket(SOCKET& socket,short port ,const char* Ip) //网络函数 { SOCKADDR_IN address; address.sin_family=AF_INET; address.sin_addr.s_addr =inet_addr(Ip); address.sin_port=htons(port); memset(address.sin_zero,0,sizeof(address.sin_zero)); if(SOCKET_ERROR == bind(socket,(const struct sockaddr*)&address,sizeof(struct sockaddr)) ) { return false; } return true; } DWORD WINAPI Fun(LPVOID lpParamter)//第二条线程 { WORD wVersionRequested; WSADATA wData; // 这结构是用于接收Wjndows Socket的结构信息的 int err; SOCKADDR_IN address; int n =sizeof(struct sockaddr); char talk[100]={0}; char buffer[max_size] = {0}; int i = 0; int j = 0; wVersionRequested = MAKEWORD( 1, 1 ); // 请求WinSock库 err = WSAStartup( wVersionRequested, &wData ); if ( err != 0 ) { return -1; // 返回值为零时表示成功WSAStartup } SOCKET sockSrv = socket(AF_INET, SOCK_DGRAM, 0); if(sockSrv<0) { printf("failed"); return 0; } #if 0 printf("NEWSocket success.\n"); printf("请输入本机IP地址:\n"); gets(IPaddr); printf("请输入本机端口号:\n"); scanf("%d",&port); gets(buffer); //去掉回车 #endif while(! BindSocket(sockSrv,port,IPaddr) ) { #if 0 printf("failed"); printf("请输入本机端口号:\n"); scanf("%d",&port); #endif } printf("BindSocket success.\n"); while(1) { i = recvfrom(sockSrv,buffer, max_size,0,(struct sockaddr*)&address,&n); if(i ==SOCKET_ERROR ) printf("接收失败\n"); else { //printf("%d:\n",i); pisition_num = i; position = 0; #if 0 position = (buffer[0]); position *= 100; position += (buffer[1]); position *= 100; position +=( buffer[2]); position *= 100; position += (buffer[3]); display[position] = buffer[4]; display[position] <<=8; display[position] += buffer[5]; #endif #if 1 position = (buffer[0]); position *= 100; position += (buffer[1]); position *= 100; position +=( buffer[2]); position *= 100; position += (buffer[3]); int length; length = (buffer[4]); length <<= 8; length += (buffer[5]); int i; int j; for(i = 6,j = 0;j < length;j++) { display[position+j] = buffer[i++]; display[position+j] <<=8; display[position+j] += buffer[i++]; } #endif ceshi1 = length; ceshi2 = buffer[1]; ceshi3 = buffer[2]; ceshi4 = buffer[3]; //buffer[i-1] = '\0'; //puts(buffer); //printf("please talk:\n"); //gets(talk); //sendto(sockSrv,talk, sizeof(talk), 0,(const struct sockaddr*)&address,sizeof(struct sockaddr) ); } } closesocket(sockSrv); WSACleanup(); } int co16_to_24(int temp) { int temp_1 = 0; temp_1 = ((temp&0xf800)<<8); temp_1 |= ((temp&0x7e0)<<5); temp_1 |= ((temp&0x1f)<<3); return temp_1; } void totary(HDC hdc) { HPEN hPen; HPEN hPen1; int i; int j; int k = 0; unsigned char temp = 0; //hPen = CreatePen (PS_DOT, 3, 0xff) ; //hPen1 = CreatePen (PS_DOT, 3, 0) ; //SelectObject (hdc, hPen) ; //MoveToEx (hdc, 300, 300, NULL) ; //LineTo (hdc, 300, 300) ; //DeleteObject (SelectObject (hdc, GetStockObject (BLACK_PEN))) ; //HBITMAP hbit = CreateBitmap(1024,600,8,24,display);CreateCompatibleBitmap #if 0 HBITMAP hBitmap = CreateBitmap(1024,600,1,24,display); if(hBitmap) { BITMAP bitmap; //GetObject (hBitmap, sizeof (BITMAP), &bitmap) ; HDC hdcMem = CreateCompatibleDC (hdc) ; CreateCompatibleBitmap(hdcMem,1024,600); SelectObject (hdcMem, hBitmap) ; BitBlt(hdc,dlt_x,dlt_y,1024,600,hdcMem,0,0,SRCINVERT); DeleteDC (hdcMem) ; } #endif BITMAP bit = {0, 200, 600, 4, 1, 1}; //bit.bmBitsPixel=16; //bit.bmType = 0; //bit.bmHeight = 600; //bit.bmWidth = 1024; //bit.bmWidthBytes = 16; #if 0 bit.bmBits = display; HBITMAP hBitmap = CreateBitmapIndirect(&bit); SetBitmapBits(hBitmap,sizeof(display),display); GetObject (hBitmap, sizeof (BITMAP), &bit) ; HDC hdcMem = CreateCompatibleDC (hdc) ; SelectObject (hdcMem, hBitmap) ; BitBlt(hdc,dlt_x,dlt_y,20,600,hdcMem,0,0,SRCCOPY); DeleteDC (hdcMem) ; #endif #if 0 tagBITMAPINFOHEADER head; head.biSize = 40; head.biWidth = 1024; head.biHeight = 600; head.biPlanes = 1; head.biBitCount = 4; head.biCompression = BI_RGB; #endif #if 1 BITMAPINFO info; info.bmiHeader.biSize = 40; info.bmiHeader.biWidth = 1024; info.bmiHeader.biHeight = 600; info.bmiHeader.biPlanes = 1; info.bmiHeader.biBitCount = 16; //info.bmiHeader.biCompression = BI_RGB; info.bmiHeader.biCompression = 0; //info.bmiColors = 0x00332211; info.bmiColors[0].rgbBlue = 255; info.bmiColors[0].rgbGreen = 255; info.bmiColors[0].rgbRed = 255; HDC hdcMem = CreateCompatibleDC (hdc) ; StretchDIBits(hdc, dlt_x,dlt_y, 1024,-600, 0,0, 1024,600, display, &info, DIB_RGB_COLORS, SRCCOPY); #endif #if 0 for(j=0;j<dis_high;j++) { for(i=0;i<dis_width;i++) { //if(display[j*dis_width+i] != display_1[j*dis_width+i]) { display_1[j*dis_width+i] = display[j*dis_width+i]; //ceshi = display_1[j*dis_width+i]; //if(2 == k) { SetPixel (hdc, i+dlt_x, j+dlt_y, co16_to_24(display[j*dis_width+i])) ; k = 0; } //else { k ++; } //StretchBits //FloodFill(); } } } #endif TextOut (hdc, 50, 50,(LPCWSTR)sum2,wsprintf ((LPWSTR)sum2, TEXT ("%i"),ceshi1)) ; //TextOut (hdc, 50, 80,(LPCWSTR)sum2,wsprintf ((LPWSTR)sum2, TEXT ("%i"),(ceshi2))) ; //TextOut (hdc, 50, 100,(LPCWSTR)sum2,wsprintf ((LPWSTR)sum2, TEXT ("%i"),ceshi3)) ; //TextOut (hdc, 50, 120,(LPCWSTR)sum2,wsprintf ((LPWSTR)sum2, TEXT ("%i"),ceshi4)) ; } int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: 在此放置代码。 MSG msg; HACCEL hAccelTable; int i; for(i = 0;i<dis_width*dis_high;i++) display[i]= 0x5; HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL); CloseHandle(hThread); // 初始化全局字符串 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_LINUX_SCREEN, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // 执行应用程序初始化: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_LINUX_SCREEN)); // 主消息循环: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } // // 函数: MyRegisterClass() // // 目的: 注册窗口类。 // // 注释: // // 仅当希望 // 此代码与添加到 Windows 95 中的“RegisterClassEx” // 函数之前的 Win32 系统兼容时,才需要此函数及其用法。调用此函数十分重要, // 这样应用程序就可以获得关联的 // “格式正确的”小图标。 // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_LINUX_SCREEN)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_LINUX_SCREEN); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx(&wcex); } // // 函数: InitInstance(HINSTANCE, int) // // 目的: 保存实例句柄并创建主窗口 // // 注释: // // 在此函数中,我们在全局变量中保存实例句柄并 // 创建和显示主程序窗口。 // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; // 将实例句柄存储在全局变量中 hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, 0, 0, 1920, 1080, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // 函数: WndProc(HWND, UINT, WPARAM, LPARAM) // // 目的: 处理主窗口的消息。 // // WM_COMMAND - 处理应用程序菜单 // WM_PAINT - 绘制主窗口 // WM_DESTROY - 发送退出消息并返回 // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 分析菜单选择: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); totary(hdc); InvalidateRect (hWnd, NULL, 0) ; #if 0 ceshi+=200; for(i = 0;i< 1024*600;i++) { display[i] = ceshi; } #endif EndPaint (hWnd, &ps) ; break; // TODO: 在此添加任意绘图代码... case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // “关于”框的消息处理程序。 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; }
3.linux的shell脚本,设置linux开发板的ip并运行生成的linux程序,此处192.168.10.200对应window的ip地址
运行前需要确认window和linux开发板通讯是否异常,本人测试linux开发板平window不通原因为window的防火墙未关闭,
#!/bin/sh chmod 777 uartapp ifconfig eth0 up ifconfig eth0 192.168.10.205 echo set ok ./uartapp 192.168.10.200
4.最终效果,图像折叠可能问设备树的参数不正确,不影响实际显示,实测途中图标可以被鼠标点击,时钟会走动
-
【正点原子Linux连载】第三十七章 Linux内核移植 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0
2021-08-28 10:40:231)实验平台:正点原子...3)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新 第三十七章 Linux内核移植 前两章我们简单了解了一下Linux内核顶层Makefile和Linux内核 -
【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.2.pdf
2021-08-25 22:39:21【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.2.pdf -
嵌入式Linux之正点原子Linux开发板入手
2020-03-08 16:05:11这不是开箱测评 ...受肺炎疫情的影响,历经千山万水的正点原子Linux开发板终于到了我的手上。当我拆开快递盒的那一刹那,我愣住了,我看到的是这样的盒子 发错快递了(心里犹如千万匹骏马爬过) ... -
【正点原子Linux连载】第七十章 Linux WIFI驱动实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0
2021-10-18 15:53:123)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新 第七十章 Linux WIFI驱动实验 WIFI的使用已经很常见了,手机、平板、汽车等等,虽然可以使用有线 -
【正点原子Linux连载】第四十九章 Linux按键输入实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0
2021-09-06 10:34:273)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新 第四十九章 Linux按键输入实验 在前几章我们都是使用的GPIO输出功能,还没有用过GPIO输入功能,本 -
【linux】正点原子linux教程学习
2019-12-17 10:57:46最近看了正点原子的linux教学视频,感觉讲的挺不错,简单来整理一下,对此有个印象。 linux移植三大部分 uboot linux内核(包含设备树) 根文件系统 裸机代码 视频教程中讲了nxp的imx6ull的soc... -
正点原子 linux 开发板学习 uboot 篇 一
2022-04-08 13:22:01出厂可以直接使用 原子出厂源码, 出厂源码会随时修复bug或者添加新的驱动以兼容正点原子的其他模块 学习的时候 U-Boot 烧写与启动 uboot 启动位置根据拨码开关 烧写 通过.imxdownload 工具把 编译后的u-... -
【正点原子Linux连载】第三章 初识Qt摘自【正点原子】I.MX6U嵌入式Qt开发指南V1.0.2
2022-03-28 14:49:523)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新 第三章 初识Qt 本章将介绍什么是Qt,同时与大家一起安装Qt,根据不同用户的编程习惯,这里我们介绍在Wi -
【正点原子Linux连载】第五十六章 Linux自带的LED灯驱动实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发...
2021-09-22 16:00:133)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新 第五十六章 Linux自带的LED灯驱动实验 前面我们都是自己编写LED灯驱动,其实像LED灯这样非常基础 -
【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.2.pdf
2020-03-06 15:13:34本篇讲解如何将 Uboot、 Linux 和根文件系统移植到我们的开发板上,为后面的 Linux 驱 动开发做准备。 第四篇: Linux 驱动开发 前面做了那么多的工作就是为了本篇,因此本篇注定了将是本书重中之重,大家应该... -
linux开发板 - 参考正点原子 - imx6ull开发板(AD原理图+pcb)
2022-04-04 15:56:06参考正点原子IMX6ULL Mini ARM Linux开发板画的开发板(注意是底板,需搭配正点原子的核心板使用),4层10*75cm巴掌大小,基本和正点原子的开发板一致。想DIY自己的linux功能板这个工程可以帮你减少80%的画板时间吧,... -
「正点原子Linux连载」第六十三章Linux RS232/485/GPS驱动实验
2021-05-14 19:42:091)实验平台:正点原子Linux开发板2)摘自《正点原子I.MX6U嵌入式Linux驱动开发指南》关注官方微信号公众号,获取更多资料:正点原子第六十三章Linux RS232/485/GPS驱动实验串口是很常用的一个外设,在Linux下通常通过... -
正点原子Linux阿尔法开发板4.3 寸多点电容触摸屏测试问题和gt9xx系列linux驱动移植
2022-01-21 08:12:15正点原子Linux阿尔法开发板4.3 寸多点电容触摸屏测试问题和gt9xx系列linux驱动移植4.3 寸多点电容触摸屏测试问题正点原子gt9xx系列linux驱动移植1.首先我们要获取驱动文件2.将t9xx.c和gt9xx.h放至正点原子教程源码... -
【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.1.pdf
2019-12-23 14:14:43正点原子IMX6ULL linux驱动开发文档V1.1, 1600页版本的开发手册,包含裸机开发、系统移植、linux设备驱动开发等等 -
【正点原子Linux连载】第六十七章 Linux USB驱动实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0
2021-09-27 11:14:533)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新 第六十七章 Linux USB驱动实验 USB是很常用的接口,目前大多数的设备都是USB接口的,比如鼠标、 -
正点原子linux开发文档
2022-02-14 22:04:59正点原子linux开发文档 -
【正点原子Linux连载】第三十六章 Linux内核启动流程 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0
2021-08-28 10:32:151)实验平台:正点原子...3)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新 第三十六章 Linux内核启动流程 看完Linux内核的顶层Makefile以后再来看Linux内核的大致 -
【正点原子Linux连载】第十五章点亮LED-摘自【正点原子】I.MX6U嵌入式Linux C应用编程指南V1.1
2021-08-17 10:00:013)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新 第十六章点亮LED 对于一款学习型开发板来说,永远都绕不开LED这个小小的设备,基本上每块板子都至少会有一 -
正点原子Linux开发板实现WiFi开机自动连接
2021-01-31 00:28:101.开发板使用的是正点原子阿尔法Linux开发板 2.使用的WiFi模块为正点原子配套的SDIO-WiFi模块 实现思路: 在开机运行的脚本中加入WiFi连接脚本 具体实现: 1、保存WiFi名字、密码到配置文件/etc/wpa_supplicant.... -
【正点原子Linux连载】第二十一章串口应用编程-摘自【正点原子】I.MX6U嵌入式Linux C应用编程指南V1.1
2021-08-19 15:34:483)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新 第二十一章串口应用编程 本小节我们来学习Linux下串口应用编程,串口(UART)是一种非常常见的外设,串 -
【正点原子Linux连载】第五十九章 Linux LCD驱动实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0
2021-09-23 15:18:473)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新 第五十九章 Linux LCD驱动实验 LCD是很常用的一个外设,在裸机篇中我们讲解了如何编写LCD裸机驱 -
正点原子linux教程裸机篇通用Makefile详细解读
2021-09-29 16:12:23=” 表示:如果CROSS_COMPILE已经有值,忽略该语句,如果没有值,将arm-linux-gnueabihf- 赋值给CROSS_COMPILE,这里是第一次给CROSS_COMPILE赋值,因此CROSS_COMPILE值为arm-linux-gnueabihf-) 第2行:新建变量... -
【正点原子Linux连载】第五十七章Linux MISC驱动实验-摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南 ...
2021-05-18 17:16:441 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10#include 11#include 12#include 13#include 14#include 15#include 16#... -
【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.pdf.zip
2021-08-07 21:26:56正点原子团队基于IMX6U Alpha/Mini开发板推出的教程。 v1.4版本。 很详细,适合作为初学者入门,以及相关问题来查询使用。 本着原子自身开源分享的精神的,我设置的所需下载积分是0。(可能系统会自动改成1或者其他...