ADC API change
[gnuk/neug.git] / src / adc_stm32f103.c
1 /*
2  * adc_stm32f103.c - ADC driver for STM32F103
3  *                   In this ADC driver, there are NeuG specific parts.
4  *                   You need to modify to use this as generic ADC driver.
5  *
6  * Copyright (C) 2011, 2012, 2013, 2015, 2016
7  *               Free Software Initiative of Japan
8  * Author: NIIBE Yutaka <gniibe@fsij.org>
9  *
10  * This file is a part of NeuG, a True Random Number Generator
11  * implementation based on quantization error of ADC (for STM32F103).
12  *
13  * NeuG is free software: you can redistribute it and/or modify it
14  * under the terms of the GNU General Public License as published by
15  * the Free Software Foundation, either version 3 of the License, or
16  * (at your option) any later version.
17  *
18  * NeuG is distributed in the hope that it will be useful, but WITHOUT
19  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
21  * License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
25  *
26  */
27
28 #include <stdint.h>
29 #include <stdlib.h>
30 #include <chopstx.h>
31
32 #include "neug.h"
33 #include "stm32f103.h"
34 #include "adc.h"
35
36 #define NEUG_CRC32_COUNTS 4
37
38 #define STM32_ADC_ADC1_DMA_PRIORITY         2
39
40 #define ADC_SMPR1_SMP_VREF(n)   ((n) << 21)
41 #define ADC_SMPR1_SMP_SENSOR(n) ((n) << 18)
42
43 #define ADC_SMPR1_SMP_AN10(n)   ((n) << 0)
44 #define ADC_SMPR1_SMP_AN11(n)   ((n) << 3)
45
46 #define ADC_SMPR2_SMP_AN0(n)    ((n) << 0)
47 #define ADC_SMPR2_SMP_AN1(n)    ((n) << 3)
48 #define ADC_SMPR2_SMP_AN2(n)    ((n) << 6)
49 #define ADC_SMPR2_SMP_AN9(n)    ((n) << 27)
50
51 #define ADC_SQR1_NUM_CH(n)      (((n) - 1) << 20)
52
53 #define ADC_SQR3_SQ1_N(n)       ((n) << 0)
54 #define ADC_SQR3_SQ2_N(n)       ((n) << 5)
55 #define ADC_SQR3_SQ3_N(n)       ((n) << 10)
56 #define ADC_SQR3_SQ4_N(n)       ((n) << 15)
57
58 #define ADC_SAMPLE_1P5          0
59
60 #define ADC_CHANNEL_IN0         0
61 #define ADC_CHANNEL_IN1         1
62 #define ADC_CHANNEL_IN2         2
63 #define ADC_CHANNEL_IN9         9
64 #define ADC_CHANNEL_IN10        10
65 #define ADC_CHANNEL_IN11        11
66 #define ADC_CHANNEL_SENSOR      16
67 #define ADC_CHANNEL_VREFINT     17
68
69 #define DELIBARATELY_DO_IT_WRONG_VREF_SAMPLE_TIME
70 #define DELIBARATELY_DO_IT_WRONG_START_STOP
71
72 #ifdef DELIBARATELY_DO_IT_WRONG_VREF_SAMPLE_TIME
73 #define ADC_SAMPLE_VREF ADC_SAMPLE_1P5
74 #define ADC_SAMPLE_SENSOR ADC_SAMPLE_1P5
75 #else
76 #define ADC_SAMPLE_VREF ADC_SAMPLE_239P5
77 #define ADC_SAMPLE_SENSOR ADC_SAMPLE_239P5
78 #endif
79
80 #define NEUG_DMA_CHANNEL STM32_DMA1_STREAM1
81 #define NEUG_DMA_MODE                                                   \
82   (  STM32_DMA_CR_PL (STM32_ADC_ADC1_DMA_PRIORITY)                      \
83      | STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD                \
84      | STM32_DMA_CR_MINC       | STM32_DMA_CR_TCIE                      \
85      | STM32_DMA_CR_TEIE  )
86
87 #define NEUG_ADC_SETTING1_SMPR1 ADC_SMPR1_SMP_VREF(ADC_SAMPLE_VREF)     \
88                               | ADC_SMPR1_SMP_SENSOR(ADC_SAMPLE_SENSOR)
89 #define NEUG_ADC_SETTING1_SMPR2 0
90 #define NEUG_ADC_SETTING1_SQR3  ADC_SQR3_SQ1_N(ADC_CHANNEL_VREFINT)     \
91                               | ADC_SQR3_SQ2_N(ADC_CHANNEL_SENSOR)      \
92                               | ADC_SQR3_SQ3_N(ADC_CHANNEL_SENSOR)      \
93                               | ADC_SQR3_SQ4_N(ADC_CHANNEL_VREFINT)
94 #define NEUG_ADC_SETTING1_NUM_CHANNELS 4
95
96 /*
97  * ADC finish interrupt
98  */
99 #define INTR_REQ_DMA1_Channel1 11
100
101 static chopstx_intr_t adc_intr;
102
103 /*
104  * Do calibration for both of ADCs.
105  */
106 void
107 adc_init (void)
108 {
109   RCC->APB2ENR |= (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN);
110   RCC->APB2RSTR = (RCC_APB2RSTR_ADC1RST | RCC_APB2RSTR_ADC2RST);
111   RCC->APB2RSTR = 0;
112
113   ADC1->CR1 = 0;
114   ADC1->CR2 = ADC_CR2_ADON;
115   ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL;
116   while ((ADC1->CR2 & ADC_CR2_RSTCAL) != 0)
117     ;
118   ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_CAL;
119   while ((ADC1->CR2 & ADC_CR2_CAL) != 0)
120     ;
121   ADC1->CR2 = 0;
122
123   ADC2->CR1 = 0;
124   ADC2->CR2 = ADC_CR2_ADON;
125   ADC2->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL;
126   while ((ADC2->CR2 & ADC_CR2_RSTCAL) != 0)
127     ;
128   ADC2->CR2 = ADC_CR2_ADON | ADC_CR2_CAL;
129   while ((ADC2->CR2 & ADC_CR2_CAL) != 0)
130     ;
131   ADC2->CR2 = 0;
132   RCC->APB2ENR &= ~(RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN);
133
134   chopstx_claim_irq (&adc_intr, INTR_REQ_DMA1_Channel1);
135 }
136
137 #include "sys.h"
138 #if defined(HAVE_SYS_H)
139 # define SYS_BOARD_ID sys_board_id
140 #else
141 # include "board.h"
142 # define SYS_BOARD_ID BOARD_ID
143 #endif
144
145 static void
146 get_adc_config (uint32_t config[4])
147 {
148   config[2] = ADC_SQR1_NUM_CH(2);
149   switch (SYS_BOARD_ID)
150     {
151     case BOARD_ID_FST_01:
152       config[0] = 0;
153       config[1] = ADC_SMPR2_SMP_AN0(ADC_SAMPLE_1P5)
154                 | ADC_SMPR2_SMP_AN9(ADC_SAMPLE_1P5);
155       config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN0)
156                 | ADC_SQR3_SQ2_N(ADC_CHANNEL_IN9);
157       break;
158
159     case BOARD_ID_OLIMEX_STM32_H103:
160     case BOARD_ID_STBEE:
161       config[0] = ADC_SMPR1_SMP_AN10(ADC_SAMPLE_1P5)
162                 | ADC_SMPR1_SMP_AN11(ADC_SAMPLE_1P5);
163       config[1] = 0;
164       config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN10)
165                 | ADC_SQR3_SQ2_N(ADC_CHANNEL_IN11);
166       break;
167
168     case BOARD_ID_STBEE_MINI:
169       config[0] = 0;
170       config[1] = ADC_SMPR2_SMP_AN1(ADC_SAMPLE_1P5)
171                 | ADC_SMPR2_SMP_AN2(ADC_SAMPLE_1P5);
172       config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN1)
173                 | ADC_SQR3_SQ2_N(ADC_CHANNEL_IN2);
174       break;
175
176     case BOARD_ID_CQ_STARM:
177     case BOARD_ID_FST_01_00:
178     case BOARD_ID_MAPLE_MINI:
179     case BOARD_ID_STM32_PRIMER2:
180     case BOARD_ID_STM8S_DISCOVERY:
181     case BOARD_ID_ST_DONGLE:
182     case BOARD_ID_ST_NUCLEO_F103:
183     case BOARD_ID_NITROKEY_START:
184     default:
185       config[0] = 0;
186       config[1] = ADC_SMPR2_SMP_AN0(ADC_SAMPLE_1P5)
187                 | ADC_SMPR2_SMP_AN1(ADC_SAMPLE_1P5);
188       config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN0)
189                 | ADC_SQR3_SQ2_N(ADC_CHANNEL_IN1);
190       break;
191     }
192 }
193
194
195 void
196 adc_start (void)
197 {
198   uint32_t config[4];
199
200   get_adc_config (config);
201
202   /* Use DMA channel 1.  */
203   RCC->AHBENR |= RCC_AHBENR_DMA1EN;
204   DMA1_Channel1->CCR = STM32_DMA_CCR_RESET_VALUE;
205   DMA1->IFCR = 0xffffffff;
206
207   RCC->APB2ENR |= (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN);
208
209   ADC1->CR1 = (ADC_CR1_DUALMOD_2 | ADC_CR1_DUALMOD_1 | ADC_CR1_DUALMOD_0
210                | ADC_CR1_SCAN);
211   ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
212                | ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
213   ADC1->SMPR1 = NEUG_ADC_SETTING1_SMPR1;
214   ADC1->SMPR2 = NEUG_ADC_SETTING1_SMPR2;
215   ADC1->SQR1 = ADC_SQR1_NUM_CH(NEUG_ADC_SETTING1_NUM_CHANNELS);
216   ADC1->SQR2 = 0;
217   ADC1->SQR3 = NEUG_ADC_SETTING1_SQR3;
218
219   ADC2->CR1 = (ADC_CR1_DUALMOD_2 | ADC_CR1_DUALMOD_1 | ADC_CR1_DUALMOD_0
220                | ADC_CR1_SCAN);
221   ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
222   ADC2->SMPR1 = config[0];
223   ADC2->SMPR2 = config[1];
224   ADC2->SQR1 = config[2];
225   ADC2->SQR2 = 0;
226   ADC2->SQR3 = config[3];
227
228 #ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
229   /*
230    * We could just let ADC run continuously always and only enable DMA
231    * to receive stable data from ADC.  But our purpose is not to get
232    * correct data but noise.  In fact, we can get more noise when we
233    * start/stop ADC each time.
234    */
235   ADC2->CR2 = 0;
236   ADC1->CR2 = 0;
237 #else
238   /* Start conversion.  */
239   ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
240   ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
241                | ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
242 #endif
243 }
244
245 uint32_t adc_buf[64];
246
247 void
248 adc_start_conversion (int offset, int count)
249 {
250   DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR;        /* SetPeripheral */
251   DMA1_Channel1->CMAR = (uint32_t)&adc_buf[offset]; /* SetMemory0    */
252   DMA1_Channel1->CNDTR = count;                     /* Counter       */
253   DMA1_Channel1->CCR = NEUG_DMA_MODE | DMA_CCR1_EN; /* Mode   */
254
255 #ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
256   /* Power on */
257   ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
258   ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
259                | ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
260   /*
261    * Start conversion.  tSTAB is 1uS, but we don't follow the spec, to
262    * get more noise.
263    */
264   ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
265   ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
266                | ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
267 #endif
268 }
269
270
271 static void adc_stop_conversion (void)
272 {
273   DMA1_Channel1->CCR &= ~DMA_CCR1_EN;
274
275 #ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
276   ADC2->CR2 = 0;
277   ADC1->CR2 = 0;
278 #endif
279 }
280
281 void
282 adc_stop (void)
283 {
284   ADC1->CR1 = 0;
285   ADC1->CR2 = 0;
286
287   ADC2->CR1 = 0;
288   ADC2->CR2 = 0;
289
290   RCC->AHBENR &= ~RCC_AHBENR_DMA1EN;
291   RCC->APB2ENR &= ~(RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN);
292 }
293
294
295 static uint32_t adc_err;
296
297 /*
298  * Return 0 on success.
299  * Return 1 on error.
300  */
301 int
302 adc_wait_completion (void)
303 {
304   uint32_t flags;
305
306   while (1)
307     {
308       chopstx_poll (NULL, 1, &adc_intr);
309       flags = DMA1->ISR & STM32_DMA_ISR_MASK; /* Channel 1 interrupt cause.  */
310       /*
311        * Clear interrupt cause of channel 1.
312        *
313        * Note that CGIFx=0, as CGIFx=1 clears all of GIF, HTIF, TCIF
314        * and TEIF.
315        */
316       DMA1->IFCR = (flags & ~1);
317
318       if ((flags & STM32_DMA_ISR_TEIF) != 0)  /* DMA errors  */
319         {
320           /* Should never happened.  If any, it's coding error. */
321           /* Access an unmapped address space or alignment violation.  */
322           adc_err++;
323           adc_stop_conversion ();
324           return 1;
325         }
326       else if ((flags & STM32_DMA_ISR_TCIF) != 0) /* Transfer complete */
327         {
328           adc_stop_conversion ();
329           return 0;
330         }
331     }
332 }