You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

149 lines
3.6 KiB

/*
* usart.c
*
* Created on: Dec 6, 2017
* Author: maximilian
*/
#include "usart.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_usart.h"
#include "porting.h"
static uint8_t tx_overflow = 0;
static osQUEUE_t usart_rx_q, usart_tx_q;
static uint8_t usart_rx_data[USART_QUEUE_SIZE];
static uint8_t usart_tx_data[USART_QUEUE_SIZE];
void usart2Init(void)
{
/* Enable clocks. */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA , ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
/* Initialize used GPIOs. */
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_StructInit(&GPIO_InitStruct);
/* Initialize USART2_TX */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Init. USART2_RX */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Init. USART2 peripheral. */
USART_InitTypeDef USART_InitStructure ;
USART_StructInit(&USART_InitStructure );
USART_InitStructure.USART_BaudRate = 230400;
USART_InitStructure.USART_WordLength = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART2, &USART_InitStructure);
USART_Cmd(USART2, ENABLE);
/* Config. interrupts. */
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
USART_ITConfig(USART2, USART_IT_TXE, ENABLE);
NVIC_EnableIRQ(USART2_IRQn);
/* Init. SW queues. */
osQInit(&usart_rx_q, sizeof(uint8_t), USART_QUEUE_SIZE, usart_rx_data);
osQInit(&usart_tx_q, sizeof(uint8_t), USART_QUEUE_SIZE, usart_tx_data);
}
void USART2_IRQHandler(void)
{
/* USART2 receive buffer contains a char. */
if(USART_GetITStatus(USART2, USART_IT_RXNE) == SET)
{
uint8_t data;
data = USART_ReceiveData(USART2) & 0xFF;
if(!osEnqueue(&usart_rx_q, (void*)&data))
THROW_ERROR(E_USART_RX_BUFFER_OVERLOW);
}
/* USART2 transmit buffer empty. */
if(USART_GetITStatus(USART2, USART_IT_TXE) == SET)
{
uint8_t data;
if(osDequeue(&usart_tx_q, &data))
USART_SendData(USART2, data);
else
{
/* Nothing to send. Disable interrupt. */
USART_ITConfig(USART2, USART_IT_TXE, DISABLE);
tx_overflow = 0;
}
}
}
static uint8_t usart2PutChar(uint8_t data)
{
/* Signal, that the buffer has overflowed. */
if(tx_overflow)
return 0;
/* Put data in the q. */
if(!osEnqueue(&usart_tx_q, (void*)&data))
{
tx_overflow = 1;
return 0;
}
/* Enable interrupt. */
USART_ITConfig(USART2, USART_IT_TXE, ENABLE);
return 1;
}
static uint8_t usart2GetChar(void)
{
uint8_t data;
/* Wait until data arrives. */
while(!osDequeue(&usart_rx_q, &data)){}
return data;
}
uint8_t usart2PutString(uint8_t* word, size_t size)
{
/* Push data as long as it needs that it comes through. */
for(uint8_t i=0; i<size; i++)
while(!usart2PutChar(word[i])){}
/* Did a overflow occur? */
if(tx_overflow)
{
THROW_ERROR(E_USART_RX_BUFFER_OVERLOW);
}
return 1;
}
uint8_t usart2GetString(uint8_t* word, size_t buff_size, size_t *string_size)
{
uint8_t data;
*string_size = 0;
do
{
data = usart2GetChar();
if(data == 0)
return 0;
usart2PutChar(data);
if( *string_size < (buff_size-1) )
word[*string_size] = data;
else
{
THROW_ERROR(E_BUFFER_OVERFLOW);
return 0;
}
(*string_size)++;
} while( (data != '\r') && (data != '\n') );
/* Append string termination. */
word[*string_size] = '\0';
(*string_size)++;
return 1;
}