串口内核打印
干货FreeRTOS学习笔记——实验:串口后台打印
干货FreeRTOS学习笔记——实验:串口后台打印EEWorld电子资讯犀利解读技术干货每日更新现在来探讨一下如何利用FreeRTOS 的服务来为单片机程序设计提供方便,也感受下引入FreeRTOS 后系统处理效率的变化。
我想了个简单的常用需求:串口的“后台”打印输出(单片机开发时常用于调试信息输出),来进行实验。
串口(异步串行通讯口的简称, UART)相对于 CPU 是一个低速的设备,一般较高通信速率为115200bit/s,在此速率下输出一个8-bit 字符(假设用1个起始位,1个停止位,无校验)用的时间为87us. CPU 将字符写入串口的发送数据寄存器需要的时间可以忽略,但是由于串口硬件FIFO很小,务必要等待发送数据寄存器允许写入时才可以进行写操作。
于是,简单的程序设计中就不断查询标志位,等待寄存器可以写了就写一个字符,直到要发送的字符串写完。
要照顾执行效率的时候一定不能这么做,特别是在多任务环境下,因为这种循环重复查询标志位的做法让其它任务也只能等待,没有利用CPU处理能力。
于是我们需要一种“后台”输出的方法,让当前任务将要从串口输出的字符串提交到系统之后,程序往下执行,不用等待字符串从串口发送完;或者是当前任务等待字符串发送完,但是其它任务可以执行。
以下我的实验代码在ST Nucleo-L4R5ZI 板子上运行,也很容易改动一下以在其它 STM32 上运行(不过 STM32L4R5 的SRAM大,方便挥霍)。
在这块开发板上,USB串口连接到了STM32L4R5 的LPUART1, 我就编写一个 uart_puts(char *) 函数来从 LPUART1 输出字符串。
LPUART1 的TDR 寄存器时候用来写要发送的数据的,发送完成等状态可以从ISR 寄存器获取。
当然为了实现后台工作,中断是需要用到的了。
1简单直接的办法——字符队列不能反复查询,那么就让 LPUART1 的 TDR 寄存器可以写的时候,产生一个中断来告诉CPU,该写字符了。
linux_虚拟串口实现方法_概述及解释说明
linux 虚拟串口实现方法概述及解释说明1. 引言1.1 概述本文将介绍Linux下实现虚拟串口的方法,并对每种方法进行解释说明。
虚拟串口指的是一种软件仿真的串口设备,可以模拟物理串口的功能,实现数据的收发和传输。
在Linux系统中,使用虚拟串口可以满足一些特定场景下的需求,如开发、测试和调试等。
1.2 文章结构本文按照以下结构进行组织:- 第一部分为引言,对文章进行概述,并介绍文章的结构和目标;- 第二部分将介绍虚拟串口的背景知识,包括串口通信原理、虚拟串口定义与作用以及Linux中虚拟串口的应用场景;- 第三部分将详细介绍Linux下实现虚拟串口的三种方法:内核模块方式、用户空间模拟方式和设备树(DT)方式;- 第四部分将对每种实现方法进行解释说明,包括其原理、特点和适用情况;- 第五部分为总结与展望,对文章内容进行总结并展望未来发展方向。
1.3 目的本文旨在提供一个全面且清晰的介绍Linux下实现虚拟串口方法的资料,帮助读者理解虚拟串口的概念和原理,并根据实际需求选择合适的实现方法。
通过阅读本文,读者将了解到不同实现方法的优缺点,以及它们在不同场景下的应用情况。
同时,本文也对未来虚拟串口技术的发展进行展望。
2. 虚拟串口的背景:2.1 串口通信的基本原理:串口是一种用于在计算机和外部设备之间进行数据传输的通信接口。
它通过一个物理连接,使用一组控制信号和数据信号来实现双向通信。
串口通信具有简单、可靠、广泛应用等特点,因此在许多领域都得到了广泛应用,如电脑与打印机、调制解调器、路由器等设备之间的连接。
2.2 虚拟串口的定义与作用:虚拟串口是对物理串口进行仿真或模拟的一种技术。
它通过软件方式模拟了一个不存在的串行接口,使得应用程序可以通过虚拟串口与外部设备进行通信。
虚拟串口具有操作灵活、易于扩展等特点,可以提供与物理串口相似或更强大的功能。
2.3 虚拟串口在Linux中的应用场景:在Linux系统中,虚拟串口广泛应用于各种嵌入式系统开发和调试场景。
IAR5.40中stm32用printf打印语句到串口
IAR EWARM 5.40和J-LinkV8调试STM32四、一、开发工具:u开发环境:IAR EWARM 5.40u固件库:V2.0.3,09/22/2008 (下载的压缩包为um0427)u仿真器:J-Link V8u开发板:ALIENTEK开发板二、参考资料u思蜕盟网站:《printf应用范例》u Ourdev论坛:《stm32 printf 问题》、《请教如何在IAR上使用代码库自带的printf函数》、《IAR环境下怎样定制printf打印语句到指定的串口上》三、部分源代码(1)在IAR中设置全库。
在Workspace中,选择XXX-Debug,然后点击鼠标右键,选择“Options”,在“General Options ->Library configuration -> Library”里面选择Full,见图1。
在“Library Options ”里面也选择Full,见图2。
(2)在main函数前面添加如下的代码。
#include <stdio.h>#ifdef __GNUC__/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf set to 'Yes') calls __io_putchar() */#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)1#else#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)#endif /* __GNUC__ *//******************************************************************************** Function Name : PUTCHAR_PROTOTYPE* Description : Retargets the C library printf function to the USART.* Input : None* Output : None* Return : None*******************************************************************************/PUTCHAR_PROTOTYPE{/* Write a character to the USART */USART_SendData(USART1, (u16) ch);/* Loop until the end of transmission */while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET) {}return ch;}2图13图24图35。
DMA实现串口打印
DMA1_Channel4->CNDTR = (u32)sizeof(SendBuff);//传输数据量 DMA1_Channel4->CCR = 0x00000000;//复位 DMA1_Channel4->CCR |= 1<<4;//从内存读数据 DMA1_Channel4->CCR |= 0<<5;//不执行循环模式 1
定期更新总结,专注 STM32 寄存器配置,实现简单的功能
本次实验主要是利用 STM32 的 DMA 控制串口打印,将一个数组当中字符通过 DMA 方式传 送到调试助手以屏幕输出。 首先,我们需要配置串口相关的 IO,这个在战舰开发板中已经完全写好。 我们需要做的就是配置 DMA 的工作模式,并且打开串口的 DMA 工作方式。 这里非常重要的是串口的 DMA 工作方式是在 CR3 中配置的,在程序中我们通过以下语句实 现:USART1->CR3 |= 1<<7;//开启 USART 的 DMA 发送模式 其次就是要配置与串口对应的 DMA 通道,从下图中刻意看出,与串口发送对应的是 DMA 的通道 4,这个在配置中不能出错。以上两项配置好后,基本功能就能实现。
int main(void)
{
Stm32_Clock_Init(9); //系统时钟设置
uart_init(72,9600); delay_init(72);
//串口初始化为 9600 //延时初始化
LED_Init(); // LCD_Init();
//初始化与 LED 连接的硬件接口 //初始化 LCD
DMA1_Channel4->CCR |= 0<<6;//外设地址不自增 DMA1_Channel4->CCR |= 1<<7;//内存地址自增
串口驱动程序的编写总结(一)
串⼝驱动程序的编写总结(⼀)8250/16450/16550芯⽚都⽤同个8250驱动1、对现有驱动进⾏拷贝,然后进⾏局部修改2、不必过多深⼊系统内核驱动的调⽤过程,区分好哪些是需要修改的,哪些是内核驱动⾃带的3、对于要修改的内容,参考别⼈成功的例⼦,看哪些需要修改的4、必要时,可以先把原拷贝先不加载进驱动,把⾃⼰拷贝的驱动加载进去5、谨记要实现的功能,按步骤实现6、知道每个模块的作⽤与功能,哪些是涉及硬件,哪些是涉及系统的,⼀般来说,进⾏设备、驱动的注册时,⼀般不涉及驱动,只有应⽤层调⽤时才进⾏硬件的相关调⽤。
7、对串⼝驱动程序的改造时如果是采⽤外部模块加载的⽅式,即insmod⽅式,⽽不是内置于内核⽣成vmlinux,则不能使⽤console驱动,否则编译会出现error: redefinition of '__inittest'/opt/kangear/hello/hello.c:16: note: previous definition of '__inittest' was here错误,会出现重定义的情况。
解决⽅法:去除console的相关驱动,屏蔽console_initcall()函数的调⽤8、对串⼝的发送的配置属性,最终调⽤底层驱动的ioctl函数。
⽽ioctl函数得执⾏copy_from_user、copy_to_user函数进⾏⽤户与内核之间的数据拷贝,⽽在ioctl函数执⾏这些操作后,底层的驱动程序才能继续对配置参数(波特率、数据位、停⽌位、检9、在⽤户层⾯操作open()函数时,会调⽤底层驱动的⼀系列默认配置参数,这是在uart_core.c⽂件⾥进⾏属性的配置10、中断有分系统中断与外部中断,系统中断在⼀开机时就已经初始好,⽽外部中断是在驱动程序启动时调⽤,⽽中断的触发是靠硬件进⾏中断请求,cpu响应进⾏处理驱动详解:1、在串⼝驱动中,中断的产⽣都是⽤户态所触发引起的。
Linux串口打印设置
一、基于VM虚拟机linux系统串口配置配置分为虚拟机下配置及linux系统下minicom配置两部分。
虚拟机模块配置如下:打开虚拟机配置界面。
选择Edit virtual machine settings。
进入配置界面。
选择Add…按钮,添加相关的设备文件。
选中串口选项后继续选择下一步。
此处选择”使用主机上的物理串口设备”选项,继续下一步。
此处我们选择文件。
对于物理串口选项,此处可以采用自动检测选项。
如果下来菜单中有对应于串口的端口号,则可以选择。
注意,对于设备状态,要确保选中“connect at power on“,即,上电连接状态。
至此,虚拟机端串口配置完毕。
注意:此处我们串口添加成功后默认未COM2.Linux下串口配置及使用。
Linux下一般使用minicom来作为串口数据输入输出的终端。
类似于Windows下的超级终端。
虚拟机下配置完毕后,进入Linux系统中,在Shell 终端下输入minicom -s即可配置串口终端。
配置完成后执行minicom启动串口终端。
在终端界面下完成相关的参数配置并保存后,启动终端设备,即可在minicom中观察到数据输出。
<四>Minicom的使用(1)minicom界面介绍第一次运行minicom,启动minicom要以root权限登录系统,需要进行minicom的设置,输入下了命令#minicom –s,显示的屏幕如下所示,按上下光标键进行上下移动选择,我们要对串行端口进行设置,因此选中Serial port setup,然后回车:__[configuration]─-─—┐//配置│ Filenames and paths │//文件名和路径│ File transfer protocols│//文件传输协议│ Serial port setup │//串行端口设置│ Modem and dialing │//调制解调器和拨号│ Screen and keyboard │//屏幕和键盘│ Save setup as dfl │//设置保存到│ Save setup as.. │//储存设定为│ Exit │//退出│ Exit from Minicom │//退出minicom└──────────┘(2)minicom的参数设置选中设置串行端口,点击回车后,弹出设置的界面如下:点击”A”设置串行设置为/dev/ttyS1,这表示使用串口2(com2),如果是/dev/ttyS1则表示使用串口2(com 2).按”E”键进入设置”bps/par/Bits”(波特率)界面,如下图所示。
打印调试技术 printk klogd dmesg(解决打印信息的问题)
4.2.1. printk#includeprintk(KERN_CRIT"error %s,%i",__FILE__,__LINE__);注:1). printk函数中能够指定优先级,假如printk没有指定优先级,采用默认优先级,DEFAULT_MESSAGE_LEVEL,其值在kernel/printk.c.头文档linux/printk.h中宏定义了8个级别,0-8从高到低分别是:KERN_EMERG, KERNEL_ALERT, KERN_CRIT, KERN_ERR, KERN_WARNING, KERN_NOTICE, KERN_INFO, KERN_DEBUG2). 当printk指定的优先级小于指定的控制台优先级console_loglevel时,调试消息就显示在控制台虚拟终端。
缺省的console_loglevel值是DEFAULT_CONSOLE_LOGLEVEL。
.也能够使用系统调用sys_syslog或klogd -c来修改console_loglevel值。
.在新版本中,也能够直接通过文档/proc/sys/kernel/printk修改,这个文档包含4个整数值,前两个表示系统当前的优先级和缺省优先级。
能够直接echo 8 > /proc/sys/kernel/printk.也能够指定显示在其他控制台,通过调用ioctl(TIOCLINUX)或shell命令setconsole来配置。
.假如运行了klogd和syslogd,则printk打印到var/log/messages。
. 用打印调试最常用的调试技术是监视, 在应用程序编程当中是通过在合适的地方调用printf 来实现. 在你调试内核代码时, 你可以通过printk 来达到这个目的.一个不同是printk 允许你根据消息的严重程度对其分类, 通过附加不同的记录级别或者优先级在消息上. 你常常用一个宏定义来指示记录级别. 例如, KERN_INFO, 我们之前曾在一些打印语句的前面看到过, 是消息记录级别的一种可能值. 记录宏定义扩展成一个字串, 在编译时与消息文本连接在一起; 这就是为什么下面的在优先级和格式串之间没有逗号的原因. 这里有2 个printk 命令的例子, 一个调试消息, 一个紧急消息:printk(KERN_DEBUG "Here I am: %s:%i/n", __FILE__, __LINE__);printk(KERN_CRIT "I'm trashed; giving up on %p/n", ptr);有8 种可能的记录字串, 在头文件<linux/kernel.h> 里定义; 我们按照严重性递减的顺序列出它们:KERN_EMERG用于紧急消息, 常常是那些崩溃前的消息.KERN_ALERT需要立刻动作的情形.KERN_CRIT严重情况, 常常与严重的硬件或者软件失效有关.KERN_ERR用来报告错误情况; 设备驱动常常使用KERN_ERR 来报告硬件故障.KERN_WARNING有问题的情况的警告, 这些情况自己不会引起系统的严重问题.KERN_NOTICE正常情况, 但是仍然值得注意. 在这个级别一些安全相关的情况会报告.KERN_INFO信息型消息. 在这个级别, 很多驱动在启动时打印它们发现的硬件的信息.KERN_DEBUG用作调试消息.每个字串( 在宏定义扩展里)代表一个在角括号中的整数. 整数的范围从0 到7, 越小的数表示越大的优先级.一条没有指定优先级的printk 语句缺省是DEFAULT_MESSAGE_LOGLEVEL, 在kernel/printk.c 里指定作为一个整数. 在2.6.10 内核中, DEFAULT_MESSAGE_LOGLEVEL 是KERN_WARNING, 但是在过去已知是改变的.基于记录级别, 内核可能打印消息到当前控制台, 可能是一个文本模式终端, 串口, 或者是一台并口打印机. 如果优先级小于整型值console_loglevel, 消息被递交给控制台, 一次一行( 除非提供一个新行结尾, 否则什么都不发送). 如果klogd 和syslogd 都在系统中运行, 内核消息被追加到/var/log/messages (或者另外根据你的syslogd 配置处理), 独立于console_loglevel. 如果klogd 没有运行, 你只有读/proc/kmsg ( 用dmsg 命令最易做到)将消息取到用户空间. 当使用klogd 时, 你应当记住, 它不会保存连续的同样的行; 它只保留第一个这样的行, 随后是, 它收到的重复行数.变量console_loglevel 初始化成DEFAULT_CONSOLE_LOGLEVEL, 并且可通过sys_syslog 系统调用修改. 一种修改它的方法是在调用klogd 时指定-c 开关, 在klogd 的manpage 里有指定. 注意要改变当前值, 你必须先杀掉klogd, 接着使用-c 选项重启它. 另外, 你可写一个程序来改变控制台记录级别. 你会发现这样一个程序的版本在由O' Reilly 提供的FTP 站点上的miscprogs/setlevel.c. 新的级别指定未一个整数, 在1 和8 之前, 包含1 和8. 如果它设为1, 只有0 级消息( KERN_EMERG )到达控制台; 如果它设为8, 所有消息, 包括调试消息, 都显示.也可以通过文本文件/proc/sys/kernel/printk 读写控制台记录级别. 这个文件有4 个整型值: 当前记录级别, 适用没有明确记录级别的消息的缺省级别, 允许的最小记录级别, 以及启动时缺省记录级别. 写一个单个值到这个文件就改变当前记录级别成这个值; 因此, 例如, 你可以使所有内核消息出现在控制台, 通过简单地输入:# echo 8 > /proc/sys/kernel/printk现在应当清楚了为什么hello.c 例子使用KERN_ALERT 标志; 它们是要确保消息会出现在控制台上.4.2.2. 重定向控制台消息Linux 在控制台记录策略上允许一些灵活性, 它允许你发送消息到一个指定的虚拟控制台(如果你的控制台使用的是文本屏幕). 缺省地, 这个"控制台"是当前虚拟终端. 为了选择一个不同地虚拟终端来接收消息, 你可对任何控制台设备调用ioctl(TIOCLINUX). 下面的程序, setconsole, 可以用来选择哪个控制台接收内核消息; 它必须由超级用户运行, 可以从misc-progs 目录得到.下面是全部程序. 应当使用一个参数来指定用以接收消息的控制台的编号.int main(int argc, char **argv){char bytes[2] = {11,0}; /* 11 is the TIOCLINUX cmd number */if (argc==2) bytes[1] = atoi(argv[1]); /* the chosen console */else {fprintf(stderr, "%s: need a single arg/n",argv[0]); exit(1); } if (ioctl(STDIN_FILENO, TIOCLINUX, bytes)<0) { /* use stdin */ fprintf(stderr,"%s: ioctl(stdin, TIOCLINUX): %s/n",argv[0], strerror(errno));exit(1);}exit(0);}setconsole 使用特殊的ioctl 命令TIOCLINUX, 来实现特定于linux 的功能. 为使用TIOCLINUX, 你传递它一个指向字节数组的指针作为参数. 数组的第一个字节是一个数, 指定需要的子命令, 下面的字节是特对于子命令的. 在setconsole 里, 使用子命令11, 下一个字节(存于bytes[1])指定虚拟控制台. TIOCLINUX 的完整描述在内核源码的drivers/char/tty_io.c 里.4.2.3. 消息是如何记录的printk 函数将消息写入一个__LOG_BUF_LEN 字节长的环形缓存, 长度值从4 KB 到1 MB, 由配置内核时选择. 这个函数接着唤醒任何在等待消息的进程, 就是说, 任何在系统调用中睡眠或者在读取/proc/kmsg 的进程. 这2 个日志引擎的接口几乎是等同的, 但是注意, 从/proc/kmsg 中读取是从日志缓存中消费数据, 然而syslog 系统调用能够选择地在返回日志数据地同时保留它给其他进程. 通常, 读取/proc 文件容易些并且是klogd 的缺省做法. dmesg 命令可用来查看缓存的内容, 不会冲掉它; 实际上, 这个命令将缓存区的整个内容返回给stdout, 不管它是否已经被读过.在停止klogd 后, 如果你偶尔手工读取内核消息, 你会发现/proc 看起来象一个FIFO, 读者阻塞在里面, 等待更多数据. 显然, 你无法以这种方式读消息, 如果klogd 或者其他进程已经在读同样的数据, 因为你要竞争它.如果环形缓存填满, printk 绕回并在缓存的开头增加新数据, 覆盖掉最老的数据. 因此, 这个记录过程会丢失最老的数据. 这个问题相比于使用这样一个环形缓存的优点是可以忽略的. 例如, 环形缓存允许系统即便没有一个日志进程也可运行, 在没有人读它的时候可以通过覆盖旧数据浪费最少的内存. Linux 对于消息的解决方法的另一个特性是, printk 可以从任何地方调用, 甚至从一个中断处理里面, 没有限制能打印多少数据. 唯一的缺点是可能丢失一些数据.如果klogd 进程在运行, 它获取内核消息并分发给syslogd, syslogd 接着检查/etc/syslog.conf 来找出如何处理它们. syslogd 根据一个设施和一个优先级来区分消息; 这个设施和优先级的允许值在<sys/syslog.h> 中定义. 内核消息由LOG_KERN 设施来记录, 在一个对应于printk 使用的优先级上(例如, LOG_ERR 用于KERN_ERR 消息). 如果klogd 没有运行, 数据保留在环形缓存中直到有人读它或者缓存被覆盖.如果你要避免你的系统被来自你的驱动的监视消息击垮, 你或者给klogd 指定一个-f (文件) 选项来指示它保存消息到一个特定的文件, 或者定制/etc/syslog.conf 来适应你的要求. 但是另外一种可能性是采用粗暴的方式: 杀掉klogd 和详细地打印消息在一个没有用到的虚拟终端上,[13 ] 或者从一个没有用到的xterm 上发出命令cat /proc/kmsg.4.2.4. 打开和关闭消息在驱动开发的早期, printk 非常有助于调试和测试新代码. 当你正式发行驱动时, 换句话说, 你应当去掉, 或者至少关闭, 这些打印语句. 不幸的是, 你很可能会发现, 就在你认为你不再需要这些消息并去掉它们时, 你要在驱动中实现一个新特性(或者有人发现了一个bug), 你想要至少再打开一个消息. 有几个方法来解决这2 个问题, 全局性地打开或关闭你地调试消息和打开或关闭单个消息.这里我们展示一种编码printk 调用的方法, 你可以单独或全局地打开或关闭它们; 这个技术依靠定义一个宏, 在你想使用它时就转变成一个printk (或者printf)调用.每个printk 语句可以打开或关闭, 通过去除或添加单个字符到宏定义的名子.所有消息可以马上关闭, 通过在编译前改变CFLAGS 变量的值.同一个print 语句可以在内核代码和用户级代码中使用, 因此对于格外的消息, 驱动和测试程序能以同样的方式被管理.下面的代码片断实现了这些特性, 直接来自头文件scull.h:#undef PDEBUG /* undef it, just in case */#ifdef SCULL_DEBUG# ifdef __KERNEL__/* This one if debugging is on, and kernel space */# define PDEBUG(fmt, args...) printk( KERN_DEBUG "scull: " fmt, ## args)# else/* This one for user space */# define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)# endif#else# define PDEBUG(fmt, args...) /* not debugging: nothing */#endif#undef PDEBUGG #define PDEBUGG(fmt, args...) /* nothing: it's a placeholder */符号PDEBUG 定义和去定义, 取决于SCULL_DEBUG 是否定义, 和以何种方式显示消息适合代码运行的环境: 当它在内核中就使用内核调用printk, 在用户空间运行就使用libc 调用fprintf 到标准错误输出. PDEBUGG 符号, 换句话说, 什么不作; 他可用来轻易地"注释" print 语句, 而不用完全去掉它们.为进一步简化过程, 添加下面的行到你的makfile 里:# Comment/uncomment the following line to disable/enable debuggingDEBUG = y# Add your debugging flag (or not) to CFLAGSifeq ($(DEBUG),y)DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlineselseDEBFLAGS = -O2endifCFLAGS += $(DEBFLAGS)本节中出现的宏定义依赖gcc 对ANSI C 预处理器的扩展, 支持带可变个数参数的宏定义. 这个gcc 依赖不应该是个问题, 因为无论如何内核固有的非常依赖于gcc 特性. 另外, makefile 依赖GNU 版本的make; 再一次, 内核也依赖GNU make, 所以这个依赖不是问题.如果你熟悉C 预处理器, 你可以扩展给定的定义来实现一个"调试级别"的概念, 定义不同的级别, 安排一个整数(或者位掩码)值给每个级别, 以便决定它应当多么详细.但是每个驱动有它自己的特性和监视需求. 好的编程技巧是在灵活性和效率之间选择最好的平衡, 我们无法告诉你什么是最好的. 记住, 预处理器条件(连同代码中的常数表达式)在编译时执行, 因此你必须重新编译来打开或改变消息. 一个可能的选择是使用C 条件句, 它在运行时执行, 因而, 能允许你在出现执行时打开或改变消息机制. 这是一个好的特性, 但是它在每次代码执行时需要额外的处理, 这样即便消息给关闭了也会影响效率. 有时这个效率损失无法接受.本节出现的宏定义已经证明在多种情况下是有用的, 唯一的缺点是要求在任何对它的消息改变后重新编译.4.2.5. 速率限制如果你不小心, 你会发现自己用printk 产生了上千条消息, 压倒了控制台并且, 可能地, 使系统日志文件溢出. 当使用一个慢速控制台设备(例如, 一个串口), 过量的消息速率也能拖慢系统或者只是使它不反应了. 非常难于着手于系统出错的地方, 当控制台不停地输出数据. 因此, 你应当非常注意你打印什么, 特别在驱动的产品版本以及特别在初始化完成后. 通常, 产品代码在正常操作时不应当打印任何东西; 打印的输出应当是指示需要注意的异常情况.另一方面, 你可能想发出一个日志消息, 如果你驱动的设备停止工作. 但是你应当小心不要做过了头. 一个面对失败永远继续的傻瓜进程能产生每秒上千次的尝试; 如果你的驱动每次都打印"my device is broken", 它可能产生大量的输出, 如果控制台设备慢就有可能霸占CPU -- 没有中断用来驱动控制台, 就算是一个串口或者一个行打印机.在很多情况下, 最好的做法是设置一个标志说, "我已经抱怨过这个了", 并不打印任何后来的消息只要这个标志设置着. 然而, 有几个理由偶尔发出一个"设备还是坏的"的提示. 内核已经提供了一个函数帮助这个情况:int printk_ratelimit(void);这个函数应当在你认为打印一个可能会常常重复的消息之前调用. 如果这个函数返回非零值, 继续打印你的消息, 否则跳过它. 这样, 典型的调用如这样:if (printk_ratelimit())printk(KERN_NOTICE "The printer is still on fire/n");printk_ratelimit 通过跟踪多少消息发向控制台而工作. 当输出级别超过一个限度, printk_ratelimit 开始返回0 并使消息被扔掉.printk_ratelimit 的行为可以通过修改/proc/sys/kern/printk_ratelimit( 在重新使能消息前等待的秒数) 和/proc/sys/kernel/printk_ratelimit_burst(限速前可接收的消息数)来定制.4.2.6. 打印设备编号偶尔地, 当从一个驱动打印消息, 你会想打印与感兴趣的硬件相关联的设备号. 打印主次编号不是特别难, 但是, 为一致性考虑, 内核提供了一些实用的宏定义( 在<linux/kdev_t.h> 中定义)用于这个目的:int print_dev_t(char *buffer, dev_t dev);char *format_dev_t(char *buffer, dev_t dev);两个宏定义都将设备号编码进给定的缓冲区; 唯一的区别是print_dev_t 返回打印的字符数, 而format_dev_t 返回缓存区; 因此, 它可以直接用作printk 调用的参数, 但是必须记住printk 只有提供一个结尾的新行才会刷行. 缓冲区应当足够大以存放一个设备号; 如果64 位编号在以后的内核发行中明显可能, 这个缓冲区应当可能至少是20 字节长.总结:(1)所有系统信息是输出到ring buffer中去的.dmesg所显示的内容也是从ring buffer中读取的.(2)linux系统中/etc/init.d/sysklogd会启动2个守护进程:klogd&&syslogd(3)klogd是负责读取内核信息的,有2种方式:syslog()系统调用(这个函数用法比较全,大家去man一下看看)直接的对/proc/kmsg进行读取(再这提一下,/proc/kmsg是专门输出内核信息的地方)(4)klogd的输出结果会传送给syslogd进行处理,syslogd会根据/etc/syslog.conf的配置把log信息输出到/var/log/下的不同文件中。
rtt打印函数使用
rtt打印函数使用摘要:1.RTT 打印函数简介2.RTT 打印函数的使用方法3.RTT 打印函数的实例正文:【1.RTT 打印函数简介】RTT 打印函数是一种在嵌入式系统中常用的打印函数,它可以向屏幕或串口发送数据。
RTT 打印函数的优势在于它可以直接在汇编代码中使用,无需进行额外的库文件链接。
在嵌入式系统中,由于存储空间和运行速度的限制,使用RTT 打印函数可以有效地节省资源和提高程序运行效率。
【2.RTT 打印函数的使用方法】RTT 打印函数的使用方法相对简单,一般分为以下几个步骤:1) 初始化RTT 打印函数:在使用RTT 打印函数之前,需要对其进行初始化。
通常情况下,可以使用`initscr()`函数进行初始化。
2) 打开/关闭设备:根据需要,可以使用`open()`和`close()`函数分别打开和关闭打印设备。
3) 设置打印属性:使用`setv()`函数可以设置打印属性,例如打印速度、打印密度等。
4) 打印数据:使用`puts()`或`printf()`函数可以将需要打印的数据发送到打印设备。
5) 关闭设备:在完成打印操作后,需要使用`close()`函数关闭打印设备。
【3.RTT 打印函数的实例】以下是一个使用RTT 打印函数的简单实例,演示如何在屏幕上打印一条信息:```c#include <reg52.h> // 包含头文件,定义了RTT 打印函数void main() // 主函数{initscr(); // 初始化RTT 打印函数openscr(); // 打开屏幕设备setv(0, "Hello, RTT!"); // 设置打印速度和密度,打印"Hello, RTT!"puts("Hello, RTT!"); // 打印字符串closescr(); // 关闭屏幕设备}```通过以上实例,可以看出RTT 打印函数的使用方法较为简单,且功能强大。
printk打印不能显示到终端的问题
printk打印不能显示到终端的问题对于做嵌入式或者熟悉linux内核的人来说,对printk这个函数一定不会感到陌生。
printk相当于printf的孪生姐妹,她们一个运行在用户态,另一个则在内核态被人们所熟知。
【原型】int printk(const char * fmt,…);【示例】与大多数展示printf的功能一样,我们也用一个helloworld的程序来演示printk的输出:编写一个内核模块:#include<linux/kernel.h>#include<linux/module.h>#if CONFIG_MODVERSIONS==1#define MODVERSIONS#include<linux/modversions.h>#endifMODULE_LICENSE("GPL");int init_module(){printk("hello.word-this is the kernel speaking\n");return 0;}void cleanup_module(){printk("Short is the life of a kernel module\n");}保存为文件hello.c编写一个Makefile:CC=gccMODCFLAGS:=-O6 -Wall -DMODULE -D__KERNEL__ -DLINUXhello.o:hello.c /usr/include/linux/version.h$(CC) $(MODCFLAGS) -c hello.cecho insmod hello.o to turn it on保存为文件Makefile执行make我们可以看到生成了一个hello.o的内核模块,我们想通过这个模块在插入内核的时候输出"hello.word-this is the kernel speaking"这样一条信息。
printk用法
printk用法引言:在 Linux 内核中,打印信息是一个很重要的任务。
内核提供了 printk 函数来实现这一任务。
printk 函数的作用就是向系统日志输出一段信息。
本文就来介绍 printk 函数的用法。
一、printk 函数的使用方式printk 函数用于向内核日志输出数据,其通用的格式为:```C int printk(const char * fmt, …) ```参数 `fmt` 是格式化字符串,参数列表则包含要输出的参数变量。
下面是一个简单的例子:```C bool flag = true; int num = 15;printk(KERN_INFO "flag = %d, num = %d\n", flag, num); ```它输出的结果将会是:```C Jun 3 14:12:48 localhost kernel: flag = 1, num = 15 ```二、printk 函数中的KERN_XXX在上面的例子中,KERN_INFO 是一个前缀,它可以控制日志打印的输出级别。
KERN_XXX 常量定义在`include/linux/kernel.h` 头文件中,用于控制日志输出级别,其具体含义如下:| KERN_EMERG | 系统处于非正常状态。
| |------------|--------------------------| | KERN_ALERT | 系统需要立刻采取措施。
| | KERN_CRIT | 严重错误,需要立即解决。
| | KERN_ERR | 一般错误。
| |KERN_WARNING | 警告信息。
| | KERN_NOTICE | 通知信息。
| | KERN_INFO | 信息类型。
| | KERN_DEBUG | 调试信息。
|printk 流程:1. 获取当前内核时间printk 在输出信息之前,会获取当前内核的时间,并将其输出为日志的一部分。
2440启动串口输出乱码问题
2440 移植2.6.30 (转)解压缩内核压缩文件后进入到目录中,然后修改Makefile,找到ARCH ?=CROSS_COMPILE ?=这两项,不修改这两项的话将会默认使用x86的配置,这里修改为ARCH ?= armCROSS_COMPILE ?= arm-linux-arm-linux- 是交叉编译器~ 这里我使用的交叉编译器为友善送的arm-linux-gcc-4.3.2.tgz,带EABI然后执行make menuconfig,然后进入System Type中看看是否为ARM体系~第一行为ARM system type 说明没错~ 然后在ARM system type中选择SamSung“S3C2410...”随后在下面出现的S3C2440 Machines中选择SMDK2440退出保存~ 执行make zImage出现ERRORdrivers/video/console/vgacon.c:510:error “PCIMEM_BASE undeclared”是在vgacon_startup中,vgacon是啥?~ 不认识~ 应该是不必要的东西~ 去掉它~vim drivers/video/console/Makefile在里面看见了这句obj-$(CONFIG_VGA_CONSOLE) += vgacon.o然后执行find ./ -name “Kconfig” | xargs grep “VGA_CONSOLE”看见config VGA_CONSOLE 在driver/video/console/Kconfig中也就是说在驱动->视频->终端中,执行make menuconfig在Device Drivers->Graphics Support->Console display driver support中发现了VGA text console去掉它,保存设置后再编译编译完成后将在arch/arm/boot中得到zImage文件使用SuperVivi的USB加载功能启动这个内核文件~ 得到下列输出zImage magic = 0x016f2818Setup linux parameters at 0x30000100linux command line is: "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0" MACH_TYPE = 1999NOW, Booting Linux......Uncompressing Linux........................................................................................................ done, booting the kernel.失败信息不够丰富~ 根据kasim大大的指点,在配置中进入Kernel hacking打开Kernel debugging和Kernel low-level debugging functions 还有Kernel low-level debugging messages via S3C UART保存后再编译运行zImage后得下列输出zImage magic = 0x016f2818Setup linux parameters at 0x30000100linux command line is: "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0" MACH_TYPE = 1999NOW, Booting Linux......Uncompressing Linux........................................................................................................ done, booting the kernel.Error: unrecognized/unsupported machine ID (r1 = 0x000007cf).Available machine support:ID (hex) NAME0000016a SMDK2440Please check your kernel config and/or bootloader.失败原来是machine的ID和Supervivi传递进来的ID不匹配~关于machine ID,可以参考一下这篇文章<2.6.18-2内核中对S3C2440的引导启动分析>虽然版本老了点,但是核心思想还是没有变vim arch/arm/mach-s3c2440/mach-smdk2440.c在最后一段有这句MACHINE_START(S3C2440 , ”SMDK2440”)这里S3C2440就是machine ID的代号~ 呢具体值是多少呢?~在arch/arm/tools/mach-types中s3c2440 ARCH_S3C2440 S3C2440 362原来我们的machine ID是362~呢bootloader传递进来的值是多少呢?~Error: unrecognized/unsupported machine ID (r1 = 0x000007cf).注意到没有?~ 0x7CF转换成10进制也就是1999修改mach-types中的对应项s3c2440 ARCH_S3C2440 S3C2440 1999虽然这样就和下面MINI2440的1999冲突了,但是只要不加入MINI2440的配置就没事修改后编译,再执行zImage后得下列输出zImage magic = 0x016f2818Setup linux parameters at 0x30000100linux command line is: "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0" MACH_TYPE = 1999NOW, Booting Linux......Uncompressing Linux........................................................................................................ done, booting the kernel.失败咦?~ 啥都没有?~ 最起码也应该有个乱码吧这时候我的第一反应是会不会没有跳入到start_kernel中所以马上编辑init/main.c,在start_kernel的前部加上printk(KERN_INFO “in start_kernel \n”);但是这个时候内核还没有初始化,所以printk是没有作用的~继续得到kasim大大的指点,编辑kernel/printk.c中的printk函数{va_list args;int r;#ifdef CONFIG_DEBUG_LLextern void printascii(const char *);char buff[256];#endifva_start(args, fmt);r = vprintk(fmt, args);#ifdef CONFIG_DEBUG_LLvsprintf(buff, fmt, args);#endifva_end(args);#ifdef CONFIG_DEBUG_LLprintascii(buff);#endifreturn r;}编译后执行zImage,得下列输出zImage magic = 0x016f2818Setup linux parameters at 0x30000100linux command line is: "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0" MACH_TYPE = 1999NOW, Booting Linux......Uncompressing Linux........................................................................................................ done, booting the kernel.<6>in start_kernel<6>Initializing cgroup subsys cpuset<6>Initializing cgroup subsys cpu<5>Linux version 2.6.30.3 (wolf@ubuntu) (gcc version 4.3.2 (Sourcery G++ Lite2008q3-72) ) #4 Wed Aug 5 16:54:49 CST 2009 ..................................................失败虽然正常输出了~ 有进入start_kernel~ 但是为什么之前每输出呢?~ 会不会是没有找到输出设备在输出中看到这行<5>Kernel command line: noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0 console=ttySAC0 会不会是没有ttySAC0这个设备呢~ 在内核中搜索ttySAC 在driver/serial/samsung.c中得到对应项目这时候我猜想会不会没有加载samsung.c , 经过一轮Makefile和Kconfig的查询, 发现对应选项在Device Drivers->Character devices->Serial drivers中一看,原来根本就没有加载Samsung SoC serial support , 选成静态编译之后又出现了Support for console on Samsung SoC serial port ,就是它了,选上, 退出的时候顺便把Kernel low-level debugging functions给取消了否则我们设置的printk会自行输出,就不知道ttySAC有没有加载成功了编译后执行,得下列输出zImage magic = 0x016f2818Setup linux parameters at 0x30000100linux command line is: "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0" MACH_TYPE = 1999NOW, Booting Linux......Uncompressing Linux......................................................................................................... done, booting the kernel.w# DpñGpGp´ó70ÇC¼ØûÛ»›3ó•ó¸Û0ƒw#DpñGpGp´ó•tØ›•p¸›7¿³ó•\@û7¼¿[£¼Û3•¼ó;£¸ÀÛ;[7û;D°•D@GoGpGpíó•t›7•{ð#ßóÄ;›•770ÄÄ3Çß;GoDh}û7wœ´{…[ó7ûÛ›30°ôܸ‡#_sÄ;›•770Øijœ¼DG@ÁôÛ•ûÄ;•sÄ›£Ø›•DŽ³ÃÛ70ÄGpÁ4ßœ»ôGã›30³D˜ßF[s˜£ÀÛû70ÛD8ßÄ4G8ôGv£°ÇÃGpÍ´0ƒ†# DpñGš´;óC…[4¸F¸ÄÛtÜàGp}4GGÇ4tD@Ä38ÀGpGß ôØ Û›ŸÄÛD\Cûƒ£¸ƒ;7v›Ã30Ü›4Û´£ô¼;C3[;7ù³û770‡¸°[•4tD@Ä38ÀGpGß ´´p‡ƒ•ô¼Û7ŸtÛG»4œØ…Çpíƒw# .......................................失败但这说明ttySAC加载成功了~ 不过为什么是乱码呢?~这时候就需要对比友善的配置和我们的配置有什么不同了~打开友善送的linux-2.6.29,观察arch/arm/mach-s3c2440/mach-mini2440.c和我们的2.6.30.4下面的arch/arm/mach-s3c2440/mach-smdk2440.c有什么不同由于乱码主要是时钟问题,所以我们重点观察UART的设置和基本设置,其它什么NAND LCD 的就不看先修改smdk2440_uartcfgs[][2] = {.ulcon = 0x03,}修改s3c24xx_init_clocks(12000000);然后编译再运行,输出为zImage magic = 0x016f2818Setup linux parameters at 0x30000100linux command line is: "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0" MACH_TYPE = 1999NOW, Booting Linux......Uncompressing Linux......................................................................................................... done, booting the kernel.[ 0.000000] in start_kernel[ 0.000000] Initializing cgroup subsys cpuset[ 0.000000] Initializing cgroup subsys cpu ...........................最后为Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)失败终于可以正常输出了,但是根文件系统挂载失败因为板子上的根文件系统为yaffs2 这时候内核还没有这个文件系统的支持,需要我们加上去拷贝友善的送的2.6.29下的fs/yaffs2目录到我们的fs目录下然后修改观察一下友善的送的2.6.29下的fs/Kconfig 和fs/Makefile和我们的有什么不同在我们的Kconfig中的source “fs/jffs2/Kconfig” 上面加上source “fs/yaffs2/Kconfig”在Makefile中的obj-$(CONFIG_FAT_FS) += fat/ 上面加上obj-$(CONFIG_YAFFS_FS) += yaffs2/然后在配置的File systems->Miscellaneous filesystems 中选上“YAFFS2 file system support” “Autoselect yaffs2 format” “Cache short names in RAM”然后编译运行,输出如下......................Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)失败还是不行,往上看几行VFS: Cannot open root device "mtdblock2" or unknown-block(0,0)Please append a correct "root=" boot option; here are the available partitions:Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)原来是没有可用的分区这个时候就要更正我们的NAND配置了还是对照友善送的linux-2.6.29,观察arch/arm/plat-s3c24xx/common-friendly-smdk.c来修改我们的arch/arm/plat-s3c24xx/common-smdk.c主要修改smdk_default_nand_part[]{[0] = {.name = “supervivi”,.size = 0x00060000,.offset = 0,},[1] = {.name = “Kernel”,.offset = 0x00060000,.size = 0x00200000,},[2] = {.name = “root”,.offset = 0x00260000,.size = 1024*1024*1024,},[3] = {.name = “nand”,.offset = 0x00000000,.size = 1024*1024*1024,}};编译后运行,输出VFS: Cannot open root device "mtdblock2" or unknown-block(0,0)Please append a correct "root=" boot option; here are the available partitions:Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)失败还是不行,连最起码的分区都没有看见,会不会是MTD没有加载呢?~打开配置进入Device DriversMemory Technology Device ......... 前面是个M~ 说明这个模块是动态加载的,而我们编译的zImage里面只有静态模块将MTD选为静态加载,然后进入MTD配置中看看还有什么需要选的NAND Device Support 这个也是动态,选为静态加载进入NAND Device Support原来连NAND Flash support for S3C2410/S3C2440 SoC都没选,马上选为静态加载保存配置后编译运行,再运行输出如下:NAND device: Manufacturer ID: 0xec, Chip ID: 0xf1 (Samsung NAND 128MiB 3,3V 8-bit) Scanning device for bad blocksCreating 4 MTD partitions on "NAND 128MiB 3,3V 8-bit":0x000000000000-0x000000060000 : "supervivi"0x000000060000-0x000000260000 : "Kernel"0x000000260000-0x000040260000 : "root"mtd: partition "root" extends beyond the end of device "NAND 128MiB 3,3V 8-bit" -- size truncated to 0x7da00000x000000000000-0x000040000000 : "nand"mtd: partition "nand" extends beyond the end of device "NAND 128MiB 3,3V 8-bit" -- size truncated to 0x8000000 ...............................VFS: Cannot open root device "mtdblock2" or unknown-block(0,0)Please append a correct "root=" boot option; here are the available partitions:Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)失败还是没有可用分区,虽然成功分辨了分区,但是没有加载成功,估计还是在MTD的模块选择上这时候需要对照友善的配置,经过对比,发现在友善的配置中静态编译了MTD中的下面3个模块Direct char device access to MTD devicesCommon interface to block layer for MTD …translation layers‟Caching block device access to MTD devices我们也选为静态编译保存配置后编译运行,输出如下List of all partitions:1f00 384 mtdblock0 (driver?)1f01 2048 mtdblock1 (driver?)1f02 128640 mtdblock2 (driver?)1f03 131072 mtdblock3 (driver?)No filesystem could mount root, tried: cramfsKernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(31,2)分区加载成功了,但是文件系统却不能识别,我们之前不是已经加入了yaffs2么?~回到配置中再看,原来是动态编译,并没有真正进入到内核之中,选为静态编译~保存配置后编译,输出为yaffs: dev is 32505858 name is "mtdblock2"yaffs: passed flags ""yaffs: Attempting MTD mount on 31.2, "mtdblock2"yaffs: auto selecting yaffs2yaffs_read_super: isCheckpointed 0VFS: Mounted root (yaffs filesystem) on device 31:2.Freeing init memory: 128KKernel panic - not syncing: Attempted to kill init!失败依然错误,这个时候懵了,哪里错呢~ 没办法,只能对照着友善的配置一个个大模块对着来改当改到Kernel Features的时候错误消失了,原来需要选上Use the ARM EABI to compile the kernelAllow old ABI binaries to run with thie Kernel为什么呢?~ Google了一下,原来友善的根文件系统在编译的时候也启用了EABI特性,内核和文件系统需要对上文件系统用了EABI 内核也要用EABI 内核不用EABI 也只能读取不用EABI的文件系统选上这两项之后再编译,运行,输出如下yaffs: dev is 32505858 name is "mtdblock2"yaffs: passed flags ""yaffs: Attempting MTD mount on 31.2, "mtdblock2"yaffs: auto selecting yaffs2yaffs_read_super: isCheckpointed 0VFS: Mounted root (yaffs filesystem) on device 31:2.Freeing init memory: 128Kmount: mounting none on /proc/bus/usb failed: No such file or directoryhwclock: can't open '/dev/misc/rtc': No such file or directory[01/Jan/1970:00:00:13 +0000] boa: server version Boa/0.94.13[01/Jan/1970:00:00:13 +0000] boa: server built Mar 26 2009 at 15:28:42.[01/Jan/1970:00:00:13 +0000] boa: starting server pid=845, port 80open device leds: No such file or directoryTry to bring eth0 interface up......ifconfig: SIOCGIFFLAGS: No such deviceifconfig: SIOCSIFHWADDR: No such deviceifconfig: SIOCSIFADDR: No such deviceroute: SIOCADDRT: No such processDoneifconfig: SIOCSIFADDR: No such devicePlease press Enter to activate this console.[root@FriendlyARM /]#成功了,ls后输出如下bin home lost+found proc sys vardev lib mini2440 root tmp wwwetc linuxrc opt sbin usr不过ifconfig命令没有成功,继续来配置网卡对比友善的mach-mini2440.c文件,发现我们的mach-smdk2440.c中的smdk2440_devices[]数组并没有&s3c_device_dm9k这个结构,加上,追踪发现该数据结构在arch/arm/plat-s3c24xx/devs.c中,我们的devs.c中没有该数据结构的定义,加上#include <linux/dm9000.h>static struct resource s3c_dm9k_resource[] = {[0] = {.start = S3C2410_CS4,.end = S3C2410_CS4 + 3,.flags = IORESOURCE_MEM,},[1] = {.start = S3C2410_CS4 + 4,.end = S3C2410_CS4 + 4 + 3,.flags = IORESOURCE_MEM,},[2] = {.start = IRQ_EINT7,.end = IRQ_EINT7,.flags = IORESOURCE_IRQ | IRQF_TRIGGER_RISING,},};static struct dm9000_plat_data s3c_dm9k_platdata = {.flags = DM9000_PLATF_16BITONLY,};struct platform_device s3c_device_dm9k = {.name = “dm9000”,.id = 0;.num_resources = ARRAY_SIZE(s3c_dm9k_resource),.resource = s3c_dm9k_resource,.dev = {.platform_data = &s3c_dm9k_platdata,}};EXPORT_SYMBOL(s3c_device_dm9k);编译,出错,error : s3c_device_dm9k undeclared here找不到结构?~ 打开mach-smdk2440.c看看有什么头文件比较显眼的就是<plat/s3c2410.h><plat/s3c2440.h><plat/devs.h>,我们刚才编辑的文件是devs.c呢么devs.h的可能性较高,通过搜索,这个devs.h在/arch/arm/plat-s3c/include/plat/中,打开,BINGO,里面都是devs.c的数据定义加上我们的s3c_device_dm9kextern struct platform_device s3c_device_dm9k;再编译,通过了,不过这个时候先别急,我们只添加了设备,驱动有没有静态加载呢?~ 打开配置Device Drivers->Networks device support->Ethernet(10 or 100Mbit)DM9000 support没选上,马上选为静态编译保存配置,编译后运行,输出如下Try to bring eth0 interface up......说明DM9000配置成功使用ping命令进行测试,发现丢包率高达78%是不是驱动没设置好呢?~ 比较了一下友善的driver/net/dm9000.c和2.6.30.4的dm9000.c,发现明显不同直接拷贝友善的dm9000.c和dm9000.h过来编译后运行,顺利进入终端,然后运行PING丢包改善,基本无丢包我对这次内核移植的总结是:一步步来~ 先做好终端输出再挂载好根文件系统最后才考虑其它驱动的配置到此移植就基本结束了= 3=)/ 感谢阅读。
STM32打印调试的方法
一、前言在我们的嵌入式开发中,常常把printf重定向到MCU的串口外设,再配合上位机界面软件,通过打印调试信息的方式来调试我们的嵌入式软件。
此处,我们介绍另一种打印调试的方法——SEGGER 的RTT 。
RTT全称是Real Time Transmit(实时传输),是Segger公司推出的,是配合J-link使用的一种调试手段。
其框图如下:可见,我们的MCU通过J-Link,凭借RTT就可往电脑打印调试信息,电脑端这边用的是J-LINK 的小软件RTT Viewer (不能用别的软件哦)。
这样,我们就可以把MCU的串口资源释放出来了,特别对于一些串口资源不那么充足的MCU来说就可以省出一个串口去与其它外围芯片进行串口通讯。
二、SEGGER_RTT的使用所需准备,J-Link及SEGGER_RTT源码,可在本公众号聊天界面回复关键词:RTT,即可获取下载链接。
下面演示在Keil-MDK环境下使用SEGGER_RTT:1、安装J-Link驱动安装完之后就可在看到如图所示的J-Link RTT Viewer V6.44b,我们待会要把调试信息传输到这个软件上。
2、SEGGER_RTT的收发测试(1)把SEGGER_RTT_V640添加到我们的工程文件夹中SEGGER_RTT_V640中的内容如下:(2)把SEGGER_RTT_V640下的RTT下的所有文件添加到我们的工程中(3)添加文件路径(4)在main.c中添加如下测试代码int main(void){/* 今天是2019-08-15 */#define YEAR 2019#define MONTH 8#define DAY 15int GetKey;/* 配置通道0,上行配置(STM32->RTT Viewer软件)*/SEGGER_RTT_ConfigUpBuffer(0, "RTTUP", NULL, 0,SEGGER_RTT_MODE_NO_BLOCK_SKIP);/* 配置通道0,下行配置(RTT Viewer软件->STM32)*/SEGGER_RTT_ConfigDownBuffer(0, "RTTDOWN", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);while (1){/* 收发测试*/if (SEGGER_RTT_HasKey()) /* 判断接收缓冲区中是否有数据*/{GetKey = SEGGER_RTT_GetKey(); /* 从接受缓冲区中取出一个字符*/SEGGER_RTT_SetTerminal(1);SEGGER_RTT_printf(0, "GetKey = %c\r\nHello world! Today is %.4d-%.2d-%.2d", GetKey, YEAR, MONTH, DAY);}}return 0;}需要注意的是:记得添加头文件SEGGER_RTT.h,范例工程可在聊天界面回复关键词RTT进行获取。
修改UBOOT和LINUX调试串口(TI--DM6467)
1.1 概述TI针对DM6467提供的UBOOT和内核默认都是串口0作为调试串口输出的,但现在我需要使用DM6467的UART0的modem功能,所以修改代码,改变调试串口为串口2。
需要修改的主要有几部分内容:1. UBL 代码(这部分代码在刚上电的时候,初始化CPU和拷贝UBOOT到DDR,打印信息只有很少,所以不做修改)。
2. UBOOT代码。
3. linux内核驱动。
2.1 修改UBOOT代码因为DM6467的串口是符合TL16C550标准的,所以驱动也是使用16550的驱动,默认情况下,我们只需要提供需要配置的串口的基地址和中断号等资源给16550的驱动就可以了,寄存器的配置不需要我们去关心。
要用起DM6467的串口有几个地方的配置一定要注意:1. 引脚复用寄存器(PINMUX0/1);2. VDD3P3V_PWDN寄存器,需要使能UART的相关引脚(bit4~bit9置零)3.CLKCTL,bit24/25置零。
在UBOOT里涉及到上面几个寄存器的配置的是在dm6467_evm.c的初始化部分我的修改如下:1static void davinci_hd_psc_enable ( void )2 {3 unsigned int alwaysonpdnum = 0;45/* Note this function assumes that the Power Domains are alread on */6 REG(PSC_ADDR+0xA00+4*14) |= 0x03; /* EMAC */7 REG(PSC_ADDR+0xA00+4*15) |= 0x03; /* VDCE */8 REG(PSC_ADDR+0xA00+4*16) |= 0x03; /* Video Port */9 REG(PSC_ADDR+0xA00+4*17) |= 0x03; /* Video Port */10 REG(PSC_ADDR+0xA00+4*20) |= 0x03; /* DDR2 */11 REG(PSC_ADDR+0xA00+4*21) |= 0x03; /* EMIFA */12 REG(PSC_ADDR+0xA00+4*26) |= 0x03; /* UART0 */13 REG(PSC_ADDR+0xA00+4*27) |= 0x03; /* UART1 */14 REG(PSC_ADDR+0xA00+4*28) |= 0x03; /* UART2 */15 REG(PSC_ADDR+0xA00+4*31) |= 0x03; /* I2C */16 REG(PSC_ADDR+0xA00+4*33) |= 0x03; /* GPIO */17 REG(PSC_ADDR+0xA00+4*34) |= 0x03; /* TIMER0 */18 REG(PSC_ADDR+0xA00+4*35) |= 0x03; /* TIMER1 */1920/* Set PTCMD.GO to 0x1 to initiate the state transtion for Modules i n21 * the ALWAYSON Power Domain22*/23 REG(PSC_PTCMD) = (1<<alwaysonpdnum);2425/* Wait for PTSTAT.GOSTAT0 to clear to 0x0 */26while(! (((REG(PSC_PTSTAT) >> alwaysonpdnum) & 0x00000001) == 0));2728/* Enable GIO3.3V cells used for EMAC (???) */29 REG(VDD3P3V_PWDN) = (1<<27); //disable clkout03031/* Select UART function on UART0 */32 REG(PINMUX0) &= ~(0x0000003f << 18);34 REG(PINMUX1) = ((1<<4)|(1<<2)|(1<<0));3536/* Enable USB */37 REG(PINMUX0) &= ~(0x80000000);3839/* Set the Bus Priority Register to appropriate value */40 REG(VBPR) = 0x20;41 }接下来还有一个比较重要的地方需要修改,因为DM6467的串口是支持多种模式的,但16550的驱动是默认设备是工作在UART模式的,它没有去配置设备串口的工作模式,所以我们需要去配置一下串口的工作模式。
内核中测试串口波特率的方法
内核中测试串口波特率的方法摘要:一、内核中测试串口波特率的方法概述二、具体测试步骤1.设备驱动配置2.串口通信配置3.数据发送与接收4.波特率测试与优化三、测试结果与分析四、总结与建议正文:内核中测试串口波特率的方法在嵌入式系统中,串口波特率的正确配置对于设备的通信稳定性至关重要。
本文将介绍如何在内核中测试串口波特率,并对测试结果进行分析,以保证设备能够正常工作。
一、内核中测试串口波特率的方法概述内核中测试串口波特率主要通过设备驱动配置、串口通信配置、数据发送与接收以及波特率测试与优化四个步骤完成。
在测试过程中,需要确保设备驱动正确加载,串口通信参数设置合理,数据发送与接收正常。
二、具体测试步骤1.设备驱动配置根据设备类型(如UART、SPI等),配置相应的设备驱动。
确保设备驱动能够正确加载,并在内核中注册。
2.串口通信配置配置串口通信的参数,包括波特率、数据位、停止位、校验位等。
这些参数需要与通信伙伴一致,以确保通信正常。
3.数据发送与接收通过设备驱动发送和接收数据。
在发送数据时,可以使用内核提供的串口发送函数;在接收数据时,使用串口接收中断或轮询方式。
4.波特率测试与优化在数据发送与接收的过程中,通过计算发送和接收数据的时间间隔,来测试串口波特率。
根据测试结果,对波特率进行优化,以保证通信稳定性。
三、测试结果与分析通过对内核中串口波特率的测试,可以得到实际的通信速率。
将测试结果与理论值进行对比,分析通信过程中的瓶颈和问题,进一步优化波特率设置。
四、总结与建议内核中测试串口波特率的方法可以帮助我们确保设备在正确的波特率下工作,提高通信稳定性。
在实际应用中,需要根据设备性能和通信需求,合理配置串口波特率,并进行定期测试与优化。
串口打印机不能打印或打印乱码
为何通过串口不能打印或打印乱码?一、硬件准备首先确保你的硬件满足以下条件,并且使用的串口线是XPrinter指定代理或经销商提供的标准线缆。
打印机:请先确认你的打印机端确实是串口,XPrinter的热敏系列打印机串口为25针D型接口或9针D型接口计算机:计算机必须具有串口,如没有串口可使用PCI串口扩展卡(如使用串口扩展卡,要注意多数都是3线制通讯,只能选XON/XOFF握手协议)。
由于USB转串口设备的不稳定性,不建议使用此类转换器。
打印电缆:串行口打印电缆,下列图表说明了XPrinter打印机串口电缆的配置情况。
计算机端(25针D型)---打印机端(25针D型)计算机端(9针) -----------打印机端(25针)PC XPrinterRXD 2 ---------------------- 2 TXDTXD 3 ---------------------- 3 RXDGND 5 ---------------------- 7 GNDDSR 6 ---------------------- 20 DTRCTS 8 ---------------------- 4 RTS注意:Modem使用的串口电缆无法用于PC机和XPrinter打印机的串口打印。
二、配置2.1首先检查打印机当前的串口设置。
方法:首先关闭打印机电源,然后按住面板上的"FEED"键不放,再将打印机打开,等二到三秒就松了按键,此时打印机会打印出当前的串口设置。
2.2根据上图的端口设置,(波特率:19200、数据位:8、奇偶校验:无、停止位:1),在WINDOWS系统的端口属性中输入相同的端口配置(如下图),确认后就可正常打印了。
方法:打开打印机属性→端口→选择COM1→配置端口。
LINUX内核STARTINGKERNEL...串口无输出问题归纳
下面两篇文章是ARM9论坛上的讲解ramdisk文件系统的很不错的文章今天做了个试验,让Linux2.6.29.4从ramdisk根文件系统启动成功,总结一下。
其中涉及的内容较多,很多东西不再详述,如需深入研究请查阅相关资料(百度或谷歌一下一大堆)。
开发环境:Fedora 9交叉编译工具链:arm-linux-gcc 4.3.2 with EABI嵌入式Linux内核版本:2.6.29.4-FriendlyARM。
昨天写贴子的时候具体记不清了,今天起来启动开发板用uname -r查一下,就是叫做2.6.29.4-FriendlyARM,帖子已经改好了。
本文就是友善之臂的2.6.29.4-FriendlyARM的那个版本的内核的基础上改的。
其它版本的应该也类似,仅供参考。
开发板:mini2440-128M Nand FlashBootloader:u-boot-2009.11具体步骤如下:1.解压内核源码树解压linux-2.6.29-mini2440-20090708.tgz到自己的工作目录,会生成一个友善之臂修改过的并且有几个mini2440默认配置文件的内核源码目录linux-2.6.29。
具体步骤参照友善之臂mini2440开发板用户手册,具体不详述了。
2.修改内核配置选项进入内核源码目录linux-2.6.29目录#cp config_mini2440_t35 .config#make menuconfig ARCH=arm打开配置菜单,修改两个配置项,分别是:a):General setup-->选择Initial RAM filesystem and RAM disk...... 项b):Device Drivers-->Block devices-->选择RAM block device support 项并检查Optimize for size是否被选中,如果没有则选中,此项优化内核大小,根据需要进行配置。
linux系统下如何使用minicom传送文件
Minicom是在linux下的一个友好的串口通信程序,类似于Windows操作系统下的超级终端工具。
如果安装双系统,不用虚拟机的朋友,可以直接在linux 下使用minicom传送文件到开发板上,非常方便。
以下是我最近使用minicom传送文件的一点小小的总结,写的非常简单,希望对需要使用的朋友能有些帮助。
首先是要安装和配置minicom。
安装:sudo apt-get install minicom配置:1 . 在终端中输入minicom以启动minicom;2. 先按下Ctrl + a, 放开, 再按o, 出现配置菜单.3. 选择 Serial port setup, 此时所示图标在“Change which setting”中,键入“A”,此时光标移到第A项对应处:串口COM1对应ttyS0, COM2对应ttyS1. (注意选择)具体的配置信息如下所示:Serial port setup [Enter]+-------------------------------------------------------------+| A - Serial Device : /dev/ttyUSB0 || B - Lockfile Location : /var/lock || C - Callin Program : || D - Callout Program -: || E - Bps/Par/Bits : 115200 8N1 || F - Hardware Flow Control : No || G - Software Flow Control : No || || Change which setting? |+-------------------------------------------------------------+注意:如果没有使用USB转串口,而是直接使用串口,那么Serial Device要配置为/dev/ttyS0(如果使用USB转串口,则需要查看dev下是否存在ttyUS,若没有,则创建一个:mknod /dev/ttyUSB0 c 188 0) 。
内核中disp打印
内核中disp打印[ 11.982955] [DISP WRN] file:drivers/video/sun7i/disp/OSAL/OSAL_Clock.c,line:347: [i2c2] incomplete xfer (status: 0x20, dev addr: 0x41)[ 12.014420] NULL hdle[ 12.032095] [DISP WRN] file:drivers/video/sun7i/disp/OSAL/OSAL_Clock.c,line:347: [i2c2] incomplete xfer (status: 0x20, dev addr: 0x41)[ 12.086419] NULL hdle[ 12.089008] [DISP WRN] file:drivers/video/sun7i/disp/OSAL/OSAL_Clock.c,line:347: [i2c2] incomplete xfer (status: 0x20, dev addr: 0x41)[ 12.115151] NULL hdle[ 12.117723] [DISP WRN] file:drivers/video/sun7i/disp/OSAL/OSAL_Clock.c,line:347: [i2c2] incomplete xfer (status: 0x20, dev addr: 0x41)[ 12.141976] [camera_print][detect][L662]camera detect driver init[ 12.151339] [camera_print][detect][L171]NULL hdle[ 12.165883] [DISP WRN] file:drivers/video/sun7i/disp/OSAL/OSAL_Clock.c,line:347: NULL hdle[ 12.180557] csi0_para.csi_dev_qty=1[ 12.184508] [camera_print][detect][L171][ 12.205182] [DISP WRN] file:drivers/video/sun7i/disp/OSAL/OSAL_Clock.c,line:347: NULL hdle[ 12.216997] [DISP WRN] file:drivers/video/sun7i/disp/de_bsp/de/disp_hdmi.c,line:183:csi0_para.csi_twi_id=1[ 12.228448] [camera_print][detect][L171]hdmi_mode_support is NULL [ 12.259891] csi0_para.csi_facing=0[ 12.263723] [camera_print][detect][L193]csi0_para.csi_reset gpio=218,mul_sel=1,data:0[ 12.284796] [camera_print][detect][L193]csi0_para.csi_power_engpio=219,mul_sel=1,data:0[ 12.299603] [camera_print][detect][L198]fetch script data csi0_para.csi_stby fail[ 12.308463] [camera_print][detect][L198]fetch script data csi0_para.csi_af_en fail[ 12.321348] [camera_print][detect][L207]csi0_para.csi_iovdd=[ 12.327741] [camera_print][detect][L207]csi0_para.csi_avdd=[ 12.333943] [camera_print][detect][L207]csi0_para.csi_dvdd=[ 12.340988] [camera_print][detect][L418]camera_list_size: 23 [ 12.347534] [camera_print][detect][L423]modules: OV2710_aw6131 need detect!![ 12.356232] [camera_print][detect][L423]modules: AP0100CS need detect!![ 12.364271] [camera_print][detect][L108]camera_mclk_open !![ 12.372886] [camera_print][detect][L438]camera_diff_i2c_id_detect!![ 12.381123] [camera_print][list][L727]try to detect aw6131_ov2710 ...[ 12.390319] [camera_print][list][L32]OSAL_GPIO_Request ok, gpio_name=csi_power_en, gpio=219,mul_sel=1[ 12.426394] [camera_print][list][L32]OSAL_GPIO_Request ok, gpio_name=csi_power_en, gpio=219,mul_sel=1[ 12.455161] [camera_print][list][L32]OSAL_GPIO_Request ok, gpio_name=csi_reset, gpio=218,mul_sel=1[ 12.468444] [camera_print][list][L32]OSAL_GPIO_Request ok, gpio_name=csi_reset, gpio=218,mul_sel=1[ 12.490757] [camera_print][list][L32]OSAL_GPIO_Request ok, gpio_name=csi_reset, gpio=218,mul_sel=1[ 12.519256] [camera_print][list][L739]reset OV2710_aw6131 .................................[ 12.532484] [camera_print][list][L141]reg[0]:255->data[0]:255[ 12.540201] [camera_print][list][L141]reg[1]:253->data[1]:253[ 12.549444] [camera_print][list][L145]value[0]:128->data[2]:123[ 12.558534] [camera_print][list][L141]reg[0]:255->data[0]:255[ 12.567874] [camera_print][list][L141]reg[1]:254->data[1]:254[ 12.583604] [camera_print][list][L145]value[0]:128->data[2]:128[ 12.604400] camera_detect_OV2710_aw6131 success[ 12.611689] [camera_print][list][L786]detect aw6131_ov2710 success!![ 12.623487] [camera_print][detect][L133]camera_mclk_close !!。
串口打印原理
串口打印原理标题:串口打印原理引言:在计算机和电子设备中,串口(Serial Port)是一种常见的通信接口,用于将数据以连续的位流形式传输。
串口打印是通过串口接口将计算机或其他设备上的信息输出到打印机或其他外部设备上。
本文将详细介绍串口打印的原理,包括串口通信的基本原理、串口通信协议和串口打印的实现方式。
正文:1. 串口通信的基本原理1.1 串口通信的定义和特点1.2 串口通信的基本原理1.3 串口通信的工作模式2. 串口通信协议2.1 常见的串口通信协议2.1.1 RS-232协议2.1.2 RS-485协议2.1.3 USB串口协议2.2 串口通信协议的工作原理2.2.1 数据位、停止位和校验位2.2.2 波特率和数据传输速率2.2.3 数据流控制3. 串口打印的实现方式3.1 串口打印的硬件实现3.1.1 串口接口和线缆3.1.2 打印机的串口设置3.2 串口打印的软件实现3.2.1 串口通信的编程接口3.2.2 数据的发送和接收3.2.3 错误处理和异常情况1. 串口通信的基本原理1.1 串口通信的定义和特点串口通信是指通过串行接口进行数据传输的通信方式。
串口通信相对于并行接口通信来说,只需要使用少量的引脚,因此在资源有限的情况下更为适用。
串口通信的特点包括传输速率较低、传输距离较短、数据传输稳定可靠等。
1.2 串口通信的基本原理串口通信是通过将数据以连续的位流形式传输来实现的。
在传输过程中,数据被分为多个字节,每个字节由起始位、数据位、校验位和停止位组成。
起始位用于标识数据传输的开始,停止位用于标识数据传输的结束,校验位用于检测传输过程中的错误。
1.3 串口通信的工作模式串口通信可以分为同步传输和异步传输两种工作模式。
同步传输是指数据的发送和接收在时钟信号的同步下进行,传输速率较高,但对硬件要求较高。
异步传输是指数据的发送和接收没有时钟信号的同步,传输速率较低,但对硬件要求较低。
2. 串口通信协议2.1 常见的串口通信协议常见的串口通信协议包括RS-232协议、RS-485协议和USB串口协议。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
r3 : b4c16880 r2 : 00000000 r1 : b4c16880 r0 : 00000000
Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel
fe80: bf81f810 00000060 00000008 00000080 000000ff 80704df8 8874febc 8874fea8
fea0: 802ddf78 802dddd4 8077001c 00000060 8874fef4 8874fec0 802f762c 802ddf38
fd00: b7327800 00000001 b54dd000 00000000 8874fd2c 8874fd20 804e8324 804e7ba0
fd20: 8874fd44 8874fd30 802f0004 804e8318 802effe0 b54dd000 8874fd54 8874fd48
LR is at rt_spin_lock_slowlock+0x68/0x27c
pc : [<804e7e08>] lr : [<804e7bfc>] psr: 60000113
sp : 8874fcb8 ip : b4c16881 fp : 8874fd1c
r10: 00000000 r9 : 8077001c r8 : b4c16880
[<802ddee8>] (flush_to_ldisc+0x120/0x164) from [<802ddf78>] (tty_flip_buffer_push+0x4c/0x50)
[<802ddf78>] (tty_flip_buffer_push+0x4c/0x50) from [<802f762c>] (altera_uart_interrupt+0x2c8/0x348)
fcc0: 804e7a7c 800536f8 804e7a7c 800536f8 b4c17a80 8874e000 8874fcfc 8874fce8
fce0: 800545c0 00000000 00000001 8874e001 8874fd14 bf81f800 b7327d1d b7327800
ff80: 00000000 00000000 8874ff88 8874ff88 880c3c28 800478f8 00000000 00000000
ffa0: 00000000 8874ffb0 8000ea58 80047904 00000000 00000000 00000000 00000000
fd_dir is 53 ------------[ cut here ]------------
kernel BUG at kernel/rtmutex.c:738!
Internal error: Oops - BUG: 0 [#1] PREEMPT SMP ARM
Modules linked in: axiram_config(O) axiram_dspload(O) axiram_nm(O) axiram_service(O) axiram_class(O)
fd40: 802daf20 802effec 8874fd94 8874fd58 802d83b4 802daf04 8874fd74 8874fd68
fd60: b7327a80 b7327a6c 8874fd94 b54dd000 b7327d1d b7327c1d b7327800 00000001
[<80085618>] (irq_thread+0x13c/0x1a4) from [<800479a4>] (kthread+0xac/0xb4)
[<800479a4>] (kthread+0xac/0xb4) from [<8000ea58>] (ret_from_fork+0x14/0x20)
Code: e7f001f2 ebfffbd1 eaffffe4 e7f001f2 (e7f001f2)
---[ end trace 0000000000000002 ]---
note: irq/77-altera_u[154] exited with preempt_count 1
Unable to handle kernel paging request at virtual address ffffffec
fe00: 00000001 8874e000 8874fe2c 8874fe18 8874fe34 8874fe20 800545c0 800729e0
fe20: 00000001 8874e000 8874fe4c 8874fe38 80054680 800545b8 8874e000 800558a8
CPU: 0 PID: 154 Comm: irq/77-altera_u Tainted: G D O 3.10.37-ltsi-rt37 #9
task: b4c16880 ti: 8874e000 task.ti: 8874e000
PC is at kthread_data+0x18/0x20
[<802d83b4>] (process_echoes+0x5c/0x2a8) from [<802d9adc>] (n_tty_receive_buf+0x498/0x10bc)
[<802d9adc>] (n_tty_receive_buf+0x498/0x10bc) from [<802ddee8>] (flush_to_ldisc+0x120/0x164)
ffc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
ffe0: 00000000 00000000 00000000 00000000 00000013 00000000 6e65706f 0073665f
r7 : b4c16880 r6 : 00000000 r5 : 807427d4 r4 : b4c16880
r3 : 00000000 r2 : 8874fae0 r1 : 8874ff28 r0 : b4c16880
Flags: nzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user
ff00: b45bfd60 00000000 8874ff5c 8874ff18 80085618 80085484 8874e000 b45bfd60
ff20: b45bfd40 00000000 00000000 80085374 00000000 880c3c28 00000000 b45bfd40
CPU: 0 PID: 154 Comm: irq/77-altera_u Tainted: G O 3.10.37-ltsi-rt37 #9
task: b416880 ti: 8874e000 task.ti: 8874e000
PC is at rt_spin_lock_slowlock+0x274/0x27c
Control: 10c5387d Table: 08e0404a DAC: 00000015
Process irq/77-altera_u (pid: 154, stack limit = 0x8874e240)
Stack: (0x8874fcb8 to 0x88750000)
fca0: Байду номын сангаас 00000000 8874fcc8
fec0: 00000000 8874fed0 80055a18 b45bfd40 bf808a80 00000000 00000001 bf808a80
fee0: 80085478 b45bfd40 8874ff14 8874fef8 800854a8 802f7370 00000004 80704ebc
LR is at irq_thread_dtor+0x38/0xc0
pc : [<80047eb8>] lr : [<800853ac>] psr: 20000193
sp : 8874fad0 ip : 8874fae0 fp : 8874fadc
r10: 80709550 r9 : 8874e000 r8 : 8874e000
[<802f762c>] (altera_uart_interrupt+0x2c8/0x348) from [<800854a8>] (irq_forced_thread_fn+0x30/0x64)
[<800854a8>] (irq_forced_thread_fn+0x30/0x64) from [<80085618>] (irq_thread+0x13c/0x1a4)
fdc0: 80054680 804e7bfc bf81f810 b54dd000 8874fdf4 8874e000 b54dd000 bf81f810
fde0: b45bf880 804e7d80 8874fe5c 8874fdf8 8874fe14 8874fe00 800545c0 800729e0
pgd = 80004000