⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 csi2c1.c

📁 硬件的cpu是arm920i2c总线和camera之间的连接驱动在嵌入式linux操作系统下编写
💻 C
📖 第 1 页 / 共 2 页
字号:
		return;	}	i2c_csi_client.adapter->inc_use( i2c_csi_client.adapter );}static void I2C_cleanup(void){	i2c_detach_client(&i2c_csi_client );	i2c_del_driver(&i2c_csi_driver);}//-------------------------------////	Port enable for CSI signals////-------------------------------static void port_init_CSI(void){//	PA14 : CSI_PIXCLK//	PA13 : CSI_HSYNC//	PA12 : CSI_VSYNC//	PA11 : CSI_D7//	PA10 : CSI_D6//	PA9  : CSI_D5//	PA8  : CSI_D4//	PA7  : CSI_D3//	PA6  : CSI_D2//	PA5  : CSI_D1//	PA4  : CSI_D0//	PA3  : CSI_MCLK	* (U32 *)PTA_DDIR |=  0x00007FF8;	* (U32 *)PTA_GIUS &= ~0x00007FF8;	return;}////	Offset Calibration Block///*static void offsetCal(void){		I2C_write(0x20, 0x00);	I2C_write(0x21, 0x10);	I2C_write(0x23, 0x2A);//offset RAM registers// 12 sets of 64 columns (768 total columns)	int i, j;	for (i=0; i < 12; i++)	{		// Fixing columns with 1st method.		for (j=0; j < 33; j++)		{			I2C_write(0x22,0x00);		}		I2C_write(0x22,0x0a);	// neg offset (bright col)		I2C_write(0x22,0x09);	// neg offset (bright col)		I2C_write(0x22,0x01);	// pos offset (dark col)		I2C_write(0x22,0x02);	// pos offset (dark col)				for (j=0; j < 27; j++)		{			I2C_write(0x22,0x00);		}	} //change by tony	I2C_write(0x0A,0x80);}*/static void U32 CSI_init(){//	U32 mclkdiv;//	U32 MCLKDIV;//set port for CSI signals	port_init_CSI();//clock divider setting//	mclkdiv = systemClock / sensorClock;//	if(mclkdiv % 2)	//truncate to divider to even nos.//		mclkdiv -= 1;//	MCLKDIV = (((mclkdiv / 2) - 1) << 12) & 0xF000;	//gen register value	* (U32 *)CSI_CTRL_REG1   = 0x00000000;		//module reset	* (U32 *)CSI_CTRL_REG1   = 0x00000001;		//module enable	* (U32 *)CSI_CTRL_REG1  |= 0x000;				//MCLK enable	* (U32 *)CSI_CTRL_REG1  |= MCLKDIV;			//set clock divider//our sensor has its own clock	* (U32 *)CSI_CTRL_REG1  |= 0x00020000;		//SOF int disabled, SOF = rising edge	* (U32 *)CSI_CTRL_REG1  |= 0x00040000;		//RxFIFO full int enb	* (U32 *)CSI_CTRL_REG1  |= 0x00000100;		//sync clear FIFOs	* (U32 *)CSI_CTRL_REG1  |= 0x01000000;		//RX FIFO overrun interrupt enable////	Set FIFO full level////	This is a system timing issue, a HIGHER full level would produce//	LESS interrupt, which may reduce the overhead of ISR or polling//	* (U32 *)CSI_CTRL_REG1 &= ~0x180000;	//full = 16 words	* (U32 *)CSI_CTRL_REG1 |= 0x100000;	//full = 16 words//return the truncated sensor clock//	gSensorClock = sensorClock = systemClock / mclkdiv;// changed by tony		port_init_SENSOR();	// toggle INIT pin of sensor to hard reset it   *(U32 *)PTB_DR |= (0x1 << 18); 	// RESET asserted   *(U32 *)PTB_DR &= ~(0x1 << 18); 	// RESET released	//	// do soft reset of sensor//	I2C_write(0x0E, 0x03);	//sensor reset//	I2C_write(0x0E, 0x00);	//clear reset// change by tony 2004-4-10	// set global gain, TO control the input mode//	I2C_write(0x10, 0);    I2C_write(0x01,0x00);	I2C_write(0x02,0xC1); 	// set color gain	I2C_write(0x03,0x23);	I2C_write(0x04,0x00);	I2C_write(0x05,0x00);	/*I2C_write(0x00, 0x06);		// Green of Green-Red Row	I2C_write(0x01, 0x0C);		// Red	I2C_write(0x02, 0x0E);		// Blue	I2C_write(0x03, 0x06);		// Green of Blue-Green Row    *///同步控制	I2C_write(0x06,0xEB);	I2C_write(0x07,0xE0);	I2C_write(0x08,0x88);//亮度、色度控制	I2C_write(0x09,0x01);//	I2C_write(0x0A,0x80);	I2C_write(0x0B,0x47);	I2C_write(0x0C,0x40);	I2C_write(0x0D,0x00);	I2C_write(0x0E,0x01);	/////////	//output format control  YUV CCIR-656 8 bits	I2C_write(0x10,0xC0);	I2C_write(0x11,0x1C);	I2C_write(0x12,0x00);	I2C_write(0x13,0x00);	I2C_write(0x14,0x00);	I2C_write(0x15,0x00);	I2C_write(0x16,0x00);	I2C_write(0x17,0x00);/*	// Power Configuration	//	I2C_write(0x0C, 0x40);	// Color Tile Configuration	I2C_write(0x05, 0x05);		//	Color Tile Configuration 	I2C_write(0x06, 0x44);		// Row 1 Definition	I2C_write(0x07, 0xEE);		// Row 2 Definition	I2C_write(0x08, 0x00);		// Row 3 Definition	I2C_write(0x09, 0x00);		// Row 4 Definition	// Set Voltage Reference 	I2C_write(0x0A, 0x76);		// Negative Voltage	I2C_write(0x0B, 0x80);		// Positive Voltage	// Post ADC Control		I2C_write(0x30, 0xFE);		// While Pixel Threshold	I2C_write(0x31, 0x01);		// Black Pixel Threshold	I2C_write(0x32, 0x00);		// Post ADC Control	// Timing Control		I2C_write(0x54, 0xC0);		// SOF control	I2C_write(0x55, 0x90);		// VCLK control	I2C_write(0x63, 0x08);		// Factory Use Only Register, 										// but you have to set it like this	I2C_write(0x60, 0x00);		// Internal Timing*/	// Offset Calibration	//	offsetCal();/*	// capture mode setting	I2C_write(0x40, 0x35);		// Continuous capture, continuous streaming	// set WOI	I2C_write(0x4B, 0x02);		// WOI width (640)	I2C_write(0x4C, 0x7F);			I2C_write(0x47, 0x01);		// WOI Depth (480)	I2C_write(0x48, 0xDF);			I2C_write(0x49, 0x00);		// WOI column pointer (48)	I2C_write(0x4A, 48);			I2C_write(0x45, 0x00);		// WOI row pointer (20)	I2C_write(0x46, 20);		*//*		I2C_write(0x50, 0x02);		// WOI width (640+11)	I2C_write(0x51, 0x8B);		*/		return ;}//---------------------------////	SENSOR Register Write////---------------------------//#define DEBUG_I2CWR#ifdef DEBUG_I2CWR#define dprinti2cwr(str...) printk("<"__FUNCTION__"> "str)#else#define dprinti2cwr(str...)	// nothing#endifstatic void I2C_write(U32 reg, U32 data){	struct i2c_msg msg;	char buf[2];			/* 	 * store the register value to the first address of the buffer 	 * the adapter/algorithm driver will regard the first byte 	 * as the register value 	 */	buf[0] = (char)reg;	buf[1] = (char)data;	msg.addr = i2c_csi_client.addr;	msg.flags = I2C_M_WRITE;//	msg.len = count;	msg.len = 2;	msg.buf = buf;	/* 	 * initialize the message structure	 */	i2c_transfer( i2c_csi_client.adapter, &msg, 1 );}//---------------------------////	SENSOR Register Read////---------------------------static void I2C_read(U32 reg, U32 * _data){	struct i2c_msg msg[2];	char buf;	char command;	/* 	 * store the register value to the first address of the buffer 	 * the adapter/algorithm driver will regard the first byte 	 * as the register value 	 */	buf = 0;	command = (char)reg;	/* 	 * initialize the message structure	 */	msg[0].addr = i2c_csi_client.addr;	msg[0].flags = 0x00;//	msg.len = count;	msg[0].len = 1;	msg[0].buf = &command;		msg[1].addr = i2c_csi_client.addr;	msg[1].flags = I2C_M_READ;//	msg.len = count;	msg[1].len = 1;	msg[1].buf = &buf;	i2c_transfer( i2c_csi_client.adapter, msg, 2 );	*_data = (U32)buf;}void setPortSYNC(U32 level){	if(level)		* (U32 *)PTA_DR |=  0x00800000;	else		* (U32 *)PTA_DR &= ~0x00800000;			return;}//-------------------------------////	Port enable for SENSOR signals////-------------------------------static void port_init_SENSOR(void){//PA23 = SYNC (~CS5)//config PA23 for SYNC	* (U32 *)PTA_DR  &= ~0x00800000;	* (U32 *)PTA_GIUS |= 0x00800000;		* (U32 *)PTA_OCR2 |= 0x0000C000;	* (U32 *)PTA_DDIR |= 0x00800000;	* (U32 *)PTA_GPR  |= 0x00800000;//	* (U32 *)PTA_DR   |= 0x00800000;//default set port to low//	* (U32 *)PTA_DR  &= ~0x00800000;}//------------------------------------////	Capture image data with DMA////	Unified function for all //	supported image size capture////	Return TRUE if success//	Return FALSE if FIFO is overrun////------------------------------------static U32 SFCM_capture_DMA(U32 nPixel){	dma_data_size = nPixel;	readSeqNum = capSeqNum = SOFseqNum = 0;	stopCapture = 0;		* (U32 *)CSI_STS_REG   = 0x10000;	//clear last SOF irq	* (U32 *)CSI_CTRL_REG1  |= 0x60;		//prepare for sync clear FIFOs	*(U32 *)CSI_CTRL_REG1  |= 0x10000;			//enable SOF intr	return TRUE;}static void dma_complete_handler(){	*((U32 *)(DMA_CCR0+dma_channel*0x40)) = 0x800;				// disable DMA channel	*((U32 *)DMA_ISR) = (1<<dma_channel);		// clear DMA complete interrupt flag	if (stopCapture)	{		dmaStopped = 1;		wake_up_interruptible(&stop_capture_wait);		return;	}		if (*(U32 *)CSI_STS_REG & 1)	{		//	printk("!!! Data in FIFO !!!\n");		return;	}	capSeqNum++;//	if (!stopCapture)//	{		*((U32 *)(DMA_DAR0+dma_channel*0x40)) = dma_buf_phy_addr;	// destination		*((U32 *)(DMA_CNTR0+dma_channel*0x40)) = dma_data_size;		// count		*((U32 *)(DMA_CCR0+dma_channel*0x40)) = 0x809;					// enable DMAchannel		badFrame = 0;	// mark a good frame		wake_up_interruptible(&dma_wait);//	}}static void dma_error_handler(int error_type){	printk("*** CSI DMA error, type = 0x%08x ! ***\n", error_type);}static void csi_intr_handler(int irq, void *dev_id, struct pt_regs *regs){	if (*(U32 *)CSI_STS_REG & 0x10000)	// SOF intr ?	{		*(U32 *)CSI_STS_REG = 0x10000;						// clear SOF intr			if (stopCapture)		{			*(U32 *)CSI_CTRL_REG1  &= ~0x10000;				//disable SOF intr			SOFintrStopped = 1;			wake_up_interruptible(&stop_capture_wait);			return;		}		else		{			if (SOFseqNum==0)	// first SOF interrupt ?			{				*((U32 *)(DMA_DAR0+dma_channel*0x40)) = dma_buf_phy_addr;	// destination				*((U32 *)(DMA_CNTR0+dma_channel*0x40)) = dma_data_size;		// count				*((U32 *)(DMA_CCR0+dma_channel*0x40)) = 0x809;					// enable DMAchannel			}			else	// subsequent SOF interrupt (for data lost checking)			{				if (capSeqNum < SOFseqNum)	// i.e. DMA NOT completed on-time				{					// re-sync data					capSeqNum++;					*((U32 *)(DMA_CCR0+dma_channel*0x40)) = 0x800;					// disable DMA channel					// Notify read routine that there has been a bad frame					badFrame = 1;					wake_up_interruptible(&dma_wait);						*((U32 *)(DMA_DAR0+dma_channel*0x40)) = dma_buf_phy_addr;	// destination					*((U32 *)(DMA_CNTR0+dma_channel*0x40)) = dma_data_size;		// count					*((U32 *)(DMA_CCR0+dma_channel*0x40)) = 0x809;					// enable DMAchannel				}							}			readSeqNum = SOFseqNum;		// reading of last frame is not allowed			SOFseqNum++;		}		return;	}	printk("*** unknown interrupt ***\n");	*(U32 *)CSI_STS_REG = *(U32 *)CSI_STS_REG;	// clear all remaining interrupt flags}static devfs_handle_t devfs_handle;int init_module(){	int result;	printk("CSI driver "__DATE__" / "__TIME__"\n");	/* register our character device */		 	result = devfs_register_chrdev(0, "csi2c", &csi2c_fops); 	if ( result < 0 ) 	{		printk("csi2c driver: Unable to register driver\n");		return -ENODEV;	}	devfs_handle = devfs_register(NULL, "csi2c", DEVFS_FL_DEFAULT,				      result, 0,				      S_IFCHR | S_IRUSR | S_IWUSR,				      &csi2c_fops, NULL);   		      printk("make node for csi2c with 'mknod csi2c c %d 0'\n", result);		gMajor = result;		//init GPIO (PB19 / SIM_CLK) - used as STDBY by new CMOS sensor   *((U32 *)PTB_GIUS) |= 0x1 << 19;   *((U32 *)PTB_OCR2) |= 0x3 << (19 * 2 - 32);   *((U32 *)PTB_DDIR) |= 0x1 << 19;   *((U32 *)PTB_GPR ) |= 0x1 << 19;   *((U32 *)PTB_DR  ) &= ~(0x1 << 19); 	// normal mode	// init GPIO (PB18) - used as CMOS H/W reset by CMOS sensor   *((U32 *)PTB_GIUS) |= 0x1 << 18;   *((U32 *)PTB_OCR2) |= 0x3 << (18 * 2 - 32);   *((U32 *)PTB_DDIR) |= 0x1 << 18;   *((U32 *)PTB_GPR ) |= 0x1 << 18;   *((U32 *)PTB_DR  ) &= ~(0x1 << 18); 	// RESET released	if (request_irq(CSI_IRQ, csi_intr_handler, SA_INTERRUPT, "CSI", NULL))		printk("*** Cannot register interrupt handler for CSI ! ***\n");	else		printk("CSI interrupt handler registered\n");		I2C_init();	malloc_buffer();   return 0;}void cleanup_module(){	if (gMajor > 0){		devfs_unregister_chrdev(gMajor, "csi2c");		devfs_unregister(devfs_handle);		}			free_irq(CSI_IRQ, 0);	I2C_cleanup();		free_buffer();		printk("Say goodbye to csi2c\n");}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -