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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [devs/] [adc/] [cortexm/] [lm3s/] [current/] [src/] [adc_lm3s.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      adc_lm3s.c
4
//
5
//      ADC driver for Stellaris Cortex M3 microcontroller
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 2011 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):   Uwe Kindler <uwe_kindler@web.de>
43
//              Updated for Stellaris device, ccoutand
44
// Contributors:
45
// Date:         2011-01-08
46
// Purpose:
47
// Description:
48
//
49
//
50
//####DESCRIPTIONEND####
51
//
52
//==========================================================================
53
 
54
 
55
//==========================================================================
56
//                                 INCLUDES
57
//==========================================================================
58
#include <pkgconf/system.h>
59
#include <pkgconf/devs_adc_cortexm_lm3s.h>
60
 
61
#include <cyg/infra/cyg_type.h>
62
#include <cyg/infra/cyg_ass.h>
63
#include <cyg/infra/diag.h>
64
#include <cyg/io/adc.h>
65
#include <cyg/hal/hal_arch.h>
66
#include <cyg/hal/hal_io.h>
67
#include <cyg/hal/hal_intr.h>
68
#include <cyg/hal/drv_api.h>
69
 
70
#if CYGPKG_DEVS_ADC_CORTEXM_LM3S_DEBUG_LEVEL > 0
71
# define lm3s_adc_diag(args...) diag_printf(args)
72
#else
73
# define lm3s_adc_diag(args...)
74
#endif
75
 
76
#define CYGHWR_HAL_LM3S_ADC_MAX_CHAN 8
77
 
78
//==========================================================================
79
//                                  DATA TYPES
80
//==========================================================================
81
typedef struct lm3s_adc_info {
82
    cyg_uint32      adc_base;          // ADC base address
83
    cyg_uint32      adc_periph;        // ADC peripheral mask
84
    cyg_vector_t    adc_vector;        // Interrupt vector number
85
    cyg_priority_t  adc_intprio;       // Interrupt priority of ADC interrupt
86
    cyg_uint32      timer_base;        // Base address of Timer peripheral
87
    cyg_uint32      timer_interval;    // Timer value
88
    cyg_uint32      timer_periph;      // Timer peripheral mask
89
    cyg_uint8       sensor_channel;    // Temperature sensor channel if any
90
    cyg_uint8       max_channel;       // Number of ADC channel
91
    cyg_handle_t    int_handle;        // For initializing the interrupt
92
    cyg_interrupt   int_data;
93
    cyg_uint8       adc_avg;           // Sample averaging
94
    // Stores references to channel objects
95
    struct cyg_adc_channel *channel[CYGHWR_HAL_LM3S_ADC_MAX_CHAN];
96
    cyg_uint8       chan_mask;         // Mask that indicates channels used
97
                                       // by ADC driver
98
} lm3s_adc_info;
99
 
100
 
101
//==========================================================================
102
//                               DECLARATIONS
103
//==========================================================================
104
static bool     lm3s_adc_init(struct cyg_devtab_entry *tab);
105
static Cyg_ErrNo lm3s_adc_lookup(struct cyg_devtab_entry **tab,
106
                                 struct cyg_devtab_entry *sub_tab,
107
                                 const char *name);
108
static void     lm3s_adc_enable(cyg_adc_channel * chan);
109
static void     lm3s_adc_disable(cyg_adc_channel * chan);
110
static void     lm3s_adc_set_rate(cyg_adc_channel * chan, cyg_uint32 rate);
111
static cyg_uint32 lm3s_adc_isr(cyg_vector_t vector, cyg_addrword_t data);
112
static void     lm3s_adc_dsr(cyg_vector_t vector,
113
                             cyg_ucount32 count, cyg_addrword_t data);
114
 
115
static void     lm3s_adc_disable_sequencer0(cyg_uint32);
116
static void     lm3s_adc_enable_sequencer0(cyg_uint32);
117
static void     lm3s_adc_flush(cyg_uint32);
118
static void     lm3s_adc_update_sequencer0(cyg_adc_channel *);
119
 
120
// -------------------------------------------------------------------------
121
// Driver functions:
122
CYG_ADC_FUNCTIONS( lm3s_adc_funs,
123
                   lm3s_adc_enable,
124
                   lm3s_adc_disable,
125
                   lm3s_adc_set_rate );
126
 
127
 
128
#include CYGDAT_DEVS_ADC_CORTEXM_LM3S_INL       // Instantiate ADCs
129
 
130
 
131
//==========================================================================
132
//
133
// The eCos Sellaris ADC drivers uses a single sequencer ( sequencer 0 ).
134
// The same sequencer is used to sample all channels.
135
// Sampling of the different channel is triggered from a timer interrupt.
136
// The ADC driver flexibility does not allow to trigger sampling from
137
// external GPIO or analog comparator event. It should be noted that enabling
138
// / disabling an ADC channel disturbs the sampling of other channels since it
139
// requires to stop sampling to re-organize the sequencer. Also the FIFO
140
// is flushed to ensure correct sample order out of the sequencer FIFO.
141
//
142
//==========================================================================
143
static bool
144
lm3s_adc_init(struct cyg_devtab_entry *tab)
145
{
146
    cyg_adc_channel *chan = (cyg_adc_channel *) tab->priv;
147
    cyg_adc_device *device = chan->device;
148
    lm3s_adc_info  *info = device->dev_priv;
149
 
150
    lm3s_adc_diag("ADC: Init\n");
151
 
152
    if (!info->int_handle) {
153
        lm3s_adc_diag("ADC: IRQ vect %d, pri %d\n",
154
                      info->adc_vector, info->adc_intprio);
155
 
156
        cyg_drv_interrupt_create(info->adc_vector,
157
                                 info->adc_intprio,
158
                                 (cyg_addrword_t)device,
159
                                 &lm3s_adc_isr,
160
                                 &lm3s_adc_dsr,
161
                                 &(info->int_handle), &(info->int_data));
162
        cyg_drv_interrupt_attach(info->int_handle);
163
        cyg_drv_interrupt_mask(info->adc_vector);
164
 
165
        // Enable ADC and sampling timer peripheral
166
        CYGHWR_HAL_LM3S_PERIPH_SET(info->adc_periph, 1);
167
        CYGHWR_HAL_LM3S_PERIPH_SET((CYGHWR_HAL_LM3S_PERIPH_GC1 | info->
168
                                    timer_periph), 1);
169
 
170
        // Disable timer
171
        HAL_WRITE_UINT32(info->timer_base + CYGHWR_HAL_LM3S_GPTIM_CTL, 0);
172
 
173
        // Disable / reset sequencer
174
        HAL_WRITE_UINT32(info->adc_base + CYGHWR_HAL_LM3S_ADC_ACTSS, 0);
175
        HAL_WRITE_UINT32(info->adc_base + CYGHWR_HAL_LM3S_ADC_SS_MUX0, 0);
176
        HAL_WRITE_UINT32(info->adc_base + CYGHWR_HAL_LM3S_ADC_SS_CTL0, 0);
177
 
178
        // Trigger sampling from timer
179
        HAL_WRITE_UINT32(info->adc_base + CYGHWR_HAL_LM3S_ADC_EMUX,
180
                         CYGHWR_HAL_LM3S_ADC_EMUX_EM_TIMER(0));
181
 
182
        // Set Averaging
183
        HAL_WRITE_UINT32(info->adc_base + CYGHWR_HAL_LM3S_ADC_SAC,
184
                         info->adc_avg);
185
 
186
        // Setup timer
187
        HAL_WRITE_UINT32(info->timer_base + CYGHWR_HAL_LM3S_GPTIM_CFG,
188
                         CYGHWR_HAL_LM3S_GPTIM_CFG_32BIT);
189
        HAL_WRITE_UINT32(info->timer_base + CYGHWR_HAL_LM3S_GPTIM_TAMR,
190
                         CYGHWR_HAL_LM3S_GPTIM_TAMR_PERIODIC);
191
 
192
        // Setup the default sample rate
193
        lm3s_adc_set_rate(chan, chan->device->config.rate);
194
 
195
    }
196
 
197
    // Initialize generic parts of driver
198
    cyg_adc_device_init(device);
199
 
200
    return true;
201
}
202
 
203
 
204
//==========================================================================
205
// This function is called when a client looks up or opens a channel. It
206
// should call cyg_adc_channel_init() to initialize the generic part of
207
// the channel. It should also perform any operations needed to start the
208
// channel generating samples.
209
//==========================================================================
210
static Cyg_ErrNo
211
lm3s_adc_lookup(struct cyg_devtab_entry **tab,
212
                struct cyg_devtab_entry *sub_tab, const char *name)
213
{
214
    cyg_adc_channel *chan = (cyg_adc_channel *) (*tab)->priv;
215
    lm3s_adc_info  *info = chan->device->dev_priv;
216
 
217
    lm3s_adc_diag("ADC: Opening channel %d\n", chan->channel);
218
 
219
    if (chan->channel > info->max_channel)
220
        return ENOENT;
221
 
222
    info->channel[chan->channel] = chan;
223
 
224
    // Initialize generic parts of channel
225
    cyg_adc_channel_init(chan);
226
 
227
    // The generic ADC manual says: When a channel is first looked up or
228
    // opened, then it is automatically enabled and samples start to
229
    // accumulate - so we start the channel now
230
    chan->enabled = true;
231
    lm3s_adc_enable(chan);
232
 
233
    return ENOERR;
234
}
235
 
236
 
237
//==========================================================================
238
// This function is called from the generic ADC package to enable the
239
// channel in response to a CYG_IO_SET_CONFIG_ADC_ENABLE config operation.
240
// It should take any steps needed to start the channel generating samples
241
//==========================================================================
242
static void
243
lm3s_adc_enable(cyg_adc_channel * chan)
244
{
245
    lm3s_adc_info  *info = chan->device->dev_priv;
246
    cyg_uint32      ctl =
247
        CYGHWR_HAL_LM3S_GPTIM_CTL_TAEN | CYGHWR_HAL_LM3S_GPTIM_CTL_TAOTE;
248
    cyg_uint32      start = !info->chan_mask;
249
 
250
    // Disable ADC sequencer 0 and timer
251
    HAL_WRITE_UINT32(info->timer_base + CYGHWR_HAL_LM3S_GPTIM_CTL, 0);
252
    lm3s_adc_disable_sequencer0(info->adc_base);
253
 
254
    // Update sequencer
255
    info->chan_mask |= (1 << chan->channel);
256
    lm3s_adc_update_sequencer0(chan);
257
 
258
    // Unmask interrupt as soon as 1 channel is enable
259
    if (start) {
260
        cyg_drv_interrupt_unmask(info->adc_vector);
261
    }
262
    // Enable sequencer and timer
263
    lm3s_adc_enable_sequencer0(info->adc_base);
264
    HAL_WRITE_UINT32(info->timer_base + CYGHWR_HAL_LM3S_GPTIM_CTL, ctl);
265
}
266
 
267
 
268
//==========================================================================
269
// This function is called from the generic ADC package to enable the
270
// channel in response to a CYG_IO_SET_CONFIG_ADC_DISABLE config operation.
271
// It should take any steps needed to stop the channel generating samples.
272
//==========================================================================
273
static void
274
lm3s_adc_disable(cyg_adc_channel * chan)
275
{
276
    lm3s_adc_info  *info = chan->device->dev_priv;
277
    cyg_uint32      ctl =
278
        CYGHWR_HAL_LM3S_GPTIM_CTL_TAEN | CYGHWR_HAL_LM3S_GPTIM_CTL_TAOTE;
279
 
280
    // Disable ADC sequencer 0 and timer
281
    HAL_WRITE_UINT32(info->timer_base + CYGHWR_HAL_LM3S_GPTIM_CTL, 0);
282
    lm3s_adc_disable_sequencer0(info->adc_base);
283
 
284
    // Update sequencer
285
    info->chan_mask &= ~(1 << chan->channel);
286
    lm3s_adc_update_sequencer0(chan);
287
 
288
    // Stop scanning when no channel is active
289
    if (!info->chan_mask) {
290
        cyg_drv_interrupt_mask(info->adc_vector);
291
        return;
292
    }
293
    // Enable sequencer and timer
294
    lm3s_adc_enable_sequencer0(info->adc_base);
295
    HAL_WRITE_UINT32(info->timer_base + CYGHWR_HAL_LM3S_GPTIM_CTL, ctl);
296
}
297
 
298
 
299
//==========================================================================
300
// This function is called from the generic ADC package to enable the
301
// channel in response to a CYG_IO_SET_CONFIG_ADC_RATE config operation.
302
// It should take any steps needed to change the sample rate of the channel,
303
// or of the entire device.
304
// We use a timer channel to generate the interrupts for sampling the
305
// analog channels
306
//==========================================================================
307
static void
308
lm3s_adc_set_rate(cyg_adc_channel * chan, cyg_uint32 rate)
309
{
310
    cyg_adc_device *device = chan->device;
311
    lm3s_adc_info  *info = (lm3s_adc_info *) device->dev_priv;
312
 
313
    info->timer_interval = hal_lm3s_timer_clock() / rate;
314
 
315
    lm3s_adc_diag("ADC: Timer interval %d\n", info->timer_interval);
316
 
317
    HAL_WRITE_UINT32(info->timer_base + CYGHWR_HAL_LM3S_GPTIM_TAILR,
318
                     info->timer_interval);
319
}
320
 
321
 
322
//==========================================================================
323
// This function is the ISR attached to the ADC device's interrupt vector.
324
// It is responsible for reading samples from the channels and passing them
325
// on to the generic layer. It needs to check each channel for data, and call
326
// cyg_adc_receive_sample() for each new sample available, and then ready the
327
// device for the next interrupt.
328
//==========================================================================
329
static cyg_uint32
330
lm3s_adc_isr(cyg_vector_t vector, cyg_addrword_t data)
331
{
332
    cyg_adc_device *device = (cyg_adc_device *) data;
333
    lm3s_adc_info  *info = (lm3s_adc_info *) device->dev_priv;
334
    cyg_uint32      regval;
335
    cyg_uint32      res = 0;
336
    cyg_adc_sample_t adcdata;
337
    cyg_uint32      sr;
338
 
339
    cyg_uint8       active_channels = info->chan_mask;
340
    cyg_uint8       channel_no = 0;
341
 
342
    while (active_channels) {
343
        HAL_READ_UINT32(info->adc_base + CYGHWR_HAL_LM3S_ADC_SS_FIFO0_SR, sr);
344
        // Check FIFO Full
345
        if ((sr & CYGHWR_HAL_LM3S_ADC_SS_FIFO_SR_FULL)) {
346
            lm3s_adc_diag("ADC: FIFO Full\n");
347
        }
348
        // Check FIFO Empty
349
        if ((sr & CYGHWR_HAL_LM3S_ADC_SS_FIFO_SR_EMPTY)) {
350
            lm3s_adc_diag("ADC: FIFO Empty\n");
351
        }
352
        if (active_channels & 0x01) {
353
            // If ADC conversion done, save sample
354
            if (!(sr & CYGHWR_HAL_LM3S_ADC_SS_FIFO_SR_EMPTY)) {
355
                HAL_READ_UINT32(info->adc_base + CYGHWR_HAL_LM3S_ADC_SS_FIFO0,
356
                                regval);
357
                adcdata = regval & 0x3FF;
358
                res |= CYG_ISR_HANDLED
359
                    | cyg_adc_receive_sample(info->channel[channel_no],
360
                                             adcdata);
361
            }
362
        }
363
        active_channels >>= 1;
364
        channel_no++;
365
    }
366
 
367
    HAL_WRITE_UINT32(info->adc_base + CYGHWR_HAL_LM3S_ADC_ISCR,
368
                     CYGHWR_HAL_LM3S_ADC_ISCR_IN(0));
369
 
370
    cyg_drv_interrupt_acknowledge(info->adc_vector);
371
 
372
    return res;
373
}
374
 
375
 
376
//==========================================================================
377
// This function is the DSR attached to the ADC device's interrupt vector.
378
// It is called by the kernel if the ISR return value contains the
379
// CYG_ISR_HANDLED bit. It needs to call cyg_adc_wakeup() for each channel
380
// that has its wakeup field set.
381
//==========================================================================
382
static void
383
lm3s_adc_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
384
{
385
    cyg_adc_device *device = (cyg_adc_device *) data;
386
    lm3s_adc_info  *info = device->dev_priv;
387
    cyg_uint8       active_channels = info->chan_mask;
388
    cyg_uint8       chan_no = 0;
389
 
390
    while (active_channels) {
391
        if (active_channels & 0x01) {
392
            if (info->channel[chan_no]->wakeup) {
393
                cyg_adc_wakeup(info->channel[chan_no]);
394
            }
395
        }
396
        chan_no++;
397
        active_channels >>= 1;
398
    }
399
}
400
 
401
 
402
static void
403
lm3s_adc_disable_sequencer0(cyg_uint32 base)
404
{
405
    cyg_uint32      reg;
406
 
407
    HAL_WRITE_UINT32(base + CYGHWR_HAL_LM3S_ADC_IMR, 0);
408
    HAL_WRITE_UINT32(base + CYGHWR_HAL_LM3S_ADC_ISCR,
409
                     CYGHWR_HAL_LM3S_ADC_ISCR_IN(0));
410
    HAL_READ_UINT32(base + CYGHWR_HAL_LM3S_ADC_ACTSS, reg);
411
    reg &= ~(CYGHWR_HAL_LM3S_ADC_ACTSS_ASEN(0));
412
    HAL_WRITE_UINT32(base + CYGHWR_HAL_LM3S_ADC_ACTSS, reg);
413
}
414
 
415
 
416
static void
417
lm3s_adc_enable_sequencer0(cyg_uint32 base)
418
{
419
    cyg_uint32      reg;
420
 
421
    HAL_READ_UINT32(base + CYGHWR_HAL_LM3S_ADC_ACTSS, reg);
422
    reg |= (CYGHWR_HAL_LM3S_ADC_ACTSS_ASEN(0));
423
    HAL_WRITE_UINT32(base + CYGHWR_HAL_LM3S_ADC_ACTSS, reg);
424
    HAL_WRITE_UINT32(base + CYGHWR_HAL_LM3S_ADC_IMR,
425
                     CYGHWR_HAL_LM3S_ADC_IMR_MASK(0));
426
}
427
 
428
 
429
static void
430
lm3s_adc_flush(cyg_uint32 base)
431
{
432
    volatile cyg_uint32 d;
433
    volatile cyg_uint32 i;
434
 
435
    HAL_READ_UINT32(base + CYGHWR_HAL_LM3S_ADC_SS_FIFO0_SR, i);
436
    while (!(i & CYGHWR_HAL_LM3S_ADC_SS_FIFO_SR_EMPTY)) {
437
        HAL_READ_UINT32(base + CYGHWR_HAL_LM3S_ADC_SS_FIFO0, d);
438
        HAL_READ_UINT32(base + CYGHWR_HAL_LM3S_ADC_SS_FIFO0_SR, i);
439
    }
440
}
441
 
442
 
443
static void
444
lm3s_adc_update_sequencer0(cyg_adc_channel * chan)
445
{
446
    lm3s_adc_info  *info = chan->device->dev_priv;
447
    cyg_uint8       i;
448
    cyg_uint8       cnt = 0;
449
    cyg_uint32      mux = 0;
450
    cyg_uint32      ctl = 0;
451
 
452
    lm3s_adc_diag("ADC: Update sequencer for channel %d\n", chan->channel);
453
 
454
    // Update sequencer
455
    for (i = 0; i < info->max_channel; i++) {
456
        if (!(info->chan_mask & (1 << i)))
457
            continue;
458
 
459
        // Clear and update MUX register
460
        mux &= ~(CYGHWR_HAL_LM3S_ADC_SS_MUX0_M(cnt));
461
        mux |= CYGHWR_HAL_LM3S_ADC_SS_MUX0_V(i, cnt);
462
 
463
        // Temperature sensor channel
464
        if (i == info->sensor_channel) {
465
            ctl |= CYGHWR_HAL_LM3S_ADC_SS_CTL0_TS(cnt);
466
            lm3s_adc_diag("ADC: Channel %d mapped to temperature sensor\n",
467
                          i);
468
        }
469
 
470
        cnt++;
471
    }
472
 
473
    lm3s_adc_diag("ADC: MUX0 Register: 0x%x\n", mux);
474
    HAL_WRITE_UINT32(info->adc_base + CYGHWR_HAL_LM3S_ADC_SS_MUX0, mux);
475
 
476
    if (info->chan_mask) {
477
        ctl |= CYGHWR_HAL_LM3S_ADC_SS_CTL0_END((cnt - 1));
478
        ctl |= CYGHWR_HAL_LM3S_ADC_SS_CTL0_IE((cnt - 1));
479
    }
480
 
481
    lm3s_adc_diag("ADC: CTL0 Register: 0x%x\n", ctl);
482
    HAL_WRITE_UINT32(info->adc_base + CYGHWR_HAL_LM3S_ADC_SS_CTL0, ctl);
483
 
484
    lm3s_adc_flush(info->adc_base);
485
}
486
 
487
 
488
//---------------------------------------------------------------------------
489
// EOF adc_lm3s.c

powered by: WebSVN 2.1.0

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