新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > micro2440驅動分析1——LED驅動

        micro2440驅動分析1——LED驅動

        作者: 時間:2016-11-20 來源:網絡 收藏
        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)Nand Flash 驅動
        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

        本文引用地址:http://www.104case.com/article/201611/318873.htm

        1.S3C2410_GPB5是端口編號,定義在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個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 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作用是:根據端口編號pin,算出端口所在組的虛擬基址。((pin) & ~31)是去掉pin當中小于等于31的零頭(清0低5位),>>1的原因是每組GPIO中最多可以有32個端口,控制這些端口需要4個寄存器空間,4個寄存器空間就需要4*4=16個字節進行編址,32/16=2,左移一位剛好滿足。也就是說,上一組端口和下一組端口的編號相差32,而控制寄存器的地址相差16。

        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), *(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)展開是:((void)0, *(volatile unsigned int _force *)(a))。在定義了__CHECKER__的時候先調用__chk_io_ptr檢查該地址,否則__chk_io_ptr什么也不做,*(volatile unsigned 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");
        })




        評論


        技術專區

        關閉
        主站蜘蛛池模板: 隆德县| 清徐县| 云浮市| 寻甸| 额敏县| 盐亭县| 台中县| 资阳市| 汤原县| 漠河县| 平乐县| 延安市| 台中县| 吕梁市| 理塘县| 沽源县| 长白| 灯塔市| 霍山县| 常山县| 松原市| 天台县| 镇康县| 江门市| 富宁县| 建始县| 仙游县| 绥中县| 兴仁县| 屏南县| 安泽县| 平南县| 浑源县| 边坝县| 巍山| 松江区| 永胜县| 旬邑县| 闸北区| 衡南县| 巴中市|