Fiasco(.OC) KDB UART driver

The KDB UART driver uses the Fiasco(.OC) kernel debugger console as backend
for input and output. This is useful in the case that only one UART is
available.

Fixes #665.
This commit is contained in:
Christian Prochaska 2013-03-18 14:50:32 +01:00 committed by Norman Feske
parent 4bb0a8231e
commit 452624e1a6
10 changed files with 314 additions and 6 deletions

View File

@ -76,8 +76,12 @@ proc bin_dir { } {
exit 1
}
set fiasco_serial_esc_arg "-serial_esc "
proc build_boot_image {binaries} {
global fiasco_serial_esc_arg
#
# Collect contents of the ISO image
#
@ -108,7 +112,7 @@ proc build_boot_image {binaries} {
puts $fh "default 0"
puts $fh "\ntitle Genode on L4/Fiasco"
puts $fh " kernel /fiasco/bootstrap -serial -modaddr=0x02000000"
puts $fh " module /fiasco/fiasco -serial -serial_esc -jdb_cmd=JH"
puts $fh " module /fiasco/fiasco -serial -jdb_cmd=JH $fiasco_serial_esc_arg"
puts $fh " module /fiasco/sigma0"
puts $fh " module /genode/core"
puts $fh " module /genode/config"

View File

@ -136,9 +136,12 @@ proc build_boot_uimage { } {
}
}
set fiasco_serial_esc_arg "-serial_esc "
proc build_boot_image_x86 {binaries} {
global fiasco_serial_esc_arg
copy_and_strip_binaries $binaries
set foc_targets { }
@ -171,7 +174,7 @@ proc build_boot_image_x86 {binaries} {
puts $fh "default 0"
puts $fh "\ntitle Genode on Fiasco.OC"
puts $fh " kernel /fiasco/bootstrap -modaddr=0x01100000"
puts $fh " module /fiasco/fiasco -serial_esc"
puts $fh " module /fiasco/fiasco $fiasco_serial_esc_arg"
puts $fh " module /fiasco/sigma0"
puts $fh " module /genode/core"
puts $fh " module /genode/config"
@ -187,6 +190,8 @@ proc build_boot_image_x86 {binaries} {
proc build_boot_image_arm {binaries} {
global fiasco_serial_esc_arg
copy_and_strip_binaries $binaries
build "kernel sigma0 bootstrap"
@ -198,7 +203,7 @@ proc build_boot_image_arm {binaries} {
puts $fh "modaddr 0x01100000\n"
puts $fh "entry genode"
puts $fh "kernel [fiasco] -serial_esc"
puts $fh "kernel [fiasco] $fiasco_serial_esc_arg"
puts $fh "roottask genode/core"
puts $fh "module genode/config"
foreach binary $binaries {

89
os/run/kdb_uart_drv.run Normal file
View File

@ -0,0 +1,89 @@
#
# \brief Test for the KDB UART driver
# \author Christian Prochaska
# \date 2013-01-21
#
if {![have_spec foc] && ![have_spec fiasco]} {
puts "Run script only supports Fiasco/Fiasco.OC."; exit 0 }
#
# Build
#
build {
core init
drivers/timer
drivers/uart
test/terminal_echo
}
create_boot_directory
#
# Generate config
#
set config {
<config verbose="yes">
<parent-provides>
<service name="ROM"/>
<service name="RAM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="CAP"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
<service name="SIGNAL"/>
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<start name="timer">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Timer"/> </provides>
</start>
<start name="kdb_uart_drv">
<resource name="RAM" quantum="2M"/>
<provides>
<service name="Terminal"/>
<service name="Uart"/>
</provides>
<config>
<policy label="test-terminal_echo" uart="0" detect_size="yes"/>
</config>
</start>
<start name="test-terminal_echo">
<resource name="RAM" quantum="1M"/>
</start>
</config>
}
install_config $config
#
# Boot modules
#
# generic modules
set boot_modules {
core init timer
kdb_uart_drv
test-terminal_echo
}
set fiasco_serial_esc_arg ""
build_boot_image $boot_modules
#
# Execute test
#
# qemu config
append qemu_args " -m 128 -nographic "
run_genode_until forever

View File

@ -0,0 +1,3 @@
REQUIRES = fiasco
include $(PRG_DIR)/../target.inc

View File

@ -0,0 +1,3 @@
REQUIRES = foc
include $(PRG_DIR)/../target.inc

View File

@ -0,0 +1,118 @@
/*
* \brief Fiasco(.OC) KDB UART driver
* \author Christian Prochaska
* \date 2013-03-07
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _KDB_UART_H_
#define _KDB_UART_H_
/* Fiasco.OC includes */
namespace Fiasco {
#include <l4/sys/kdebug.h>
}
/* Genode includes */
#include <base/thread.h>
#include <timer_session/connection.h>
/* local includes */
#include "uart_driver.h"
using namespace Genode;
class Kdb_uart : public Uart::Driver
{
private:
signed char _buffered_char;
Lock _kdb_read_lock;
enum { STACK_SIZE = 2*1024*sizeof(addr_t) };
class Char_avail_checker_thread : public Thread<STACK_SIZE>
{
private:
Uart::Driver &_uart_driver;
Uart::Char_avail_callback &_char_avail_callback;
public:
Char_avail_checker_thread(Uart::Driver &uart_driver,
Uart::Char_avail_callback &char_avail_callback)
: _uart_driver(uart_driver),
_char_avail_callback(char_avail_callback) { }
void entry()
{
Timer::Connection timer;
for(;;) {
if (_uart_driver.char_avail())
_char_avail_callback();
else
timer.msleep(20);
}
}
} _char_avail_checker_thread;
public:
/**
* Constructor
*/
Kdb_uart(Uart::Char_avail_callback &callback)
: _buffered_char(-1),
_char_avail_checker_thread(*this, callback)
{
_char_avail_checker_thread.start();
}
/***************************
** UART driver interface **
***************************/
void put_char(char c)
{
Fiasco::outchar(c);
}
bool char_avail()
{
Lock_guard<Lock> kdb_read_lock_guard(_kdb_read_lock);
if (_buffered_char == -1)
_buffered_char = Fiasco::l4kd_inchar();
return (_buffered_char != -1);
}
char get_char()
{
char result;
if (_buffered_char != -1) {
result = _buffered_char;
_buffered_char = -1;
} else
result = 0;
return result;
}
void baud_rate(int bits_per_second)
{
}
};
#endif /* _KDB_UART_H_ */

View File

@ -0,0 +1,70 @@
/*
* \brief Fiasco(.OC) KDB UART driver
* \author Christian Prochaska
* \date 2013-03-07
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/printf.h>
#include <base/sleep.h>
#include <cap_session/connection.h>
#include "uart_component.h"
#include "kdb_uart.h"
int main(int argc, char **argv)
{
using namespace Genode;
printf("--- Fiasco(.OC) KDB UART driver started ---\n");
/**
* Factory used by 'Uart::Root' at session creation/destruction time
*/
struct Kdb_uart_driver_factory : Uart::Driver_factory
{
Kdb_uart *uart;
/**
* Constructor
*/
Kdb_uart_driver_factory() : uart(0) { }
Uart::Driver *create(unsigned index, unsigned baudrate,
Uart::Char_avail_callback &callback)
{
/*
* We assume the underlying kernel uses UART0
*/
if (index > 0)
throw Uart::Driver_factory::Not_available();
if (!uart)
uart = new (env()->heap()) Kdb_uart(callback);
return uart;
}
void destroy(Uart::Driver *driver) { /* TODO */ }
} driver_factory;
enum { STACK_SIZE = 2*1024*sizeof(addr_t) };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "uart_ep");
static Uart::Root uart_root(&ep, env()->heap(), driver_factory);
env()->parent()->announce(ep.manage(&uart_root));
sleep_forever();
return 0;
}

View File

@ -0,0 +1,7 @@
TARGET = kdb_uart_drv
SRC_CC = main.cc
LIBS = base
INC_DIR += $(PRG_DIR)/.. $(PRG_DIR)/../..
vpath main.cc $(PRG_DIR)/..

View File

@ -98,8 +98,11 @@ namespace Uart {
*/
Size _detect_size()
{
/* set cursor position to the max */
_put_string("\033[1;199r\033[199;199H");
/*
* Set cursor position to (hopefully) exceed the terminal
* dimensions.
*/
_put_string("\033[1;199r\033[199;255H");
/* flush incoming characters */
for (; _driver.char_avail(); _driver.get_char());

View File

@ -17,6 +17,8 @@
using namespace Genode;
static const bool verbose = false;
int main(int, char **)
{
static Terminal::Connection terminal;
@ -29,13 +31,17 @@ int main(int, char **)
terminal.read_avail_sigh(sig_rec.manage(&sig_ctx));
static const char *intro_text =
"--- Terminal echo test started - now you can type characters to be echoed. ---\n";
terminal.write(intro_text, strlen(intro_text) + 1);
for (;;) {
sig_rec.wait_for_signal();
int num_bytes = terminal.read(read_buffer, sizeof(read_buffer));
if (num_bytes)
if (verbose && (num_bytes > 0))
PDBG("got %d bytes", num_bytes);
for (int i = 0; i < num_bytes; i++)