diff options
author | NIIBE Yutaka <gniibe@fsij.org> | 2016-05-26 09:50:07 +0900 |
---|---|---|
committer | NIIBE Yutaka <gniibe@fsij.org> | 2016-05-26 09:50:07 +0900 |
commit | cf81e7a6dcd5be6dd9cbafbc426d8384f732d2c2 (patch) | |
tree | 522df78ec919597c48881db79316cb930ffe45c2 /example-fs-bb48 | |
parent | 2578fc0f303b97ab0fd1b1935cd00f6f45a353e9 (diff) |
example-fs-bb48: ADC added
Diffstat (limited to 'example-fs-bb48')
-rw-r--r-- | example-fs-bb48/adc.h | 2 | ||||
-rw-r--r-- | example-fs-bb48/adc_kl27z.c | 127 | ||||
-rw-r--r-- | example-fs-bb48/command.c | 60 | ||||
-rw-r--r-- | example-fs-bb48/config.h | 2 |
4 files changed, 125 insertions, 66 deletions
diff --git a/example-fs-bb48/adc.h b/example-fs-bb48/adc.h index 85a49b0..1a009f7 100644 --- a/example-fs-bb48/adc.h +++ b/example-fs-bb48/adc.h @@ -5,4 +5,4 @@ void adc_stop (void); extern uint32_t adc_buf[64]; void adc_start_conversion (int offset, int count); -int adc_wait_completion (chopstx_intr_t *intr); +int adc_wait_completion (void); diff --git a/example-fs-bb48/adc_kl27z.c b/example-fs-bb48/adc_kl27z.c index 7ad9517..a900efd 100644 --- a/example-fs-bb48/adc_kl27z.c +++ b/example-fs-bb48/adc_kl27z.c @@ -33,6 +33,27 @@ #include <chopstx.h> #include "kl_sim.h" +struct DMAMUX { + volatile uint32_t CHCFG0; + volatile uint32_t CHCFG1; + volatile uint32_t CHCFG2; + volatile uint32_t CHCFG3; +}; +static struct DMAMUX *const DMAMUX = (struct DMAMUX *const)0x40021000; + +#define INTR_REQ_DMA0 0 + +struct DMA { + volatile uint32_t SAR; + volatile uint32_t DAR; + volatile uint32_t DSR_BCR; + volatile uint32_t DCR; +}; +static struct DMA *const DMA0 = (struct DMA *const)0x40008100; +static struct DMA *const DMA1 = (struct DMA *const)0x40008110; + + +/* We don't use ADC interrupt. Just for reference. */ #define INTR_REQ_ADC 15 struct ADC { @@ -70,7 +91,7 @@ struct ADC { volatile uint32_t CLM1; volatile uint32_t CLM0; }; -static struct ADC *const ADC = (struct ADC *const)0x4003B000; +static struct ADC *const ADC0 = (struct ADC *const)0x4003B000; /* SC1 */ #define ADC_SC1_DIFF (1 << 5) @@ -92,11 +113,7 @@ static struct ADC *const ADC = (struct ADC *const)0x4003B000; /**/ #define ADC_CLOCK_SOURCE ADC_CLOCK_SOURCE_ASYNCH #define ADC_MODE ADC_MODE_16BIT -#if 0 #define ADC_ADLSMP ADC_ADLSMP_SHORT -#else -#define ADC_ADLSMP ADC_ADLSMP_LONG -#endif #define ADC_ADIV ADC_ADIV_8 #define ADC_ADLPC ADC_ADLPC_LOWPOWER @@ -129,41 +146,77 @@ static struct ADC *const ADC = (struct ADC *const)0x4003B000; #define ADC_SC3_CALF (1 << 6) #define ADC_SC3_CAL (1 << 7) +#define ADC_DMA_SLOT_NUM 40 + +/* + * Buffer to save ADC data. + */ +uint32_t adc_buf[64]; + +static const uint32_t adc0_sc1_setting = ADC_SC1_TEMPSENSOR; + +static chopstx_intr_t adc_intr; + + /* * Initialize ADC module, do calibration. - * This is called by MAIN, only once, before creating any other threads. + * + * This is called by MAIN, only once, hopefully before creating any + * other threads (to be accurate). + * + * We configure ADC0 to kick DMA0, configure DMA0 to kick DMA1. + * DMA0 records output of ADC0 to the ADC_BUF. + * DMA1 kicks ADC0 again to get another value. + * + * ADC0 --[finish conversion]--> DMA0 --[Link channel 1]--> DMA1 */ int adc_init (void) { uint32_t v; - /* Enable ADC0 clock. */ - SIM->SCGC6 |= (1 << 27); + /* Enable ADC0 and DMAMUX clock. */ + SIM->SCGC6 |= (1 << 27) | (1 << 1); + /* Enable DMA clock. */ + SIM->SCGC7 |= (1 << 8); - ADC->CFG1 = ADC_CLOCK_SOURCE | ADC_MODE | ADC_ADLSMP | ADC_ADIV | ADC_ADLPC; - ADC->CFG2 = ADC_ADLSTS | ADC_ADHSC | ADC_ADACKEN | ADC_MUXSEL; - ADC->SC2 = ADC_SC2_REFSEL_DEFAULT; - ADC->SC3 = ADC_SC3_CAL | ADC_SC3_CALF | ADC_SC3_AVGE | ADC_SC3_AVGS11; + /* ADC0 setting for calibration. */ + ADC0->CFG1 = ADC_CLOCK_SOURCE | ADC_MODE | ADC_ADLSMP | ADC_ADIV | ADC_ADLPC; + ADC0->CFG2 = ADC_ADLSTS | ADC_ADHSC | ADC_ADACKEN | ADC_MUXSEL; + ADC0->SC2 = ADC_SC2_REFSEL_DEFAULT; + ADC0->SC3 = ADC_SC3_CAL | ADC_SC3_CALF | ADC_SC3_AVGE | ADC_SC3_AVGS11; /* Wait ADC completion */ - while ((ADC->SC1[0] & ADC_SC1_COCO) == 0) - if ((ADC->SC3 & ADC_SC3_CALF) != 0) + while ((ADC0->SC1[0] & ADC_SC1_COCO) == 0) + if ((ADC0->SC3 & ADC_SC3_CALF) != 0) /* Calibration failure */ return -1; - if ((ADC->SC3 & ADC_SC3_CALF) != 0) + if ((ADC0->SC3 & ADC_SC3_CALF) != 0) /* Calibration failure */ return -1; /* Configure PG by the calibration values. */ - v = ADC->CLP0 + ADC->CLP1 + ADC->CLP2 + ADC->CLP3 + ADC->CLP4 + ADC->CLPS; - ADC->PG = 0x8000 | (v >> 1); + v = ADC0->CLP0 + ADC0->CLP1 + ADC0->CLP2 + ADC0->CLP3 + ADC0->CLP4 + ADC0->CLPS; + ADC0->PG = 0x8000 | (v >> 1); /* Configure MG by the calibration values. */ - v = ADC->CLM0 + ADC->CLM1 + ADC->CLM2 + ADC->CLM3 + ADC->CLM4 + ADC->CLMS; - ADC->MG = 0x8000 | (v >> 1); + v = ADC0->CLM0 + ADC0->CLM1 + ADC0->CLM2 + ADC0->CLM3 + ADC0->CLM4 + ADC0->CLMS; + ADC0->MG = 0x8000 | (v >> 1); + + ADC0->SC1[0] = ADC_SC1_ADCSTOP; + /* DMAMUX setting. */ + DMAMUX->CHCFG0 = (1 << 7) | ADC_DMA_SLOT_NUM; + + /* DMA0 initial setting. */ + DMA0->SAR = (uint32_t)&ADC0->R[0]; + + /* DMA1 initial setting. */ + DMA1->SAR = (uint32_t)&adc0_sc1_setting; + DMA1->DAR = (uint32_t)&ADC0->SC1[0]; + + chopstx_claim_irq (&adc_intr, INTR_REQ_DMA0); return 0; } @@ -173,32 +226,35 @@ adc_init (void) void adc_start (void) { - ADC->CFG1 = ADC_CLOCK_SOURCE | ADC_MODE | ADC_ADLSMP | ADC_ADIV | ADC_ADLPC; - ADC->CFG2 = ADC_ADLSTS | ADC_ADHSC | ADC_ADACKEN | ADC_MUXSEL; - ADC->SC2 = ADC_SC2_REFSEL_DEFAULT; - ADC->SC3 = 0; + ADC0->CFG1 = ADC_CLOCK_SOURCE | ADC_MODE | ADC_ADLSMP | ADC_ADIV | ADC_ADLPC; + ADC0->CFG2 = ADC_ADLSTS | ADC_ADHSC | ADC_ADACKEN | ADC_MUXSEL; + ADC0->SC2 = ADC_SC2_REFSEL_DEFAULT | ADC_SC2_DMAEN; + ADC0->SC3 = 0; } /* - * Buffer to save ADC data. - */ -uint32_t adc_buf[64]; - -/* * Kick getting data for COUNT times. * Data will be saved in ADC_BUF starting at OFFSET. */ void adc_start_conversion (int offset, int count) { - ADC->SC1[0] = /*ADC_SC1_AIEN*/0 | ADC_SC1_TEMPSENSOR; + /* DMA0 setting. */ + DMA0->DAR = (uint32_t)&adc_buf[offset]; + DMA0->DSR_BCR = 4 * count; + DMA0->DCR = (1 << 31) | (1 << 30) | (1 << 29) | (0 << 20) | (1 << 19) + | (0 << 17) | (1 << 7) | (2 << 4) | (1 << 2); + + /* Kick DMA1. */ + DMA1->DSR_BCR = 4 * count; + DMA1->DCR = (1 << 30) | (1 << 29) | (0 << 19) | (0 << 17) | (1 << 16) | (1 << 7); } static void adc_stop_conversion (void) { - ADC->SC1[0] = ADC_SC1_ADCSTOP; + ADC0->SC1[0] = ADC_SC1_ADCSTOP; } /* @@ -215,13 +271,14 @@ adc_stop (void) * Return 1 on error. */ int -adc_wait_completion (chopstx_intr_t *intr) +adc_wait_completion (void) { - /* Wait ADC completion */ - while ((ADC->SC1[0] & ADC_SC1_COCO) == 0) - ; + /* Wait DMA completion */ + chopstx_poll (NULL, 1, &adc_intr); + + DMA0->DSR_BCR = (1 << 24); + DMA1->DSR_BCR = (1 << 24); - adc_buf[0] = ADC->R[0]; adc_stop_conversion (); return 0; } diff --git a/example-fs-bb48/command.c b/example-fs-bb48/command.c index 480cb2e..b13ca71 100644 --- a/example-fs-bb48/command.c +++ b/example-fs-bb48/command.c @@ -3,7 +3,7 @@ #include <chopstx.h> #include "tty.h" #include "config.h" -#ifdef TEMPERATURE_SUPPORT +#ifdef ADC_SUPPORT #include "adc.h" static int adc_initialized = 0; #endif @@ -30,8 +30,8 @@ static const char *help_string = #ifdef CRC32_SUPPORT "crc32 string\r\n" #endif -#ifdef TEMPERATURE_SUPPORT - "temp\r\n" +#ifdef ADC_SUPPORT + "adc\r\n" #endif "help\r\n"; @@ -46,6 +46,7 @@ static char hexchar (uint8_t x) return '?'; } +#ifdef ENABLE_DECIMAL_OUTPUT static char * compose_decimal (char *s, int value) { @@ -81,6 +82,7 @@ compose_decimal (char *s, int value) return s; } +#endif static char * compose_hex (char *s, uint32_t v) @@ -214,18 +216,12 @@ cmd_crc32 (struct tty *tty, const char *line) } #endif -#ifdef TEMPERATURE_SUPPORT -#define ADCV_TEMP25 14800 /* TYP: 716mV=14219 */ -#define ADCV_100M 3217 - -/* m = 1.62 mV/C_degree */ - +#ifdef ADC_SUPPORT static void -cmd_temperature (struct tty *tty, const char *line) +cmd_adc (struct tty *tty, const char *line) { - uint32_t v; - int t; - char string[13]; + int i; + char output[73]; char *s; (void)line; @@ -244,21 +240,27 @@ cmd_temperature (struct tty *tty, const char *line) } } - adc_start_conversion (0, 1); - adc_wait_completion (NULL); - v = adc_buf[0]; - - t = 25 - (((int)v - ADCV_TEMP25) * 100 / ADCV_100M); - - s = compose_hex (string, v); - *s++ = '\r'; - *s++ = '\n'; - tty_send (tty, (uint8_t *)string, s - string); + adc_start_conversion (0, 64); + adc_wait_completion (); - s = compose_decimal (string, t); - *s++ = '\r'; - *s++ = '\n'; - tty_send (tty, (uint8_t *)string, s - string); + i = 0; + s = output; + while (1) + { + s = compose_hex (s, adc_buf[i]); + i++; + if ((i % 8)) + *s++ = ' '; + else + { + *s++ = '\r'; + *s++ = '\n'; + tty_send (tty, (uint8_t *)output, s - output); + s = output; + if (i >= 64) + break; + } + } } #endif @@ -276,8 +278,8 @@ struct command_table command_table[] = { #ifdef CRC32_SUPPORT { "crc32", cmd_crc32 }, #endif -#ifdef TEMPERATURE_SUPPORT - { "temp", cmd_temperature }, +#ifdef ADC_SUPPORT + { "adc", cmd_adc }, #endif { "help", cmd_help }, }; diff --git a/example-fs-bb48/config.h b/example-fs-bb48/config.h index b04454f..ceb916a 100644 --- a/example-fs-bb48/config.h +++ b/example-fs-bb48/config.h @@ -1,2 +1,2 @@ #define CRC32_SUPPORT -#define TEMPERATURE_SUPPORT +#define ADC_SUPPORT |