Skip to content
Snippets Groups Projects
Commit 650b842f authored by Sergi Hernandez's avatar Sergi Hernandez
Browse files

Added diagrams of the possible communication transactions.

Documented more functions and the main communications structure.
parent c5d664c2
No related branches found
No related tags found
No related merge requests found
comm/doc/images/rx_dma_driven.png

52 KiB

comm/doc/images/rx_irq_driven.png

50.9 KiB

comm/doc/images/tx_dma_driven.png

69.3 KiB

comm/doc/images/tx_irq_driven.png

52 KiB

......@@ -18,8 +18,68 @@ typedef enum {COMM_SUCCESS=0x00,/*!< The communication module has ended successf
} comm_error;
/**
* \brief
* \brief Generic communication device structure
*
* This structure implements a generic interface to a communication device in three
* different modes: blocking, interrupt driven and DMA driven.
*
* It is intended to be the intermediate structure between a user application
* that requires access to a communication device, and the actual communication
* device.
*
* On the communication device side, a set of functions must be implemented and
* assigned to this structure at initialization time. Furthermore, the module
* implementing this functions should implement the following features:
* * Configure the hardware to operate as desired.
* * Configure the interrupts and their priorities.
* * Configure the DMA transactions (in case they are enabled).
* * Implement the functions required by this structure to initiate and cancel
* RX and TX transactions using both IRQ and DMA.
* * Implement the basic IRQ and DMa handler functions.
*
* On the user application side, another set of functions must be also implemented
* and assigned to this structure at initialization time. The user application
* should be in charge of initializing this structure and any other data structure
* required.
*
* In blocking mode, the IRQ driven transactions are used except when the use of
* DMA is enbaled, in which case the DMA driven transactions are used.
*
* The following diagram descrives the transmission operation when using
* interrupts, and how the user application, the communication module and the
* actual communication device work together:
*
* ![](tx_irq_driven.png)
*
* The user application starts a TX driven transmission by calling the comm_send_irq()
* function, which in turn calls the low level communication function pointed by
* the parameter send_irq. At this point the interrupt handler is called each time
* a byte is actually sent, which calls the comm_do_irq_send() function to update
* the internal state and, in turn, calls the user callback function pointed by
* irq_send_cb.
*
* While the data transfer is in progress the user can call the comm_is_send_done()
* function to check the status of the transmission and the comm_get_error()
* function to check for errors (if any). This functions can be used with any kind
* of non-blobking transactions (IRQ and DMA).
*
* The following diagram descrives the reception operation when using
* interrupts, and how the user application, the communication module and the
* actual communication device work together:
*
* ![](rx_irq_driven.png)
*
* The reception is only enabled when the user application calls the comm_receive_irq()
* function, all data received before this function is called will be lost. This
* function calls the low level communication function pointed by the parameter
* receive_irq.
*
* At this point the interrupt handler is called each time a byte is received, which
* calls the comm_do_irq_receive() function to update the internal state and, in
* turn, calls the user callback function pointed by irq_receive_cb. The reception
* remains active until the desired number of bytes are received, or the user
* application cancels it.
*
*/
typedef struct
{
......@@ -92,8 +152,11 @@ typedef struct
*/
unsigned char use_dma;
/**
* \brief
* \brief DMA termination flag
*
* This parameter is used in the comm_do_irq_send() function to indicate whether
* the interrupt is generated by the last transmitted byte of a DMA transaction
* or not.
*/
unsigned char dma_waiting_buffer_empty;
/**
......@@ -104,173 +167,342 @@ typedef struct
*/
unsigned char error;
/**
* \brief
* \brief Time structure to handle timeouts
*
* This parameter is used to handle reception timeouts to avoid that the reception
* functions get blocked due to missing bytes or communication errors.
*/
TTime *time;
/**
* \brief
* \brief pointer to a user data structure
*
* This parameter is used to store a user data structure which is passed as a
* parameter to the user callback functions (irq_send_cb(),irq_receive_cb(),
* dma_send_cb() and dma_receive_cb()).
*/
void *data;
/* IRQ functions */
/**
* \defgroup harware_irq_pointers Hardware IRQ related function pointeris
*
* This set of functions, that must be implemented by the low level hardware
* communication module (either USART, I2C, SPI or any other communication
* device), are intended to handle interrupt driven receptions and transmissions.
*
* This function pointers must be assigned by the initialization function
* of the communication module.
*
*/
/**@{*/
/**
* \brief
* \brief Pointer to a function to start a transmission using interrupts
*
* This function should send the first byte through the communication device,
* clear any pending interrupt transmission complete flag and enable this
* interrupt in order to send the remaining of the data.
*/
unsigned char (*send_irq)(unsigned char first_byte);
/**
* \brief
* \brief Pointer to a function to enable the transmission interrupts
*
* This function should clear any pending transmission complete interrupt and
* enable this interrupt, but without sending any data through the communication
* device.
*/
unsigned char (*enable_tx_irq)(void);
/**
* \brief
* \brief Pointer to a function to start a reception using interrupts
*
* This function should only enable the reception interrupts so that the IRQ
* handler function is called each time a new data byte is received.
*/
unsigned char (*receive_irq)(void);
/**
* \brief
* \brief Pointer to a function to cancel a current reception using interrupts
*
* This function should only disable the reception interrupts so that the IRQ
* handler function is no longer called.
*/
unsigned char (*cancel_receive_irq)(void);
/**@}*/
/* DMA functions */
/**
* \defgroup harware_dma_pointers Hardware DMA related function pointers
*
* This set of functions, that must be implemented by the low level hardware
* communication module (either USART, I2C, SPI or any other communication
* device), are intended to handle DMA driven receptions and transmissions.
*
* This function pointers must be assigned by the initialization function
* of the communication module.
*
*/
/**@{*/
/**
* \brief
* \brief Pointer to a function to start a transmission using DMA
*
* This function should configure and enable the corresponding DMA channel
* to transfer the desired ammount of data from the internal buffer to the
* communication device. TX DMA interrupts should be enabled so that the
* corresponding IRQ handler is called when the transaction is complete or
* when an error ocurrs.
*/
unsigned char (*send_dma)(unsigned char *data,unsigned short int length);
/**
* \brief
* \brief Pointer to a function to start a reception using DMA
*
* This function should configure and enable the corresponding DMA channel
* to transfer the desired ammount of data from the communication device to
* the internal buffer. RX DMA interrupts should be enabled so that the
* corresponding IRQ handler is called when the transaction is complete or
* when an error ocurrs.
*/
unsigned char (*receive_dma)(unsigned char *data,unsigned short int length);
/**
* \brief
* \brief Pointer to a function to cancel a current reception using DMA
*
* This function should abort the current RX DMA transaction in case there
* is any active.
*/
unsigned char (*cancel_receive_dma)(void);
/**@}*/
/* irq callbacks */
/**
* \defgroup callback_irq_pointers User IRQ related function pointers
*
* This set of functions, that must be implemented by the user module that
* uses the coomunication structure, are intended to handle the specific
* requirements of each application using interrupt driven communications.
*
* This function pointers must be assigned by the initialization function
* of the user module.
*
*/
/**@{*/
/**
* \brief
* \brief Callback function to handle the end of interrupt driven transmissions
*
* This function is called whenever an IRQ driven transmission is completed so
* that the user application can perform any required action.
*
* Depending on the return value of this function, the comm_do_irq_send()
* function will send the next byte on the internal buffer (0x01) or the byte
* returned by this function (0x00).
*/
unsigned char (*irq_send_cb)(void *data,unsigned char *byte);
/**
* \brief
* \brief Callback function to handle the end of interrupt driven receptions
*
* This function is called whenever an IRQ driven reception is completed so that
* the user application can perform any required action.
*/
unsigned char (*irq_receive_cb)(void *data,unsigned char byte);
/**@}*/
/* dma callbacks */
/**
* \defgroup callback_dma_pointers User DMA related function pointers
*
* This set of functions, that must be implemented by the user module that
* uses the coomunication structure, are intended to handle the specific
* requirements of each application using DMA driven communications.
*
* This function pointers must be assigned by the initialization function
* of the user module.
*/
/**@{*/
/**
* \brief
* \brief Callback functions to handle the end of DMA driven transmissions
*
* This function is called whenever an DMA driven transmission is completed so
* that the user application can perform any required action.
*/
unsigned char (*dma_send_cb)(void *data);
/**
* \brief
* \brief Callback functions to handle the end of DMA driven receptions
*
* This function is called whenever an DMA driven reception is completed so that
* the user application can perform any required action.
*/
unsigned char (*dma_receive_cb)(void *data);
/**@}*/
}TComm;
/* public functions */
/**
* \brief
* \brief Function to initialize the communications structure
*
* This function initializes a TComm structure by default. All function
* pointer are set to dummy functions that do nothing. These functions
* have to be assigned to valid functions afterwards.
*
* This functions allows to enable or disable the use of the DMA. This
* option can not be modified afterwards. The TTime structure, if provided,
* will allow the comunicatin device to use timeouts during reception.
* Otherwise, the timeout feature will be disabled.
*
* \param dev pointer to a valid TComm structure to be initialized. If
* memory is not pre-allocated before calling this function, its
* behavior is unpredictable.
* \param use_dma flag to enable (0x01) or disable (0x00) the use of
* the DMA for the communcations structure. Any other value is
* interpreted as an enable.
* \param time a pointer to an initiliazed TTime structure to enable the
* use of timeouts. If timeouts are not desired or required, this
* parameter must be set to NULL (0x00000000).
*/
void comm_init(TComm *dev,unsigned char use_dma,TTime *time);
/**
* \brief
* \brief Function to start a blocking transmission
*
* This function is used to start a transmission in blocking mode. By default
* the interrupt driven transmission is used, unless the use of the DMA has been
* enabled in the call to the comm_init() function, in which case the DMA driven
* transmission is used.
*
* This function blocks until all bytes have been transmitted or there has been
* an error.
*
* \param dev pointer to a valid TComm structure to be initialized. If
* memory is not pre-allocated before calling this function, its
* behavior is unpredictable.
* \param data pointer to a vector where the data to be transmitted is stored.
* Memory for this parameter must be pre-allocated before calling this
* function to avoid unexpected behaviour.
* \param length Number of bytes to be transmitted.
*
* \return the status of the transmission. The possible values are the elements
* in the comm_error ennumeraiton.
*/
comm_error comm_send(TComm *dev,unsigned char *data,unsigned short int length);
/**
* \brief
* \brief Function to start a blocking reception with a timeout
*
* This function is used to start a reception in blocking mode. By default
* the interrupt driven reception is used, unless the use of the DMA has been
* enabled in the call to the comm_init() function, in which case the DMA driven
* reception is used.
*
* This function blocks until all bytes have been received, there has been an
* error or the ammount of time specified as timeout has elapsed.
*
* \param dev pointer to a valid TComm structure to be initialized. If
* memory is not pre-allocated before calling this function, its
* behavior is unpredictable.
* \param data pointer to a vector where the received data is to be stored.
* Memory for this parameter must be pre-allocated before calling this
* function to avoid unexpected behaviour.
* \param length Number of bytes to be received.
* \param timeout maximum time in micro-seconds to wait for the desired ammount
* of bytes. If the TTime structure is not valid this parameter is ignored.
*
* \return the status of the transmission. The possible values are the elements
* in the comm_error ennumeraiton.
*/
comm_error comm_receive(TComm *dev,unsigned char *data,unsigned short int *length,unsigned long int timeout);
/* IRQ functions */
/**
* \brief
* \brief Function to start an interrupt driven transmission
*
* This function is used to start a reception in IRQ driven mode. This function
* starts sending the data but returns immediatelly, reporting an error, if any.
* The data in the input parameter is copied to the internal buffer before it
* returns.
*
* This function calls the function of the low level communication module pointed
* by the send_irq parameter.
*
* \param dev pointer to a valid TComm structure to be initialized. If
* memory is not pre-allocated before calling this function, its
* behavior is unpredictable.
* \param data pointer to a vector where the data to be transmitted is stored.
* Memory for this parameter must be pre-allocated before calling this
* function to avoid unexpected behaviour.
* \param length Number of bytes to be transmitted.
*
* \return the status of the transmission. The possible values are the elements
* in the comm_error ennumeraiton.
*/
comm_error comm_send_irq(TComm *dev,unsigned char *data,unsigned short int length);
/**
* \brief
* \brief Function to handle the end of the transmission of a single byte
*
* This function should be called from the interrupt handler each time a byte has
* been sent. If this function is called as a result of the last byte of a DMA
* transfer being sent, it calls the corresponding DMA transmission callback
* function.
*
* If this function is called as a result of a byte beign sent in an IRQ driven
* transfer, this function calls the corresponding IRQ transmission callback
* function. When the last byte has been sent, this function automatically stops
* the current transmission, and returns a value of 0x00 to report it.
*/
unsigned char comm_do_irq_send(TComm *dev,unsigned char *byte);
/**
* \brief
* \brief Function to start an interrupt driven reception
*
*/
comm_error comm_receive_irq(TComm *dev,unsigned short int length);
/**
* \brief
* \brief Function to handle the reception of a single byte
*
*/
unsigned char comm_do_irq_receive(TComm *dev,unsigned char byte);
/**
* \brief
* \brief Function to get the received data
*
*/
comm_error comm_get_received_data(TComm *dev,unsigned char *data,unsigned short int *length);
/**
* \brief
* \brief Function to cancel the current interrupt driven reception
*
*/
void comm_cancel_irq_receive(TComm *dev);
/* DMA functions */
/**
* \brief
* \brief Function to start a DMA driven transmission
*
*/
comm_error comm_send_dma(TComm *dev,unsigned char *data,unsigned short int length);
/**
* \brief
* \brief Function to handle the transmission of all bytes
*
*/
void comm_do_dma_send(TComm *dev);
/**
* \brief
* \brief Function to start a DMA driven reception
*
*/
comm_error comm_receive_dma(TComm *dev,unsigned char *data,unsigned short int length);
/**
* \brief
* \brief Function to handle the reception of all desired bytes
*
*/
void comm_do_dma_receive(TComm *dev);
/**
* \brief
* \brief Function to cancel the current DMA driven reception
*
*/
void comm_cancel_dma_receive(TComm *dev);
/* common functions */
/**
* \brief
* \brief Function to check whether the current transmission has ended or not
*
*/
comm_error comm_is_send_done(TComm *dev);
/**
* \brief
* \brief Function to check whether the current reception has ended or not
*
*/
comm_error comm_is_receive_done(TComm *dev);
/**
* \brief
* \brief Function to get the communication error
*
*/
inline unsigned char comm_get_error(TComm *dev);
/**
* \brief
* \brief Function to set the communication error
*
*/
inline void comm_set_error(TComm *dev, unsigned char error);
/**
* \brief
*
*/
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment