Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1261816
  • 博文数量: 548
  • 博客积分: 7597
  • 博客等级: 少将
  • 技术积分: 4224
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-15 13:21
个人简介

嵌入式软件工程师&&太极拳

文章分类

全部博文(548)

文章存档

2014年(10)

2013年(76)

2012年(175)

2011年(287)

分类: LINUX

2011-02-20 20:23:58

Kernel_API:
申请:
	region:
		struct: 	
		init:		 register_chrdev_region
				alloc_chrdev_region
		exit:	unregister_chrdev_region
		use:		
		note:	主要干的事就是在/proc里可以看到		

注册:
	注册干的事就是根据设备号,绑定file_operations
	old: register_chrdev:
		struct:	struct file_operations, struct file,  struct node
		init:		register_chrdev
		exit:	unregister_chrdev
		use:		
		note: 	2.6内核以前用的,现在不推荐用	
	
	new: register_chrdev:
		struct:	 struct cdev
		init:		cdev_init
				cdev_add
		exit:	cdev_del	
		use:		
		note:	2.6内核新出的,cdev_add要放到最后,因为cdev_add将程序投入到内核,立即可以被使用,所以没有初始化好就投入用
				file_operations  必须单独初始化

实现系统调用:
	open, release
		 open和release可以不实现,因为内核已经初始化好了,系统调用仅仅是应用程序访问内核的途径
		使用open,release的情况有要使用private_data私有变量,还有request_irq,因为中断号是珍贵资源,所以要用的时候才注册
	read, write   
		copy_to_user/copy_from_user  带参数检查的拷贝函数(地址检查): asm/uaccess.h
		llseek + pos 在用seek的时候注册要加当前位置 		
	
	error: linux/errno.h
		错误号
		容错处理goto用法
		note:  配对,泄露问题

	private_data:
		container_of
		结构体继承
	
	llseek:
		note: read write的时候注册要加当前位置 
	
	ioctl:
		ioctl-number  
		传参(unsigned long ->结构体指针)
		switch  要对应default
		ioctl_cmd.h (在两个地方存在,在用户和内核两份)

	阻塞I/O:
		struct:	wait_queue_head_t 
		init:		init_waitqueue_head
		exit:	
		use:		read: wait_event_interruptible
				write: wake_up
		note:	睡眠机制	
	
	轮询:  linux/poll.h   (select / poll)
		struct:	struct poll_table_struct
		init:		poll(file_operations)
		exit:
		use:		poll_wait
		note:	POLLIN/POLLOUT (read/write)  相对给FD_ISSET看的
				select 在应用程序: FD_SET/FD_ISSET  一定要放在监视循环里 

	异步通知:
		struct:	struct fasync_struct
		fasync:	fasync_helper  将文件描述符放到内核信号响应队列
		exit:	调用自己的fasync函数: test_fasync(-1, filp, 0);
		use:		kill_fasync
		note:	signal,相当于软件中的中断,在应用时用sigaction
					应用: sigaction, 干的事注册,设置属性和标志

	并发和竞态(互斥):		
单核:
	内核编程注意事项:
		少用浮点
		stack 4K左右 栈小
		地址对齐,地址的非法性
		要遵守GNUC C标准
		并发竞态
			why:
				调用你的人,有可能是并发的
				kernel中断会产生并发
				smp,多核

		进程与进程之间:
			preempt
		进程和中断之间
			local_irq
		中断和中断之间   可重入性好,会保护现场
			local_irq_save;
			local_irq_restore;

多核:
			CPU自旋:	
				_raw_write_lock
		
		spin_lock:  自旋锁
			struct:	 struct spinlock_t		
			init:		spin_lock_init 		
			exit:
			use:		spin_lock/spin_unlock
			note:	不能睡眠(引起睡眠函数:copy_from_user sleep, kmalloc)
		
		semaphore:
			struct :	struct semaphore
			init:		init_MUTEX
			exit:
			use:		down/up/down_interruptible
			note:	if (down_ifterruptible(struct semaphore *sem)) return -ERESTARTSYS;   down_interruptible要加判断,可被信号打断



	分配内存: linux/slab.h
		kmalloc   一定判断返回值
			flags   GPF_ATOMIC  不会睡眠, GPF_KERNEL 常用
		
	I/O访问: asm/io.h
		mem_region:
			struct:	struct resource
			init:		request_mem_region
			exit:	release_resource
			use:
			note: 
		动态映射物理地址:	ioremap / iounmap	
		静态映射物理地址:  arch/arm/mach-s3c2410/mach-bit2440.c  编译内核生效
	
		操作I/O:
			ioread8/iowrite8   v为值,p为地址	


	中断: asm/irq.h   linux/interrupt.h
		include/asm-arm/arch-s3c2410/irqs.h          irqno  中断号,是要加16
		struct:	struct irqdesc

		open:	set_irq_type
				request_irq

		release:	free_irq
		note:	SA_SHIRQ为共享中断可以执行多个函数,SA_INTERRUPT, 一定要判断request_irq的返回值	

	描述中断机制:
	1.中断是低电频有效,硬件中断发生后经过中断控制器->CPU的i位或f位,init/main.c的start_kernel第一个函数初始化vector(trap_init), 再跳到vector找到irq异常切换成irq工作模式->asm_do_irq函数,调用了一个函数指针,这个函数指针是struct irqdesc的handler成员
	2. start_kernel的init_IRQ,最后会找到和平台相关的mach_bit2440.c里的is3c24xx_init_irq函数->do_edge_IRQ函数的do_irq循环struct irqdesc 的action成员(是一个链表指针)链表里的handler函数指针
	3. request_irq注册函数->setup_irq函数,而这个函数则就是把我们的中断处理函数指针赋给了action的handler

中断处理函数使用:
		Note: 中断处理函数中的注意事项
				1. 代码的执行时间, 在irq工作模式上时间尽量短
				2. return IRQ_HANDLED;
				3. 不能睡眠
					1. not use semphone  should be use spin_lock
					2. not use kmalloc(GFP_KERNEL) should be use kmalloc(GFP_ATOMIC)
					3. 不能跨系统层函数  copy_xxx_user
		Use:
				1. 顶半部通知, 启动底半部处理
				2. complete, wake_up, up, kill
		底半部:
			tasklet:
				struct:	struct tasklet_struct
				init:		tasklet_init
				exit:	
				use:		tasklet_schedule
				note:	不可以睡眠,软中断上下文, 效率高
		
			struct_work:  
				struct:	struct work_struct
				init:		INIT_WORK    是宏
				exit:	
				use:		schedule_work
				note:	可以睡眠  进程上下文

			timer: 也可以称为底半部,也是多进程
				struct :   struct timer_list    (文档,此知识点的主角对象,结构体)			
				init:		init_timer(struct timer_list *);    (初始化函数)
						add_timer(struct timer_list *);	(启动)
				exit: 	del_timer(struct timer_list *);     (退出函数)
				use:	  	mod_timer(struct timer_list *, unsigned long);   (用法)
				note: 	在init_timer和add_timer之间要先给struct timer_list成员赋值。 (注意事项) 时间是1秒=jiffies + 1*HZ 



linux设备模型组件:
	在/sys目录下
	struct kobject  属于所有的基类,可以把所有的对象连接起来, 一个目录
	struct kset    同一类kobject的容器,  可以用于class,归类
	struct subsystem     子系统		顶目录
		struct attribute    属性就是文件   

	总线驱动:
		总线:	
			struct:	struct bus_type
			init:		bus_register
			exit:	bus_unregister
			use:
			note:
		设备:
			struct:	struct device 
			init:		device_register
			exit:	device_unregister
			use:
			note:	
		驱动:
			struct:	struct device_driver
			init:		driver_register
			exit:	driver_unregister
			use:
			note:

	一个驱动可以对多个设备,一个设备绝对只能对一个驱动

	回调函数:在什么地方用:
		在分层结构里常用,可移植性好
		共公层
		分层驱动
	
	热插拨(hotplug):
		原理就是设备插入时会产生一个中断,然后中断处理函数来注册设备(用工作队列)		

	platform:   平台类总线设备,bus一般都是写好的
		struct :	struct platform_device
		init:		platform_device_register
		exit:	platform_device_unregister
		use:
		note:

	静态映射平台类设备资源: 即编译进内核
		1. arch/arm/mach-s3c2410/mach-bit2440.c
			struct platform_device *bit2440_devices[] __initdata 里加一句自己的设备资源
		2. arch/arm/mach-s3c2410/devs.c
			加一个 struct platform_device s3c_*_resource[] 这个结构体
			再加一个  struct platform_device s3c_device*    结构体,模仿上面的结构体写
			EXPORT_SYMBOL   再打出
		3.  arch/arm/mach-s3c2410/devs.h
			extern struct platform_device s3c*      导出
		
		.Use:   struct platform_device *pdev = container_of(dev, struct platform_device, dev); 
	

	class: 类      字符设备驱动 + class(udev)
		struct: 	struct class
		init:		class_create			给系统调试用,在sys/class创建目录
				class_device_create	创建相对于sys/class目录里设备的设备文件
		exit:	class_device_destroy
				class_destroy
		use:       用于udev,自动建立/dev/xxx设备文件
		note:

	misc:		      做的事就是cdev + class + major(主设备号为10)
 		struct:	struct miscdevice
		init:		misc_register
		exit:	misc_deregister	
		use:
		note:	初始化struct miscdevice, file_operations要的是指针


wdt:平台类设备, 字符设备, misc	


触摸屏:
	电阻式    工业用的最多,用笔点的
	电容式	用手摸的
	红外式

电阻式触摸屏:
		主要靠电阻分压器,根据电压不同算出按了哪点,再通过A/D转换成数字信号
		INT_ADC  为A/D转换完后产生一个中断
		INT_TC	   按了和抬起都会产生一个中断	

	四种模式:
		为A/D转换模式,就是除了A/D转换,没有其它功能
		分离X/Y模式   只给一个值  
		Auto 模式     会给两个值
		等待模式	  等待中断

ADCCON:
	15	    转换完成标志,状态寄存器,可以看是否A/D转换完成	
	14	    开关A/D要不要分频
	13:6	    A/D转换频率值,最大为PCLK / 5  	
	5:3	    A/D的,不能设置,跟触模屏无关	
	2	    ADC的事,使ADC能挂起
	1	    一读就开始转换或转换完给中断
	0	    如果上面的没有设置就要打开		

ADCTSC:   
	8	    设置按下或弹起才产生中断
	7:0  	   0xd3  为等待模式, 这个设置决定用哪种模式
	2	为自动转换,如果为1上面5个就没用了
	1:0	为等待模式,设置模式

ADCDLY: 延时用的,没用

ADCDAT0:
ADCDAT1:
	15:12  为只读的,只为取值用
	9:0	    取x和y坐标值,ADCDAT0取X, ADCDAT1取Y

ADCUPDN: 看是按下或弹起发生了中断
	中断完成后要清零

request_irq注册失败
	中断号被用了,记得要加上16看
		然后在cat /proc/interrupts 看哪个在用,到内核里全局搜索,然后不要编译到内核

没有钟,不可能会出来的

内核的clock:
	arch/arm/mach-s3c2410/mach-bit2440.c 找到MACHINE_START这个宏里的map_io = bit2440_map_io --> s3c24xx_init_clocks(12000000)-->(cpu->init_clocks)(xtal)
找到cpu这个结构体,找到在哪给init_clocks赋值
	s3c2410_init_clocks-->s3c24xx_setup_clocks-->
	s3c24xx_clk_enable(S#C2410_CLKCON_ADC, 0); 找到这,初始化内核是关了,后面为1开,暴力开钟
	
	注意 clk
		clk_get
		clk_use
		clk_enable/disable

	input:
		struct:	
		init:		input_register_device
		exit:	input_unregister_device
		use:		input_report_key
				input_sync   	按键不需要用
		note:	核心EVENT事件
			EV_KEY	按键
			EV_ABS	触摸屏
			EV_REL   鼠标



1.HW,datasheet En(硬件和文档英文)
2.熟读内核源代码
3.调试和优化、容错
	调试:
		第一怀疑HW的问题,要非常熟悉硬件和datasheet
		第二怀疑内核和程序的融合度
	优化:
		不是代码精简,而是时间和空间的优化,而且空间对于现在不用考虑
		驱动优化80%优化硬件

字符设备和块设备有什么?
	字符设备是以字节流访问,没有缓冲概念。


LCD:
	LCD设备,fb两部分
	dma_alloc_writecombine  只会关掉MMU页表的C位,没有关B位
	dma_alloc_coherent    会关掉MMU页表的C和B位
	返回一个虚拟地址,在显示的时候用,给fb添数的时候,和一个实际物理地址,在设置寄存器用的


1. kernel src 组织结构

2.内核的配置
	make menuconfig(读.config)
		先到arch/arm/configs/s3c24xx_defconfg 拷贝成.config
			然后再看板子的不同,再到menuconfig里配置
			arch/arm/mach-s3c2410/mach-bit2440.c  移植最重要的就是这个,跟开发板相关,跟平台,资源(地址和中断)相关
			drivers/		查看板子相关的外设驱动在内核里有没有
	Kconfig + Makefile

3.内核编程入口
	module_init
		模块不等于ko文件,只是内核提供的一个编程入口
	MODULE_LICENCE("GPL");在公司要注意这个

4.驱动函数,完成工具
	字符设备
		一切以字节流访问
		提供系统调用的实现 ,应用程序调到内核




拷贝:
	ZhangArm/Down_Class

阅读(753) | 评论(0) | 转发(0) |
0

上一篇:2010_3_15.kernel

下一篇:bootloader

给主人留下些什么吧!~~