2.1.2 是否通用
有些單片機(jī)廠家也給客戶提供了大量的驅(qū)動(dòng)程序,比如USB HOST驅(qū)動(dòng)程序,這可以讓客戶很容易就可以在它的上面編寫(xiě)程序讀寫(xiě)U盤(pán)。但是客戶寫(xiě)的這些程序,只能在這種芯片、這個(gè)驅(qū)動(dòng)程序上使用;更換另一種芯片后,即使芯片公司也提供了驅(qū)動(dòng)程序,但是接口絕對(duì)不一樣,客戶又得重新編寫(xiě)應(yīng)用程序。
基于操作系統(tǒng)的驅(qū)動(dòng)程序要遵循統(tǒng)一的接口,比如對(duì)于不同的芯片的USB HOST驅(qū)動(dòng),它們都要向上提供一個(gè)相同的數(shù)據(jù)結(jié)構(gòu),在里面實(shí)現(xiàn)了各自的USB操作。
下面是S3C2410/S3C2440的USB驅(qū)動(dòng)向上層提供的數(shù)據(jù)結(jié)構(gòu):
static const struct hc_driver ohci_s3c2410_hc_driver = {
.deion = hcd_name,
.product_desc = "S3C24XX OHCI",
.hcd_priv_size = sizeof(struct ohci_hcd),
.irq = ohci_irq,
.flags = HCD_USB11 | HCD_MEMORY,
.start = ohci_s3c2410_start,
.stop = ohci_stop,
.shutdown = ohci_shutdown,
.urb_enqueue = ohci_urb_enqueue,
.urb_dequeue = ohci_urb_dequeue,
.endpoint_disable = ohci_endpoint_disable,
.get__number = ohci_get_,
.hub_status_data = ohci_s3c2410_hub_status_data,
.hub_control = ohci_s3c2410_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
#endif
.start_port_reset = ohci_start_port_reset,
};
下面是ATMEL公司的ARM芯片的USB驅(qū)動(dòng)向上層提供的數(shù)據(jù)結(jié)構(gòu):
static const struct hc_driver ohci_at91_hc_driver = {
.deion = hcd_name,
.product_desc = "AT91 OHCI",
.hcd_priv_size = sizeof(struct ohci_hcd),
.irq = ohci_irq,
.flags = HCD_USB11 | HCD_MEMORY,
.start = ohci_at91_start,
.stop = ohci_stop,
.shutdown = ohci_shutdown,
.urb_enqueue = ohci_urb_enqueue,
.urb_dequeue = ohci_urb_dequeue,
.endpoint_disable = ohci_endpoint_disable,
.get__number = ohci_get_,
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
#endif
.start_port_reset = ohci_start_port_reset,
};
基于通用性,即使是你自己寫(xiě)的Linux驅(qū)動(dòng),簡(jiǎn)單到只是點(diǎn)亮一個(gè)LED,基于“通用性”,這個(gè)驅(qū)動(dòng)也要向上提供統(tǒng)一的接口。下面是單片機(jī)LED驅(qū)動(dòng)程序和Linux下的LED驅(qū)動(dòng)程序的部分代碼。
單片機(jī)LED驅(qū)動(dòng)程序:
void led_init(void)
{
GPBCON = GPB5_out; // 將LED對(duì)應(yīng)的GPB5引腳設(shè)為輸出
}
void led_on(void)
{
GPBDAT &= ~(1<<5);
}
void led_off(void)
{
GPBDAT |= (1<<5);
}
Linux的LED驅(qū)動(dòng)程序:
#define DEVICE_NAME "leds"
#define LED_MAJOR 231
#define IOCTL_LED_ON 0
#define IOCTL_LED_OFF 1
static unsigned long led_table [] = {
S3C2410_GPB5,
S3C2410_GPB6,
S3C2410_GPB7,
S3C2410_GPB8,
};
static unsigned int led_cfg_table [] = {
S3C2410_GPB5_OUTP,
S3C2410_GPB6_OUTP,
S3C2410_GPB7_OUTP,
S3C2410_GPB8_OUTP,
};
static int s3c24xx_leds_open(struct inode *inode, struct file *file)
{
int i;
for (i = 0; i < 4; i++) {
// 設(shè)置GPIO引腳的功能:本驅(qū)動(dòng)中LED所涉及的GPIO引腳設(shè)為輸出功能
s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
}
return 0;
}
static int s3c24xx_leds_ioctl(
struct inode *inode,
struct file *file,
unsigned int cmd,
unsigned long arg)
{
if (arg > 4) {
return -EINVAL;
}
switch(cmd) {
case IOCTL_LED_ON:
// 設(shè)置指定引腳的輸出電平為0
s3c2410_gpio_setpin(led_table[arg], 0);
return 0;
case IOCTL_LED_OFF:
// 設(shè)置指定引腳的輸出電平為1
s3c2410_gpio_setpin(led_table[arg], 1);
return 0;
default:
return -EINVAL;
}
}
static struct file_operations s3c24xx_leds_fops = {
.owner = THIS_MODULE,
.open = s3c24xx_leds_open,
.ioctl = s3c24xx_leds_ioctl,
};
static int __init s3c24xx_leds_init(void)
{
int ret;
ret = register_chrdev(LED_MAJOR, DEVICE_NAME, &s3c24xx_leds_fops);
if (ret < 0) {
printk(DEVICE_NAME " cant register major number");
return ret;
}
printk(DEVICE_NAME " initialized");
return 0;
}
static void __exit s3c24xx_leds_exit(void)
{
unregister_chrdev(LED_MAJOR, DEVICE_NAME);
}
module_init(s3c24xx_leds_init);
module_exit(s3c24xx_leds_exit);
2.2. 應(yīng)用程序開(kāi)發(fā)的區(qū)別
2.2.1 對(duì)于不帶操作系統(tǒng)的應(yīng)用編程,應(yīng)用程序和驅(qū)動(dòng)程序之間的間隔并不明顯。
舉個(gè)例子,要在LCD上顯示字母“a”,在單片機(jī)上的做法是:
① 事先在Flash上保存“a”的點(diǎn)陣數(shù)據(jù),假設(shè)它的象素大小是8x8,那么這個(gè)點(diǎn)陣大小就是8x8=64 bits,即8字節(jié)
② 應(yīng)用程序讀取這64bit數(shù)據(jù),逐個(gè)象素地在LCD上描點(diǎn)
相對(duì)的,基于操作系統(tǒng)的應(yīng)用編程,就不需要懂得硬件知識(shí),執(zhí)行一個(gè)簡(jiǎn)單的“echo a > /dev/tty1”就可以在LCD上顯示“a”了。
2.2.2 不帶操作系統(tǒng)的應(yīng)用程序,可借用的軟件資源很少;
帶操作系統(tǒng)的應(yīng)用程序,網(wǎng)上各種開(kāi)源的軟件很多。
比如要做一個(gè)播放器,在不帶操作系統(tǒng)上實(shí)現(xiàn)會(huì)非常困難;如果是在Linux下,有現(xiàn)成的。
2.2.3 不帶操作系統(tǒng)的應(yīng)用程序,各個(gè)任務(wù)是串行執(zhí)行的;
帶操作系統(tǒng)的應(yīng)用程序,各個(gè)任務(wù)是并行執(zhí)行的。
2.2.4 不帶操作系統(tǒng)的應(yīng)用程序,一旦發(fā)生程序錯(cuò)誤,整個(gè)系統(tǒng)將崩潰
帶操作系統(tǒng)的應(yīng)用程序,即使發(fā)生了程序錯(cuò)誤,操作系統(tǒng)本身并不會(huì)崩潰
評(píng)論