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

@@ -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);
}