65SIB Software implementation
65SIB Software implementation
I am starting this thread with the hopes of getting more people involved with creating some useful peripherals for the 65SIB project.
A few I can throw out are:
a battery-backed Real time clock
flash or eeprom storage
sound generation
mp3 decoder
ethernet interface
a/d converters
temperature sensors
First though, we should come up with a simple method for passing data back and forth, keeping in mind the full duplex nature of the SPI interface and the need to check the status of the slave devices to ensure they are ready.
My 65SPI chip can be a starting point. I am willing to help modify it if needed to facilitate the use of the 65SIB. This will provide a common Master. A software bit-banged solution can also be defined for those wanting to use the 65C22 or other I/O device.
In order to get a peripheral to communicate, we have to tie in the SPI interface and define the requirements for reliable, two-way data transfer.
Any thoughts?
Daryl
A few I can throw out are:
a battery-backed Real time clock
flash or eeprom storage
sound generation
mp3 decoder
ethernet interface
a/d converters
temperature sensors
First though, we should come up with a simple method for passing data back and forth, keeping in mind the full duplex nature of the SPI interface and the need to check the status of the slave devices to ensure they are ready.
My 65SPI chip can be a starting point. I am willing to help modify it if needed to facilitate the use of the 65SIB. This will provide a common Master. A software bit-banged solution can also be defined for those wanting to use the 65C22 or other I/O device.
In order to get a peripheral to communicate, we have to tie in the SPI interface and define the requirements for reliable, two-way data transfer.
Any thoughts?
Daryl
Last edited by 8BIT on Wed Feb 11, 2009 4:53 am, edited 1 time in total.
- GARTHWILSON
- Forum Moderator
- Posts: 8775
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Quote:
First though, we should come up with a simple method for passing data back and forth, keeping in mind the full duplex nature of the SPI interface and the need to check the status of the slave devices to ensure they are ready.
For bit-banging, you don't even have to know what mode you're in-- just do what the data sheet says, and watch it work. They usually work on the first try for me, and I definitely don't know my SPI modes.
For basic designs, just about any SPI IC on the market can go on a little board with the two 65SIB connectors and a 78L05 regulator. It could hardly be simpler. Microwire ICs and even a long chain of dumb shift registers like the 74HC595 can go on it too, although in some cases a hex inverter will be needed for those non-SPI applications in order to get the polarities right, or, in the case of something like 4000-series shift registers which I've used many times for 12V interfacing, voltage translation will be needed. Op amps, line drivers and receivers, etc. are extra but not part of the SPI discussion at this point.
Perhaps I should draw up a few diagrams of simple 65SIB devices that could be assembled in an afternoon, and post the diagrams. I won't be able to get to it this week with a business trip coming up, but maybe next. I don't have CAD for schematics, so they'll be done by hand and scanned. I don't like the way the CAD packages I've evaluated do schematics, so I only use CAD for laying out PC boards. Our company schematics are still on paper and reside in a flat file, and it will remain that way for the foreseeable future. At my last place of work I became very proficient with OrCAD, but hated it.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
GARTHWILSON wrote:
Since this is already quite well defined in the data sheets of every SPI IC (probably thousands of them) on the market, I must assume you're looking for discussion on how the 65SPI chip, which we look forward to, should handle the different SPI modes 0, 1, 2, and 3, and change modes on the fly possibly for every device on the bus as needed. Or, how to design protocols for new SPI devices like your IDE controller, made with programmable logic or microcontrollers.
I see my wording could have been more clear. I was thinking of protocols for new devices using microcontrollers as the SPI slave to peripheral interface. This would include the AVR's, PIC's, SX's, and any others the group may be using.
I can foresee something like this:
An SPI command interpreter, with a few simple commands:
Get Status, Get Data, Send Data, set parameter. The SPI receiver should have an interrupt so the controller does not miss an incoming request.
1) The SPI Master sends a Get Status command, waits for x amount of time for slave to be ready, then clocks the status back (two SPI transfers total)
2) If slave has data to be passed to master, master sends get data command that tells slave to send it. At this point, the time needed for the slave to respond needs to be defined so we won't miss it by starting the next transfer too soon. (two SPI transfers total)
3) Master sends Send Data command to slave, which is a command byte to tell the slave to go process something and return a value when done. The slave should acknowlege the command, then go do the task. The time needed to acknowlege the command will be variable depending upon how many commands it must decode. We need a method to ensure the ack is received by the master. (two spi transfers minimum)
When the task is done, the slave sets a status flag and waits for Master to execute task 2.
I ran into all this with the SBC-3's ATMega8 running the PC keyboard and RS-232 port. For every transmission, at least one more is needed for feedback.
Has anyone else created an SPI slave device? How did you handle it?
Last edited by 8BIT on Wed Feb 11, 2009 4:56 am, edited 1 time in total.
8BIT wrote:
An SPI command interpreter, with a few simple commands:
Get Status, Get Data, Send Data, set parameter. The SPI receiver should have an interrupt so the controller does not miss an incoming request.
1) The SPI Master sends a Get Status command, waits for x amount of time for slave to be ready, the clocks the status back (two SPI transfers total)
2) If slave has data to be passed to master, master sends get data command that tells slave to send it. At this point, the time needed for the slave to respond needs to be defined so we won't miss it by starting the next transfer too soon. (two SPI transfers total)
3) Master sends Send Data command to slave, which is a command byte to tell the slave to go process something and return a value when done. The slave should acknowlege the command, then go do the task. The time needed to acknowlege the command will be variable depending upon how many commands it must decode. We need a method to ensure the ack is received by the master. (two spi transfers minimum)
When the task is done, the slave sets a status flag and waits for Master to execute task 2.
I ran into all this with the SBC-3's ATMega8 running the PC keyboard and RS-232 port. For every transmission, at least one more is needed for feedback.
Has anyone else created an SPI slave device? How did you handle it?
Get Status, Get Data, Send Data, set parameter. The SPI receiver should have an interrupt so the controller does not miss an incoming request.
1) The SPI Master sends a Get Status command, waits for x amount of time for slave to be ready, the clocks the status back (two SPI transfers total)
2) If slave has data to be passed to master, master sends get data command that tells slave to send it. At this point, the time needed for the slave to respond needs to be defined so we won't miss it by starting the next transfer too soon. (two SPI transfers total)
3) Master sends Send Data command to slave, which is a command byte to tell the slave to go process something and return a value when done. The slave should acknowlege the command, then go do the task. The time needed to acknowlege the command will be variable depending upon how many commands it must decode. We need a method to ensure the ack is received by the master. (two spi transfers minimum)
When the task is done, the slave sets a status flag and waits for Master to execute task 2.
I ran into all this with the SBC-3's ATMega8 running the PC keyboard and RS-232 port. For every transmission, at least one more is needed for feedback.
Has anyone else created an SPI slave device? How did you handle it?
The solution is that the SPI controller must exist as a self-contained functional unit with demonstrable resiliancy against failure of the intended peripheral.
What this means can best be explained by way of example.
Assume you're implementing a simple pen plotter, using the following commands: Q, W, E, A, D, Z, X, and C are used to move the carriage in the compass directions implied by their relative placement on the QWERTY keyboard. 1 is used for "pen-down", 2 for "pen-up".
Driving a stepper motor obviously takes MUCH longer than it'll take to transfer even a single byte plus status on the SPI bus, let alone an entire buffer full of commands. How, then, can we not only make the plotter asynchronous from the host PC, but also give it the ability to synchronize?
This is a clear-cut case where experience in writing multi-threaded software gives benefits to hardware design. The solution in software is to create a separate thread, whose sole purpose is to keep an eye on the desired slave thread, on behalf of the master thread.
In hardware terms, we apply the same principle by using two microcontrollers: one whose sole purpose is to baby-sit the SPI bus, and the other to drive the plotter. They're certainly cheap enough now -- about $0.50 each for the smaller microcontrollers. Except for PCB layout issues, there's no reason to use a single microcontroller anymore.
Due to the decoupling of functionality, the SPI controller runs independently of driven peripheral. If the intended peripheral ever crashes or malfunctions, you can at least still contact the SPI interface for telemetry
The plotter's SPI controller maintains a (note: not necessarily the) command queue, as viewed by the PC, along with knowledge of how deep the command queue currently is. It also knows (via its parallel I/O pins) the relevant status information of the slave peripheral as well. Thus, when the PC queries the device, it may receive information of both the front command buffer and the current operational status of the plotter.
Seeing that the front queue is empty, the PC may transmit a block of data to the SPI controller. Stuffing bytes is trivially simple, so it's able to maintain these bytes in the front queue. When the plotter controller is ready, the SPI controller sends a byte to the plotter controller using its parallel I/O lines. Will the SPI device need to deal with interrupts? Absolutely! But, because everything is decoupled, your latencies at most are measured in microseconds, which will prove plenty fast enough for SPI interfaces, even if the plotter controller itself takes milliseconds or longer.
Ignoring cosmic ray interference, it is entirely possible to write the SPI controller to be crash-free under every input scenario. Some might argue that this takes a lot of effort; while it certainly does require more attention to detail, using formal design methodologies as simple as "Hoare triples" and deriving what are called Hoare's "weakest preconditions", a feat which requires neither formal training nor education in discrete mathematics, I would hardly call this a lot of effort. Consider the effort in debugging the system under all possible input combinations!
Thanks for the great explaination. My ATMega8 is actually doing well but IS relying on the RDY pin to keep the Master and slave in sync. Without it, bytes would get skipped and the two would loose sync with each other, resulting in a stuck loop.
I see now how you propose to get these things to work. When I get time (in about 3 weeks, I'll see if I can throw together something to get started with. I have open ports on SBC3's 65SPI and a few ATMega8's I can use as the Slave SPI controller.
Eventually, I would love to be able to have the SPI controller purely an interrupt-driven subsystem integrated into one microcontroller. If the 16-20MHz Atmel devices cannot handle it, purhaps another platform could.
Daryl
I see now how you propose to get these things to work. When I get time (in about 3 weeks, I'll see if I can throw together something to get started with. I have open ports on SBC3's 65SPI and a few ATMega8's I can use as the Slave SPI controller.
Eventually, I would love to be able to have the SPI controller purely an interrupt-driven subsystem integrated into one microcontroller. If the 16-20MHz Atmel devices cannot handle it, purhaps another platform could.
Daryl
PontusO wrote:
I'm working on a one-chip ethernet solution that connects through an SPI interface. My idea is to have the entire TCP/IP stack in the chip and a socket like API to talk with it.
I will follow this thread closely and give you any feedback or ideas when I can.
/Pontus
I will follow this thread closely and give you any feedback or ideas when I can.
/Pontus
kc5tja wrote:
PontusO wrote:
I'm working on a one-chip ethernet solution that connects through an SPI interface. My idea is to have the entire TCP/IP stack in the chip and a socket like API to talk with it.
I will follow this thread closely and give you any feedback or ideas when I can.
/Pontus
I will follow this thread closely and give you any feedback or ideas when I can.
/Pontus
I have a prototype (somewhat instable yet
/Pontus
8BIT wrote:
...I see now how you propose to get these things to work. When I get time (in about 3 weeks, I'll see if I can throw together something to get started with. I have open ports on SBC3's 65SPI and a few ATMega8's I can use as the Slave SPI controller.
Eventually, I would love to be able to have the SPI controller purely an interrupt-driven subsystem integrated into one microcontroller. If the 16-20MHz Atmel devices cannot handle it, purhaps another platform could.
Daryl
Eventually, I would love to be able to have the SPI controller purely an interrupt-driven subsystem integrated into one microcontroller. If the 16-20MHz Atmel devices cannot handle it, purhaps another platform could.
Daryl
The slave process can co-exist on the same device as the slave SPI controller, with only a few restrictions.
The protocol works like this:
Commands (sent from the master):
00 - Null (used to get responses from read requests)
01 - Receive Data from Master
02 - Receive Command from Master
04 - Send Status to Master
05 - Send Data to Master
The master sends the command, waits for the ATM8's 27 cycles (delay loop), then either writes the data or command, or $00 to read the status or data.
The slave's process code passes data to and from the Slave SPI controller via general purpose registers. The only downside is the slave process cannot use interrupts as this would interfere with the Slave SPI controller's response time. Also, a few GP registers need to be dedicated to the slave SPI controller.
I need to test it a little more, but the initial design worked the first time.
More to follow....
Daryl
I have completed testing the code.
This is the code to read the slave's status register:
This same template is used for all 4 commands, just change the null character to a data or command byte for sending.
So, it appears this will give me a pure SPI communications channel with a protocol to pass data reliably.
My next step is to test it with my ATM8 onboard SBC-3, to see if I can control keyboard and RS-232 without the handshake. If that works well, then my IDE/CF system will be next. The last area of my SBC-3 development will be ethernet.
Comments welcome...
Daryl
This is the code to read the slave's status register:
Code: Select all
stat = $FF ; status byte storage
Getstat
lda #$01 ; bit 0 of slave select register
trb SPISSR ; drop ss to select ATM8
lda spidr ; clr 65SPI flags by reading data reg
lda #$04 ; get slave status command
sta spidr
loop1 lda SPISR ; read 65SPI status register
bpl loop1 ; wait for shifting to end
nop ; wait for spi to be ready
nop
nop
nop
lda spidr ; clr flags
lda #$00 ; null character
sta spidr ; initiate second shift seq.
loop2 lda SPISR
bpl loop2 ; wait for shifting to end
lda spidr ; read Slave status byte
sta stat ; save it
lda #$01 ; bit 0 of slave select register
tsb SPISSR ; raise to deselect ATM8 SS
rts
So, it appears this will give me a pure SPI communications channel with a protocol to pass data reliably.
My next step is to test it with my ATM8 onboard SBC-3, to see if I can control keyboard and RS-232 without the handshake. If that works well, then my IDE/CF system will be next. The last area of my SBC-3 development will be ethernet.
Comments welcome...
Daryl
You know, say what you will, but, I still pine for GPIB's protocol. The concept of talkers, listeners, and so forth just made so much more sense. *sigh* Oh well.
My SPI protocol works by adopting a remote memory space model, kind of like how Firewire works. For example, the storage system works by:
TO WRITE A SECTOR:
1. "write" a sector's worth of data into a data buffer in the address space.
2. "write" the sector number into some configuration "registers".
3. "write" a control byte into a control "register" in the address space.
4. Poll by "reading" a status byte, or wait for interrupt from the peripheral.
TO READ A SECTOR:
1. Write the sector into the configuration register.
2. Write a control byte to commence the read.
3. Wait for interrupt or poll status byte.
4. Read the appropriate buffer's worth of data.
My SPI protocol works by adopting a remote memory space model, kind of like how Firewire works. For example, the storage system works by:
TO WRITE A SECTOR:
1. "write" a sector's worth of data into a data buffer in the address space.
2. "write" the sector number into some configuration "registers".
3. "write" a control byte into a control "register" in the address space.
4. Poll by "reading" a status byte, or wait for interrupt from the peripheral.
TO READ A SECTOR:
1. Write the sector into the configuration register.
2. Write a control byte to commence the read.
3. Wait for interrupt or poll status byte.
4. Read the appropriate buffer's worth of data.
- GARTHWILSON
- Forum Moderator
- Posts: 8775
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Shucks Daryl, I thought I resopnded to your second-to-last post, but I see I never sent it. The following doesn't really affect your last one.
----------------------------------
Sounds good, but the commands can probably be more integrated, simplifying transactions. With the few SPI devices I've used, the first byte from the master after it selects the slave is always a command, so you don't have to tell it "The following is a command" (like your 02). After each transaction, you normally start the next one by de-selecting and then re-selecting. What the bytes are after the initial command depends on context; for example, if it were a UART and you're sending data, the data it sends back would probably be the content of the status register, so you get a constant update without asking for it over and over. (In the case of the µC, it would be a few instructions' time behind, which is fine.) If the device were a flash memory and you told it you're going to send a page to store (and tell it where to store it), then after the 1056 bytes or however long the page is for that device, if you don't de-select and re-select to start a new sequence, the next byte would automatically be a command, even though you don't say so.
----------------------------------
Sounds good, but the commands can probably be more integrated, simplifying transactions. With the few SPI devices I've used, the first byte from the master after it selects the slave is always a command, so you don't have to tell it "The following is a command" (like your 02). After each transaction, you normally start the next one by de-selecting and then re-selecting. What the bytes are after the initial command depends on context; for example, if it were a UART and you're sending data, the data it sends back would probably be the content of the status register, so you get a constant update without asking for it over and over. (In the case of the µC, it would be a few instructions' time behind, which is fine.) If the device were a flash memory and you told it you're going to send a page to store (and tell it where to store it), then after the 1056 bytes or however long the page is for that device, if you don't de-select and re-select to start a new sequence, the next byte would automatically be a command, even though you don't say so.
Quote:
Commands (sent from the master):
00 - Null (used to get responses from read requests)
01 - Receive Data from Master
02 - Receive Command from Master
04 - Send Status to Master
05 - Send Data to Master
00 - Null (used to get responses from read requests)
01 - Receive Data from Master
02 - Receive Command from Master
04 - Send Status to Master
05 - Send Data to Master
GARTHWILSON wrote:
...Sounds good, but the commands can probably be more integrated, simplifying transactions. With the few SPI devices I've used, the first byte from the master after it selects the slave is always a command, so you don't have to tell it "The following is a command" (like your 02). After each transaction, you normally start the next one by de-selecting and then re-selecting. What the bytes are after the initial command depends on context; for example, if it were a UART and you're sending data, the data it sends back would probably be the content of the status register, so you get a constant update without asking for it over and over. (In the case of the µC, it would be a few instructions' time behind, which is fine.) If the device were a flash memory and you told it you're going to send a page to store (and tell it where to store it), then after the 1056 bytes or however long the page is for that device, if you don't de-select and re-select to start a new sequence, the next byte would automatically be a command, even though you don't say so.
This added -> The ATMega8 does not provide an interrupt for the slave select pin. Therefore, the Slave Controller has no idea when the SS is lowered or raised, making it's use impractical.
That is the design philosophy behind this approach. Writing or reading a block of data may take longer, but the controller will do what its told indepentent of the slave process. The master and slave process will communicate through the slave controller.
In order to keep my progress on the SBC-3 peripherals moving, I will use this protocol until the code and hardware for a better one is presented. I'm all for better ways, I just don't have time for more experimenting.
Daryl
Daryl
I have spent the last couple days modifying the code used for the onboard ATMega8 on SBC-3 to enable the SPI Slave Controller. The Keyboard code ran perfectly, as did the RS-232 when typing on a terminal program. However, when trying to perform a file transfer, even at 9600 baud, the serial port software could not keep up with the bit stream. Since the serial port driver cannot use Interrupts, as they would cause contention with the SPI controller interrupts, I have decided not to use the SPI controller on the on-board ATM8.
One reason is the ATM8 is doing two functions, interfacing both PC keyboard and the RS-232 port. If it were given just one function, it could possibly handle it better. The other is the continuous polling of the SPI Controller status register is surely taking away processing time form the slave function. Have an extra feedback line (or interrupt) from the slave to the master definitely reduces the demands of the interface.
For instance, I am running a 14.7MHZ ATM8 on my SBC-3 and am able to attain 115200 baud file transfers without any problems. The 8MHz ATM8 using the SPI controller could not keep up with 9600 baud.
I will now focus on implementing the SPI slave controller with my IDE/CF controller. Since this does not require interrupts, it should work without issues. I am interested in the data throughput rates using this platform.
I'll report my progress when its working.
Daryl
One reason is the ATM8 is doing two functions, interfacing both PC keyboard and the RS-232 port. If it were given just one function, it could possibly handle it better. The other is the continuous polling of the SPI Controller status register is surely taking away processing time form the slave function. Have an extra feedback line (or interrupt) from the slave to the master definitely reduces the demands of the interface.
For instance, I am running a 14.7MHZ ATM8 on my SBC-3 and am able to attain 115200 baud file transfers without any problems. The 8MHz ATM8 using the SPI controller could not keep up with 9600 baud.
I will now focus on implementing the SPI slave controller with my IDE/CF controller. Since this does not require interrupts, it should work without issues. I am interested in the data throughput rates using this platform.
I'll report my progress when its working.
Daryl