Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/****************************************************************************
* arch/arm/src/tiva/tiva_adclib.c
*
* Copyright (C) 2015 TRD2 Inc. All rights reserved.
* Author: Calvin Maguranis <calvin.maguranis@trd2inc.com>
*
* References:
*
* TM4C123GH6PM Series Data Sheet
* TI Tivaware driverlib ADC sample code.
*
* The Tivaware sample code has a BSD compatible license that requires this
* copyright notice:
*
* Copyright (c) 2005-2014 Texas Instruments Incorporated. All rights reserved.
* Software License Agreement
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
Vinicius Maciel
committed
* This is part of revision 2.1.0.12573 of the Tiva Peripheral Driver
* Library.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
Gregory Nutt
committed
#include <nuttx/config.h>
Gregory Nutt
committed
#include <sys/types.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include <debug.h>
#include <assert.h>
Gregory Nutt
committed
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/analog/adc.h>
#include <arch/board/board.h>
#include "up_arch.h"
#include "up_internal.h"
#include "tiva_gpio.h"
#include "tiva_adc.h"
#include "chip/tiva_adc.h"
#include "chip/tiva_pinmap.h"
#if defined (CONFIG_TIVA_ADC0) || defined (CONFIG_TIVA_ADC1)
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define CLOCK_CONFIG(div, src) \
(((((div) << ADC_CC_CLKDIV_SHIFT) & ADC_CC_CLKDIV_MASK) | \
((src) & ADC_CC_CS_MASK)) & (ADC_CC_CLKDIV_MASK + ADC_CC_CS_MASK))
Vinicius Maciel
committed
#define INTERNAL_VREF 0x00
#define EXTERNAL_VREF 0x01
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/****************************************************************************
* Private Data
****************************************************************************/
static uint8_t sse2irq[] =
{
#ifdef CONFIG_TIVA_ADC0
TIVA_IRQ_ADC0, TIVA_IRQ_ADC1, TIVA_IRQ_ADC2, TIVA_IRQ_ADC3
#endif
#ifdef CONFIG_TIVA_ADC1
, TIVA_IRQ_ADC1_0, TIVA_IRQ_ADC1_1, TIVA_IRQ_ADC1_2, TIVA_IRQ_ADC1_3
#endif
};
static uint32_t ain2gpio[] =
{
#ifdef GPIO_ADC_AIN0
GPIO_ADC_AIN0
#endif
#ifdef GPIO_ADC_AIN1
, GPIO_ADC_AIN1
#endif
#ifdef GPIO_ADC_AIN2
, GPIO_ADC_AIN2
#endif
#ifdef GPIO_ADC_AIN3
, GPIO_ADC_AIN3
#endif
#ifdef GPIO_ADC_AIN4
, GPIO_ADC_AIN4
#endif
#ifdef GPIO_ADC_AIN5
, GPIO_ADC_AIN5
#endif
#ifdef GPIO_ADC_AIN6
, GPIO_ADC_AIN6
#endif
#ifdef GPIO_ADC_AIN7
, GPIO_ADC_AIN7
#endif
#ifdef GPIO_ADC_AIN8
, GPIO_ADC_AIN8
#endif
#ifdef GPIO_ADC_AIN9
, GPIO_ADC_AIN9
#endif
#ifdef GPIO_ADC_AIN10
, GPIO_ADC_AIN10
#endif
#ifdef GPIO_ADC_AIN11
, GPIO_ADC_AIN11
#endif
#ifdef GPIO_ADC_AIN12
, GPIO_ADC_AIN12
#endif
#ifdef GPIO_ADC_AIN13
, GPIO_ADC_AIN13
#endif
#ifdef GPIO_ADC_AIN14
, GPIO_ADC_AIN14
#endif
#ifdef GPIO_ADC_AIN15
, GPIO_ADC_AIN15
#endif
#ifdef GPIO_ADC_AIN16
, GPIO_ADC_AIN16
#endif
#ifdef GPIO_ADC_AIN17
, GPIO_ADC_AIN17
#endif
#ifdef GPIO_ADC_AIN18
, GPIO_ADC_AIN18
#endif
#ifdef GPIO_ADC_AIN19
, GPIO_ADC_AIN19
#endif
#ifdef GPIO_ADC_AIN20
, GPIO_ADC_AIN20
#endif
#ifdef GPIO_ADC_AIN21
, GPIO_ADC_AIN21
#endif
#ifdef GPIO_ADC_AIN22
, GPIO_ADC_AIN22
#endif
#ifdef GPIO_ADC_AIN23
, GPIO_ADC_AIN23
#endif
};
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: tiva_adc_one_time_init
*
* Description:
* Perform one-time initialization of global ADC settings; clock frequency
* and sampling rate.
*
* Assumptions/Limitations:
* Peripheral must be powered before one-time initialization.
*
****************************************************************************/
void tiva_adc_one_time_init(uint32_t clock, uint8_t sample_rate)
{
static bool one_time_init = false;
#ifdef CONFIG_DEBUG_ANALOG
ainfo("setting clock=%d MHz sample rate=%d\n",
clock, sample_rate);
#endif
/* Have the common peripheral properties already been initialized? If yes,
* continue.
*/
if (one_time_init == false)
{
ainfo("performing ADC one-time initialization...\n");
Vinicius Maciel
committed
/* Set clock */
tiva_adc_clock(clock);
Vinicius Maciel
committed
/* Set sampling rate */
tiva_adc_sample_rate(sample_rate);
#ifdef CONFIG_ARCH_CHIP_TM4C129
Vinicius Maciel
committed
/* Voltage reference */
Vinicius Maciel
committed
tiva_adc_vref(INTERNAL_VREF);
#endif
one_time_init = true;
}
#ifdef CONFIG_DEBUG_ANALOG
else
{
ainfo("one time initialization previously completed\n");
}
#endif
}
/****************************************************************************
* Name: tiva_adc_configure
*
* Description:
Vinicius Maciel
committed
* Performs configuration of a single ADC, it's valid sample sequencers
* and available steps.
*
****************************************************************************/
void tiva_adc_configure(struct tiva_adc_cfg_s *cfg)
{
ainfo("configure ADC%d...\n", cfg->adc);
for (s = 0; s < 4; ++s)
{
if (cfg->sse[s])
{
tiva_adc_sse_cfg(cfg->adc, s, &cfg->ssecfg[s]);
}
#ifdef CONFIG_DEBUG_ANALOG
ainfo("ADC%d SSE%d has no configuration\n", cfg->adc, s);
#endif
for (c = 0; c < cfg->steps; ++c)
{
tiva_adc_step_cfg(&cfg->stepcfg[c]);
}
#ifdef CONFIG_DEBUG_ANALOG
tiva_adc_dump_reg_cfg(cfg->adc, 0);
#endif
}
/****************************************************************************
* Name: tiva_adc_sse_cfg
*
* Description:
* Configure the sample sequencer.
*
****************************************************************************/
void tiva_adc_sse_cfg(uint8_t adc, uint8_t sse,
struct tiva_adc_sse_cfg_s *ssecfg)
{
Vinicius Maciel
committed
uint8_t priority = ssecfg->priority;
uint8_t trigger = ssecfg->trigger;
ainfo("configure ADC%d SSE%d...\n", adc, sse);
#ifdef CONFIG_DEBUG_ANALOG
ainfo("priority=%d trigger=%d...\n", ssecfg->priority, ssecfg->trigger);
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
#endif
/* Ensure SSE is disabled before configuring */
tiva_adc_sse_enable(adc, sse, false);
/* Set conversion priority and trigger source for all steps in the SSE */
tiva_adc_sse_priority(adc, sse, priority);
tiva_adc_sse_trigger(adc, sse, trigger);
}
/****************************************************************************
* Name: tiva_adc_step_cfg
*
* Description:
* Configures a sample sequencer step.
*
****************************************************************************/
void tiva_adc_step_cfg(struct tiva_adc_step_cfg_s *stepcfg)
{
uint8_t adc = stepcfg->adc;
uint8_t sse = stepcfg->sse;
uint8_t step = stepcfg->step;
#ifdef CONFIG_EXPERIMENTAL
uint8_t shold = stepcfg->shold;
#endif
uint8_t flags = stepcfg->flags;
uint8_t ain = stepcfg->ain;
uint32_t gpio = ain2gpio[stepcfg->ain];
ainfo("configure ADC%d SSE%d STEP%d...\n", adc, sse, step);
Vinicius Maciel
committed
#ifdef CONFIG_DEBUG_ANALOG
ainfo(" shold=0x%02x flags=0x%02x ain=%d...\n",
stepcfg->shold, stepcfg->flags, stepcfg->ain);
#endif
Vinicius Maciel
committed
/* Configure the AIN GPIO for analog input if not flagged to be mux'ed to
* the internal temperature sensor
*/
if ((flags & TIVA_ADC_FLAG_TS) != TIVA_ADC_FLAG_TS)
{
tiva_configgpio(gpio);
}
/* Register, set sample/hold time and configure the step */
tiva_adc_sse_register_chn(adc, sse, step, ain);
tiva_adc_sse_differential(adc, sse, step, 0); /* TODO: update when differential
Vinicius Maciel
committed
* support is added. */
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
#ifdef CONFIG_EXPERIMENTAL
tiva_adc_sse_sample_hold_time(adc, sse, step, shold);
#endif
tiva_adc_sse_step_cfg(adc, sse, step, flags);
}
/****************************************************************************
* Name: tiva_adc_get_trigger
*
* Description:
* For a given adc, sse and step, get the AIN (channel) associated.
*
****************************************************************************/
uint8_t tiva_adc_get_trigger(uint8_t adc, uint8_t sse)
{
uintptr_t emuxaddr = TIVA_ADC_EMUX(adc);
uint32_t emux = getreg32(emuxaddr) & ADC_EMUX_MASK(sse);
return (emux >> ADC_EMUX_SHIFT(sse));
}
/****************************************************************************
* Name: tiva_adc_get_ain
*
* Description:
* For a given adc, sse and step, get the AIN (channel) associated.
*
****************************************************************************/
uint8_t tiva_adc_get_ain(uint8_t adc, uint8_t sse, uint8_t step)
{
uintptr_t ssmuxaddr = TIVA_ADC_BASE(adc)+TIVA_ADC_SSMUX(sse);
uint32_t ssmux = getreg32(ssmuxaddr) & ADC_SSMUX_MUX_MASK(step);
return (ssmux >> ADC_SSMUX_MUX_SHIFT(step));
}
/****************************************************************************
* Name: tiva_adc_irq_attach
*
* Description:
* Attach a custom interrupt handler.
*
****************************************************************************/
void tiva_adc_irq_attach(uint8_t adc, uint8_t sse, xcpt_t isr)
{
uint32_t ret = 0;
int irq = sse2irq[SSE_IDX(adc, sse)];
#ifdef CONFIG_DEBUG_ANALOG
ainfo("assigning ISR=0x%p to ADC%d SSE%d IRQ=0x%02x...\n",
isr, adc, sse, irq);
#endif
ret = irq_attach(irq, isr, NULL);
if (ret < 0)
{
aerr("ERROR: Failed to attach IRQ %d: %d\n", irq, ret);
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
return;
}
up_enable_irq(irq);
}
/****************************************************************************
* Name: tiva_adc_irq_detach
*
* Description:
* detach an interrupt handler.
*
****************************************************************************/
void tiva_adc_irq_detach(uint8_t adc, uint8_t sse)
{
uint32_t ret = 0;
int irq = sse2irq[SSE_IDX(adc, sse)];
/* Disable ADC interrupts at the level of the AIC */
up_disable_irq(irq);
/* Then detach the ADC interrupt handler. */
ret = irq_detach(irq);
if (ret < 0)
{
aerr("ERROR: Failed to detach IRQ %d: %d\n", irq, ret);
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
return;
}
}
/****************************************************************************
* Name: tiva_adc_getirq
*
* Description:
* Maps ADC and SSE value to the correct IRQ value.
*
****************************************************************************/
int tiva_adc_getirq(uint8_t adc, uint8_t sse)
{
return sse2irq[SSE_IDX(adc, sse)];
}
/****************************************************************************
* Name: tiva_adc_enable
*
* Description:
* Toggles the operational state of the ADC peripheral
*
* Input Parameters:
* state - operation state
*
****************************************************************************/
int tiva_adc_enable(uint8_t adc, bool state)
{
if (state == true)
{
/* Enable clocking to the ADC peripheral */
#ifdef TIVA_SYSCON_RCGCADC
modifyreg32(TIVA_SYSCON_RCGCADC, 0, 1 << adc);
#else
modifyreg32(TIVA_SYSCON_RCGC0, 0, SYSCON_RCGC0_ADC0);
#endif
return OK;
}
else if (state == false)
{
/* Disable clocking to the ADC peripheral */
#ifdef TIVA_SYSCON_RCGCADC
modifyreg32(TIVA_SYSCON_RCGCADC, 1 << adc, 0);
#else
modifyreg32(TIVA_SYSCON_RCGC0, SYSCON_RCGC0_ADC0, 0);
#endif
return OK;
}
/* ERROR! */
return -1;
}
/****************************************************************************
* Name: tiva_adc_clock
*
* Description:
* Sets the ADC peripherals clock to the desired frequency.
*
* Input Parameters:
* freq - ADC clock value; dependent on platform:
*
* TM4C123 - Select either MOSC or PIOSC. Both result in 16 MHz operation,
* however the PIOSC allows the ADC to operate in deep sleep mode.
*
* TM4C129 - For the 129, there is still a selection between various internal
* clocks, however the output frequency is variable (16 MHz - 32 MHz); so it
* is much more intuitive to allow the clock variable be a frequency value.
*
****************************************************************************/
void tiva_adc_clock(uint32_t freq)
{
#if defined(CONFIG_ARCH_CHIP_TM4C123)
/* For the TM4C123, the ADC clock source does not affect the frequency, it
* runs at 16 MHz regardless. You end up selecting between the MOSC (default)
* or the PIOSC. The PIOSC allows the ADC to operate even in deep sleep mode.
* Since this is the case, the clock value for the TM4C123 is always 16 MHz
*/
uintptr_t ccreg = (TIVA_ADC0_BASE + TIVA_ADC_CC_OFFSET);
modifyreg32(ccreg, ADC_CC_CS_MASK, (ADC_CC_CS_PIOSC & ADC_CC_CS_MASK));
#elif defined (CONFIG_ARCH_CHIP_TM4C129)
Vinicius Maciel
committed
/* Check clock bounds and specific match cases */
uint32_t clk_src = 0;
uint32_t div = 0;
Vinicius Maciel
committed
uintptr_t ccreg;
if (freq > TIVA_ADC_CLOCK_MAX)
{
clk_src = ADC_CC_CS_SYSPLL;
Vinicius Maciel
committed
div = (BOARD_FVCO_FREQUENCY / TIVA_ADC_CLOCK_MAX);
}
else if (freq < TIVA_ADC_CLOCK_MIN)
{
clk_src = ADC_CC_CS_PIOSC;
Vinicius Maciel
committed
div = 1;
}
else if (freq == XTAL_FREQUENCY)
{
clk_src = ADC_CC_CS_MOSC;
Vinicius Maciel
committed
div = 1;
}
else
{
clk_src = ADC_CC_CS_SYSPLL;
Vinicius Maciel
committed
div = (BOARD_FVCO_FREQUENCY / freq);
}
Vinicius Maciel
committed
ccreg = (TIVA_ADC0_BASE + TIVA_ADC_CC_OFFSET);
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
modifyreg32(ccreg, ADC_CC_CLKDIV_MASK, CLOCK_CONFIG(div, clk_src));
#else
# error Unsupported architecture reported
#endif
}
/****************************************************************************
* Name: tiva_adc_vref
*
* Description:
* Sets the ADC peripherals clock to the desired frequency.
*
* Input Parameters:
* vref - ADC clock voltage reference source
*
****************************************************************************/
#ifdef CONFIG_ARCH_CHIP_TM4C129
void tiva_adc_vref(uint8_t vref)
{
uintptr_t ctlreg = (TIVA_ADC0_BASE + TIVA_ADC_CTL_OFFSET);
modifyreg32(ctlreg, ADC_CTL_VREF_MASK, (vref & ADC_CTL_VREF_MASK));
}
#endif
/****************************************************************************
* Name: tiva_adc_sample_rate
*
* Description:
* Sets the ADC sample rate as follows for each processor.
* TM4C123 - by maximum samples: 125 ksps, 250 ksps, 500 ksps or 1 Msps
* TM4C129 - by a divisor either being full, half, quarter or
* an eighth.
*
* Input Parameters:
* rate - ADC sample rate divisor
*
****************************************************************************/
void tiva_adc_sample_rate(uint8_t rate)
{
uintptr_t pcreg = (TIVA_ADC0_BASE + TIVA_ADC_PC_OFFSET);
/* NOTE: ADC_PC_SR_MASK is intended for use with the TM4C123, the
* alternative is ADC_PC_MCR_MASK for the TM4C129. However both masks
* mask off the first 4 bits (0xF) so there is no need to distinguish
* between the two.
*/
modifyreg32(pcreg, ADC_PC_SR_MASK, (rate & ADC_PC_SR_MASK));
}
/****************************************************************************
* Name: tiva_adc_proc_trig
*
* Description:
* Triggers the sample sequence to start it's conversion(s) and store them
* to the FIFO. This is only required when the trigger source is set to the
* processor.
*
* Input Parameters:
* adc - which ADC peripherals' sample sequencers to trigger
* sse_mask - sample sequencer bitmask, each sse is 1 shifted by the sse
* number. e.g.
* SSE0 = 1 << 0
* SSE1 = 1 << 1
* SSE2 = 1 << 2
* SSE3 = 1 << 3
*
****************************************************************************/
void tiva_adc_proc_trig(uint8_t adc, uint8_t sse_mask)
{
uintptr_t pssireg = TIVA_ADC_PSSI(adc);
putreg32((sse_mask & ADC_PSSI_TRIG_MASK), pssireg);
#ifdef CONFIG_TIVA_ADC_SYNC
# warning CONFIG_TIVA_ADC_SYNC unsupported at this time.
#endif
}
/****************************************************************************
* Name: tiva_adc_int_status
*
* Description:
* Returns raw interrupt status for the input ADC
*
* Input Parameters:
* adc - which ADC peripherals' interrupt status to retrieve
*
****************************************************************************/
uint32_t tiva_adc_int_status(uint8_t adc)
{
uint32_t ris = getreg32(TIVA_ADC_RIS(adc));
return ris;
}
/****************************************************************************
* Name: tiva_adc_sse_enable
*
* Description:
* Sets the operation state of an ADC's sample sequencer (SSE). SSEs must
* be configured before being enabled.
*
* Input Parameters:
* adc - peripheral state
* sse - sample sequencer
* state - sample sequencer enable/disable state
*
* Returned Value:
* Actual state of the ACTSS register.
*
****************************************************************************/
uint8_t tiva_adc_sse_enable(uint8_t adc, uint8_t sse, bool state)
{
Vinicius Maciel
committed
uintptr_t actssreg = TIVA_ADC_ACTSS(adc);
ainfo("ADC%d SSE%d=%01d\n", adc, sse, state);
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
if (state == true)
{
modifyreg32(actssreg, 0, (1 << sse));
}
else
{
modifyreg32(actssreg, (1 << sse), 0);
}
return (getreg32(actssreg) & 0xF);
}
/****************************************************************************
* Name: tiva_adc_sse_trigger
*
* Description:
* Sets the trigger configuration for an ADC's sample sequencer (SSE).
* Possible triggers are the following:
* - Processor
* - PWMs, requires that one of the PWMnn_TRIG_CFG defines be OR'd
* into the trigger value.
* - Timers
* - GPIO (which GPIO is platform specific, consult the datasheet)
* - Always
* - !!UNSUPPORTED: Comparators
*
* Input Parameters:
* adc - peripheral state
* sse - sample sequencer
* trigger - interrupt trigger
*
****************************************************************************/
void tiva_adc_sse_trigger(uint8_t adc, uint8_t sse, uint32_t trigger)
{
uintptr_t emuxreg = (TIVA_ADC_EMUX(adc));
uint32_t trig = ((trigger << ADC_EMUX_SHIFT(sse)) & ADC_EMUX_MASK(sse));
modifyreg32(emuxreg, ADC_EMUX_MASK(sse), trig);
/* NOTE: PWM triggering needs an additional register to be set (ADC_TSSEL)
* A platform specific IOCTL command is provided to configure the triggering.
*/
}
/****************************************************************************
* Name: tiva_adc_sse_pwm_trig
*
* Description:
* Additional triggering configuration for PWM. Sets which PWM and which
* generator.
*
* Input Parameters:
* adc - peripheral state
* sse - sample sequencer
* cfg - which PWM modulator and generator to use, use TIVA_ADC_PWM_TRIG
* to encode the value correctly
*
****************************************************************************/
#ifdef CONFIG_EXPERIMENTAL
void tiva_adc_sse_pwm_trig(uint8_t adc, uint8_t sse, uint32_t cfg)
{
/* PWM triggering needs an additional register to be set (ADC_TSSEL) */
uintptr_t tsselreg = TIVA_ADC_TSSEL(adc);
modifyreg32(tsselreg, ADC_TSSEL_PS_MASK(see), cfg);
}
#endif
/****************************************************************************
* Name: tiva_adc_sse_int_enable
*
* Description:
* Sets the interrupt state of an ADC's sample sequencer (SSE). SSEs must
* be enabled before setting interrupt state.
*
* Input Parameters:
* adc - peripheral state
* sse - sample sequencer
* state - sample sequencer enable/disable interrupt state
*
****************************************************************************/
void tiva_adc_sse_int_enable(uint8_t adc, uint8_t sse, bool state)
{
irqstate_t flags;
uintptr_t imreg = TIVA_ADC_IM(adc);
int irq = tiva_adc_getirq(adc, sse);
Gregory Nutt
committed
flags = enter_critical_section();
up_disable_irq(irq);
tiva_adc_sse_clear_int(adc, sse);
if (state == true)
{
modifyreg32(imreg, 0, (1 << sse));
}
else
{
modifyreg32(imreg, (1 << sse), 0);
}
up_enable_irq(irq);
Gregory Nutt
committed
leave_critical_section(flags);
}
/****************************************************************************
* Name: tiva_adc_sse_int_status
*
* Description:
Vinicius Maciel
committed
* Returns interrupt status for the specified SSE
*
* Input Parameters:
* adc - which ADC peripherals' interrupt status to retrieve
* sse - which SSE interrupt status to retrieve
*
****************************************************************************/
bool tiva_adc_sse_int_status(uint8_t adc, uint8_t sse)
{
uint32_t intstat = tiva_adc_int_status(adc);
uint32_t sseintstat = intstat & (1 << sse);
return sseintstat > 0 ? true : false;
}
/****************************************************************************
* Name: tiva_adc_sse_clear_int
*
* Description:
* Clears the interrupt bit for the SSE.
*
* Input Parameters:
Vinicius Maciel
committed
* adc - peripheral state
* sse - sample sequencer
* state - sample sequencer
*
****************************************************************************/
void tiva_adc_sse_clear_int(uint8_t adc, uint8_t sse)
{
uintptr_t iscreg = TIVA_ADC_ISC(adc);
modifyreg32(iscreg, 0, (1 << sse));
}
/****************************************************************************
* Name: tiva_adc_sse_data
*
* Description:
* Retrieves data from the FIFOs for all steps in the given sample sequencer.
* The input data buffer MUST be as large or larger than the sample sequencer.
* otherwise
*
* Input Parameters:
* adc - peripheral state
* sse - sample sequencer
*
* Returned Value:
* number of steps read from FIFO.
*
****************************************************************************/
uint8_t tiva_adc_sse_data(uint8_t adc, uint8_t sse, int32_t *buf)
{
uint32_t ssfstatreg = getreg32(TIVA_ADC_BASE(adc) + TIVA_ADC_SSFSTAT(sse));
uint8_t fifo_count = 0;
/* Read samples from the FIFO until it is empty */
while (!(ssfstatreg & ADC_SSFSTAT_EMPTY) && fifo_count < 8)
{
/* Read the FIFO and copy it to the destination */
buf[fifo_count] = getreg32(TIVA_ADC_BASE(adc) + TIVA_ADC_SSFIFO(sse));
fifo_count++;
/* refresh fifo status register state */
ssfstatreg = getreg32(TIVA_ADC_BASE(adc) + TIVA_ADC_SSFSTAT(sse));
}
ainfo("fifo=%d\n", fifo_count);
return fifo_count;
}
/****************************************************************************
* Name: tiva_adc_sse_priority
*
* Description:
* Sets the priority configuration for an ADC's sample sequencer (SSE). The
* priority value ranges from 0 to 3, 0 being the highest priority, 3 being
* the lowest. There can be no duplicate values.
*
* Input Parameters:
Vinicius Maciel
committed
* adc - peripheral state
* sse - sample sequencer
* priority - conversion priority
*
****************************************************************************/
void tiva_adc_sse_priority(uint8_t adc, uint8_t sse, uint8_t priority)
{
uintptr_t ssprireg = TIVA_ADC_SSPRI(adc);
uint32_t sspri = 0;
sspri = (priority << ADC_SSPRI_SHIFT(sse)) & ADC_SSPRI_MASK(sse);
modifyreg32(ssprireg, ADC_SSPRI_MASK(sse), sspri);
}
/****************************************************************************
* Name: tiva_adc_sse_register_chn
*
* Description:
* Registers an input channel to an SSE. Channels are registered according
* to the step and channel values stored in the channel struct. If the SSE
* already has a channel registered, it is overwritten by the new channel.
*
* *SSEMUX only supported on TM4C129 devices
*
* Input Parameters:
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
* adc - peripheral state
* sse - sample sequencer
* chn - sample sequencer step
* ain - analog input pin
*
****************************************************************************/
void tiva_adc_sse_register_chn(uint8_t adc, uint8_t sse, uint8_t chn,
uint32_t ain)
{
/* Configure SSE mux (SSMUX) with step number */
uintptr_t ssmuxreg = (TIVA_ADC_BASE(adc) + TIVA_ADC_SSMUX(sse));
uint32_t step = 0;
step = ((ain << ADC_SSMUX_MUX_SHIFT(chn)) & ADC_SSMUX_MUX_MASK(chn));
modifyreg32(ssmuxreg, ADC_SSMUX_MUX_MASK(chn), step);
#ifdef CONFIG_ARCH_CHIP_TM4C129
/* Configure SSE extended mux (SSEMUX) with step number and configuration */
ssmuxreg = (TIVA_ADC_BASE(adc) + TIVA_ADC_SSEMUX(sse));
step = ((1 << ADC_SSEMUX_MUX_SHIFT(chn)) & ADC_SSEMUX_MUX_MASK(chn));
modifyreg32(ssmuxreg, ADC_SSEMUX_MUX_MASK(chn), step);
#endif
}
/****************************************************************************
* Name: tiva_adc_sse_differential
*
* Description:
* Sets the differential capability for a SSE. !! UNSUPPORTED
*
* Input Parameters:
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
* adc - peripheral state
* sse - sample sequencer
* chn - sample sequencer channel
* diff - differential configuration
*
****************************************************************************/
void tiva_adc_sse_differential(uint8_t adc, uint8_t sse, uint8_t chn, uint32_t diff)
{
#ifdef CONFIG_TIVA_ADC_DIFFERENTIAL
# error CONFIG_TIVA_ADC_DIFFERENTIAL unsupported!!
#else
/* for now, ensure the FIFO is used and differential sampling is disabled */
uintptr_t ssopreg = (TIVA_ADC_BASE(adc) + TIVA_ADC_SSOP(sse));
uint32_t sdcopcfg = (1 << chn);
modifyreg32(ssopreg, sdcopcfg, 0);
#endif
}
/****************************************************************************
* Name: tiva_adc_sse_sample_hold_time
*
* Description:
* Set the sample and hold time for this step.
*
* This is not available on all devices, however on devices that do not
* support this feature these reserved bits are ignored on write access.
*
* Input Parameters:
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
* adc - peripheral state
* sse - sample sequencer
* chn - sample sequencer channel
* shold - sample and hold time
*
****************************************************************************/
#ifdef CONFIG_EXPERIMENTAL
void tiva_adc_sse_sample_hold_time(uint8_t adc, uint8_t sse,
uint8_t chn, uint32_t shold)
{
uintptr_t sstshreg = (TIVA_ADC_BASE(adc) + TIVA_ADC_SSTSH(sse));
modifyreg32(sstshreg, ADC_SSTSH_MASK(sse), (shold << ADC_SSTSH_SHIFT(sse)));
}
#endif
/****************************************************************************
* Name: tiva_adc_sse_step_cfg
*
* Description:
* Configures the given SSE step to one of the following options:
* -Temperature sensor select: this step is muxed to the internal
* temperature sensor.
* -Interrupt enabled select: this step causes the interrupt bit to
* be set and, if the MASK0 bit in ADC_IM register is set, the
* interrupt is promoted to the interrupt controller.
* -Sequence end select: This step is the last sequence to be sampled.
* This MUST be set somewhere in the SSE.
* -*Comparator/Differential select: The analog input is differentially
* sampled. The corresponding ADCSSMUXn nibble must be set to the pair
* number "i", where the paired inputs are "2i and 2i+1". Because the
* temperature sensor does not have a differential option, this bit must
* not be set when the TS3 bit is set.
*
* *Comparator/Differential functionality is unsupported and ignored.
*
* Input Parameters:
* adc - peripheral state
* sse - sample sequencer
* chn - sample sequencer channel
* cfg - step configuration