Skip to content

Commit d05ef69

Browse files
committed
[M2351] Support analog-in
1 parent 1da430f commit d05ef69

File tree

2 files changed

+116
-1
lines changed

2 files changed

+116
-1
lines changed
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2017-2018 Nuvoton
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "analogin_api.h"
18+
19+
#if DEVICE_ANALOGIN
20+
21+
#include "cmsis.h"
22+
#include "pinmap.h"
23+
#include "PeripheralPins.h"
24+
#include "nu_modutil.h"
25+
26+
static uint32_t eadc_modinit_mask = 0;
27+
28+
static const struct nu_modinit_s adc_modinit_tab[] = {
29+
{ADC_0_0, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, EADC0_IRQn, NULL},
30+
{ADC_0_1, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, EADC0_IRQn, NULL},
31+
{ADC_0_2, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, EADC0_IRQn, NULL},
32+
{ADC_0_3, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, EADC0_IRQn, NULL},
33+
{ADC_0_4, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, EADC0_IRQn, NULL},
34+
{ADC_0_5, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, EADC0_IRQn, NULL},
35+
{ADC_0_6, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, EADC0_IRQn, NULL},
36+
{ADC_0_7, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, EADC0_IRQn, NULL},
37+
{ADC_0_8, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, EADC0_IRQn, NULL},
38+
{ADC_0_9, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, EADC0_IRQn, NULL},
39+
{ADC_0_10, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, EADC0_IRQn, NULL},
40+
{ADC_0_11, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, EADC0_IRQn, NULL},
41+
{ADC_0_12, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, EADC0_IRQn, NULL},
42+
{ADC_0_13, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, EADC0_IRQn, NULL},
43+
{ADC_0_14, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, EADC0_IRQn, NULL},
44+
{ADC_0_15, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, EADC0_IRQn, NULL},
45+
};
46+
47+
void analogin_init(analogin_t *obj, PinName pin)
48+
{
49+
obj->adc = (ADCName) pinmap_peripheral(pin, PinMap_ADC);
50+
MBED_ASSERT(obj->adc != (ADCName) NC);
51+
52+
const struct nu_modinit_s *modinit = get_modinit(obj->adc, adc_modinit_tab);
53+
MBED_ASSERT(modinit != NULL);
54+
MBED_ASSERT(modinit->modname == (int) obj->adc);
55+
56+
EADC_T *eadc_base = (EADC_T *) NU_MODBASE(obj->adc);
57+
58+
// NOTE: All channels (identified by ADCName) share a ADC module. This reset will also affect other channels of the same ADC module.
59+
if (! eadc_modinit_mask) {
60+
/* Reset module
61+
*
62+
* NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure.
63+
*/
64+
SYS_ResetModule_S(modinit->rsetidx);
65+
66+
/* Select IP clock source
67+
*
68+
* NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure.
69+
*/
70+
CLK_SetModuleClock_S(modinit->clkidx, modinit->clksrc, modinit->clkdiv);
71+
72+
/* Enable IP clock
73+
*
74+
* NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure.
75+
*/
76+
CLK_EnableModuleClock_S(modinit->clkidx);
77+
78+
// Set the ADC internal sampling time, input mode as single-end and enable the A/D converter
79+
EADC_Open(eadc_base, EADC_CTL_DIFFEN_SINGLE_END);
80+
}
81+
82+
uint32_t chn = NU_MODSUBINDEX(obj->adc);
83+
84+
// Wire pinout
85+
pinmap_pinout(pin, PinMap_ADC);
86+
87+
// Configure the sample module Nmod for analog input channel Nch and software trigger source
88+
EADC_ConfigSampleModule(eadc_base, chn, EADC_SOFTWARE_TRIGGER, chn);
89+
90+
eadc_modinit_mask |= 1 << chn;
91+
}
92+
93+
uint16_t analogin_read_u16(analogin_t *obj)
94+
{
95+
EADC_T *eadc_base = (EADC_T *) NU_MODBASE(obj->adc);
96+
uint32_t chn = NU_MODSUBINDEX(obj->adc);
97+
98+
EADC_START_CONV(eadc_base, 1 << chn);
99+
while (EADC_GET_DATA_VALID_FLAG(eadc_base, 1 << chn) != ((uint32_t) (1 << chn)));
100+
uint16_t conv_res_12 = EADC_GET_CONV_DATA(eadc_base, chn);
101+
// Just 12 bits are effective. Convert to 16 bits.
102+
// conv_res_12: 0000 b11b10b9b8 b7b6b5b4 b3b2b1b0
103+
// conv_res_16: b11b10b9b8 b7b6b5b4 b3b2b1b0 b11b10b9b8
104+
uint16_t conv_res_16 = (conv_res_12 << 4) | (conv_res_12 >> 8);
105+
106+
return conv_res_16;
107+
}
108+
109+
float analogin_read(analogin_t *obj)
110+
{
111+
uint16_t value = analogin_read_u16(obj);
112+
return (float) value * (1.0f / (float) 0xFFFF);
113+
}
114+
115+
#endif

targets/targets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4228,7 +4228,7 @@
42284228
"is_disk_virtual": true,
42294229
"supported_toolchains": ["GCC_ARM", "IAR", "ARMC6"],
42304230
"inherits": ["Target"],
4231-
"device_has": ["I2C", "I2CSLAVE", "I2C_ASYNCH", "LOWPOWERTIMER", "RTC", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "TRNG", "FLASH"],
4231+
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "LOWPOWERTIMER", "RTC", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "TRNG", "FLASH"],
42324232
"detect_code": ["1305"],
42334233
"release_versions": ["5"],
42344234
"device_name": "M2351KIAAEES",

0 commit comments

Comments
 (0)