xref: /btstack/port/renesas-tb-s1ja-cc256x/template/btstack_example/synergy/ssp/src/driver/r_dtc/r_dtc.c (revision 3b5c872a8c45689e8cc17891f01530f5aa5e911c)
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