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.
Lennart Eriksson d8a9adff6d USART implementation
This is an implementation of the USART but the DMA transfer is not
supported, all other functionalities are working including i.e. polling,
regular processor transmit and dma double buffer
2016-09-30 12:20:10 +02:00

214 lines
7.1 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"
// 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 partiy
{
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
***********************************************************************/
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
***********************************************************************/
uint8_t* 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);
}
}
}
*/