1 /***********************************************************************************************************************
2 * Copyright [2015-2017] Renesas Electronics Corporation and/or its licensors. All Rights Reserved.
3 *
4 * This file is part of Renesas SynergyTM Software Package (SSP)
5 *
6 * The contents of this file (the "contents") are proprietary and confidential to Renesas Electronics Corporation
7 * and/or its licensors ("Renesas") and subject to statutory and contractual protections.
8 *
9 * This file is subject to a Renesas SSP license agreement. Unless otherwise agreed in an SSP license agreement with
10 * Renesas: 1) you may not use, copy, modify, distribute, display, or perform the contents; 2) you may not use any name
11 * or mark of Renesas for advertising or publicity purposes or in connection with your use of the contents; 3) RENESAS
12 * MAKES NO WARRANTY OR REPRESENTATIONS ABOUT THE SUITABILITY OF THE CONTENTS FOR ANY PURPOSE; THE CONTENTS ARE PROVIDED
13 * "AS IS" WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
14 * PARTICULAR PURPOSE, AND NON-INFRINGEMENT; AND 4) RENESAS SHALL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, OR
15 * CONSEQUENTIAL DAMAGES, INCLUDING DAMAGES RESULTING FROM LOSS OF USE, DATA, OR PROJECTS, WHETHER IN AN ACTION OF
16 * CONTRACT OR TORT, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE CONTENTS. Third-party contents
17 * included in this file may be subject to different terms.
18 **********************************************************************************************************************/
19
20 /**********************************************************************************************************************
21 * File Name : r_dtc.c
22 * Description : DTC implementation of the transfer interface.
23 **********************************************************************************************************************/
24
25 /***********************************************************************************************************************
26 * Includes
27 **********************************************************************************************************************/
28 #include <string.h>
29 #include "r_dtc.h"
30 #include "hw/hw_dtc_private.h"
31 #include "r_dtc_private_api.h"
32 #include "r_elc.h"
33
34 /***********************************************************************************************************************
35 * Macro definitions
36 **********************************************************************************************************************/
37 /** Driver ID (DTC in ASCII), used to identify Data Transfer Controller (DTC) configuration */
38 #define DTC_ID (0x44544300)
39
40 /** Macro for error logger. */
41 #ifndef DTC_ERROR_RETURN
42 /*LDRA_INSPECTED 77 S This macro does not work when surrounded by parentheses. */
43 #define DTC_ERROR_RETURN(a, err) SSP_ERROR_RETURN((a), (err),&g_module_name[0], &g_dtc_version)
44 #endif
45
46 /** Size of vector table is based on number of vectors defined in BSP. */
47 #define DTC_VECTOR_TABLE_SIZE (BSP_MAX_NUM_IRQn)
48
49 /** Compiler specific macro to specify vector table section. */
50 #ifndef DTC_CFG_VECTOR_TABLE_SECTION_NAME
51 #ifndef SUPPRESS_WARNING_DTC_CFG_VECTOR_TABLE_SECTION_NAME
52 #warning "DTC vector table is aligned on 1K boundary. Automatic placing could lead to memory holes."
53 #endif
54 #endif
55
56 /** Used to generate a compiler error (divided by 0 error) if the assertion fails. This is used in place of "#error"
57 * for expressions that cannot be evaluated by the preprocessor like sizeof(). */
58 /*LDRA_INSPECTED 340 S Using function like macro because inline function does not generate divided by 0 error. */
59 #define DTC_COMPILE_TIME_ASSERT(e) ((void) sizeof(char[1 - 2 * !(e)]))
60
61 #define DTC_PRV_MASK_ALIGN_2_BYTES (0x1U)
62 #define DTC_PRV_MASK_ALIGN_4_BYTES (0x3U)
63
64 /***********************************************************************************************************************
65 * Typedef definitions
66 **********************************************************************************************************************/
67
68 /***********************************************************************************************************************
69 * Private function prototypes
70 **********************************************************************************************************************/
71 static IRQn_Type dtc_irq_lookup(elc_event_t const event);
72 static void r_dtc_initialize_repeat_block_mode(transfer_cfg_t const * const p_cfg);
73 static ssp_err_t r_dtc_state_initialize(dtc_instance_ctrl_t * p_ctrl,transfer_cfg_t const * const p_cfg );
74 #if DTC_CFG_PARAM_CHECKING_ENABLE
75 static ssp_err_t r_dtc_parameter_check(dtc_instance_ctrl_t * p_ctrl,transfer_cfg_t const * const p_cfg );
76 static ssp_err_t r_dtc_block_reset_parameter_check(dtc_instance_ctrl_t * p_ctrl,uint16_t const length, uint16_t const num_transfers);
77 static ssp_err_t r_dtc_reset_parameter_check(dtc_instance_ctrl_t * p_ctrl,uint16_t const num_transfers);
78 static ssp_err_t r_dtc_enable_alignment_check(transfer_info_t * p_info);
79 #endif
80
81
82 /***********************************************************************************************************************
83 * ISR function prototypes
84 **********************************************************************************************************************/
85 void elc_software_event_isr(void);
86
87 /***********************************************************************************************************************
88 * Private global variables
89 **********************************************************************************************************************/
90 /** Name of module used by error logger macro */
91 #if BSP_CFG_ERROR_LOG != 0
92 static const char g_module_name[] = "dtc";
93 #endif
94
95 /** Stores initialization state to skip initialization in ::R_DTC_Open after the first call. */
96 static bool g_dtc_state_initialized = false;
97
98 /** Stores pointer to DTC base address. */
99 static R_DTC_Type * gp_dtc_regs = NULL;
100
101 /** Stores pointer to ICU base address. */
102 static R_ICU_Type * gp_icu_regs = NULL;
103
104 #ifdef DTC_CFG_VECTOR_TABLE_SECTION_NAME
105 #define DTC_SECTION_ATTRIBUTE BSP_PLACE_IN_SECTION_V2(DTC_CFG_VECTOR_TABLE_SECTION_NAME)
106 #else
107 #define DTC_SECTION_ATTRIBUTE
108 #endif
109 /*LDRA_INSPECTED 293 S Compiler specific attributes are the best way to define section and alignment of variable. */
110 /*LDRA_INSPECTED 219 S In the GCC compiler, section placement requires a GCC attribute, which starts with underscore. */
111 /*This variable is not a part of data section so it is not initialized here. It is being initialized to zero later in the code, before it is being used. */
112 /*LDRA_INSPECTED 57 D *//*LDRA_INSPECTED 57 D */
113 /*LDRA_INSPECTED 27 D variable is declared as static */
114 static transfer_info_t * gp_dtc_vector_table[BSP_VECTOR_TABLE_MAX_ENTRIES] BSP_ALIGN_VARIABLE_V2(1024) DTC_SECTION_ATTRIBUTE;
115
116 #if defined(__GNUC__)
117 /* This structure is affected by warnings from a GCC compiler bug. This pragma suppresses the warnings in this
118 * structure only.*/
119 /*LDRA_INSPECTED 69 S */
120 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
121 #endif
122 /** Version data structure used by error logger macro. */
123 static const ssp_version_t g_dtc_version =
124 {
125 .api_version_minor = TRANSFER_API_VERSION_MINOR,
126 .api_version_major = TRANSFER_API_VERSION_MAJOR,
127 .code_version_major = DTC_CODE_VERSION_MAJOR,
128 .code_version_minor = DTC_CODE_VERSION_MINOR,
129 };
130 #if defined(__GNUC__)
131 /* Restore warning settings for 'missing-field-initializers' to as specified on command line. */
132 /*LDRA_INSPECTED 69 S */
133 #pragma GCC diagnostic pop
134 #endif
135
136 /***********************************************************************************************************************
137 * Exported global variables
138 **********************************************************************************************************************/
139 /** DTC implementation of transfer API. */
140 /*LDRA_INSPECTED 27 D This structure must be accessible in user code. It cannot be static. */
141 const transfer_api_t g_transfer_on_dtc =
142 {
143 .open = R_DTC_Open,
144 .reset = R_DTC_Reset,
145 .infoGet = R_DTC_InfoGet,
146 .start = R_DTC_Start,
147 .stop = R_DTC_Stop,
148 .enable = R_DTC_Enable,
149 .disable = R_DTC_Disable,
150 .close = R_DTC_Close,
151 .versionGet = R_DTC_VersionGet,
152 .blockReset = R_DTC_BlockReset
153 };
154
155 /*******************************************************************************************************************//**
156 * @addtogroup DTC
157 * @{
158 **********************************************************************************************************************/
159
160 /***********************************************************************************************************************
161 * Functions
162 **********************************************************************************************************************/
163
164 /*******************************************************************************************************************//**
165 * @brief Set transfer data in the vector table and enable transfer in ICU. Implements transfer_api_t::open.
166 *
167 * @retval SSP_SUCCESS Successful open. Transfer is configured and will start when trigger occurs.
168 * @retval SSP_ERR_ASSERTION An input parameter is invalid.
169 * @retval SSP_ERR_IN_USE The BSP hardware lock for the DTC is not available, or the index for this IRQ in the
170 * DTC vector table is already configured.
171 * @retval SSP_ERR_HW_LOCKED DTC hardware resource is locked.
172 * @retval SSP_ERR_IRQ_BSP_DISABLED The IRQ associated with the activation source is not enabled in the BSP.
173 * @retval SSP_ERR_NOT_ENABLED Auto-enable was requested, but enable failed due to an invalid input parameter.
174 **********************************************************************************************************************/
R_DTC_Open(transfer_ctrl_t * const p_api_ctrl,transfer_cfg_t const * const p_cfg)175 ssp_err_t R_DTC_Open (transfer_ctrl_t * const p_api_ctrl,
176 transfer_cfg_t const * const p_cfg)
177 {
178 ssp_err_t err = SSP_SUCCESS;
179 /* Generate a compiler error if transfer_info_t and dtc_reg_t are not the same size. */
180 /*LDRA_INSPECTED 57 S No effect on runtime code, used for compiler error. */
181 DTC_COMPILE_TIME_ASSERT(sizeof(transfer_info_t) == sizeof(dtc_reg_t));
182
183 dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) p_api_ctrl;
184
185 err = r_dtc_state_initialize(p_ctrl,p_cfg);
186 DTC_ERROR_RETURN(SSP_SUCCESS == err, err);
187
188 /** Make sure the activation source is mapped in the ICU. */
189 IRQn_Type irq = dtc_irq_lookup(p_cfg->activation_source);
190 p_ctrl->trigger = HW_DTC_ICUEventGet(gp_icu_regs, irq);
191 DTC_ERROR_RETURN(SSP_INVALID_VECTOR != irq, SSP_ERR_IRQ_BSP_DISABLED);
192
193 /** Make sure the activation source is not already being used by the DTC. */
194 DTC_ERROR_RETURN(NULL == gp_dtc_vector_table[irq], SSP_ERR_IN_USE);
195 r_dtc_initialize_repeat_block_mode(p_cfg);
196
197 #if DTC_CFG_SOFTWARE_START_ENABLE
198 /** If p_callback is valid and trigger is set to ELC_EVENT_ELC_SOFTWARE_EVENT_0 or ELC_EVENT_ELC_SOFTWARE_EVENT_1,
199 * enable interrupts and store the p_callback in an array for access by ISR. */
200 if ((ELC_EVENT_ELC_SOFTWARE_EVENT_0 == p_ctrl->trigger) ||
201 (ELC_EVENT_ELC_SOFTWARE_EVENT_1 == p_ctrl->trigger))
202 {
203 p_ctrl->p_callback = p_cfg->p_callback;
204 p_ctrl->p_context = p_cfg->p_context;
205 if (NULL != p_cfg->p_callback)
206 {
207 ssp_vector_info_t * p_vector_info;
208 R_SSP_VectorInfoGet(irq, &p_vector_info);
209 *(p_vector_info->pp_ctrl) = p_ctrl;
210 NVIC_SetPriority(irq, p_cfg->irq_ipl);
211 R_BSP_IrqStatusClear(irq);
212 NVIC_ClearPendingIRQ(irq);
213 NVIC_EnableIRQ(irq);
214 }
215 }
216 #endif
217
218 /** Configure the DTC transfer. See the hardware manual for details. */
219 HW_DTC_ReadSkipEnableSet(gp_dtc_regs, DTC_READ_SKIP_DISABLED);
220 gp_dtc_vector_table[irq] = p_cfg->p_info;
221
222 /** Update internal variables. */
223 p_ctrl->irq = irq;
224 /** Mark driver as open by initializing it to "DTC" in its ASCII equivalent. */
225 p_ctrl->id = DTC_ID;
226
227 /** If auto_enable is true, enable transfer and ELC events if software start is used. */
228 if (p_cfg->auto_enable)
229 {
230 err = R_DTC_Enable(p_ctrl);
231 }
232
233 /** Enable read skip after all settings are complete. */
234 HW_DTC_ReadSkipEnableSet(gp_dtc_regs, DTC_READ_SKIP_ENABLED);
235
236 DTC_ERROR_RETURN(SSP_SUCCESS == err, SSP_ERR_NOT_ENABLED);
237
238 return SSP_SUCCESS;
239 } /* End of function R_DTC_Open */
240
241 /*******************************************************************************************************************//**
242 * @brief Reset transfer source, destination, and number of transfers. Implements transfer_api_t::reset.
243 *
244 * @retval SSP_SUCCESS Transfer reset successfully.
245 * @retval SSP_ERR_ASSERTION An input parameter is invalid.
246 * @retval SSP_ERR_NOT_OPEN Handle is not initialized. Call R_DTC_Open to initialize the control block.
247 * @retval SSP_ERR_NOT_ENABLED Transfer length must not be 0 for repeat and block mode, or enable failed due
248 * to an invalid input parameter:
249 * - Transfer source must not be NULL.
250 * - Transfer destination must not be NULL.
251 **********************************************************************************************************************/
R_DTC_Reset(transfer_ctrl_t * const p_api_ctrl,void const * volatile p_src,void * volatile p_dest,uint16_t const num_transfers)252 ssp_err_t R_DTC_Reset (transfer_ctrl_t * const p_api_ctrl,
253 void const * volatile p_src,
254 void * volatile p_dest,
255 uint16_t const num_transfers)
256 {
257 ssp_err_t err = SSP_SUCCESS;
258 dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) p_api_ctrl;
259 #if DTC_CFG_PARAM_CHECKING_ENABLE
260 err = r_dtc_reset_parameter_check(p_ctrl,num_transfers );
261 DTC_ERROR_RETURN(SSP_SUCCESS == err, err);
262 #endif
263
264 /** Disable transfers on this activation source. */
265 HW_ICU_DTCDisable(gp_icu_regs, p_ctrl->irq);
266
267 /** Disable read skip prior to modifying settings. It will be enabled later. */
268 HW_DTC_ReadSkipEnableSet(gp_dtc_regs, DTC_READ_SKIP_DISABLED);
269
270 /** Reset transfer based on input parameters. */
271 if (NULL != p_src)
272 {
273 gp_dtc_vector_table[p_ctrl->irq]->p_src = p_src;
274 }
275
276 if (NULL != p_dest)
277 {
278 gp_dtc_vector_table[p_ctrl->irq]->p_dest = p_dest;
279 }
280
281 if (TRANSFER_MODE_BLOCK == gp_dtc_vector_table[p_ctrl->irq]->mode)
282 {
283 gp_dtc_vector_table[p_ctrl->irq]->num_blocks = num_transfers;
284 }
285 else if (TRANSFER_MODE_NORMAL == gp_dtc_vector_table[p_ctrl->irq]->mode)
286 {
287 gp_dtc_vector_table[p_ctrl->irq]->length = num_transfers;
288 }
289 else /* (TRANSFER_MODE_REPEAT == gp_dtc_vector_table[p_ctrl->irq]->mode) */
290 {
291 /* Do nothing. */
292 }
293
294 /** Enables transfers on this activation source. */
295 err = R_DTC_Enable(p_ctrl);
296
297 /** Enable read skip after all settings are complete. */
298 HW_DTC_ReadSkipEnableSet(gp_dtc_regs, DTC_READ_SKIP_ENABLED);
299
300 DTC_ERROR_RETURN(SSP_SUCCESS == err, SSP_ERR_NOT_ENABLED);
301
302 return SSP_SUCCESS;
303 } /* End of function R_DTC_Reset */
304
305 /*******************************************************************************************************************//**
306 * @brief Start transfer. Implements transfer_api_t::start.
307 *
308 * @retval SSP_SUCCESS Transfer started successfully.
309 * @retval SSP_ERR_ASSERTION An input parameter is invalid.
310 * @retval SSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block.
311 * @retval SSP_ERR_UNSUPPORTED One of the following is invalid:
312 * - Handle was not configured for software activation.
313 * - Mode not set to TRANSFER_START_MODE_SINGLE.
314 * - DTC_SOFTWARE_START_ENABLE set to 0 (disabled) in ssp_cfg/driver/r_dtc_cfg.h.
315 **********************************************************************************************************************/
R_DTC_Start(transfer_ctrl_t * const p_api_ctrl,transfer_start_mode_t mode)316 ssp_err_t R_DTC_Start (transfer_ctrl_t * const p_api_ctrl,
317 transfer_start_mode_t mode)
318 {
319 dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) p_api_ctrl;
320 #if DTC_CFG_SOFTWARE_START_ENABLE
321 #if DTC_CFG_PARAM_CHECKING_ENABLE
322 /** Verify parameters are valid */
323 SSP_ASSERT(NULL != p_ctrl);
324 DTC_ERROR_RETURN(p_ctrl->id == DTC_ID, SSP_ERR_NOT_OPEN);
325 DTC_ERROR_RETURN(TRANSFER_START_MODE_SINGLE == mode, SSP_ERR_UNSUPPORTED);
326 DTC_ERROR_RETURN((ELC_EVENT_ELC_SOFTWARE_EVENT_0 == p_ctrl->trigger) ||
327 (ELC_EVENT_ELC_SOFTWARE_EVENT_1 == p_ctrl->trigger), SSP_ERR_UNSUPPORTED);
328 #else
329 SSP_PARAMETER_NOT_USED(mode);
330 #endif
331
332
333 /** Clear the interrupt status flag */
334 R_BSP_IrqStatusClear(p_ctrl->irq);
335
336 /** Generate a software event in the Event Link Controller */
337 if (ELC_EVENT_ELC_SOFTWARE_EVENT_0 == p_ctrl->trigger)
338 {
339 g_elc_on_elc.softwareEventGenerate(ELC_SOFTWARE_EVENT_0);
340 }
341 else
342 {
343 g_elc_on_elc.softwareEventGenerate(ELC_SOFTWARE_EVENT_1);
344 }
345
346 return SSP_SUCCESS;
347 #else
348 SSP_PARAMETER_NOT_USED(p_ctrl);
349 SSP_PARAMETER_NOT_USED(mode);
350 return SSP_ERR_UNSUPPORTED;
351 #endif
352 } /* End of function R_DTC_Start */
353
354 /*******************************************************************************************************************//**
355 * @brief Placeholder for unsupported stop function. Implements transfer_api_t::stop.
356 *
357 * @retval SSP_ERR_UNSUPPORTED DTC software start is not supported.
358 **********************************************************************************************************************/
R_DTC_Stop(transfer_ctrl_t * const p_ctrl)359 ssp_err_t R_DTC_Stop (transfer_ctrl_t * const p_ctrl)
360 {
361 /* This function isn't supported. It is defined only to implement a required function of transfer_api_t. */
362 /** Mark the input parameter as unused since this function isn't supported. */
363 SSP_PARAMETER_NOT_USED(p_ctrl);
364
365 return SSP_ERR_UNSUPPORTED;
366 } /* End of function R_DTC_Stop */
367
368 /*******************************************************************************************************************//**
369 * @brief Enable transfer and ELC events if they are used for software start. Implements transfer_api_t::enable.
370 *
371 * @retval SSP_SUCCESS Counter value written successfully.
372 * @retval SSP_ERR_ASSERTION An input parameter is invalid.
373 * @retval SSP_ERR_NOT_OPEN Handle is not initialized. Call R_DTC_Open to initialize the control block.
374 * @retval SSP_ERR_IRQ_BSP_DISABLED The IRQ associated with the p_ctrl is not enabled in the BSP.
375 **********************************************************************************************************************/
R_DTC_Enable(transfer_ctrl_t * const p_api_ctrl)376 ssp_err_t R_DTC_Enable (transfer_ctrl_t * const p_api_ctrl)
377 {
378 dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) p_api_ctrl;
379 #if DTC_CFG_PARAM_CHECKING_ENABLE
380 SSP_ASSERT(NULL != p_ctrl);
381 DTC_ERROR_RETURN(p_ctrl->id == DTC_ID, SSP_ERR_NOT_OPEN);
382 DTC_ERROR_RETURN(SSP_INVALID_VECTOR != (IRQn_Type)p_ctrl->irq, SSP_ERR_IRQ_BSP_DISABLED);
383 transfer_info_t * p_local_info = gp_dtc_vector_table[p_ctrl->irq];
384 SSP_ASSERT(NULL != p_local_info->p_dest);
385 SSP_ASSERT(NULL != p_local_info->p_src);
386
387 ssp_err_t err = r_dtc_enable_alignment_check(p_local_info);
388 DTC_ERROR_RETURN(SSP_SUCCESS == err, err);
389 #endif
390
391 /** Enable transfer. */
392 HW_ICU_DTCEnable(gp_icu_regs, p_ctrl->irq);
393
394 #if DTC_CFG_SOFTWARE_START_ENABLE
395 if ((NULL != p_ctrl->p_callback) && ((ELC_EVENT_ELC_SOFTWARE_EVENT_0 == p_ctrl->trigger) ||
396 (ELC_EVENT_ELC_SOFTWARE_EVENT_1 == p_ctrl->trigger)))
397 {
398 /** If this is a software event, enable the IRQ. */
399 NVIC_EnableIRQ(p_ctrl->irq);
400 }
401 #endif
402
403 return SSP_SUCCESS;
404 } /* End of function R_DTC_Enable */
405
406 /*******************************************************************************************************************//**
407 * @brief Disable transfer. Implements transfer_api_t::disable.
408 *
409 * @retval SSP_SUCCESS Counter value written successfully.
410 * @retval SSP_ERR_ASSERTION An input parameter is invalid.
411 * @retval SSP_ERR_NOT_OPEN Handle is not initialized. Call R_DTC_Open to initialize the control block.
412 **********************************************************************************************************************/
R_DTC_Disable(transfer_ctrl_t * const p_api_ctrl)413 ssp_err_t R_DTC_Disable (transfer_ctrl_t * const p_api_ctrl)
414 {
415 dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) p_api_ctrl;
416 #if DTC_CFG_PARAM_CHECKING_ENABLE
417 SSP_ASSERT(NULL != p_ctrl);
418 DTC_ERROR_RETURN(p_ctrl->id == DTC_ID, SSP_ERR_NOT_OPEN);
419 #endif
420
421 /** Disable transfer. */
422 HW_ICU_DTCDisable(gp_icu_regs, p_ctrl->irq);
423
424 #if DTC_CFG_SOFTWARE_START_ENABLE
425 if ((NULL != p_ctrl->p_callback) && ((ELC_EVENT_ELC_SOFTWARE_EVENT_0 == p_ctrl->trigger) ||
426 (ELC_EVENT_ELC_SOFTWARE_EVENT_1 == p_ctrl->trigger)))
427 {
428 /** If this is a software event, enable the IRQ. */
429 if (SSP_INVALID_VECTOR != p_ctrl->irq)
430 {
431 NVIC_DisableIRQ(p_ctrl->irq);
432 }
433 }
434 #endif
435
436 return SSP_SUCCESS;
437 } /* End of function R_DTC_Disable */
438
439 /*******************************************************************************************************************//**
440 * @brief Set driver specific information. Implements transfer_api_t::infoGet.
441 *
442 * @retval SSP_SUCCESS Counter value written successfully.
443 * @retval SSP_ERR_ASSERTION An input parameter is invalid.
444 * @retval SSP_ERR_NOT_OPEN Handle is not initialized. Call R_DTC_Open to initialize the control block.
445 **********************************************************************************************************************/
R_DTC_InfoGet(transfer_ctrl_t * const p_api_ctrl,transfer_properties_t * const p_info)446 ssp_err_t R_DTC_InfoGet (transfer_ctrl_t * const p_api_ctrl,
447 transfer_properties_t * const p_info)
448 {
449 dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) p_api_ctrl;
450 #if DTC_CFG_PARAM_CHECKING_ENABLE
451 SSP_ASSERT(NULL != p_ctrl);
452 DTC_ERROR_RETURN(p_ctrl->id == DTC_ID, SSP_ERR_NOT_OPEN);
453 SSP_ASSERT(NULL != p_info);
454 #endif
455
456 /** If a transfer is active, store it in p_in_progress. */
457 uint16_t status = HW_DTC_StatusGet(gp_dtc_regs);
458 p_info->in_progress = false;
459 if (status >> 15)
460 {
461 IRQn_Type irq = (IRQn_Type) (status & 0x00FF);
462 if (p_ctrl->irq == irq)
463 {
464 p_info->in_progress = true;
465 }
466 }
467
468 /** Transfer information for the activation source is taken from DTC vector table. */
469 transfer_info_t* p_dtc_transfer_info = gp_dtc_vector_table[p_ctrl->irq];
470 if (TRANSFER_MODE_BLOCK == p_dtc_transfer_info->mode)
471 {
472 p_info->transfer_length_remaining = p_dtc_transfer_info->num_blocks;
473 }
474 else
475 {
476 p_info->transfer_length_remaining = p_dtc_transfer_info->length;
477
478 /** Mask out the high byte in case of repeat transfer. */
479 if (TRANSFER_MODE_REPEAT == p_dtc_transfer_info->mode)
480 {
481 p_info->transfer_length_remaining &= 0x00FFU;
482 }
483 }
484
485 /** Store maximum transfer length. */
486 if (TRANSFER_MODE_NORMAL == gp_dtc_vector_table[p_ctrl->irq]->mode)
487 {
488 p_info->transfer_length_max = DTC_NORMAL_MAX_LENGTH;
489 }
490 else
491 {
492 p_info->transfer_length_max = DTC_REPEAT_BLOCK_MAX_LENGTH;
493 }
494
495 return SSP_SUCCESS;
496 } /* End of function R_DTC_InfoGet */
497
498 /*******************************************************************************************************************//**
499 * @brief Disables transfer in the ICU, then clears transfer data from the DTC vector table. Implements
500 * transfer_api_t::close.
501 *
502 * @retval SSP_SUCCESS Successful close.
503 * @retval SSP_ERR_ASSERTION An input parameter is invalid.
504 * @retval SSP_ERR_NOT_OPEN Handle is not initialized. Call R_DTC_Open to initialize the control block.
505 * @retval SSP_ERR_IRQ_BSP_DISABLED The IRQ associated with the p_ctrl is not enabled in the BSP.
506 **********************************************************************************************************************/
R_DTC_Close(transfer_ctrl_t * const p_api_ctrl)507 ssp_err_t R_DTC_Close (transfer_ctrl_t * const p_api_ctrl)
508 {
509 dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) p_api_ctrl;
510 ssp_err_t err = SSP_SUCCESS;
511
512 #if DTC_CFG_PARAM_CHECKING_ENABLE
513 SSP_ASSERT(NULL != p_ctrl);
514 DTC_ERROR_RETURN(p_ctrl->id == DTC_ID, SSP_ERR_NOT_OPEN);
515 #endif
516 DTC_ERROR_RETURN(SSP_INVALID_VECTOR != (IRQn_Type)p_ctrl->irq, SSP_ERR_IRQ_BSP_DISABLED);
517 /** Clear DTC enable bit in ICU. */
518 HW_ICU_DTCDisable(gp_icu_regs, p_ctrl->irq);
519
520 /** Clear pointer in vector table. */
521 gp_dtc_vector_table[p_ctrl->irq] = NULL;
522 p_ctrl->id = 0U;
523
524 #if DTC_CFG_SOFTWARE_START_ENABLE
525 if ((NULL != p_ctrl->p_callback) && ((ELC_EVENT_ELC_SOFTWARE_EVENT_0 == p_ctrl->trigger) ||
526 (ELC_EVENT_ELC_SOFTWARE_EVENT_1 == p_ctrl->trigger)))
527 {
528 /** If this is a software event, disable the IRQ. */
529 NVIC_DisableIRQ(p_ctrl->irq);
530 ssp_vector_info_t * p_vector_info;
531 R_SSP_VectorInfoGet(p_ctrl->irq, &p_vector_info);
532 *(p_vector_info->pp_ctrl) = NULL;
533 }
534 #endif
535
536 return err;
537 } /* End of function R_DTC_Close */
538
539 /*******************************************************************************************************************//**
540 * @brief Set driver version based on compile time macros. Implements transfer_api_t::versionGet.
541 *
542 * @retval SSP_SUCCESS Successful close.
543 * @retval SSP_ERR_ASSERTION An input parameter is invalid.
544 **********************************************************************************************************************/
R_DTC_VersionGet(ssp_version_t * const p_version)545 ssp_err_t R_DTC_VersionGet (ssp_version_t * const p_version)
546 {
547 #if DTC_CFG_PARAM_CHECKING_ENABLE
548 /** Verify parameters are valid */
549 SSP_ASSERT(NULL != p_version);
550 #endif
551
552 /** Set driver version based on compile time macros */
553 p_version->version_id = g_dtc_version.version_id;
554
555 return SSP_SUCCESS;
556 } /* End of function R_DTC_VersionGet */
557
558 /*******************************************************************************************************************//**
559 * @brief BlockReset transfer source, destination, length and number of transfers. Implements transfer_api_t::blockReset.
560 *
561 * @retval SSP_SUCCESS Transfer reset successfully.
562 * @retval SSP_ERR_ASSERTION An input parameter is invalid.
563 * @retval SSP_ERR_NOT_OPEN Handle is not initialized. Call R_DTC_Open to initialize the control block.
564 * @retval SSP_ERR_UNSUPPORTED If mode is other than Block Transfer Mode.
565 * @retval SSP_ERR_NOT_ENABLED Enable failed due to an invalid input parameter:
566 * - Transfer source must not be NULL.
567 * - Transfer destination must not be NULL.
568 **********************************************************************************************************************/
R_DTC_BlockReset(transfer_ctrl_t * const p_api_ctrl,void const * volatile p_src,void * volatile p_dest,uint16_t const length,transfer_size_t size,uint16_t const num_transfers)569 ssp_err_t R_DTC_BlockReset (transfer_ctrl_t * const p_api_ctrl,
570 void const * volatile p_src,
571 void * volatile p_dest,
572 uint16_t const length,
573 transfer_size_t size,
574 uint16_t const num_transfers)
575 {
576 ssp_err_t err = SSP_SUCCESS;
577 dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) p_api_ctrl;
578 #if DTC_CFG_PARAM_CHECKING_ENABLE
579 err = r_dtc_block_reset_parameter_check(p_ctrl,length,num_transfers );
580 DTC_ERROR_RETURN(SSP_SUCCESS == err, err);
581 #endif
582
583 /** Disable transfers on this activation source. */
584 HW_ICU_DTCDisable(gp_icu_regs, p_ctrl->irq);
585
586 /** Disable read skip prior to modifying settings. It will be enabled later. */
587 HW_DTC_ReadSkipEnableSet(gp_dtc_regs, DTC_READ_SKIP_DISABLED);
588
589 /** Reset transfer based on input parameters. */
590 if (NULL != p_src)
591 {
592 gp_dtc_vector_table[p_ctrl->irq]->p_src = p_src;
593 }
594
595 if (NULL != p_dest)
596 {
597 gp_dtc_vector_table[p_ctrl->irq]->p_dest = p_dest;
598 }
599
600 gp_dtc_vector_table[p_ctrl->irq]->num_blocks = num_transfers;
601 gp_dtc_vector_table[p_ctrl->irq]->length = length;
602 gp_dtc_vector_table[p_ctrl->irq]->size = size;
603
604 dtc_reg_t * p_reg = (dtc_reg_t *) gp_dtc_vector_table[p_ctrl->irq];
605 p_reg->CRA_b.CRAH = p_reg->CRA_b.CRAL;
606
607 /** Enables transfers on this activation source. */
608 err = R_DTC_Enable(p_ctrl);
609
610 /** Enable read skip after all settings are complete. */
611 HW_DTC_ReadSkipEnableSet(gp_dtc_regs, DTC_READ_SKIP_ENABLED);
612
613 DTC_ERROR_RETURN(SSP_SUCCESS == err, SSP_ERR_NOT_ENABLED);
614
615 return SSP_SUCCESS;
616 } /* End of function R_DTC_Reset */
617
618 /*******************************************************************************************************************//**
619 * @} (end addtogroup DTC)
620 **********************************************************************************************************************/
621
622 /*******************************************************************************************************************//**
623 * @brief Finds the IRQ associated with the requested ELC event.
624 *
625 * @return IRQ value IRQ matches with the requested ELC event.
626 * @return SSP_INVALID_VECTOR IRQ not matches with the requested ELC event.
627 **********************************************************************************************************************/
dtc_irq_lookup(elc_event_t const event)628 static IRQn_Type dtc_irq_lookup(elc_event_t const event)
629 {
630 for (IRQn_Type i = (IRQn_Type) 0; i < (IRQn_Type) BSP_VECTOR_TABLE_MAX_ENTRIES; i++)
631 {
632 if (event == HW_DTC_ICUEventGet(gp_icu_regs, i))
633 {
634 /* This IRQ is tied to the requested ELC event. Return this IRQ to be used as DTC trigger */
635 return i;
636 }
637 }
638
639 return SSP_INVALID_VECTOR;
640 }
641
642 /*******************************************************************************************************************//**
643 * @brief Interrupt called when transfer triggered from ELC software event is complete.
644 *
645 * Saves context if RTOS is used, calls callback if one was provided in the open function, and restores context if
646 * RTOS is used.
647 **********************************************************************************************************************/
elc_software_event_isr(void)648 void elc_software_event_isr(void)
649 {
650 SF_CONTEXT_SAVE
651
652 ssp_vector_info_t * p_vector_info = NULL;
653 R_SSP_VectorInfoGet(R_SSP_CurrentIrqGet(), &p_vector_info);
654 dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) *(p_vector_info->pp_ctrl);
655
656 /** Clear pending IRQ to make sure it doesn't fire again after exiting */
657 R_BSP_IrqStatusClear(R_SSP_CurrentIrqGet());
658
659 /** Call user p_callback */
660 if ((NULL != p_ctrl) && (NULL != p_ctrl->p_callback))
661 {
662 transfer_callback_args_t args;
663 args.p_context = p_ctrl->p_context;
664 p_ctrl->p_callback(&args);
665 }
666
667 SF_CONTEXT_RESTORE
668 }
669
670 /*******************************************************************************************************************//**
671 * @brief For repeat and block modes, copy the data from the initial length into the reload length.
672 *
673 * @param[in] p_cfg Pointer to configuration structure.
674 **********************************************************************************************************************/
r_dtc_initialize_repeat_block_mode(transfer_cfg_t const * const p_cfg)675 static void r_dtc_initialize_repeat_block_mode( transfer_cfg_t const * const p_cfg)
676 {
677 transfer_info_t * p_info_temp = p_cfg->p_info;
678 bool chain_mode_disable_flag = true;
679 do
680 {
681 if (TRANSFER_MODE_NORMAL != p_info_temp->mode)
682 {
683 dtc_reg_t * p_reg = (dtc_reg_t *) p_info_temp;
684 p_reg->CRA_b.CRAH = p_reg->CRA_b.CRAL;
685 }
686 if(TRANSFER_CHAIN_MODE_DISABLED != p_info_temp->chain_mode)
687 {
688 /* There should be more elements on the chain */
689 p_info_temp++;
690 }
691 else
692 {
693 /* No more elements on the chain */
694 chain_mode_disable_flag = false;
695 }
696 } while (chain_mode_disable_flag);
697 }
698
699 /*******************************************************************************************************************//**
700 * @brief For dtc state initialization.
701 *
702 * @param[in] p_ctrl Pointer to instance control structure.
703 * @param[in] p_cfg Pointer to configuration structure.
704 *
705 * @retval SSP_SUCCESS Successful open.
706 * @retval SSP_ERR_ASSERTION An input parameter is invalid.
707 * @retval SSP_ERR_IN_USE DTC resource is used.
708 * @retval SSP_ERR_HW_LOCKED DTC hardware resource is locked.
709 * @return See @ref Common_Error_Codes or functions called by this function for other possible
710 * return codes. This function calls:
711 * * fmi_api_t::productFeatureGet
712 *
713 **********************************************************************************************************************/
r_dtc_state_initialize(dtc_instance_ctrl_t * p_ctrl,transfer_cfg_t const * const p_cfg)714 static ssp_err_t r_dtc_state_initialize(dtc_instance_ctrl_t * p_ctrl,transfer_cfg_t const * const p_cfg )
715 {
716 ssp_err_t err = SSP_SUCCESS;
717 #if DTC_CFG_PARAM_CHECKING_ENABLE
718 SSP_ASSERT(NULL != p_ctrl);
719 SSP_ASSERT(NULL != p_cfg);
720 SSP_ASSERT(NULL != p_cfg->p_info);
721 err = r_dtc_parameter_check(p_ctrl,p_cfg);
722 DTC_ERROR_RETURN(SSP_SUCCESS == err, err);
723 #endif
724 SSP_PARAMETER_NOT_USED(p_ctrl);
725 SSP_PARAMETER_NOT_USED(p_cfg);
726 /** DTC requires a one time initialization. This will be handled only the first time this function
727 * is called. This initialization:
728 * -# Acquires the BSP hardware lock for the DTC to keep this section thread safe and prevent use of
729 * this driver if another driver has locked the DTC block.
730 * -# Stores the register base addresses for DTC and ICU.
731 * -# Powers on the DTC block.
732 * -# Initializes the vector table to NULL pointers.
733 * -# Sets the vector table base address.
734 * -# Enables DTC transfers. */
735 if (!g_dtc_state_initialized)
736 {
737 ssp_feature_t ssp_feature = {{(ssp_ip_t) 0U}};
738 ssp_feature.channel = 0U;
739 ssp_feature.unit = 0U;
740 ssp_feature.id = SSP_IP_DTC;
741 fmi_feature_info_t info = {0};
742 err = g_fmi_on_fmi.productFeatureGet(&ssp_feature, &info);
743 DTC_ERROR_RETURN(SSP_SUCCESS == err, err);
744 gp_dtc_regs = (R_DTC_Type *) info.ptr;
745 ssp_err_t bsp_err = R_BSP_HardwareLock(&ssp_feature);
746 DTC_ERROR_RETURN(SSP_SUCCESS == bsp_err, SSP_ERR_HW_LOCKED);
747 R_BSP_ModuleStart(&ssp_feature);
748 memset(&gp_dtc_vector_table, 0U, BSP_VECTOR_TABLE_MAX_ENTRIES * sizeof(transfer_info_t *));
749 HW_DTC_VectorTableAddressSet(gp_dtc_regs, &gp_dtc_vector_table);
750 HW_DTC_StartStop(gp_dtc_regs, DTC_START);
751 ssp_feature.id = SSP_IP_ICU;
752 g_fmi_on_fmi.productFeatureGet(&ssp_feature, &info);
753 gp_icu_regs = (R_ICU_Type *) info.ptr;
754 g_dtc_state_initialized = true;
755 }
756
757 return err;
758 }
759
760 #if DTC_CFG_PARAM_CHECKING_ENABLE
761 /*******************************************************************************************************************//**
762 * @brief For dtc parameter checking.
763 *
764 * @param[in] p_ctrl Pointer to instance control structure.
765 * @param[in] p_cfg Pointer to configuration structure.
766 *
767 * @retval SSP_SUCCESS Successful open.
768 * @retval SSP_ERR_ASSERTION An input parameter is invalid.
769 * @retval SSP_ERR_IN_USE DTC resource is used.
770 **********************************************************************************************************************/
r_dtc_parameter_check(dtc_instance_ctrl_t * p_ctrl,transfer_cfg_t const * const p_cfg)771 static ssp_err_t r_dtc_parameter_check(dtc_instance_ctrl_t * p_ctrl,transfer_cfg_t const * const p_cfg )
772 {
773 if (TRANSFER_MODE_NORMAL != p_cfg->p_info->mode)
774 {
775 SSP_ASSERT(p_cfg->p_info->length <= DTC_REPEAT_BLOCK_MAX_LENGTH);
776 }
777 DTC_ERROR_RETURN(p_ctrl->id != DTC_ID, SSP_ERR_IN_USE);
778
779 return SSP_SUCCESS;
780 }
781
782 /*******************************************************************************************************************//**
783 * @brief For dtc reset parameter checking.
784 *
785 * @param[in] p_ctrl Pointer to instance control structure.
786 * @param[in] num_transfers Number of times to transfer.
787 *
788 * @retval SSP_SUCCESS Successful open.
789 * @retval SSP_ERR_ASSERTION An input parameter is invalid.
790 * @retval SSP_ERR_NOT_ENABLED Transfer length must not be 0 for repeat and block mode.
791 * @retval SSP_ERR_NOT_OPEN Handle is not initialized. Call R_DTC_Open to initialize the control block.
792 **********************************************************************************************************************/
r_dtc_reset_parameter_check(dtc_instance_ctrl_t * p_ctrl,uint16_t const num_transfers)793 static ssp_err_t r_dtc_reset_parameter_check(dtc_instance_ctrl_t * p_ctrl, uint16_t const num_transfers)
794 {
795 SSP_ASSERT(NULL != p_ctrl);
796 if (TRANSFER_MODE_NORMAL != gp_dtc_vector_table[p_ctrl->irq]->mode)
797 {
798 DTC_ERROR_RETURN(0 != num_transfers, SSP_ERR_NOT_ENABLED);
799 }
800 DTC_ERROR_RETURN(p_ctrl->id == DTC_ID, SSP_ERR_NOT_OPEN);
801 if (TRANSFER_MODE_BLOCK == gp_dtc_vector_table[p_ctrl->irq]->mode)
802 {
803 SSP_ASSERT(0 != gp_dtc_vector_table[p_ctrl->irq]->length);
804 }
805
806 return SSP_SUCCESS;
807 }
808
809 /*******************************************************************************************************************//**
810 * @brief For dtc block reset parameter checking.
811 * @param[in] p_ctrl Pointer to instance control structure.
812 * @param[in] length Length of each transfer.
813 * @param[in] num_transfers Number of times to transfer.
814 *
815 * @retval SSP_SUCCESS Successful open.
816 * @retval SSP_ERR_ASSERTION An input parameter is invalid.
817 * @retval SSP_ERR_UNSUPPORTED If mode is other than Block Transfer Mode.
818 * @retval SSP_ERR_NOT_OPEN Handle is not initialized. Call R_DTC_Open to initialize the control block.
819 **********************************************************************************************************************/
r_dtc_block_reset_parameter_check(dtc_instance_ctrl_t * p_ctrl,uint16_t const length,uint16_t const num_transfers)820 static ssp_err_t r_dtc_block_reset_parameter_check(dtc_instance_ctrl_t * p_ctrl,uint16_t const length, uint16_t const num_transfers)
821 {
822 SSP_ASSERT(NULL != p_ctrl);
823 DTC_ERROR_RETURN(TRANSFER_MODE_BLOCK == gp_dtc_vector_table[p_ctrl->irq]->mode, SSP_ERR_UNSUPPORTED);
824 SSP_ASSERT(0 != num_transfers);
825 SSP_ASSERT(0 != length);
826 DTC_ERROR_RETURN(p_ctrl->id == DTC_ID, SSP_ERR_NOT_OPEN);
827
828 return SSP_SUCCESS;
829 }
830
831 /*******************************************************************************************************************//**
832 * Alignment checking for source and destination pointers.
833 *
834 * @param[in] p_info Pointer to DTC descriptor block.
835 *
836 * @retval SSP_SUCCESS Alignment on source and destination pointers is valid.
837 * @retval SSP_ERR_ASSERTION Alignment on source and destination pointers is invalid.
838 **********************************************************************************************************************/
r_dtc_enable_alignment_check(transfer_info_t * p_info)839 static ssp_err_t r_dtc_enable_alignment_check(transfer_info_t * p_info)
840 {
841 if (TRANSFER_SIZE_2_BYTE == p_info->size)
842 {
843 SSP_ASSERT(0U == ((uint32_t) p_info->p_dest & DTC_PRV_MASK_ALIGN_2_BYTES));
844 SSP_ASSERT(0U == ((uint32_t) p_info->p_src & DTC_PRV_MASK_ALIGN_2_BYTES));
845 }
846 if (TRANSFER_SIZE_4_BYTE == p_info->size)
847 {
848 SSP_ASSERT(0U == ((uint32_t) p_info->p_dest & DTC_PRV_MASK_ALIGN_4_BYTES));
849 SSP_ASSERT(0U == ((uint32_t) p_info->p_src & DTC_PRV_MASK_ALIGN_4_BYTES));
850 }
851
852 return SSP_SUCCESS;
853 }
854 #endif
855