elbear_arduino_bsp/cores/arduino/HardwareSerial.cpp
khristolyubov e36b851783 ready to alpha
подготовка к альфа-тестированию
2024-08-19 22:44:04 +07:00

187 lines
4.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
HardwareSerial.cpp - Hardware serial library for Wiring
*/
#include "HardwareSerial.h"
#include <uart_lib.h>
#include "mik32_hal_irq.h"
// объект класса HardwareSerial для использования в arduino ide
HardwareSerial Serial;
void serialEvent() __attribute__((weak));
bool Serial0_available() __attribute__((weak));
void serialEventRun(void)
{
if (Serial0_available && serialEvent && Serial0_available())
serialEvent();
}
// Public Methods
void HardwareSerial::begin(unsigned long baud, uint8_t config)
{
// find the frequency divider (F_CPU is in the preprocessor defines)
uint32_t brr = (uint32_t)(F_CPU/baud);
if (brr < 16) // the driver says that the divisor must be at least 16
brr = 16;
// parse config
uint32_t reg1config = UART_CONTROL1_RE_M | UART_CONTROL1_TE_M | UART_CONTROL1_RXNEIE_M;
uint32_t reg2config = 0;
uint32_t reg3config = 0;
// first look at parity, because the parity bit is included in the data length
bool useParity = true;
if ((config >> 4) == 0) // no - everything is zero, don't set anything in reg1config
useParity = false;
else if ((config >> 4) == 2) // even
reg1config |= UART_CONTROL1_PCE_M;
else if ((config >> 4) == 3) // odd
reg1config |= (UART_CONTROL1_PCE_M | UART_CONTROL1_PS_M);
// data length
if (((config & 0x07) == 4) && (useParity == false)) // 7 bit + no parity
// 7 bits without parity - configure 7 bits
reg1config |= UART_CONTROL1_M_7BIT_M;
else if (((config & 0x07) == 6) && (useParity == true)) // 8 bit + parity
// 8 bits with parity - configure 9 bits
reg1config |= UART_CONTROL1_M_9BIT_M;
// if 7 bits with parity or 8 bits without parity - do not change anything,
// leaving the data length selected as 8 bits
// stop bit // stop bit = 1 - everything is zero, don't set anything
if ((config >> 3) & (0x01 == 1)) // stop bit = 2
reg2config |= UART_CONTROL2_STOP_1_M;
// turn on the receiver and transmitter, apply the parsed config
UART_Init(UART_0, brr, reg1config, reg2config, reg3config);
// Enable level-based interrupts for the EPIC_UART_0 line, we have only receive interrupt enabled
HAL_EPIC_MaskLevelSet(HAL_EPIC_UART_0_MASK);
isInited = true;
}
void HardwareSerial::end()
{
if (isInited)
{
// wait for the data to be sent if necessary
flush();
// disable clock
__HAL_PCC_UART_0_CLK_DISABLE();
HAL_EPIC_MaskLevelClear(HAL_EPIC_UART_0_MASK);
// reconfigure pins to z state
GPIO_InitTypeDef GPIO_InitStruct;
memset(&GPIO_InitStruct, 0, sizeof(GPIO_InitStruct));
GPIO_InitStruct.Pin = (HAL_PinsTypeDef)(GPIO_PIN_5 | GPIO_PIN_6);
GPIO_InitStruct.Mode = HAL_GPIO_MODE_GPIO_INPUT;
GPIO_InitStruct.Pull = HAL_GPIO_PULL_NONE;
HAL_GPIO_Init(GPIO_0, &GPIO_InitStruct);
// reset buffer indices
_rx_buffer_head = _rx_buffer_tail = 0;
isInited = false;
}
}
int HardwareSerial::available(void)
{
// free space in buffer
return ((unsigned int)(SERIAL_RX_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail)) % SERIAL_RX_BUFFER_SIZE;
}
int HardwareSerial::availableForWrite(void)
{
// don't use buffer
return -1;
}
void HardwareSerial::rx_complete_irq(void)
{
// find next index in buffer with upper limit
uint8_t i = (uint8_t)(_rx_buffer_head + 1)%SERIAL_RX_BUFFER_SIZE;
unsigned char c;
// while there is something to receive, put the data into the buffer
// and edit the buffer index
while (!UART_IsRxFifoEmpty(UART_0))
{
c = UART_ReadByte(UART_0);
if (i != _rx_buffer_tail)
{
// write if there is space in the buffer
_rx_buffer[_rx_buffer_head] = c;
_rx_buffer_head = i;
}
}
}
// wrapper for use in С-files
extern "C" void serial_handler_wrapper(void)
{
Serial.rx_complete_irq();
}
int HardwareSerial::peek(void)
{
if (_rx_buffer_head == _rx_buffer_tail) // nothing to read
return -1;
else
return _rx_buffer[_rx_buffer_tail]; // return first element
}
int HardwareSerial::read(void)
{
// if there is nothing to read, return -1
if (_rx_buffer_head == _rx_buffer_tail)
return -1;
else
{
// return first element and edit the buffer index
unsigned char c = _rx_buffer[_rx_buffer_tail];
_rx_buffer_tail = (uint8_t)(_rx_buffer_tail + 1)%SERIAL_RX_BUFFER_SIZE;
return (int)c;
}
}
// write byte
size_t HardwareSerial::write(uint8_t c)
{
if (isInited)
{
UART_WriteByte(UART_0, c);
UART_WaitTransmission(UART_0);
return 1;
}
else
return 0;
}
// write bytes buffer
size_t HardwareSerial::write(const uint8_t *buffer, size_t size)
{
if (isInited)
{
size_t n = 0;
while (size--)
{
if (HardwareSerial::write(*buffer++))
n++;
else
break;
}
return n;
}
else
return 0;
}
void HardwareSerial::flush()
{
// wait for the data transfer complete
while((UART_0->FLAGS & UART_FLAGS_TC_M) == 0)
;
}