/* HardwareSerial.cpp - Hardware serial library for Wiring */ #include "HardwareSerial.h" #include #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) ; }