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