balz333
Posts: 5
Joined: Sun Jan 06, 2019 1:46 pm

SPI CS/CE with active high

Sun Jan 06, 2019 1:48 pm

Hello,

sorry for my bad english but I hope you understand my question. I would like program an EEPROM 93C56 at the SPI-Interface with the linux flashrom tool. I use a Raspberry Model B with the following kernel and SPI driver

[email protected]:~ $ cat /proc/version
Linux version 4.14.79+ ([email protected]) (gcc version 4.9.3 (crosstool-NG crosstool-ng-1.22.0-88-g8460611)) #1159 Sun Nov 4 17:28:08 GMT 2018
[email protected]:~ $ sudo modprobe spi-bcm2835
[email protected]:~ $

But my EEPROM will not recognized because the raspberry use active low for the CS/CE pin as standard. Is it possible to change the behavior to active high ?

thx
Mario
Germany

AnneRanch
Posts: 67
Joined: Fri Oct 19, 2018 1:48 pm

Re: SPI CS/CE with active high

Fri Jan 11, 2019 5:05 pm

Yes, you need to set the BCM processor SPi configuration register. Not sure how it will interact with your driver- it is obviously set for CE "low" now.

danjperron
Posts: 3144
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: SPI CS/CE with active high

Mon Jan 14, 2019 3:42 pm

I did check linux flashroom tool and that device is not listed. This mean even if you set the CS High it won't work


Interfacing the chip using bit banging is not complicated. I got some old code in PLM51 with the 93C46 hanging in one diskette at home.
This tell you how old that device is ;-)

I will dig the code and make a small python script. I will post the code tonight.

danjperron
Posts: 3144
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: SPI CS/CE with active high

Mon Jan 14, 2019 6:09 pm

Ok I did this in my luch time. It should work but can't confirm before tonight!

Be aware that some 93C46 only works with 5V so you will need some level shifter to make it work.

The python3 class

Code: Select all

import RPi.GPIO as GPIO
#ORG = 0  ASSUME 8Bits data



class eerom93CX6:

  def __init__(self,type=9366, CS=12,SK=16,DI=20,DO=21):
     if type == 9366:
        self.bitMask=256
        self.andMask=511
        self.addressRange=9
        self.size=512
     elif type == 9356:
        self.bitMask=256
        self.andMask=511
        self.addressRange=9
        self.size=256
     else:
        self.bitMask=64
        self.andMask=127
        self.addressRange=7
        self.size=128

     self.CS=CS
     self.SK=SK
     self.DI=DI
     self.DO=DO

     GPIO.setwarnings(False)
     GPIO.setwarnings(False)
     GPIO.setmode(GPIO.BCM)
     GPIO.setup(CS,GPIO.OUT)
     GPIO.setup(SK,GPIO.OUT)
     GPIO.setup(DI,GPIO.OUT)
     GPIO.setup(DO,GPIO.IN,pull_up_down=GPIO.PUD_UP)
     GPIO.output(CS,0)
     GPIO.output(SK,0)
     GPIO.output(DI,0)

  def bitOUT(self,value):
     GPIO.output(self.DI,value)
     GPIO.output(self.SK,1)
     GPIO.output(self.SK,0)

  def bitIN(self):
     GPIO.output(self.SK,1)
     value=GPIO.input(self.DO)
     GPIO.output(self.SK,0)
     return value

  def read(self,address):
     data=0
     GPIO.output(self.CS,0)
     self.bitOUT(0)
     GPIO.output(self.CS,1)
     self.bitOUT(0)
     self.bitOUT(1)
     self.bitOUT(1)
     self.bitOUT(0)
     #set address
     for i in range(self.addressRange):
       if (address & self.bitMask) == self.bitMask:
         self.bitOUT(1)
       else:
         self.bitOUT(0)
       address= (address << 1) & self.andMask
     #read 8 bits
     for i in range(8):
       data = data << 1
       if self.bitIN():
         data = data | 1
     GPIO.output(self.CS,0)
     GPIO.output(self.DI,0)
     return data

  def enable(self):
     GPIO.output(self.CS,0)
     self.bitOUT(0)
     GPIO.output(self.CS,1)
     self.bitOUT(1)
     self.bitOUT(0)
     self.bitOUT(0)
     self.bitOUT(1)
     self.bitOUT(1)
     for i in range(self.addressRange -2):
       self.bitOUT(0)
     GPIO.output(self.CS,0)

  def disable(self):
     GPIO.output(self.CS,0)
     self.bitOUT(0)
     GPIO.output(self.CS,1)
     self.bitOUT(1)
     self.bitOUT(0)
     self.bitOUT(0)
     self.bitOUT(0)
     self.bitOUT(0)
     for i in range(self.addressRange -2):
       self.bitOUT(0)
     GPIO.output(self.CS,0)


  def write(self,address,data):
     GPIO.output(self.CS,0)
     self.bitOUT(0)
     GPIO.output(self.CS,1)
     self.bitOUT(1)
     self.bitOUT(0)
     self.bitOUT(1)
     #set address
     for i in range(self.addressRange):
       if (address & self.bitMask) == self.bitMask:
         self.bitOUT(1)
       else:
         self.bitOUT(0)
       address= (address << 1) & self.andMask
     #write 8 bits data
     for i in range(8):
       if (data & 128) == 128:
         self.bitOUT(1)
       else:
         self.bitOUT(0)
       data= (data << 1) & 255
     GPIO.output(self.DI,0)
     GPIO.output(self.CS,0)
     #wait for ready
     GPIO.output(self.CS,1)
     while not self.bitIN():
        pass
     GPIO.output(self.CS,0)
the script read93C56.py which write binary file "eerom.dat"

Code: Select all

import eerom93CX6


#assume default pin
CS= 12
SK= 16
DI= 20
DO= 21


file=open("eerom.dat","wb")


eerom = eerom93CX6.eerom93CX6(9356,CS=12,SK=16,DI=20,DO=21)

for i in range(eerom.size):
   v = eerom.read(i)
   if i % 16 == 0:
     print("{:03X} : ".format(i),end="")
   print("{:2x} ".format(v),end="")
   file.write(v.to_bytes(1,byteorder='big'))
   if i % 16 == 15:
     print()

print("file eerom.dat written\n")
file.close()

And finally the script write93C56.py which read eerom.dat and write the data into the chip.

Code: Select all

import eerom93CX6
import sys


filename="eerom.dat"

if len(sys.argv) == 2:
   filename = sys.argv(1)

print("From file ",filename," to eerom.");

file=open(filename,"rb")

data = file.read()
file.close()

eerom = eerom93CX6.eerom93CX6(9356,CS=12,SK=16,DI=20,DO=21)

eerom.enable()
print("Writing eerom")

for i in range(len(data)):
   if i >= eerom.size:
     break;
   v = data[i]
   eerom.write(i,v)
   if i % 16 == 0:
     print("{:03X} : ".format(i),end="")
   print("{:2x} ".format(v),end="")
   if i % 16 == 15:
     print()
     
eerom.disable()
print("Writing Done\nRead eerom back")

for i in range(eerom.size):
   v = eerom.read(i)
   if i % 16 == 0:
     print("{:03X} : ".format(i),end="")
   print("{:2x} ".format(v),end="")
   if i % 16 == 15:
     print()
UPDATE*** Update script, fix bugs and confirm that 93C46 works

balz333
Posts: 5
Joined: Sun Jan 06, 2019 1:46 pm

Re: SPI CS/CE with active high

Fri Jan 18, 2019 7:21 pm

Thank you very much!!!

I will try it directly tomorrow. Only one question yet. Does it need a special driver or only the bcm2835 ?

thx
Mario

danjperron
Posts: 3144
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: SPI CS/CE with active high

Fri Jan 18, 2019 7:40 pm

No driver!

I'm not using the SPI at all. Just GPIO pins with a python3 script.

Pins definition
CS=12,
SK=16,
DI=20,
DO=21

If you have an old Raspberry Pi B, 26 pins connectors, you will need to set new pin definition.

P.S. don't forget that a lot of 93CX6 eeroms work only on 5V. Please check the specification. If it is, then use some 3.3V to 5V adapter like this one.
https://www.sparkfun.com/products/12009 or put a resistor divider on D0 pin ,2k/3K3. This way you don't put 5V on the raspberry Pi GPIO

Andyroo
Posts: 795
Joined: Sat Jun 16, 2018 12:49 am

Re: SPI CS/CE with active high

Fri Jan 18, 2019 9:09 pm

Why not use an inverter or transistor and a couple of resistors?

You could also handle the 3.3v to 5V difference for this pin with the transistor at the same time :lol:
Need Pi spray - these things are breeding in my house...

danjperron
Posts: 3144
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: SPI CS/CE with active high

Fri Jan 18, 2019 9:40 pm

Good chance that only two resistors will do the trick.
PI_93C46.jpg
93C46 to Raspberry PI
PI_93C46.jpg (53.88 KiB) Viewed 264 times

balz333
Posts: 5
Joined: Sun Jan 06, 2019 1:46 pm

Re: SPI CS/CE with active high

Sun Jan 20, 2019 3:48 pm

[email protected] for the great idea. But I have some questions to the suggestion.

As I described I want use my old Raspberry 1 Model B. This model have only the 26-pin I/O connector. Is it also possible to use the GPIO ports 22, 23, 24 and 25 and to remap in your script? These GPIO ports should be free and not reserved from the SPI or I2C driver. Is it right that you recommend an 2,2kOhm and an 3,3kOhm resistor?
I'm not a software developer. Must be the class file and script file in a special directory?

Many Thanks to Canada !

Regards
Mario
Germany
Attachments
raspberry-pi-rev2-gpio-pinout-1024x715.jpg
raspberry-pi-rev2-gpio-pinout-1024x715.jpg (148.86 KiB) Viewed 189 times

danjperron
Posts: 3144
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: SPI CS/CE with active high

Sun Jan 20, 2019 7:41 pm

Yes just change the GPIO in the read and write script!

eerom = eerom93CX6.eerom93CX6(9356,CS=22,SK=23,DI=24,DO=25)


Most of the 93CX6 only works with 5V. Please check the technical specification.


The Raspberry PI have only 3.3V GPIO. They can't support more than that!

Only the output from the 93CX6 needs to be converted to 3.3V. All inputs from the 93CX6 will work on 3.3V since the ViH is 2.7V.

Then to get 3.3V from a 5V output we need to create a resistor divider. Check wikipedia to know how it works. https://en.wikipedia.org/wiki/Voltage_divider


4K7/10K will do also or any value of resistors when 5V is near 3V. Be sure that the current is not to much. (< 2ma)

balz333
Posts: 5
Joined: Sun Jan 06, 2019 1:46 pm

Re: SPI CS/CE with active high

Mon Jan 21, 2019 8:12 am

Hello,

I understand your hint about the voltage difference but the voltage divider is currently not my main issue.

I try to understand your Python script. My 93C56 is currently soldered on a PCB and is set in the 16-bit Mode (ORG is connected to Vcc). Therefore the address bits are going from A0-A7 and the data bits from D0-D15. Is it for example enough to change the range for the data bits in your read script ?

#read 8 bits
for i in range(8): <<<<-------- 16 ???
data = data << 1
if self.bitIN():
data = data | 1

I don't know where the program code is for the address counter.

Many Thanks !
Mario

P.S. Sorry again for my english !

danjperron
Posts: 3144
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: SPI CS/CE with active high

Mon Jan 21, 2019 3:38 pm

I will made tonight then change to the class to allow 8 or 16 bits. I will also use my old PI B.


Check Table5 to see how many bits for address and data.
https://www.jameco.com/Jameco/Products/ ... 393601.pdf

balz333
Posts: 5
Joined: Sun Jan 06, 2019 1:46 pm

Re: SPI CS/CE with active high

Mon Jan 21, 2019 4:18 pm

I know this datasheet. I just wanted to say, that with 8-bit mode the address bits are going from A0-A8 and in 16-bit mode from A0-A7. I think currently only the 8-bit mode is programmed in your script. I have tried to change it but if you would do it for me, this would be very nice.

danjperron
Posts: 3144
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: SPI CS/CE with active high

Tue Jan 22, 2019 1:01 am

I modified the eerom93CX6 class to be 8 or 16 bits with the 'org'parameters. I also changed the GPIO for 22,23,24 and 25. This way you could use the Raspberry Pi B.


eerom93CX6.py

Code: Select all

import RPi.GPIO as GPIO
#ORG = 1  ASSUME 16Bits data



class eerom93CX6:


  def __init__(self,type=9356,org=1,CS=22,SK=23,DI=24,DO=25):
     self.org=org
     if org ==0:
       self.dataBitSize=8
     else:
       self.dataBitSize=16
#===== 9366 =====
     if type == 9366:
       if org == 0:
          self.bitMask=256
          self.addressRange=9
          self.size=512
       else:
          self.bitMask=128
          self.addressRange=8
          self.size=256
#===== 9356 =====
     elif type == 9356:
       if org ==0:
          self.bitMask=256
          self.addressRange=9
          self.size=256
       else:
          self.bitMask=128
          self.addressRange=8
          self.size=128
#===== 9346 =====
     else:
       if org ==0:
          self.bitMask=64
          self.addressRange=7
          self.size=128
       else:
          self.bitMask=32
          self.addressRange=6
          self.size=64

     print("BitMasK=",self.bitMask)
     print("addressRange=",self.addressRange)
     print("size=",self.size)


     self.CS=CS
     self.SK=SK
     self.DI=DI
     self.DO=DO

     GPIO.setwarnings(False)
     GPIO.setwarnings(False)
     GPIO.setmode(GPIO.BCM)
     GPIO.setup(CS,GPIO.OUT)
     GPIO.setup(SK,GPIO.OUT)
     GPIO.setup(DI,GPIO.OUT)
     GPIO.setup(DO,GPIO.IN,pull_up_down=GPIO.PUD_UP)
     GPIO.setup(7,GPIO.OUT)
     if org == 0:
       GPIO.output(7,0)
     else:
       GPIO.output(7,1)

     GPIO.output(CS,0)
     GPIO.output(SK,0)
     GPIO.output(DI,0)

  def bitOUT(self,value):
     GPIO.output(self.DI,value)
     GPIO.output(self.SK,1)
     GPIO.output(self.SK,0)

  def bitIN(self):

     GPIO.output(self.SK,1)
     GPIO.output(self.SK,0)
     value=GPIO.input(self.DO)
     return value

  def eraseAll(self):
     self.enable()
     GPIO.output(self.CS,0)
     self.bitOUT(0)
     GPIO.output(self.CS,1)
     self.bitOUT(1)
     self.bitOUT(0)
     self.bitOUT(0)
     self.bitOUT(1)
     self.bitOUT(0)
     for i in range(self.addressRange -2):
       self.bitOUT(0)
     GPIO.output(self.CS,0)




  def read(self,address):
     data=0
     GPIO.output(self.CS,0)
     self.bitOUT(0)
     GPIO.output(self.CS,1)
     self.bitOUT(0)
     self.bitOUT(1)
     self.bitOUT(1)
     self.bitOUT(0)
     #set address
     for i in range(self.addressRange):
       if (address & self.bitMask) == self.bitMask:
         self.bitOUT(1)
       else:
         self.bitOUT(0)
       address= address << 1

     #read data bits
     for i in range(self.dataBitSize):
       data = data << 1
       if self.bitIN():
         data = data | 1
     GPIO.output(self.CS,0)
     GPIO.output(self.DI,0)
     return data

  def enable(self):
     GPIO.output(self.CS,0)
     self.bitOUT(0)
     GPIO.output(self.CS,1)
     self.bitOUT(0)
     self.bitOUT(1)
     self.bitOUT(0)
     self.bitOUT(0)
     self.bitOUT(1)
     self.bitOUT(1)
     for i in range(self.addressRange -2):
       self.bitOUT(0)
     GPIO.output(self.CS,0)

  def disable(self):
     GPIO.output(self.CS,0)
     self.bitOUT(0)
     GPIO.output(self.CS,1)
     self.bitOUT(0)
     self.bitOUT(1)
     self.bitOUT(0)
     self.bitOUT(0)
     self.bitOUT(0)
     self.bitOUT(0)
     for i in range(self.addressRange -2):
       self.bitOUT(0)
     GPIO.output(self.CS,0)


  def write(self,address,data):
     GPIO.output(self.CS,0)
     self.bitOUT(0)
     GPIO.output(self.CS,1)
     self.bitOUT(0)
     self.bitOUT(1)
     self.bitOUT(0)
     self.bitOUT(1)
     #set address
     for i in range(self.addressRange):
       if (address & self.bitMask) == self.bitMask:
         self.bitOUT(1)
       else:
         self.bitOUT(0)
       address= address << 1
     #write data
     if self.org == 0:
        databitMask = 0x0080
     else:
        databitMask=  0x8000

     for i in range(self.dataBitSize):
       if (data & databitMask) == databitMask:
         self.bitOUT(1)
       else:
         self.bitOUT(0)
       data= data << 1
     GPIO.output(self.DI,0)
     GPIO.output(self.CS,0)
     #wait for ready
     GPIO.output(self.CS,1)
     while not self.bitIN():
        pass
     GPIO.output(self.CS,0)
read93C56.py

Code: Select all

#!/usr/bin/python3
import eerom93CX6



file=open("eerom.dat","wb")


eerom = eerom93CX6.eerom93CX6(9356,org=1,CS=22,SK=23,DI=24,DO=25)


for i in range(eerom.size):
   v = eerom.read(i)
   if i % 8 == 0:
     print("{:03X} : ".format(i),end="")
   print("{:04X} ".format(v),end="")
   file.write(v.to_bytes(2,byteorder='little'))
   if i % 8 == 7:
     print()


print("file eerom.dat written\n")
file.close()

write93C56.py

Code: Select all

#!/usr/bin/python3
import eerom93CX6
import sys
import time


filename="eerom.dat"

if len(sys.argv) == 2:
   filename = sys.argv[1]

print("From file ",filename," to eerom.");

file=open(filename,"rb")

data = file.read()
file.close()

eerom = eerom93CX6.eerom93CX6(9356,org=1,CS=22,SK=23,DI=24,DO=25)

eerom.enable()


print("Writing eerom")
dataFormat="{:02X} "


if eerom.org == 1:
  dataFormat="{:04X} "
  #if 16bits (org=1) then convert 8bits to 16bits (small endian)
  data16bits=[]
  for i in range(len(data)//2):
    data16bits.append(data[i*2] | data[(i*2)+1] << 8)
  data = data16bits


for i in range(len(data)):
   if i >= eerom.size:
     break;
   v = data[i]
   eerom.write(i,v)
   time.sleep(0.01)
   if i % 8 == 0:
     print("{:03X} : ".format(i),end="")
   print(dataFormat.format(v),end="")
   if i % 8 == 7:
     print()

eerom.disable()

print("Writing Done\nRead eerom back")

for i in range(eerom.size):
   v = eerom.read(i)
   if i % 8 == 0:
     print("{:03X} : ".format(i),end="")
   print(dataFormat.format(v),end="")
   if i % 8 == 7:
     print()
P.S. read93C56.py will create a file 'eerom.dat' which is little endian.

Return to “Interfacing (DSI, CSI, I2C, etc.)”