Hi I'm testing Fiasco.OC+L4re on YSE5250 (Exynos 5250) Board. I have compiled and tested some examples. I'm testing a GPS Driver for the board. The GPS is conected over UART3 at 9600 baudrate, first I'm testing UART3 port comunicating the UART1 serial output with UART3. I'm following as example the serial-drv package on L4re. I have adapted the source code to my uart driver
gps_drv.cc
#include <l4/drivers/uart_s3c2410.h> #include <l4/io/io.h> #include <l4/re/env> #include <l4/re/error_helper> #include <l4/re/namespace> #include <l4/re/util/cap_alloc> #include <l4/re/util/object_registry> #include <l4/re/util/icu_svr> #include <l4/re/util/vcon_svr> #include <l4/sys/irq> #include <l4/util/util.h>
#include <cstdlib> #include <cstdio>
#define IRQ_NUM 86 #define UART_BASE 0x12C30000
static L4::Cap<void> srv_rcv_cap;
class Loop_hooks : public L4::Ipc_svr::Ignore_errors, public L4::Ipc_svr::Default_timeout, public L4::Ipc_svr::Compound_reply { public: void setup_wait(L4::Ipc::Istream &istr, bool) { istr.reset(); istr << L4::Ipc::Small_buf(srv_rcv_cap.cap(), L4_RCV_ITEM_LOCAL_ID); l4_utcb_br_u(istr.utcb())->bdr = 0; } };
using L4Re::Env; using L4Re::Util::Registry_server; static Registry_server<Loop_hooks> server(l4_utcb(), Env::env()->main_thread(), Env::env()->factory());
using L4Re::Util::Vcon_svr; using L4Re::Util::Icu_cap_array_svr;
class GPS_server : public Vcon_svr<GPS_server>, public Icu_cap_array_svr<GPS_server>, public L4::Server_object { public: GPS_server(); virtual ~GPS_server() throw() {}
bool running() const { return _running; }
int vcon_write(const char *buffer, unsigned size); unsigned vcon_read(char *buffer, unsigned size);
L4::Cap<void> rcv_cap() { return srv_rcv_cap; }
int handle_irq();
bool init(); int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios);
private: bool _running; L4::Uart *_uart; L4::CapL4::Irq _uart_irq; Icu_cap_array_svr<GPS_server>::Irq _irq; };
GPS_server::GPS_server() : Icu_cap_array_svr<GPS_server>(1, &_irq), _running(false), _uart(0), _uart_irq(L4_INVALID_CAP), _irq() { if (init()) _running = true; }
int GPS_server::vcon_write(const char *buffer, unsigned size) { _uart->write(buffer, size); return -L4_EOK; }
unsigned GPS_server::vcon_read(char *buffer, unsigned size) { unsigned i = 0; while (_uart->char_avail() && size) { int c = _uart->get_char(false); if (c >= 0) { buffer[i++] = (char)c; size--; } else break; } // if there still some data available send this info to the client if (_uart->char_avail()) i++; else _uart_irq->unmask(); return i; }
int GPS_server::handle_irq() { if (_irq.cap().is_valid()) _irq.cap()->trigger();
return L4_EOK; }
bool GPS_server::init() { l4_addr_t virt_base = 0;
// Mapeando memoria de registros del UART if (l4io_request_iomem((l4_addr_t)UART_BASE, 0x1000, L4IO_MEM_NONCACHED, &virt_base)) { printf("gps-drv: request io-memory from l4io failed.\n"); return false; } printf("gps-drv: virtual base at:%lx\n", virt_base);
// Inicializando memoria de los registros del UART L4::Io_register_block_mmio *regs = new L4::Io_register_block_mmio(virt_base);
// Inicializando UART _uart = new (malloc(sizeof(L4::Uart_s5pv210))) L4::Uart_s5pv210; _uart->startup(regs);
/** * FIX - Ajustando el BaudRate del UART * Valores calculados experimentalmente a través del UART1 * SCLK_UART = 100 MHz * TODO - Hacer el ajuste del BaudRate en el propio UART */ regs->write<unsigned int>(0x28,0x28a); regs->write<unsigned int>(0x2C,0x0);
_uart_irq = L4Re::Util::cap_alloc.allocL4::Irq(); if (!_uart_irq.is_valid()) { printf("gps-drv: Alloc capability for uart-irq failed.\n"); return false; }
if (l4io_request_irq(IRQ_NUM, _uart_irq.cap())) { printf("gps-drv: request uart-irq from l4io failed\n"); return false; }
/* setting IRQ type to L4_IRQ_F_POS_EDGE seems to be wrong place */ if (l4_error(_uart_irq->attach((l4_umword_t)static_cast<L4::Server_object *>(this), L4Re::Env::env()->main_thread()))) { printf("gps-drv: attach to uart-irq failed.\n"); return false; }
if ((l4_ipc_error(_uart_irq->unmask(), l4_utcb()))) { printf("gps-drv: unmask uart-irq failed.\n"); return false; } _uart->enable_rx_irq(true);
srv_rcv_cap = L4Re::Util::cap_alloc.alloc<void>(); if (!srv_rcv_cap.is_valid()) { printf("serial-drv: Alloc capability for rcv-cap failed.\n"); return false; }
return true; }
int GPS_server::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios) { l4_msgtag_t tag; ios >> tag; switch (tag.label()) { case L4_PROTO_IRQ: if (!L4Re::Util::Icu_svr<GPS_server>::dispatch(obj, ios)) return handle_irq(); case L4_PROTO_LOG: return L4Re::Util::Vcon_svr<GPS_server>::dispatch(obj, ios); default: return -L4_EBADPROTO; } }
int main() { char buffer[100]; int tmp; static GPS_server gps_srv;
// Register calculation server if (!server.registry()->register_obj(&gps_srv, "gps_srv").is_valid()) { printf("Could not register GPS service, is there a 'gps_srv' in the caps table?\n"); return 1; }
if (!gps_srv.running()) { printf("Failed to initialize serial driver; Aborting.\n"); return 1; }
gps_srv.vcon_write("Hola Mundo\n",11); while(1){ tmp = gps_srv.vcon_read(buffer,11); if(tmp>0) printf("Readed data: %s\n",buffer); } // Wait for client requests server.loop(); return 0; }
I have created my run config file
gps-drv.cfg
require("L4"); -- Shortcuts local ld = L4.default_loader; local vbus_uart03 = ld:new_channel(); local platform_ctl = ld:new_channel(); local gps_srv = ld:new_channel(); -- Start the IO Server ld:start( { caps = { sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0); icu = L4.Env.icu; platform_ctl = platform_ctl:svr(); uart03 = vbus_uart03:svr(); }, log = { "IO Server", "green" }, l4re_dbg = L4.Dbg.Warn, }, "rom/io rom/yse5250.devs rom/yse5250.io");
-- Start the GPS Driver Server conected to UART3 ld:start( { caps = { gps_srv = gps_srv:svr(); vbus = vbus_uart03; }, log = {"GPS Driver","blue"} }, "rom/gps_drv");
And have created the yse5250.devs and yse5250.io to put the UART3 on a virtual BUS
yse5250.devs
local Hw = Io.Hw local Res = Io.Res Io.hw_add_devices { UART3 = Hw.Device { hid = "UART3"; Res.irq(86); Res.mmio(0x12C30000, 0x12C3ffff); } }
yse5250.io
Io.add_vbusses { -- Create a virtual bus for a client and give access to UART3 uart03 = Io.Vi.System_bus(function () dev = wrap(Io.system_bus():match("UART3")); end); }
On modules.list have added an entry for my example
entry GPS-Driver kernel fiasco -serial_esc roottask moe rom/gps-drv.cfg module l4re module ned module gps-drv.cfg module gps_drv module io module yse5250.devs module yse5250.io
After that i have compiled and uploaded the example to the board. At runtime, i got the "Hola Mundo" over UART3 but when I write in the UART3 I never read the written information. Something is wrong with my code?
Hi,
it is hard to see any obvious errors in your code and without the hardware to test it is hard to give any hints beyond educated guesses.
You should start instrumenting your code (vcon_read) and see what's going on there. You can also check in jdb whether the hardware interrupt gets triggered for UART3.
Matthias.
On 02/23/2015 01:31 AM, Reinier Millo Sánchez wrote:
Hi I'm testing Fiasco.OC+L4re on YSE5250 (Exynos 5250) Board. I have compiled and tested some examples. I'm testing a GPS Driver for the board. The GPS is conected over UART3 at 9600 baudrate, first I'm testing UART3 port comunicating the UART1 serial output with UART3. I'm following as example the serial-drv package on L4re. I have adapted the source code to my uart driver
gps_drv.cc
#include <l4/drivers/uart_s3c2410.h> #include <l4/io/io.h> #include <l4/re/env> #include <l4/re/error_helper> #include <l4/re/namespace> #include <l4/re/util/cap_alloc> #include <l4/re/util/object_registry> #include <l4/re/util/icu_svr> #include <l4/re/util/vcon_svr> #include <l4/sys/irq> #include <l4/util/util.h> #include <cstdlib> #include <cstdio> #define IRQ_NUM 86 #define UART_BASE 0x12C30000 static L4::Cap<void> srv_rcv_cap; class Loop_hooks : public L4::Ipc_svr::Ignore_errors, public L4::Ipc_svr::Default_timeout, public L4::Ipc_svr::Compound_reply { public: void setup_wait(L4::Ipc::Istream &istr, bool) { istr.reset(); istr << L4::Ipc::Small_buf(srv_rcv_cap.cap(), L4_RCV_ITEM_LOCAL_ID); l4_utcb_br_u(istr.utcb())->bdr = 0; } }; using L4Re::Env; using L4Re::Util::Registry_server; static Registry_server<Loop_hooks> server(l4_utcb(), Env::env()->main_thread(), Env::env()->factory()); using L4Re::Util::Vcon_svr; using L4Re::Util::Icu_cap_array_svr; class GPS_server : public Vcon_svr<GPS_server>, public Icu_cap_array_svr<GPS_server>, public L4::Server_object { public: GPS_server(); virtual ~GPS_server() throw() {} bool running() const { return _running; } int vcon_write(const char *buffer, unsigned size); unsigned vcon_read(char *buffer, unsigned size); L4::Cap<void> rcv_cap() { return srv_rcv_cap; } int handle_irq(); bool init(); int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios); private: bool _running; L4::Uart *_uart; L4::Cap<L4::Irq> _uart_irq; Icu_cap_array_svr<GPS_server>::Irq _irq; }; GPS_server::GPS_server() : Icu_cap_array_svr<GPS_server>(1, &_irq), _running(false), _uart(0), _uart_irq(L4_INVALID_CAP), _irq() { if (init()) _running = true; } int GPS_server::vcon_write(const char *buffer, unsigned size) { _uart->write(buffer, size); return -L4_EOK; } unsigned GPS_server::vcon_read(char *buffer, unsigned size) { unsigned i = 0; while (_uart->char_avail() && size) { int c = _uart->get_char(false); if (c >= 0) { buffer[i++] = (char)c; size--; } else break; } // if there still some data available send this info to the client if (_uart->char_avail()) i++; else _uart_irq->unmask(); return i; } int GPS_server::handle_irq() { if (_irq.cap().is_valid()) _irq.cap()->trigger(); return L4_EOK; } bool GPS_server::init() { l4_addr_t virt_base = 0; // Mapeando memoria de registros del UART if (l4io_request_iomem((l4_addr_t)UART_BASE, 0x1000, L4IO_MEM_NONCACHED, &virt_base)) { printf("gps-drv: request io-memory from l4io failed.\n"); return false; } printf("gps-drv: virtual base at:%lx\n", virt_base); // Inicializando memoria de los registros del UART L4::Io_register_block_mmio *regs = new L4::Io_register_block_mmio(virt_base); // Inicializando UART _uart = new (malloc(sizeof(L4::Uart_s5pv210))) L4::Uart_s5pv210; _uart->startup(regs); /** * FIX - Ajustando el BaudRate del UART * Valores calculados experimentalmente a través del UART1 * SCLK_UART = 100 MHz * TODO - Hacer el ajuste del BaudRate en el propio UART */ regs->write<unsigned int>(0x28,0x28a); regs->write<unsigned int>(0x2C,0x0); _uart_irq = L4Re::Util::cap_alloc.alloc<L4::Irq>(); if (!_uart_irq.is_valid()) { printf("gps-drv: Alloc capability for uart-irq failed.\n"); return false; } if (l4io_request_irq(IRQ_NUM, _uart_irq.cap())) { printf("gps-drv: request uart-irq from l4io failed\n"); return false; } /* setting IRQ type to L4_IRQ_F_POS_EDGE seems to be wrong place */ if (l4_error(_uart_irq->attach((l4_umword_t)static_cast<L4::Server_object *>(this), L4Re::Env::env()->main_thread()))) { printf("gps-drv: attach to uart-irq failed.\n"); return false; } if ((l4_ipc_error(_uart_irq->unmask(), l4_utcb()))) { printf("gps-drv: unmask uart-irq failed.\n"); return false; } _uart->enable_rx_irq(true); srv_rcv_cap = L4Re::Util::cap_alloc.alloc<void>(); if (!srv_rcv_cap.is_valid()) { printf("serial-drv: Alloc capability for rcv-cap failed.\\n"); return false; } return true; } int GPS_server::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios) { l4_msgtag_t tag; ios >> tag; switch (tag.label()) { case L4_PROTO_IRQ: if (!L4Re::Util::Icu_svr<GPS_server>::dispatch(obj, ios)) return handle_irq(); case L4_PROTO_LOG: return L4Re::Util::Vcon_svr<GPS_server>::dispatch(obj, ios); default: return -L4_EBADPROTO; } } int main() { char buffer[100]; int tmp; static GPS_server gps_srv; // Register calculation server if (!server.registry()->register_obj(&gps_srv, "gps_srv").is_valid()) { printf("Could not register GPS service, is there a 'gps_srv' in the caps table?\n"); return 1; } if (!gps_srv.running()) { printf("Failed to initialize serial driver; Aborting.\n"); return 1; } gps_srv.vcon_write("Hola Mundo\n",11); while(1){ tmp = gps_srv.vcon_read(buffer,11); if(tmp>0) printf("Readed data: %s\n",buffer); } // Wait for client requests server.loop(); return 0; }
I have created my run config file
gps-drv.cfg
require("L4"); -- Shortcuts local ld = L4.default_loader; local vbus_uart03 = ld:new_channel(); local platform_ctl = ld:new_channel(); local gps_srv = ld:new_channel(); -- Start the IO Server ld:start( { caps = { sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0); icu = L4.Env.icu; platform_ctl = platform_ctl:svr(); uart03 = vbus_uart03:svr(); }, log = { "IO Server", "green" }, l4re_dbg = L4.Dbg.Warn, }, "rom/io rom/yse5250.devs rom/yse5250.io"); -- Start the GPS Driver Server conected to UART3 ld:start( { caps = { gps_srv = gps_srv:svr(); vbus = vbus_uart03; }, log = {"GPS Driver","blue"} }, "rom/gps_drv");
And have created the yse5250.devs and yse5250.io to put the UART3 on a virtual BUS
yse5250.devs
local Hw = Io.Hw local Res = Io.Res Io.hw_add_devices { UART3 = Hw.Device { hid = "UART3"; Res.irq(86); Res.mmio(0x12C30000, 0x12C3ffff); } }
yse5250.io
Io.add_vbusses { -- Create a virtual bus for a client and give access to UART3 uart03 = Io.Vi.System_bus(function () dev = wrap(Io.system_bus():match("UART3")); end); }
On modules.list have added an entry for my example
entry GPS-Driver kernel fiasco -serial_esc roottask moe rom/gps-drv.cfg module l4re module ned module gps-drv.cfg module gps_drv module io module yse5250.devs module yse5250.io
After that i have compiled and uploaded the example to the board. At runtime, i got the "Hola Mundo" over UART3 but when I write in the UART3 I never read the written information. Something is wrong with my code?
-- Lic. Reinier Millo Sánchez Centro de Estudios de Informática Universidad Central "Marta Abreu" de Las Villas
"antes de discutir ... respira; antes de hablar ... escucha; antes de escribir ... piensa; antes de herir ... siente; antes de rendirte ... intenta; antes de morir ... vive"
l4-hackers mailing list l4-hackers@os.inf.tu-dresden.de http://os.inf.tu-dresden.de/mailman/listinfo/l4-hackers
l4-hackers@os.inf.tu-dresden.de