Generic bus interface.
More...
#include </home/travis/build/forGGe/theCore/dev/bus/export/dev/bus.hpp>
template<class PBus>
class ecl::generic_bus< PBus >
Generic bus interface.
The generic bus is useful adapter, that allows to:
- Encapsulate locking policy when multithreaded environment is used.
- Hide differences between full-duplex and half-duplex busses.
- Define and simplify platform-level bus interface
- Template Parameters
-
PBus | Platform-level bus driver (I2C, SPI, etc.) |
This class uses one of methods to prevent “static initialization order fiasco” to handle initialization of the static members. See https://isocpp.org/wiki/faq/ctors
◆ platform_handle
Exported platform bus type.
◆ generic_bus()
Construction is not allowed.
◆ ~generic_bus()
◆ init()
Inits a bus.
Lazy initialization. Inits an underlying platform bus.
- Todo:
- introduce init counter.
- Returns
- Status of operation.
◆ deinit()
De-inits a bus.
- Precondition
- Bus is initied.
- Todo:
- use init counter to measure how many users are inited this bus.
- Returns
- Status of operation.
◆ lock()
Locks a bus.
Any further operations can be executed after call to this function. If previous async xfer is in progress then current thread will be blocked until its finish.
- Precondition
- Bus is inited successfully.
- Postcondition
- Bus is locked.
- See also
- unlock()
◆ unlock()
Unlocks a bus.
Any operations beside lock() is not permitted after this method finishes.
- Side effects:
- In block mode all buffers provided with set_buffers() will be discarded
- In async mode if operation still ongoing, buffers will be discarded after operation will finish.
- Precondition
- Bus is locked.
- Postcondition
- Bus is unlocked.
- See also
- set_buffers()
◆ set_buffers() [1/3]
Sets RX and TX buffers and their sizes.
If only TX or RX transaction required, then only one buffer must be passed. All effects from calls to set_buffers() will be discarded. This API is convenient analog if both buffers are equal in size.
- Side effects:
-
- Precondition
- Bus is locked.
- Postcondition
- Bus is ready to execute xfer.
- Parameters
-
[in] | tx | Data to transmit. If this param is null, then rx must be set. |
[in] | rx | Buffer to receive a data. Optional. If this param is null, then tx must be set. |
[in] | size | Size of buffers. Zero is valid size. |
- Return values
-
◆ set_buffers() [2/3]
Sets RX and TX buffers and their sizes.
If only TX or RX transaction required, then only one buffer must be passed. All effects from calls to set_buffers() will be discarded.
- Side effects:
-
- Precondition
- Bus is locked.
- Postcondition
- Bus is ready to execute xfer.
- Parameters
-
[in] | tx | Data to transmit. If this param is null, then rx must be set. |
[in] | rx | Buffer to receive a data. Optional. If this param is null, then tx must be set. |
[in] | tx_size | Size of TX buffer. Zero is valid size. |
[in] | rx_size | Size of RX buffer. Zero is valid size. |
- Return values
-
◆ set_buffers() [3/3]
Sets TX buffer size and fills it with given byte.
This will instruct a platform bus to send a byte given number of times. It is implementation defined how platform-level bus handles incoming data, e.g. it can be splitted into chunks when sending to the destination, if platform bus protocol allows such thing.
In half-duplex case RX will not be performed. If platform bus is in full duplex mode then RX will be executed but RX data will be ignored.
- Side effects
-
- Precondition
- Bus is locked.
- Postcondition
- Bus is ready to execute xfer.
- Parameters
-
[in] | size | Size of filled buffer. |
[in] | fill_byte | Byte which will be sent in TX stream. |
- Return values
-
err::ok | Buffer successfully set and filled. |
err::busy | Device is still executing async xfer. |
◆ xfer() [1/2]
template<class PBus >
ecl::err ecl::generic_bus< PBus >::xfer |
( |
size_t * |
sent = nullptr , |
|
|
size_t * |
received = nullptr , |
|
|
std::chrono::milliseconds |
timeout = std::chrono::milliseconds::max() |
|
) |
| |
|
static |
Performs xfer in blocking mode using buffers set previously with optional timeout.
If underlying bus works in half-duplex mode then first tx transaction will occur and then rx. Any deferred xfer will be canceled in result of this call and simple, blocking xfer will proceed.
- Warning
- Method uses a semaphore to wait for a bus event (most likely an IRQ event). It means that in bare-metal environment, without RTOS it is implemented as simple spin-lock. Likely that such behavior is unwanted. In order to control event handling, consider using xfer(const handler_fn &handler) overload.
- Precondition
- Bus is locked and buffers are set.
- Postcondition
- Bus remains in the same state.
- Parameters
-
[out] | sent | Optional. Bytes sent during this xfer. |
[out] | received | Optional. Bytes received during this xfer. |
[in] | timeout | Optional. Timeout to wait for operation to complete. |
- Return values
-
err::ok | Data is sent successfully. |
err::busy | Device is still executing async xfer. |
err::io | Transaction started but failed. |
err::timedout | Operation was not completed before timeout hit. |
err | Any other error that can occur in platform bus |
◆ xfer() [2/2]
Performs xfer in async mode using buffers set previously.
If underlying bus works in half-duplex mode then first tx transaction will occur and then rx. When xfer will be done, given handler will be invoked with a type of an event.
It is also possible to postpone xfer, i.e. "defer" it and then trigger at will using xfer_trigger() method. See xfer_trigger() for more defails. Any previous deferred xfer will be canceled in result of this call.
- Warning
- Event handler most likely will be executed in ISR context. Pay attention to it. Do not block inside of it or do anything else that can break ISR or impose high interrupt latency.
- Note
- Bytes transferred are reported via user-supplied handler per each channel (tx, rx) separately.
-
Errors that occur after transaction has started are reported via user-supplied handler.
- See also
- PBus::event
- Precondition
- Bus is locked and buffers are set.
- Postcondition
- Bus remains in the same state.
- Parameters
-
[in] | handler | User-supplied event handler. |
[in] | type | Type of xfer. Possible values are:
|
- Return values
-
err::ok | Data is sent successfully. |
err::busy | Device is still executing async xfer. |
err | Any other error that can occur in platform bus. |
◆ trigger_xfer()
Triggers continued or deferred xfer in async mode.
Method is capable of triggering two types of xfers:
- Continuated: triggers a new xfer with the same buffers and handlers that were used during last xfer.
- Deferred: triggers the scheduled xfer, such that was defer using xfer() call.
This method is a kind of a important optimization trick. It is possible to call it from IRQ context. It uses buffers and handlers from previous xfers, so there is no overhead for unneeded assignments.
- Precondition
- Bus is locked, buffers are set and async xfer is either deferred or executed.
- Postcondition
- Xfer is ongoing.
◆ cancel_xfer()
Cancels xfer.
Capable of cancelling any previously started or scheduled xfer. Keeps buffer and callback configured. Callable from ISR context.
- Precondition
- Bus locked, xfer started or scheduled. If bus is unlocked, behaviour is undefined.
- Todo:
- Decide how platform bus should behave if cancel_xfer() called from ISR. Is platform bus should generate 'transfer complete' event?
- Postcondition
- Xfer canceled, but buffers is not touched. Note that xfer can be ongoing or even completed during this call.
The documentation for this class was generated from the following file: