1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #9722 from smlng/pr/cc2538/adc

cpu/cc2538: enhance periph ADC
This commit is contained in:
Andreas "Paul" Pauli 2018-09-06 14:12:03 +02:00 committed by GitHub
commit dc6eb82406
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 60 additions and 93 deletions

View File

@ -118,7 +118,7 @@ static const spi_conf_t spi_config[] = {
* @name ADC configuration
* @{
*/
#define SOC_ADC_ADCCON_REF SOC_ADC_ADCCON_REF_AVDD5
#define SOC_ADC_ADCCON3_EREF SOC_ADC_ADCCON3_EREF_AVDD5
static const adc_conf_t adc_config[] = {
GPIO_PIN(0, 6), /**< GPIO_PA6 = ADC_ALS_PIN */

View File

@ -71,7 +71,7 @@ static const timer_conf_t timer_config[] = {
* @name ADC configuration
* @{
*/
#define SOC_ADC_ADCCON_REF SOC_ADC_ADCCON_REF_AVDD5
#define SOC_ADC_ADCCON3_EREF SOC_ADC_ADCCON3_EREF_AVDD5
static const adc_conf_t adc_config[] = {
GPIO_PIN(1, 0), /**< GPIO_PB0 = GPIO0_PIN */

View File

@ -69,7 +69,7 @@ static const timer_conf_t timer_config[] = {
* @name ADC configuration
* @{
*/
#define SOC_ADC_ADCCON_REF SOC_ADC_ADCCON_REF_AVDD5
#define SOC_ADC_ADCCON3_EREF SOC_ADC_ADCCON3_EREF_AVDD5
static const adc_conf_t adc_config[] = {
GPIO_PIN(0, 2), /**< GPIO_PA2 = AD4_PIN */

View File

@ -73,7 +73,7 @@ static const spi_conf_t spi_config[] = {
* @name ADC configuration
* @{
*/
#define SOC_ADC_ADCCON_REF SOC_ADC_ADCCON_REF_AVDD5
#define SOC_ADC_ADCCON3_EREF SOC_ADC_ADCCON3_EREF_AVDD5
static const adc_conf_t adc_config[] = {
GPIO_PIN(0, 6), /**< GPIO_PA6 = ADC2_PIN */

View File

@ -73,7 +73,7 @@ static const spi_conf_t spi_config[] = {
* @name ADC configuration
* @{
*/
#define SOC_ADC_ADCCON_REF SOC_ADC_ADCCON_REF_AVDD5
#define SOC_ADC_ADCCON3_EREF SOC_ADC_ADCCON3_EREF_AVDD5
static const adc_conf_t adc_config[] = {
GPIO_PIN(0, 5), /**< GPIO_PA5 = ADC1_PIN */

View File

@ -75,7 +75,7 @@ static const spi_conf_t spi_config[] = {
* @name ADC configuration
* @{
*/
#define SOC_ADC_ADCCON_REF SOC_ADC_ADCCON_REF_AVDD5
#define SOC_ADC_ADCCON3_EREF SOC_ADC_ADCCON3_EREF_AVDD5
static const adc_conf_t adc_config[] = {
GPIO_PIN(0, 5), /**< GPIO_PA5 = ADC1_PIN */

View File

@ -675,14 +675,6 @@ typedef volatile uint32_t cc2538_reg_t; /**< Least-significant 32 bits of the IE
#define SMWDTHROSC_STCV2 ( *(cc2538_reg_t*)0x400d5064 ) /**< Sleep Timer Capture value byte 2 */
#define SMWDTHROSC_STCV3 ( *(cc2538_reg_t*)0x400d5068 ) /**< Sleep Timer Capture value byte 3 */
#define ANA_REGS_IVCTRL ( *(cc2538_reg_t*)0x400d6004 ) /**< Analog control register */
#define SOC_ADC_ADCCON1 ( *(cc2538_reg_t*)0x400d7000 ) /**< ADC Control Register 1 */
#define SOC_ADC_ADCCON2 ( *(cc2538_reg_t*)0x400d7004 ) /**< ADC Control Register 2 */
#define SOC_ADC_ADCCON3 ( *(cc2538_reg_t*)0x400d7008 ) /**< ADC Control Register 3 */
#define SOC_ADC_ADCL ( *(cc2538_reg_t*)0x400d700c ) /**< Least-significant part of ADC conversion result. */
#define SOC_ADC_ADCH ( *(cc2538_reg_t*)0x400d7010 ) /**< Most-significant part of ADC conversion result. */
#define SOC_ADC_RNDL ( *(cc2538_reg_t*)0x400d7014 ) /**< Random-number-generator data; low byte. */
#define SOC_ADC_RNDH ( *(cc2538_reg_t*)0x400d7018 ) /**< Random-number-generator data; high byte. */
#define SOC_ADC_CMPCTL ( *(cc2538_reg_t*)0x400d7024 ) /**< Analog comparator control and status register. */
#define GPIO_A_DATA ( *(cc2538_reg_t*)0x400d9000 ) /**< GPIO_A Data Register */
#define GPIO_A_DIR ( *(cc2538_reg_t*)0x400d9400 ) /**< GPIO_A data direction register */
#define GPIO_A_IS ( *(cc2538_reg_t*)0x400d9404 ) /**< GPIO_A Interrupt Sense register */

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2014 Loci Controls Inc.
* 2018 HAW Hamburg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -15,6 +16,7 @@
* @brief CC2538 SOC ADC interface
*
* @author Ian Martin <ian@locicontrols.com>
* @author Sebastian Meiling <s@mlng.net>
*/
#ifndef CC2538_SOC_ADC_H
@ -30,34 +32,17 @@ extern "C" {
* @brief SOC ADC component registers
*/
typedef struct {
/**
* @brief ADC control register
*/
union {
cc2538_reg_t ADCCON1; /**< ADC Control Register 1 */
struct {
cc2538_reg_t RESERVED2 : 2; /**< Reserved bits */
cc2538_reg_t RCTRL : 2; /**< Random number generator control */
cc2538_reg_t STSEL : 2; /**< Start select */
cc2538_reg_t ST : 1; /**< Start conversion */
cc2538_reg_t EOC : 1; /**< End of conversion */
cc2538_reg_t RESERVED1 : 24; /**< Reserved bits */
} ADCCON1bits;
} cc2538_adc_adccon1;
cc2538_reg_t ADCCON2; /**< ADC Control Register 2 */
cc2538_reg_t ADCCON3; /**< ADC Control Register 3 */
cc2538_reg_t ADCL; /**< Least-significant part of ADC conversion result. */
cc2538_reg_t ADCH; /**< Most-significant part of ADC conversion result. */
cc2538_reg_t RNDL; /**< Random-number-generator data; low byte. */
cc2538_reg_t RNDH; /**< Random-number-generator data; high byte. */
cc2538_reg_t RESERVED[2]; /**< Reserved bytes */
cc2538_reg_t CMPCTL; /**< Analog comparator control and status register. */
cc2538_reg_t ADCCON1; /**< ADC Control Register 1 */
cc2538_reg_t ADCCON2; /**< ADC Control Register 2 */
cc2538_reg_t ADCCON3; /**< ADC Control Register 3 */
cc2538_reg_t ADCL; /**< Least-significant part of ADC conversion result. */
cc2538_reg_t ADCH; /**< Most-significant part of ADC conversion result. */
cc2538_reg_t RNDL; /**< Random-number-generator data; low byte. */
cc2538_reg_t RNDH; /**< Random-number-generator data; high byte. */
cc2538_reg_t RESERVED[2]; /**< Reserved bytes */
cc2538_reg_t CMPCTL; /**< Analog comparator control and status register. */
} cc2538_soc_adc_t;
#define SOC_ADC ( (cc2538_soc_adc_t*)0x400d7000 ) /**< One and only instance of the SOC ADC component */
#ifdef __cplusplus
} /* end extern "C" */
#endif

View File

@ -24,6 +24,8 @@
#include <stdint.h>
#include <stdio.h>
#include "vendor/hw_soc_adc.h"
#include "cpu.h"
#include "vendor/hw_ssi.h"
@ -264,36 +266,13 @@ typedef enum {
typedef gpio_t adc_conf_t;
/**
* @name SOC_ADC_ADCCON3 register bit masks
* @name SOC_ADC_ADCCON3_EREF registers field values
* @{
*/
#define SOC_ADC_ADCCON3_EREF (0x000000C0) /**< Reference voltage for extra */
#define SOC_ADC_ADCCON3_EDIV (0x00000030) /**< Decimation rate for extra */
#define SOC_ADC_ADCCON3_ECH (0x0000000F) /**< Single channel select */
/** @} */
/**
* @name SOC_ADC_ADCCONx registers field values
* @{
*/
#define SOC_ADC_ADCCON_REF_INT (0 << 6) /**< Internal reference */
#define SOC_ADC_ADCCON_REF_EXT (1 << 6) /**< External reference on AIN7 pin */
#define SOC_ADC_ADCCON_REF_AVDD5 (2 << 6) /**< AVDD5 pin */
#define SOC_ADC_ADCCON_REF_DIFF (3 << 6) /**< External reference on AIN6-AIN7 differential input */
#define SOC_ADC_ADCCON_CH_GND (0xC) /**< GND */
/** @} */
/**
* @brief Mask to check end-of-conversion (EOC) bit
*/
#define SOC_ADC_ADCCON1_EOC_MASK (0x80)
/**
* @name Masks for ADC raw data
* @{
*/
#define SOC_ADC_ADCL_MASK (0x000000FC)
#define SOC_ADC_ADCH_MASK (0x000000FF)
#define SOC_ADC_ADCCON3_EREF_INT (0 << SOC_ADC_ADCCON3_EREF_S) /**< Internal reference */
#define SOC_ADC_ADCCON3_EREF_EXT (1 << SOC_ADC_ADCCON3_EREF_S) /**< External reference on AIN7 pin */
#define SOC_ADC_ADCCON3_EREF_AVDD5 (2 << SOC_ADC_ADCCON3_EREF_S) /**< AVDD5 pin */
#define SOC_ADC_ADCCON3_EREF_DIFF (3 << SOC_ADC_ADCCON3_EREF_S) /**< External reference on AIN6-AIN7 differential input */
/** @} */
/**

View File

@ -20,6 +20,9 @@
* @}
*/
#include "vendor/hw_memmap.h"
#include "vendor/hw_soc_adc.h"
#include "board.h"
#include "cpu.h"
#include "periph_conf.h"
@ -29,6 +32,8 @@
#define ENABLE_DEBUG (0)
#include "debug.h"
static cc2538_soc_adc_t *soc_adc = (cc2538_soc_adc_t *)SOC_ADC_BASE;
int adc_init(adc_t line)
{
if (line >= ADC_NUMOF) {
@ -36,11 +41,10 @@ int adc_init(adc_t line)
return -1;
}
cc2538_soc_adc_t *adca = SOC_ADC;
/* stop random number generator, and set STSEL = 1 */
adca->cc2538_adc_adccon1.ADCCON1 = 0x3c;
soc_adc->ADCCON1 = (SOC_ADC_ADCCON1_STSEL_M | SOC_ADC_ADCCON1_RCTRL_M);
/* disable any DMA, continous ADC settings */
adca->ADCCON2 = 0x0;
soc_adc->ADCCON2 = 0x0;
/* configure ADC GPIO as analog input */
gpio_init(adc_config[line], GPIO_IN_ANALOG);
@ -83,25 +87,23 @@ int adc_sample(adc_t line, adc_res_t res)
*/
rshift--;
cc2538_soc_adc_t *adca = SOC_ADC;
/* configure adc line with parameters and trigger a single conversion*/
uint32_t reg = (adca->ADCCON3) & ~(SOC_ADC_ADCCON3_EREF |
SOC_ADC_ADCCON3_EDIV |
SOC_ADC_ADCCON3_ECH);
adca->ADCCON3 = reg | res | SOC_ADC_ADCCON_REF |
(adc_config[line] & GPIO_PIN_MASK);
uint32_t reg = (soc_adc->ADCCON3) & ~(SOC_ADC_ADCCON3_EREF_M |
SOC_ADC_ADCCON3_EDIV_M |
SOC_ADC_ADCCON3_ECH_M);
soc_adc->ADCCON3 = reg | res | SOC_ADC_ADCCON3_EREF |
(adc_config[line] & GPIO_PIN_MASK);
DEBUG("ADCCON1: %"PRIu32" ADCCON2: %"PRIu32" ADCCON3: %"PRIu32"\n",
adca->cc2538_adc_adccon1.ADCCON1, adca->ADCCON2, adca->ADCCON3);
soc_adc->ADCCON1, soc_adc->ADCCON2, soc_adc->ADCCON3);
/* Poll/wait until end of conversion */
while ((adca->cc2538_adc_adccon1.ADCCON1 &
SOC_ADC_ADCCON1_EOC_MASK) == 0) {}
while ((soc_adc->ADCCON1 & SOC_ADC_ADCCON1_EOC_M) == 0) {}
/* Read result after conversion completed,
* reading SOC_ADC_ADCH last will clear SOC_ADC_ADCCON1.EOC */
int16_t sample = adca->ADCL & SOC_ADC_ADCL_MASK;
sample |= (adca->ADCH & SOC_ADC_ADCH_MASK) << 8;
int16_t sample = soc_adc->ADCL & SOC_ADC_ADCL_ADC_M;
sample |= (soc_adc->ADCH & SOC_ADC_ADCH_ADC_M) << 8;
/* sample right shifted depending on resolution */
sample = sample >> rshift;
DEBUG("adc_sample: raw value %"PRIi16"\n", sample);

View File

@ -21,22 +21,31 @@
* @}
*/
#include "vendor/hw_memmap.h"
#include "vendor/hw_soc_adc.h"
#include "cpu.h"
#include "periph/hwrng.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
static cc2538_soc_adc_t *soc_adc = (cc2538_soc_adc_t *)SOC_ADC_BASE;
void hwrng_init(void)
{
uint16_t seed = 0;
int i;
/* Make sure the RNG is on */
SOC_ADC->cc2538_adc_adccon1.ADCCON1bits.RCTRL = 0;
uint32_t reg32 = soc_adc->ADCCON1 & ~(SOC_ADC_ADCCON1_RCTRL_M);
soc_adc->ADCCON1 = reg32;
/* Enable clock for the RF Core */
SYS_CTRL_RCGCRFC = 1;
/* Wait for the clock ungating to take effect */
while (SYS_CTRL_RCGCRFC != 1);
while (SYS_CTRL_RCGCRFC != 1) {}
/* Infinite RX - FRMCTRL0[3:2] = 10. This will mess with radio operation */
RFCORE_XREG_FRMCTRL0 = 0x00000008;
@ -63,8 +72,8 @@ void hwrng_init(void)
}
/* Seed the high byte first: */
SOC_ADC_RNDL = (seed >> 8) & 0xff;
SOC_ADC_RNDL = seed & 0xff;
soc_adc->RNDH = (seed >> 8) & 0xff;
soc_adc->RNDL = seed & 0xff;
/* Turn RF off: */
RFCORE_SFR_RFST = ISRFOFF;
@ -72,16 +81,16 @@ void hwrng_init(void)
void hwrng_read(void *buf, unsigned int num)
{
unsigned count;
uint8_t *b = (uint8_t *)buf;
for (count = 0; count < num; ) {
for (unsigned count = 0; count < num; count++) {
/* Clock the RNG LSFR once: */
SOC_ADC->cc2538_adc_adccon1.ADCCON1bits.RCTRL = 1;
soc_adc->ADCCON1 = soc_adc->ADCCON1 | (1UL << SOC_ADC_ADCCON1_RCTRL_S);
/* Read up to 2 bytes of hwrng data: */
b[count++] = SOC_ADC_RNDL;
if (count >= num) break;
b[count++] = SOC_ADC_RNDH;
b[count] = soc_adc->RNDL;
count++;
if (count < num) {
b[count] = soc_adc->RNDH;
}
}
}