Merge remote-tracking branch 'refs/remotes/origin/UART_LENNART'
This commit is contained in:
commit
3c89d4ae07
213
UAV-ControlSystem/inc/drivers/usart.h
Normal file
213
UAV-ControlSystem/inc/drivers/usart.h
Normal file
@ -0,0 +1,213 @@
|
||||
/**************************************************************************
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
399
UAV-ControlSystem/src/drivers/usart.c
Normal file
399
UAV-ControlSystem/src/drivers/usart.c
Normal file
@ -0,0 +1,399 @@
|
||||
/**************************************************************************
|
||||
* NAME: usart.c
|
||||
* 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
|
||||
* -------- ---- -----------
|
||||
**************************************************************************/
|
||||
|
||||
#include "drivers/usart.h"
|
||||
#include "stm32f4xx_revo.h"
|
||||
#include "drivers/system_clock.h"
|
||||
|
||||
|
||||
//Define registers for the USART since the HAL library does not work with sending
|
||||
//data at the moment
|
||||
|
||||
// CR1
|
||||
#define UE 0x2000 // Usart Enabled
|
||||
#define M 0x0000 // word length 8
|
||||
#define RE 0x0004 // Receive enabled
|
||||
#define TE 0x0008 // Transmit enabled
|
||||
#define PARITY_OFFSET 9 //Offset to parity bits
|
||||
|
||||
//CR2
|
||||
#define STOP_OFFSET 12 // offset to stop bits in CR2
|
||||
|
||||
//CR3
|
||||
#define DMAR 0x0040 // Enable DMA rx
|
||||
#define DMAT 0x0080 // Enable DMA tx
|
||||
|
||||
//BRR
|
||||
#define USART_BRR(_PCLK_, _BAUD_) ((_PCLK_ /(_BAUD_ * 16)) * 16) // Calculate BRR from the desired baud rate
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* 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, // The USART instance to be used, i.e. USART1, USART3 or USART6 for the REVO card
|
||||
usart_dma_profile* profile_out, // The USART profile that will be used when sending or receiving data
|
||||
uint32_t baud_rate, // The baud rate that the USART will communicate with
|
||||
stop_bits stopbits, // The number of stop bits that the USART should have
|
||||
parity parity_mode, // The parity that the USART should have
|
||||
uint32_t dma_rx_buffersize, // The buffer size for the DMA rx buffers
|
||||
uint32_t dma_tx_buffersize) // The buffer size for the DMA tx buffers
|
||||
{
|
||||
// Local variables used when extracting the different USARTs
|
||||
DMA_Stream_TypeDef *dma_rx_instance, *dma_tx_instance;
|
||||
uint32_t channel;
|
||||
|
||||
// Check if the instance is either USART1, USART3 of USART6 since
|
||||
// those are the only ones available on the REVO card
|
||||
if(usart_inst == USART1)
|
||||
{
|
||||
dma_rx_instance = DMA2_Stream2;
|
||||
dma_tx_instance = DMA2_Stream5;
|
||||
channel = DMA_CHANNEL_4;
|
||||
}
|
||||
else if(usart_inst == USART3)
|
||||
{
|
||||
dma_rx_instance = DMA1_Stream1;
|
||||
dma_tx_instance = DMA1_Stream3;
|
||||
channel = DMA_CHANNEL_4;
|
||||
}
|
||||
else if(usart_inst == USART6)
|
||||
{
|
||||
dma_rx_instance = DMA2_Stream2;
|
||||
dma_tx_instance = DMA2_Stream6;
|
||||
channel = DMA_CHANNEL_5;
|
||||
}
|
||||
else
|
||||
return false; // If any other USART is sent in return false
|
||||
|
||||
// Enable the correct clock if it has not been enabled already
|
||||
if(__HAL_RCC_DMA2_IS_CLK_DISABLED() && (usart_inst == USART6 || usart_inst == USART1))
|
||||
__HAL_RCC_DMA2_CLK_ENABLE();
|
||||
if(__HAL_RCC_DMA1_IS_CLK_DISABLED()&& usart_inst == USART3)
|
||||
__HAL_RCC_DMA1_CLK_ENABLE();
|
||||
|
||||
// Initialize the regular usart before adding on the DMA
|
||||
if(!usart_init(usart_inst, &profile_out->usart_pro, baud_rate, stopbits, parity_mode))
|
||||
return false; // If the initialization did not complete return false
|
||||
|
||||
// set the USART profile buffers and initialize them to 0x00 for every element
|
||||
profile_out->dma_rx_buffer1 = malloc(sizeof(uint8_t) * dma_rx_buffersize);
|
||||
profile_out->dma_rx_buffer2 = malloc(sizeof(uint8_t) * dma_rx_buffersize);
|
||||
profile_out->dma_tx_buffer = malloc(sizeof(uint8_t) * dma_tx_buffersize);
|
||||
memset(profile_out->dma_rx_buffer1, 0x00, dma_rx_buffersize);
|
||||
memset(profile_out->dma_rx_buffer2, 0x00, dma_rx_buffersize);
|
||||
memset(profile_out->dma_tx_buffer, 0x00, dma_tx_buffersize);
|
||||
|
||||
// Set the DMA instances in the USART profile
|
||||
profile_out->dma_usart_rx_instance = dma_rx_instance;
|
||||
profile_out->dma_usart_tx_instance = dma_tx_instance;
|
||||
|
||||
// Enable the DMA on the USARTon register level
|
||||
profile_out->usart_pro.usart_instance->CR3 |= DMAR | DMAT;
|
||||
|
||||
// This is only a dummy that is used by the DMA linking later on
|
||||
USART_HandleTypeDef usart;
|
||||
usart.Instance = usart_inst;
|
||||
|
||||
// Set up the DMA handle for the USART rx
|
||||
DMA_HandleTypeDef g_DmaHandle_rx;
|
||||
g_DmaHandle_rx.Instance = dma_rx_instance; // the rx instance
|
||||
g_DmaHandle_rx.Init.Channel = channel; // the rx channel
|
||||
g_DmaHandle_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; // set data direction to peripheral to memory
|
||||
g_DmaHandle_rx.Init.PeriphInc = DMA_PINC_DISABLE; // peripheral increment data pointer disabled
|
||||
g_DmaHandle_rx.Init.MemInc = DMA_MINC_ENABLE; // Memory increment data pointer enabled
|
||||
g_DmaHandle_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; // Align data words on the peripheral
|
||||
g_DmaHandle_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; // Align data words on the memory
|
||||
g_DmaHandle_rx.Init.Mode = DMA_SxCR_DBM; // Enable Double buffer mode
|
||||
g_DmaHandle_rx.Init.Priority = DMA_PRIORITY_HIGH; // Set the receive priority to high
|
||||
g_DmaHandle_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; // Disable fifo mode
|
||||
g_DmaHandle_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL; // Set fifo threshold to half full although this is probably not used
|
||||
g_DmaHandle_rx.Init.MemBurst = DMA_MBURST_SINGLE; // In double buffer mode the burst must always be single
|
||||
g_DmaHandle_rx.Init.PeriphBurst = DMA_PBURST_SINGLE; // In double buffer mode the burst must always be single
|
||||
|
||||
// Initialize the DMA handle
|
||||
HAL_DMA_Init(&g_DmaHandle_rx);
|
||||
|
||||
// Link the DMA to the USART instance
|
||||
__HAL_LINKDMA(&usart, hdmarx ,g_DmaHandle_rx);
|
||||
|
||||
|
||||
//Set up the DMA handle for the USART tx
|
||||
DMA_HandleTypeDef g_DmaHandle_tx;
|
||||
g_DmaHandle_tx.Instance = dma_tx_instance;
|
||||
g_DmaHandle_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
|
||||
g_DmaHandle_tx.Init.Channel = channel;
|
||||
HAL_DMA_Init(&g_DmaHandle_tx);
|
||||
__HAL_LINKDMA(&usart, hdmatx ,g_DmaHandle_tx);
|
||||
|
||||
|
||||
// g_DmaHandle.Instance = dma_tx_instance;
|
||||
// g_DmaHandle.Init.Direction = DMA_MEMORY_TO_PERIPH;
|
||||
// g_DmaHandle.Init.Mode = 0x00;
|
||||
// g_DmaHandle.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
|
||||
// g_DmaHandle.Init.Priority = DMA_PRIORITY_MEDIUM;
|
||||
//
|
||||
// HAL_DMA_Init(&g_DmaHandle);
|
||||
//
|
||||
// __HAL_LINKDMA(&usart, hdmatx ,g_DmaHandle);
|
||||
|
||||
|
||||
|
||||
//Setup DMA buffers
|
||||
|
||||
// Disable the DMA, must be done before writing to the addresses below
|
||||
dma_rx_instance->CR &= ~(DMA_SxCR_EN);
|
||||
|
||||
dma_rx_instance->NDTR = dma_rx_buffersize; // Set the buffer size
|
||||
dma_rx_instance->PAR = (uint32_t)&profile_out->usart_pro.usart_instance->DR; // Set the address to the USART data register
|
||||
dma_rx_instance->M0AR = (uint32_t)profile_out->dma_rx_buffer1; // Set the address to the first DMA buffer
|
||||
dma_rx_instance->M1AR = (uint32_t)profile_out->dma_rx_buffer2; // Set the address to the second DMA buffer
|
||||
dma_rx_instance->CR &= ~(0xF << 11); // Set the data size to 8 bit values
|
||||
|
||||
//Enable the DMA again to start receiving data from the USART
|
||||
dma_rx_instance->CR |= DMA_SxCR_EN;
|
||||
|
||||
|
||||
dma_tx_instance->CR &= ~(DMA_SxCR_EN);
|
||||
|
||||
dma_tx_instance->NDTR = dma_tx_buffersize;
|
||||
dma_tx_instance->PAR = (uint32_t)&profile_out->usart_pro.usart_instance->DR;
|
||||
dma_tx_instance->M0AR = (uint32_t)profile_out->dma_tx_buffer;
|
||||
dma_tx_instance->CR &= ~(0xF << 11);
|
||||
|
||||
|
||||
dma_tx_instance->CR |= DMA_SxCR_EN;
|
||||
|
||||
return true; // everything went as planned and the USART should be ready to use
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* 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, // The USART instance to be used, i.e. USART1, USART3 or USART6 for the REVO board
|
||||
usart_profile* profile_out, // The USART profile that will be used when sending or receiving data
|
||||
uint32_t baud_rate, // The baud rate that the USART will communicate with
|
||||
stop_bits stopbits, // The number of stop bits that the USART should have
|
||||
parity parity_mode) // The parity that the USART should have
|
||||
{
|
||||
// set the USART profiles USART instance
|
||||
profile_out->usart_instance = usart_inst;
|
||||
|
||||
// Local variables used when extracting the different USARTs
|
||||
uint32_t rx_pin, tx_pin, af_func;
|
||||
GPIO_TypeDef* gpioport;
|
||||
|
||||
// Check if the instance is either USART1, USART3 of USART6 since
|
||||
// those are the only ones available on the REVO card
|
||||
if(usart_inst == USART1)
|
||||
{
|
||||
rx_pin = USART1_RX_PIN;
|
||||
tx_pin = USART1_TX_PIN;
|
||||
af_func = GPIO_AF7_USART1;
|
||||
gpioport = USART1_RX_PORT;
|
||||
|
||||
//Enable clock if not already enabled
|
||||
if(__HAL_RCC_USART1_IS_CLK_DISABLED())
|
||||
__HAL_RCC_USART1_CLK_ENABLE();
|
||||
}
|
||||
else if(usart_inst == USART3)
|
||||
{
|
||||
rx_pin = USART3_RX_PIN;
|
||||
tx_pin = USART3_TX_PIN;
|
||||
af_func = GPIO_AF7_USART3;
|
||||
gpioport = USART3_RX_PORT;
|
||||
|
||||
//Enable clock if not already enabled
|
||||
if(__HAL_RCC_USART3_IS_CLK_DISABLED())
|
||||
__HAL_RCC_USART3_CLK_ENABLE();
|
||||
}
|
||||
else if(usart_inst == USART6)
|
||||
{
|
||||
rx_pin = USART6_RX_PIN;
|
||||
tx_pin = USART6_TX_PIN;
|
||||
af_func = GPIO_AF8_USART6;
|
||||
gpioport = USART6_RX_PORT;
|
||||
|
||||
//Enable clock if not already enabled
|
||||
if(__HAL_RCC_USART6_IS_CLK_DISABLED())
|
||||
__HAL_RCC_USART6_CLK_ENABLE();
|
||||
}
|
||||
else
|
||||
return false;// If any other USART is sent in return false
|
||||
|
||||
|
||||
// PIN Initialization for the USART
|
||||
GPIO_InitTypeDef gpio;
|
||||
gpio.Pin = rx_pin | tx_pin;
|
||||
gpio.Pull = GPIO_NOPULL;
|
||||
gpio.Mode = GPIO_MODE_AF_PP;
|
||||
gpio.Speed = GPIO_SPEED_HIGH;
|
||||
gpio.Alternate = af_func;
|
||||
HAL_GPIO_Init(gpioport, &gpio);
|
||||
|
||||
// USART initialization
|
||||
// This is on register level since the HAL library did not work as expected
|
||||
usart_inst->CR1 = UE | M | RE | TE | (parity_mode << PARITY_OFFSET);
|
||||
usart_inst->CR2 = stopbits << STOP_OFFSET;
|
||||
usart_inst->BRR = USART_BRR(HAL_RCC_GetPCLK2Freq(), baud_rate);
|
||||
|
||||
return true; // Everything went as planned and the USART is enabled
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* 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, // The USART profile to send data from
|
||||
uint8_t* buffer, // The buffer to send
|
||||
uint32_t size, // The size of the buffer to send
|
||||
uint32_t timeout_us) // If time exceeds this microsecond value the function will return
|
||||
{
|
||||
// Calculate at what time the function should stop sending and return if not done
|
||||
uint32_t time_to_leave = clock_get_us() + timeout_us;
|
||||
int i;
|
||||
// Send all messages in the buffer
|
||||
for(i = 0; i < size; i++)
|
||||
{
|
||||
profile->usart_instance->DR = buffer[i];
|
||||
// Wait for the buffer to be emptied and sent over the usart, if the timeout value is reached leave this function
|
||||
while (!(profile->usart_instance->SR & 0x40) && time_to_leave > clock_get_us());
|
||||
|
||||
// If the overrun error is active clear it before continue
|
||||
if(profile->usart_instance->SR & 0x08)
|
||||
{
|
||||
profile->usart_instance->SR;
|
||||
profile->usart_instance->DR;
|
||||
}
|
||||
|
||||
// if the timeout is reached return the number of bytes that was successfully sent over USART
|
||||
if(time_to_leave <= clock_get_us())
|
||||
return i;
|
||||
}
|
||||
|
||||
//return the number of Bytes sent on the USART, this should be the same size as the provided buffer size
|
||||
return i;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* 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)
|
||||
{
|
||||
// this is only a try to get the system working so there is no definite proof that this
|
||||
// is the correct way. This is only kept if it were to be implemented to see what have been
|
||||
// done.
|
||||
|
||||
/*
|
||||
for(int i = 0; i < size; i++)
|
||||
{
|
||||
profile->dma_tx_buffer[i] = buffer[i];
|
||||
}
|
||||
|
||||
profile->dma_usart_tx_instance->CR &= ~(DMA_SxCR_EN);
|
||||
|
||||
profile->dma_usart_tx_instance->NDTR = size;
|
||||
|
||||
profile->dma_usart_tx_instance->CR |= DMA_SxCR_EN;
|
||||
*/
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* BRIEF: return if the USART has any data to be received in the buffer
|
||||
* INFORMATION:
|
||||
***********************************************************************/
|
||||
bool usart_poll_data_ready(usart_profile* profile)
|
||||
{
|
||||
// check if the Read Data Register Not Empty (RXNE) is set
|
||||
if(profile->usart_instance->SR & 0x20)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* 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, // The USART profile to receive data from
|
||||
uint8_t* buffer, // The buffer to put the data in
|
||||
uint32_t size, // The expected size of the data
|
||||
uint32_t timeout_us) // If time exceeds this microsecond value the function will return
|
||||
{
|
||||
// Calculate at what time the function should stop sending and return if not done
|
||||
uint32_t time_to_leave = clock_get_us() + timeout_us;
|
||||
|
||||
int i = 0;
|
||||
// While the timeout is not exceeded and we have data to read run this loop
|
||||
while(time_to_leave > clock_get_us() && i < size)
|
||||
{
|
||||
// Check if data is ready to be received
|
||||
if(usart_poll_data_ready(profile))
|
||||
{
|
||||
// Copy the data from the data register to the buffer
|
||||
buffer[i++] = profile->usart_instance->DR & 0xFF;
|
||||
|
||||
// Wait until the status register gets ready again
|
||||
while (profile->usart_instance->SR & 0x20);
|
||||
}
|
||||
}
|
||||
|
||||
//return the number of bytes received
|
||||
return i;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* 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)
|
||||
{
|
||||
// Check which buffer the DMA is writing to at the moment and return the other buffer
|
||||
if(profile->dma_usart_rx_instance->CR & DMA_SxCR_CT)
|
||||
{
|
||||
return profile->dma_rx_buffer1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return profile->dma_rx_buffer2;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user