OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [devs/] [wallclock/] [dallas/] [ds12887/] [current/] [src/] [ds12887.cxx] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      devs/wallclock/ds12887.inl
4
//
5
//      Wallclock implementation for Dallas 12887
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):     jskov
43
// Contributors:  jskov
44
// Date:          2001-07-06
45
// Purpose:       Wallclock driver for Dallas 12887
46
//
47
//####DESCRIPTIONEND####
48
//
49
//==========================================================================
50
 
51
#include <pkgconf/wallclock.h>          // Wallclock device config
52
 
53
#include <cyg/hal/hal_io.h>             // IO macros
54
#include <cyg/hal/hal_intr.h>           // interrupt enable/disable
55
#include <cyg/infra/cyg_type.h>         // Common type definitions and support
56
 
57
#include <cyg/io/wallclock.hxx>         // The WallClock API
58
#include <cyg/io/wallclock/wallclock.inl> // Helpers
59
 
60
#include <cyg/infra/diag.h>
61
 
62
#define nDEBUG
63
 
64
// Platform details
65
#include CYGDAT_DEVS_WALLCLOCK_DALLAS_12887_INL
66
 
67
#ifndef DS_READ_UINT8
68
# define DS_READ_UINT8(x,y) HAL_READ_UINT8(x,y)
69
# define DS_WRITE_UINT8(x,y) HAL_WRITE_UINT8(x,y)
70
#endif
71
 
72
#if !defined(DS_READ) && !defined(DS_WRITE) //  Allow for INL to define this
73
#ifdef DS_LINEAR
74
# ifndef DS_STEP
75
#  define DS_STEP 0
76
# endif
77
# ifndef DS_BASE
78
#  error "Need to know base of DS12887 part"
79
# endif
80
#define DS_READ( offset, data)  \
81
    DS_READ_UINT8( DS_BASE + ((offset) << DS_STEP), (data))
82
#define DS_WRITE(offset, data)  \
83
    DS_WRITE_UINT8(DS_BASE + ((offset) << DS_STEP), (data))
84
#else   //  !DS_LINEAR
85
# if !defined(DS_ADDR) || !defined(DS_DATA)
86
#  error "Need to know addr/data locations of DS12887 part"
87
# endif
88
# define DS_READ(offset, data)                 \
89
  CYG_MACRO_START                              \
90
  DS_WRITE_UINT8(DS_ADDR, (offset));           \
91
  DS_READ_UINT8(DS_DATA, (data));              \
92
  CYG_MACRO_END
93
# define DS_WRITE(offset, data)                \
94
  CYG_MACRO_START                              \
95
  DS_WRITE_UINT8(DS_ADDR, (offset));           \
96
  DS_WRITE_UINT8(DS_DATA, (data));             \
97
  CYG_MACRO_END
98
#endif
99
#endif  //  ! DS_READ && ! DS_WRITE
100
 
101
// Registers
102
#define DS_SECONDS         0x00
103
#define DS_SECONDS_ALARM   0x01
104
#define DS_MINUTES         0x02
105
#define DS_MINUTES_ALARM   0x03
106
#define DS_HOURS           0x04
107
#define DS_HOURS_ALARM     0x05
108
#define DS_DOW             0x06
109
#define DS_DOM             0x07
110
#define DS_MONTH           0x08
111
#define DS_YEAR            0x09
112
#define DS_CENTURY         0x32
113
 
114
#define DS_REG_A           0x0a
115
#define DS_REG_B           0x0b
116
#define DS_REG_C           0x0c
117
#define DS_REG_D           0x0d
118
 
119
// Control bits
120
#define DS_REG_A_UIP       0x80
121
#define DS_REG_A_ENABLE    0x20
122
 
123
#define DS_REG_B_SET       0x80
124
#define DS_REG_B_DM        0x04
125
#define DS_REG_B_24H       0x02
126
 
127
 
128
//----------------------------------------------------------------------------
129
// Accessor functions
130
static inline void
131
init_ds_hwclock(void)
132
{
133
    cyg_uint8 _regb, _tmp;
134
 
135
    // Set 24H mode
136
    DS_WRITE(DS_REG_B, DS_REG_B_24H);
137
    // Enable clock
138
    DS_WRITE(DS_REG_A, DS_REG_A_ENABLE);
139
 
140
    // Verify that there are reasonable default settings - otherwise
141
    // set them.
142
 
143
    // Stop counting
144
    DS_READ(DS_REG_B, _regb);
145
    _regb |= DS_REG_B_SET;
146
    DS_WRITE(DS_REG_B, _regb);
147
 
148
    DS_READ(DS_CENTURY, _tmp);
149
    if (0xff == _tmp)
150
        DS_WRITE(DS_CENTURY, TO_BCD(20));
151
 
152
    DS_READ(DS_MONTH, _tmp);
153
    if (0x00 == _tmp)
154
        DS_WRITE(DS_MONTH, TO_BCD(1));
155
 
156
    DS_READ(DS_DOM, _tmp);
157
    if (0x00 == _tmp)
158
        DS_WRITE(DS_DOM, TO_BCD(1));
159
 
160
    DS_READ(DS_DOM, _tmp);
161
    if (0x00 == _tmp)
162
        DS_WRITE(DS_DOM, TO_BCD(1));
163
 
164
    // Restart counting
165
    _regb &= ~DS_REG_B_SET;
166
    DS_WRITE(DS_REG_B, _regb);
167
}
168
 
169
 
170
static inline void
171
set_ds_hwclock(cyg_uint32 year, cyg_uint32 month, cyg_uint32 mday,
172
               cyg_uint32 hour, cyg_uint32 minute, cyg_uint32 second)
173
{
174
    cyg_uint8 _regb;
175
    // Stop counting
176
    DS_READ(DS_REG_B, _regb);
177
    _regb |= DS_REG_B_SET;
178
    DS_WRITE(DS_REG_B, _regb);
179
 
180
    DS_WRITE(DS_CENTURY, TO_BCD((cyg_uint8)(year / 100)));
181
    DS_WRITE(DS_YEAR, TO_BCD((cyg_uint8)(year % 100)));
182
    DS_WRITE(DS_MONTH, TO_BCD((cyg_uint8)month));
183
    DS_WRITE(DS_DOM, TO_BCD((cyg_uint8)mday));
184
    DS_WRITE(DS_HOURS, TO_BCD((cyg_uint8)hour));
185
    DS_WRITE(DS_MINUTES, TO_BCD((cyg_uint8)minute));
186
    DS_WRITE(DS_SECONDS, TO_BCD((cyg_uint8)second));
187
 
188
    // Restart counting
189
    _regb &= ~DS_REG_B_SET;
190
    DS_WRITE(DS_REG_B, _regb);
191
 
192
#ifdef DEBUG
193
    // This will cause the test to eventually fail due to these printouts
194
    // causing timer interrupts to be lost...
195
    diag_printf("Set -------------\n");
196
    diag_printf("year %02d\n", year);
197
    diag_printf("month %02d\n", month);
198
    diag_printf("mday %02d\n", mday);
199
    diag_printf("hour %02d\n", hour);
200
    diag_printf("minute %02d\n", minute);
201
    diag_printf("second %02d\n", second);
202
#endif
203
}
204
 
205
static inline void
206
get_ds_hwclock(cyg_uint32* year, cyg_uint32* month, cyg_uint32* mday,
207
               cyg_uint32* hour, cyg_uint32* minute, cyg_uint32* second)
208
{
209
    cyg_uint8 _reg, _t1, _t2;
210
    cyg_uint32 _old;
211
 
212
    // Wait for update flag clears
213
    do {
214
        DS_READ(DS_REG_A, _reg);
215
    } while (_reg & DS_REG_A_UIP);
216
 
217
    // Disable interrupts while reading to ensure it doesn't take more
218
    // than 244us.
219
    HAL_DISABLE_INTERRUPTS(_old);
220
 
221
    DS_READ(DS_CENTURY, _t1);
222
    DS_READ(DS_YEAR, _t2);
223
    *year = (cyg_uint32)TO_DEC(_t1)*100 + (cyg_uint32)TO_DEC(_t2);
224
 
225
    DS_READ(DS_MONTH, _t1);
226
    *month = (cyg_uint32)TO_DEC(_t1);
227
 
228
    DS_READ(DS_DOM, _t1);
229
    *mday = (cyg_uint32)TO_DEC(_t1);
230
 
231
    DS_READ(DS_HOURS, _t1);
232
    *hour = (cyg_uint32)TO_DEC(_t1);
233
 
234
    DS_READ(DS_MINUTES, _t1);
235
    *minute = (cyg_uint32)TO_DEC(_t1);
236
 
237
    DS_READ(DS_SECONDS, _t1);
238
    *second = (cyg_uint32)TO_DEC(_t1);
239
 
240
    // Reenable interrupts
241
    HAL_RESTORE_INTERRUPTS(_old);
242
 
243
#ifdef DEBUG
244
    // This will cause the test to eventually fail due to these printouts
245
    // causing timer interrupts to be lost...
246
    diag_printf("year %02d\n", *year);
247
    diag_printf("month %02d\n", *month);
248
    diag_printf("mday %02d\n", *mday);
249
    diag_printf("hour %02d\n", *hour);
250
    diag_printf("minute %02d\n", *minute);
251
    diag_printf("second %02d\n", *second);
252
#endif
253
}
254
 
255
//-----------------------------------------------------------------------------
256
// Functions required for the hardware-driver API.
257
 
258
// Returns the number of seconds elapsed since 1970-01-01 00:00:00.
259
cyg_uint32
260
Cyg_WallClock::get_hw_seconds(void)
261
{
262
    cyg_uint32 year, month, mday, hour, minute, second;
263
 
264
    get_ds_hwclock(&year, &month, &mday, &hour, &minute, &second);
265
 
266
    cyg_uint32 now = _simple_mktime(year, month, mday, hour, minute, second);
267
    return now;
268
}
269
 
270
#ifdef CYGSEM_WALLCLOCK_SET_GET_MODE
271
 
272
// Sets the clock. Argument is seconds elapsed since 1970-01-01 00:00:00.
273
void
274
Cyg_WallClock::set_hw_seconds( cyg_uint32 secs )
275
{
276
    cyg_uint32 year, month, mday, hour, minute, second;
277
 
278
    _simple_mkdate(secs, &year, &month, &mday, &hour, &minute, &second);
279
 
280
    set_ds_hwclock(year, month, mday, hour, minute, second);
281
}
282
 
283
#endif
284
 
285
void
286
Cyg_WallClock::init_hw_seconds(void)
287
{
288
#ifdef CYGSEM_WALLCLOCK_SET_GET_MODE
289
    init_ds_hwclock();
290
#else
291
    // This is our base: 1970-01-01 00:00:00
292
    // Set the HW clock - if for nothing else, just to be sure it's in a
293
    // legal range. Any arbitrary base could be used.
294
    // After this the hardware clock is only read.
295
    set_ds_hwclock(1970,1,1,0,0,0);
296
#endif
297
}
298
 
299
//-----------------------------------------------------------------------------
300
// End of devs/wallclock/ds12887.inl

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.