157 lines
5.0 KiB
C
157 lines
5.0 KiB
C
/*
|
|
* This file is part of Adafruit for EFR32 project
|
|
*
|
|
* The MIT License (MIT)
|
|
*
|
|
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*/
|
|
|
|
#include "py/mphal.h"
|
|
#include "py/ringbuf.h"
|
|
#include "supervisor/port.h"
|
|
#include "supervisor/serial.h"
|
|
#include "shared/readline/readline.h"
|
|
#include "shared/runtime/interrupt_char.h"
|
|
#include "shared-bindings/microcontroller/Pin.h"
|
|
#include "py/runtime.h"
|
|
|
|
#include "em_cmu.h"
|
|
#include "em_core.h"
|
|
#include "em_gpio.h"
|
|
#include "em_eusart.h"
|
|
#include "em_gpio.h"
|
|
#include "em_cmu.h"
|
|
|
|
#define CONSOLE_RCV_BUFFER_SIZE 4096
|
|
|
|
#define EUSART_VCOM_TX_PORT gpioPortA
|
|
#define EUSART_VCOM_TX_PIN 5
|
|
|
|
#define EUSART_VCOM_RX_PORT gpioPortA
|
|
#define EUSART_VCOM_RX_PIN 6
|
|
|
|
STATIC ringbuf_t con_uart_rx_ringbuf;
|
|
STATIC byte con_uart_rx_buf[CONSOLE_RCV_BUFFER_SIZE];
|
|
STATIC volatile uint8_t received_data;
|
|
|
|
// USART0 RX interrupt handler , put characters to ring buffer one by one
|
|
void EUSART0_RX_IRQHandler(void) {
|
|
CORE_DECLARE_IRQ_STATE;
|
|
CORE_ENTER_ATOMIC();
|
|
|
|
received_data = EUSART0->RXDATA;
|
|
if (1 != ringbuf_put_n(&con_uart_rx_ringbuf, (uint8_t *)&received_data, 1)) {
|
|
mp_raise_OverflowError_varg(translate("Console UART RX buffer overflow"));
|
|
}
|
|
|
|
CORE_EXIT_ATOMIC();
|
|
port_wake_main_task();
|
|
|
|
if (received_data == CHAR_CTRL_C &&
|
|
mp_interrupt_char == CHAR_CTRL_C) {
|
|
ringbuf_clear(&con_uart_rx_ringbuf);
|
|
mp_sched_keyboard_interrupt();
|
|
}
|
|
EUSART_IntClear(EUSART0, EUSART_IF_RXFL);
|
|
}
|
|
|
|
// Configure EUSART0 for REPL
|
|
void port_serial_early_init(void) {
|
|
|
|
// Enable clock to GPIO and EUSART1
|
|
CMU_ClockEnable(cmuClock_GPIO, true);
|
|
CMU_ClockEnable(cmuClock_EUSART0, true);
|
|
|
|
// Configure the EUSART TX pin to the board controller as an output
|
|
GPIO_PinModeSet(EUSART_VCOM_TX_PORT, EUSART_VCOM_TX_PIN, gpioModePushPull, 0);
|
|
|
|
// Configure the EUSART RX pin to the board controller as an input
|
|
GPIO_PinModeSet(EUSART_VCOM_RX_PORT, EUSART_VCOM_RX_PIN, gpioModeInput, 0);
|
|
|
|
// Route EUSART0 TX and RX to the board controller TX and RX pins
|
|
GPIO->EUSARTROUTE[0].TXROUTE = (EUSART_VCOM_TX_PORT << _GPIO_EUSART_TXROUTE_PORT_SHIFT)
|
|
| (EUSART_VCOM_TX_PIN << _GPIO_EUSART_TXROUTE_PIN_SHIFT);
|
|
GPIO->EUSARTROUTE[0].RXROUTE = (EUSART_VCOM_RX_PORT << _GPIO_EUSART_RXROUTE_PORT_SHIFT)
|
|
| (EUSART_VCOM_RX_PIN << _GPIO_EUSART_RXROUTE_PIN_SHIFT);
|
|
|
|
// Enable RX and TX signals now that they have been routed
|
|
GPIO->EUSARTROUTE[0].ROUTEEN = GPIO_EUSART_ROUTEEN_RXPEN | GPIO_EUSART_ROUTEEN_TXPEN;
|
|
|
|
// Default asynchronous initializer (115.2 Kbps, 8N1, no flow control)
|
|
EUSART_UartInit_TypeDef init = EUSART_UART_INIT_DEFAULT_HF;
|
|
|
|
// Configure and enable EUSART0 for high-frequency (EM0/1) operation
|
|
EUSART_UartInitHf(EUSART0, &init);
|
|
|
|
|
|
// Claim and never reset UART console pin
|
|
common_hal_mcu_pin_claim(&pin_PA5);
|
|
common_hal_mcu_pin_claim(&pin_PA6);
|
|
common_hal_never_reset_pin(&pin_PA5);
|
|
common_hal_never_reset_pin(&pin_PA6);
|
|
}
|
|
|
|
// Enable EUSART0 interrupt, init ring buffer
|
|
void port_serial_init(void) {
|
|
ringbuf_init(&con_uart_rx_ringbuf,
|
|
con_uart_rx_buf,
|
|
CONSOLE_RCV_BUFFER_SIZE);
|
|
|
|
received_data = 0;
|
|
// Enable NVIC USART sources
|
|
NVIC_ClearPendingIRQ(EUSART0_RX_IRQn);
|
|
NVIC_EnableIRQ(EUSART0_RX_IRQn);
|
|
NVIC_SetPriority(EUSART0_RX_IRQn, 3);
|
|
EUSART_IntEnable(EUSART0, EUSART_IEN_RXFL);
|
|
}
|
|
|
|
bool port_serial_connected(void) {
|
|
return true;
|
|
}
|
|
|
|
// Get a characters from ring buffer
|
|
char port_serial_read(void) {
|
|
int data;
|
|
|
|
CORE_DECLARE_IRQ_STATE;
|
|
CORE_ENTER_ATOMIC();
|
|
|
|
data = ringbuf_get(&con_uart_rx_ringbuf);
|
|
|
|
CORE_EXIT_ATOMIC();
|
|
|
|
return (char)data;
|
|
}
|
|
|
|
// Checking ring buffer haves bytes available or not
|
|
bool port_serial_bytes_available(void) {
|
|
return ringbuf_num_filled(&con_uart_rx_ringbuf) > 0 ? true : false;
|
|
}
|
|
|
|
// Send n bytes data to serial by EUSART0
|
|
void port_serial_write_substring(const char *text, uint32_t len) {
|
|
char *p_text = (char *)text;
|
|
while (len--) {
|
|
EUSART_Tx(EUSART0, *p_text);
|
|
p_text++;
|
|
}
|
|
}
|