Summary and analysis of IIC timing problems in mini2440 debugging

Publisher:delta14Latest update time:2024-06-20 Source: elecfansKeywords:mini2440 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Description: mini2440 platform, wince6.0 system, vs2005

After several months of study and pause, I finally added the IIC bus simulated by GPIO under wince and realized the transplantation of IIC. The chip of IIC is SHT21 temperature and humidity chip.

The reason why I haven't figured out IIC for so long is that I implemented it very early in ADS, but it was always wrong when I added it to the system! The oscilloscope captured and found that the timing was wrong after the chip was reset. I searched and searched but couldn't figure out what was going on! Now I'm stuck.

I'm stuck in a vicious circle and can't get out of it!

I posted online and netizens gave me a lot of tips. Thank you! Jonsenwu netizen's words reminded me! When the driver is added to the system, the system scheduling takes time, and the delay of the driver will be extended! According to his tips, I also asked him for further advice. I would like to thank him here! Adjust the priority of the driver so that it always keeps the right to use the CPU during operation. The delay function tested under ADS will not be the same under the system!

Things I learned from this transplant:

1. Knowledge about priority in wince

The following is the code: used to implement priority preemption

//dwThreadID = GetCurrentThread(); //Get thread ID
//dwThreadPri = CeGetThreadPriority(dwThreadID); //Get thread ID priority
//dwThreadQuantum = CeGetThreadQuantum(dwThreadID); //Get thread time slice parameter
//CeSetThreadPriority(dwThreadID, 0);// Set current thread priority to the highest
//CeSetThreadQuantum(dwThreadID, 0); //Set current thread time slice to 0 to keep CPU ownership
//
//.......... (function for operating i2c)
//
//CeSetThreadQuantum(dwThreadID, dwThreadQuantum); //Restore normal time slice
//CeSetThreadPriority(dwThreadID, dwThreadPri); //Restore normal priority

Note: There are two functions for setting the priority, one function can set the priority from 0 to 255 (CeSetThreadPriority()), and the other function can only set the application priority from 248 to 255 (SetThreadPriority())!!

After the IIC debugging is successful, there is another problem in passing the data to the application. First, I implemented the transfer in XXX_IOControl, but no data came out no matter how I tried. Finally, I put it in XXX_Read and it was OK. Here I have to explain the problem about memcpy. As follows:

2. Understanding of memcpy function

Let’s first look at the problematic writing:

unsigned short SHT_Data[2];//

memcpy(pBuffer, SHT_Data, 2);//output

The only data my application reads is the temperature, the humidity is a very high number! I'm sure an expert will see the problem at a glance!

This is because: the copy of the memcpy function is based on bytes. The number of copies I made above is 2, so only the temperature is normal, and the humidity is not copied at all.

The correct method is 4 bytes: memcpy(pBuffer, SHT_Data, 4); //output

3. GPIO description

Here I have to despise the friendly arm's technical service again! I originally used the default two pins of 2440 for GPIO (the default ones were connected to EEPROM and Camera!!, it would be strange if they were correct!), and finally found the free pins of SPI0 to get it done.

The code can be found at: http://www.linuxidc.com/Linux/2012-11/74419p2.htm


Using the simulated IIC timing of the IIC IO port on mini2440 to drive a peripheral chip, the ADS debugging is correct, but it does not work when added to the system. The priority of the driver is also increased, but it is still incorrect.

volatile IOPreg *s2440IOP = (IOPreg *)IOP_BASE;

//volatile INTreg *s2440INT = (INTreg *)INT_BASE;

float SHT_Data[2];///tmp

HANDLE hDevSHT21;

DWORD SHT2x_Option_ThreadFuc(LPVOID Context);

void Virtual_Alloc(); // Virtual allocation

////////////////////////////////////////////////////// ////////////////////////////

///////////////////////////////////I2C.c source/////////////// ////////////////////////////

#define noACK 0

#define aCk 1

#define SCL_OutEnable s2440IOP->rGPECON =( s2440IOP->rGPECON | 0x30000000 ) & 0xDFFFFFFF //28 config SCL as output

#define SDA_OutEnable s2440IOP->rGPECON =( s2440IOP->rGPECON | 0xC0000000 ) & 0x7FFFFFFF //30config SDA as output

#define SDA_OutDisable s2440IOP->rGPECON =( s2440IOP->rGPECON & 0x3fffffff)//config SDA as input

#define SCL_Set s2440IOP->rGPEDAT |= (1 << 14) //SCL output "1"

#define SCL_Clear s2440IOP->rGPEDAT &= ~(1 << 14) //SCL output "0"

#define SDA_Set s2440IOP->rGPEDAT |= (1 << 15) //SDA output "1"

#define SDA_Clear s2440IOP->rGPEDAT &= ~(1 << 15)

void Delay_us(U32 uS)

{

volatile DWORD dwCounter;

dwCounter = 100 * uS;

while(dwCounter--);

}

void I2c_Initialize ()

{ // put setup code here

SCL_OutEnable; // set gpio6->SCL as output

SCL_Set; // set SCL = "1"

SDA_OutDisable; // set gpio7->SDA as input

SDA_Set;

Delay_us(100); // let I2C device ready

}

//================================================ ==============================

void I2c_StartCondition ()

//================================================ ==============================

{

SDA_OutEnable; // set SDA as output

//SCL_OutEnable; //!!

SDA_Set;

SCL_Set;

Delay_us(1);

SDA_Clear;

Delay_us(5);

SCL_Clear;

Delay_us(5);

}

//================================================ ==============================

void I2c_StopCondition ()

//================================================ ==============================

{

SDA_OutEnable; // set SDA as output

//SCL_OutEnable; //!!

SDA_Clear;

SCL_Clear;

Delay_us(1);

SCL_Set;

Delay_us(5);

SDA_Set;

Delay_us(5);

}

//------------------------------------------------ ----------------------------------

unsigned char I2c_WriteByte(unsigned char value)

// writes a byte on the Sensibus and checks the acknowledge

//------------------------------------------------ ----------------------------------

{

// dwThreadID = GetCurrentThread();

//dwThreadPri = CeGetThreadPriority(dwThreadID);

//dwThreadQuantum = CeGetThreadQuantum(dwThreadID);

//CeSetThreadPriority(dwThreadID, 0);/

//CeSetThreadQuantum(dwThreadID, 0);

//

// . . . . . . (This part is the function for operating i2c)

//

//CeSetThreadQuantum(dwThreadID, dwThreadQuantum);

//CeSetThreadPriority(dwThreadID, dwThreadPri);

HANDLE dwThreadID = GetCurrentThread();

DWORD dwThreadPri = CeGetThreadPriority(dwThreadID);

DWORD dwThreadQuantum = CeGetThreadQuantum(dwThreadID);

CeSetThreadPriority(dwThreadID, 0);

CeSetThreadQuantum(dwThreadID, 0);

int error=0, i1=0, i2=0;

for(i2 = 0; i2 < 8; i2++ )

{ // setup data onto SDA

if(value & 0x80){

SDA_Set; //SetSDA( 1 );

}

else{

SDA_Clear; //SetSDA( 0 );

}

Delay_us(1); //I2C timing: data setup time > 200ns

//issue a clock

SCL_Set; //SetSCL( 1 );

Delay_us(1); //I2C timing: SCL high time > 0.6us

SCL_Clear; //SetSCL( 0 );

Delay_us(2); //I2C timing: SCL low time > 1.3us

value= value<< 1;

}

//check ACK(Low state) from I2C device

SDA_OutDisable; //set SDA as input

Delay_us(1); //I2C timing: data(from I2C device) setup time > 200ns

SCL_Set; //SetSCL( 1 ); // issue a clock

Delay_us(1); //I2C timing: SCL high time > 0.6us

if(s2440IOP->rGPEDAT>>15) //read ACK_BIT issued from I2C device

{

// NO ACK, so setup STOP condition

SCL_Set; //SetSCL( 1 );

Delay_us(1); //I2C timing: stop setup timing > 0.6us

SDA_Set; //SetSDA( 1 ); SDA is in input status!

return -(i1+1); // no acknowledgment -> failed

}

SCL_Clear; //SetSCL( 0 );

Delay_us(2); //I2C timing: SCL low time > 1.3us

//check ACK passed, config SDA as output for further outputing

SDA_OutEnable;

// backup the thread priority;

CeSetThreadQuantum(dwThreadID, dwThreadQuantum);

CeSetThreadPriority(dwThreadID, dwThreadPri);

return 0;

}

//------------------------------------------------ ----------------------------------

unsigned char I2c_ReadByte(unsigned char ack)

//------------------------------------------------ ----------------------------------

// reads a byte form the Sensibus and gives an acknowledge in case of "ack=1"

{

HANDLE dwThreadID = GetCurrentThread();

DWORD dwThreadPri = CeGetThreadPriority(dwThreadID);

DWORD dwThreadQuantum = CeGetThreadQuantum(dwThreadID);

CeSetThreadPriority(dwThreadID, 0);

CeSetThreadQuantum(dwThreadID, 0);

unsigned char i,val=0;

int i2=0,ub[1];

SDA_OutDisable; //SetSDADir( 0 ); // set SDA as input

// then read a byte

for(i2 = 0; i2 < 8; i2++)

{

ub[0] = ub[0] << 1;

//issue a clock

SCL_Set; //SetSCL( 1 );

//DelayInuSec(1); //I2C timing: SCL high time > 0.6us

if(s2440IOP->rGPEDAT>>15) // read SDA

{

ub[0] = ub[0] | 0x01;

}

SCL_Clear; //SetSCL( 0 );

Delay_us(5); //I2C timing: SCL low time > 1.3us

}

//issue ACK condition properly

SDA_OutEnable;

if (ack)

{ SDA_Clear; }

else

{ SDA_Set; }

Delay_us(1); //I2C timing: data setup time > 200ns

SCL_Set; //SetSCL( 1 );

Delay_us(1); //I2C timing: SCL high time > 0.6us

SCL_Clear;

Delay_us(2); //I2C timing: SCL low time > 1.3us

// backup the thread priority;

CeSetThreadQuantum(dwThreadID, dwThreadQuantum);

CeSetThreadPriority(dwThreadID, dwThreadPri);

return ub[0];

}

/////////////////////////////// SHT2x.c source ////////////////// ///////////////////////

//================================================ ===========================

unsigned char SHT2x_MeasureHM(etSHT2xMeasureType eSHT2xMeasureType, unsigned int *pMeasurand)

[1] [2]
Keywords:mini2440 Reference address:Summary and analysis of IIC timing problems in mini2440 debugging

Previous article:Definition of 2440GPIO port in Linux
Next article:mini2440 ADC adjustable resistor driver development source code (miscellaneous device driver framework)

Recommended ReadingLatest update time:2024-11-15 07:20

MINI2440 MPLL
1. S3C2440 clock system The clock control logic of s3c2410/s3c2440 can either connect an external crystal oscillator and then generate a clock source through the internal circuit; or it can directly use the external clock source, which is selected by the pin settings. The clock control logic provides three clocks for
[Microcontroller]
MINI2440 MPLL
Successfully ported ffmpeg on mini2440
On mini2440, the entire porting process is divided into three steps: (1) compile x264; (2) compile ffmpeg; (3) after the porting is successful, test it by using ffmpeg to record the video. (1) Compile x264 I downloaded the latest x264 from the official website, the address is http://www.videolan.org/developers/x26
[Microcontroller]
BOA server transplantation based on mini2440
Win7 system development board: mini2440 Virtual machine: Ubuntu 12.04 Preparation: Make sure the host and development board can communicate normally, that is, they can ping each other. For specific operation, please refer to my previous essay. 1. First download the boa source code from http://www.boa.org/ and co
[Microcontroller]
BOA server transplantation based on mini2440
Detailed explanation of porting u-boot-2011.03 to Mini2440 under Windows (2)
Debug uboot in SDRAM The code download address for this part is at the end of the article. Before entering the debugging state, you must install the Jlink driver. Then power on the mini2440 development board and run the J-Link GDB Server via JTAG, as shown below. Then click the down arrow in Eclipse and select u
[Microcontroller]
Detailed explanation of porting u-boot-2011.03 to Mini2440 under Windows (2)
Establish Keil MDK/Jlink development and debugging environment for mini2440 development board
Create a new Keil project, select Samsung's s3c2440 as the device. When asked whether to copy the startup code to the project directory, select Yes. In the Target tab of the project configuration, make the following configuration: After confirmation, write the main function and compile the project. If there is n
[Microcontroller]
U-boot-2014.04 ported to MINI2440 (10) Porting nand flash to save environment variables and add partitions
1. Save environment variables to nand flash Step 1: Modify mini2440.h Since we execute the saveenv command and then save the environment variables, the u-boot commands are all implemented under common. Cut in and execute gerp "saveenv" –nr ./*.c, and find the following results: There are a lot of things here, op
[Microcontroller]
U-boot-2014.04 ported to MINI2440 (10) Porting nand flash to save environment variables and add partitions
Arm mini2440 video remote monitoring based on v4l2 ffmpeg x264
The mini2440-based camera surveillance that is popular on the Internet is generally based on MJPEG-Streamer. This method uses the underlying driver of V4L2, and then cooperates with the streaming transmission of the mjpeg format, and then browses the video and controls it through the browser. The following is a so
[Microcontroller]
Summary of character driver writing (based on mini2440, LED driver)
    Programming: what features are needed (mechanisms), how to use them (strategies)     As driver writers, we need to choose an acceptable compromise between the required programming time and the flexibility of the driver. Readers may be surprised to say that the driver is "flexible". We use this word to emphasize
[Microcontroller]
Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号