Advertisement
Guest User

Untitled

a guest
May 26th, 2018
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.02 KB | None | 0 0
  1. /*************************************************************************************************************
  2. *
  3. * Project: ROPA
  4. * Language: C
  5. * Module: firmware
  6. * Initial: 2018-01-11
  7. * Author: C.Schoenegger
  8. * Copyright: illumination network systems GmbH
  9. *
  10. * Description: ADC trigger via TPM, sampling of several signals, and eDMA transfers into ping-pong buffer.
  11. *
  12. *************************************************************************************************************/
  13. #include "adc_task.h"
  14.  
  15. /* FreeRTOS kernel includes */
  16. #include "FreeRTOS.h"
  17. #include "queue.h"
  18. #include "task.h"
  19. #include "timers.h"
  20.  
  21. /* drivers */
  22. #include "error_codes.h"
  23. #include "fsl_adc16.h"
  24. #include "fsl_debug_console.h"
  25. #include "fsl_dmamux.h"
  26. #include "fsl_edma.h"
  27. #include "fsl_tpm.h"
  28. #include "rtos_config.h"
  29.  
  30. #include <cr_section_macros.h>
  31.  
  32. /*************************************************************************************************************
  33. * Definitions
  34. *************************************************************************************************************/
  35. /*! @brief Signal to ADC channel assignment */
  36. enum adc_channel_t
  37. {
  38. ADC0_CHANNEL_I1 = 10U, //!< I1 signal connected to this channel on ADC0
  39. ADC0_CHANNEL_Q1, //!< Q1 signal connected to this channel on ADC0
  40. ADC1_CHANNEL_I2 = 10U, //!< I2 signal connected to this channel on ADC1
  41. ADC1_CHANNEL_Q2 //!< Q2 signal connected to this channel on ADC1
  42. };
  43.  
  44. /*! @brief ADC to eDMA channel assignment */
  45. enum dma_source_t
  46. {
  47. ADC0_CHANNEL10_EDMA0 = 0U, //!< ADC0 channel 10 connected to EDMA channel 0
  48. ADC0_CHANNEL11_EDMA1, //!< ADC0 channel 11 connected to EDMA channel 1
  49. ADC1_CHANNEL10_EDMA2, //!< ADC1 channel 10 connected to EDMA channel 2
  50. ADC1_CHANNEL11_EDMA3 //!< ADC1 channel 11 connected to EDMA channel 3
  51. };
  52.  
  53. /*************************************************************************************************************
  54. * Variables
  55. *************************************************************************************************************/
  56. /*! @brief ADC queue which tells the buffer switch events */
  57. QueueHandle_t g_adcQueue;
  58.  
  59. /*! @brief ADC ping-pong buffer for each signal -> organized as nested array */
  60. /** @cond */__BSS(RAM2) /** @endcond */ uint16_t g_adcValues[NUM_ADC_SIGNALS][2U*ADC_BUFFER_SIZE];
  61.  
  62. //TickType_t g_ticks1;
  63. //TickType_t g_ticks2;
  64.  
  65. /*! @brief ADC task handle used for suspend/resume operations */
  66. static TaskHandle_t g_adcTaskHandle;
  67.  
  68. /*! @brief DMA handles for each channel */
  69. static edma_handle_t g_edmaHandle[NUM_ADC_SIGNALS];
  70.  
  71. /*! @brief DMA channel transfer completion flag */
  72. static volatile bool g_edmaTransferDone[NUM_ADC_SIGNALS];
  73.  
  74. /*************************************************************************************************************
  75. * Functions
  76. *************************************************************************************************************/
  77. /**
  78. * @brief EDMA interrupt callback
  79. *
  80. * The EDMA interrupt is configured to fire twice per buffer and channel (kEDMA_HalfInterruptEnable).
  81. *
  82. * @param handle ignored in this function, the handles are saved in g_edmaHandle
  83. * @param userData the DMA source is contained as user data (configured at EDMA_SetCallback() below)
  84. * @param transferDone ignored in this function
  85. * @param tcds ignored in this function
  86. */
  87. static void EDMA_Callback(edma_handle_t *handle, void *userData, bool transferDone, uint32_t tcds)
  88. {
  89. enum dma_source_t source = (enum dma_source_t) userData;
  90.  
  91. /* Set unused arguments */
  92. (void) handle;
  93. (void) transferDone;
  94. (void) tcds;
  95.  
  96. /* Clear Edma interrupt flags and set Transfer-Done flags */
  97. switch(source)
  98. {
  99. case ADC0_CHANNEL10_EDMA0:
  100. EDMA_ClearChannelStatusFlags(DMA0, ADC0_CHANNEL10_EDMA0, kEDMA_InterruptFlag);
  101. g_edmaTransferDone[ADC0_CHANNEL10_EDMA0] = true;
  102. break;
  103. case ADC0_CHANNEL11_EDMA1:
  104. EDMA_ClearChannelStatusFlags(DMA0, ADC0_CHANNEL11_EDMA1, kEDMA_InterruptFlag);
  105. g_edmaTransferDone[ADC0_CHANNEL11_EDMA1] = true;
  106. break;
  107. case ADC1_CHANNEL10_EDMA2:
  108. EDMA_ClearChannelStatusFlags(DMA0, ADC1_CHANNEL10_EDMA2, kEDMA_InterruptFlag);
  109. g_edmaTransferDone[ADC1_CHANNEL10_EDMA2] = true;
  110. break;
  111. case ADC1_CHANNEL11_EDMA3:
  112. EDMA_ClearChannelStatusFlags(DMA0, ADC1_CHANNEL11_EDMA3, kEDMA_InterruptFlag);
  113. g_edmaTransferDone[ADC1_CHANNEL11_EDMA3] = true;
  114. break;
  115. default:
  116. break;
  117. }
  118. }
  119.  
  120. /**
  121. * @brief ADC FreeRTOS task
  122. *
  123. * This task waits until a transfer-done event is signaled by the DMA ISR and tells a buffer
  124. * switch event using the ADC message queue. The ADC message queue is used to serialize the
  125. * various DMA events that run in parallel.
  126. *
  127. * @param arg not used by this function
  128. */
  129. static void ADC_Task(void *arg)
  130. {
  131. uint8_t adcBufferSwitch[NUM_ADC_SIGNALS];
  132.  
  133. enum buffer_state_t bufferSelect = BUFFERS_NOT_READY;
  134.  
  135. /* Set unused argument */
  136. (void) arg;
  137.  
  138. PRINTF("ADC Task started!\r\n");
  139.  
  140. //g_ticks1 = xTaskGetTickCount();
  141. //PRINTF("start ticks: %d\r\n", xTaskGetTickCount());
  142.  
  143. /* Buffer and variable initialization */
  144. memset(g_adcValues[ADC0_CHANNEL10_EDMA0], 0U, sizeof(g_adcValues[ADC0_CHANNEL10_EDMA0]));
  145. memset(g_adcValues[ADC0_CHANNEL11_EDMA1], 0U, sizeof(g_adcValues[ADC0_CHANNEL11_EDMA1]));
  146. memset(g_adcValues[ADC1_CHANNEL10_EDMA2], 0U, sizeof(g_adcValues[ADC1_CHANNEL10_EDMA2]));
  147. memset(g_adcValues[ADC1_CHANNEL11_EDMA3], 0U, sizeof(g_adcValues[ADC1_CHANNEL11_EDMA3]));
  148.  
  149. g_edmaTransferDone[ADC0_CHANNEL10_EDMA0] = false;
  150. g_edmaTransferDone[ADC0_CHANNEL11_EDMA1] = false;
  151. g_edmaTransferDone[ADC1_CHANNEL10_EDMA2] = false;
  152. g_edmaTransferDone[ADC1_CHANNEL11_EDMA3] = false;
  153.  
  154. adcBufferSwitch[ADC0_CHANNEL10_EDMA0] = 0U;
  155. adcBufferSwitch[ADC0_CHANNEL11_EDMA1] = 0U;
  156. adcBufferSwitch[ADC1_CHANNEL10_EDMA2] = 0U;
  157. adcBufferSwitch[ADC1_CHANNEL11_EDMA3] = 0U;
  158.  
  159. /* suspend and wait on external ADC enable signal */
  160. vTaskSuspend(NULL);
  161.  
  162. while(1)
  163. {
  164. if(g_edmaTransferDone[ADC0_CHANNEL10_EDMA0] == true)
  165. {
  166. g_edmaTransferDone[ADC0_CHANNEL10_EDMA0] = false;
  167. bufferSelect = (adcBufferSwitch[ADC0_CHANNEL10_EDMA0] == 0U) ? I1_LOWER_READY : I1_UPPER_READY;
  168. adcBufferSwitch[ADC0_CHANNEL10_EDMA0] = 1U - adcBufferSwitch[ADC0_CHANNEL10_EDMA0];
  169. }
  170. else if(g_edmaTransferDone[ADC0_CHANNEL11_EDMA1] == true)
  171. {
  172. g_edmaTransferDone[ADC0_CHANNEL11_EDMA1] = false;
  173. bufferSelect = (adcBufferSwitch[ADC0_CHANNEL11_EDMA1] == 0U) ? Q1_LOWER_READY : Q1_UPPER_READY;
  174. adcBufferSwitch[ADC0_CHANNEL11_EDMA1] = 1U - adcBufferSwitch[ADC0_CHANNEL11_EDMA1];
  175. }
  176. else if(g_edmaTransferDone[ADC1_CHANNEL10_EDMA2] == true)
  177. {
  178. g_edmaTransferDone[ADC1_CHANNEL10_EDMA2] = false;
  179. bufferSelect = (adcBufferSwitch[ADC1_CHANNEL10_EDMA2] == 0U) ? I2_LOWER_READY : I2_UPPER_READY;
  180. adcBufferSwitch[ADC1_CHANNEL10_EDMA2] = 1U - adcBufferSwitch[ADC1_CHANNEL10_EDMA2];
  181. }
  182. else if(g_edmaTransferDone[ADC1_CHANNEL11_EDMA3] == true)
  183. {
  184. g_edmaTransferDone[ADC1_CHANNEL11_EDMA3] = false;
  185. bufferSelect = (adcBufferSwitch[ADC1_CHANNEL11_EDMA3] == 0U) ? Q2_LOWER_READY : Q2_UPPER_READY;
  186. adcBufferSwitch[ADC1_CHANNEL11_EDMA3] = 1U - adcBufferSwitch[ADC1_CHANNEL11_EDMA3];
  187. }
  188.  
  189. /* send the buffer complete events via message queue */
  190. if(bufferSelect != BUFFERS_NOT_READY)
  191. {
  192. if(xQueueSend(g_adcQueue, &bufferSelect, 0U) != pdPASS)
  193. {
  194. throwError(ERROR_MESSAGE_QUEUE_FULL);
  195. PRINTF("%s\r\n", getErrorMessage(ERROR_MESSAGE_QUEUE_FULL));
  196. }
  197. bufferSelect = BUFFERS_NOT_READY;
  198. }
  199. }
  200. }
  201.  
  202. /**
  203. * @brief TPM configuration used to assert the hardware trigger lines of both ADC interfaces
  204. *
  205. * Configuration for a free-running counter that triggers SC1A at counter == 0 and SC1B
  206. * at counter == half period. The period is currently set to 8 us to achieve a sampling
  207. * rate of 125 kHz. The 12 MHz oscillator clock is used to generate the counter events.
  208. */
  209. static void TPM_Configuration(void)
  210. {
  211. tpm_config_t tpmConfig;
  212.  
  213. /* set OSCERCLK as TPM input clock source */
  214. CLOCK_SetTpmClock(2U);
  215.  
  216. TPM_GetDefaultConfig(&tpmConfig);
  217.  
  218. TPM_Init(TPM1, &tpmConfig);
  219. TPM_Init(TPM2, &tpmConfig);
  220.  
  221. /* Set the timer to be in free-running mode */
  222. TPM_SetTimerPeriod(TPM1, USEC_TO_COUNT(8U, CLOCK_GetFreq(kCLOCK_Osc0ErClkUndiv)));
  223. TPM_SetTimerPeriod(TPM2, USEC_TO_COUNT(8U, CLOCK_GetFreq(kCLOCK_Osc0ErClkUndiv)));
  224.  
  225. /* Setup the output compare mode to pulse on a match */
  226. TPM_SetupOutputCompare(TPM1, kTPM_Chnl_0, kTPM_HighPulseOutput, 0U);
  227. TPM_SetupOutputCompare(TPM1, kTPM_Chnl_1, kTPM_HighPulseOutput, USEC_TO_COUNT(4U, CLOCK_GetFreq(kCLOCK_Osc0ErClkUndiv)));
  228.  
  229. TPM_SetupOutputCompare(TPM2, kTPM_Chnl_0, kTPM_HighPulseOutput, 0U);
  230. TPM_SetupOutputCompare(TPM2, kTPM_Chnl_1, kTPM_HighPulseOutput, USEC_TO_COUNT(4U, CLOCK_GetFreq(kCLOCK_Osc0ErClkUndiv)));
  231.  
  232. /* Enable DMA */
  233. TPM1->CONTROLS[kTPM_Chnl_0].CnSC |= TPM_CnSC_DMA_MASK;
  234. TPM1->CONTROLS[kTPM_Chnl_1].CnSC |= TPM_CnSC_DMA_MASK;
  235. TPM2->CONTROLS[kTPM_Chnl_0].CnSC |= TPM_CnSC_DMA_MASK;
  236. TPM2->CONTROLS[kTPM_Chnl_1].CnSC |= TPM_CnSC_DMA_MASK;
  237. }
  238.  
  239. /**
  240. * @brief Configuration of ADC0 and ADC1 interfaces
  241. *
  242. * The 12 MHz oscillator is used as clock source for the ADC module. The conversion time
  243. * of both ADC interfaces is set to 24 ADCK cycles which results in a conversion rate of
  244. * 500 kHz, fast enough to sample two channels at 125 kHz sampling rate.
  245. * The ADC resolution is set to 12 bit.
  246. * Hardware triggering is enabled via TPM channel pulses.
  247. * Auto-Calibration is performed once at initialization.
  248. */
  249. static void ADC16_Configuration(void)
  250. {
  251. adc16_config_t adcConfig;
  252. adc16_channel_config_t adcChannelConfig;
  253.  
  254. /*
  255. * Initialization ADC for 12bit resolution, alternate crystal clock, long sample and high speed mode
  256. */
  257. ADC16_GetDefaultConfig(&adcConfig);
  258.  
  259. adcConfig.clockDivider = kADC16_ClockDivider1; // divide by 1, resulting ADCK = 12 MHz
  260. adcConfig.clockSource = kADC16_ClockSourceAlt2; // clock source is the alternate (quartz) clock (12 MHz)
  261. adcConfig.enableHighSpeed = true; // high freqeuency clock mode -> 2 extra ADCK cycles
  262. adcConfig.longSampleMode = kADC16_LongSampleCycle6; // long sample mode with 2 extra ADCK cycles
  263. adcConfig.resolution = kADC16_ResolutionSE12Bit; // 12 bit resolution -> 20 ADCK cycles
  264. adcConfig.enableContinuousConversion = false; // single conversion mode
  265.  
  266. ADC16_Init(ADC0, &adcConfig);
  267. ADC16_Init(ADC1, &adcConfig);
  268.  
  269. #if defined(FSL_FEATURE_ADC16_HAS_CALIBRATION) && FSL_FEATURE_ADC16_HAS_CALIBRATION
  270. /* Auto calibration */
  271. if (kStatus_Success == ADC16_DoAutoCalibration(ADC0))
  272. {
  273. PRINTF("ADC0 Auto-Calibration Done!\r\n");
  274. }
  275. else
  276. {
  277. throwError(ERROR_ADC_AUTOCALIBRATION_FAILED);
  278. PRINTF("%s\r\n", getErrorMessage(ERROR_ADC_AUTOCALIBRATION_FAILED));
  279. }
  280. if (kStatus_Success == ADC16_DoAutoCalibration(ADC1))
  281. {
  282. PRINTF("ADC1 Auto-Calibration Done!\r\n");
  283. }
  284. else
  285. {
  286. throwError(ERROR_ADC_AUTOCALIBRATION_FAILED);
  287. PRINTF("%s\r\n", getErrorMessage(ERROR_ADC_AUTOCALIBRATION_FAILED));
  288. }
  289. #endif
  290.  
  291. /* Enable hardware trigger for both ADC0 and ADC1. */
  292. ADC16_EnableHardwareTrigger(ADC0, true);
  293. ADC16_EnableHardwareTrigger(ADC1, true);
  294.  
  295. /* Channel Configuration */
  296. adcChannelConfig.enableDifferentialConversion = false; // configured for single-ended conversion
  297. adcChannelConfig.enableInterruptOnConversionCompleted = false; // disable interrupt on conversion completion
  298.  
  299. /* Configure SC1A and SC1B registers for ADC0 and ADC1 */
  300. adcChannelConfig.channelNumber = ADC0_CHANNEL_I1;
  301. ADC16_SetChannelConfig(ADC0, 0U, &adcChannelConfig);
  302.  
  303. adcChannelConfig.channelNumber = ADC0_CHANNEL_Q1;
  304. ADC16_SetChannelConfig(ADC0, 1U, &adcChannelConfig);
  305.  
  306. adcChannelConfig.channelNumber = ADC1_CHANNEL_I2;
  307. ADC16_SetChannelConfig(ADC1, 0U, &adcChannelConfig);
  308.  
  309. adcChannelConfig.channelNumber = ADC1_CHANNEL_Q2;
  310. ADC16_SetChannelConfig(ADC1, 1U, &adcChannelConfig);
  311. }
  312.  
  313. /**
  314. * @brief Configuration of DMAMUX element
  315. *
  316. * The DMAMUX component uses the ADC-to-eDMA channel assignment defined above.
  317. */
  318. static void DMAMUX_Configuration(void)
  319. {
  320. /* Configure DMAMUX */
  321. DMAMUX_Init(DMAMUX0);
  322.  
  323. DMAMUX_SetSource(DMAMUX0, ADC0_CHANNEL10_EDMA0, 28U); /* Map TPM1 channel 0 source to DMA channel 0 */
  324. DMAMUX_SetSource(DMAMUX0, ADC0_CHANNEL11_EDMA1, 29U); /* Map TPM1 channel 1 source to DMA channel 1 */
  325. DMAMUX_SetSource(DMAMUX0, ADC1_CHANNEL10_EDMA2, 30U); /* Map TPM2 channel 0 source to DMA channel 2 */
  326. DMAMUX_SetSource(DMAMUX0, ADC1_CHANNEL11_EDMA3, 31U); /* Map TPM2 channel 1 source to DMA channel 3 */
  327.  
  328. /* Enable Channels in DMAMUX */
  329. DMAMUX_EnableChannel(DMAMUX0, ADC0_CHANNEL10_EDMA0);
  330. DMAMUX_EnableChannel(DMAMUX0, ADC0_CHANNEL11_EDMA1);
  331. DMAMUX_EnableChannel(DMAMUX0, ADC1_CHANNEL10_EDMA2);
  332. DMAMUX_EnableChannel(DMAMUX0, ADC1_CHANNEL11_EDMA3);
  333. }
  334.  
  335. /**
  336. * @brief EDMA Configuration for continuous DMA transfers using double-buffering
  337. *
  338. * There is a problem in the fsl_edma driver which automatically stops every DMA
  339. * request after one transfer -> thus, the used TCD registers are written here and
  340. * configured for continuous DMA requests and to restart at the buffer start-addresses.
  341. * This permits minimal CPU interaction and the usage of enable/disable functions to
  342. * control the entire ADC sampling flow.
  343. */
  344. static void EDMA_Configuration(void)
  345. {
  346. edma_config_t edmaConfig;
  347. edma_transfer_config_t edmaTransferConfig;
  348.  
  349. /* Initialize eDMA */
  350. EDMA_GetDefaultConfig(&edmaConfig);
  351. EDMA_Init(DMA0, &edmaConfig);
  352.  
  353. EDMA_CreateHandle(&g_edmaHandle[ADC0_CHANNEL10_EDMA0], DMA0, ADC0_CHANNEL10_EDMA0);
  354. EDMA_CreateHandle(&g_edmaHandle[ADC0_CHANNEL11_EDMA1], DMA0, ADC0_CHANNEL11_EDMA1);
  355. EDMA_CreateHandle(&g_edmaHandle[ADC1_CHANNEL10_EDMA2], DMA0, ADC1_CHANNEL10_EDMA2);
  356. EDMA_CreateHandle(&g_edmaHandle[ADC1_CHANNEL11_EDMA3], DMA0, ADC1_CHANNEL11_EDMA3);
  357.  
  358. EDMA_SetCallback(&g_edmaHandle[ADC0_CHANNEL10_EDMA0], EDMA_Callback, (void *) ADC0_CHANNEL10_EDMA0);
  359. EDMA_SetCallback(&g_edmaHandle[ADC0_CHANNEL11_EDMA1], EDMA_Callback, (void *) ADC0_CHANNEL11_EDMA1);
  360. EDMA_SetCallback(&g_edmaHandle[ADC1_CHANNEL10_EDMA2], EDMA_Callback, (void *) ADC1_CHANNEL10_EDMA2);
  361. EDMA_SetCallback(&g_edmaHandle[ADC1_CHANNEL11_EDMA3], EDMA_Callback, (void *) ADC1_CHANNEL11_EDMA3);
  362.  
  363. /* Setup transfer configuration for ADC0 SC1A */
  364. EDMA_PrepareTransfer(&edmaTransferConfig, (void *)&ADC0->R[0U], sizeof(uint16_t),
  365. (void *)g_adcValues[ADC0_CHANNEL10_EDMA0], sizeof(uint16_t), sizeof(uint16_t),
  366. sizeof(g_adcValues[ADC0_CHANNEL10_EDMA0]), kEDMA_PeripheralToMemory);
  367. EDMA_SubmitTransfer(&g_edmaHandle[ADC0_CHANNEL10_EDMA0], &edmaTransferConfig);
  368.  
  369. DMA0->TCD[ADC0_CHANNEL10_EDMA0].DLAST_SGA = -(2U*ADC_BUFFER_SIZE*sizeof(uint16_t)); // reset to start address
  370. DMA0->TCD[ADC0_CHANNEL10_EDMA0].CSR &= ~DMA_CSR_DREQ_MASK; // don't disable DMA REQ line
  371.  
  372. /* Setup transfer configuration for ADC0 SC1B */
  373. EDMA_PrepareTransfer(&edmaTransferConfig, (void *)&ADC0->R[1U], sizeof(uint16_t),
  374. (void *)g_adcValues[ADC0_CHANNEL11_EDMA1], sizeof(uint16_t), sizeof(uint16_t),
  375. sizeof(g_adcValues[ADC0_CHANNEL11_EDMA1]), kEDMA_PeripheralToMemory);
  376. EDMA_SubmitTransfer(&g_edmaHandle[ADC0_CHANNEL11_EDMA1], &edmaTransferConfig);
  377.  
  378. DMA0->TCD[ADC0_CHANNEL11_EDMA1].DLAST_SGA = -(2U*ADC_BUFFER_SIZE*sizeof(uint16_t)); // reset to start address
  379. DMA0->TCD[ADC0_CHANNEL11_EDMA1].CSR &= ~DMA_CSR_DREQ_MASK; // don't disable DMA REQ line
  380.  
  381. /* Setup transfer configuration for ADC1 SC1A */
  382. EDMA_PrepareTransfer(&edmaTransferConfig, (void *)&ADC1->R[0U], sizeof(uint16_t),
  383. (void *)g_adcValues[ADC1_CHANNEL10_EDMA2], sizeof(uint16_t), sizeof(uint16_t),
  384. sizeof(g_adcValues[ADC1_CHANNEL10_EDMA2]), kEDMA_PeripheralToMemory);
  385. EDMA_SubmitTransfer(&g_edmaHandle[ADC1_CHANNEL10_EDMA2], &edmaTransferConfig);
  386.  
  387. DMA0->TCD[ADC1_CHANNEL10_EDMA2].DLAST_SGA = -(2U*ADC_BUFFER_SIZE*sizeof(uint16_t)); // reset to start address
  388. DMA0->TCD[ADC1_CHANNEL10_EDMA2].CSR &= ~DMA_CSR_DREQ_MASK; // don't disable DMA REQ line
  389.  
  390. /* Setup transfer configuration for ADC1 SC1B */
  391. EDMA_PrepareTransfer(&edmaTransferConfig, (void *)&ADC1->R[1U], sizeof(uint16_t),
  392. (void *)g_adcValues[ADC1_CHANNEL11_EDMA3], sizeof(uint16_t), sizeof(uint16_t),
  393. sizeof(g_adcValues[ADC1_CHANNEL11_EDMA3]), kEDMA_PeripheralToMemory);
  394. EDMA_SubmitTransfer(&g_edmaHandle[ADC1_CHANNEL11_EDMA3], &edmaTransferConfig);
  395.  
  396. DMA0->TCD[ADC1_CHANNEL11_EDMA3].DLAST_SGA = -(2U*ADC_BUFFER_SIZE*sizeof(uint16_t)); // reset to start address
  397. DMA0->TCD[ADC1_CHANNEL11_EDMA3].CSR &= ~DMA_CSR_DREQ_MASK; // don't disable DMA REQ line
  398.  
  399. /* Configure two Interrupts per buffer filling */
  400. EDMA_EnableChannelInterrupts(DMA0, ADC0_CHANNEL10_EDMA0, kEDMA_HalfInterruptEnable);
  401. EDMA_EnableChannelInterrupts(DMA0, ADC0_CHANNEL11_EDMA1, kEDMA_HalfInterruptEnable);
  402. EDMA_EnableChannelInterrupts(DMA0, ADC1_CHANNEL10_EDMA2, kEDMA_HalfInterruptEnable);
  403. EDMA_EnableChannelInterrupts(DMA0, ADC1_CHANNEL11_EDMA3, kEDMA_HalfInterruptEnable);
  404. }
  405.  
  406. void ADC_Enable(void)
  407. {
  408. vTaskResume(g_adcTaskHandle);
  409. PRINTF("ADC Task resumed\r\n");
  410.  
  411. /* Start EDMA transfers */
  412. EDMA_StartTransfer(&g_edmaHandle[ADC0_CHANNEL10_EDMA0]);
  413. EDMA_StartTransfer(&g_edmaHandle[ADC0_CHANNEL11_EDMA1]);
  414. EDMA_StartTransfer(&g_edmaHandle[ADC1_CHANNEL10_EDMA2]);
  415. EDMA_StartTransfer(&g_edmaHandle[ADC1_CHANNEL11_EDMA3]);
  416.  
  417. /* Start TPM counters */
  418. TPM_StartTimer(TPM1, kTPM_SystemClock);
  419. TPM_StartTimer(TPM2, kTPM_SystemClock);
  420. }
  421.  
  422. void ADC_Disable(void)
  423. {
  424. /* Stop TPM counters */
  425. TPM_StopTimer(TPM1);
  426. TPM_StopTimer(TPM2);
  427.  
  428. /* Stop EDMA transfers */
  429. EDMA_StopTransfer(&g_edmaHandle[ADC0_CHANNEL10_EDMA0]);
  430. EDMA_StopTransfer(&g_edmaHandle[ADC0_CHANNEL11_EDMA1]);
  431. EDMA_StopTransfer(&g_edmaHandle[ADC1_CHANNEL10_EDMA2]);
  432. EDMA_StopTransfer(&g_edmaHandle[ADC1_CHANNEL11_EDMA3]);
  433.  
  434. PRINTF("ADC Task suspended\r\n");
  435. vTaskSuspend(g_adcTaskHandle);
  436. }
  437.  
  438. TaskHandle_t ADC_TaskInit(void)
  439. {
  440. uint32_t tmp32;
  441.  
  442. TaskHandle_t xCreatedTask, xReturn;
  443. portBASE_TYPE xResult;
  444.  
  445. /* configure ADC0/ADC1 alternate trigger via TPM */
  446. tmp32 = SIM->SOPT7 & ~(SIM_SOPT7_ADC0TRGSEL_MASK | SIM_SOPT7_ADC1TRGSEL_MASK);
  447. tmp32 |= SIM_SOPT7_ADC1ALTTRGEN_MASK | SIM_SOPT7_ADC1TRGSEL(15U) | SIM_SOPT7_ADC0ALTTRGEN_MASK | SIM_SOPT7_ADC0TRGSEL(15U);
  448. SIM->SOPT7 = tmp32;
  449.  
  450. TPM_Configuration(); /* Initialize TPM. */
  451. ADC16_Configuration(); /* Initialize ADC16. */
  452. DMAMUX_Configuration(); /* Initialize DMAMUX. */
  453. EDMA_Configuration(); /* Initialize EDMA. */
  454.  
  455. g_adcQueue = xQueueCreate(10U, 1U);
  456. if(g_adcQueue == NULL)
  457. {
  458. throwError(ERROR_QUEUE_CREATION_FAILURE);
  459. PRINTF("%s ADC!\r\n", getErrorMessage(ERROR_QUEUE_CREATION_FAILURE));
  460. return NULL;
  461. }
  462.  
  463. xResult = xTaskCreate(ADC_Task, "adc_task", TASK_STACKSIZE_ADC, NULL, TASK_PRIO_ADC, &xCreatedTask);
  464. if(xResult == pdPASS)
  465. {
  466. g_adcTaskHandle = xCreatedTask;
  467. xReturn = xCreatedTask;
  468. }
  469. else
  470. {
  471. throwError(ERROR_TASK_CREATION_FAILURE);
  472. PRINTF("%s ADC!\r\n", getErrorMessage(ERROR_TASK_CREATION_FAILURE));
  473. xReturn = NULL;
  474. }
  475. return xReturn;
  476. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement