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
214 lines
7.1 KiB
C
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);
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|