1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-11-30 08:24:11 +01:00
LibrePilot/flight/Doc/Architecture/stm32_i2c_fsm.dot

173 lines
5.2 KiB
Plaintext
Raw Normal View History

i2c: rewrite i2c layer The STM32 I2C block has a number of errata associated with it. These errata are primarily related to timing sensitivities between the peripheral and the interrupt handler. In particular, the correct generation of the stop bit relies on the I2C IRQ running immediately and not being held off for any reason. NOTE: The I2C interrupts must be the highest priority IRQs in the system to ensure correct operation. I2C protocol is now implemented as a formal state machine. See: stm32_i2c_fsm.{dot,jpg} for FSM description. I2C init is now expressed by const initializers in pios_board.c for both OP and AHRS boards. I2C device drivers (ie. bmp085/hmc5843) now pass in const arrays of an unlimited number of bus transfers to be done atomically. The I2C adapter driver now handles all bus-level locking across the list of transactions. Generation of start/restart/stop conditions are handled automatically over the list of transactions. Timeouts have been removed from the API for now. May be added back later. This driver has run error free on both the OP and AHRS boards for up to 48hrs but it still sometimes fails earlier than that on the OP board. There is another possible set of improvements to the driver that could employ the DMA engine for transfers of >= 2bytes. This change would reduce the timing sensitivities between the peripheral and the driver but unfortunately, both the SPI and I2C interfaces share the DMA1 engine. That means only one of these two peripherals can use the DMA engine and right now, SPI between OP and AHRS is already using it. Failures are currently fatal and will lock up the CPU. This allows useful information to be obtained in the failure cases. git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@1241 ebee16cc-31ac-478f-84a7-5cbb03baadba
2010-08-08 06:15:08 +02:00
// Regenerate using graphviz/dotty with this command
// dot -Tjpg ./flight/Doc/Architecture/stm32_i2c_fsm.dot > ./flight/Doc/Architecture/stm32_i2c_fsm.jpg
digraph stm32_i2c_fsm {
label="STM32 I2C FSM"
labelloc=t
labeljust = l
{
node [ style=filled,color=lightgray ]
stopped [ shape="doublecircle" ]
}
node [ style=filled,color=blue ]
{
rank=same
stopped
stopping
starting
}
// start addr/w[A] data[A] stop
// SB ADDR BTF
// ADDR DR
// STOP
//
// start addr/w[A] data[A] data[A] stop
// SB ADDR BTF BTF
// ADDR DR DR
// STOP
//
// start addr/w[A] data[A] data[A] data[A] stop
// SB ADDR BTF BTF BTF
// ADDR DR DR DR
// STOP
//
subgraph cluster_w_last_txn {
label="Final Write Txn"
w_last_txn_addr
w_last_txn_middle
w_last_txn_last
}
// start addr/w[A] data[A] start
// SB ADDR BTF
// ADDR DR
// START
//
// start addr/w[A] data[A] data[A] start
// SB ADDR BTF BTF
// ADDR DR DR
// START
//
// start addr/w[A] data[A] data[A] data[A] stop
// SB ADDR BTF BTF BTF
// ADDR DR DR DR
// START
//
subgraph cluster_w_more_txn {
label="Write Txn with Restart"
w_more_txn_addr
w_more_txn_middle
w_more_txn_last
}
// start addr/r[A] [data] N stop
// SB ADDR RXNE
// ADDR STOP DR
// NAK
//
// start addr/r[A] [data] A [data] N stop
// SB ADDR RXNE RXNE
// ADDR DR DR
// ACK NAK
// STOP
//
// start addr/r[A] [data] A [data] A [data] N stop
// SB ADDR RXNE RXNE RXNE
// ADDR DR DR DR
// ACK ACK NAK
// STOP
//
subgraph cluster_r_last_txn {
label="Final Read Txn"
r_last_txn_addr
r_last_txn_pre_one
r_last_txn_pre_first
r_last_txn_pre_middle
r_last_txn_pre_last
r_last_txn_post_last
}
// start addr/r[A] [data] N start
// SB ADDR RXNE
// ADDR START DR
// NAK
//
// start addr/r[A] [data] A [data] N start
// SB ADDR RXNE RXNE
// ADDR DR DR
// ACK NAK
// START
//
// start addr/r[A] [data] A [data] A [data] N start
// SB ADDR RXNE RXNE RXNE
// ADDR DR DR DR
// ACK ACK NAK
// START
subgraph cluster_r_more_txn {
label="Read Txn with Restart"
r_more_txn_addr
r_more_txn_pre_one
r_more_txn_pre_first
r_more_txn_pre_middle
r_more_txn_pre_last
r_more_txn_post_last
}
stopping -> stopped [ label="auto" ]
stopped -> starting [ label="start" ]
starting -> w_last_txn_addr [ label="SB\nop=write\nlast txn" ]
starting -> w_more_txn_addr [ label="SB\nop=write\nmore txn" ]
starting -> r_last_txn_addr [ label="SB\nop=read\nlast txn" ]
starting -> r_more_txn_addr [ label="SB\nop=read\nmore txn" ]
w_last_txn_addr -> w_last_txn_last [ label="ADDR\nlen==1" ]
w_more_txn_addr -> w_more_txn_last [ label="ADDR\nlen==1" ]
w_last_txn_addr -> w_last_txn_middle [ label="ADDR\nlen>1" ]
w_more_txn_addr -> w_more_txn_middle [ label="ADDR\nlen>1" ]
w_last_txn_middle -> w_last_txn_middle [ label="BTF\nlen>1" ]
w_more_txn_middle -> w_more_txn_middle [ label="BTF\nlen>1" ]
w_last_txn_middle -> w_last_txn_last [ label="BTF\nlen==1" ]
w_more_txn_middle -> w_more_txn_last [ label="BTF\nlen==1" ]
w_last_txn_last -> stopped [ label="BTF\nlen==0" ]
w_more_txn_last -> starting [ label="BTF\nlen==0" ]
r_last_txn_addr -> r_last_txn_pre_one [ label="ADDR\nlen==1" ]
r_more_txn_addr -> r_more_txn_pre_one [ label="ADDR\nlen==1" ]
r_last_txn_addr -> r_last_txn_pre_first [ label="ADDR\nlen>=2" ]
r_more_txn_addr -> r_more_txn_pre_first [ label="ADDR\nlen>=2" ]
i2c: rewrite i2c layer The STM32 I2C block has a number of errata associated with it. These errata are primarily related to timing sensitivities between the peripheral and the interrupt handler. In particular, the correct generation of the stop bit relies on the I2C IRQ running immediately and not being held off for any reason. NOTE: The I2C interrupts must be the highest priority IRQs in the system to ensure correct operation. I2C protocol is now implemented as a formal state machine. See: stm32_i2c_fsm.{dot,jpg} for FSM description. I2C init is now expressed by const initializers in pios_board.c for both OP and AHRS boards. I2C device drivers (ie. bmp085/hmc5843) now pass in const arrays of an unlimited number of bus transfers to be done atomically. The I2C adapter driver now handles all bus-level locking across the list of transactions. Generation of start/restart/stop conditions are handled automatically over the list of transactions. Timeouts have been removed from the API for now. May be added back later. This driver has run error free on both the OP and AHRS boards for up to 48hrs but it still sometimes fails earlier than that on the OP board. There is another possible set of improvements to the driver that could employ the DMA engine for transfers of >= 2bytes. This change would reduce the timing sensitivities between the peripheral and the driver but unfortunately, both the SPI and I2C interfaces share the DMA1 engine. That means only one of these two peripherals can use the DMA engine and right now, SPI between OP and AHRS is already using it. Failures are currently fatal and will lock up the CPU. This allows useful information to be obtained in the failure cases. git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@1241 ebee16cc-31ac-478f-84a7-5cbb03baadba
2010-08-08 06:15:08 +02:00
r_last_txn_pre_one -> r_last_txn_post_last [ label="BTF\nlen==1" ]
r_more_txn_pre_one -> r_more_txn_post_last [ label="BTF\nlen==1" ]
r_last_txn_pre_first -> r_last_txn_pre_last [ label="BTF\nlen==2" ]
r_more_txn_pre_first -> r_more_txn_pre_last [ label="BTF\nlen==2" ]
r_last_txn_pre_first -> r_last_txn_pre_middle [ label="BTF\nlen>2" ]
r_more_txn_pre_first -> r_more_txn_pre_middle [ label="BTF\nlen>2" ]
r_last_txn_pre_middle -> r_last_txn_pre_middle [ label="BTF\nlen>2" ]
r_more_txn_pre_middle -> r_more_txn_pre_middle [ label="BTF\nlen>2" ]
r_last_txn_pre_middle -> r_last_txn_pre_last [ label="BTF\nlen==2" ]
r_more_txn_pre_middle -> r_more_txn_pre_last [ label="BTF\nlen==2" ]
r_last_txn_pre_last -> r_last_txn_post_last [ label="BTF\nlen==1" ]
r_more_txn_pre_last -> r_more_txn_post_last [ label="BTF\nlen==1" ]
r_last_txn_post_last -> stopping [ label="auto" ]
r_more_txn_post_last -> starting [ label="auto" ]
}