theCore C++ embedded framework
ecl::generic_bus< PBus > Class Template Reference

Generic bus interface. More...

#include </home/travis/build/forGGe/theCore/dev/bus/export/dev/bus.hpp>

Public Types

using platform_handle = PBus
 Exported platform bus type. More...
 

Public Member Functions

 generic_bus ()=delete
 Construction is not allowed. More...
 
 ~generic_bus ()=delete
 

Static Public Member Functions

static err init ()
 Inits a bus. More...
 
static err deinit ()
 De-inits a bus. More...
 
static void lock ()
 Locks a bus. More...
 
static void unlock ()
 Unlocks a bus. More...
 
static err set_buffers (const uint8_t *tx, uint8_t *rx, size_t size)
 Sets RX and TX buffers and their sizes. More...
 
static err set_buffers (const uint8_t *tx, uint8_t *rx, size_t tx_size, size_t rx_size)
 Sets RX and TX buffers and their sizes. More...
 
static err set_buffers (size_t size, uint8_t fill_byte=0xff)
 Sets TX buffer size and fills it with given byte. More...
 
static err xfer (size_t *sent=nullptr, size_t *received=nullptr, std::chrono::milliseconds timeout=std::chrono::milliseconds::max())
 Performs xfer in blocking mode using buffers set previously with optional timeout. More...
 
static err xfer (const bus_handler &handler, async_type type=async_type::immediate)
 Performs xfer in async mode using buffers set previously. More...
 
static err trigger_xfer ()
 Triggers continued or deferred xfer in async mode. More...
 
static err cancel_xfer ()
 Cancels xfer. More...
 

Detailed Description

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
    PBusPlatform-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

Member Typedef Documentation

◆ platform_handle

template<class PBus >
using ecl::generic_bus< PBus >::platform_handle = PBus

Exported platform bus type.

Constructor & Destructor Documentation

◆ generic_bus()

template<class PBus >
ecl::generic_bus< PBus >::generic_bus ( )
delete

Construction is not allowed.

◆ ~generic_bus()

template<class PBus >
ecl::generic_bus< PBus >::~generic_bus ( )
delete

Member Function Documentation

◆ init()

template<class PBus >
err ecl::generic_bus< PBus >::init ( )
static

Inits a bus.

Lazy initialization. Inits an underlying platform bus.

Todo:
introduce init counter.
Returns
Status of operation.
Here is the call graph for this function:

◆ deinit()

template<class PBus >
err ecl::generic_bus< PBus >::deinit ( )
static

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()

template<class PBus >
void ecl::generic_bus< PBus >::lock ( )
static

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()

template<class PBus >
void ecl::generic_bus< PBus >::unlock ( )
static

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]

template<class PBus >
ecl::err ecl::generic_bus< PBus >::set_buffers ( const uint8_t *  tx,
uint8_t *  rx,
size_t  size 
)
static

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]txData to transmit. If this param is null, then rx must be set.
[in]rxBuffer to receive a data. Optional. If this param is null, then tx must be set.
[in]sizeSize of buffers. Zero is valid size.
Return values
err::okBuffers successfully set.
err::invalBoth buffers are null.
err::busyDevice is still executing async xfer.

◆ set_buffers() [2/3]

template<class PBus >
ecl::err ecl::generic_bus< PBus >::set_buffers ( const uint8_t *  tx,
uint8_t *  rx,
size_t  tx_size,
size_t  rx_size 
)
static

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]txData to transmit. If this param is null, then rx must be set.
[in]rxBuffer to receive a data. Optional. If this param is null, then tx must be set.
[in]tx_sizeSize of TX buffer. Zero is valid size.
[in]rx_sizeSize of RX buffer. Zero is valid size.
Return values
err::okBuffers successfully set.
err::invalBoth buffers are null.
err::busyDevice is still executing async xfer.

◆ set_buffers() [3/3]

template<class PBus >
ecl::err ecl::generic_bus< PBus >::set_buffers ( size_t  size,
uint8_t  fill_byte = 0xff 
)
static

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]sizeSize of filled buffer.
[in]fill_byteByte which will be sent in TX stream.
Return values
err::okBuffer successfully set and filled.
err::busyDevice 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]sentOptional. Bytes sent during this xfer.
[out]receivedOptional. Bytes received during this xfer.
[in]timeoutOptional. Timeout to wait for operation to complete.
Return values
err::okData is sent successfully.
err::busyDevice is still executing async xfer.
err::ioTransaction started but failed.
err::timedoutOperation was not completed before timeout hit.
errAny other error that can occur in platform bus
Here is the call graph for this function:

◆ xfer() [2/2]

template<class PBus >
ecl::err ecl::generic_bus< PBus >::xfer ( const bus_handler handler,
async_type  type = async_type::immediate 
)
static

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]handlerUser-supplied event handler.
[in]typeType of xfer. Possible values are:
Return values
err::okData is sent successfully.
err::busyDevice is still executing async xfer.
errAny other error that can occur in platform bus.

◆ trigger_xfer()

template<class PBus >
ecl::err ecl::generic_bus< PBus >::trigger_xfer ( )
static

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.
Here is the call graph for this function:

◆ cancel_xfer()

template<class PBus >
ecl::err ecl::generic_bus< PBus >::cancel_xfer ( )
static

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.
Here is the call graph for this function:

The documentation for this class was generated from the following file: