With this patch, the kernel fetches serial data also when the '-serial_esc' option is not set. To keep the patch minimally invasive, the 'serial ESC' functionality gets enabled by default and the existence of the '-serial_esc' argument gets only checked when an ESC character was received and the decision of entering the kernel debugger or not needs to be made. Fixes ssumpf/foc#3.
238 lines
4.4 KiB
C++
238 lines
4.4 KiB
C++
INTERFACE:
|
|
|
|
class Irq_base;
|
|
|
|
class Vkey
|
|
{
|
|
public:
|
|
enum Echo_type { Echo_off = 0, Echo_on = 1, Echo_crnl = 2 };
|
|
};
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
IMPLEMENTATION:
|
|
|
|
#include "irq_chip.h"
|
|
|
|
static Irq_base *vkey_irq;
|
|
|
|
PUBLIC static
|
|
void
|
|
Vkey::irq(Irq_base *i)
|
|
{ vkey_irq = i; }
|
|
|
|
// ---------------------------------------------------------------------------
|
|
IMPLEMENTATION [debug && serial && !ux]:
|
|
|
|
#include <cstdio>
|
|
|
|
#include "config.h"
|
|
#include "cpu.h"
|
|
#include "globals.h"
|
|
#include "kernel_console.h"
|
|
#include "keycodes.h"
|
|
#include "koptions.h"
|
|
#include "uart.h"
|
|
|
|
static Vkey::Echo_type vkey_echo;
|
|
static char vkey_buffer[256];
|
|
static unsigned vkey_tail, vkey_head;
|
|
static Console *uart = Kconsole::console()->find_console(Console::UART);
|
|
|
|
PUBLIC static
|
|
void
|
|
Vkey::set_echo(Echo_type echo)
|
|
{
|
|
vkey_echo = echo;
|
|
}
|
|
|
|
PRIVATE static
|
|
bool
|
|
Vkey::add(int c)
|
|
{
|
|
bool hit = false;
|
|
unsigned nh = (vkey_head + 1) % sizeof(vkey_buffer);
|
|
unsigned oh = vkey_head;
|
|
if (nh != vkey_tail)
|
|
{
|
|
vkey_buffer[vkey_head] = c;
|
|
vkey_head = nh;
|
|
}
|
|
|
|
if (oh == vkey_tail)
|
|
hit = true;
|
|
|
|
if (vkey_echo == Vkey::Echo_crnl && c == '\r')
|
|
c = '\n';
|
|
|
|
if (vkey_echo)
|
|
putchar(c);
|
|
|
|
return hit;
|
|
}
|
|
|
|
PRIVATE static
|
|
bool
|
|
Vkey::add(const char *seq)
|
|
{
|
|
bool hit = false;
|
|
for (; *seq; ++seq)
|
|
hit |= add(*seq);
|
|
return hit;
|
|
}
|
|
|
|
PRIVATE static
|
|
void
|
|
Vkey::trigger()
|
|
{
|
|
if (vkey_irq)
|
|
vkey_irq->hit(0);
|
|
}
|
|
|
|
PUBLIC static
|
|
void
|
|
Vkey::add_char(int v)
|
|
{
|
|
if (add(v))
|
|
trigger();
|
|
}
|
|
|
|
PUBLIC static
|
|
int
|
|
Vkey::check_()
|
|
{
|
|
if (!uart)
|
|
return 1;
|
|
|
|
int ret = 1;
|
|
bool hit = false;
|
|
|
|
// disable last branch recording, branch trace recording ...
|
|
Cpu::cpus.cpu(current_cpu()).debugctl_disable();
|
|
|
|
while (1)
|
|
{
|
|
int c = uart->getchar(false);
|
|
|
|
if (c == -1)
|
|
break;
|
|
|
|
if ((c == KEY_ESC) && (Koptions::o()->opt(Koptions::F_serial_esc)))
|
|
{
|
|
ret = 0; // break into kernel debugger
|
|
break;
|
|
}
|
|
|
|
switch (c)
|
|
{
|
|
case KEY_CURSOR_UP: hit |= add("\033[A"); break;
|
|
case KEY_CURSOR_DOWN: hit |= add("\033[B"); break;
|
|
case KEY_CURSOR_LEFT: hit |= add("\033[D"); break;
|
|
case KEY_CURSOR_RIGHT: hit |= add("\033[C"); break;
|
|
case KEY_CURSOR_HOME: hit |= add("\033[1~"); break;
|
|
case KEY_CURSOR_END: hit |= add("\033[4~"); break;
|
|
case KEY_PAGE_UP: hit |= add("\033[5~"); break;
|
|
case KEY_PAGE_DOWN: hit |= add("\033[6~"); break;
|
|
case KEY_INSERT: hit |= add("\033[2~"); break;
|
|
case KEY_DELETE: hit |= add("\033[3~"); break;
|
|
case KEY_F1: hit |= add("\033OP"); break;
|
|
case KEY_BACKSPACE: hit |= add(127); break;
|
|
case KEY_TAB: hit |= add(9); break;
|
|
case KEY_ESC: hit |= add(27); break;
|
|
case KEY_RETURN: hit |= add(13); break;
|
|
default: hit |= add(c); break;
|
|
}
|
|
}
|
|
|
|
if (hit)
|
|
trigger();
|
|
|
|
// Hmmm, we assume that a console with the UART flag set is of type Uart
|
|
if (Config::serial_esc == Config::SERIAL_ESC_IRQ)
|
|
static_cast<Uart*>(uart)->enable_rcv_irq();
|
|
|
|
// reenable debug stuff (undo debugctl_disable)
|
|
Cpu::cpus.cpu(current_cpu()).debugctl_enable();
|
|
|
|
return ret;
|
|
}
|
|
|
|
PUBLIC static
|
|
int
|
|
Vkey::get()
|
|
{
|
|
if (vkey_tail != vkey_head)
|
|
return vkey_buffer[vkey_tail];
|
|
|
|
return -1;
|
|
}
|
|
|
|
PUBLIC static
|
|
void
|
|
Vkey::clear()
|
|
{
|
|
if (vkey_tail != vkey_head)
|
|
vkey_tail = (vkey_tail + 1) % sizeof(vkey_buffer);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
IMPLEMENTATION [!debug || !serial || ux]:
|
|
|
|
PUBLIC static inline
|
|
void
|
|
Vkey::set_echo(Echo_type)
|
|
{}
|
|
|
|
PUBLIC static inline
|
|
void
|
|
Vkey::clear()
|
|
{}
|
|
|
|
PUBLIC static inline
|
|
void
|
|
Vkey::add_char(int)
|
|
{}
|
|
|
|
//----------------------------------------------------------------------------
|
|
IMPLEMENTATION [debug && (!serial || ux)]:
|
|
|
|
#include "kernel_console.h"
|
|
|
|
PUBLIC static
|
|
int
|
|
Vkey::get()
|
|
{
|
|
return Kconsole::console()->getchar(0);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
IMPLEMENTATION [!debug && serial]:
|
|
|
|
#include "kernel_console.h"
|
|
#include "kernel_uart.h"
|
|
|
|
static Console *uart = Kconsole::console()->find_console(Console::UART);
|
|
|
|
PUBLIC static
|
|
int
|
|
Vkey::get()
|
|
{
|
|
return uart->getchar(false);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
IMPLEMENTATION[!debug && !serial]:
|
|
|
|
PUBLIC static
|
|
int
|
|
Vkey::get()
|
|
{ return -1; }
|
|
|
|
//----------------------------------------------------------------------------
|
|
IMPLEMENTATION[!debug || !serial]:
|
|
|
|
PUBLIC static inline
|
|
int
|
|
Vkey::check_(int = -1)
|
|
{ return 0; }
|