注册中断:对每个pin进行循环遍历
for (pin_num = 0; pin_num < min_t(int, ZYNQ_GPIO_NR_GPIOS, (int)chip->ngpio); pin_num++)
gpio_irq = irq_find_mapping(irq_domain, pin_num);
将GPIO号映射为Linux系统中断号。
在Linux中断系统中,一个irq_domain表示一个中断控制器,其内中断由0开始编号(尚存在疑问)
unsigned int irq_find_mapping(struct irq_domain *domain, irq_hw_number_t hwirq)
将一个中断控制器上的某个硬件中断映射为某个Linux系统中断。
/**
* struct irq_domain - Hardware interrupt number translation object
* @link: Element in global irq_domain list.
* @name: Name of interrupt domain
* @ops: pointer to irq_domain methods
* @host_data: private data pointer for use by owner. Not touched by irq_domain
* core code.
*
* Optional elements
* @of_node: Pointer to device tree nodes associated with the irq_domain. Used
* when decoding device tree interrupt specifiers.
* @gc: Pointer to a list of generic chips. There is a helper function for
* setting up one or more generic chips for interrupt controllers
* drivers using the generic chip library which uses this pointer.
*
* Revmap data, used internally by irq_domain
* @revmap_direct_max_irq: The largest hwirq that can be set for controllers that
* support direct mapping
* @revmap_size: Size of the linear map table @linear_revmap[]
* @revmap_tree: Radix map tree for hwirqs that don't fit in the linear map
* @linear_revmap: Linear table of hwirq->virq reverse mappings
*/
struct irq_domain {
struct list_head link;
const char *name;
const struct irq_domain_ops *ops;
void *host_data;
/* Optional data */
struct device_node *of_node;
struct irq_domain_chip_generic *gc;
/* reverse map data. The linear map gets appended to the irq_domain */
irq_hw_number_t hwirq_max;
unsigned int revmap_direct_max_irq;
unsigned int revmap_size;
struct radix_tree_root revmap_tree;
unsigned int linear_revmap[];
};
revmap_direct_max_irq: 小于该值的中断,Linux中断号和硬件中断号相同,直接返回。
revmap_size: 线性反向映射(似乎要求域内IRQ从零开始,有点矛盾),小于该值的hwirq直接利用linear_revmap做查找。否则用radix tree来查找映射。
irq_set_chip_and_handler(gpio_irq, &zynq_gpio_irqchip, handle_simple_irq);
调用irq_get_desc_lock(irq, &flags, 0);,获取irq对应的irq_desc。并设定irq_desc的chip:desc->irq_data.chip = chip;
调用irq_reserve_irq(irq);,将allocated_irqs中断位图中相应的中断标识为已占用。
调用__irq_set_handler,将irq_desc中的handle_irq设定:desc->handle_irq = handle;
irq_set_chip_data(gpio_irq, (void *)gpio);
这个比较简单,将要用私有的变量关联到irq,desc->irq_data.chip_data = data;
set_irq_flags(gpio_irq, IRQF_VALID);
公司新来一个小伙,设计类的时候喜欢这么搞,例如要实现一个串口通讯类,他会把基类做的很复杂,然后靠重载某些函数来实现不同的协议,虽然我一直觉得很别扭,但是也没有找出合适的理由来说服他。
今天下午偶然讨论起来,我突然想起一个类比,我举了一个猫和狗的类比。例如说我们要实现一个猫类,一个狗类,小伙的方法是先实现一个狗,然后让猫继承自狗,然后把所有猫和狗不同的行为进行重载,实现出一个猫来。而一般做法是,先实现一个动物,然后实现猫和狗,总共需要3个类。
为什么小伙这种方法有问题呢,是因为你如果让猫继承自狗,这样实现狗的类时候,就会带很重的狗的味道,你把狗改成猫,虽然看起来像猫了,但是一般你还是闻得出来一些狗的味道。更坏的情况是,如果某一天,因为某种需求,狗添加了一些的特征,而猫没有去重载,就会让猫里面出现狗的特征。而实现三个类这种设计,这猫里面最多会没有这个新特征,而不会出现狗的特征。而且,实现动物的时候,也不会考虑狗的一些特质,这样,猫里面也就不会有狗的味道。这是很重要的。
PowerPC U-Boot程序的Nand启动spl处理很有点意思,由于Nand只有4k可靠,所以u-boot的NAND启动由3部分构成:SPL1,SPL2和u-boot本体。
在SPL1结束的位置,代码大概如下:
#ifdef CONFIG_NAND_SPL_S1
mflr r8
li r3,0x1000
add r8,r8,r3 /* Shift address by 0x1000 */
mtlr r8
blr
#else
/*
* First initialize SDRAM. It has to be available *before* calling
* nand_boot().
*/
.........
#endif
这个代码很有意思,这个代码的导致SPL1读取SPL2代码之后,直接跳到#else后面的代码执行,虽然SPL2和SPL1代码在这之前是一样的,但实际在SPL2中不执行。在明白之前,还一直疑惑,寄存器、TLB之类的重复做一遍,不会有问题吗。呵呵。
很遗憾,这个总结还是姗姗来迟了,虽然原本计划是面试完那几天就立刻做的。
总体来说,这次的面试表现得也不好(还是对面试当前公司的时候表现最满意)。总结原因的话,仍然是准备不足。知道去面试的是老本行——电力设备企业,由于一直对自己技术方面有信心,所以也有点大意。面试主要点为:
总体来说,虽然结果尚可,但应该由于面试感觉不好,有要得不多的原因,总体来说,不成功。
n年前,选择了一款密码箱软件,当时选择了PwdBox。进来越来越发现这个密码箱不好用,例如多平台等。要命的是它还没有导出功能。看着里面的好几百条记录,手动拷贝显然不靠谱。得,写个专门程序吧。
导出程序思路上不复杂,给程序发消息进行遍历,得内容呗。用Spy++看了下,Delphi程序,基本构成上有一个TTreeView,一个ListView,还有若干个类Edit。程序也比较简单,得到TTreeView和TListView以及若干Edt的HWND,对TTreeView和TListView进行遍历,然后依次获取Edit的内容。但其中也有一些要注意的:
对TTreeView和TListView的操作要注意跨进程问题,所以调TreeView_xxx类和ListView_xxx类函数,要在目标程序的进程空间内分配内存,再进行进程间数据交换,基本手段为VirtualAllocEx,WriteProcessMemory和ReadProcessMemory。
获取文本使用WM_GETTEXT不需要使用目标进程的内存空间,用本进程的即可,操作系统会处理跨进程问题。
注意以上两个问题,遍历就不是什么难事了。不过,这也花费了我一天的时间。
NFS需要的相关服务为portmap(centos下为rpcbind), quota。注意quota要安装。