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