rt-thread-official/bsp/simulator/drivers/uart_console.c

278 lines
6.1 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.

/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include <stdio.h>
#include <rthw.h>
#include <rtdevice.h>
#include <rtthread.h>
#include <rtdevice.h>
/* uart driver */
struct console_uart
{
int rx_ready;
struct rt_ringbuffer rb;
rt_uint8_t rx_buffer[256];
} _console_uart;
static struct rt_serial_device _serial;
#define SAVEKEY(key) do { char ch = key; rt_ringbuffer_put_force(&(_console_uart.rb), &ch, 1); } while (0)
#ifdef _WIN32
#include <windows.h>
#include <mmsystem.h>
#include <conio.h>
extern int getch(void);
/*
* Handler for OSKey Thread
*/
static HANDLE OSKey_Thread;
static DWORD OSKey_ThreadID;
static DWORD WINAPI ThreadforKeyGet(LPVOID lpParam);
void console_lowlevel_init(void)
{
/*
* create serial thread that receive key input from keyboard
*/
OSKey_Thread = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)ThreadforKeyGet,
0,
CREATE_SUSPENDED,
&OSKey_ThreadID);
if (OSKey_Thread == NULL)
{
//Display Error Message
return;
}
SetThreadPriority(OSKey_Thread,
THREAD_PRIORITY_NORMAL);
SetThreadPriorityBoost(OSKey_Thread,
TRUE);
SetThreadAffinityMask(OSKey_Thread,
0x01);
/*
* Start OS get key Thread
*/
ResumeThread(OSKey_Thread);
}
static DWORD WINAPI ThreadforKeyGet(LPVOID lpParam)
#else /* POSIX version */
#include <pthread.h>
#include <semaphore.h>
#include <stdlib.h>
#include <signal.h>
#include <termios.h> /* for tcxxxattr, ECHO, etc */
#include <unistd.h> /* for STDIN_FILENO */
static void * ThreadforKeyGet(void * lpParam);
static pthread_t OSKey_Thread;
void console_lowlevel_init(void)
{
int res;
res = pthread_create(&OSKey_Thread, NULL, &ThreadforKeyGet, NULL);
if (res)
{
printf("pthread create faild, <%d>\n", res);
exit(EXIT_FAILURE);
}
}
static struct termios oldt, newt;
/*simulate windows' getch(), it works!!*/
static void set_stty(void)
{
/* get terminal input's attribute */
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
/* set termios' local mode */
newt.c_lflag &= ~(ECHO|ICANON);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
}
void restore_stty(void)
{
/* recover terminal's attribute */
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
}
#define getch getchar
static void * ThreadforKeyGet(void * lpParam)
#endif /* not _WIN32*/
{
/*
* left key(左) 0xe04b
* up key(上) 0xe048
* right key(右) 0xe04d
* down key(下) 0xe050
*/
unsigned char key;
#ifndef _WIN32
sigset_t sigmask, oldmask;
/* set the getchar without buffer */
sigfillset(&sigmask);
pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask);
set_stty();
#endif
(void)lpParam; //prevent compiler warnings
for (;;)
{
key = getch();
#ifdef _WIN32
if (key == 0xE0)
{
key = getch();
if (key == 0x48) //up key , 0x1b 0x5b 0x41
{
SAVEKEY(0x1b);
SAVEKEY(0x5b);
SAVEKEY(0x41);
}
else if (key == 0x50)//0x1b 0x5b 0x42
{
SAVEKEY(0x1b);
SAVEKEY(0x5b);
SAVEKEY(0x42);
}
else if (key == 0x4b)//<- 0x1b 0x5b 0x44
{
SAVEKEY(0x1b);
SAVEKEY(0x5b);
SAVEKEY(0x44);
}
else if (key == 0x4d)//<- 0x1b 0x5b 0x43
{
SAVEKEY(0x1b);
SAVEKEY(0x5b);
SAVEKEY(0x43);
}
continue;
}
#endif
SAVEKEY(key);
/* Notfiy serial ISR */
rt_hw_serial_isr(&_serial, RT_SERIAL_EVENT_RX_IND);
}
return RT_NULL;
} /*** ThreadforKeyGet ***/
static rt_err_t console_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
{
/* no baudrate, nothing */
return RT_EOK;
}
static rt_err_t console_control(struct rt_serial_device *serial, int cmd, void *arg)
{
struct console_uart* uart;
RT_ASSERT(serial != RT_NULL);
uart = (struct console_uart *)serial->parent.user_data;
switch (cmd)
{
case RT_DEVICE_CTRL_CLR_INT:
uart->rx_ready = 0;
break;
case RT_DEVICE_CTRL_SET_INT:
uart->rx_ready = 1;
break;
}
return RT_EOK;
}
static int console_putc(struct rt_serial_device *serial, char c)
{
int level;
RT_ASSERT(serial != RT_NULL);
#if 0 /* Enable it if you want to save the console log */
{
static FILE* fp = NULL;
if (fp == NULL)
fp = fopen("log.txt", "wb+");
if (fp != NULL)
fwrite(buffer, size, 1, fp);
}
#endif
level = rt_hw_interrupt_disable();
fwrite(&c, 1, 1, stdout);
fflush(stdout);
rt_hw_interrupt_enable(level);
return 1;
}
static int console_getc(struct rt_serial_device *serial)
{
char ch;
struct console_uart* uart;
RT_ASSERT(serial != RT_NULL);
uart = (struct console_uart *)serial->parent.user_data;
if (rt_ringbuffer_getchar(&(uart->rb), &ch)) return ch;
return -1;
}
static const struct rt_uart_ops console_uart_ops =
{
console_configure,
console_control,
console_putc,
console_getc,
};
int uart_console_init(void)
{
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
struct console_uart* uart;
struct rt_serial_device* serial;
uart = &_console_uart;
serial = &_serial;
uart->rx_ready = 0;
serial->ops = &console_uart_ops;
serial->config = config;
/* initialize ring buffer */
rt_ringbuffer_init(&uart->rb, uart->rx_buffer, sizeof(uart->rx_buffer));
/* register UART device */
rt_hw_serial_register(serial, "console",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
uart);
console_lowlevel_init();
return 0;
}