diff --git a/config/caps.py b/config/caps.py index ffc00c4..7ca98fe 100644 --- a/config/caps.py +++ b/config/caps.py @@ -151,6 +151,18 @@ cap_strings = { 'ipc' : \ \t\t\t\t.start = 0, .end = 0, .size = 0, \t\t\t}, ''' +, 'timer' : \ +''' +\t\t\t[${idx}] = { +\t\t\t\t/* For device selection */ +\t\t\t\t.target = ${cid}, +\t\t\t\t.uattr = CAP_DEVTYPE_TIMER | (${devnum} << 16), +\t\t\t\t.type = CAP_TYPE_MAP_PHYSMEM | CAP_RTYPE_CONTAINER, +\t\t\t\t.access = CAP_MAP_READ | CAP_MAP_WRITE | CAP_MAP_EXEC | +\t\t\t\t\tCAP_MAP_CACHED | CAP_MAP_UNCACHED | CAP_MAP_UNMAP | CAP_MAP_UTCB, +\t\t\t\t.start = 0, .end = 0, .size = 0, +\t\t\t}, +''' } diff --git a/config/cml/container_ruleset.template b/config/cml/container_ruleset.template index 4ab0db3..d37da7e 100644 --- a/config/cml/container_ruleset.template +++ b/config/cml/container_ruleset.template @@ -158,6 +158,7 @@ CONT%(cn)d_BAREMETAL_PROJ1 'Hello World' CONT%(cn)d_BAREMETAL_PROJ2 'Thread Library Demo' CONT%(cn)d_BAREMETAL_PROJ3 'Test Project' CONT%(cn)d_BAREMETAL_PROJ4 'UART Service' +CONT%(cn)d_BAREMETAL_PROJ5 'Timer Service' choices cont%(cn)d_baremetal_params CONT%(cn)d_BAREMETAL_PROJ0 @@ -165,6 +166,7 @@ choices cont%(cn)d_baremetal_params CONT%(cn)d_BAREMETAL_PROJ2 CONT%(cn)d_BAREMETAL_PROJ3 CONT%(cn)d_BAREMETAL_PROJ4 + CONT%(cn)d_BAREMETAL_PROJ5 default CONT%(cn)d_BAREMETAL_PROJ0 menu cont%(cn)d_default_pager_params @@ -218,14 +220,23 @@ symbols cont%(cn)d_device_uart1 'Container %(cn)d UART1 Menu' cont%(cn)d_device_uart2 'Container %(cn)d UART2 Menu' cont%(cn)d_device_uart3 'Container %(cn)d UART3 Menu' +cont%(cn)d_device_timer1 'Container %(cn)d TIMER1 Menu' +cont%(cn)d_device_timer2 'Container %(cn)d TIMER2 Menu' +cont%(cn)d_device_timer3 'Container %(cn)d TIMER3 Menu' CONT%(cn)d_CAP_UART1_DEVICE_USE 'Container %(cn)d UART1 Enable' CONT%(cn)d_CAP_UART2_DEVICE_USE 'Container %(cn)d UART2 Enable' CONT%(cn)d_CAP_UART3_DEVICE_USE 'Container %(cn)d UART3 Enable' +CONT%(cn)d_CAP_TIMER1_DEVICE_USE 'Container %(cn)d TIMER1 Enable' +CONT%(cn)d_CAP_TIMER2_DEVICE_USE 'Container %(cn)d TIMER2 Enable' +CONT%(cn)d_CAP_TIMER3_DEVICE_USE 'Container %(cn)d TIMER3 Enable' default CONT%(cn)d_CAP_UART1_DEVICE_USE from n default CONT%(cn)d_CAP_UART2_DEVICE_USE from n default CONT%(cn)d_CAP_UART3_DEVICE_USE from n +default CONT%(cn)d_CAP_TIMER1_DEVICE_USE from n +default CONT%(cn)d_CAP_TIMER2_DEVICE_USE from n +default CONT%(cn)d_CAP_TIMER3_DEVICE_USE from n # Note: We are suppressing the menu not symbol here, as in future # we will add new parameters to menu, so suprpressing each symbol @@ -290,6 +301,66 @@ when CONT3_CAP_UART3_DEVICE_USE == y suppress cont1_device_uart3 cont2_device_uart3 +when CONT0_CAP_TIMER1_DEVICE_USE == y suppress + cont1_device_timer1 + cont2_device_timer1 + cont3_device_timer1 + +when CONT1_CAP_TIMER1_DEVICE_USE == y suppress + cont0_device_timer1 + cont2_device_timer1 + cont3_device_timer1 + +when CONT2_CAP_TIMER1_DEVICE_USE == y suppress + cont0_device_timer1 + cont1_device_timer1 + cont3_device_timer1 + +when CONT3_CAP_TIMER1_DEVICE_USE == y suppress + cont0_device_timer1 + cont1_device_timer1 + cont2_device_timer1 + +when CONT0_CAP_TIMER2_DEVICE_USE == y suppress + cont1_device_timer2 + cont2_device_timer2 + cont3_device_timer2 + +when CONT1_CAP_TIMER2_DEVICE_USE == y suppress + cont0_device_timer2 + cont2_device_timer2 + cont3_device_timer2 + +when CONT2_CAP_TIMER2_DEVICE_USE == y suppress + cont0_device_timer2 + cont1_device_timer2 + cont3_device_timer2 + +when CONT3_CAP_TIMER2_DEVICE_USE == y suppress + cont0_device_timer2 + cont1_device_timer2 + cont2_device_timer2 + +when CONT0_CAP_TIMER3_DEVICE_USE == y suppress + cont1_device_timer3 + cont2_device_timer3 + cont3_device_timer3 + +when CONT1_CAP_TIMER3_DEVICE_USE == y suppress + cont0_device_timer3 + cont2_device_timer3 + cont3_device_timer3 + +when CONT2_CAP_TIMER3_DEVICE_USE == y suppress + cont0_device_timer3 + cont1_device_timer3 + cont3_device_timer3 + +when CONT3_CAP_TIMER3_DEVICE_USE == y suppress + cont0_device_timer3 + cont1_device_timer3 + cont2_device_timer3 + menu cont%(cn)d_device_uart1 CONT%(cn)d_CAP_UART1_DEVICE_USE @@ -299,11 +370,22 @@ menu cont%(cn)d_device_uart2 menu cont%(cn)d_device_uart3 CONT%(cn)d_CAP_UART3_DEVICE_USE +menu cont%(cn)d_device_timer1 + CONT%(cn)d_CAP_TIMER1_DEVICE_USE + +menu cont%(cn)d_device_timer2 + CONT%(cn)d_CAP_TIMER2_DEVICE_USE + +menu cont%(cn)d_device_timer3 + CONT%(cn)d_CAP_TIMER3_DEVICE_USE + menu cont%(cn)d_device_list cont%(cn)d_device_uart1 cont%(cn)d_device_uart2 cont%(cn)d_device_uart3 - + cont%(cn)d_device_timer1 + cont%(cn)d_device_timer2 + cont%(cn)d_device_timer3 # # Settings for Custom Capabilities # diff --git a/conts/baremetal/baremetal5/SConstruct b/conts/baremetal/baremetal5/SConstruct new file mode 100644 index 0000000..cc082da --- /dev/null +++ b/conts/baremetal/baremetal5/SConstruct @@ -0,0 +1,71 @@ +# -*- mode: python; coding: utf-8; -*- +# +# Codezero -- Virtualization microkernel for embedded systems. +# +# Copyright © 2009 B Labs Ltd +# +import os, shelve, sys +from os.path import * + +PROJRELROOT = '../..' + +sys.path.append(PROJRELROOT) + +from config.projpaths import * +from config.configuration import * +from configure import * + +config = configuration_retrieve() +arch = config.arch +platform = config.platform +gcc_cpu_flag = config.gcc_cpu_flag + +# Wrapper library for system calls +LIBL4_RELDIR = 'conts/libl4' +KERNEL_INCLUDE = join(PROJROOT, 'include') +LIBL4_DIR = join(PROJROOT, LIBL4_RELDIR) +LIBL4_INCLUDE = join(LIBL4_DIR, 'include') +LIBL4_LIBPATH = join(BUILDDIR, LIBL4_RELDIR) + +# Some user-space libraries +LIBC_RELDIR = 'conts/libc' +LIBC_DIR = join(PROJROOT, LIBC_RELDIR) +LIBC_LIBPATH = join(BUILDDIR, LIBC_RELDIR) +LIBC_INCLUDE = [join(LIBC_DIR, 'include'), \ + join(LIBC_DIR, 'include/arch' + '/' + arch)] + +LIBDEV_RELDIR = 'conts/libdev' +LIBDEV_DIR = join(PROJROOT, LIBDEV_RELDIR) +LIBDEV_LIBPATH = join(join(BUILDDIR, LIBDEV_RELDIR), 'sys-userspace') +LIBDEV_INCLUDE = [join(LIBDEV_DIR, 'uart/include'), + join(LIBDEV_DIR, 'timer/sp804/include')] +LIBDEV_CCFLAGS = '-DPLATFORM_' + platform.upper() + +LIBMEM_RELDIR = 'conts/libmem' +LIBMEM_DIR = join(PROJROOT, LIBMEM_RELDIR) +LIBMEM_LIBPATH = join(BUILDDIR, LIBMEM_RELDIR) +LIBMEM_INCLUDE = LIBMEM_DIR + +env = Environment(CC = config.user_toolchain + 'gcc', + # We don't use -nostdinc because sometimes we need standard headers, + # such as stdarg.h e.g. for variable args, as in printk(). + CCFLAGS = ['-g', '-nostdlib', '-ffreestanding', '-std=gnu99', '-Wall', \ + '-Werror', ('-mcpu=' + gcc_cpu_flag), LIBDEV_CCFLAGS], \ + LINKFLAGS = ['-nostdlib', '-T' + "include/linker.lds", "-u_start"],\ + ASFLAGS = ['-D__ASSEMBLY__'], \ + PROGSUFFIX = '.elf', # The suffix to use for final executable + ENV = {'PATH' : os.environ['PATH']}, # Inherit shell path + LIBS = ['gcc', 'libl4', 'c-userspace', 'libdev-userspace', \ + 'libmm', 'libmc', 'libmalloc', 'gcc', 'c-userspace'], + # libgcc.a - This is required for division routines. + CPPPATH = ["#include", KERNEL_INCLUDE, LIBL4_INCLUDE, LIBDEV_INCLUDE, \ + LIBC_INCLUDE, LIBMEM_INCLUDE], + LIBPATH = [LIBL4_LIBPATH, LIBDEV_LIBPATH, LIBC_LIBPATH, LIBMEM_LIBPATH], + CPPFLAGS = '-include l4/config.h -include l4/macros.h -include l4/types.h') + +src = Glob('*.[cS]') +src += Glob('src/*.[cS]') + +objs = env.Object(src) +prog = env.Program('main.elf', objs) +Depends(prog, 'include/linker.lds') diff --git a/conts/baremetal/baremetal5/container.c b/conts/baremetal/baremetal5/container.c new file mode 100644 index 0000000..7bcbf9e --- /dev/null +++ b/conts/baremetal/baremetal5/container.c @@ -0,0 +1,21 @@ +/* + * Container entry point for pager + * + * Copyright (C) 2007-2009 B Labs Ltd. + */ + +#include +#include + + +void main(void); + +void __container_init(void) +{ + /* Generic L4 initialisation */ + __l4_init(); + + /* Entry to main */ + main(); +} + diff --git a/conts/baremetal/baremetal5/include/capability.h b/conts/baremetal/baremetal5/include/capability.h new file mode 100644 index 0000000..5cfce89 --- /dev/null +++ b/conts/baremetal/baremetal5/include/capability.h @@ -0,0 +1,12 @@ +#ifndef __UART_SERVICE_CAPABILITY_H__ +#define __UART_SERVICE_CAPABILITY_H__ + +#include +#include +#include + +void cap_print(struct capability *cap); +void cap_list_print(struct cap_list *cap_list); +int cap_read_all(); + +#endif /* header */ diff --git a/conts/baremetal/baremetal5/include/container.h b/conts/baremetal/baremetal5/include/container.h new file mode 100644 index 0000000..8241815 --- /dev/null +++ b/conts/baremetal/baremetal5/include/container.h @@ -0,0 +1,13 @@ +/* + * Autogenerated definitions for this container. + */ +#ifndef __CONTAINER_H__ +#define __CONTAINER_H__ + + +#define __CONTAINER_NAME__ "timer_service" +#define __CONTAINER_ID__ 0 +#define __CONTAINER__ "cont0" + + +#endif /* __CONTAINER_H__ */ diff --git a/conts/baremetal/baremetal5/include/linker.h b/conts/baremetal/baremetal5/include/linker.h new file mode 100644 index 0000000..e39da2f --- /dev/null +++ b/conts/baremetal/baremetal5/include/linker.h @@ -0,0 +1,7 @@ +#ifndef __LINKER_H__ +#define __LINKER_H__ + +extern char vma_start[]; +extern char __end[]; + +#endif /* __LINKER_H__ */ diff --git a/conts/baremetal/baremetal5/include/test.h b/conts/baremetal/baremetal5/include/test.h new file mode 100644 index 0000000..e69de29 diff --git a/conts/baremetal/baremetal5/main.c b/conts/baremetal/baremetal5/main.c new file mode 100644 index 0000000..e4ebacf --- /dev/null +++ b/conts/baremetal/baremetal5/main.c @@ -0,0 +1,105 @@ +/* + * Main function for this container + */ +#include +#include +#include +#include +#include +#include "sp804_timer.h" + +/* + * Address where we want to map timer + * Be sure that we using a valid address, depending upon + * how we make use of this driver. + */ +#define TIMER_VIRT_BASE 0x91000000 + +/* Frequency of timer in MHz */ +#define TIMER_FREQUENCY 1 + +#define __TASKNAME__ "Driver Mapper" + +void handle_request(void) +{ +# if 0 + /* Generic ipc data */ + u32 mr[MR_UNUSED_TOTAL]; + l4id_t senderid; + u32 tag; + int ret; + + if ((ret = l4_receive(L4_ANYTHREAD)) < 0) { + printf("%s: %s: IPC Error: %d. Quitting...\n", __TASKNAME__, + __FUNCTION__, ret); + BUG(); + } + + /* Syslib conventional ipc data which uses first few mrs. */ + tag = l4_get_tag(); + senderid = l4_get_sender(); + + + if (!(sender = find_task(senderid))) { + l4_ipc_return(-ESRCH); + return; + } + + + /* Read mrs not used by syslib */ + for (int i = 0; i < MR_UNUSED_TOTAL; i++) + mr[i] = read_mr(MR_UNUSED_START + i); + + switch(tag) { + case L4_IPC_TAG_GET_TIME: + ret = sp804_read_value(TIMER_VIRT_BASE); + break; + } + + /* Reply */ + if ((ret = l4_ipc_return(ret)) < 0) { + printf("%s: L4 IPC Error: %d.\n", __FUNCTION__, ret); + BUG(); + } +#endif +} + +int main(void) +{ + int ret = 0; + unsigned value = 0; + + /* + * Map Timer 2 to Ram allocated to us + * FIXME: do we need to set the frequency for sp810? + */ + ret = l4_map((void *)TIMER2_PHYS_BASE, (void *)TIMER_VIRT_BASE, 1, \ + MAP_USR_IO_FLAGS, self_tid()); + if (ret) { + printf("Failed to map the requested device\n"); + return ret; + } + + /* Initialise timer */ + sp804_init(TIMER_VIRT_BASE, SP804_TIMER_RUNMODE_FREERUN, \ + SP804_TIMER_WRAPMODE_WRAPPING, SP804_TIMER_WIDTH32BIT, \ + SP804_TIMER_IRQDISABLE); + + sp804_enable(TIMER_VIRT_BASE, 1); + +#if 1 + /* Read Timer value */ + while(1) { + value = sp804_read_value(TIMER_VIRT_BASE); + printf("Read timer with value = %x\n", value); + } +#else + printf("Driver Mapper: Waiting for ipc\n"); + while (1) { + handle_request(); + } +#endif + + return ret; +} + diff --git a/conts/baremetal/baremetal5/src/test.c b/conts/baremetal/baremetal5/src/test.c new file mode 100644 index 0000000..e69de29 diff --git a/conts/libdev/timer/sp804/include/sp804_timer.h b/conts/libdev/timer/sp804/include/sp804_timer.h new file mode 100644 index 0000000..70a5b1a --- /dev/null +++ b/conts/libdev/timer/sp804/include/sp804_timer.h @@ -0,0 +1,67 @@ +/* + * SP804 Primecell Timer offsets + * + * Copyright (C) 2007 Bahadir Balban + * + */ +#ifndef __SP804_TIMER_H__ +#define __SP804_TIMER_H__ + +#define SP804_TIMER2_OFFSET 0x20 + +/* Base address of Timers for differen platforms */ +#if defined(PLATFORM_PB926) +#define TIMER0_PHYS_BASE 0x101E2000 +#define TIMER1_PHYS_BASE (TIMER0_PHYS_BASE + SP804_TIMER2_OFFSET) +#define TIMER2_PHYS_BASE 0x101E3000 +#define TIMER3_PHYS_BASE (TIMER2_PHYS_BASE + SP804_TIMER2_OFFSET) +#elif defined(PLATFORM_EB) +#define TIMER0_PHYS_BASE 0x10011000 +#define TIMER1_PHYS_BASE (TIMER0_PHYS_BASE + SP804_TIMER2_OFFSET) +#define TIMER2_PHYS_BASE 0x10012000 +#define TIMER3_PHYS_BASE (TIMER2_PHYS_BASE + SP804_TIMER2_OFFSET) +#elif defined(PLATFORM_PB11MPCORE) || defined(PLATFORM_PBA8) +#define TIMER0_PHYS_BASE 0x10011000 +#define TIMER1_PHYS_BASE (TIMER0_PHYS_BASE + SP804_TIMER2_OFFSET) +#define TIMER2_PHYS_BASE 0x10012000 +#define TIMER3_PHYS_BASE (TIMER2_PHYS_BASE + SP804_TIMER2_OFFSET) +#define TIMER4_PHYS_BASE 0x10018000 +#define TIMER5_PHYS_BASE (TIMER4_PHYS_BASE + SP804_TIMER2_OFFSET) +#define TIMER6_PHYS_BASE 0x10019000 +#define TIMER7_PHYS_BASE (TIMER6_PHYS_BASE + SP804_TIMER2_OFFSET) +#endif + +/* Run mode of timers */ +#define SP804_TIMER_RUNMODE_FREERUN 0 +#define SP804_TIMER_RUNMODE_PERIODIC 1 + +/* Wrap mode of timers */ +#define SP804_TIMER_WRAPMODE_WRAPPING 0 +#define SP804_TIMER_WRAPMODE_ONESHOT 1 + +/* Operational width of timer */ +#define SP804_TIMER_WIDTH16BIT 0 +#define SP804_TIMER_WIDTH32BIT 1 + +/* Enable/disable irq on timer */ +#define SP804_TIMER_IRQDISABLE 0 +#define SP804_TIMER_IRQENABLE 1 + +/* Register offsets */ +#define SP804_TIMERLOAD 0x0 +#define SP804_TIMERVALUE 0x4 +#define SP804_TIMERCONTROL 0x8 +#define SP804_TIMERINTCLR 0xC +#define SP804_TIMERRIS 0x10 +#define SP804_TIMERMIS 0x14 +#define SP804_TIMERBGLOAD 0x18 + +void sp804_init(unsigned int timer_base, int runmode, int wrapmode, \ + int width, int irq_enable); +void sp804_irq_handler(unsigned int timer_base); +void sp804_enable(unsigned int timer_base, int enable); +void sp804_set_irq(unsigned int timer_base, int enable); + +unsigned int sp804_read_value(unsigned int timer_base); + +#endif /* __SP804_TIMER_H__ */ diff --git a/conts/libdev/timer/sp804/src/sp804_timer.c b/conts/libdev/timer/sp804/src/sp804_timer.c new file mode 100644 index 0000000..cbb8c11 --- /dev/null +++ b/conts/libdev/timer/sp804/src/sp804_timer.c @@ -0,0 +1,104 @@ +/* + * SP804 Primecell Timer driver + * + * Copyright (C) 2007 Bahadir Balban + */ +#include + +#define read(a) *((volatile unsigned int *)(a)) +#define write(v, a) (*((volatile unsigned int *)(a)) = v) +#define setbit(bit, a) write(read(a) | bit, a) +#define clrbit(bit, a) write(read(a) & ~bit, a) + +void sp804_irq_handler(unsigned int timer_base) +{ + /* + * Timer enabled as Periodic/Wrapper only needs irq clearing + * as it automatically reloads and wraps + */ + write(1, (timer_base + SP804_TIMERINTCLR)); +} + +static inline void sp804_control(unsigned int timer_base, int bit, int setclr) +{ + unsigned long addr = (timer_base + SP804_TIMERCONTROL); + setclr ? setbit(bit, addr) : clrbit(bit, addr); +} + +/* + * Sets timer's run mode: + * @periodic: periodic mode = 1, free-running = 0. + */ +#define SP804_PEREN (1 << 6) +static inline void sp804_set_runmode(unsigned int timer_base, int periodic) +{ + sp804_control(timer_base, SP804_PEREN, periodic); +} + +/* + * Sets timer's wrapping mode: + * @oneshot: oneshot = 1, wrapping = 0. + */ +#define SP804_ONESHOT (1 << 0) +static inline void sp804_set_wrapmode(unsigned int timer_base, int oneshot) +{ + sp804_control(timer_base, SP804_ONESHOT, oneshot); +} + +/* + * Sets the operational width of timers. + * In 16bit mode, top halfword is ignored. + * @width: 32bit mode = 1; 16bit mode = 0 + */ +#define SP804_32BIT (1 << 1) +static inline void sp804_set_widthmode(unsigned int timer_base, int width) +{ + sp804_control(timer_base, SP804_32BIT, width); +} + +/* + * Enable/disable timer: + * @enable: enable = 1, disable = 0; + */ +#define SP804_ENABLE (1 << 7) +void sp804_enable(unsigned int timer_base, int enable) +{ + sp804_control(timer_base, SP804_ENABLE, enable); +} + +/* + * Enable/disable local irq register: + * @enable: enable = 1, disable = 0 + */ +#define SP804_IRQEN (1 << 5) +void sp804_set_irq(unsigned int timer_base, int enable) +{ + sp804_control(timer_base, SP804_IRQEN, enable); +} + +/* Loads timer with value in val */ +static inline void sp804_load_value(unsigned int timer_base, unsigned int val) +{ + write(val, (timer_base + SP804_TIMERLOAD)); +} + +/* Returns current timer value */ +unsigned int sp804_read_value(unsigned int timer_base) +{ + return read(timer_base + SP804_TIMERVALUE); +} + +/* TODO: Define macro values for duration */ +void sp804_init(unsigned int timer_base, int run_mode, int wrap_mode, \ + int width, int irq_enable) +{ + /* 1 tick per usec */ + const int duration = 250; + + sp804_set_runmode(timer_base, run_mode); /* Periodic */ + sp804_set_wrapmode(timer_base, wrap_mode); /* Wrapping */ + sp804_set_widthmode(timer_base, width); /* 32 bit */ + sp804_set_irq(timer_base, irq_enable); /* Enable */ + sp804_load_value(timer_base, duration); +} +