This repository has been archived on 2020-06-14. You can view files and clone it, but cannot push or open issues or pull requests.

221 lines
7.2 KiB
C

/**************************************************************************
* NAME: usart.h
* AUTHOR: Lennart Eriksson
* PURPOSE: USART implementation for sending data
* INFORMATION:
* This file includes 2 types of USARTS, regular polling or DMA based
* the polling version of the USART uses the processor in order to get
* messages while the DMA has Direct Memory Access and does not need the
* processor to receive the messages and can copy the entire message once.
* The DMA is implemented using a double buffer with fixed sizes of the
* buffers in order to work with fixed data sizes of the messages. The up
* side of this is that the system can read a complete message and not
* where the DMA is not writing on the same place. Though this means that
* the message sizes needs to be know on before hand
*
* GLOBAL VARIABLES:
* Variable Type Description
* -------- ---- -----------
**************************************************************************/
#ifndef DRIVERS_USART_H_
#define DRIVERS_USART_H_
#include "stm32f4xx.h"
typedef struct dma_usart_return {
uint8_t* buff;
bool new_data;
} dma_usart_return;
// Enumeration for USART stop bits
typedef enum stop_bits
{
STOP_BITS_1 = 0,
STOP_BITS_0_5,
STOP_BITS_2,
STOP_BITS_1_5
} stop_bits;
// Enuymeration for USART parity
typedef enum parity
{
PARITY_NONE = 0x0,
PARITY_EVEN = 0x2,
PARITY_ODD = 0x3
} parity;
// Struct to be used for regular USART with polling
typedef struct usart_profile
{
USART_TypeDef* usart_instance; // The USART used to send or receive data
} usart_profile;
// struct to be used for dma receiving of USART messages
typedef struct usart_dma_profile
{
usart_profile usart_pro; // The USART profile to be used
DMA_Stream_TypeDef* dma_usart_rx_instance; // The DMA profile corresponding to the rx buffer
DMA_Stream_TypeDef* dma_usart_tx_instance; // The DMA profile corresponding to the tx buffer
uint8_t* dma_rx_buffer1; // The first rx buffer used in double buffering
uint8_t* dma_rx_buffer2; // The second rx buffer used in double buffering
uint8_t* dma_tx_buffer; // The tx buffer used for sending messages
} usart_dma_profile;
/***********************************************************************
* BRIEF: Initialize the USART with DMA reception of messages
* INFORMATION:
* Initialize the specified USART and enable the DMA for it so that the
* messages can be received without utilizing any processor load. This
* function returns false if any error occurred during the initialization
* and true of everything went well
***********************************************************************/
bool usart_init_dma(USART_TypeDef* usart_inst,
usart_dma_profile* profile_out,
uint32_t baud_rate,
stop_bits stopbits,
parity parity_mode,
uint32_t dma_rx_buffersize,
uint32_t dma_tx_buffersize);
/***********************************************************************
* BRIEF: Initialize a regular USART that can be used for polling
* INFORMATION:
* Initialize the specified USART in order to get polling and regular
* transmit of messages to work. If the initialization fails this function
* returns false and otherwise it returns true
* * For USART1 Inverter is ON on RX by default
***********************************************************************/
bool usart_init(USART_TypeDef* usart_inst,
usart_profile* profile_out,
uint32_t baud_rate,
stop_bits stopbits,
parity parity_mode);
/***********************************************************************
* BRIEF: Send message over USART
* INFORMATION:
* Try to send a message over USART, if the time exceeds the specified
* timeout the transmit will be stopped. This function returns the number
* of bytes that was successfully sent down to the USART bus even if
* the timeout was reached before it was done.
***********************************************************************/
uint32_t usart_transmit(usart_profile *profile,
uint8_t* buffer,
uint32_t size,
uint32_t timeout_us);
/***********************************************************************
* BRIEF: return if the USART has any data to be received in the buffer
* INFORMATION:
***********************************************************************/
bool usart_poll_data_ready(usart_profile* profile);
/***********************************************************************
* BRIEF: Poll messages from the USART
* INFORMATION:
* Try to get a message from the USART, if the time spent receiving
* exceeds the specified timeout the function will return the buffer
* that has been received to that point. The function returns the number
* of bytes received even if the timeout was exceeded.
***********************************************************************/
uint32_t usart_poll(usart_profile *profile,
uint8_t* buffer,
uint32_t size,
uint32_t timeout_us);
/***********************************************************************
* BRIEF: Get the DMA buffer that was most recently completed
* INFORMATION:
* This function will return the buffer that the DMA most recently
* completed so that the DMA can continue writing to the second buffer
* without interfering with the rest of the system
***********************************************************************/
dma_usart_return usart_get_dma_buffer(usart_dma_profile *profile);
/***********************************************************************
* BRIEF: NOT IMPLEMENTED YET
* INFORMATION:
* Use the usart_transmit function instead with the
* usart_dma_profile.usart_pro as input argument instead
***********************************************************************/
void usart_transmit_dma(usart_dma_profile *profile,
uint8_t* buffer,
uint32_t size);
#endif /* DRIVERS_USART_H_ */
// -------------------- EXAMPLE OF USART POLL -------------------------
/*
int main()
{
//Initialize the system
init_system();
//Set up a usart profile
usart_profile usart_p;
//Initiate the profile for specified USART
usart_init(USART1, &usart_p, 115200, STOP_BITS_1, PARITY_NONE);
//The data buffer used
uint8_t data = 0x00;
while(1)
{
//poll data from the USART
uint32_t num_received = usart_poll(&usart_p, &data, 1, 1000);
//if data was received send the data back over the USART
if(num_received > 0x00)
{
usart_transmit(&usart_p, &data, 1, 1000);
}
}
}
*/
// -------------------- EXAMPLE OF USART DMA -------------------------
/*
#define USART_DMA_SIZE 4
int main(void)
{
//Init the system
init_system();
//Set up a usart DMA profile
usart_dma_profile dma_p;
//Initiate USART DMA profile
usart_init_dma(USART1, &dma_p, 115200, STOP_BITS_1, PARITY_NONE, USART_DMA_SIZE, 0);
//Temporary array to compare against
uint8_t tmp[USART_DMA_SIZE] = { 0x00 };
while(1)
{
uint8_t* buf;
// Get the dma finished buffer
buf = usart_get_dma_buffer(&dma_p);
bool change = false;
//compare against the previous buffer and copy the elements
for(int i = 0; i < USART_DMA_SIZE; i++)
{
if(tmp[i] != (tmp[i] = buf[i]))
change |= true;
}
//if the buffer has changed print the buffer back over USART
if(change)
{
usart_transmit(&dma_p, tmp, USART_DMA_SIZE, 1000);
}
}
}
*/