Notifications
Clear all

EEPROM acknowledge polling via smbus

9 Posts
3 Users
0 Reactions
523 Views
(@gorek)
Member
Joined: 2 years ago
Posts: 8
Topic starter  

In eeprom datasheet (e.g. AT24C256) I can read memory chip needs some time (usually 5ms) to write data to nonvolatile memory and eeprom will not respond to any i2c commands until the internal write is complete.
In another place of the datasheet is described we ca run acknowledge polling to determine is eeprom ready for next operation or not.

For Adruino I found something as below:

void write_function(...){
  //write commands...

  while(isBusy()){
    delayMicroseconds(50);
  }
}

bool isBusy(){
  Wire.beginTransmission(I2C_ADDRESS);
  return Wire.endTransmission();
}

I wonder how can I implement something similar via python smbus module.

gorek


   
Quote
Ron
 Ron
(@zander)
Father of a miniature Wookie
Joined: 4 years ago
Posts: 7410
 

Posted by: @gorek

In eeprom datasheet (e.g. AT24C256) I can read memory chip needs some time (usually 5ms) to write data to nonvolatile memory and eeprom will not respond to any i2c commands until the internal write is complete.
In another place of the datasheet is described we ca run acknowledge polling to determine is eeprom ready for next operation or not.

For Adruino I found something as below:

void write_function(...){
  //write commands...

  while(isBusy()){
    delayMicroseconds(50);
  }
}

bool isBusy(){
  Wire.beginTransmission(I2C_ADDRESS);
  return Wire.endTransmission();
}

I wonder how can I implement something similar via python smbus module.

gorek

 

I am NOT a Python guy, but I bet the Python equivalent of smbus has beginTransmission and endTransmission. If it does then the above code just needs to be rewritten using Python syntax. Maybe one of the Python guys will answer your query as well.

 

First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.


   
ReplyQuote
byron
(@byron)
No Title
Joined: 5 years ago
Posts: 1136
 

@gorek

something like the python in the link below will probably do the job.

https://gist.github.com/CRImier/b3922e0656825746a801594a7ccba8af

But if you were using micropython on a rpi Pico or an ESP32 etc then you cant do better than use the libraries from the excellent Peter Hinch repositories.

https://github.com/peterhinch/micropython_eeprom/blob/master/eeprom/i2c/eeprom_i2c.py

This post was modified 11 months ago by byron

   
ReplyQuote
Ron
 Ron
(@zander)
Father of a miniature Wookie
Joined: 4 years ago
Posts: 7410
 

@byron @gorek Those are interesting links. I am surprised that the C code is at least an order of magnitude less code and more easily understood. Perhaps my idea of Python is mistaken, I thought it was an easier higher-level language which generally means less code. How come it is more complex?

First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.


   
ReplyQuote
byron
(@byron)
No Title
Joined: 5 years ago
Posts: 1136
 

Posted by: @zander

How come it is more complex

Think of the C code snippet as a brick, whereas the linked examples showed a whole blooming house. 😀   As you may see the micropython library covered a whole bunch of eeproms and more.

And you probably missed the //write commands... comment in the C snippet.

But C is more terse and python is generally more verbose, and thus more easily read and followed.  One usually spends 10 times the amount of time reading and amending ones code than the initial write, so I like a bit of verbosity.  

 

This post was modified 11 months ago by byron

   
ReplyQuote
Ron
 Ron
(@zander)
Father of a miniature Wookie
Joined: 4 years ago
Posts: 7410
 

@byron I knew the write statement needed to be there. I was just surprised at how much Python code was needed. 

I had to look up Terse since my expectations were getting ahead of what I thought you were writing.

In a language hierarchy, the least 'terse' code is machine code, followed by ASM, followed by C. C++ is mostly C with some data abstraction concepts, so it is both less terse in some areas and more terse in others. Library creators do need C++ to create their Classes and methods but that is rare in this forum.

First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.


   
ReplyQuote
byron
(@byron)
No Title
Joined: 5 years ago
Posts: 1136
 

Posted by: @zander

I knew the write statement needed to be there. I was just surprised at how much Python code was needed. 

You are not really comparing like for like.  For example in the following code that is a method (a function of a class) to wait for i2c, the sort of thing the OP was asking:

 

    def _wait_rdy(self):  # After a write, wait for device to become ready
        self._buf1[0] = 0
        while True:
            try:
                if self._i2c.writeto(self._i2c_addr, self._buf1):  # Poll ACK
                    break
            except OSError:
                pass
            finally:
                time.sleep_ms(1)

 

The only real pertinent bit of code is - self._i2c.writeto(self._i2c_addr, self._buf1) - if you want terse 😀.  

As you can see the function is defined, the buffer to use is identified and the code loops until a condition is met.  The pertinent bit of code is also put into a try except clause for error handling, such as the eeprom finally giving up the ghost on a write too far for it meagre life expectancy.   The linked code is, as said, a library that can read/write to a number of different eeproms thus necessesitaking a bunch if if's etc. and, as the author of the lib should, has provided much error checking and comments which all add to the perceived code glut.   

I hope you a good boy and put in lots of error handling code into you programs 😎  

 


   
ReplyQuote
Ron
 Ron
(@zander)
Father of a miniature Wookie
Joined: 4 years ago
Posts: 7410
 

@byron I have some code now running for over 40 years. I have code in IBM mainframe OS and in dozens of corporate internet situations. I have always noticed that my code has far less error-checking than many of my peers. At least a part of the reason for that is other people do what can only be described as stupid error-checking. For example, I have seen numerous cases where a programmer did a hard-coded sequence check of a master file after being sorted by the vendor's utility. NOT ONCE was an error found. Also, many programmers do not study their compiler to learn what it can do. I have seen a lot of code checking for if an input field is 0 or blank. That is also the most common run time error, except for a bad pointer. HOWEVER, there are either compiler or language tools that prevent both of those in a way that either corrects or at least traps the error.

Keep in mind I worked for Big Blue (trained on hardware, firmware, and OS) and was the master of the OS and compiler. The IBM system engineers, when stumped, would call on me to go to the customer site either physically or via the net (we had that internally long before the internet) to solve the problem they were having. I have occasionally thought of writing a book about my activities, but I can't do it without getting IBM legal involved, and I am just too old to suffer through that amount of administrivia. Some security and NDAs are still in effect, but I don't know which are and am too tired to go through the discovery process.

So the bottom line is I didn't put much 'error checking' in my code because it wasn't needed. Since I have decades of constant use of that code with NO failures, I think I had the right amount.

First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.


   
ReplyQuote
(@gorek)
Member
Joined: 2 years ago
Posts: 8
Topic starter  

Posted by: @zander

I am NOT a Python guy, but I bet the Python equivalent of smbus has beginTransmission and endTransmission.

After long study smbus source code I found unfortunately smbus hasn't equivalent of these functions. Smbus just wrap linux kernel's i2c commands in python.

In Arduino you can create i2c message from scratch by adding any write/read commands sequence between start and stop (or even send stop and start sequences again inside message payload).

In smbus you can only send to device one of complete i2c message (beginning with start sequence, certain read/write command and end sequence). You can't edit message payload (except rdwr mode but it is out of scope of this post). List of these messages is described in https://docs.kernel.org/i2c/smbus-protocol.html .

Equivalent of message created by beginTransmission and endTransmission in Python is just write_quick(i2c_addr).

So python's isBusy could looks like:

isBusy(bus, deviceAddress):
	timeout = 100
	while timeout:
		try:
			bus.write_quick(deviceAddress)
			break
		except OSError as expt:
			timeout -= 1
			sleep(0.0001)

timeout is not necessary but it avoid to infinite loop when for example device is accidentally unplugged.

Maybe it will be helpful for someone else in future.


   
ReplyQuote