drv_adc.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2011-02-21 onelife Initial creation for EFM32
  9. * 2011-07-14 onelife Add multiple channels support for scan mode
  10. */
  11. /***************************************************************************//**
  12. * @addtogroup efm32
  13. * @{
  14. ******************************************************************************/
  15. /* Includes ------------------------------------------------------------------*/
  16. #include "board.h"
  17. #include "drv_adc.h"
  18. #if defined(RT_USING_ADC0)
  19. /* Private typedef -----------------------------------------------------------*/
  20. /* Private define ------------------------------------------------------------*/
  21. /* Private macro -------------------------------------------------------------*/
  22. #ifdef RT_ADC_DEBUG
  23. #define adc_debug(format,args...) rt_kprintf(format, ##args)
  24. #else
  25. #define adc_debug(format,args...)
  26. #endif
  27. /* Private variables ---------------------------------------------------------*/
  28. #ifdef RT_USING_ADC0
  29. static struct rt_device adc0_device;
  30. #endif
  31. static rt_uint32_t adcErrataShift = 0;
  32. /* Private function prototypes -----------------------------------------------*/
  33. /* Private functions ---------------------------------------------------------*/
  34. /***************************************************************************//**
  35. * @brief
  36. * Calibrate offset and gain for the specified reference.
  37. * Supports currently only single ended gain calibration.
  38. * Could easily be expanded to support differential gain calibration.
  39. *
  40. * @details
  41. * The offset calibration routine measures 0 V with the ADC, and adjust
  42. * the calibration register until the converted value equals 0.
  43. * The gain calibration routine needs an external reference voltage equal
  44. * to the top value for the selected reference. For example if the 2.5 V
  45. * reference is to be calibrated, the external supply must also equal 2.5V.
  46. *
  47. * @param[in] adc
  48. * Pointer to ADC peripheral register block.
  49. *
  50. * @param[in] ref
  51. * Reference used during calibration. Can be both external and internal
  52. * references.
  53. *
  54. * @param[in] input
  55. * Input channel used during calibration.
  56. *
  57. * @return
  58. * The final value of the calibration register, note that the calibration
  59. * register gets updated with this value during the calibration.
  60. * No need to load the calibration values after the function returns.
  61. ******************************************************************************/
  62. rt_uint32_t efm32_adc_calibration(
  63. ADC_TypeDef *adc,
  64. ADC_Ref_TypeDef ref,
  65. ADC_SingleInput_TypeDef input)
  66. {
  67. rt_uint32_t cal;
  68. rt_int32_t sample;
  69. rt_int8_t high, mid, low, tmp;
  70. ADC_InitSingle_TypeDef singleInit = ADC_INITSINGLE_DEFAULT;
  71. /* Init for single conversion use, measure diff 0 with selected reference. */
  72. singleInit.reference = ref;
  73. singleInit.input = adcSingleInpDiff0;
  74. singleInit.acqTime = adcAcqTime32;
  75. singleInit.diff = true;
  76. /* Enable oversampling rate */
  77. singleInit.resolution = adcResOVS;
  78. ADC_InitSingle(adc, &singleInit);
  79. /* ADC is now set up for offset calibration */
  80. /* Offset calibration register is a 7 bit signed 2's complement value. */
  81. /* Use unsigned indexes for binary search, and convert when calibration */
  82. /* register is written to. */
  83. high = 63;
  84. low = -64;
  85. /* Do binary search for offset calibration*/
  86. while (low < high)
  87. {
  88. /* Calculate midpoint */
  89. mid = low + (high - low) / 2;
  90. /* Midpoint is converted to 2's complement and written to both scan and */
  91. /* single calibration registers */
  92. cal = adc->CAL & ~(_ADC_CAL_SINGLEOFFSET_MASK | _ADC_CAL_SCANOFFSET_MASK);
  93. tmp = mid < 0 ? (((mid & 0x3F) ^ 0x3F) | 0x40) + 1 : mid;
  94. cal |= tmp << _ADC_CAL_SINGLEOFFSET_SHIFT;
  95. cal |= tmp << _ADC_CAL_SCANOFFSET_SHIFT;
  96. adc_debug("adc->CAL = %x, cal = %x, tmp = %x\n", adc->CAL, cal, tmp);
  97. adc->CAL = cal;
  98. /* Do a conversion */
  99. ADC_Start(adc, adcStartSingle);
  100. /* Wait while conversion is active */
  101. while (adc->STATUS & ADC_STATUS_SINGLEACT) ;
  102. /* Get ADC result */
  103. sample = ADC_DataSingleGet(adc);
  104. /* Check result and decide in which part of to repeat search */
  105. /* Calibration register has negative effect on result */
  106. if (sample < 0)
  107. {
  108. /* Repeat search in bottom half. */
  109. high = mid;
  110. }
  111. else if (sample > 0)
  112. {
  113. /* Repeat search in top half. */
  114. low = mid + 1;
  115. }
  116. else
  117. {
  118. /* Found it, exit while loop */
  119. break;
  120. }
  121. }
  122. adc_debug("adc->CAL = %x\n", adc->CAL);
  123. /* Now do gain calibration, only input and diff settings needs to be changed */
  124. adc->SINGLECTRL &= ~(_ADC_SINGLECTRL_INPUTSEL_MASK | _ADC_SINGLECTRL_DIFF_MASK);
  125. adc->SINGLECTRL |= (input << _ADC_SINGLECTRL_INPUTSEL_SHIFT);
  126. adc->SINGLECTRL |= (false << _ADC_SINGLECTRL_DIFF_SHIFT);
  127. /* ADC is now set up for gain calibration */
  128. /* Gain calibration register is a 7 bit unsigned value. */
  129. high = 127;
  130. low = 0;
  131. /* Do binary search for gain calibration */
  132. while (low < high)
  133. {
  134. /* Calculate midpoint and write to calibration register */
  135. mid = low + (high - low) / 2;
  136. /* Midpoint is converted to 2's complement */
  137. cal = adc->CAL & ~(_ADC_CAL_SINGLEGAIN_MASK | _ADC_CAL_SCANGAIN_MASK);
  138. cal |= mid << _ADC_CAL_SINGLEGAIN_SHIFT;
  139. cal |= mid << _ADC_CAL_SCANGAIN_SHIFT;
  140. adc_debug("adc->CAL = %x, cal = %x, mid = %x\n", adc->CAL, cal, mid);
  141. adc->CAL = cal;
  142. /* Do a conversion */
  143. ADC_Start(adc, adcStartSingle);
  144. /* Wait while conversion is active */
  145. while (adc->STATUS & ADC_STATUS_SINGLEACT) ;
  146. /* Get ADC result */
  147. sample = ADC_DataSingleGet(adc);
  148. /* Check result and decide in which part to repeat search */
  149. /* Compare with a value atleast one LSB's less than top to avoid overshooting */
  150. /* Since oversampling is used, the result is 16 bits, but a couple of lsb's */
  151. /* applies to the 12 bit result value, if 0xffe is the top value in 12 bit, this */
  152. /* is in turn 0xffe0 in the 16 bit result. */
  153. /* Calibration register has positive effect on result */
  154. if (sample > 0xffd0)
  155. {
  156. /* Repeat search in bottom half. */
  157. high = mid;
  158. }
  159. else if (sample < 0xffd0)
  160. {
  161. /* Repeat search in top half. */
  162. low = mid + 1;
  163. }
  164. else
  165. {
  166. /* Found it, exit while loop */
  167. break;
  168. }
  169. }
  170. adc_debug("adc->CAL = %x\n", adc->CAL);
  171. return adc->CAL;
  172. }
  173. /***************************************************************************//**
  174. * @brief
  175. * Configure DMA for ADC
  176. *
  177. * @details
  178. *
  179. * @note
  180. *
  181. * @param[in] adc_device
  182. * Pointer to ADC registers base address
  183. *
  184. * @param[in] mode
  185. * ADC mode
  186. *
  187. * @param[in] channel
  188. * DMA channel
  189. ******************************************************************************/
  190. void efm32_adc_cfg_dma(
  191. ADC_TypeDef *adc_device,
  192. rt_uint8_t mode,
  193. rt_uint8_t channel)
  194. {
  195. DMA_CfgChannel_TypeDef chnlCfg;
  196. DMA_CfgDescr_TypeDef descrCfg;
  197. if (channel == (rt_uint8_t)EFM32_NO_DMA)
  198. {
  199. return;
  200. }
  201. /* Set up DMA channel */
  202. chnlCfg.highPri = false;
  203. chnlCfg.enableInt = false;
  204. if (adc_device == ADC0)
  205. {
  206. switch (mode & ADC_MASK_MODE)
  207. {
  208. case ADC_MODE_SINGLE:
  209. chnlCfg.select = DMAREQ_ADC0_SINGLE;
  210. break;
  211. case ADC_MODE_SCAN:
  212. chnlCfg.select = DMAREQ_ADC0_SCAN;
  213. break;
  214. default:
  215. return;
  216. }
  217. }
  218. else
  219. {
  220. // TODO: Any other channel?
  221. return;
  222. }
  223. chnlCfg.cb = RT_NULL;
  224. DMA_CfgChannel((rt_uint32_t)channel, &chnlCfg);
  225. /* Setting up DMA channel descriptor */
  226. descrCfg.dstInc = dmaDataInc4;
  227. descrCfg.srcInc = dmaDataIncNone;
  228. descrCfg.size = dmaDataSize4;
  229. descrCfg.arbRate = dmaArbitrate1;
  230. descrCfg.hprot = 0;
  231. DMA_CfgDescr((rt_uint32_t)channel, true, &descrCfg);
  232. }
  233. /***************************************************************************//**
  234. * @brief
  235. * Activate DMA for ADC
  236. *
  237. * @details
  238. *
  239. * @note
  240. *
  241. * @param[in] adc_device
  242. * Pointer to ADC registers base address
  243. *
  244. * @param[in] mode
  245. * ADC mode
  246. *
  247. * @param[in] count
  248. * ADC channel count
  249. *
  250. * @param[in] channel
  251. * DMA channel
  252. *
  253. * @param[out] buffer
  254. * Pointer to ADC results buffer
  255. ******************************************************************************/
  256. void efm32_adc_on_dma(
  257. ADC_TypeDef *adc_device,
  258. rt_uint8_t mode,
  259. rt_uint8_t count,
  260. rt_uint8_t channel,
  261. void *buffer)
  262. {
  263. switch (mode & ADC_MASK_MODE)
  264. {
  265. case ADC_MODE_SINGLE:
  266. /* Activate DMA */
  267. DMA_ActivateBasic(
  268. (rt_uint32_t)channel,
  269. true,
  270. false,
  271. buffer,
  272. (void *)&(adc_device->SINGLEDATA),
  273. count - 1);
  274. break;
  275. case ADC_MODE_SCAN:
  276. DMA_ActivateBasic(
  277. (rt_uint32_t)channel,
  278. true,
  279. false,
  280. buffer,
  281. (void *)&(adc_device->SCANDATA),
  282. count - 1);
  283. break;
  284. default:
  285. return;
  286. }
  287. }
  288. /***************************************************************************//**
  289. * @brief
  290. * Initialize ADC device
  291. *
  292. * @details
  293. *
  294. * @note
  295. *
  296. * @param[in] dev
  297. * Pointer to device descriptor
  298. *
  299. * @return
  300. * Error code
  301. ******************************************************************************/
  302. static rt_err_t rt_adc_init(rt_device_t dev)
  303. {
  304. RT_ASSERT(dev != RT_NULL);
  305. rt_uint32_t temp;
  306. struct efm32_adc_device_t *adc;
  307. adc = (struct efm32_adc_device_t *)(dev->user_data);
  308. temp = efm32_adc_calibration(adc->adc_device, ADC_CALI_REF, ADC_CALI_CH);
  309. adc_debug("adc->CAL = %x\n", temp);
  310. return RT_EOK;
  311. }
  312. /***************************************************************************//**
  313. * @brief
  314. * Configure ADC device
  315. *
  316. * @details
  317. *
  318. * @note
  319. *
  320. * @param[in] dev
  321. * Pointer to device descriptor
  322. *
  323. * @param[in] cmd
  324. * ADC control command
  325. *
  326. * @param[in] args
  327. * Arguments
  328. *
  329. * @return
  330. * Error code
  331. ******************************************************************************/
  332. static rt_err_t rt_adc_control(
  333. rt_device_t dev,
  334. rt_uint8_t cmd,
  335. void *args)
  336. {
  337. RT_ASSERT(dev != RT_NULL);
  338. struct efm32_adc_device_t *adc;
  339. adc = (struct efm32_adc_device_t *)(dev->user_data);
  340. switch (cmd)
  341. {
  342. case RT_DEVICE_CTRL_SUSPEND:
  343. /* Suspend device */
  344. dev->flag |= RT_DEVICE_FLAG_SUSPENDED;
  345. adc->adc_device->CMD = ADC_CMD_SINGLESTOP | ADC_CMD_SCANSTOP;
  346. break;
  347. case RT_DEVICE_CTRL_RESUME:
  348. {
  349. /* Resume device */
  350. struct efm32_adc_result_t *control = \
  351. (struct efm32_adc_result_t *)args;
  352. dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;
  353. switch (control->mode)
  354. {
  355. case ADC_MODE_SINGLE:
  356. if (adc->singleDmaChannel != (rt_uint8_t)EFM32_NO_DMA)
  357. {
  358. efm32_adc_on_dma(
  359. adc->adc_device,
  360. control->mode,
  361. adc->singleCount,
  362. adc->singleDmaChannel,
  363. control->buffer);
  364. }
  365. ADC_Start(adc->adc_device, adcStartSingle);
  366. break;
  367. case ADC_MODE_SCAN:
  368. if (adc->scanDmaChannel != (rt_uint8_t)EFM32_NO_DMA)
  369. {
  370. efm32_adc_on_dma(
  371. adc->adc_device,
  372. control->mode,
  373. adc->scanCount,
  374. adc->scanDmaChannel,
  375. control->buffer);
  376. }
  377. ADC_Start(adc->adc_device, adcStartScan);
  378. break;
  379. case ADC_MODE_TAILGATE:
  380. {
  381. void *index = control->buffer;
  382. if (adc->scanDmaChannel != (rt_uint8_t)EFM32_NO_DMA)
  383. {
  384. efm32_adc_on_dma(
  385. adc->adc_device,
  386. control->mode,
  387. adc->scanCount,
  388. adc->scanDmaChannel,
  389. index);
  390. index += adc->scanCount;
  391. }
  392. if (adc->singleDmaChannel != (rt_uint8_t)EFM32_NO_DMA)
  393. {
  394. efm32_adc_on_dma(
  395. adc->adc_device,
  396. control->mode,
  397. adc->singleCount,
  398. adc->singleDmaChannel,
  399. index);
  400. index += adc->singleCount;
  401. }
  402. ADC_Start(adc->adc_device, adcStartScanAndSingle);
  403. }
  404. break;
  405. default:
  406. return -RT_ERROR;
  407. }
  408. }
  409. break;
  410. case RT_DEVICE_CTRL_ADC_MODE:
  411. {
  412. /* change device setting */
  413. struct efm32_adc_control_t *control = \
  414. (struct efm32_adc_control_t *)args;
  415. switch (control->mode)
  416. {
  417. case ADC_MODE_SINGLE:
  418. ADC_InitSingle(adc->adc_device, control->single.init);
  419. break;
  420. case ADC_MODE_SCAN:
  421. ADC_InitScan(adc->adc_device, control->scan.init);
  422. break;
  423. case ADC_MODE_TAILGATE:
  424. ADC_InitSingle(adc->adc_device, control->single.init);
  425. ADC_InitScan(adc->adc_device, control->scan.init);
  426. break;
  427. default:
  428. return -RT_ERROR;
  429. }
  430. if (control->mode == ADC_MODE_TAILGATE)
  431. {
  432. adc->mode = ADC_MODE_TAILGATE;
  433. }
  434. else
  435. {
  436. adc->mode &= ~(rt_uint8_t)ADC_MODE_TAILGATE;
  437. adc->mode |= control->mode;
  438. }
  439. if ((control->mode == ADC_MODE_TAILGATE) || \
  440. (control->mode == ADC_MODE_SINGLE))
  441. {
  442. if (control->single.init->rep)
  443. {
  444. adc->mode |= ADC_OP_SINGLE_REPEAT;
  445. }
  446. adc->singleCount = control->single.count;
  447. adc->singleDmaChannel = control->single.dmaChannel;
  448. efm32_adc_cfg_dma(adc->adc_device, control->mode, adc->singleDmaChannel);
  449. }
  450. if ((control->mode == ADC_MODE_TAILGATE) || \
  451. (control->mode == ADC_MODE_SCAN))
  452. {
  453. if (control->scan.init->rep)
  454. {
  455. adc->mode |= ADC_OP_SCAN_REPEAT;
  456. }
  457. adc->scanCount = control->scan.count;
  458. adc->scanDmaChannel = control->scan.dmaChannel;
  459. efm32_adc_cfg_dma(adc->adc_device, control->mode, adc->scanDmaChannel);
  460. }
  461. }
  462. break;
  463. case RT_DEVICE_CTRL_ADC_RESULT:
  464. {
  465. struct efm32_adc_result_t *control = \
  466. (struct efm32_adc_result_t *)args;
  467. switch (control->mode)
  468. {
  469. case ADC_MODE_SINGLE:
  470. if (adc->singleDmaChannel != (rt_uint8_t)EFM32_NO_DMA)
  471. {
  472. if (adc->mode & ADC_OP_SINGLE_REPEAT)
  473. {
  474. if (!(DMA->IF & (1 << adc->singleDmaChannel)))
  475. {
  476. efm32_adc_on_dma(
  477. adc->adc_device,
  478. control->mode,
  479. adc->singleCount,
  480. adc->singleDmaChannel,
  481. control->buffer);
  482. }
  483. while (!(DMA->IF & (1 << adc->singleDmaChannel)));
  484. }
  485. else
  486. {
  487. while (adc->adc_device->STATUS & ADC_STATUS_SINGLEACT);
  488. }
  489. }
  490. else
  491. {
  492. while (adc->adc_device->STATUS & ADC_STATUS_SINGLEACT);
  493. *((rt_uint32_t *)control->buffer) = \
  494. ADC_DataSingleGet(adc->adc_device) << adcErrataShift;
  495. }
  496. break;
  497. case ADC_MODE_SCAN:
  498. if (adc->scanDmaChannel != (rt_uint8_t)EFM32_NO_DMA)
  499. {
  500. if (adc->mode & ADC_OP_SCAN_REPEAT)
  501. {
  502. if (!(DMA->IF & (1 << adc->scanDmaChannel)))
  503. {
  504. efm32_adc_on_dma(
  505. adc->adc_device,
  506. control->mode,
  507. adc->scanCount,
  508. adc->scanDmaChannel,
  509. control->buffer);
  510. }
  511. while (!(DMA->IF & (1 << adc->scanDmaChannel)));
  512. }
  513. else
  514. {
  515. while (adc->adc_device->STATUS & ADC_STATUS_SCANACT);
  516. }
  517. }
  518. else
  519. {
  520. while (adc->adc_device->STATUS & ADC_STATUS_SCANACT);
  521. *((rt_uint32_t *)control->buffer) = \
  522. ADC_DataScanGet(adc->adc_device) << adcErrataShift;
  523. }
  524. break;
  525. case ADC_MODE_TAILGATE:
  526. {
  527. void *index = control->buffer;
  528. if ((adc->scanDmaChannel != (rt_uint8_t)EFM32_NO_DMA) && \
  529. !(adc->mode & ADC_OP_SCAN_REPEAT))
  530. {
  531. index += adc->scanCount;
  532. }
  533. if ((adc->singleDmaChannel != (rt_uint8_t)EFM32_NO_DMA) && \
  534. !(adc->mode & ADC_OP_SINGLE_REPEAT))
  535. {
  536. index += adc->singleCount;
  537. }
  538. if (adc->scanDmaChannel != (rt_uint8_t)EFM32_NO_DMA)
  539. {
  540. if (adc->mode & ADC_OP_SCAN_REPEAT)
  541. {
  542. if (!(DMA->IF & (1 << adc->scanDmaChannel)))
  543. {
  544. efm32_adc_on_dma(
  545. adc->adc_device,
  546. control->mode,
  547. adc->scanCount,
  548. adc->scanDmaChannel,
  549. index);
  550. index += adc->scanCount;
  551. }
  552. while (!(DMA->IF & (1 << adc->scanDmaChannel)));
  553. }
  554. else
  555. {
  556. while (adc->adc_device->STATUS & ADC_STATUS_SCANACT);
  557. }
  558. }
  559. else
  560. {
  561. while (adc->adc_device->STATUS & ADC_STATUS_SCANACT);
  562. *(rt_uint32_t *)(index++) = \
  563. ADC_DataScanGet(adc->adc_device) << adcErrataShift;
  564. }
  565. if (adc->singleDmaChannel != (rt_uint8_t)EFM32_NO_DMA)
  566. {
  567. if (adc->mode & ADC_OP_SINGLE_REPEAT)
  568. {
  569. if (!(DMA->IF & (1 << adc->singleDmaChannel)))
  570. {
  571. efm32_adc_on_dma(
  572. adc->adc_device,
  573. control->mode,
  574. adc->singleCount,
  575. adc->singleDmaChannel,
  576. index);
  577. index += adc->singleCount;
  578. }
  579. while (!(DMA->IF & (1 << adc->singleDmaChannel)));
  580. }
  581. else
  582. {
  583. while (adc->adc_device->STATUS & ADC_STATUS_SINGLEACT);
  584. }
  585. }
  586. else
  587. {
  588. while (adc->adc_device->STATUS & ADC_STATUS_SINGLEACT);
  589. *(rt_uint32_t *)(index++) = \
  590. ADC_DataSingleGet(adc->adc_device) << adcErrataShift;
  591. }
  592. }
  593. break;
  594. default:
  595. return -RT_ERROR;
  596. }
  597. }
  598. break;
  599. default:
  600. return -RT_ERROR;
  601. }
  602. return RT_EOK;
  603. }
  604. /***************************************************************************//**
  605. * @brief
  606. * Register ADC device
  607. *
  608. * @details
  609. *
  610. * @note
  611. *
  612. * @param[in] device
  613. * Pointer to device descriptor
  614. *
  615. * @param[in] name
  616. * Device name
  617. *
  618. * @param[in] flag
  619. * Configuration flags
  620. *
  621. * @param[in] adc
  622. * Pointer to ADC device descriptor
  623. *
  624. * @return
  625. * Error code
  626. ******************************************************************************/
  627. rt_err_t rt_hw_adc_register(
  628. rt_device_t device,
  629. const char *name,
  630. rt_uint32_t flag,
  631. struct efm32_adc_device_t *adc)
  632. {
  633. RT_ASSERT(device != RT_NULL);
  634. device->type = RT_Device_Class_Char; /* fixme: should be adc type */
  635. device->rx_indicate = RT_NULL;
  636. device->tx_complete = RT_NULL;
  637. device->init = rt_adc_init;
  638. device->open = RT_NULL;
  639. device->close = RT_NULL;
  640. device->read = RT_NULL;
  641. device->write = RT_NULL;
  642. device->control = rt_adc_control;
  643. device->user_data = adc;
  644. /* register a character device */
  645. return rt_device_register(device, name, flag);
  646. }
  647. /***************************************************************************//**
  648. * @brief
  649. * Initialize the specified ADC unit
  650. *
  651. * @details
  652. *
  653. * @note
  654. *
  655. * @param[in] device
  656. * Pointer to device descriptor
  657. *
  658. * @param[in] unitNumber
  659. * Unit number
  660. *
  661. * @return
  662. * Pointer to ADC device
  663. ******************************************************************************/
  664. static struct efm32_adc_device_t *rt_hw_adc_unit_init(
  665. rt_device_t device,
  666. rt_uint8_t unitNumber)
  667. {
  668. struct efm32_adc_device_t *adc;
  669. CMU_Clock_TypeDef adcClock;
  670. ADC_Init_TypeDef init = ADC_INIT_DEFAULT;
  671. do
  672. {
  673. /* Allocate device and set default value */
  674. adc = rt_malloc(sizeof(struct efm32_adc_device_t));
  675. if (adc == RT_NULL)
  676. {
  677. adc_debug("no memory for ADC%d driver\n", unitNumber);
  678. break;
  679. }
  680. adc->mode = 0;
  681. adc->singleCount = 0;
  682. adc->singleDmaChannel = (rt_uint8_t)EFM32_NO_DMA;
  683. adc->scanCount = 0;
  684. adc->scanDmaChannel = (rt_uint8_t)EFM32_NO_DMA;
  685. /* Initialization */
  686. if (unitNumber >= ADC_COUNT)
  687. {
  688. break;
  689. }
  690. switch (unitNumber)
  691. {
  692. case 0:
  693. adc->adc_device = ADC0;
  694. adcClock = (CMU_Clock_TypeDef)cmuClock_ADC0;
  695. break;
  696. default:
  697. break;
  698. }
  699. /* Enable ADC clock */
  700. CMU_ClockEnable(adcClock, true);
  701. /* Reset */
  702. ADC_Reset(adc->adc_device);
  703. /* Configure ADC */
  704. // TODO: Fixed oversampling rate?
  705. init.ovsRateSel = adcOvsRateSel4096;
  706. init.timebase = ADC_TimebaseCalc(0);
  707. init.prescale = ADC_PrescaleCalc(ADC_CONVERT_FREQUENCY, 0);
  708. ADC_Init(adc->adc_device, &init);
  709. return adc;
  710. } while(0);
  711. if (adc)
  712. {
  713. rt_free(adc);
  714. }
  715. rt_kprintf("ADC: Init failed!\n");
  716. return RT_NULL;
  717. }
  718. /***************************************************************************//**
  719. * @brief
  720. * Initialize all ADC module related hardware and register ADC device to kernel
  721. *
  722. * @details
  723. *
  724. * @note
  725. *
  726. ******************************************************************************/
  727. void rt_hw_adc_init(void)
  728. {
  729. SYSTEM_ChipRevision_TypeDef chipRev;
  730. struct efm32_adc_device_t *adc;
  731. #ifdef RT_USING_ADC0
  732. if ((adc = rt_hw_adc_unit_init(&adc0_device, 0)) != RT_NULL)
  733. {
  734. rt_hw_adc_register(&adc0_device, RT_ADC0_NAME, EFM32_NO_DATA, adc);
  735. }
  736. #endif
  737. /* ADC errata for rev B when using VDD as reference, need to multiply */
  738. /* result by 2 */
  739. SYSTEM_ChipRevisionGet(&chipRev);
  740. if ((chipRev.major == 0x01) && (chipRev.minor == 0x01))
  741. {
  742. adcErrataShift = 1;
  743. }
  744. }
  745. #endif
  746. /***************************************************************************//**
  747. * @}
  748. ******************************************************************************/