正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-19.1讲 串口格式化输出printf

前言:

本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM(MX6U)裸机篇”视频的学习笔记,在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。

引用:

正点原子IMX6U仓库 (GuangzhouXingyi) - Gitee.com

《【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.2.pdf》

正点原子资料下载中心 — 正点原子资料下载中心 1.0.0 文档

正文:

本文是 “正点原子[第二期]Linux之ARM(MX6U)裸机篇--第19 讲” 的读书笔记。第19讲主要是介绍I.MX6U处理器的UART串口并实现串口UART的字符格式化打印实验。本节将参考正点原子的视频教程第18讲和配套的正点原子开发指南文档进行学习。

0. 概述

上一章实验我们实现了 UART1 基本的数据收发功能,虽然可以用来调试程序,但是功能太单一了,只能输出字符。如果需要输出数字的时候就需要我们自己先将数字转换为字符,非常的不方便。学习 STM32 串口的时候我们都会将 printf 函数映射到串口上,这样就可以使用printf 函数来完成格式化输出了,使用非常方便。本章我们就来学习如何将 printf 这样的格式化函数移植到 I.MX6U-ALPHA 开发板上。

1. 串口格式化函数简介

格式化函数说的是 printf, sprintf 和 scanf 这样的函数,分为格式化输出和格式化输入两类函数。学习C语言的时候常常会通过 printf 函数在屏幕上显示字符串,通过 scanf 函数从键盘获取输入。这样就用了输入和输出了,实现了最基本的人机交互。学习STM32的时候会将 printf 映射到串口上,这样即使没有屏幕,也可以通过串口和开发板进行交互。在 I.MX6U-ALPHA 开发板上也可以使用此方法,将  printf 和 scanf 映射到串口上,这样就可以使用 SecureCRT 作为开发板的终端,完成与开发板的交互。也可以使用 printf 和 sprintf 来实现各种各样的格式化字符串,方便我们后续的开发。串口驱动我们上一章已经编写完成了,而且实现了最基本的字节收发,本章我们就通过移植网上别人已经做好的文件来实现格式化函数。

2. 硬件原理分析

本章所需的硬件和上一章相同

3. 实验程序编写

本章实验所需要移植的源码已经放到了开发板光盘中,路径为: 1、例程源码->5、模块驱动源码->2、格式化函数源码->stdio,文件夹 stdio 里面的文件就是我们要移植的源码文件。本章实验在上一章例程的基础上完成,将 stdio 文件夹复制到实验工程根目录中,如图 22.3.1 所示:

stdio 里面有两个文件夹: include 和 lib,这两个文件夹里面的内容如图 22.3.2 所示:

图 22.3.2 就是 stdio 里面的所有文件, stdio 里面的文件其实是从 uboot 里面移植过来的。后面学习 uboot 以后大家有兴趣的话可以自行从 uboot 源码里面“扣”出相应的文件,完成格式化函数的移植。这里要注意一点, stdio 中并没有实现完全版的格式化函数,比如 printf 函数并不支持浮点数,但是基本够我们使用了。

将正点原子提供的示例源码中的"stdio"文件夹放到本实验的 "14_printf" 目录中,然后修改Makefile 将移植的"stdio"目录放到编译源文件里。

3.1 Makefile编译错误1

执行 "make" 命令进行编译,此时编译器报如下错误提示:

 在正点原子的视频教程和指导文档里说明了解决此编译错误的方法是修改Makefile,在Makefile编译命令里加上如下编译选项 "-Wa,-mimplicit-it=thumb"【ARM 嵌入式 编译系列 2.3 -- GCC 编译参数学习 -Wa,-mimplicit-it=thumb 使用介绍】-CSDN博客文章浏览阅读750次,点赞12次,收藏8次。在使用编译 ARM 架构代码时,你可能会碰到一些控制汇编器行为的编译器选项。-wa是一个 GCC 编译器选项,用于向汇编器传递参数。-wa。_-wa,-mimplicit-it=thumbhttps://blog.csdn.net/sinat_32960911/article/details/135645189

$(COBJS) : obj/%.o : %.c$(CC) -Wall -nostdlib -fno-builtin -Wa,-mimplicit-it=thumb $(INCLUDE) -O2 -c -o $@ $<

 3.2 Makefile编译错误2

执行 "make" 命令进行编译,此时编译器报如下错误提示:

"__aeabi_uidiv" 用来实现ARM无符号数除法,编译链接器报错的是因为 ARM 是RISC精简指令集没有算术除法指令,所以在ARM裸机开发(也包括Uboot)里面的除法运算需要使用到 GCC 编译器提供的 libgcc.a 库里提供的ARM汇编除法函数实现。一般从uboot或者Kernel内核里能够找到ARM汇编除法函数的实现 "__aeabi_uidiv" 。

LIBPATH		:= -lgcc -L /home/dimon/I.MX6U/tool/gcc-linaro-4.9.4-2017.01-i686_arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/4.9.4/
#LIBGCCA		:= /home/dimon/I.MX6U/tool/gcc-linaro-4.9.4-2017.01-i686_arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/4.9.4/libgcc.a$(TARGET).bin : $(OBJS)echo $(LD) $(TARGET).elf
#	$(LD) -Timx6u.lds  $(LIBPATH) -o $(TARGET).elf $^ $(LIBGCCA) $(LD) -Timx6u.lds  -o $(TARGET).elf $^ $(LIBGCCA) $(LIBPATH)$(OBJCOPY) -O binary -S $(TARGET).elf $(TARGET).bin$(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis
#	$(OBJDUMP) -d -s -m arm $(TARGET).elf > $(TARGET).dis

注意这里经过我的测试发现 "$(LIBPATH)" 需要写在链接命令的最后,刚开始我将"$(LIBPATH)" 写在了链接命令的中间部分链接的时候编译器一直报错,即使我们修改Makefiel指定了链接路径。

div64.c:(.text+0x22): undefined reference to `__aeabi_uidiv'
make: *** [printf.bin] Error 1

 这里"$(LIBPATH)"在链接命令里先后顺序影响到最终链接结果是否成功的原因是和GCC LD 连接器的文件链接顺序机制有关系。在《程序员的自我修养-链接装载与库》中好像介绍过这一部分,印象中好像是先在链接.o文件的时候发现找不到某个符号,然后去搜索 "-Lxx -lxx" 指令的库文件中去搜索未定义的符号,如果先在链接命令里指定了"-Lxx -lxx"此时没有未定义符号的话就忽略掉了,记得号向是这样解释的。

好了,这里注意 "$(LIBPATH)" 需要写在链接命令的最后。

4. prinf格式化源码编写

移植好以后就要测试相应的函数工作是否正常,我们使用 scanf 函数等待键盘输入两个整数,然后将两个整数进行相加并使用 printf 函数输出结果。在 main.c 里面输入如下内容。

#include "cc.h"
#include "bsp_clk.h"
#include "bsp_led.h"
#include "bsp_delay.h"
#include "bsp_beep.h"
#include "bsp_gpio.h"
#include "bsp_key.h"
#include "bsp_int.h"
#include "bsp_exti.h"
#include "bsp_epittimer.h"
#include "bsp_keyfilter.h"
#include "bsp_delay.h"
#include "bsp_uart.h"
#include "stdio.h"char *banner = 	"========================================================\r\n""正点原子I.MX6ULL ALPHA/Mini开发板Linux驱动之ARM逻辑开发\r\n" \"--Date: 	2024/05/21\r\n" \"--Author: 	ChenHaoxu, Dimon.chen, 11813202388@qq.com\r\n" \"========================================================\r\n";int main(void)
{static uint8_t led_state = OFF;// static uint8_t beep_state = OFF;int_init();			/* 中断初始化 */imx6u_clkinit();	/* 时钟主频初始化,PLL1, PLL2, PLL3 */clk_init();			/* 使能所有外设时钟 */led_init();			/* led gpio 初始化 */beep_init();		/* beep gpio 初始化 *///key_init();			/* key gpio 初始化 */exti_init();		/* gpio外设中断初始化 *///epittimer_init(0, 0, 33000000);	/* EPIT分频frac=0 1分频,EPIT1时钟源66MHz,EPIT1->LR加载值计数器=33MHz,定时周期为500ms *///epittimer_init(1, 0, 66000000/20);	/* EPIT分频frac=0 1分频,EPIT1时钟源66MHz,EPIT1->LR加载值计数器=33MHz,定时周期为1000/20=50ms */keyfilter_init();delay_init();uart_init();		/* UART初始化 */led_switch(LED_0, ON);beep_switch(ON);delay(200);beep_switch(OFF);delay(200);beep_switch(ON);delay(200);beep_switch(OFF);printf("%s", banner);unsigned int a = 10;while(1){led_state = !led_state;led_switch(LED_0, led_state);printf("Hello World\r\n");printf("a=%d hex=%x\r\n", a, a);scanf("%u", &a);}return 0;
}

5. 编译烧写SD卡验证实验结果

译修改主频后源码烧录SD卡验证本节的 I.MX6U UART串口实验。预期烧录SD卡后正点原子I.MX6ULL ALPHA/Mini 开发板后,UART串口可以在串口工具,如SecureCRT或者Xshell上打印字符串输出。

我本地验证的结果是基于GPT定时器的高精度延时实验结果正常,UART串口可以在串口工具XShell上打印字符串。

6. 总结和实验遇到的问题记录

本节移植了正点原子示例源码中的 printf 格式化打印函数,之后就可以在串口中实现字符串格式化打印来调试I.MX6U ARM 裸机开发板了,这样会方便很多。本节实验里遇到的问题主要是移植 printf 函数时的编译报错问题,需要修改Makefile解决,makefile修改方法在正点原子的教程里和网上博客里有多用说明,本文也记录了解决问题的详细步骤。

7. 结束

本文至此结束。


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/333425.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络攻防概述(基础概念)

文章目录 APTAPT概念APT攻击过程 网络空间与网络空间安全网络空间(Cyberspace)网络空间安全(Cyberspace Security) 网络安全属性机密性(Confidentiality或Security)完整性(Integrity)可用性&#xff08;Availability&#xff09;不可否认性&#xff08;Non-repudiation&#xf…

Vue.js - 计算属性与侦听器 【0基础向 Vue 基础学习】

文章目录 计算属性 computedcomputed 的使用方法computed 与 method 的区别计算属性完整写法 watch 侦听器&#xff08;监视器&#xff09;简单写法 → 简单类型数据&#xff0c;直接监视完整写法 → 添加额外配置项 计算属性 computed computed 的使用方法 **概念&#xff1…

01Python相关基础学习

Python基础 模块相关导入模块sys模块 模块相关 导入模块 1. import 模块名 2. import 模块名 as 别名 3. from 模块名 import 成员名 as 别名sys模块 1. sys.argv 介绍: 实现从程序的外部想程序传递参数返回的是一个列表,第一个元素是程序文件名,第二个元素是程序外部传入的…

K8s的常用命令以及yaml文件的创建

目录 一、声明式管理方法&#xff1a;YAML文件 1、yaml文件简介 2、yaml和json的主要区别&#xff1a; 3、YAML的语法格式 4、yaml文件组成部分 ①控制器定义 5、查看api资源版本标签 6、编写nginx-deployment.yaml资源配置清单 6.1创建资源对象 6.2查看创建的pod资源…

Spring Boot:SpringBoot 如何优雅地定制JSON响应数据返回

一、前言 目前微服务项目中RESTful API已经是前后端对接数据格式的标配模式了&#xff0c;RESTful API是一种基于REST&#xff08;Representational State Transfer&#xff0c;表述性状态转移&#xff09;原则的应用程序编程接口&#xff08;Application Programming Interfac…

GEE27:遥感数据可用数据源计算及条带号制作

1.写在前面 &#x1f30d;✨今天读了一篇关于遥感数据可用数据源计算及条带号制作的文章&#xff0c;结合着自己的理解&#xff0c;添加了一些内容。 2.GEE代码 &#x1f4da;&#x1f4da;这段代码的主要作用是利用Google Earth Engine平台&#xff0c;通过分析Landsat 8影…

【C++ 】学习问题及补充

一.自定义类型不初始化直接就赋值&#xff0c;比如string类会怎么样 vectr<string>里已经给每个string对象已经分配好空间&#xff0c;为什么不初始化再赋值会报错 在C中&#xff0c;std::string类是一个动态字符串类&#xff0c;它内部管理着一个字符数组&#xff0c;用…

【常用的队列总结】

文章目录 队列的介绍Queue队列的基本概念与操作队列的基本概念 常见的队列介绍非阻塞队列LinkedList:ArrayDeque:PriorityQueue: 阻塞队列ArrayBlockingQueueLinkedBlockingQueuePriorityBlockingQueue DelayQueueSynchronousQueue 队列的介绍 Queue队列的基本概念与操作 在 …

知攻善防应急响应靶机训练-Web3

前言 本次应急响应靶机采用的是知攻善防实验室的Web-3应急响应靶机 靶机下载地址为&#xff1a; https://pan.quark.cn/s/4b6dffd0c51a 相关账户密码 用户:administrator 密码:xj123456xj123456 解题过程 第一题-攻击者的两个IP地址 直接查看apache的log日志搜索.php 发现…

【学习笔记】Windows GDI绘图目录

题外话 不知几时开始&#xff0c;觉得学习过程中将内容记录下来&#xff0c;有助于加强记忆&#xff0c;还方便后续查找&#xff0c;顺便帮助有需要的人&#xff0c;更有来自您阅读、点赞、收藏和评论时给我带来的动力与兴奋。 目录 【学习笔记】Windows GDI绘图(一)图形概述…

Python操作MySQL数据库的工具--sqlalchemy

文章目录 一、pymysql和sqlalchemy的区别二、sqlalchemy的详细使用1.安装库2.核心思想3.整体思路4.sqlalchemy需要连接数据库5.使用步骤1.手动提前创建数据库2.使用代码创建数据表3.用代码操作数据表3.1 增加数据3.2 查询数据3.3 删除数据3.4 修改数据 一、pymysql和sqlalchemy…

vs code怎么补全路径,怎么快捷输入文件路径

安装插件&#xff1a; 链接&#xff1a;https://marketplace.visualstudio.com/items?itemNamejakob101.RelativePath 使用 按住 Ctrl Shift H&#xff0c;弹出窗口&#xff0c;输入文件补全&#xff0c;回车就可以了 排除文件 如果你的项目下文件太多&#xff0c;它会…

Ubuntu22.04之解决:忘记登录密码(二百三十二)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

有哪些永久免费的进销存管理软件?

我明白许多中小企业在寻求进销存系统时&#xff0c;希望能找到一款完全免费的解决方案&#xff0c;以减轻经济压力。这种心态非常正常&#xff0c;毕竟成本是任何企业都需要仔细考虑的因素。然而&#xff0c;我要强调的是&#xff0c;市场上那些声称“完全免费”的进销存系统&a…

【FixBug】超级大Json转POJO失败

今天遇到了一个问题&#xff1a;使用Jackson将一个超级大的JSON字符串转换POJO失败&#xff0c;debug看没问题&#xff0c;将JSON字符串粘贴到main方法中测试&#xff0c;提示错误信息如下&#xff1a; 自己猜测是因为字符串超长导致转换时先截断字符串导致JSON格式不正确&…

BFS解决最短路问题(详解)

目录 BFS简介 && 框架&#xff1a; 一.二叉树的最小深度 二&#xff1a;迷宫中里入口最近的出口&#xff1a; 三.最小基因变化: 四&#xff1a;单词接龙&#xff1a; ​五&#xff1a;为高尔夫比赛砍树&#xff1a; BFS简介 && 框架&#xff1a; 说到BFS…

linux centos tomcat启动内存泄漏

tomcat启动内存泄漏 经过与开发沟通&#xff0c;结果是开发写了死循环&#xff0c;导致内存泄漏&#xff0c;上一次是开发少打了一个jar包&#xff0c;让开发查代码就行&#xff0c;重新更新代码

【python】python商家会员数据分析可视化(源码+数据集+课程报告论文)

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

Elasticsearch之文本分析

文本分析基本概念 官网&#xff1a;Text analysis | Elasticsearch Guide [7.17] | Elastic 官网称为文本分析&#xff0c;这是对文本进行一直分析处理的方式&#xff0c;基本处理逻辑是为按照预先制定的分词规则&#xff0c;把原本的文档进行分割成多个小颗粒度的词项&#x…

每天五分钟深度学习框架pytorch:tensor张量的维度转换大全

本文重点 在深度学习中比较让人头疼的一点就是矩阵的维度,我们必须构建出符合神经网络维度的矩阵,只有将符合要求的矩阵放到神经网络中才可以运行神经网络,本节课程我们将学习以下tensor中维度的变化。 view和shape View和shape,这两个方法可以完成维度的变换操作,而且使…