• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2   ****************************************************************************************
3   * @file    app_dma.c
4   * @author  BLE Driver Team
5   * @brief   HAL APP module driver.
6   ****************************************************************************************
7   * @attention
8   #####Copyright (c) 2019 GOODIX
9    All rights reserved.
10 
11    Redistribution and use in source and binary forms, with or without
12    modification, are permitted provided that the following conditions are met:
13    * Redistributions of source code must retain the above copyright
14     notice, this list of conditions and the following disclaimer.
15    * Redistributions in binary form must reproduce the above copyright
16      notice, this list of conditions and the following disclaimer in the
17      documentation and/or other materials provided with the distribution.
18    * Neither the name of GOODIX nor the names of its contributors may be used
19      to endorse or promote products derived from this software without
20      specific prior written permission.
21 
22    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25    ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
26    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32    POSSIBILITY OF SUCH DAMAGE.
33   ****************************************************************************************
34   */
35 
36 /*
37  * INCLUDE FILES
38  *****************************************************************************************
39  */
40 #include <string.h>
41 #include <stdbool.h>
42 #include "app_pwr_mgmt.h"
43 #include "platform_sdk.h"
44 #include "app_dma.h"
45 
46 /*
47  * DEFINES
48  *****************************************************************************************
49  */
50 #define DMA_HANDLE_MAX            8
51 
52 /*
53  * STRUCT DEFINE
54  *****************************************************************************************
55  */
56 
57 /**@brief App dma state types. */
58 typedef enum {
59     APP_DMA_INVALID = 0,
60     APP_DMA_ACTIVITY,
61 #ifdef APP_DRIVER_WAKEUP_CALL_FUN
62     APP_DMA_SLEEP,
63 #endif
64 } app_dma_state_t;
65 
66 struct dma_env_t {
67     app_dma_state_t       dma_state;
68     dma_handle_t          handle;
69     app_dma_evt_handler_t evt_handler;
70 };
71 
72 /*
73  * LOCAL FUNCTION DECLARATION
74  *****************************************************************************************
75  */
76 static bool dma_prepare_for_sleep(void);
77 static void dma_sleep_canceled(void);
78 static void dma_wake_up_ind(void);
79 
80 /*
81  * LOCAL VARIABLE DEFINITIONS
82  *****************************************************************************************
83  */
84 static bool             s_sleep_cb_registered_flag = false;
85 static struct dma_env_t s_dma_env[DMA_HANDLE_MAX];
86 static int16_t          s_dma_pwr_id;
87 
88 static const app_sleep_callbacks_t dma_sleep_cb = {
89     .app_prepare_for_sleep  = dma_prepare_for_sleep,
90     .app_sleep_canceled     = dma_sleep_canceled,
91     .app_wake_up_ind        = dma_wake_up_ind,
92 };
93 
94 /*
95  * LOCAL FUNCTION DEFINITIONS
96  *****************************************************************************************
97  */
dma_prepare_for_sleep(void)98 static bool dma_prepare_for_sleep(void)
99 {
100     hal_dma_state_t state;
101 
102     for (uint8_t i = 0; i < DMA_HANDLE_MAX; i++) {
103         if (s_dma_env[i].dma_state == APP_DMA_ACTIVITY) {
104             state = hal_dma_get_state(&s_dma_env[i].handle);
105             if ((state != HAL_DMA_STATE_RESET) && (state != HAL_DMA_STATE_READY)) {
106                 return false;
107             }
108             hal_dma_suspend_reg(&s_dma_env[i].handle);
109 #ifdef APP_DRIVER_WAKEUP_CALL_FUN
110             s_dma_env[i].dma_state = APP_DMA_SLEEP;
111 #endif
112         }
113     }
114 
115     return true;
116 }
117 
dma_sleep_canceled(void)118 static void dma_sleep_canceled(void)
119 {
120 }
121 
dma_wake_up_ind(void)122 SECTION_RAM_CODE static void dma_wake_up_ind(void)
123 {
124 #ifndef APP_DRIVER_WAKEUP_CALL_FUN
125     bool find = false;
126 
127     for (uint8_t i = 0; i < DMA_HANDLE_MAX; i++) {
128         if (s_dma_env[i].dma_state == APP_DMA_ACTIVITY) {
129             hal_dma_resume_reg(&s_dma_env[i].handle);
130             find = true;
131         }
132     }
133 
134     if (find) {
135         hal_nvic_clear_pending_irq(DMA_IRQn);
136         hal_nvic_enable_irq(DMA_IRQn);
137     }
138 #endif
139 }
140 
141 #ifdef APP_DRIVER_WAKEUP_CALL_FUN
dma_wake_up(int16_t id)142 void dma_wake_up(int16_t id)
143 {
144     if (id<0 || id >= DMA_HANDLE_MAX) {
145         return;
146     }
147 
148     if (s_dma_env[id].dma_state == APP_DMA_SLEEP) {
149         hal_dma_resume_reg(&s_dma_env[id].handle);
150         s_dma_env[id].dma_state = APP_DMA_ACTIVITY;
151 
152         if (!NVIC_GetEnableIRQ(DMA_IRQn)) {
153             hal_nvic_clear_pending_irq(DMA_IRQn);
154             hal_nvic_enable_irq(DMA_IRQn);
155         }
156     }
157 }
158 #endif
159 
160 /*
161  * GLOBAL FUNCTION DEFINITIONS
162  ****************************************************************************************
163  */
dma_tfr_callback(struct _dma_handle * hdma)164 void dma_tfr_callback(struct _dma_handle *hdma)
165 {
166     uint8_t i;
167 
168     for (i = 0; i < DMA_HANDLE_MAX; i++) {
169         if ((s_dma_env[i].dma_state == APP_DMA_ACTIVITY) &&
170                 (s_dma_env[i].handle.channel == hdma->channel)) {
171             if (s_dma_env[i].evt_handler != NULL) {
172                 s_dma_env[i].evt_handler(APP_DMA_EVT_TFR);
173             }
174             break;
175         }
176     }
177 }
178 
dma_err_callback(struct _dma_handle * hdma)179 void dma_err_callback(struct _dma_handle * hdma)
180 {
181     uint8_t i;
182 
183     for (i = 0; i < DMA_HANDLE_MAX; i++) {
184         if ((s_dma_env[i].dma_state == APP_DMA_ACTIVITY) &&
185                 (s_dma_env[i].handle.channel == hdma->channel)) {
186             if (s_dma_env[i].evt_handler != NULL) {
187                 s_dma_env[i].evt_handler(APP_DMA_EVT_ERROR);
188             }
189             break;
190         }
191     }
192 }
193 
194 
dma_handle_config(uint8_t * p_i,int16_t * p_id,app_dma_params_t * p_params)195 static void dma_handle_config(uint8_t *p_i, int16_t *p_id, app_dma_params_t *p_params)
196 {
197     GLOBAL_EXCEPTION_DISABLE();
198     for (*p_i = 0; (*p_i) < DMA_HANDLE_MAX; (*p_i)++) {
199         if (s_dma_env[*p_i].dma_state == APP_DMA_INVALID || \
200             s_dma_env[*p_i].handle.channel == p_params->channel_number) {
201             if (HAL_DMA_STATE_BUSY == s_dma_env[*p_i].handle.state) {
202                 *p_i = DMA_HANDLE_MAX;
203                 break;
204             } else {
205                 *p_id = *p_i;
206                 s_dma_env[*p_i].dma_state = APP_DMA_ACTIVITY;
207                 break;
208             }
209         }
210     }
211     GLOBAL_EXCEPTION_ENABLE();
212 }
213 
app_dma_init(app_dma_params_t * p_params,app_dma_evt_handler_t evt_handler)214 int16_t app_dma_init(app_dma_params_t *p_params, app_dma_evt_handler_t evt_handler)
215 {
216     uint8_t      i  = 0;
217     int16_t     id = -1;
218     hal_status_t status = HAL_ERROR;
219 
220     if (p_params != NULL) {
221         if (!IS_DMA_ALL_INSTANCE(p_params->channel_number)) {
222             return -1;
223         }
224 
225         dma_handle_config(&i, &id, p_params);
226 
227         if (i < DMA_HANDLE_MAX) {
228             if (s_sleep_cb_registered_flag == false) { // register sleep callback
229                 s_sleep_cb_registered_flag = true;
230                 s_dma_pwr_id = pwr_register_sleep_cb(&dma_sleep_cb, APP_DRIVER_DMA_WAPEUP_PRIORITY);
231             }
232             s_dma_env[i].handle.channel = p_params->channel_number;
233             memcpy_s(&s_dma_env[i].handle.init, sizeof(s_dma_env[i].handle.init), &p_params->init, sizeof(dma_init_t));
234             s_dma_env[i].handle.xfer_tfr_callback   = dma_tfr_callback;
235             s_dma_env[i].handle.xfer_error_callback = dma_err_callback;
236             s_dma_env[i].handle.xfer_abort_callback = NULL;
237             s_dma_env[i].evt_handler = evt_handler;
238 
239             hal_nvic_clear_pending_irq(DMA_IRQn);
240             hal_nvic_enable_irq(DMA_IRQn);
241             status = hal_dma_init(&s_dma_env[i].handle);
242         }
243     }
244 
245     if (HAL_OK != status) {
246         id = -1;
247     }
248 
249     return id;
250 }
251 
252 
app_dma_deinit(int16_t id)253 uint16_t app_dma_deinit(int16_t id)
254 {
255     uint8_t i;
256 
257     if ((id < 0) || (id >= DMA_HANDLE_MAX) || (s_dma_env[id].dma_state == APP_DMA_INVALID)) {
258         return APP_DRV_ERR_INVALID_ID;
259     }
260 
261     GLOBAL_EXCEPTION_DISABLE();
262     hal_dma_deinit(&s_dma_env[id].handle);
263     s_dma_env[id].dma_state = APP_DMA_INVALID;
264     s_dma_env[id].handle.channel = (dma_channel_t)(-1);
265 
266     for (i = 0; i < DMA_HANDLE_MAX; i++) {
267         if (s_dma_env[i].dma_state == APP_DMA_ACTIVITY) {
268             break;
269         }
270     }
271 
272     if (i == DMA_HANDLE_MAX) {
273         pwr_unregister_sleep_cb(s_dma_pwr_id);
274         s_sleep_cb_registered_flag = false;
275         hal_nvic_disable_irq(DMA_IRQn);
276     }
277     GLOBAL_EXCEPTION_ENABLE();
278 
279     return APP_DRV_SUCCESS;
280 }
281 
app_dma_get_handle(int16_t id)282 dma_handle_t *app_dma_get_handle(int16_t id)
283 {
284     if (id < 0 || id >= DMA_HANDLE_MAX || s_dma_env[id].dma_state == APP_DMA_INVALID) {
285         return NULL;
286     }
287 
288 #ifdef APP_DRIVER_WAKEUP_CALL_FUN
289     dma_wake_up(id);
290 #endif
291 
292     return &s_dma_env[id].handle;
293 }
294 
app_dma_start(int16_t id,uint32_t src_address,uint32_t dst_address,uint32_t data_length)295 uint16_t app_dma_start(int16_t id, uint32_t src_address, uint32_t dst_address, uint32_t data_length)
296 {
297     hal_status_t status = HAL_ERROR;
298 
299     if (id < 0 || id >= DMA_HANDLE_MAX || s_dma_env[id].dma_state == APP_DMA_INVALID) {
300         return APP_DRV_ERR_INVALID_PARAM;
301     }
302 
303 #ifdef APP_DRIVER_WAKEUP_CALL_FUN
304     dma_wake_up(id);
305 #endif
306 
307     status = hal_dma_start_it(&s_dma_env[id].handle, src_address, dst_address, data_length);
308     if (HAL_OK != status) {
309         return (uint16_t)status;
310     }
311 
312     return APP_DRV_SUCCESS;
313 }
314 
DMA_IRQHandler(void)315 SECTION_RAM_CODE void DMA_IRQHandler(void)
316 {
317 #if FLASH_PROTECT_PRIORITY
318     platform_interrupt_protection_push();
319 #endif
320     uint8_t i;
321     for (i = 0; i < DMA_HANDLE_MAX; i++) {
322         if (s_dma_env[i].dma_state == APP_DMA_ACTIVITY) {
323             hal_dma_irq_handler(&s_dma_env[i].handle);
324         }
325     }
326 #if FLASH_PROTECT_PRIORITY
327     platform_interrupt_protection_pop();
328 #endif
329 }
330 
331