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