1.正点原子嵌入式linux驱动开发——Linux C编程入门
2.正点原子FPGA连载第九章基于OV5640的正点字符叠加实验--领航者ZYNQ之HLS 开发指南
3.正点原子嵌入式linux驱动开发——外置RTC芯片PCF8563
4.正点原子lwIP学习笔记——ICMP协议
5.正点原子lwIP学习笔记——网络数据包管理
6.正点原子lwIP学习笔记——IP协议
正点原子嵌入式linux驱动开发——Linux C编程入门
这一章主要利用Ubuntu自带的vi编辑器进行C语言代码编写。对原理不感兴趣的原源源码读者,可以自行搜索并使用VSCode等编辑器进行操作。码正
首先,点原创建一个名为"C_Program"的下载文件夹,用于管理所有代码。正点爆店码系统源码每次编写的原源源码代码放在"C_Program"文件夹下的子文件夹中,便于管理。码正
在"/etc/vim/vimrc"文件中,点原设置tab为4个空格,下载并启用行号显示,正点通过在文件最后两行添加相应的原源源码代码实现。
设置完成后的码正vi编辑器,用于编写经典代码"Hello World!"。点原创建名为"main.c"的下载文件,内容如下:
使用"cat"命令查看内容,如图所示。
进行代码编译。Ubuntu下的C语言编译器为GCC,若Ubuntu未安装GCC工具,需手动安装gcc、g++和make等工具。通过安装"build-essential"软件包即可。安装完成后,使用命令查看,如图所示。
安装成功后,GCC编译器版本为7.5.0,适用于x架构CPU。对于ARM架构,需要使用针对ARM的GCC编译器,即交叉编译器。需记住不同架构下的GCC编译器不同。
使用GCC编译器编译"main.c"文件,GCC命令模式下输入命令,编译完成后生成可执行文件"a.out",使用命令"./a.out"执行,如图所示。
可自定义命名生成的可执行文件,在使用gcc命令时加上"-o"指定文件名,如编译"main.c"后生成名为"main"的可执行文件,操作如图所示。
GCC编译器命令格式如下,主要选项如下:
编写示例代码演示GCC错误警告,代码中有两处错误:在第8行少写了一个分号;第9行中的printf语句错误。编译后,GCC会给出错误提示,根据提示修改代码即可。
GCC编译流程包括预处理、编译、汇编和链接,APP充值网页源码预处理展开头文件、替换宏、解析条件编译;编译将预处理后的代码编译成汇编代码;汇编将汇编语言编译成二进制目标文件;链接将多个目标文件链接成可执行文件。
使用make命令进行编译,通过一个Makefile文件描述编译哪些源码文件、如何编译。Makefile跟脚本文件类似,执行系统命令,使用make命令即可自动完成工程编译,提高开发效率。在Linux下使用最多的GCC编译器,需要自行编写Makefile。
创建名为"Makefile"的文件,描述工程中需要编译的源码文件和依赖关系。在命令行输入"make"即可编译工程,可能遇到编译失败的情况。修改Makefile,确保在修改文件后能正确编译。Makefile中规则描述目标文件及其依赖文件,命令执行更新。
总结,Makefile中规则定义目标文件及其依赖文件,命令执行更新。Makefile的"终极目标"是Makefile文件中第一个规则的目标,没有指定目标时,默认为目标。Makefile变量用于简化代码,变量赋值使用"="或"==","=="只使用已定义的值。模式规则用于编译所有以特定后缀结尾的文件,自动化变量用于简化命令执行。Makefile中的伪目标不生成文件,用于避免与实际文件冲突。Makefile支持条件判断和函数调用,实现逻辑控制和字符串处理。
本章节介绍了在Linux环境下使用GCC和Makefile进行C语言代码的编译和执行。学习后可直接进行实践,实践过程中会更直观地理解操作流程。基础了解即可,具体应用需在实践中深入体会。
正点原子FPGA连载第九章基于OV的字符叠加实验--领航者ZYNQ之HLS 开发指南
基于OV的字符叠加实验:领航者ZYNQ之HLS开发详解
在领航者ZYNQ开发中,我们通过正点原子的教程,实现了基于OV摄像头的字符叠加实验。这个实验旨在将字符数据与视频图像实时叠加在LCD屏幕上,适合多媒体监控和人机界面应用。以下是实验关键步骤的概述:实验目标
任务是使用Vivado HLS工具设计并验证一个字符叠加IP核,该核能在摄像头采集的图像上叠加字符数据。步骤一:字符模提取
利用PCtoLCD软件获取汉字“正点原子”的字模,将其合并为一个大字模,以适应LCD显示需求。ai视频剪切源码步骤二:HLS设计
在F:\ZYNQ\High_Level_Synthesis目录下创建名为“text_overlay”的工程,使用C++编写源代码,利用hls_video.h库。编译后,导出为IP核。步骤三:IP验证
将生成的IP核集成到Vivado的Block Design中,将其与OV摄像头的灰度显示实验工程相结合,验证字符叠加功能。步骤四:下载验证
将设计下载到领航者开发板,通过LCD屏幕查看摄像头采集图像与字符叠加后的结果,确保功能正常。 最终,你将看到摄像头捕获的图像上叠加了预设字符,这展示了字符叠加技术在实际应用中的效果。完整教程和代码资源可在正点原子的官方渠道获取,包括实验源码、手册和视频教程。正点原子嵌入式linux驱动开发——外置RTC芯片PCF
学习正点原子STMMP开发板上的外置RTC芯片PCF驱动开发,首先了解PCF基本特性与结构。PCF是一个CMOS RTC芯片,具备时间、日历功能与可编程时钟输出、中断输出及低电压检测能力。它以两线式IIC接口进行数据传输,支持最大Kbit/S的传输速率,在读写寄存器时,地址会自动递增。其主要功能包括时钟输出、中断输出、低电压检测等。PCF的特性与结构如下:
PCF拥有个内部寄存器,全部为8位。前两个寄存器作为控制/状态寄存器,0x-0x寄存器保存时间与日期信息,0x-0x0C为闹钟寄存器,而0x0D为时钟输出频率寄存器,0x0E和0x0F为时钟控制寄存器。BCD格式用于存储时间与日期信息。
接下来,详细探讨PCF的寄存器结构与用途。控制状态寄存器1与2用于控制RTC的运行模式、停止状态与中断功能,而时间与日期寄存器则分别对应秒、分、时、日、星期、月与年。闹钟寄存器用于设定闹钟信息,时钟输出频率寄存器调整RTC的sx1280源码输出频率,时钟控制寄存器用于控制RTC的时钟输出。
此外,PCF支持中断功能,中断引脚与外部硬件相连接。Linux系统集成PCF驱动,因此在开发板上使用时,只需要在设备树中添加相应的配置信息,如IIC接口的引脚配置与中断引脚的定义。内核内部的驱动使得使用过程非常简单,只需通过修改设备树添加PCF节点信息,并使能内核中的PCF驱动即可。
硬件原理图显示PCF通过IIC接口连接到STMMP上,中断引脚连接到PI3,用于中断处理。在实验中,首先在设备树中配置IIC引脚与中断引脚信息,然后按照Linux内核提供的文档说明使用自带的PCF驱动。配置内核与设备树后,重新编译,启动开发板验证驱动功能。
测试结果显示系统可以识别PCF并提供时间信息,即使在开发板掉电后,纽扣电池仍能继续为RTC供电,确保时间的连续性。驱动源码分析揭示了核心功能在于初始化PCF并使用RTC驱动框架进行时间与闹钟的读写操作。
总结,通过设备树配置与Linux内核集成的驱动,使用PCFRTC芯片非常简便。对于IIC接口的RTC芯片驱动开发,基本思路相似,可根据实际项目需求选择合适的芯片。
正点原子lwIP学习笔记——ICMP协议
ICMP协议是一个网络层协议。一个新搭建好的网络,通常需要先进行一个基本的测试,以验证网络是否畅通;但IP协议并不提供可靠传输。如果数据包丢失了,IP协议并不能通知传输层是否丢失以及丢失的原因。因此,我们需要ICMP协议来完成这样的功能。
总结来说,为了更有效地转发IP数据报和提高交付成功机会。
ICMP协议类型与结构:对于ICMP协议中的差错报告报文,在lwIP中实现的是目的不可达以及超时的报文;对于超时报文,又分为两种,一种是生存时间TTL(在IP首部中),另一种是分片传输中,接收到一个分片后的超时等待时间超时;ICMP协议中的询问报文,lwIP实现的则是回送请求/应答报文。
无论是差错还是询问报文,前4个字节是仿wps表单源码一样的:第一个是类型,第二个是代码,例如超时就是0/1,0代表生存时间为0、1则是超时等待时间为0;后两个是校验和;之后的4个字节则是取决于ICMP报文的类型;整个ICMP的数据部分,长度取决于类型;整个ICMP报文是在网络层,可以说IP数据包包含了IP首部以及ICMP报文。
ICMP差错报文用于检测IP数据报在传输过程中的异常信息(目的不可达、源站抑制、重定向、超时、参数错误)。
ICMP类型为3,则代表了是目的不可达;lwIP实现了代码值2、3、4的差错;ICMP类型为则代表了是超时错误;代码值0代表传输期间生存时间为0,1代表数据报组装期间生存时间为0。
ICMP查询报文用于诊断两个网络设备之间是否能够通信。
lwIP只处理ICMP类型0/8,代表了回显请求/应答;目的主机收到ICMP回送请求报文后立即回送应答报文,若源主机能收到ICMP回送应答报文,则说明到达该主机的网络正常(PING)。
ICMP报文数据结构:以上结构体位于icmp.h中;包括有ICMP的类型、代码、校验和、标志符以及序号五个变量。
差错报文中,前4个字节是类型、代码和校验后;后4个字节全为0;然后传输的数据就是因其差错的IP首部以及他的pbuf的前8个字节的数据;查询报文的前4个字节与差错报文一样;后4个字节中,2格式标识符,2个事序号;数据部分则是请求报文发送和应答报文重复(就是类型为8,就是回送请求,直接把类型改为0,变成回送应答)。
lwIP只实现目的不可达、超时差错报文,它们分别为icmp_dest_unreach和icmp_time_exceeded函数;这两种差错报文都是调用icmp_send_response发送;其源码和注释如下:
以上源码的逻辑,就是根据当前的type和code判断处理方式,判断得到是差错报文,就把被丢弃数据包的pbuf中的IP首部和前8个字节数据拷贝到差错报文中(同样也是一个pbuf)。
请求报文发送,应答报文重复。简单来讲,应答包是在请求包的基础上修改得来;查询报文的源码和注释如下:
总结来说,ICMP的回送请求,把ICMP结构体的type从8改成0,然后把pbuf的payload上移个字节,添加IP首部,就变成了回送应答包。
这一篇的源码还是比较简单易懂的,没有太多要F跳转的内容,总的原理也比较清晰。
至此,lwIP的大部分协议都学完了,还剩下TCP和UDP协议,现在的lwIP框架如下:
正点原子lwIP学习笔记——网络数据包管理
TCP/IP作为一种数据通信机制,其协议栈的实现本质上是对数据包的处理。为了实现高效率的处理,lwIP数据包管理提供了一种高效的机制。协议栈各层能够灵活处理数据包,同时减少数据在各层间传递时的时间和空间开销,这是提高协议栈工作效率的关键。在lwIP中,这种机制被称为pbuf。
用户的数据经过申请pbuf,拷贝到pbuf结构的内存堆中。在应用层,数据的前面加上应用层首部,在传输层加上传输层首部,最后在网络层加上网络层首部。
pbuf用于lwIP各层间数据传递,避免各层拷贝数据!
lwIP与标准TCP/IP协议栈的区别在于,lwIP是一种模糊分层的TCP/IP协议,大大提高了数据传输效率!
这是定义在pbuf.h中的关键结构体pbuf。通过指针next构建出了一个数据包的单向链表;payload指向的是现在这个结构体所存储的数据区域;tot_len是所有的数据长度,包括当前pbuf和后续所有pbuf;而len就是指当前pbuf的长度;type_internal有四种类型;ref代表当前pbuf被引用的次数。
右边展示的pbuf_layer就是用来首部地址偏移,用来对应相应的结构体。
PBUF_RAM采用内存堆,长度不定,一般用在传输数据;PBUF_POOL采用内存池,固定大小的内存块,所以分配速度快(一般字节,就是分配3个PBUF_POOL的内存池),一般用在中断服务中;PBUF_ROM和PBUF_REF都是内存池形式,而且只有pbuf没有数据区域,数据都是直接指向了内存区(PBUF_ROM指向ROM中,PBUF_REF指向RAM中)。
左边第一幅对应PBUF_RAM;中间两幅对应PBUF_POOL;最后一幅对应PBUF_ROM和PBUF_REF。
其中PBUF_RAM和PBUF_POOL相对更为常用。
更多的函数,都可以在pbuf.c和.h中找到。pbuf_alloc()如果是PBUF_REF或者是PBUF_ROM,就会如上图所示,创建一个结构体指针p,然后会进入pbuf_alloc_reference;该函数中,会申请一个pbuf结构体大小的内存;然后调用pbuf_init_alloced_pbuf进行初始化,初始化可以如上图所示。
如果是PBUF_POOL,会定义q和last两个pbuf结构体指针,q和last都初始化为NULL,rem_len(剩余长度)初始化为(用户指定需要构建的长度);然后q会经过内存申请,qlen则是去rem_len和当前可申请的数据大小(PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset))取小值,然后同样经过pbuf_init_alloced_pbuf初始化q中的pbuf结构体;然后会把offset清零,就是说之后的pbuf都没有offset了,只有第一个链表的元素有offset;经过if判断并判断rem_len的大小,只要还有剩余就会回去循环继续执行上述操作,直到完成3个内存块的初始化。
首先会计算payload_len和alloc_len,如果是传输数据,那么LWIP_MEM_ALIGN_SIZE(offset)就是,计算得到payload_len=,alloc_len=;然后进入判断payload和alloc的长度是否
进入判断p是否为空,不为空证明还没有释放;进入while语句,每一次都--ref(引用次数);然后类似链表删除,调用相应的pbuf类型的内存释放(内存堆或者内存池),直到p全部被释放。源码如下:
这个就要看你使用的是什么类型,然后会根据类型来决定payload_len的大小,进行相应的payload指针指向数据区前的首部字段。
这一章主要讲述了lwIP中重要的pbuf缓冲,具体有哪些数据构成,为之后的学习奠定基础,确定了pbuf除了所需传输的数据,还有哪些变量需要添加,如何申请对应的pbuf内存大小,以及对应的内存堆和内存池。
正点原子lwIP学习笔记——IP协议
IP协议,作为TCP/IP协议族的核心,负责TCP、UDP、ICMP、IGMP等数据的传输(IPv4和IPv6)。它提供了无连接、不可靠的服务,这意味着数据传输不需维持对方信息,每次发送数据都需要明确目标IP地址,且不能保证数据包准确到达,只尽力而为,如发送失败会通知上层协议但不重传。
IP协议的功能包括:寻址,当主机间跨网段通信时,数据通过主机发送到路由器,路由器根据IP地址的网络号和主机号进行转发;利用路由表决定数据包的传输路径,目标网络、下一跳地址和子网掩码是关键信息;当数据包大小超过MTU(通常字节),则需要进行分片和重组。
IP协议与ARP、ICMP和IGMP等配合工作。与MAC地址(物理地址)不同,IP地址是网络层以上的标识,分为五类。理解IP协议内容,IPv4的首部结构包含字节的固定部分,如差分服务区域、总长度、标识符、标志等,以及源和目标IP地址等信息。
IP分片原理涉及MTU限制,当数据包超过MTU,就需要进行分片操作,比如字节的数据可能被分为多个片段,每个片段包含偏移量、标志等字段。pbuf内存分配和重组过程是关键,例如,使用pbuf结构存储和传递数据,TCP和IP头部会插入pbuf,通过ip_reassdata结构连接分片,直到所有分片接收完整后进行重组。
IP重组是根据到达顺序重新组合分片,lwIP处理分片时,ip_reassdata链表用于存储和管理未完整接收的数据包。源码中的函数如ip4_reass()和ip_reass_chain_frag_into_datagram_and_validate()处理了这些逻辑,确保数据包在到达目的地后正确组合。
总的来说,理解lwIP协议的这部分内容,关注核心原理和源码示例,把握数据传输的完整逻辑,包括IP首部字段、分片与重组,以及与MAC地址、TCP/IP协议的交互,是十分重要的。
正点原子寄存器版本的程序源码文件夹介绍
正点原子寄存器版本程序源码文件夹详解
正点原子的开发资源提供了寄存器版本和库函数两种源码,鉴于其在嵌入式开发中的优势,我选择深入研究寄存器版本。该版本的源码虽然结构复杂,但更贴近硬件底层,便于理解和优化。
程序源码文件夹被精心组织,以模块化和层次结构划分,有助于降低复杂度和代码管理。四个主要的子文件夹分别是:
1. HARDWARE:这个文件夹主要用于配置实验时的片外设备,如LCD和BEEP,代码设计清晰易懂,有助于理解硬件接口操作。
2.
OBJ:包含编译后的.hex文件,是单片机可执行的程序,是程序开发过程中的重要产物。
3.
USER:存放Keil工程文件,这些文件与用户界面和自定义功能紧密相关。
4.
SYSMEER:是STMFX系列的核心驱动,由《原子教你玩stm》一书提及,对于快速搭建工程至关重要。其中的子文件夹如delay、sys、usart,详细记录了底层硬件操作和通信功能。
4.1 delay文件夹包含7个处理延时的函数,对于控制程序执行节奏很有帮助。
4.2 sys文件夹包含了系统相关功能,如sys.c处理寄存器定义和IO口操作,sys.h定义了IO口操作的宏,使得编写代码更加直观。
4.2.2 sys.c则负责配置系统时钟、IO口和中断,是系统初始化的核心部分。
4.3 usart文件夹涉及串口通信,usart.c提供了串口初始化和中断接收的函数,还支持串口printf功能,对通信功能的实现至关重要。
这些文件夹和文件的详细结构,为嵌入式开发人员提供了一个清晰的框架,使得代码调试和维护更加便捷。
正点原子嵌入式linux驱动开发——TF-A使用
TF-A,即Arm Trusted Firmware,是ARM推出的用于硬件隔离和提供安全服务的开源软件,最初针对Armv8-A架构,ST的STMMP1系列芯片内置TrustZone支持,因此使用了TF-A。TF-A的主要作用是创建一个安全环境,为硬件提供保护,并提供安全服务。TF-A的使用涉及硬件和软件两个方面,硬件有TrustZone解决方案,而软件则包括TF-A本身。
获取TF-A源码是TF-A使用流程中的重要步骤。通常,直接从官方下载源码的难度较大,因此半导体厂商会从TF-A官网下载源码,并根据自身芯片进行修改和适配。在实际项目开发中,直接使用半导体厂商提供的TF-A源码即可。
获取TF-A源码的步骤如下:
1. 从ST官方获取STMMP1系列的系统源码包,包括TF-A、Uboot、kernel等。例如,en.SOURCES-stmmp1-openstlinux-5-4-dunfell-mp1---.tar.xz。
2. 在Ubuntu系统中创建目录存放源码,并将官方源码包解压到此目录。解压后的文件夹名为stmmp1-openstlinux-5.4-dunfell-mp1---。
3. 进入源码包中,找到包含uboot、optee、tf-a、kernel的源码文件夹,理解每个文件夹的含义。
4. TF-A源码是ST移植到MP1芯片上的,经过了ST的修改和优化,可以直接使用ST提供的TF-A源码,包括uboot和Linux kernel。
TF-A源码需要进行补丁处理以适应特定的硬件环境。补丁文件(后缀为.patch)通常由原始作者提供给特定的硬件厂商,用于修改源码以适应特定的硬件配置。补丁文件在TF-A源码目录下进行应用,以确保源码能够正常编译和运行在特定的硬件上。
使用VSCode可以更方便地阅读和管理TF-A源码。在创建VSCode工程时,选择打开解压后的TF-A源码文件夹,VSCode左侧资源管理器将显示工程目录结构,便于理解和追踪源码。最后,保存工作区,以便在后续开发中快速访问。
编译和烧录TF-A是TF-A使用过程中的关键步骤。TF-A源码通常需要根据特定的硬件环境进行修改和编译,以确保在实际设备上正常运行。在编译TF-A后,需要通过STMCubeProgrammer工具将其烧录到开发板中。该过程涉及配置STMCubeProgrammer的FlashLayout文件,以指定TF-A的烧录路径和相关参数,确保TF-A能够正确加载并运行。
总结而言,TF-A的使用涉及到获取源码、进行补丁处理、编译源码、配置烧录工具和烧录TF-A到开发板等多个步骤。通过这些步骤,开发者能够将TF-A集成到STMMP1系列芯片的系统中,为设备提供安全的运行环境。