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.
 
 

213 lines
5.4 KiB

/*
* Serial.c
*
* Created on: Oct 17, 2020
* Author: Florin (Nicolas)
*/
#include "serial.h"
#include "stm32f0xx.h"
#include "stm32f0xx_hal_def.h"
#include "gpio.h"
//public functions
static void Serial_enableTx(Serial* this);
static void initBuf(Buffer* b);
static inline uint8_t Buffer_getByte(Buffer* b);
static inline uint32_t Buffer_getAvailable(Buffer* b);
static inline void Buffer_setByte(Buffer* b, uint8_t data);
void ISR_Serial(Serial* this) {
UART_HandleTypeDef *huart = this->handler;
uint32_t isrflags = READ_REG(huart->Instance->ISR);
uint32_t cr1its = READ_REG(huart->Instance->CR1);
//uint32_t cr3its = READ_REG(huart->Instance->CR3);
uint32_t errorflags = (isrflags & (uint32_t)(USART_ISR_PE | USART_ISR_FE | USART_ISR_ORE | USART_ISR_NE | USART_ISR_RTOF));
if (errorflags == 0) {
//handle normal
if (((isrflags & USART_ISR_RXNE) != 0U) && ((cr1its & USART_CR1_RXNEIE) != 0U)) {
//received something
// if (huart->RxState == HAL_UART_STATE_BUSY_RX) {
uint16_t uhMask = huart->Mask;
uint16_t uhdata = (uint16_t) READ_REG(huart->Instance->RDR);
uint8_t data = (uint8_t)(uhdata & (uint8_t)uhMask);
Buffer_setByte(&this->in, data);
// } else {
// /* Clear RXNE interrupt flag */
// __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
// }
}
} else {
//handle the errors (receive error)
}
if (((isrflags & USART_ISR_TXE) != 0U) && ((cr1its & USART_CR1_TXEIE) != 0U)) {
//sent something
//if (huart->gState == HAL_UART_STATE_BUSY_TX) {
uint8_t outAvail = Buffer_getAvailable(&this->out);
if (outAvail == 0) {
/* Disable the UART Transmit Data Register Empty Interrupt */
CLEAR_BIT(huart->Instance->CR1, USART_CR1_TXEIE);
/* Tx process is ended, restore huart->gState to Ready */
huart->gState = HAL_UART_STATE_READY;
/* Enable the UART Transmit Complete Interrupt */
SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);
} else {
huart->Instance->TDR = Buffer_getByte(&this->out);
}
//}
}
if (((isrflags & USART_ISR_TC) != 0U) && ((cr1its & USART_CR1_TCIE) != 0U)) {
//transmission ended
/* Disable the UART Transmit Complete Interrupt */
CLEAR_BIT(huart->Instance->CR1, USART_CR1_TCIE);
this->txnComplete = 1;
if (this->flow) {
gpio_ResetPin(this->flowPort, this->flowPin);
}
}
huart->Instance->ICR = 0b00000000000000100000101001011111;
//huart->Instance->ICR = 0; //clear all isr flags
}
void Serial_init(Serial* this, UART_HandleTypeDef* handler) {
this->handler = handler;
initBuf(&this->in);
initBuf(&this->out);
this->flow = 0;
UART_HandleTypeDef *huart = handler;
/* Computation of UART mask to apply to RDR register */
UART_MASK_COMPUTATION(huart);
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->RxState = HAL_UART_STATE_BUSY_RX;
/* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
SET_BIT(huart->Instance->CR3, USART_CR3_EIE);
/* Enable the UART Parity Error interrupt and Data Register Not Empty interrupt */
SET_BIT(huart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE);
}
void Serial_initFlow(Serial* this, GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) {
this->flow = 1;
this->flowPort = GPIOx;
this->flowPin = GPIO_Pin;
}
uint16_t Serial_available(Serial* this){
return Buffer_getAvailable(&this->in);
}
void Serial_flushRX(Serial* this){
initBuf(&this->in);
}
void Serial_flushTX(Serial* this){
initBuf(&this->out);
}
void Serial_print(Serial* this, const char* str){
const uint8_t* ptr = (uint8_t*)str;
while (*ptr != '\0'){
Buffer_setByte(&this->out, *ptr);
ptr++;
}
Serial_enableTx(this);
}
/**
* unguarded about overflow!
* use Serial_available!
*/
uint8_t Serial_read(Serial* this) {
return Buffer_getByte(&this->in);
}
uint16_t Serial_readBuf(Serial* this, uint8_t* buf, uint16_t len) {
uint16_t count = 0;
while (Buffer_getAvailable(&this->in) && (count < len)) {
buf[count] = Buffer_getByte(&this->in);
count++;
}
return count;
// uint16_t max = Buffer_getAvailable(&this->in);
// if (max > len) {
// len = max;
// }
// for (uint16_t i = 0; i < len; i++) {
// buf[i] = Buffer_getByte(&this->in);
// }
// return len;
}
void Serial_writeBuf(Serial* this, const uint8_t* buf, uint16_t len) {
for (uint16_t i = 0; i < len; i++) {
Buffer_setByte(&this->out, buf[i]);
}
Serial_enableTx(this);
}
void Serial_write(Serial* this, const uint8_t data) {
Buffer_setByte(&this->out, data);
Serial_enableTx(this);
}
static void Serial_enableTx(Serial* this) {
if (this->flow) {
gpio_SetPin(this->flowPort, this->flowPin);
}
UART_HandleTypeDef *huart = this->handler;
if (huart->gState == HAL_UART_STATE_READY) {
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->gState = HAL_UART_STATE_BUSY_TX;
/* Enable the Transmit Data Register Empty interrupt */
SET_BIT(huart->Instance->CR1, USART_CR1_TXEIE);
/* Interrupt fires as soon as register is empty (probalbly right now) */
} else {
//huart->gState = HAL_UART_STATE_BUSY_TX;
}
this->txnComplete = 0;
}
static void initBuf(Buffer* b) {
b->head = 0;
b->tail = 0;
}
static inline uint8_t Buffer_getByte(Buffer* b) {
uint32_t tail = b->tail;
uint8_t data = b->buf[tail];
b->tail = (tail + 1) % BUFFER_LEN;
return data;
}
static inline uint32_t Buffer_getAvailable(Buffer* b) {
return (b->head - b->tail) % BUFFER_LEN;
}
static inline void Buffer_setByte(Buffer* b, uint8_t data) {
uint32_t head = b->head;
b->buf[head] = data;
b->head = (head + 1) % BUFFER_LEN;
}