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
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;
|
|
}
|
|
|