mirror of
https://github.com/drasko/codezero.git
synced 2026-01-11 18:33:16 +01:00
Timer capability added, Baremetal5 added as Timer Sevice, Code not
tested yet.
This commit is contained in:
@@ -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},
|
||||
'''
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
#
|
||||
|
||||
71
conts/baremetal/baremetal5/SConstruct
Normal file
71
conts/baremetal/baremetal5/SConstruct
Normal 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')
|
||||
21
conts/baremetal/baremetal5/container.c
Normal file
21
conts/baremetal/baremetal5/container.c
Normal 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();
|
||||
}
|
||||
|
||||
12
conts/baremetal/baremetal5/include/capability.h
Normal file
12
conts/baremetal/baremetal5/include/capability.h
Normal 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 */
|
||||
13
conts/baremetal/baremetal5/include/container.h
Normal file
13
conts/baremetal/baremetal5/include/container.h
Normal 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__ */
|
||||
7
conts/baremetal/baremetal5/include/linker.h
Normal file
7
conts/baremetal/baremetal5/include/linker.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef __LINKER_H__
|
||||
#define __LINKER_H__
|
||||
|
||||
extern char vma_start[];
|
||||
extern char __end[];
|
||||
|
||||
#endif /* __LINKER_H__ */
|
||||
0
conts/baremetal/baremetal5/include/test.h
Normal file
0
conts/baremetal/baremetal5/include/test.h
Normal file
105
conts/baremetal/baremetal5/main.c
Normal file
105
conts/baremetal/baremetal5/main.c
Normal 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;
|
||||
}
|
||||
|
||||
0
conts/baremetal/baremetal5/src/test.c
Normal file
0
conts/baremetal/baremetal5/src/test.c
Normal file
67
conts/libdev/timer/sp804/include/sp804_timer.h
Normal file
67
conts/libdev/timer/sp804/include/sp804_timer.h
Normal 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__ */
|
||||
104
conts/libdev/timer/sp804/src/sp804_timer.c
Normal file
104
conts/libdev/timer/sp804/src/sp804_timer.c
Normal 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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user