/************************************************************************** * 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); } } } */