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