S3C2440各类端口操作函数简介

发布时间:2024-08-09  

micro2440采用S3C2440处理器(和S3C2410区别不大),在其Linux源码中,和这个平台相关的代码主要在arch/arm/mach-s3c2410和include/asm-arm/arch-s3c2410中,相关驱动在drivers目录中。



(1)DM9000网卡驱动
kernel-2.6.13/drivers/net/dm9000x.c
(2)串口(包括三个串口驱动0,1,2,对应设备名/dev/tts/0,1,2)
kernel-2.6.13/drivers/serial/s3c2410.c
(3)实时时钟RTC驱动
kernel-2.6.13/drivers/char/s3c2410-rtc.c
(4)LED驱动
kernel-2.6.13/drivers/char/qq2440_leds.c
(5)按键驱动
kernel-2.6.13/drivers/char/qq2440_buttons.c
(6)触摸屏驱动
kernel-2.6.13/drivers/input/touchscreen/s3c2410_ts.c
(7)yaffs文件系统源代码目录
kernel-2.6.13/fs/yaffs2
(8)USB鼠标、键盘源代码
kernel-2.6.13/drivers/usb/input/hid-input.c
(9)SD/MMC 卡驱动源代码目录(在2.6.13内核中仅支持2G容量以内的SD卡)
kernel-2.6.13/drivers/mmc
(10)NandFlash 驱动
kernel-2.6.13/drivers/mtd/nand
(11)UDA1341音频驱动目录
kernel-2.6.13/sound/oss/uda1341.c
kernel-2.6.13/ drivers/l3
(12)LCD驱动(包含3.5",7", 8.4", 10.4", 12.4",15"等大小的驱动)
kernel-2.6.13/drivers/video/s3c2410fb.c
(13)优盘支持驱动
kernel-2.6.13/drivers/usb/storage
(14)中星微USB摄像头驱动
kernel-2.6.13/drivers/usb/media/gspca



1.S3C2410_GPB5是端口编号,定义在regs-gpio.h中,

#define S3C2410_GPIO_BANKB   (32*1)
#defineS3C2410_GPIONO(bank,offset)   ((bank) + (offset))
#defineS3C2410_GPB5        S3C2410_GPIONO(S3C2410_GPIO_BANKB, 5)

S3C2410共有130个GPIO,分为9组(GPA~GPJ),每组最多可以有32个,每个GPIO有2~4个可选功能,每组的控制寄存器空间有4个,例如对于GPB,有GPBCON、GPBDAT、GPBUP和Reserved,分别是功能配置、数据缓存、上拉使能和保留。

上面的S3C2410_GPB5就是GPIO的编号,也就是在号码空间(0~32*9-1)中的位置,bank是分组的基号码,offset是组内偏移量。



2.S3C2410_GPB5_OUTP是端口功能,定义在regs-gpio.h中,

#define S3C2410_GPB5_INP     (0x00 <<10)
#define S3C2410_GPB5_OUTP    (0x01 <<10)

GPBCON的第10、11两位用于配置GPB5的功能,00= Input ,01= Output

3.S3C2410 GPIO的操作函数

在hardware.h文件中有:

s3c2410_gpio_cfgpin    //配置端口的GPIO的功能
s3c2410_gpio_getcfg    //读取功能配置
s3c2410_gpio_pullup    //配置上拉电阻
s3c2410_modify_misccr//杂项配置

s3c2410_gpio_getirq     //给定端口,转换出IRQ号
s3c2410_gpio_irqfilter   //配置IRQ过滤使能与否

s3c2410_gpio_setpin    //写数据到端口
s3c2410_gpio_getpin    //从端口读数据

这些函数的实现在gpio.h中

void s3c2410_gpio_setpin(unsigned int pin, unsigned intto)
{
void __iomem *base = S3C2410_GPIO_BASE(pin);
unsignedlong offs = S3C2410_GPIO_OFFSET(pin);
unsigned longflags;
unsigned long dat;

local_irq_save(flags);

dat = __raw_readl(base + 0x04);
dat &= ~(1 <dat |= to << offs;
__raw_writel(dat, base +0x04);

local_irq_restore(flags);
}

(自己的理解:dat= __raw_readl(base + 0x04); dat &= ~(1 << offs); dat |= to<< offs;譬如操作的是端口5,这几句能保证其他的端口保持原值,而仅仅是端口5值改变)



4.S3C2410_GPIO_BASE和S3C2410_GPIO_OFFSET也是在regs-gpio.h文件中定义,

#define S3C2410_GPIO_BASE(pin)      ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO)
#defineS3C2410_GPIO_OFFSET(pin)   ((pin) & 31)

而在map.h中有:


#define S3C24XX_VA_GPIO   S3C2410_ADDR(0x00E00000) //虚拟地址S3C24XX_VA_GPIO=0xF0E00000
#define S3C2400_PA_GPIO   (0x15600000)
#define S3C2410_PA_GPIO   (0x56000000) //GPACON 物理地址
#defineS3C24XX_SZ_GPIO    SZ_1M //0x100000 = 1024 *1024

S3C2410_GPIO_BASE作用是:根据端口编号pin,算出端口所在组的虚拟基址。((pin)&~31)是去掉pin当中小于等于31的零头(清0低5位),>>1的原因是每组GPIO中最多可以有32个端口,控制这些端口需要4个寄存器空间,4个寄存器空间就需要4*4=16个字节进行编址,32/16=2,左移一位刚好满足。也就是说,上一组端口和下一组端口的编号相差32,而控制寄存器的地址相差16。(自己的理解:因为每个GPIO口对应4个寄存器,每个寄存器32位,S3C2410_GPIO_BASE仅仅是算出虚拟基址,而不管是哪个具体端口,2的5次方正好是32,((pin)&~31)可以屏蔽掉低五位,右移一位是因为端口数不超过32,每个GPIO口对应4个寄存器,每个寄存器32位,4*32/8=16=0x10,例如GPIOA=0X10+S3C24XX_VA_GPIO,GPIOB=0X20+S3C24XX_VA_GPIO,0x10所表示的数的个数超过32)

S3C2410_GPIO_OFFSET作用是:根据端口编号pin,算出端口所在组的偏移量。((pin)& 31)即去掉比31大的数(清0第6位以上的位)。



5. __raw_readl和__raw_writel

Linux对I/O的操作都定义在asm/io.h中,相应的在arm平台下,就在asm-arm/io.h中。

#define __raw_readl(a)   (__chk_io_ptr(a), *(volatileunsigned int __force   *)(a))
#define __raw_writel(v,a)(__chk_io_ptr(a), *(volatile unsigned int __force   *)(a)= (v))

在includelinuxcompiler.h中:

#ifdef __CHECKER__
……
extern void __chk_io_ptr(void__iomem *);
#else
……
# define __chk_io_ptr(x)(void)0
……
#endif

__raw_readl(a)展开是:((void)0,*(volatile unsigned int _force*)(a))。在定义了__CHECKER__的时候先调用__chk_io_ptr检查该地址,否则__chk_io_ptr什么也不做,*(volatileunsigned int _force*)(a)就是返回地址为a处的值。(void)xx的做法有时候是有用的,例如编译器打开了检查未使用的参数的时候需要将没有用到的参数这么弄一下才能编译通过。

CPU对I/O的物理地址的编程方式有两种:一种是I/O映射,一种是内存映射。__raw_readl和__raw_writel等是原始的操作I/O的方法,由此派生出来的操作方法有:inb、outb、_memcpy_fromio、readb、writeb、ioread8、iowrite8等。



6.local_irq_save和local_irq_restore

关中断和开中断,在asm-arm/system.h中定义。

#define local_irq_save(x)     
({       
__asm____volatile__(     
"mrs %0,cpsr   @ local_irq_saven"
"cpsid i"      
: "=r" (x) : : "memory", "cc");    
})

#define local_irq_save(x)     
({       
  unsigned long temp;    
   (void)(&temp == &x);    
__asm____volatile__(     
"mrs %0,cpsr   @ local_irq_saven"
" orr %1, %0,#128n"     
" msr cpsr_c,%1"     
: "=r" (x),"=r" (temp)     
:       
: "memory", "cc");     
})


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>