亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 1455 | 回復(fù): 0
打印 上一主題 下一主題

Driving The S3C44B0X IIS Controller In uCLinux [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2010-02-03 12:01 |只看該作者 |倒序瀏覽

Wang Guibao (
puma20@sina.com
) 2010-02-01

This is a short article reflecting my works during the winter holiday: adding a char device driver module into the kernel, which initializes the IIS controller embedded in the ARM7 processor S3C44B0X, and provides write and ioctl interface. When an user application write data to this device, it feeds the data to an D/A converter, CS4334, which converts the data into analog signals, and drives a loudspeaker or earphone as output. Much of this article consists material found on the Web, while the source code is written from scracth, though.

1. Configure uClinux building system
1) In linux-2.4.x/driver/char/Makefile, add
    obj_$(CONFIG_S3C44B0X_IIS) += cs4334.o
Normally you see many modules like the line above already there, just append this line after them.
2) In linux-2.4.x/driver/char/Config.in, add
    bool 'S3C44B0X IIS controller support' CONFIG_S3C44B0X_IIS
Normally you see many menuitems out there already, just append this line after them.

By now, if you make menuconfig or make xconfig, you can see a new menu item in the Character Devices submenu. Select it.

Makefile can determine the source code file name by module name automatically. In this case, it expects a file named cs4334.c in drivers/char directory. Create it with any one of your favorite text editor. From now on, my text focus on the design of the IIS driver itself.

Before we start, we have some issues to make clear.
1. What type of this driver might be? What interface calls it should expose?
2. The use of ioctl method.
3. Does the driver need to face reentrant issue? How to make it reentrant?
4. Does the driver have user-configurable parameters? What's the configuration interface like?
5. When to power up the controller? By powering the device up it might be enable the input clock, or something else.

First of all, our driver module is chosen to be a char driver, because it doesn't require block read/write. Second, it acts an audio output device, so it's unnecessary to provide a read() method - what you expect to read from a loudspeaker, anyway? Further more, we do have to make it reentrant, we cannot afford writing two streams of different sampling rates to it at the same time, so there must be a semaphore to take this duty. At last, we let user applications configure driver parameters via the ioctl() call.
Now, we have decided to make it a char driver. What it needs to register to the kernel is a file_operations structure, as in

ret = register_chrdev(cs4334_major, "cs4334", &cs4334_fops);
Here cs4334_major is the major number the kernel identifies the driver module among all other driver types, for debug purpose, we choose 254. cs4334_fops is struct file_operations which contains a lot of function pointers (in linux/fs.h):

struct file_operations {
    struct module *owner;
    loff_t (*llseek) (struct file *, loff_t, int);
    ssize_t (*read) (struct file *, char *, size_t, loff_t *);
    ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
    int (*readdir) (struct file *, void *, filldir_t);
    unsigned int (*poll) (struct file *, struct poll_table_struct *);
    int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
    int (*mmap) (struct file *, struct vm_area_struct *);
    int (*open) (struct inode *, struct file *);
    int (*flush) (struct file *);
    int (*release) (struct inode *, struct file *);
    int (*fsync) (struct file *, struct dentry *, int datasync);
    int (*fasync) (int, struct file *, int);
    int (*lock) (struct file *, int, struct file_lock *);
    ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
    ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
    ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
    unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
#ifdef MAGIC_ROM_PTR
    int (*romptr) (struct file *, struct vm_area_struct *);
#endif /* MAGIC_ROM_PTR */
};
As mentioned earlier, we concentrate on open, release, ioctl and write operations,other fields, expect the owner field, are left NULL.
/* File operations structure */
struct file_operations cs4334_fops = {
    write: cs4334_write,
    ioctl: cs4334_ioctl,
    open: cs4334_open,
    release: cs4334_release,
};
While the owner field is initialized with SET_MODULE_OWNER macro at driver initialization time:
SET_MODULE_OWNER(&cs4334_ops);
Because the driver initialization method is called at system initlization time (versus that of loadable module), if we enable the master clock into the IIS controller, it would be consuming power while does nothing, so I decide to delay this step to write() time. There is little left to the initialization method, then.

static int __init cs4334_init(void)
{
    int ret = 0;
    SET_MODULE_OWNER(&cs4334_ops);
    /*
     * Register your major. This is the first
     * thing to do, in order to avoid releasing other module's fops in
     * cs4334_cleanup
     */
    ret = register_chrdev(cs4334_major, "cs4334", &cs4334_fops);
    if (ret  0) {
        printk(KERN_WARNING "cs4334: can't get major %d\n", cs4334_major);
        return ret;
    }
    if (0 == cs4334_major) {
        cs4334_major = ret;
    }
    cs4334_dev = kmalloc(sizeof(CS4334_DEV), GFP_KERNEL);
    if (NULL == cs4334_dev) {
        ret = -ENOMEM;
        goto fail;
    }
    sema_init(&cs4334_dev->sem, 1);
    return 0;
fail:
    cs4334_cleanup();
    return ret;
}
Now let's see what happens in cs4334_open:
int cs4334_open(struct inode *inode, struct file *filp)
{
    filp->private_data = cs4334_dev;
    MOD_INC_USE_COUNT; /* Before we maybe sleep */
    if (down_interruptible(&cs4334_dev->sem) != 0) {
        MOD_DEC_USE_COUNT;
        return -1;
    }
    cs4334_init_hw();
    up(&cs4334_dev->sem);
    return 0;
}
As we can see, its main job is initializing the IIS controller, without enabling the master clock and FIFO. We are not going to dive into the real init code, 'cause it's trivial.
The next step is configuring some device parameters that cannot be determined by the driver itself. Cases of them are sampling_rate and bits_per_sample, they are only obtained when a specific file is opened by user application, and must let the driver know before real audio data is processed. I decide to let user configure these parameters via ioctl call:

int cs4334_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
        unsigned long arg)
{
    ...
    switch (cmd) {
        case CS4334_IOCT_SAMPLING_RATE: /* Data sampling frenquency changed */
            Disable_master_clock_before_writing_to_register;
            switch (arg) {
                Write_to_register_according_to_arg;
            }
            break;
        case CS4334_IOCT_BITS_PER_SAMP:
            Disable_master_clock_before_writing_to_register;
            switch (arg) {
                Write_to_register_according_to_arg;
            }
            break;
        default:
            ret = -1;
            break;
    }
    return ret;
}
At last, when user really feeds data in, we check if the master clock is enabled already; if not, we will enable it at this time. The core code of feeding data to the IIS controller is then simple job.
You can find complete driver source at the end of this article, along with which is an test case called playwave.c.
Before I end this short note, I'd like to show you how to access this driver module in user space. In vendors/Samsung/44B0/Makefile, the DEVICES section, add a line like
iis,c,254,0
Make romfs will then generate a node under /dev directory. User application access the driver by a open() call:
int dev_fd;
dev_fd = open("/dev/iis", O_WRONLY);
2010-02-03 Add:
    I might have added an open count to prevent multiple opens on a single device, or there is no way to prevent this situation.

文件:
uclinux_2.4.x_iis_driver.rar
大小:
4KB
下載:
下載


本文來自ChinaUnix博客,如果查看原文請點:http://blog.chinaunix.net/u/17532/showart_2170076.html
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP