新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > micro2440驅(qū)動(dòng)分析1——LED驅(qū)動(dòng)

micro2440驅(qū)動(dòng)分析1——LED驅(qū)動(dòng)

作者: 時(shí)間:2016-11-20 來(lái)源:網(wǎng)絡(luò) 收藏
micro2440采用S3C2440處理器(和S3C2410區(qū)別不大),在其Linux源碼中,和這個(gè)平臺(tái)相關(guān)的代碼主要在arch/arm/mach-s3c2410和include/asm-arm/arch-s3c2410中,相關(guān)驅(qū)動(dòng)在drivers目錄中。

(1)DM9000 網(wǎng)卡驅(qū)動(dòng)
kernel-2.6.13/drivers/net/dm9000x.c
(2)串口(包括三個(gè)串口驅(qū)動(dòng)0,1,2,對(duì)應(yīng)設(shè)備名/dev/tts/0,1,2)
kernel-2.6.13/drivers/serial/s3c2410.c
(3)實(shí)時(shí)時(shí)鐘RTC 驅(qū)動(dòng)
kernel-2.6.13/drivers/char/s3c2410-rtc.c
(4)LED 驅(qū)動(dòng)
kernel-2.6.13/drivers/char/qq2440_leds.c
(5)按鍵驅(qū)動(dòng)
kernel-2.6.13/drivers/char/qq2440_buttons.c
(6)觸摸屏驅(qū)動(dòng)
kernel-2.6.13/drivers/input/touchscreen/s3c2410_ts.c
(7)yaffs 文件系統(tǒng)源代碼目錄
kernel-2.6.13/fs/yaffs2
(8)USB 鼠標(biāo)、鍵盤(pán)源代碼
kernel-2.6.13/drivers/ usb/input/hid-input.c
(9)SD/MMC 卡驅(qū)動(dòng)源代碼目錄(在2.6.13 內(nèi)核中僅支持2G 容量以?xún)?nèi)的SD 卡)
kernel-2.6.13/drivers/mmc
(10)Nand Flash 驅(qū)動(dòng)
kernel-2.6.13/drivers/mtd/nand
(11)UDA1341 音頻驅(qū)動(dòng)目錄
kernel-2.6.13/ sound/oss/uda1341.c
kernel-2.6.13/ drivers/l3
(12)LCD 驅(qū)動(dòng)(包含3.5", 7", 8.4", 10.4", 12.4", 15"等大小的驅(qū)動(dòng))
kernel-2.6.13/drivers/video/s3c2410fb.c
(13)優(yōu)盤(pán)支持驅(qū)動(dòng)
kernel-2.6.13/drivers/usb/storage
(14)中星微USB 攝像頭驅(qū)動(dòng)
kernel-2.6.13/drivers/usb/media/gspca

本文引用地址:http://butianyuan.cn/article/201611/318873.htm

1.S3C2410_GPB5是端口編號(hào),定義在regs-gpio.h中,

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

S3C2410共有130個(gè)GPIO,分為9組(GPA~GPJ),每組最多可以有32個(gè),每個(gè)GPIO有2~4個(gè)可選功能,每組的控制寄存器空間有4個(gè),例如對(duì)于GPB,有GPBCON、GPBDAT、GPBUP和Reserved,分別是功能配置、數(shù)據(jù)緩存、上拉使能和保留。

上面的S3C2410_GPB5就是GPIO的編號(hào),也就是在號(hào)碼空間(0~32*9-1)中的位置,bank是分組的基號(hào)碼,offset是組內(nèi)偏移量。

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的操作函數(shù)

在hardware.h文件中有:

s3c2410_gpio_cfgpin //配置端口的GPIO的功能
s3c2410_gpio_getcfg //讀取功能配置
s3c2410_gpio_pullup //配置上拉電阻
s3c2410_modify_misccr //雜項(xiàng)配置

s3c2410_gpio_getirq //給定端口,轉(zhuǎn)換出IRQ號(hào)
s3c2410_gpio_irqfilter //配置IRQ過(guò)濾使能與否

s3c2410_gpio_setpin //寫(xiě)數(shù)據(jù)到端口
s3c2410_gpio_getpin //從端口讀數(shù)據(jù)

這些函數(shù)的實(shí)現(xiàn)在gpio.h中

void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
{
void __iomem *base = S3C2410_GPIO_BASE(pin);
unsigned long offs = S3C2410_GPIO_OFFSET(pin);
unsigned long flags;
unsigned long dat;

local_irq_save(flags);

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

local_irq_restore(flags);
}

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

#define S3C2410_GPIO_BASE(pin) ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO)
#define S3C2410_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 物理地址
#define S3C24XX_SZ_GPIO SZ_1M //0x100000 = 1024 *1024

S3C2410_GPIO_BASE作用是:根據(jù)端口編號(hào)pin,算出端口所在組的虛擬基址。((pin) & ~31)是去掉pin當(dāng)中小于等于31的零頭(清0低5位),>>1的原因是每組GPIO中最多可以有32個(gè)端口,控制這些端口需要4個(gè)寄存器空間,4個(gè)寄存器空間就需要4*4=16個(gè)字節(jié)進(jìn)行編址,32/16=2,左移一位剛好滿(mǎn)足。也就是說(shuō),上一組端口和下一組端口的編號(hào)相差32,而控制寄存器的地址相差16。

S3C2410_GPIO_OFFSET作用是:根據(jù)端口編號(hào)pin,算出端口所在組的偏移量。((pin) & 31)即去掉比31大的數(shù)(清0第6位以上的位)。

5. __raw_readl和__raw_writel

Linux對(duì)I/O的操作都定義在asm/io.h中,相應(yīng)的在arm平臺(tái)下,就在asm-arm/io.h中。

#define __raw_readl(a) (__chk_io_ptr(a), *(volatile unsigned 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)展開(kāi)是:((void)0, *(volatile unsigned int _force *)(a))。在定義了__CHECKER__的時(shí)候先調(diào)用__chk_io_ptr檢查該地址,否則__chk_io_ptr什么也不做,*(volatile unsigned int _force *)(a)就是返回地址為a處的值。(void)xx的做法有時(shí)候是有用的,例如編譯器打開(kāi)了檢查未使用的參數(shù)的時(shí)候需要將沒(méi)有用到的參數(shù)這么弄一下才能編譯通過(guò)。

CPU對(duì)I/O的物理地址的編程方式有兩種:一種是I/O映射,一種是內(nèi)存映射。__raw_readl和__raw_writel等是原始的操作I/O的方法,由此派生出來(lái)的操作方法有:inb、outb、_memcpy_fromio、readb、writeb、ioread8、iowrite8等。

6.local_irq_save和local_irq_restore

關(guān)中斷和開(kāi)中斷,在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");
})




評(píng)論


技術(shù)專(zhuān)區(qū)

關(guān)閉