Files
Yukihiro "Matz" Matsumoto a8c82b506f hw-uart: consolidate platform gems into ports/ directories
Move hw-esp32-uart and hw-rp2040-uart into hw-uart/ports/esp32/
and hw-uart/ports/rp2040/ using the new ports build system.

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-23 19:25:37 +09:00

148 lines
3.5 KiB
C

#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "driver/uart.h"
#include <mruby/uart.h>
#define RX_TASK_BUF_SIZE 128
#define QUEUE_LENGTH 20
#define TASK_STACK_SIZE 4096
#define TASK_PRIORITY 12
typedef struct {
int unit;
QueueHandle_t queue;
mrb_uart_ringbuf *rxbuf;
} uart_ctx;
static uart_ctx ctx[UART_NUM_MAX];
static void
rx_task(void *arg)
{
uart_ctx *c = (uart_ctx*)arg;
uart_event_t event;
uint8_t buf[RX_TASK_BUF_SIZE];
for (;;) {
if (xQueueReceive(c->queue, &event, portMAX_DELAY)) {
if (event.type == UART_DATA) {
size_t n = event.size > RX_TASK_BUF_SIZE ? RX_TASK_BUF_SIZE : event.size;
uart_read_bytes(c->unit, buf, n, portMAX_DELAY);
for (size_t i = 0; i < n; i++) {
mrb_uart_ringbuf_push(c->rxbuf, buf[i]);
}
}
}
}
}
int
mrb_uart_unit_name_to_num(const char *name)
{
if (strcmp(name, "ESP32_UART0") == 0) return UART_NUM_0;
if (strcmp(name, "ESP32_UART1") == 0) return UART_NUM_1;
#ifdef UART_NUM_2
if (strcmp(name, "ESP32_UART2") == 0) return UART_NUM_2;
#endif
return MRB_UART_ERROR_UNIT;
}
mrb_uart_status
mrb_uart_init(int unit, uint32_t tx_pin, uint32_t rx_pin,
mrb_uart_ringbuf *rxbuf)
{
if (unit < 0 || unit >= UART_NUM_MAX) return MRB_UART_ERROR_UNIT;
uart_config_t cfg = {
.baud_rate = 9600,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_DEFAULT,
};
int bufsize = (rxbuf->mask + 1);
uart_driver_install(unit, bufsize, 0, QUEUE_LENGTH, &ctx[unit].queue, 0);
uart_param_config(unit, &cfg);
uart_set_pin(unit, tx_pin, rx_pin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
ctx[unit].unit = unit;
ctx[unit].rxbuf = rxbuf;
char name[32];
snprintf(name, sizeof(name), "uart_rx_%d", unit);
xTaskCreate(rx_task, name, TASK_STACK_SIZE, &ctx[unit], TASK_PRIORITY, NULL);
return MRB_UART_OK;
}
uint32_t
mrb_uart_set_baudrate(int unit, uint32_t baudrate)
{
uart_set_baudrate(unit, baudrate);
return baudrate;
}
void
mrb_uart_set_format(int unit, uint32_t data_bits, uint32_t stop_bits,
uint8_t parity)
{
static const uart_word_length_t wl[] = {
UART_DATA_5_BITS, UART_DATA_6_BITS, UART_DATA_7_BITS, UART_DATA_8_BITS
};
static const uart_stop_bits_t sb[] = {
UART_STOP_BITS_1, UART_STOP_BITS_2
};
static const uart_parity_t pr[] = {
UART_PARITY_DISABLE, UART_PARITY_EVEN, UART_PARITY_ODD
};
if (data_bits >= 5 && data_bits <= 8)
uart_set_word_length(unit, wl[data_bits - 5]);
if (stop_bits >= 1 && stop_bits <= 2)
uart_set_stop_bits(unit, sb[stop_bits - 1]);
if (parity <= 2)
uart_set_parity(unit, pr[parity]);
}
void
mrb_uart_set_flow_control(int unit, bool cts, bool rts)
{
uart_hw_flowcontrol_t mode = UART_HW_FLOWCTRL_DISABLE;
if (cts && rts) mode = UART_HW_FLOWCTRL_CTS_RTS;
else if (cts) mode = UART_HW_FLOWCTRL_CTS;
else if (rts) mode = UART_HW_FLOWCTRL_RTS;
uart_set_hw_flow_ctrl(unit, mode, 122);
}
void
mrb_uart_write(int unit, const uint8_t *src, size_t len)
{
uart_write_bytes(unit, (const char*)src, len);
}
void
mrb_uart_flush(int unit)
{
uart_wait_tx_done(unit, 100);
}
void
mrb_uart_send_break(int unit, uint32_t duration_ms)
{
uart_write_bytes_with_break(unit, NULL, 0, duration_ms);
}
void
mrb_uart_clear_rx(int unit)
{
uart_flush_input(unit);
}
void
mrb_uart_clear_tx(int unit)
{
/* not supported on ESP-IDF */
}