drv_dcmi.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020-07-27 thread-liu the first version
  9. */
  10. #include "board.h"
  11. #if defined(BSP_USING_DCMI)
  12. #include <drv_dcmi.h>
  13. #define DRV_DEBUG
  14. #define LOG_TAG "drv.dcmi"
  15. #include <drv_log.h>
  16. struct stm32_dcmi
  17. {
  18. DCMI_HandleTypeDef DCMI_Handle;
  19. struct rt_dcmi_device dev;
  20. };
  21. static struct stm32_dcmi rt_dcmi = {0};
  22. DMA_HandleTypeDef hdma_dcmi;
  23. static void rt_hw_dcmi_dma_init(void)
  24. {
  25. __HAL_RCC_DMA2_CLK_ENABLE();
  26. hdma_dcmi.Instance = DMA2_Stream1;
  27. hdma_dcmi.Init.Request = DMA_REQUEST_DCMI;
  28. hdma_dcmi.Init.Direction = DMA_PERIPH_TO_MEMORY;
  29. hdma_dcmi.Init.PeriphInc = DMA_PINC_DISABLE;
  30. hdma_dcmi.Init.MemInc = DMA_MINC_ENABLE;
  31. hdma_dcmi.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
  32. hdma_dcmi.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
  33. hdma_dcmi.Init.Mode = DMA_CIRCULAR;
  34. hdma_dcmi.Init.Priority = DMA_PRIORITY_HIGH;
  35. hdma_dcmi.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
  36. hdma_dcmi.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
  37. hdma_dcmi.Init.MemBurst = DMA_MBURST_SINGLE;
  38. hdma_dcmi.Init.PeriphBurst = DMA_PBURST_SINGLE;
  39. HAL_DMA_DeInit(&hdma_dcmi);
  40. HAL_DMA_Init(&hdma_dcmi);
  41. __HAL_LINKDMA(&rt_dcmi.DCMI_Handle, DMA_Handle, hdma_dcmi);
  42. HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 0x00, 0x00);
  43. HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);;
  44. }
  45. void rt_hw_dcmi_dma_config(rt_uint32_t dst_addr1, rt_uint32_t dst_addr2, rt_uint32_t len)
  46. {
  47. __HAL_UNLOCK(&hdma_dcmi);
  48. HAL_DMAEx_MultiBufferStart(&hdma_dcmi, (rt_uint32_t)&DCMI->DR, dst_addr1, dst_addr2, len);
  49. __HAL_DMA_ENABLE_IT(&hdma_dcmi, DMA_IT_TC);
  50. }
  51. static rt_err_t rt_hw_dcmi_init(DCMI_HandleTypeDef *device)
  52. {
  53. RT_ASSERT(device != RT_NULL);
  54. device->Instance = DCMI;
  55. device->Init.SynchroMode = DCMI_SYNCHRO_HARDWARE;
  56. device->Init.PCKPolarity = DCMI_PCKPOLARITY_RISING;
  57. device->Init.VSPolarity = DCMI_VSPOLARITY_LOW;
  58. device->Init.HSPolarity = DCMI_HSPOLARITY_LOW;
  59. device->Init.CaptureRate = DCMI_CR_ALL_FRAME;
  60. device->Init.ExtendedDataMode = DCMI_EXTEND_DATA_8B;
  61. device->Init.JPEGMode = DCMI_JPEG_ENABLE;
  62. device->Init.ByteSelectMode = DCMI_BSM_ALL;
  63. device->Init.ByteSelectStart = DCMI_OEBS_ODD;
  64. device->Init.LineSelectMode = DCMI_LSM_ALL;
  65. device->Init.LineSelectStart = DCMI_OELS_ODD;
  66. if (HAL_DCMI_Init(device) != HAL_OK)
  67. {
  68. LOG_E("dcmi init error!");
  69. return RT_ERROR;
  70. }
  71. DCMI->IER = 0x0;
  72. __HAL_DCMI_ENABLE_IT(device, DCMI_IT_FRAME);
  73. __HAL_DCMI_ENABLE(device);
  74. return RT_EOK;
  75. }
  76. void DCMI_IRQHandler(void)
  77. {
  78. /* enter interrupt */
  79. rt_interrupt_enter();
  80. HAL_DCMI_IRQHandler(&rt_dcmi.DCMI_Handle);
  81. /* leave interrupt */
  82. rt_interrupt_leave();
  83. }
  84. void DCMI_Start(void)
  85. {
  86. __HAL_DMA_ENABLE(&hdma_dcmi);
  87. DCMI->CR |= DCMI_CR_CAPTURE;
  88. }
  89. void DCMI_Stop(void)
  90. {
  91. DCMI->CR &= ~(DCMI_CR_CAPTURE);
  92. while (DCMI->CR & 0x01);
  93. __HAL_DMA_DISABLE(&hdma_dcmi);
  94. }
  95. /* Capture a frame of the image */
  96. void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi)
  97. {
  98. extern void camera_frame_data_process(void);
  99. /* enter interrupt */
  100. rt_interrupt_enter();
  101. /* move frame data to buffer */
  102. camera_frame_data_process();
  103. __HAL_DCMI_ENABLE_IT(&rt_dcmi.DCMI_Handle, DCMI_IT_FRAME);
  104. /* leave interrupt */
  105. rt_interrupt_leave();
  106. }
  107. void DMA2_Stream1_IRQHandler(void)
  108. {
  109. extern void camera_dma_data_process(void);
  110. /* enter interrupt */
  111. rt_interrupt_enter();
  112. if (__HAL_DMA_GET_FLAG(&hdma_dcmi, DMA_FLAG_TCIF1_5) != RESET)
  113. {
  114. __HAL_DMA_CLEAR_FLAG(&hdma_dcmi, DMA_FLAG_TCIF1_5);
  115. /* move dma data to buffer */
  116. camera_dma_data_process();
  117. }
  118. /* leave interrupt */
  119. rt_interrupt_leave();
  120. }
  121. static rt_err_t rt_dcmi_init(rt_device_t dev)
  122. {
  123. RT_ASSERT(dev != RT_NULL);
  124. rt_err_t result = RT_EOK;
  125. result = rt_hw_dcmi_init(&rt_dcmi.DCMI_Handle);
  126. if (result != RT_EOK)
  127. {
  128. return result;
  129. }
  130. rt_hw_dcmi_dma_init();
  131. return result;
  132. }
  133. static rt_err_t rt_dcmi_open(rt_device_t dev, rt_uint16_t oflag)
  134. {
  135. RT_ASSERT(dev != RT_NULL);
  136. return RT_EOK;
  137. }
  138. static rt_err_t rt_dcmi_close(rt_device_t dev)
  139. {
  140. RT_ASSERT(dev != RT_NULL);
  141. return RT_EOK;
  142. }
  143. static rt_err_t rt_dcmi_control(rt_device_t dev, int cmd, void *args)
  144. {
  145. RT_ASSERT(dev != RT_NULL);
  146. return RT_EOK;
  147. }
  148. static rt_size_t rt_dcmi_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  149. {
  150. RT_ASSERT(dev != RT_NULL);
  151. return RT_EOK;
  152. }
  153. static rt_size_t rt_dcmi_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  154. {
  155. RT_ASSERT(dev != RT_NULL);
  156. return RT_EOK;
  157. }
  158. int dcmi_init(void)
  159. {
  160. rt_dcmi.dev.parent.type = RT_Device_Class_Miscellaneous;
  161. rt_dcmi.dev.parent.init = rt_dcmi_init;
  162. rt_dcmi.dev.parent.open = rt_dcmi_open;
  163. rt_dcmi.dev.parent.close = rt_dcmi_close;
  164. rt_dcmi.dev.parent.read = rt_dcmi_read;
  165. rt_dcmi.dev.parent.write = rt_dcmi_write;
  166. rt_dcmi.dev.parent.control = rt_dcmi_control;
  167. rt_dcmi.dev.parent.user_data = RT_NULL;
  168. rt_device_register(&rt_dcmi.dev.parent, "dcmi", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
  169. LOG_I("dcmi init success!");
  170. return RT_EOK;
  171. }
  172. INIT_BOARD_EXPORT(dcmi_init);
  173. #endif