1 I2C communication protocol and S3C2410 chip Introduction
I2C (Inter Integrated Circuit) bus was launched by Philips in 1980. The I2C bus transmits information between the bus and the device using two wires (SDA and SCL), serial communication between the microcontroller and external devices, or bidirectional data transmission between the master device and the slave device. The two communication lines are pulled up to + 5 V through the pull-up resistor. Each Integrated Circuit in the control system can read each line through a CMOS Buffer, or the level of each line can be pulled down through a gate open-circuit FET tube. Therefore, for each chip, each line is both an input line and an output line.
The I2C bus follows the synchronous serial transmission protocol, that is, the serial transmission (one-bit, one-bit), and the clock (clock) line indicates the time of the data line. Each packet has an address before it to indicate which device receives the data.
Based on ARM920T, S3C2410 is a 16/32-bit Proteus microprocessor. It is mainly used for handheld devices and features high cost performance and low power consumption. It is also one of the most embedded development boards available on the market. The chip has a 16 KB instruction and data cache, and a storage management unit (MMU) LCD controller, three serial ports, four DMA channels, four clock timers, eight 10-bit A/D conversion; supports I2C, I2S, SPI, Master/Slave USB, and SD/MMC cards.
The I2C bus of the S3C2410 microprocessor can be in the following four modes: Master receiving mode, Master sending mode, slave receiving mode, and slave sending mode. The operation of the processor on I2C is mainly to read/write the following registers:
◇ IIC control register, iiccon (physical address 0x54000000, virtual address after memory ing );
◇ IIC control/Status Register, iicstat (physical address 0x54000004 );
◇ IIC data register, iicds (physical address 0x54000008 );
◇ IIC address register, iicadd (physical address 0x5400000c ).
In this design, the CPU works in the master mode to communicate with the following I2C interface device.
2 Windows CE driver features
The Windows ce.net driver has two models: local device drivers and stream interface drivers. The local device driver is suitable for devices integrated into the windows ce.net platform. These device drivers are required by some hardware and are created by the manufacturer of the original device to drive devices, such as keyboards, touch screens, and audio devices. These drivers will not be replaced once sold, for example, general-purpose LED Drivers, power drivers, keyboard drivers, and display drivers are all driven by local devices. For the driver of the local device, platform Builder provides some driver samples to facilitate developers to quickly develop their own drivers. When Win CE
When the system starts, the driver of the local device is loaded into the system memory. The development of local drivers can be divided into hierarchical drivers and single-chip drivers. The hierarchical driver uses the upper layer of the Application Communication provided by Microsoft, known as the module driver MDD (Model Device Driver ). The MDD layer communicates with the application through the device driver interface DDI (Device Driver Interface). The development driver usually does not modify the MDD layer and focuses on the underlying layers related to specific hardware, depending on the platform's device driver PDD (platform dependent driver), the PDD layer uses the device driver Service Interface (Device
Driver Service Provider Interface) to directly manage hardware. A Streaming Interface Device Driver (an installable Startup Program) can be provided by a third-party manufacturer to support devices added to the system. The device drivers in Windows CE work at the same protection level as the applications. When the system starts, most drivers are loaded by the device management process (device. EXE). All these drivers share the same process address space.
3 I2C bus driver design
The I2C bus driver is a real driver that is located at the OEM adaptation layer (oal) layer on the underlying Windows CE operating system kernel.
3.1 initialize I2C interrupt and write ISR routine
I2C communication is performed by operating I2C registers. In I2C communication, the four registers described above are read and written. The command status characters in these registers can be read and written to detect and control the behavior of the I2C bus. In Windows ce.net, first add the I2C interrupt number macro definition in the file oalintr. h:
# Definesysintr_i2c (sysintr_firmware + 19)
Then, add the I2C interrupt initialization, disable, and reset to the file CFW. C. The Code is as follows:
In the oeminterruptenable function, add
Case sysintr_iic:
S2410int-> rsrcpnd = bit_iic;
If (s2410int-> rintpnd & bit_iic) s2410int-> rintpnd = bit_iic;
S2410int-> rintmsk & = ~ Bit_iic;
Break;
In the oeminterruptdisable function, add
Case sysintr_iic:
S2410int-> rintmsk | = bit_iic;
Break;
Add the following to the oeminterruptdone function:
Case sysintr_iic:
S2410int-> rsrcpnd = bit_iic;
If (s2410int-> rintpnd & bit_iic) s2410int-> rintpnd = bit_iic;
S2410int-> rintmsk & = ~ Bit_iic;
Break;
Add the ISR program to the armint. c file to return the defined interrupt number after the interrupt occurs. The Code is as follows:
In the oeminterrupthandler function, add
Else if (intpendval = intsrc_iic ){
S2410int-> rsrcpnd = bit_iic;/* clear interrupt */
If (s2410int-> rintpnd & bit_iic) s2410int-> rintpnd = bit_iic;
S2410int-> rintmsk | = bit_iic;/* I2C interrupt prohibited */
Return (sysintr_rtc_alarm );
}
3.2 write a stream driver
The I2C bus driver adopts the standard form of Win CE stream driver. In the iic_init function, the virtualalloc () and virtualcopy () functions are used to associate the physical address of I2C in the chip with the virtual storage space of the operating system, the operation on the virtual address space is equivalent to the operation on the physical address of the chip. The address ing code is as follows:
Reg = (pvoid) virtualalloc (0, SZ, mem_reserve, page_noaccess );
If (REG ){
If (! Virtualcopy (Reg, ADDR, SZ, page_readwrite | page_nocache )){
Retailmsg (debugmode, (text ("Initializing interrupt \ n \ r ")
));
Virtualfree (Reg, SZ, mem_release );
Reg = NULL;
}
}
Here, SZ is the length of the application, and ADDR is the ing address of the actual physical address applied for the virtual address space in Win CE.
Then, perform operations on the Applied virtual address, install the streaming Driver Model in windows, and write the following functions.
Iic_init ()
In the function, it mainly initializes I2C. The main statement is as follows:
V_piicregs = (volatile iicreg *) iic_regalloc (pvoid) iic_base, sizeof (iicreg ));
V_piopregs = (volatile iopreg *) iop_regalloc (pvoid) iop_base, sizeof (iopreg ));
V_piopregs-> rgpeup | = 0xc000;
V_piopregs-> rgpecon | = 0xa00000;
V_piicregs-> riiccon = (1 <7) | (0 <6) | (1 <5) | (0xf );
V_piicregs-> riicadd = 0x10;
V_piicregs-> riicstat = 0x10;
Virtualfree (pvoid) v_piopregs, sizeof (iopreg), mem_release );
V_piopregs = NULL;
If (! Startdispatchthread (piichead ))
{Iic_deinit (piichead); Return (null);} in the startdispatchthread () function, the thread is created, associated events, and interruptions. The main statement is as follows:
Interruptinitialize (36, piichead-> hiicevent, null, 0); // correlation time and interruption
Createthread (null, 0, iicdispatchthread, piichead, 0, null); // creation thread wait time
In the iicdispatchthread () function, wait for the interruption to be generated and run: waitreturn = waitforsingleobject (piichead-> hiicevent, infinite );
Iiceventhandler (piichead); // event processing function
Interruptdone (36 );
Finally, in the iic_open, iic_read, and iic_write functions, perform operations on each register and assign values to the data to obtain the data read and sent by I2C.
4 I2C driver encapsulation and addition to Windows CE
Through the above work, You can compile a DLL function, but this cannot be called a stream interface driver. Because its interface functions have not been exported, you also need to tell the linked program what function to output. to create your own def file, you can use NotePad to create one named mydrive. Def:
Library mydriver
Exports
Iic_close
Iic_deinit
Iic_init
Iic_iocontrol
Iic_open
Iic_powerdown
Iic_powerup
Iic_read
Iic_seek
Iic_write
Then, use NotePad to write a registry file named mydrive. Reg:
[HKEY_LOCAL_MACHINE \ drivers \ builtin \ strings]
"Index" = DWORD: 1
"Prefix" = "IIC"
"DLL" = "mydriver. dll"
"Order" = DWORD: 0
Finally, write your own CEC file. The main task is to add a build method. The task is to copy the registry to the Windows CE system directory. Add a bib file. The main function is to add the compiled mydrive. dll file to the system kernel. Save the prepared CEC file. Open Platform builder, open the "file" menu, and add the prepared CEC features to the system options. When the system is generated, you can add your own CEC feature to include the compiled I2C drive.
The above introduces the driver structure of Win CE, and provides some source code of Win CE-based I2C driver. Experiments show that the design is feasible.
1.1 initialize IIC interrupt and write ISR routine
IIC communication is performed by operating IIC registers. In IIC communication, the four registers described above are read and written. The command status characters in these registers can be read and written to detect and control the behavior of the IIC bus. In Windows CE. net, we first need to add the IIC interrupt number macro definition in the file oalintr. h:
# Define sysintr_iic (sysintr_firmware + 19)
Then, add the IIC interrupt initialization, prohibition, and reset in the CFW. c file.
In the oeminterruptenable function, by writing 1 to the 27th-bit interrupt register rsrcpnd, the IIC interrupt source has an interrupt request. If you write 0 to the 27th-bit interrupt register rintmsk, the IIC interrupt is marked as a processing status. In this way, the IIC interrupt Initialization is implemented. In the oeminterruptdisable function, IIC interruption is prohibited by writing 1 to the 27th-bit interrupt register rintmsk.
The IIC driver needs to create an event, which can be implemented using the createevent function. Then interruptinitialize is called to bind the event to the IIC interrupt number, so that the interrupt can be performed. The oeminerrupteenable in OAL will be called, if this function does not return true, interruptinitialize fails. Then, the IST function in the driver can use the waitforsingleobject function to wait for interruption.
When an IIC is interrupted, the operating system encounters an exception. The interrupt vector indicates the CE exception handler. The exception handler then calls the oeminterrupthandler function of OAL. After the function detects the hardware, convert the hardware interruption to the software interrupt number and return it to the system. The interrupt number is the one used in interruptinitialize. After obtaining the interrupt number, the system finds the event corresponding to the interrupt number and wakes up the thread waiting for the event (IST). Then, the IST can process the interrupt in the user State. After the processing is complete, ist needs to call interruptdone to tell the operating system that the interrupt processing is complete, and the operating system calls oal again.
The oeminterruptdone function in to complete the interrupt processing.
1.2 write a stream driver
The IIC driver is written in the standard form of the Windows CE stream driver. In the iic_init function, the virtualalloc () and virtualcopy () functions are used (), associate the physical address of the IIC in the chip with the virtual address space of the operating system. The operation on the virtual address space is equivalent to the operation on the physical address of the chip.
Then, perform operations on the Applied virtual address and install the streaming Driver Model in windows, which mainly includes the compilation of the following functions:
1. iic_init (): initializes the IIC. It is called first after the Device Manager loads the IIC driver to initialize required variables, hardware devices, and other resources. This process is allocated to represent the data structure of the hardware instance of the device, and the hardware is initialized through the Hardware Abstraction interface hwinit. At the same time, this function will call interruptinitialize to create events for receiving logical interruptions in the kernel and initialize the critical section. 2. startdispatchthread (): it is mainly used to create threads, associate events and interruptions. The main statements are as follows:
Interruptinitialize (36, piichead-> hiicevent, null, 0); // associate events and interruptions
Createthread (null, 0, iicdispatchthread, piichead, 0, null); // creation thread wait time.
If startdispatchthread () returns false after execution, the iic_deinit () command is executed to uninstall the IIC driver.
3. iicdispatchthread (): Wait for the interruption to be generated, and then execute
Waitreturn = waitforsingleobject (piichead-> hiicevent, infinite );
Iiceventhandler (piichead); // event processing function
Interruptdone (36 );
Finally, in the iic_open, iic_read, and iic_write functions, perform operations on each register and assign values to the data. Obtain the data read by IIC and the sending speed data.
2 IIC driver encapsulation and addition to Windows CE
Through the above work, we can compile a DLL function, but this cannot be called a stream interface driver, because its interface function has not been exported, we also need to tell the linked program what function to output. To create a Def file of our own, you can use the Notepad program to edit a file named "mydrive. def file. The job of this file is to list the name of the function to be output from the DLL after the exports segment. You must add the actual name of the file to be compiled after the library, and then add the file to the project of the stream interface driver.
Then, use NotePad to write a registry file named "mydrive. Reg" and save it to the directory of the stream interface driver. The following is the content of this registry file.
[HKEY_LOCAL_MACHINE \ drivers \ builtin \ strings]
"Index" = DWORD: 1
"Prefix" = "IIC"
"DLL" = "mydriver. dll"
"Order" = DWORD: 0
Finally, write your own CEC file. The main task is to add a build method. The task is to copy the registry to the Windows CE system directory. Next, add a bib file. Its main function is to add the compiled mydrive. dll file to the system kernel. Then save the prepared CEC file. Open Platform build, open the "file" menu, and add the prepared CEC features to the system options. When the system is generated, you can add your own CEC feature to include the IIC driver you just compiled.
This article from the csdn blog, reproduced please indicate the source: http://blog.csdn.net/cfanlwn/archive/2009/12/04/4939786.aspx
How I2C bus works
Bus composition and signal type
The I2C bus is a serial bus consisting of the SDA data line and the clock SCL, which can send and receive data. Two-way transmission is performed between the CPU and the Controlled IC, and between the IC and IC. The maximum transmission rate is 100 kbps. Various controlled Circuits are connected in parallel on this bus, but just like telephones, only dialing their respective numbers can work. Therefore, each circuit and module has a unique address, in the process of information transmission, each module circuit connected to the I2C bus is both the master controller (or controller) and the transmitter (or receiver), depending on the functions it wants to accomplish. The control signal sent by the CPU is divided into address code and control amount. The address code is used for site selection, that is, the circuit to be controlled is connected to determine the type of control; the control value determines the type (such as contrast and brightness) of the adjustment and the amount to be adjusted. In this way, although each control circuit is mounted on the same bus, it is independent of each other and irrelevant to each other.
The I2C bus has three types of signals during data transmission: start signal, end signal, and response signal.
Start signal: in high-power mode, SDA switches from high level to low level to start transmitting data.
End signal: in high-power mode, SDA changes from low-level to high-level and ends data transmission.
Response signal: After receiving 8-bit data, the IC that receives the data sends a specific low-level pulse to the IC that sends the data, indicating that the data has been received. After the CPU sends a signal to the controlled unit, it waits for the controlled unit to send a response signal. After the CPU receives the response signal, it determines whether to continue to transmit the signal based on the actual situation. If no response signal is received, it is determined that the controlled unit has a fault.
Among these signals, the start signal is required. Either the end signal or the response signal can be used.
At present, many semiconductor integrated circuits have integrated I2C interfaces. Single-Chip Microcomputer with I2C interfaces include: cygnal's c8051f0xx series, philipsp87lpc7xx series, and microchip's pic16c6xx series. Many peripheral devices, such as memory and monitoring chips, also provide I2C interfaces.
I2C bus is a two-way two-wire bus used for the connection between IC Devices. It can be attached to multiple devices and connected through two wires, which occupies a very small space, the length of the bus can be up to 25 feet, and the maximum transmission rate of 10 Kbps can support four components. Its other advantage is the multi-controller, as long as the devices that can receive and send can become the master controller, of course, multiple masters cannot work at the same time.
The I2C bus has two signal lines, one of which is SDA (data line) and the other is SCL (clock line ). Clock signals are generated by the master device at any time.
I2C bus operation
I2C procedures use Master/Slave bidirectional communication. When a device sends data to the bus, it is defined as a sender, and the device receives data as a receiver. Both the master and slave devices can work in the receiving and sending status. The bus must be controlled by the main device (usually a microcontroller). The main device generates a serial clock (SCL) to control the transmission direction of the bus and generates Start and Stop conditions. The data status on the SDA line can be changed only during the period when the SCL is low. During the period when the SCL is high, the SDA status change is used to indicate the start and stop conditions.
Control byte
After the start condition, it must be the control byte of the device. The four-bit high is the device type identifier (the EEPROM is generally 1010 for different chip types ), the three digits are selected as slices, and the last digit is the read/write bit. When the value is 1, the read operation is performed, and when the value is 0, the write operation is performed.
Write operation
Write operations are divided into two types: byte write and page write. page write operations vary depending on the bytes loaded at a time on the chip.
Read operations
There are three basic read operations: Current address read, random read, and sequential read. Figure 4 shows the sequence of sequential reads. It should be noted that the 9th clock cycles of the last read operation are not "irrelevant ". To end the read operation, the host must issue a stop condition between 9th cycles or maintain SDA as high within 9th clock cycles, and then issue a stop condition.
Here, we can use the I2C interface of the device to link to the I2C bus, or the gpio port of the master chip to simulate the I2C interface.
The I2C data format is as follows:
No data: SCL = 1, SDA = 1;
Start: SDA changes from 1 to 0 when the SCL is 1;
Stop: SDA changes from 0 to 1 when the SCL is 1;
Data bit: When the SCL changes from 0 to 1, the sender controls the SDA. In this case, the SDA is valid data and cannot be changed at will;
The data on SDA can be changed at will when the check mark is set to 0;
Address bit: defines the same data bit, but only sends it to slave by the master;
Ack: When the sender sends 8 bits, the sender releases the SDA, which is controlled by the receiver and SDA = 0;
No response bit (NACK): When the sender sends 8 bits, the sender releases SDA, which is controlled by the receiver and SDA = 1.
When the data is transmitted in a single byte, the format is:
Start bit, 8-bit address bit (including 1-bit read/write bit), response, 8-bit data, response, stop bit.
When data is transmitted as a string of bytes, the format is:
Start bit, 8-bit address bit (including 1-bit read/write bit), response, 8-bit data, response, 8-bit data, response ,......, 8-bit data, response, and stop bit.
Note that:
1. The SCL is always controlled by the master. The SDA is controlled by the slave during data reading and the SDA is controlled by the master during data writing. After the eight-bit data is transferred, the SDA control of the response bit or no response bit is opposite to that of the Data bit transfer.
2. The start bit "start" and stop bit "stop" can only be issued by the master.
3. After the 8-bit address is transferred, the slave device with the address configured must send "Ack ". Otherwise, after a certain period of time, the master will be deemed as time-out, and data transmission will be abandoned and "stop" will be sent ".
4. When writing data, the master sends 8 data bits each time. If the slave device still has space to accept the next byte, it should answer "Ack ", if the slave device does not have space to accept more bytes, it should answer "Nack". When the master receives "Nack" or does not receive any data after a certain period of time, it will be deemed as timeout. At this time, the master abandons data transmission, send "stop ".
5. When reading data, the slave device sends 8 data bits each time. If the master wants to continue reading the next byte, the master should answer "Ack" to prompt the slave to prepare the next data, if the master does not want to read more bytes, the master should answer "Nack" to prompt the slave device to receive the stop signal.
6. When the master node is too fast and the slave end is too late to process the data, the slave device can lower the SCL (the "line and" will occur when the SCL = 0) to prevent the master node from sending more data. In this case, the master will slow down or stop data transmission as needed.
In actual application, it is not mandatory that the data receiver must respond to the eight-bit data sent, especially when both the master and slave are implemented by using gpio software simulation, the programmer can specify the length of data transfer without sending ack, sometimes it can reduce system overhead.