精华内容
下载资源
问答
  • 基于正点原子Linux开发板(ALIENTEK I.MX6U ALPHA V2.2)的个人自学记录
    千次阅读
    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入门篇208小时58分 8秒0天 8小时58分 8秒
    【第二期】手把手教你学Linux之ARM(MX6U)裸机篇7639小时57分 2秒1天15小时57分 2秒
    【第三期】手把手教你学Linux之系统移植和根文件系统构建5629小时23分22秒1天 5小时23分22秒
    【第四期】手把手教你学 Linux之驱动开发篇14669小时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命令130:41
    P7第6.2讲 Ubuntu终端操作与Shell命令229: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工程管理实验-编写测试通用Makefile34: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讲 串口实验-串口驱动实验编写与验证129:55
    P44第19.3讲 串口实验-串口驱动实验编写与验证230: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主机控制器驱动程序编写138:36
    P63第23.4讲 I2C实验-I2C主机控制器驱动程序编写233: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讲 多点电容触摸屏实验-电容触摸屏幕驱动编写135:52
    P73第25.3讲 多点电容触摸屏实验-电容触摸屏幕驱动编写231: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编译-什么是uboot29: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过程详解126:40
    P22第6.9讲 Uboot启动流程详解-bootz启动Linux过程详解231: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总线简介131:09
    P56第16.4讲 platform设备驱动实验-platform总线简介219: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 串口实验-使能UART312: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块设备驱动实验-块设备驱动框架分析124:26
    P116第29.2讲 Linux块设备驱动实验-块设备驱动框架分析223: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_device14:22
    P124第30.5讲 Linux网络驱动实验-Linux驱动框架详解之net_device_ops&sk_buff&NAPI217: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开发板的屏幕使用
  • 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、创建VSCODE移植工程 二、修改根目录下Makefile 三、添加自己的linux开发板 ...学习正点原子I.MX6ULL移植内...

    目录

    前言

    一、创建VSCODE移植工程

    二、修改根目录下Makefile

     三、添加自己的linux开发板

           1、创建linux开发板配置文件

           2、创建linux开发板设备树文件

           3、修改编译文件

    四、编译并通过网络验证移植

            1、配置uboot环境变量bootargs

            2、修改bootcmd变量

    五、修改网络驱动

            1、修改EMMC模式

            2、修改 LAN8720 的复位以及网络时钟引脚驱动

            3、使能LAN8720驱动

            4、修改smsc.c文件

    总结



    前言

    学习正点原子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.dts    

           3、修改编译文件

            .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内核,一步一步来

    展开全文
  • 3)对正点原子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语言应用工程,具体的步骤的就不再演示了。
    本小节内容到此结束。

    展开全文
  • 正点原子团队基于IMX6U Alpha/Mini开发板推出的教程。 v1.4版本。 很详细,适合作为初学者入门,以及相关问题来查询使用。 本着原子自身开源分享的精神的,我设置的所需下载积分是0。(可能系统会自动改成1或者其他...
  • 买个正点原子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.最终效果,图像折叠可能问设备树的参数不正确,不影响实际显示,实测途中图标可以被鼠标点击,时钟会走动

    软件地址https://download.csdn.net/download/qq_43683623/82474709

    展开全文
  • 1)实验平台:正点原子...3)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新 第三十七章 Linux内核移植 前两章我们简单了解了一下Linux内核顶层Makefile和Linux内核
  • 正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.2.pdf
  • 这不是开箱测评 ...受肺炎疫情的影响,历经千山万水的正点原子Linux开发板终于到了我的手上。当我拆开快递盒的那一刹那,我愣住了,我看到的是这样的盒子 发错快递了(心里犹如千万匹骏马爬过) ...
  • 3)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新 第七十章 Linux WIFI驱动实验 WIFI的使用已经很常见了,手机、平板、汽车等等,虽然可以使用有线
  • 3)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新 第四十九章 Linux按键输入实验 在前几章我们都是使用的GPIO输出功能,还没有用过GPIO输入功能,本
  • 【linux】正点原子linux教程学习

    千次阅读 2019-12-17 10:57:46
      最近看了正点原子linux教学视频,感觉讲的挺不错,简单来整理一下,对此有个印象。 linux移植三大部分 uboot linux内核(包含设备树) 根文件系统 裸机代码   视频教程中讲了nxp的imx6ull的soc...
  • 出厂可以直接使用 原子出厂源码, 出厂源码会随时修复bug或者添加新的驱动以兼容正点原子的其他模块 学习的时候 U-Boot 烧写与启动 uboot 启动位置根据拨码开关 烧写 通过.imxdownload 工具把 编译后的u-...
  • 3)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新 第三章 初识Qt 本章将介绍什么是Qt,同时与大家一起安装Qt,根据不同用户的编程习惯,这里我们介绍在Wi
  • 3)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新 第五十六章 Linux自带的LED灯驱动实验 前面我们都是自己编写LED灯驱动,其实像LED灯这样非常基础
  • 本篇讲解如何将 Uboot、 Linux 和根文件系统移植到我们的开发板上,为后面的 Linux 驱 动开发做准备。 第四篇: Linux 驱动开发 前面做了那么多的工作就是为了本篇,因此本篇注定了将是本书重中之重,大家应该...
  • 参考正点原子IMX6ULL Mini ARM Linux开发板画的开发板(注意是底板,需搭配正点原子的核心板使用),4层10*75cm巴掌大小,基本和正点原子的开发板一致。想DIY自己的linux功能板这个工程可以帮你减少80%的画板时间吧,...
  • 1)实验平台:正点原子Linux开发板2)摘自《正点原子I.MX6U嵌入式Linux驱动开发指南》关注官方微信号公众号,获取更多资料:正点原子第六十三章Linux RS232/485/GPS驱动实验串口是很常用的一个外设,在Linux下通常通过...
  • 正点原子Linux阿尔法开发板4.3 寸多点电容触摸屏测试问题和gt9xx系列linux驱动移植4.3 寸多点电容触摸屏测试问题正点原子gt9xx系列linux驱动移植1.首先我们要获取驱动文件2.将t9xx.c和gt9xx.h放至正点原子教程源码...
  • 正点原子IMX6ULL linux驱动开发文档V1.1, 1600页版本的开发手册,包含裸机开发、系统移植、linux设备驱动开发等等
  • 3)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新 第六十七章 Linux USB驱动实验 USB是很常用的接口,目前大多数的设备都是USB接口的,比如鼠标、
  • 正点原子linux开发文档
  • 1)实验平台:正点原子...3)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新 第三十六章 Linux内核启动流程 看完Linux内核的顶层Makefile以后再来看Linux内核的大致
  • 3)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新 第十六章点亮LED 对于一款学习型开发板来说,永远都绕不开LED这个小小的设备,基本上每块板子都至少会有一
  • 1.开发板使用的是正点原子阿尔法Linux开发板 2.使用的WiFi模块为正点原子配套的SDIO-WiFi模块 实现思路: 在开机运行的脚本中加入WiFi连接脚本 具体实现: 1、保存WiFi名字、密码到配置文件/etc/wpa_supplicant....
  • 3)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新 第二十一章串口应用编程 本小节我们来学习Linux下串口应用编程,串口(UART)是一种非常常见的外设,串
  • 3)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新 第五十九章 Linux LCD驱动实验 LCD是很常用的一个外设,在裸机篇中我们讲解了如何编写LCD裸机驱
  • =” 表示:如果CROSS_COMPILE已经有值,忽略该语句,如果没有值,将arm-linux-gnueabihf- 赋值给CROSS_COMPILE,这里是第一次给CROSS_COMPILE赋值,因此CROSS_COMPILE值为arm-linux-gnueabihf-) 第2行:新建变量...
  • 1 #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#...
  • 正点原子团队基于IMX6U Alpha/Mini开发板推出的教程。 v1.4版本。 很详细,适合作为初学者入门,以及相关问题来查询使用。 本着原子自身开源分享的精神的,我设置的所需下载积分是0。(可能系统会自动改成1或者其他...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,383
精华内容 1,753
关键字:

正点原子linux

友情链接: autoCAD.rar