Revised EC Port 6C Command Protocol: Difference between revisions

From OLPC
Jump to navigation Jump to search
mNo edit summary
(Pretty-printed table of actions in 2 columns. Cleaned up a few bits of wording.)
 
(One intermediate revision by one other user not shown)
Line 11: Line 11:


This protocol is intended to be reliable, predictable, and efficient. Every step is interlocked in a coherent fashion, with no arbitrary delays or unnecessary steps and no unnecessary EC interrupts.
This protocol is intended to be reliable, predictable, and efficient. Every step is interlocked in a coherent fashion, with no arbitrary delays or unnecessary steps and no unnecessary EC interrupts.

The CPU may abandon an in-progress command ''at any time'' by writing a new command byte to port 6c.


It depends on these facts:
It depends on these facts:


* The EC can receive an interrupt when the CPU writes a byte to either port 0x68 or port 0x6c when IBF=0, i.e. on a 0->1 IBF transition. To enable that interrupt, bit 1 of EC register 0xfe9d LPC68CFG must be set.
# The EC can receive an interrupt when the CPU writes a byte to either port 0x68 or port 0x6c when IBF=0, i.e. on a 0→1 IBF transition. To enable that interrupt, bit 1 of EC register 0xfe9d LPC68CFG must be set.
# The EC can receive an interrupt when the CPU read a byte from port 0x68 when OBF=1, i.e. on a 1→0 OBF transition. To enable that interrupt, bit 0 of EC register 0xfe9d LPC68CFG must be set. (The protocol enables the OBF interrupt only as needed, during intermediate stages of multi-byte commands.)

# The EC can distinguish between a write to port 0x68 and a write to port 0x6c, via bit 6 of EC register 0xfe9e LPC68CSR.
* The EC can receive an interrupt when the CPU read a byte from port 0x68 when OBF=1, i.e. on a 1->0 OBF transition. To enable that interrupt, bit 0 of EC register 0xfe9d LPC68CFG must be set. (The protocol enables the OBF interrupt only as needed, during intermediate stages of multi-byte commands.)

* The EC can distinguish between a write to port 0x68 and a write to port 0x6c, via bit 6 of EC register 0xfe9e LPC68CSR.


The protocol is as follows:
The protocol is as follows:
{| style="margin: 1em 1em 1em 0; background: #f9f9f9; border: 1px #aaa solid; border-collapse: collapse;"

! CPU Actions || EC Actions
Starting from a quiescent state, where IBF=0 and OBF=0:
|-

- The EC idle state is "IBF interrupt enabled, OBF interrupt disabled, IBF=0, OBF=0"
| Starting from a quiescent state, where IBF=0 and OBF=0
| The EC idle state is "IBF interrupt enabled, OBF interrupt disabled, IBF=0, OBF=0"

|-
C1: CPU waits until IBF=0, then sends the command by writing it to port 0x6c.
|

'''C1:''' CPU waits until IBF=0, then sends the command by writing it to port 0x6c.
E1: EC receives IBF interrupt, checks register 0xfe9e bit 6 and observes that it
|
was 1, hence a new command.
|-

| ||
E2: EC cancels any previous commands by setting its state variables
'''E1''': EC receives IBF interrupt, checks register 0xfe9e bit 6 and observes that it
to "new command" state.
was 1, hence a new command. (If the bit is 0, this is a data byte; proceed to step E8.)

|-
E3: If OBF=1, EC clears it by writing 0x01 to reg 0xfe9e. This is the
| ||
crucial interlock that makes the protocol predictable - this must
'''E2:''' EC cancels any previous commands by setting its state variables
be done prior to clearing IBF in a later step. This step discards
to "new command" state.
any residue from incomplete earlier commands, and step E2 cancels
|-
any tendency for earlier command to continue generating data.
| ||

E4: EC reads the command byte from reg 0xfe9f, clears IBF by writing 2
'''E3:''' If OBF=1, EC clears it by writing 0x01 to reg 0xfe9e. This is the
crucial interlock that makes the protocol predictable - this must
to reg 0xfe9e, decodes the command, and sets a state variable accordingly.
be done prior to clearing IBF in a later step. This step discards

any residue from incomplete earlier commands, and step E2 has canceled
E5a: If the next step of the command is to send data to the CPU and
any tendency for earlier command to continue generating data.
there are no more steps after that, EC disables the OBF interrupt,
|-
puts the data byte in the data register, sets state to "idle",
| ||
and returns from the protocol handler.
'''E4:''' EC reads the command byte from reg 0xfe9f, clears IBF by writing 2

E5b: If the next step of the command is to send data to the CPU and
to reg 0xfe9e, decodes the command, and sets a state variable accordingly.
|-
there are more steps after that, EC enables the OBF interrupt, puts
| ||
the first data byte in the data register, and returns from the
protocol handler. (When the CPU later reads the byte, the EC will
'''E5a:''' If the next step of the command is to send data to the CPU and
there are no more steps after that, EC disables the OBF interrupt,
receive the OBF interrupt as described in E7.)
puts the data byte in the data register, sets state to "idle",

and returns from the protocol handler.
E5c: If the next step of the command is to receive data from the
|-
CPU, EC disables the OBF interrupt, and returns from the protocol
| ||
handler. (When the CPU later writes the byte to the data register,
'''E5b:''' If the next step of the command is to send data to the CPU and
the EC will perform step E8.)
there are more steps after that, EC enables the OBF interrupt, puts
E5d: If there is no more data to be sent or received, the EC
the first data byte in the data register, and returns from the
protocol handler. (When the CPU later reads the byte, the EC will
disables OBF interrupt, sets state to idle, and returns from the
receive the OBF interrupt as described in E7.)
protocol handler.
|-

| ||
C2: If the next stage of the command is an EC-to-CPU data byte, the CPU
'''E5c:''' If the next step of the command is to receive data from the
CPU, EC disables the OBF interrupt, and returns from the protocol
handler. (When the CPU later writes the byte to the data register,
the EC will perform step E8.)
|-
| ||
'''E5d:''' If there is no more data to be sent or received, the EC
disables OBF interrupt, sets state to idle, and returns from the
protocol handler.
|-
|
'''C2:''' If the next stage of the command is an EC-to-CPU data byte, the CPU
polls port 0x6c until IBF,OBF=0,1, then reads the data byte from port 0x68.
polls port 0x6c until IBF,OBF=0,1, then reads the data byte from port 0x68.
IBF must be included in the test, since it makes the E3 interlock work.
IBF must be included in the test, since it makes the E3 interlock work.
Line 69: Line 81:
drive OBF to 0 while IBF is still 1, so the IBF,OBF=0,1 test will not
drive OBF to 0 while IBF is still 1, so the IBF,OBF=0,1 test will not
succeed until the EC reaches step E5a or E5b.
succeed until the EC reaches step E5a or E5b.
|

|-
E6: If that byte was the last thing in the command sequence, the EC
| ||
will not receive an OBF interrupt because step E5a disabled the
'''E6:''' If that byte was the last thing in the command sequence, the EC
interrupt. The EC is already back in idle state, so it does not
will not receive an OBF interrupt because step E5a disabled the
need notification that the CPU read the byte.
interrupt. The EC is already back in idle state, so it does not

need notification that the CPU read the byte.
E7: If there are more bytes after this to send or receive, the EC
|-
will receive an OBF interrupt (because of step E5b) and go to step
| ||
E5 to continue processing the command.
'''E7:''' If there are more bytes after this to send or receive, the EC

will receive an OBF interrupt (because of step E5b) and go to step
C3: If the next stage of the command is a CPU-to-EC data byte, the CPU
E5 to continue processing the command.
|-
|
'''C3:''' If the next stage of the command is a CPU-to-EC data byte, the CPU
polls port 6c until IBF=0, then writes the data byte to port 0x68.
polls port 6c until IBF=0, then writes the data byte to port 0x68.
|

|-
E8: When the CPU writes the byte to the data register, the EC will
| ||
receive the IBF interrupt and notice (via reg 0xfe9e bit 6 = 0) that
the write was to the data register. The EC then reads the byte from
'''E8:''' When the CPU writes the byte to the data register, the EC will
reg 0xfe9f, clears IBF by writing 2 to reg 0xfe9e, handles the byte
receive the IBF interrupt and notice (via reg 0xfe9e bit 6 = 0) that
according to the command sematics, and goes to step E5 to continue
the write was to the data register. The EC then reads the byte from
reg 0xfe9f, clears IBF by writing 2 to reg 0xfe9e, handles the byte
processing the command.
according to the command semantics, and goes to step E5 to continue

processing the command.
|}
Note that there is no need for arbitrary delays.
Note that there is no need for arbitrary delays.


Line 102: Line 120:
[[Category:developers]]
[[Category:developers]]
[[Category:Firmware]]
[[Category:Firmware]]
[[Category:EC]]

Latest revision as of 08:13, 8 January 2011

This is a replacement for an EC command protocol that was giving us problems.

see Ec_specification#Old_Port_6c_Command_Protocol

The objective is to transmit information back and forth between the CPU and the embedded controller (EC), via CPU I/O ports 0x68 and 0x6c. This protocol can support:

  • Commands with no data transfer
  • Commands that return data from the EC to the CPU
  • Commands that send data from the CPU to the EC
  • Commands that send data in both directions

This protocol is intended to be reliable, predictable, and efficient. Every step is interlocked in a coherent fashion, with no arbitrary delays or unnecessary steps and no unnecessary EC interrupts.

The CPU may abandon an in-progress command at any time by writing a new command byte to port 6c.

It depends on these facts:

  1. The EC can receive an interrupt when the CPU writes a byte to either port 0x68 or port 0x6c when IBF=0, i.e. on a 0→1 IBF transition. To enable that interrupt, bit 1 of EC register 0xfe9d LPC68CFG must be set.
  2. The EC can receive an interrupt when the CPU read a byte from port 0x68 when OBF=1, i.e. on a 1→0 OBF transition. To enable that interrupt, bit 0 of EC register 0xfe9d LPC68CFG must be set. (The protocol enables the OBF interrupt only as needed, during intermediate stages of multi-byte commands.)
  3. The EC can distinguish between a write to port 0x68 and a write to port 0x6c, via bit 6 of EC register 0xfe9e LPC68CSR.

The protocol is as follows:

CPU Actions EC Actions
Starting from a quiescent state, where IBF=0 and OBF=0 The EC idle state is "IBF interrupt enabled, OBF interrupt disabled, IBF=0, OBF=0"

C1: CPU waits until IBF=0, then sends the command by writing it to port 0x6c.

E1: EC receives IBF interrupt, checks register 0xfe9e bit 6 and observes that it was 1, hence a new command. (If the bit is 0, this is a data byte; proceed to step E8.)

E2: EC cancels any previous commands by setting its state variables to "new command" state.

E3: If OBF=1, EC clears it by writing 0x01 to reg 0xfe9e. This is the crucial interlock that makes the protocol predictable - this must be done prior to clearing IBF in a later step. This step discards any residue from incomplete earlier commands, and step E2 has canceled any tendency for earlier command to continue generating data.

E4: EC reads the command byte from reg 0xfe9f, clears IBF by writing 2 to reg 0xfe9e, decodes the command, and sets a state variable accordingly.

E5a: If the next step of the command is to send data to the CPU and there are no more steps after that, EC disables the OBF interrupt, puts the data byte in the data register, sets state to "idle", and returns from the protocol handler.

E5b: If the next step of the command is to send data to the CPU and there are more steps after that, EC enables the OBF interrupt, puts the first data byte in the data register, and returns from the protocol handler. (When the CPU later reads the byte, the EC will receive the OBF interrupt as described in E7.)

E5c: If the next step of the command is to receive data from the CPU, EC disables the OBF interrupt, and returns from the protocol handler. (When the CPU later writes the byte to the data register, the EC will perform step E8.)

E5d: If there is no more data to be sent or received, the EC disables OBF interrupt, sets state to idle, and returns from the protocol handler.

C2: If the next stage of the command is an EC-to-CPU data byte, the CPU polls port 0x6c until IBF,OBF=0,1, then reads the data byte from port 0x68. IBF must be included in the test, since it makes the E3 interlock work. If there is leftover data that causes OBF to start out as 1, step E3 will drive OBF to 0 while IBF is still 1, so the IBF,OBF=0,1 test will not succeed until the EC reaches step E5a or E5b.

E6: If that byte was the last thing in the command sequence, the EC will not receive an OBF interrupt because step E5a disabled the interrupt. The EC is already back in idle state, so it does not need notification that the CPU read the byte.

E7: If there are more bytes after this to send or receive, the EC will receive an OBF interrupt (because of step E5b) and go to step E5 to continue processing the command.

C3: If the next stage of the command is a CPU-to-EC data byte, the CPU polls port 6c until IBF=0, then writes the data byte to port 0x68.

E8: When the CPU writes the byte to the data register, the EC will receive the IBF interrupt and notice (via reg 0xfe9e bit 6 = 0) that the write was to the data register. The EC then reads the byte from reg 0xfe9f, clears IBF by writing 2 to reg 0xfe9e, handles the byte according to the command semantics, and goes to step E5 to continue processing the command.

Note that there is no need for arbitrary delays.

Note: The above description of the EC behavior assumes that, if another IBF or OBF interrupt occurs while the EC is processing the steps E1..E8, the handling of that interrupt will be deferred until the end of step E5x where it "returns from the protocol handler". The new interrupt will neither cause premature re-entry to the protocol handler code (E1..E8), nor be lost. If that is not the case, some additional complexity may be necessary.