Smart210学习记录-----中断

1. OVERVIEW OF VECTORED INTERRUPT CONTROLLER(概述向量中断控制器)

  主要有4个VIC,4个TZIC还有一个很特殊的ARM PrimeCell PL192。主要的VIC和TZIC可以支持93个中断源。其中TZIC是为TrustZone技术所准备的,ARM TrustZone® 技术是系统范围的安全方法,针对高性能计算平台上的大量应用,包括安全支付、数字版权管理 (DRM)、企业服务和基于 Web 的服务(援引官方的介绍)。TZIC提供了安全控制的nFIQ中断并且使该这类中断从传统的不安全中断VIC中屏蔽掉,从而达到应用在数据传输时的安全性和保密性。

2,KEY FEATURES OF VECTORED INTERRUPT CONTROLLER

• Supports 93 vectored IRQ interrupts
• Fixed hardware interrupts priority levels (固定硬件中断优先级)
• Programmable interrupt priority levels (可编程中断优先级)
• Supports Hardware interrupt priority level masking (支持硬件中断优先级的屏蔽)
• Programmable interrupt priority level masking
• Generates IRQ and FIQ (产生IRQ和FIQ)
• Generates Software interrupt
• Test registers
• Raw interrupt status (原中断状态,就是设置使能,屏蔽寄存器之前的各中断状态)
• Interrupt request status
• Supports Privileged mode for restricted access(支持限制访问特权模式)

3.  When user clears interrupt pending, user must write 0 to all the VICADDRESS registers (VIC0ADDRESS,
VIC1ADDRESS, VIC2ADDRESS, and VIC3ADDRESS).

4.各中断寄存器请参考s5pv320用户手册。

中断参考程序:

.global _start
.global IRQ_handle

_start:
	// 关闭看门狗
	ldr	r0, =0xE2700000
	mov	r1, #0
	str	r1, [r0]

	// 设置栈,以便调用c函数
	ldr	sp, =0x40000000		

	// 开中断
	mov r0, #0x53
	msr CPSR_cxsf, r0	

	// 汇编初始化时钟
	bl clock_init	

	// 调用main函数
	bl main	

IRQ_handle:
	// 设置中断模式的栈
	ldr sp, =0xD0037F80
	// 保存现场
	sub lr, lr, #4
	stmfd sp!, {r0-r12, lr}
	// 跳转到中断处理函数
	bl	irq_handler
	// 恢复现场
	ldmfd sp!, {r0-r12, pc}^

  

首先,关闭看门狗,设置栈,开中断,设置时钟,,,当一个中断源(不是一个中断)发生时执行中断服务程序IRQ_handle,设置中断模式的栈, 保存现场,跳转到中断处理函(irq_handler),中断处理函数首先判断是哪个中断组发生中断,然后进入相应的中断处理子程序(irq_xxx),在事先我们要设置中断处理子程序irq_xxx(如irq_key)在地址VICxVECTADDRx中,,,当有中断发生时,硬件上会将当前中断的中断处理子程序从寄存器 VICxVECTADDxR 自动拷贝到寄存器VICADDR 中,所以我们在 irq_handler()函数里会调用保存在寄存器 VICDDR 里的中断处理函数即可。

( 一个中断组有32个中断源,为什么我们可以直接运行中断组的VICxINTADDR指定的函数而无需知道是具体哪个中断源触发了中断呢?这是由于中断组内的中断源在触发中断后硬件会自动把对应中断源的处理函数入口地址赋给所属组的VICADDR,这样我们就能省去检索中断源再跳转到对应中断函数入口的时间了,当然,前提是我们要把【按键中断】的服务程序入口地址赋给某个对应的寄存器(假设是VIC0INTADDR12,所属组是VIC0组,所对应入口是VIC0INTADDR))。

这一段真的有点难懂,需要花点时间

#include "stdio.h"
#include "int.h"

#define 	GPH2CON 	(*(volatile unsigned long *) 0xE0200C40)
#define 	GPH2DAT		(*(volatile unsigned long *) 0xE0200C44)

#define 	GPH2_0_EINT16 	(0xf<<(0*4))
#define 	GPH2_1_EINT17 	(0xf<<(1*4))
#define 	GPH2_2_EINT18 	(0xf<<(2*4))
#define 	GPH2_3_EINT19 	(0xf<<(3*4))

#define		EXT_INT_0_CON  			( *((volatile unsigned long *)0xE0200E00) )
#define		EXT_INT_1_CON  			( *((volatile unsigned long *)0xE0200E04) )
#define		EXT_INT_2_CON  			( *((volatile unsigned long *)0xE0200E08) )
#define		EXT_INT_3_CON  			( *((volatile unsigned long *)0xE0200E0C) )

#define		EXT_INT_0_MASK   		( *((volatile unsigned long *)0xE0200F00) )
#define		EXT_INT_1_MASK   		( *((volatile unsigned long *)0xE0200F04) )
#define		EXT_INT_2_MASK   		( *((volatile unsigned long *)0xE0200F08) )
#define		EXT_INT_3_MASK   		( *((volatile unsigned long *)0xE0200F0C) )

#define		EXT_INT_0_PEND   		( *((volatile unsigned long *)0xE0200F40) )
#define		EXT_INT_1_PEND   		( *((volatile unsigned long *)0xE0200F44) )
#define		EXT_INT_2_PEND   		( *((volatile unsigned long *)0xE0200F48) )
#define		EXT_INT_3_PEND   		( *((volatile unsigned long *)0xE0200F4C) )

void uart_init();

// 延时函数
void delay(unsigned long count)
{
	volatile unsigned long i = count;
	while (i--);
}

void isr_key(void)
{
	printf("we get company:EINT16_31\r\n");

	// clear VIC0ADDR
	intc_clearvectaddr();
	// clear pending bit
	EXT_INT_2_PEND |= 1<<0;
}

int main(void)
{
	int c = 0;

	// 初始化串口
	uart_init();

	// 中断相关初始化
	system_initexception();						

	printf("**************Int test *************** \r\n");

	// 外部中断相关的设置
	// 1111 = EXT_INT[16]
	GPH2CON |= 0xF;
	// 010 = Falling edge triggered
	EXT_INT_2_CON |= 1<<1;
	// unmasked
	EXT_INT_2_MASK &= ~(1<<0);

	// 设置中断EINT16_31的处理函数
	intc_setvectaddr(NUM_EINT16_31, isr_key);
	// 使能中断EINT16_31
	intc_enable(NUM_EINT16_31);

	while (1)
	{
		printf("%d\r\n",c++);
		delay(0x100000);
	}
}

 

#include "int.h"
#include "stdio.h"

//// Interrupt
#define VIC0_BASE					(0xF2000000)
#define VIC1_BASE					(0xF2100000)
#define VIC2_BASE					(0xF2200000)
#define VIC3_BASE					(0xF2300000)

// VIC0
#define		VIC0IRQSTATUS			( *((volatile unsigned long *)(VIC0_BASE + 0x00)) )
#define		VIC0FIQSTATUS			( *((volatile unsigned long *)(VIC0_BASE + 0x04)) )
#define		VIC0RAWINTR				( *((volatile unsigned long *)(VIC0_BASE + 0x08)) )
#define		VIC0INTSELECT			( *((volatile unsigned long *)(VIC0_BASE + 0x0c)) )
#define		VIC0INTENABLE			( *((volatile unsigned long *)(VIC0_BASE + 0x10)) )
#define		VIC0INTENCLEAR			( *((volatile unsigned long *)(VIC0_BASE + 0x14)) )
#define		VIC0SOFTINT				( *((volatile unsigned long *)(VIC0_BASE + 0x18)) )
#define		VIC0SOFTINTCLEAR		( *((volatile unsigned long *)(VIC0_BASE + 0x1c)) )
#define		VIC0PROTECTION			( *((volatile unsigned long *)(VIC0_BASE + 0x20)) )
#define		VIC0SWPRIORITYMASK		( *((volatile unsigned long *)(VIC0_BASE + 0x24)) )
#define		VIC0PRIORITYDAISY		( *((volatile unsigned long *)(VIC0_BASE + 0x28)) )
#define 	VIC0VECTADDR			(VIC0_BASE + 0x100)
#define 	VIC0VECPRIORITY			( *((volatile unsigned long *)(VIC0_BASE + 0x200)) )
#define 	VIC0ADDR				( *((volatile unsigned long *)(VIC0_BASE + 0xf00)) )
#define 	VIC0PERID0				( *((volatile unsigned long *)(VIC0_BASE + 0xfe0)) )
#define 	VIC0PERID1				( *((volatile unsigned long *)(VIC0_BASE + 0xfe4)) )
#define 	VIC0PERID2				( *((volatile unsigned long *)(VIC0_BASE + 0xfe8)) )
#define 	VIC0PERID3				( *((volatile unsigned long *)(VIC0_BASE + 0xfec)) )
#define 	VIC0PCELLID0			( *((volatile unsigned long *)(VIC0_BASE + 0xff0)) )
#define 	VIC0PCELLID1			( *((volatile unsigned long *)(VIC0_BASE + 0xff4)) )
#define 	VIC0PCELLID2			( *((volatile unsigned long *)(VIC0_BASE + 0xff8)) )
#define 	VIC0PCELLID3			( *((volatile unsigned long *)(VIC0_BASE + 0xffc)) )

// VIC1
#define		VIC1IRQSTATUS			( *((volatile unsigned long *)(VIC1_BASE + 0x00)) )
#define		VIC1FIQSTATUS			( *((volatile unsigned long *)(VIC1_BASE + 0x04)) )
#define		VIC1RAWINTR				( *((volatile unsigned long *)(VIC1_BASE + 0x08)) )
#define		VIC1INTSELECT			( *((volatile unsigned long *)(VIC1_BASE + 0x0c)) )
#define		VIC1INTENABLE			( *((volatile unsigned long *)(VIC1_BASE + 0x10)) )
#define		VIC1INTENCLEAR			( *((volatile unsigned long *)(VIC1_BASE + 0x14)) )
#define		VIC1SOFTINT				( *((volatile unsigned long *)(VIC1_BASE + 0x18)) )
#define		VIC1SOFTINTCLEAR		( *((volatile unsigned long *)(VIC1_BASE + 0x1c)) )
#define		VIC1PROTECTION			( *((volatile unsigned long *)(VIC1_BASE + 0x20)) )
#define		VIC1SWPRIORITYMASK		( *((volatile unsigned long *)(VIC1_BASE + 0x24)) )
#define		VIC1PRIORITYDAISY		( *((volatile unsigned long *)(VIC1_BASE + 0x28)) )
#define 	VIC1VECTADDR			(VIC1_BASE + 0x100)
#define 	VIC1VECPRIORITY			( *((volatile unsigned long *)(VIC1_BASE + 0x200)) )
#define 	VIC1ADDR				( *((volatile unsigned long *)(VIC1_BASE + 0xf00)) )
#define 	VIC1PERID0				( *((volatile unsigned long *)(VIC1_BASE + 0xfe0)) )
#define 	VIC1PERID1				( *((volatile unsigned long *)(VIC1_BASE + 0xfe4)) )
#define 	VIC1PERID2				( *((volatile unsigned long *)(VIC1_BASE + 0xfe8)) )
#define 	VIC1PERID3				( *((volatile unsigned long *)(VIC1_BASE + 0xfec)) )
#define 	VIC1PCELLID0				( *((volatile unsigned long *)(VIC1_BASE + 0xff0)) )
#define 	VIC1PCELLID1				( *((volatile unsigned long *)(VIC1_BASE + 0xff4)) )
#define 	VIC1PCELLID2				( *((volatile unsigned long *)(VIC1_BASE + 0xff8)) )
#define 	VIC1PCELLID3				( *((volatile unsigned long *)(VIC1_BASE + 0xffc)) )

// VIC2
#define		VIC2IRQSTATUS			( *((volatile unsigned long *)(VIC2_BASE + 0x00)) )
#define		VIC2FIQSTATUS			( *((volatile unsigned long *)(VIC2_BASE + 0x04)) )
#define		VIC2RAWINTR				( *((volatile unsigned long *)(VIC2_BASE + 0x08)) )
#define		VIC2INTSELECT			( *((volatile unsigned long *)(VIC2_BASE + 0x0c)) )
#define		VIC2INTENABLE			( *((volatile unsigned long *)(VIC2_BASE + 0x10)) )
#define		VIC2INTENCLEAR			( *((volatile unsigned long *)(VIC2_BASE + 0x14)) )
#define		VIC2SOFTINT				( *((volatile unsigned long *)(VIC2_BASE + 0x18)) )
#define		VIC2SOFTINTCLEAR		( *((volatile unsigned long *)(VIC2_BASE + 0x1c)) )
#define		VIC2PROTECTION			( *((volatile unsigned long *)(VIC2_BASE + 0x20)) )
#define		VIC2SWPRIORITYMASK		( *((volatile unsigned long *)(VIC2_BASE + 0x24)) )
#define		VIC2PRIORITYDAISY		( *((volatile unsigned long *)(VIC2_BASE + 0x28)) )
#define 		VIC2VECTADDR			(VIC2_BASE + 0x100)
#define 		VIC2VECPRIORITY			( *((volatile unsigned long *)(VIC2_BASE + 0x200)) )
#define 		VIC2ADDR				( *((volatile unsigned long *)(VIC2_BASE + 0xf00)) )
#define 		VIC2PERID0				( *((volatile unsigned long *)(VIC2_BASE + 0xfe0)) )
#define 		VIC2PERID1				( *((volatile unsigned long *)(VIC2_BASE + 0xfe4)) )
#define 		VIC2PERID2				( *((volatile unsigned long *)(VIC2_BASE + 0xfe8)) )
#define 		VIC2PERID3				( *((volatile unsigned long *)(VIC2_BASE + 0xfec)) )
#define 		VIC2PCELLID0				( *((volatile unsigned long *)(VIC2_BASE + 0xff0)) )
#define 		VIC2PCELLID1				( *((volatile unsigned long *)(VIC2_BASE + 0xff4)) )
#define 		VIC2PCELLID2				( *((volatile unsigned long *)(VIC2_BASE + 0xff8)) )
#define 		VIC2PCELLID3				( *((volatile unsigned long *)(VIC2_BASE + 0xffc)) )

// VIC3
#define		VIC3IRQSTATUS			( *((volatile unsigned long *)(VIC3_BASE + 0x00)) )
#define	 	VIC3FIQSTATUS			( *((volatile unsigned long *)(VIC3_BASE + 0x04)) )
#define	 	VIC3RAWINTR				( *((volatile unsigned long *)(VIC3_BASE + 0x08)) )
#define	 	VIC3INTSELECT			( *((volatile unsigned long *)(VIC3_BASE + 0x0c)) )
#define	 	VIC3INTENABLE			( *((volatile unsigned long *)(VIC3_BASE + 0x10)) )
#define	 	VIC3INTENCLEAR			( *((volatile unsigned long *)(VIC3_BASE + 0x14)) )
#define	 	VIC3SOFTINT				( *((volatile unsigned long *)(VIC3_BASE + 0x18)) )
#define	 	VIC3SOFTINTCLEAR		( *((volatile unsigned long *)(VIC3_BASE + 0x1c)) )
#define	 	VIC3PROTECTION			( *((volatile unsigned long *)(VIC3_BASE + 0x20)) )
#define	 	VIC3SWPRIORITYMASK		( *((volatile unsigned long *)(VIC3_BASE + 0x24)) )
#define	 	VIC3PRIORITYDAISY		( *((volatile unsigned long *)(VIC3_BASE + 0x28)) )
#define 		VIC3VECTADDR			(VIC3_BASE + 0x100)
#define 		VIC3VECPRIORITY			( *((volatile unsigned long *)(VIC3_BASE + 0x200)) )
#define 		VIC3ADDR				( *((volatile unsigned long *)(VIC3_BASE + 0xf00)) )
#define 		VIC3PERID0				( *((volatile unsigned long *)(VIC3_BASE + 0xfe0)) )
#define 		VIC3PERID1				( *((volatile unsigned long *)(VIC3_BASE + 0xfe4)) )
#define 		VIC3PERID2				( *((volatile unsigned long *)(VIC3_BASE + 0xfe8)) )
#define 		VIC3PERID3				( *((volatile unsigned long *)(VIC3_BASE + 0xfec)) )
#define 		VIC3PCELLID0				( *((volatile unsigned long *)(VIC3_BASE + 0xff0)) )
#define 		VIC3PCELLID1				( *((volatile unsigned long *)(VIC3_BASE + 0xff4)) )
#define 		VIC3PCELLID2				( *((volatile unsigned long *)(VIC3_BASE + 0xff8)) )
#define 		VIC3PCELLID3				( *((volatile unsigned long *)(VIC3_BASE + 0xffc)) )

#define		_Exception_Vector			0xD0037400
#define		 pExceptionRESET			( *((volatile unsigned long *)(_Exception_Vector + 0x0)) )
#define		 pExceptionUNDEF			( *((volatile unsigned long *)(_Exception_Vector + 0x4)) )
#define		 pExceptionSWI			( *((volatile unsigned long *)(_Exception_Vector + 0x8)) )
#define 		pExceptionPABORT			( *((volatile unsigned long *)(_Exception_Vector + 0xc)) )
#define 		pExceptionDABORT			( *((volatile unsigned long *)(_Exception_Vector + 0x10)) )
#define		 pExceptionRESERVED		( *((volatile unsigned long *)(_Exception_Vector + 0x14)) )
#define 		pExceptionIRQ				( *((volatile unsigned long *)(_Exception_Vector + 0x18)) )
#define 		pExceptionFIQ				( *((volatile unsigned long *)(_Exception_Vector + 0x1c)) )

void exceptionundef(void)
{
    printf("undefined instruction exception.\n");
    while(1);
}

void exceptionswi(void)
{
    printf("swi exception.\n");
    while(1);
}

void exceptionpabort(void)
{
    printf("pabort exception.\n");
    while(1);
}

void exceptiondabort(void)
{

    printf("dabort exception.\n");
    while(1);
}

// 中断相关初始化
void system_initexception( void)
{
    // 设置中断向量表
    pExceptionUNDEF	  =	(unsigned long)exceptionundef;
    pExceptionSWI  	  =	(unsigned long)exceptionswi;
    pExceptionPABORT  =	(unsigned long)exceptionpabort;
    pExceptionDABORT  =	(unsigned long)exceptiondabort;
    pExceptionIRQ	  =	(unsigned long)IRQ_handle;
    pExceptionFIQ	  =	(unsigned long)IRQ_handle;

    // 初始化中断控制器
    intc_init();

}

// 初始化中断控制器
void intc_init(void)
{
    // 禁止所有中断
    VIC0INTENCLEAR = 0xffffffff;
    VIC1INTENCLEAR = 0xffffffff;
    VIC2INTENCLEAR = 0xffffffff;
    VIC3INTENCLEAR = 0xffffffff;

    // 选择中断类型为IRQ
    VIC0INTSELECT = 0x0;
    VIC1INTSELECT = 0x0;
    VIC2INTSELECT = 0x0;
    VIC3INTSELECT = 0x0;

    // 清VICxADDR
    intc_clearvectaddr();

}

// 保存需要处理的中断的中断处理函数的地址
void intc_setvectaddr(unsigned long intnum, void (*handler)(void))
{
    //VIC0
    if(intnum<32)
    {
        *( (volatile unsigned long *)(VIC0VECTADDR + 4*intnum) ) = (unsigned)handler;
    }
    //VIC1
    else if(intnum<64)
    {
        *( (volatile unsigned long *)(VIC1VECTADDR + 4*(intnum-32)) ) = (unsigned)handler;
    }
    //VIC2
    else if(intnum<96)
    {
        *( (volatile unsigned long *)(VIC2VECTADDR + 4*(intnum-64)) ) = (unsigned)handler;
    }
    //VIC3
    else
    {
        *( (volatile unsigned long *)(VIC3VECTADDR + 4*(intnum-96)) ) = (unsigned)handler;
    }
    return;
}

// 清除需要处理的中断的中断处理函数的地址
void intc_clearvectaddr(void)
{
    // VICxADDR:当前正在处理的中断的中断处理函数的地址
    VIC0ADDR = 0;
    VIC1ADDR = 0;
    VIC2ADDR = 0;
    VIC3ADDR = 0;
}

// 使能中断
void intc_enable(unsigned long intnum)
{
    unsigned long temp;
    if(intnum<32)
    {
        temp = VIC0INTENABLE;
        temp |= (1<<intnum);
        VIC0INTENABLE = temp;
    }
    else if(intnum<64)
    {
        temp = VIC1INTENABLE;
        temp |= (1<<(intnum-32));
        VIC1INTENABLE = temp;
    }
    else if(intnum<96)
    {
        temp = VIC2INTENABLE;
        temp |= (1<<(intnum-64));
        VIC2INTENABLE = temp;
    }
    else if(intnum<NUM_ALL)
    {
        temp = VIC3INTENABLE;
        temp |= (1<<(intnum-96));
        VIC3INTENABLE = temp;
    }
    // NUM_ALL : enable all interrupt
    else
    {
        VIC0INTENABLE = 0xFFFFFFFF;
        VIC1INTENABLE = 0xFFFFFFFF;
        VIC2INTENABLE = 0xFFFFFFFF;
        VIC3INTENABLE = 0xFFFFFFFF;
    }

}

// 禁止中断
void intc_disable(unsigned long intnum)
{
    unsigned long temp;

    if(intnum<32)
    {
        temp = VIC0INTENCLEAR;
        temp |= (1<<intnum);
        VIC0INTENCLEAR = temp;
    }
    else if(intnum<64)
    {
        temp = VIC1INTENCLEAR;
        temp |= (1<<(intnum-32));
        VIC1INTENCLEAR = temp;
    }
    else if(intnum<96)
    {
        temp = VIC2INTENCLEAR;
        temp |= (1<<(intnum-64));
        VIC2INTENCLEAR = temp;
    }
    else if(intnum<NUM_ALL)
    {
        temp = VIC3INTENCLEAR;
        temp |= (1<<(intnum-96));
        VIC3INTENCLEAR = temp;
    }
    // NUM_ALL : disable all interrupt
    else
    {
        VIC0INTENCLEAR = 0xFFFFFFFF;
        VIC1INTENCLEAR = 0xFFFFFFFF;
        VIC2INTENCLEAR = 0xFFFFFFFF;
        VIC3INTENCLEAR = 0xFFFFFFFF;
    }

    return;
}

// 读中断状态
unsigned long intc_getvicirqstatus(unsigned long ucontroller)
{
    if(ucontroller == 0)
        return	VIC0IRQSTATUS;
    else if(ucontroller == 1)
        return 	VIC1IRQSTATUS;
    else if(ucontroller == 2)
        return 	VIC2IRQSTATUS;
    else if(ucontroller == 3)
        return 	VIC3IRQSTATUS;
    else
    {}
    return 0;
}

// 通用中断处理函数
void irq_handler(void)
{
    unsigned long vicaddr[4] = {VIC0ADDR,VIC1ADDR,VIC2ADDR,VIC3ADDR};
    int i=0;
    void (*isr)(void) = NULL;

    for(; i<4; i++)
    {
        if(intc_getvicirqstatus(i) != 0)
        {
            isr = (void (*)(void)) vicaddr[i];
            break;
        }
    }
    (*isr)();
}
时间: 2024-10-27 07:25:29

Smart210学习记录-----中断的相关文章

Smart210学习记录-------linux驱动中断

Linux中断 1.申请和释放中断 申请中断 int request_irq(unsigned int irq, irq_handler_t handler,  unsigned long irqflags, const char *devname, void *dev_id) irq 是要申请的硬件中断号. handler 是向系统登记的中断处理函数(顶半部),是一个回调函数,中断发生时,系统调用 这个函数, dev_id 参数将被传递给它. irqflags是中断处理的属性,可以指定中断的触

Smart210学习记录------块设备

转自:http://bbs.chinaunix.net/thread-2017377-1-1.html 本章的目的用尽可能最简单的方法写出一个能用的块设备驱动.所谓的能用,是指我们可以对这个驱动生成的块设备进行mkfs,mount和读写文件.为了尽可能简单,这个驱动的规模不是1000行,也不是500行,而是100行以内. 这里插一句,我们不打算在这里介绍如何写模块,理由是介绍的文章已经满天飞舞了.如果你能看得懂.并且成功地编译.运行了这段代码,我们认为你已经达到了本教程的入学资格,当然,如果你不

Smart210学习记录-------linux内核模块

Linux 驱动工程师需要牢固地掌握 Linux 内核的编译方法以为嵌入式系统构建可运行的Linux 操作系统映像.在编译 LDD6410 的内核时,需要配置内核,可以使用下面命令中的 一个: #make config(基于文本的最为传统的配置界面,不推荐使用) #make menuconfig(基于文本菜单的配置界面) #make xconfig(要求 QT 被安装) #make gconfig(要求 GTK+被安装) 在配置Linux 2.6内核所使用的make config.make me

Smart210学习记录-----SD/MMC/SDIO驱动

转自:http://jingpin.jikexueyuan.com/article/23369.html 一.SD/MMC/SDIO概念区分 SD(SecureDigital)与 MMC(MultimediaCard) SD 是一种 flash memory card 的标准,也就是一般常见的 SD 记忆卡,而 MMC 则是较早的一种记忆卡标准,目前已经被 SD 标准所取代.在维基百科上有相当详细的 SD/MMC 规格说明:[http://zh.wikipedia.org/wiki/Secure

Smart210学习记录-----Linux i2c驱动

一:Linux i2c子系统简介: 1.Linux 的 I2C 体系结构分为 3 个组成部分: (1) I2C 核心. I2C 核心提供了 I2C 总线驱动和设备驱动的注册.注销方法,I2C 通信方法(即“algorithm”)上层的.与具体适配器无关的代码以及探测设备.检测设备地址的上层代码等. (2) I2C 总线驱动. I2C 总线驱动是对 I2C 硬件体系结构中适配器端的实现,适配器可由 CPU 控制,甚至可以直接集成在 CPU 内部. I2C 总线驱动主要包含了 I2C 适配器数据结构

Smart210学习记录------linux串口驱动

转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=27025492&id=327609 一.核心数据结构 串口驱动有3个核心数据结构,它们都定义在<#include linux/serial_core.h> 1.uart_driver uart_driver包含了串口设备名.串口驱动名.主次设备号.串口控制台(可选)等信息,还封装了tty_driver(底层串口驱动无需关心tty_driver). struct

Smart210学习记录-----linux定时器

1.内核定时器: Linux 内核所提供的用于操作定时器的数据结构和函数如下: (1) timer_list 在 Linux 内核中,timer_list 结构体的一个实例对应一个定时器 1 struct timer_list { 2    struct list_head entry; /* 定时器列表 */ 3    unsigned long expires; /*定时器到期时间*/ 4    void (*function)(unsigned long); /* 定时器处理函数 */ 5

Smart210学习记录------nor flash驱动

nor flash驱动与nand flash驱动的差别不大,只是设置不同的结构体而已,, nor flash驱动代码: #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/device.h> #include

【学习记录】关于makefile而进行的互联网学习技巧练习及学习笔记和学习心得记录(vs2010)

我也不知道作为一个完全的windows平台下的不怎么专业的软件工程学生,看到<Accelerated C++>的源代码,第一反应是:哦!我应该用make生成工程文件.然后我愉快的用AOL开始搜索相关资料. 然并卵!我一定是被什么奇怪的生物附身了.我应该直接用vs创建项目->导入文件.然后……ctrl+F5.多么完美. 可是……以下: [教程]来自于云风大大的blog(云风的 BLOG) IDE 不是程序员的唯一选择(一) 以及后面的(二)(三)(四) 以及大大写了一篇半,只为了说明用cl