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