1、对UART驱动添加设备信息
对于2440的UART,内核已经对其完整的配置不需要做写入任何的代码,
这里要说明的是,在学习的裸机的时候,我们知道,UART相应的引脚可以配置称为红外IR,这里串口2就被配置成了红外驱动。
对于平台设备,首先要说明的应该是s3c2410_uartcfg结构体,该结构体定义在,Serial_s3c.h(includelinux)文件中
structs3c2410_uartcfg {undefined
unsigned char hwport; /* 硬件端口编号比如UART0 UART1 等等*/
unsigned char unused; //发送和接收使能控制信号
unsigned short flags; //标记号
upf_t uart_flags; /* 默认UART标记号,流量控制标志位*/
unsigned int clk_sel; //时钟选择
unsigned int has_fracval;
unsigned long ucon; /* 对应控制寄存器UCONn*/
unsigned long ulcon; /*对应格式寄存器ULCONn */
unsigned long ufcon; /* 设置缓冲区的寄存器UFCONn */
};
在Mach-smdk2440.c (archarmmach-s3c24xx)文件中,有对其平台设备信息的描述:
static structs3c2410_uartcfg smdk2440_uartcfgs[] __initdata = {undefined
[0] = {undefined
.hwport = 0,
.flags = 0,
.ucon = 0x3c5,//00000011 1100 0101
/**************************************************************************
对应的二进制为0000 0011 1100 0101
查看数据手册可以很直观的看出来,这里是设置含义是:
接收和发送均使用中断或者查询法
将发生数据帧错误时将触发中断
当使用FIFO的时候,接收超时将产生中断,设置为低电平触发中断
UART的时钟选用PCLK
*******************************************************************/
.ulcon = 0x03,
/**************************************************************************
对应的二进制为0000 0000 0000 0011
这里主要设设置帧格式:
8为数据位
1为停止位
无校验位
正常模式(非红外模式)
*******************************************************************/
.ufcon = 0x51,
/**************************************************************************
对应的二进制为0000 00000101 0001
这是设置使用FIFO
使能FIFO
接收FIFO的阈值为8BYTE
接收FIFO的阈值为16BYTE
*******************************************************************/
},
[1] = {undefined
.hwport = 1,
.flags = 0,
.ucon = 0x3c5,
.ulcon = 0x03,
.ufcon = 0x51,
},
/* 设备为红外模式*/
[2] = {undefined
.hwport = 2,
.flags = 0,
.ucon = 0x3c5,
.ulcon = 0x43, //红外模式
.ufcon = 0x51,
}
};
在Mach-smdk2440.c中的smdk2440_map_io函数中有:
s3c24xx_init_uarts(smdk2440_uartcfgs,ARRAY_SIZE(smdk2440_uartcfgs));(该函数定义在Init.c (archarmplat-samsung) 中),干函数又调用:
(cpu->init_uarts)(cfg,no);
cpu->init_uarts在Common.c (archarmmach-s3c24xx)文件中,指向的是s3c244x_init_uarts(该函数定义在S3c244x.c (archarmmach-s3c24xx)),然后s3c244x_init_uarts又调用s3c244x_init_uarts函数:
void __inits3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no)
{undefined
s3c24xx_init_uartdevs("s3c2440-uart",s3c2410_uart_resources, cfg, no);
}
也就是说s3c24xx_init_uarts(smdk2440_uartcfgs,ARRAY_SIZE(smdk2440_uartcfgs));最终会被使用成:
s3c24xx_init_uartdevs("s3c2440-uart",s3c2410_uart_resources, cfg, no);
也就是,UART的平台设备定义的名字为:"s3c2440-uart"
可以,应该不容忽视的是,这里内核还定义了系统的资源,s3c2410_uart_resources,该资源在Common.c (archarmmach-s3c24xx)文件中被定义:
static structresource s3c2410_uart0_resource[] = {undefined
[0] = DEFINE_RES_MEM(S3C2410_PA_UART0,SZ_16K),
[1] = DEFINE_RES_NAMED(IRQ_S3CUART_RX0,
IRQ_S3CUART_ERR0 -IRQ_S3CUART_RX0 + 1,
NULL, IORESOURCE_IRQ)
};
static structresource s3c2410_uart1_resource[] = {undefined
[0] = DEFINE_RES_MEM(S3C2410_PA_UART1,SZ_16K),
[1] = DEFINE_RES_NAMED(IRQ_S3CUART_RX1,
IRQ_S3CUART_ERR1 -IRQ_S3CUART_RX1 + 1,
NULL, IORESOURCE_IRQ)
};
static structresource s3c2410_uart2_resource[] = {undefined
[0] = DEFINE_RES_MEM(S3C2410_PA_UART2,SZ_16K),
[1] = DEFINE_RES_NAMED(IRQ_S3CUART_RX2,
IRQ_S3CUART_ERR2 -IRQ_S3CUART_RX2 + 1,
NULL, IORESOURCE_IRQ)
};
在这里,我们以uart0的资源为例来分析一下资源的构成:
static structresource s3c2410_uart0_resource[] = {undefined
[0] = DEFINE_RES_MEM(S3C2410_PA_UART0,SZ_16K),
[1] =DEFINE_RES_NAMED(IRQ_S3CUART_RX0,
IRQ_S3CUART_ERR0 - IRQ_S3CUART_RX0 + 1,
NULL, IORESOURCE_IRQ)
};
可以看到对于UART0一共定义了两个资源,其中:
[0] =DEFINE_RES_MEM(S3C2410_PA_UART0, SZ_16K),表明声明的为内存资源,其实,宏DEFINE_RES_MEM被定义为:
{
.start = (_start),
.end = (_start) + (_size) - 1,
.name = (_name),
.flags = (_flags),
}
其中name为NULL;也就是说,UART申请的内存资源为起始物理地址为S3C2410_PA_UART0,大小为SZ_16K,很容易可以查到S3C2410_PA_UART0对应的物理地址就是0x50000000,通过查看数据手册得到0x50000000对应的是ULCON0(UART channel 0 line controlregister,控制帧格式的寄存器)的首地址,那么为什么是SZ_16K呢?继续看数据手册,发现ULCON1的首地址是0x50004000,那么0x50004000-0x50000000=SZ_16K,所以是大小为16kBYTE;.flags = (_flags)这个标号对应的内存资源的标记号,只不过系统为每种资源设定的标记号码而已,驱动找什么类型资源就是对应这个标号找的。
补充一点的是:这里的内存资源是16Kbyte,而且申请的时候为什么只有是一个寄存器的地址,这里是因为对于控制UART0的寄存器组的地址是有规律的,也就是说每个寄存器占有四个字节,上一个寄存器的地址+4就是下一个寄存器的首地址,而ULCON0(0x50000000)就UART0寄存器组的第一个寄存器,可以理解为是该组寄存器的首地址。
查看数据手册,对于UART0来说,看一下其寄存器分配:
ULCON0 0x50000000 R/W UART channel 0 line controlregister
UCON0 0x50000004 R/W UART channel 0 controlregister
UFCON0 0x50000008 R/W UART channel 0 FIFO controlregister
UMCON0 0x5000000C R/W UART channel 0 Modem controlregister
UTRSTAT0 0x50000010 R UART channel 0 Tx/Rx statusregister
UERSTAT0 0x50000014 R UART channel 0 Rx error statusregister
UFSTAT0 0x50000018 R UART channel 0 FIFO statusregister
UMSTAT0 0x5000001C R UART channel 0 modem statusregister
UTXH00x50000020(L)
0x50000023(B) W (by byte) UART channel 0 transmit buffer register
URXH00x50000024(L)
0x50000027(B) R (bybyte) UART channel 0 receive bufferregister
UBRDIV0 0x50000028 R/W Baud rate divisior register 0
接下来看第二个资源:
[1] =DEFINE_RES_NAMED(IRQ_S3CUART_RX0,
IRQ_S3CUART_ERR0 -IRQ_S3CUART_RX0 + 1,
NULL, IORESOURCE_IRQ)
首先把宏替换掉就是:
.start = IRQ_S3CUART_RX0, //74
.end = RQ_S3CUART_ERR0 -IRQ_S3CUART_RX0 + 1, //76-74+1
.name = NULL,
.flags = IORESOURCE_IRQ,
对于IRQ就比较简单了,内核为每个中断都有对其唯一的IRQ号,这些号码定义在Irqs.h(archarmmach-s3c24xxincludemach) 文件中(对于中断号的问题,这些东西在裸机接扫寄存器的时候已经写的很详细了,通过中断号可以判定是哪个中断源引起的中断),可以看到:
UART0接收中断 #define IRQ_S3CUART_RX0 74
UART0发送中断 #define IRQ_S3CUART_TX0 75
UART0错误中断 #define IRQ_S3CUART_ERR0 76
在平台设备中定义的这些资源,可以通过在驱动程序通过函数:
platform_get_resource来或许相应的资源。
对于平台设备,暂时分析到这里,后面看驱动分析和测试部分。
2、对UART驱动的测试
假如够细心的话,可以在内核启动的时候看到:
s3c2440-uart.0:ttySAC0 at MMIO 0x50000000 (irq = 74, base_baud = 0) is a S3C2440
上一篇:七 linux LCD驱动代码分析
下一篇:linux USB 摄像头 驱动 移植,使用
推荐阅读

推荐帖子
- wince5.0添加触摸屏问题
- 我有一个2410的板子,运行5.0的操作系统.添加了触摸屏,但触摸屏什么反应都没有.运行touchcalibrate.exe时,程序一闪而过,无法打开,请问是什么问题?wince5.0添加触摸屏问题
-
hezhengli
WindowsCE
- pe导出函数问题
- 大家好: 根据导出函数表找到了addressofrunction的数组地址,并且根据addressofnameordinal和addressofname找到了相应的索引,但是有句代码我看不太懂,就是: WORDnumber=*((WORD*)(functionAddress+1)); if(number>ped->NumberOfNames)continue; lstrcpy
-
hilin029
嵌入式系统
- 电子时钟设计, 使用定时器设计具有时、分、秒显示的电子时钟,1602显示屏显示msp430
- 这个其实是MSP430的单片机的题,因为没有这个模块要求:使用定时器设计一个具有时、分、秒显示的电子时钟(采用1602液晶显示),并定义一个启动键,当按下该键时电子时钟从当前值开始走时,再按一下停止走时。1》我的思路是用定时器A先采用增计数模式,然后当摁下启动键后,对自己定义的时间进行增计数,再摁下后,产生中断信号,停止计数,之后恢复到之前停止计数的状态进行重新计数。我不知道这样的方法可行吗??2》我看到还有个RTC模块,但这个我不知道怎么用求解如果可以的话,可以写上定时器的具
-
lulla
51单片机
- 电子设计大赛中怎样领导团队前进?
- 本帖最后由paulhyde于2014-9-1509:36编辑我们都在不断寻找关于电子设计大赛的种种资料,忙的不亦乐乎!但是要想赢得比赛,我们却不知不觉把一个很重要的因素淡忘了,那就是团队的力量!!!那么我们该怎么建立一个优秀的团队,和采取怎样的团队管理办法呢?忘各个团队的负责人,和有经验的盟友研讨! 电子设计大赛中怎样领导团队前进?
-
小平无间道
电子竞赛
- 只为uC而生,uS成长历程 9
- 昨晚我们已经基本阐明了这样一个以(字节间)超时作为判断一串数据是否接收完整的超时机制的完整思路和假设性分析。 为了避免过于冲突,今晚我仍然不会立马切到我之前上传的那份我经过整理的已经变成一个足以成为第三方库的模块。 而是以串口为例,从一个更加符合逻辑的过程来进行这个模块功能的一步步实现的推演过程。只为uC而生,uS成长历程9
-
辛昕
编程基础
- LP54100 而非LPC1100系列接收心得-{澄清下}
- 本帖最后由fyaocn于2015-3-1811:24编辑 本次按照LPC54100准备,不过收到的时候是LPC1100,没有准备,所以不大熟悉。所以这次就先比较一下。 LPC54100是高性能MCU,属于典型的低功耗,高性能芯片。主要的均衡的性能和随时唤醒的低功耗功能,很适合现在热门的物联网设计和有关的设备。内核是双核的32位ARMCortex-M4F/M0+100MHz,最多到512kB板载Flash,低功耗的串行接口I2C,UART,SPI,最多50个GPI
-
fyaocn
NXP MCU
实战 培训 开发板 精华推荐
最新视频课程更多
- 【ST板卡来了(下)】 品读STM32实战经验,汲取FAE经验闯关去抽奖
- 晒出我使用MSP430编译器的经验与技巧!
- EEWORLD新年有奖竞猜,邀你来出题啦!
- 推荐有礼,分享有你!DSP学习季开学了,推荐你最喜欢的TI DSP资料!
- 【EEWORLD第二十三届】2011年02月社区明星人物揭晓!
- 2022 Digi-Key KOL 视频系列:你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍
- TI电机驱动课程重磅来袭,评论赢奖!
- 【TI 教室】学电源,晒成绩,挖楼有礼!
- 开发板芯币竞拍,每日一款!今日竞拍开发板:Banana PI D1
- 【EEWORLD第四十二届】2012年09月社区明星人物揭晓!