summaryrefslogtreecommitdiff
path: root/firmware/target/arm
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2007-07-06 21:36:32 +0000
committerMichael Sevakis <jethead71@rockbox.org>2007-07-06 21:36:32 +0000
commit4ae87c8b8ab7ddbd286f5288adaddcaf0a187e31 (patch)
treed3880b9f53a5c38d2211a1b8812724bf96913c4c /firmware/target/arm
parentcbed7a2cd21bb2715b39ebcd3015147a9d7ff3c2 (diff)
downloadrockbox-4ae87c8b8ab7ddbd286f5288adaddcaf0a187e31.tar.gz
rockbox-4ae87c8b8ab7ddbd286f5288adaddcaf0a187e31.zip
Gigabeat: Add timer functionality. Rework tick timer setup to be exactly 100Hz. Metronome should work now but some pcm changes are needed to have faster tocks work correctly (in the works).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13806 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm')
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c51
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/timer-meg-fx.c127
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/timer-target.h39
-rw-r--r--firmware/target/arm/system-arm.h44
4 files changed, 229 insertions, 32 deletions
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c
index 9df90a2344..39e4efab49 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c
@@ -1,13 +1,49 @@
1#include "config.h"
2#include "system.h"
1#include "kernel.h" 3#include "kernel.h"
4#include "timer.h"
2#include "thread.h" 5#include "thread.h"
3 6
4#include <stdio.h>
5#include "lcd.h"
6
7extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void); 7extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
8 8
9void timer4(void) { 9void tick_start(unsigned int interval_in_ms)
10 int i; 10{
11 /*
12 * Based on default PCLK of 49.1568MHz - scaling chosen to give
13 * remainder-free result for tick interval of 10ms (100Hz)
14 * Timer input clock frequency =
15 * fPCLK / {prescaler value+1} / {divider value}
16 * TIMER_FREQ = 49156800 / 2
17 * 13300 = TIMER_FREQ / 231 / 8
18 * 49156800 = 19*(11)*(7)*7*5*5*(3)*2*2*2*2*2*2
19 * 231 = 11*7*3
20 */
21
22 /* stop timer 4 */
23 TCON &= ~(1 << 20);
24 /* Set the count for timer 4 */
25 TCNTB4 = (TIMER_FREQ / 231 / 8) * interval_in_ms / 1000;
26 /* Set the the prescaler value for timers 2,3, and 4 */
27 TCFG0 = (TCFG0 & ~0xff00) | ((231-1) << 8);
28 /* MUX4 = 1/16 */
29 TCFG1 = (TCFG1 & ~0xff0000) | 0x030000;
30 /* set manual bit */
31 TCON |= 1 << 21;
32 /* reset manual bit */
33 TCON &= ~(1 << 21);
34 /* interval mode */
35 TCON |= 1 << 22;
36 /* start timer 4 */
37 TCON |= (1 << 20);
38
39 /* timer 4 unmask interrupts */
40 INTMSK &= ~TIMER4_MASK;
41}
42
43void TIMER4(void)
44{
45 int i;
46
11 /* Run through the list of tick tasks */ 47 /* Run through the list of tick tasks */
12 for(i = 0; i < MAX_NUM_TICK_TASKS; i++) 48 for(i = 0; i < MAX_NUM_TICK_TASKS; i++)
13 { 49 {
@@ -19,7 +55,6 @@ void timer4(void) {
19 55
20 current_tick++; 56 current_tick++;
21 57
22 /* following needs to be fixed. */ 58 SRCPND = TIMER4_MASK;
23 /*wake_up_thread();*/ 59 INTPND = TIMER4_MASK;
24} 60}
25
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/timer-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/timer-meg-fx.c
new file mode 100644
index 0000000000..4654c7c845
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/timer-meg-fx.c
@@ -0,0 +1,127 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* Copyright (C) 2007 by Michael Sevakis
11*
12* All files in this archive are subject to the GNU General Public License.
13* See the file COPYING in the source tree root for full license agreement.
14*
15* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16* KIND, either express or implied.
17*
18****************************************************************************/
19#include "config.h"
20#include "cpu.h"
21#include "system.h"
22#include "timer.h"
23#include "logf.h"
24
25/* GPB0/TOUT0 should already have been configured as output so that pin
26 should not be a functional pin and TIMER0 output unseen there */
27void TIMER0(void)
28{
29 if (pfn_timer != NULL)
30 pfn_timer();
31
32 SRCPND = TIMER0_MASK;
33 INTPND = TIMER0_MASK;
34}
35
36static void stop_timer(void)
37{
38 /* mask interrupt */
39 INTMSK |= TIMER0_MASK;
40
41 /* stop any running TIMER0 */
42 TCON &= ~(1 << 0);
43
44 /* clear pending */
45 SRCPND = TIMER0_MASK;
46 INTPND = TIMER0_MASK;
47}
48
49bool __timer_set(long cycles, bool start)
50{
51 bool retval = false;
52
53 /* Find the minimum factor that puts the counter in range 1-65535 */
54 unsigned int prescaler = (cycles + 65534) / 65535;
55
56 /* Maximum divider setting is x / 256 / 16 = x / 4096 */
57 if (prescaler <= 4096)
58 {
59 int oldlevel;
60 unsigned int divider;
61
62 if (start && pfn_unregister != NULL)
63 {
64 pfn_unregister();
65 pfn_unregister = NULL;
66 }
67
68 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
69
70 TCMPB0 = 0;
71 TCNTB0 = (unsigned int)cycles / prescaler;
72
73 /* Max prescale is 255+1 */
74 for (divider = 0; prescaler > 256; prescaler >>= 1, divider++);
75
76 TCFG0 = (TCFG0 & ~0xff) | (prescaler - 1);
77 TCFG1 = (TCFG1 & ~0xf) | divider;
78
79 set_irq_level(oldlevel);
80
81 retval = true;
82 }
83
84 return retval;
85}
86
87bool __timer_register(void)
88{
89 bool retval = true;
90
91 int oldstatus = set_interrupt_status(IRQ_FIQ_DISABLED, IRQ_FIQ_STATUS);
92
93 stop_timer();
94
95 /* neurosis - make sure something didn't set GPB0 to TOUT0 */
96 if ((GPBCON & 0x3) != 0x2)
97 {
98 /* manual update: on (to reset count) */
99 TCON |= (1 << 1);
100 /* dead zone: off, inverter: off, manual off */
101 TCON &= ~((1 << 4) | (1 << 2) | (1 << 1));
102 /* interval mode (auto reload): on */
103 TCON |= (1 << 3);
104 /* start timer */
105 TCON |= (1 << 0);
106 /* unmask interrupt */
107 INTMSK &= ~TIMER0_MASK;
108 }
109
110 if (!(TCON & (1 << 0)))
111 {
112 /* timer could not be started due to config error */
113 logf("Timer error: GPB0 set to TOUT0");
114 retval = false;
115 }
116
117 set_interrupt_status(oldstatus, IRQ_FIQ_STATUS);
118
119 return retval;
120}
121
122void __timer_unregister(void)
123{
124 int oldstatus = set_interrupt_status(IRQ_FIQ_DISABLED, IRQ_FIQ_STATUS);
125 stop_timer();
126 set_interrupt_status(oldstatus, IRQ_FIQ_STATUS);
127}
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/timer-target.h b/firmware/target/arm/s3c2440/gigabeat-fx/timer-target.h
new file mode 100644
index 0000000000..e9f330cf8e
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/timer-target.h
@@ -0,0 +1,39 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* Copyright (C) 2007 by Michael Sevakis
11*
12* All files in this archive are subject to the GNU General Public License.
13* See the file COPYING in the source tree root for full license agreement.
14*
15* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16* KIND, either express or implied.
17*
18****************************************************************************/
19#ifndef TIMER_TARGET_H
20#define TIMER_TARGET_H
21
22/* timer is based on PCLK and minimum division is 2 */
23#define TIMER_FREQ (49156800/2)
24
25bool __timer_set(long cycles, bool set);
26bool __timer_register(void);
27void __timer_unregister(void);
28
29#define __TIMER_SET(cycles, set) \
30 __timer_set(cycles, set)
31
32#define __TIMER_REGISTER(reg_prio, unregister_callback, cycles, \
33 int_prio, timer_callback) \
34 __timer_register()
35
36#define __TIMER_UNREGISTER(...) \
37 __timer_unregister()
38
39#endif /* TIMER_TARGET_H */
diff --git a/firmware/target/arm/system-arm.h b/firmware/target/arm/system-arm.h
index 99cab9e1a3..37c367fdc4 100644
--- a/firmware/target/arm/system-arm.h
+++ b/firmware/target/arm/system-arm.h
@@ -87,23 +87,6 @@ static inline uint32_t swap_odd_even32(uint32_t value)
87 return value; 87 return value;
88} 88}
89 89
90#define HIGHEST_IRQ_LEVEL (0x80)
91
92static inline int set_irq_level(int level)
93{
94 unsigned long cpsr;
95 int oldlevel;
96 /* Read the old level and set the new one */
97 asm volatile (
98 "mrs %1, cpsr \n"
99 "bic %0, %1, #0x80 \n"
100 "orr %0, %0, %2 \n"
101 "msr cpsr_c, %0 \n"
102 : "=&r,r"(cpsr), "=&r,r"(oldlevel) : "r,i"(level & 0x80)
103 );
104 return oldlevel;
105}
106
107static inline void set_fiq_handler(void(*fiq_handler)(void)) 90static inline void set_fiq_handler(void(*fiq_handler)(void))
108{ 91{
109 /* Install the FIQ handler */ 92 /* Install the FIQ handler */
@@ -133,22 +116,35 @@ static inline void disable_fiq(void)
133} 116}
134 117
135/* This one returns the old status */ 118/* This one returns the old status */
136#define FIQ_ENABLED 0x00 119#define IRQ_ENABLED 0x00
137#define FIQ_DISABLED 0x40 120#define IRQ_DISABLED 0x80
138static inline int set_fiq_status(int status) 121#define IRQ_STATUS 0x80
122#define FIQ_ENABLED 0x00
123#define FIQ_DISABLED 0x40
124#define FIQ_STATUS 0x40
125#define IRQ_FIQ_ENABLED 0x00
126#define IRQ_FIQ_DISABLED 0xc0
127#define IRQ_FIQ_STATUS 0xc0
128#define HIGHEST_IRQ_LEVEL IRQ_DISABLED
129
130#define set_irq_level(status) set_interrupt_status((status), IRQ_STATUS)
131#define set_fiq_status(status) set_interrupt_status((status), FIQ_STATUS)
132
133static inline int set_interrupt_status(int status, int mask)
139{ 134{
140 unsigned long cpsr; 135 unsigned long cpsr;
141 int oldstatus; 136 int oldstatus;
142 /* Read the old level and set the new one */ 137 /* Read the old levels and set the new ones */
143 asm volatile ( 138 asm volatile (
144 "mrs %1, cpsr \n" 139 "mrs %1, cpsr \n"
145 "bic %0, %1, #0x40 \n" 140 "bic %0, %1, %[mask] \n"
146 "orr %0, %0, %2 \n" 141 "orr %0, %0, %2 \n"
147 "msr cpsr_c, %0 \n" 142 "msr cpsr_c, %0 \n"
148 : "=&r,r"(cpsr), "=&r,r"(oldstatus) : "r,i"(status & 0x40) 143 : "=&r,r"(cpsr), "=&r,r"(oldstatus)
144 : "r,i"(status & mask), [mask]"i,i"(mask)
149 ); 145 );
146
150 return oldstatus; 147 return oldstatus;
151} 148}
152 149
153
154#endif /* SYSTEM_ARM_H */ 150#endif /* SYSTEM_ARM_H */