Timer capability added, Baremetal5 added as Timer Sevice, Code not

tested yet.
This commit is contained in:
Amit Mahajan
2009-11-25 13:50:24 +05:30
parent b53cc73747
commit 9f57cb7c67
12 changed files with 495 additions and 1 deletions

View File

@@ -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},
'''
}

View File

@@ -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
#

View File

@@ -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')

View File

@@ -0,0 +1,21 @@
/*
* Container entry point for pager
*
* Copyright (C) 2007-2009 B Labs Ltd.
*/
#include <l4lib/init.h>
#include <l4lib/utcb.h>
void main(void);
void __container_init(void)
{
/* Generic L4 initialisation */
__l4_init();
/* Entry to main */
main();
}

View File

@@ -0,0 +1,12 @@
#ifndef __UART_SERVICE_CAPABILITY_H__
#define __UART_SERVICE_CAPABILITY_H__
#include <l4lib/capability.h>
#include <l4/api/capability.h>
#include <l4/generic/cap-types.h>
void cap_print(struct capability *cap);
void cap_list_print(struct cap_list *cap_list);
int cap_read_all();
#endif /* header */

View File

@@ -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__ */

View File

@@ -0,0 +1,7 @@
#ifndef __LINKER_H__
#define __LINKER_H__
extern char vma_start[];
extern char __end[];
#endif /* __LINKER_H__ */

View File

@@ -0,0 +1,105 @@
/*
* Main function for this container
*/
#include <l4lib/arch/syslib.h>
#include <l4lib/arch/syscalls.h>
#include <l4/api/space.h>
#include <l4lib/ipcdefs.h>
#include <l4/api/errno.h>
#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;
}

View File

View File

@@ -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__ */

View File

@@ -0,0 +1,104 @@
/*
* SP804 Primecell Timer driver
*
* Copyright (C) 2007 Bahadir Balban
*/
#include <sp804_timer.h>
#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);
}