1 /*
2 * Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /***********************************************************************************************************************
8 * Includes
9 **********************************************************************************************************************/
10 #include <string.h>
11 #include "r_dtc.h"
12
13 /***********************************************************************************************************************
14 * Macro definitions
15 **********************************************************************************************************************/
16
17 /** Driver ID (DTC in ASCII), used to identify Data Transfer Controller (DTC) configuration */
18 #define DTC_OPEN (0x44544300)
19
20 /** Size of vector table is based on number of vectors defined in BSP. */
21 #define DTC_VECTOR_TABLE_ENTRIES (BSP_ICU_VECTOR_MAX_ENTRIES)
22
23 /** The size of transfer_info_t is defined in the Hardware Manual therefore it must be 16 bytes. */
24 #define DTC_TRANSFER_INFO_SIZE (16U)
25
26 /* Compiler specific macro to specify vector table section. */
27 #ifndef DTC_CFG_VECTOR_TABLE_SECTION_NAME
28 #define DTC_SECTION_ATTRIBUTE
29 #ifndef SUPPRESS_WARNING_DTC_CFG_VECTOR_TABLE_SECTION_NAME
30 #warning "DTC vector table is aligned on 1K boundary. Automatic placing could lead to memory holes."
31 #endif
32 #else
33 #define DTC_SECTION_ATTRIBUTE BSP_PLACE_IN_SECTION(DTC_CFG_VECTOR_TABLE_SECTION_NAME)
34 #endif
35
36 /* Used to generate a compiler error (divided by 0 error) if the assertion fails. This is used in place of "#error"
37 * for expressions that cannot be evaluated by the preprocessor like sizeof(). */
38 #define DTC_COMPILE_TIME_ASSERT(e) ((void) sizeof(char[1 - 2 * !(e)]))
39
40 /* Calculate the mask bits for byte alignment from the transfer_size_t. */
41 #define DTC_PRV_MASK_ALIGN_N_BYTES(x) ((1U << (x)) - 1U)
42
43 /* Counter Register A Lower Byte Mask */
44 #define DTC_PRV_MASK_CRAL (0xFFU)
45
46 /* Counter Register A Upper Byte Offset */
47 #define DTC_PRV_OFFSET_CRAH (8U)
48
49 /* Offset of in_progress bit in R_DTC->DTCSTS. */
50 #define DTC_PRV_OFFSET_IN_PROGRESS (15U)
51
52 /* DTC Control Register RRS Enable value. */
53 #define DTC_PRV_RRS_ENABLE (0x18)
54
55 /* DTC Control Register RRS Disable value. */
56 #define DTC_PRV_RRS_DISABLE (0x08)
57
58 /***********************************************************************************************************************
59 * Private function prototypes
60 **********************************************************************************************************************/
61
62 static fsp_err_t r_dtc_prv_enable(dtc_instance_ctrl_t * p_ctrl);
63 static void r_dtc_state_initialize(void);
64 static void r_dtc_block_repeat_initialize(transfer_info_t * p_info);
65 static void r_dtc_set_info(dtc_instance_ctrl_t * p_ctrl, transfer_info_t * p_info);
66
67 #if DTC_CFG_PARAM_CHECKING_ENABLE
68 #if BSP_CFG_ASSERT != 3
69 static fsp_err_t r_dtc_length_assert(transfer_info_t * p_info);
70
71 #endif
72 static fsp_err_t r_dtc_source_destination_parameter_check(transfer_info_t * p_info);
73
74 #endif
75
76 static void r_dtc_wait_for_transfer_complete(dtc_instance_ctrl_t * p_ctrl);
77 static void r_dtc_disable_transfer(const IRQn_Type irq);
78
79 /***********************************************************************************************************************
80 * Private global variables
81 **********************************************************************************************************************/
82
83 static transfer_info_t * gp_dtc_vector_table[DTC_VECTOR_TABLE_ENTRIES] BSP_ALIGN_VARIABLE(1024)
84 DTC_SECTION_ATTRIBUTE;
85
86 /***********************************************************************************************************************
87 * Exported global variables
88 **********************************************************************************************************************/
89
90 /** DTC implementation of transfer API. */
91 const transfer_api_t g_transfer_on_dtc =
92 {
93 .open = R_DTC_Open,
94 .reconfigure = R_DTC_Reconfigure,
95 .reset = R_DTC_Reset,
96 .infoGet = R_DTC_InfoGet,
97 .softwareStart = R_DTC_SoftwareStart,
98 .softwareStop = R_DTC_SoftwareStop,
99 .enable = R_DTC_Enable,
100 .disable = R_DTC_Disable,
101 .reload = R_DTC_Reload,
102 .callbackSet = R_DTC_CallbackSet,
103 .close = R_DTC_Close,
104 };
105
106 /*******************************************************************************************************************//**
107 * @addtogroup DTC
108 * @{
109 **********************************************************************************************************************/
110
111 /***********************************************************************************************************************
112 * Functions
113 **********************************************************************************************************************/
114
115 /*******************************************************************************************************************//**
116 * Configure the vector table if it hasn't been configured, enable the Module and copy the pointer to the transfer info
117 * into the DTC vector table. Implements @ref transfer_api_t::open.
118 *
119 * Example:
120 * @snippet r_dtc_example.c R_DTC_Open
121 *
122 * @retval FSP_SUCCESS Successful open.
123 * Transfer transfer info pointer copied to DTC Vector table.
124 * Module started.
125 * DTC vector table configured.
126 * @retval FSP_ERR_ASSERTION An input parameter is invalid.
127 * @retval FSP_ERR_UNSUPPORTED Address Mode Offset is selected.
128 * @retval FSP_ERR_ALREADY_OPEN The control structure is already opened.
129 * @retval FSP_ERR_IN_USE The index for this IRQ in the DTC vector table is already configured.
130 * @retval FSP_ERR_IRQ_BSP_DISABLED The IRQ associated with the activation source is not enabled in the BSP.
131 **********************************************************************************************************************/
R_DTC_Open(transfer_ctrl_t * const p_api_ctrl,transfer_cfg_t const * const p_cfg)132 fsp_err_t R_DTC_Open (transfer_ctrl_t * const p_api_ctrl, transfer_cfg_t const * const p_cfg)
133 {
134 /* Generate a compiler error if transfer_info_t is modified. */
135 DTC_COMPILE_TIME_ASSERT(sizeof(transfer_info_t) == DTC_TRANSFER_INFO_SIZE);
136
137 dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) p_api_ctrl;
138
139 #if DTC_CFG_PARAM_CHECKING_ENABLE
140 FSP_ASSERT(NULL != p_ctrl);
141 FSP_ERROR_RETURN(p_ctrl->open != DTC_OPEN, FSP_ERR_ALREADY_OPEN);
142 FSP_ASSERT(NULL != p_cfg);
143 FSP_ASSERT(NULL != p_cfg->p_extend);
144 #endif
145
146 /* One time initialization for all DTC instances. */
147 r_dtc_state_initialize();
148
149 /* Make sure the activation source is mapped in the ICU. */
150 dtc_extended_cfg_t * p_dtc_cfg = (dtc_extended_cfg_t *) p_cfg->p_extend;
151 IRQn_Type irq = p_dtc_cfg->activation_source;
152 FSP_ERROR_RETURN(irq >= (IRQn_Type) 0, FSP_ERR_IRQ_BSP_DISABLED);
153
154 /* Make sure the activation source is not already being used by the DTC. */
155 FSP_ERROR_RETURN(NULL == gp_dtc_vector_table[irq], FSP_ERR_IN_USE);
156
157 /* irq is used to index the DTC vector table. */
158 p_ctrl->irq = irq;
159
160 /* Copy p_info into the DTC vector table. */
161 if (p_cfg->p_info)
162 {
163 #if DTC_CFG_PARAM_CHECKING_ENABLE
164 fsp_err_t err = r_dtc_length_assert(p_cfg->p_info);
165 FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
166 #endif
167 r_dtc_set_info(p_ctrl, p_cfg->p_info);
168 }
169
170 /* Mark driver as open by initializing it to "DTC" in its ASCII equivalent. */
171 p_ctrl->open = DTC_OPEN;
172
173 return FSP_SUCCESS;
174 }
175
176 /*******************************************************************************************************************//**
177 * Copy pointer to transfer info into the DTC vector table and enable transfer in ICU.
178 * Implements @ref transfer_api_t::reconfigure.
179 *
180 * @retval FSP_SUCCESS Transfer is configured and will start when trigger occurs.
181 * @retval FSP_ERR_ASSERTION An input parameter is invalid.
182 * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DTC_Open to initialize the control block.
183 * @retval FSP_ERR_NOT_ENABLED Transfer source address is NULL or is not aligned correctly.
184 * Transfer destination address is NULL or is not aligned correctly.
185 *
186 * @note p_info must persist until all transfers are completed.
187 **********************************************************************************************************************/
R_DTC_Reconfigure(transfer_ctrl_t * const p_api_ctrl,transfer_info_t * p_info)188 fsp_err_t R_DTC_Reconfigure (transfer_ctrl_t * const p_api_ctrl, transfer_info_t * p_info)
189 {
190 dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) p_api_ctrl;
191
192 #if DTC_CFG_PARAM_CHECKING_ENABLE
193 FSP_ASSERT(NULL != p_ctrl);
194 FSP_ERROR_RETURN(p_ctrl->open == DTC_OPEN, FSP_ERR_NOT_OPEN);
195 FSP_ASSERT(NULL != p_info);
196 FSP_ASSERT(FSP_SUCCESS == r_dtc_length_assert(p_info));
197 #endif
198
199 /* Disable transfers on this activation source. */
200 r_dtc_disable_transfer(p_ctrl->irq);
201
202 /* Wait for current transfer to finish. */
203 r_dtc_wait_for_transfer_complete(p_ctrl);
204
205 /* Copy p_info into the DTC vector table. */
206 r_dtc_set_info(p_ctrl, p_info);
207
208 /* This is an exception to FSP Architecture Parameter Checking (May return an error after modifying registers). */
209 /* Enable transfers on this activation source. */
210 FSP_ERROR_RETURN(FSP_SUCCESS == r_dtc_prv_enable(p_ctrl), FSP_ERR_NOT_ENABLED);
211
212 return FSP_SUCCESS;
213 }
214
215 /*******************************************************************************************************************//**
216 * Reset transfer source, destination, and number of transfers. Implements @ref transfer_api_t::reset.
217 *
218 * @retval FSP_SUCCESS Transfer reset successfully (transfers are enabled).
219 * @retval FSP_ERR_ASSERTION An input parameter is invalid.
220 * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DTC_Open to initialize the control block.
221 * @retval FSP_ERR_NOT_ENABLED Transfer source address is NULL or is not aligned correctly.
222 * Transfer destination address is NULL or is not aligned correctly.
223 **********************************************************************************************************************/
R_DTC_Reset(transfer_ctrl_t * const p_api_ctrl,void const * volatile p_src,void * volatile p_dest,uint16_t const num_transfers)224 fsp_err_t R_DTC_Reset (transfer_ctrl_t * const p_api_ctrl,
225 void const * volatile p_src,
226 void * volatile p_dest,
227 uint16_t const num_transfers)
228 {
229 dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) p_api_ctrl;
230
231 #if DTC_CFG_PARAM_CHECKING_ENABLE
232 FSP_ASSERT(NULL != p_ctrl);
233 FSP_ERROR_RETURN(p_ctrl->open == DTC_OPEN, FSP_ERR_NOT_OPEN);
234 #endif
235
236 const IRQn_Type irq = p_ctrl->irq;
237 transfer_info_t * const gp_dtc_vector = gp_dtc_vector_table[irq];
238
239 /* Disable transfers on this activation source. */
240 r_dtc_disable_transfer(irq);
241
242 /* Wait for current transfer to finish. */
243 r_dtc_wait_for_transfer_complete(p_ctrl);
244
245 /* Disable read skip prior to modifying settings. It will be enabled later
246 * (See DTC Section 18.4.1 of the RA6M3 manual R01UH0886EJ0100). */
247 #if !BSP_TZ_NONSECURE_BUILD && BSP_FEATURE_TZ_HAS_TRUSTZONE
248 R_DTC->DTCCR_SEC = DTC_PRV_RRS_DISABLE;
249 #else
250 R_DTC->DTCCR = DTC_PRV_RRS_DISABLE;
251 #endif
252
253 /* Reset transfer based on input parameters. */
254 if (NULL != p_src)
255 {
256 gp_dtc_vector->p_src = p_src;
257 }
258
259 if (NULL != p_dest)
260 {
261 gp_dtc_vector->p_dest = p_dest;
262 }
263
264 if (TRANSFER_MODE_BLOCK == gp_dtc_vector->transfer_settings_word_b.mode)
265 {
266 gp_dtc_vector->num_blocks = num_transfers;
267 }
268 else if (TRANSFER_MODE_NORMAL == gp_dtc_vector->transfer_settings_word_b.mode)
269 {
270 gp_dtc_vector->length = num_transfers;
271 }
272 else /* TRANSFER_MODE_REPEAT */
273 {
274 /* Do nothing. */
275 }
276
277 /* Enable read skip after all settings are written. */
278 #if !BSP_TZ_NONSECURE_BUILD && BSP_FEATURE_TZ_HAS_TRUSTZONE
279 R_DTC->DTCCR_SEC = DTC_PRV_RRS_ENABLE;
280 #else
281 R_DTC->DTCCR = DTC_PRV_RRS_ENABLE;
282 #endif
283
284 /* This is an exception to FSP Architecture Parameter Checking (May return an error after modifying registers). */
285 /* Enable transfers on this activation source. */
286 FSP_ERROR_RETURN(FSP_SUCCESS == r_dtc_prv_enable(p_ctrl), FSP_ERR_NOT_ENABLED);
287
288 return FSP_SUCCESS;
289 }
290
291 /*******************************************************************************************************************//**
292 * Placeholder for unsupported softwareStart function. Implements @ref transfer_api_t::softwareStart.
293 *
294 * @retval FSP_ERR_UNSUPPORTED DTC software start is not supported.
295 **********************************************************************************************************************/
R_DTC_SoftwareStart(transfer_ctrl_t * const p_api_ctrl,transfer_start_mode_t mode)296 fsp_err_t R_DTC_SoftwareStart (transfer_ctrl_t * const p_api_ctrl, transfer_start_mode_t mode)
297 {
298 /* This function isn't supported. It is defined only to implement a required function of transfer_api_t.
299 * Mark the input parameter as unused since this function isn't supported. */
300 FSP_PARAMETER_NOT_USED(p_api_ctrl);
301 FSP_PARAMETER_NOT_USED(mode);
302
303 return FSP_ERR_UNSUPPORTED;
304 }
305
306 /*******************************************************************************************************************//**
307 * Placeholder for unsupported softwareStop function. Implements @ref transfer_api_t::softwareStop.
308 *
309 * @retval FSP_ERR_UNSUPPORTED DTC software stop is not supported.
310 **********************************************************************************************************************/
R_DTC_SoftwareStop(transfer_ctrl_t * const p_api_ctrl)311 fsp_err_t R_DTC_SoftwareStop (transfer_ctrl_t * const p_api_ctrl)
312 {
313 /* This function isn't supported. It is defined only to implement a required function of transfer_api_t.
314 * Mark the input parameter as unused since this function isn't supported. */
315 FSP_PARAMETER_NOT_USED(p_api_ctrl);
316
317 return FSP_ERR_UNSUPPORTED;
318 }
319
320 /*******************************************************************************************************************//**
321 * Enable transfers on this activation source. Implements @ref transfer_api_t::enable.
322 *
323 * Example:
324 * @snippet r_dtc_example.c R_DTC_Enable
325 *
326 * @retval FSP_SUCCESS Transfers will be triggered by the activation source
327 * @retval FSP_ERR_ASSERTION An input parameter is invalid.
328 * @retval FSP_ERR_UNSUPPORTED Address Mode Offset is selected.
329 * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DTC_Open to initialize the control block.
330 **********************************************************************************************************************/
R_DTC_Enable(transfer_ctrl_t * const p_api_ctrl)331 fsp_err_t R_DTC_Enable (transfer_ctrl_t * const p_api_ctrl)
332 {
333 dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) p_api_ctrl;
334 #if DTC_CFG_PARAM_CHECKING_ENABLE
335 FSP_ASSERT(NULL != p_ctrl);
336 FSP_ERROR_RETURN(p_ctrl->open == DTC_OPEN, FSP_ERR_NOT_OPEN);
337 #endif
338
339 return r_dtc_prv_enable(p_ctrl);
340 }
341
342 /*******************************************************************************************************************//**
343 * Disable transfer on this activation source. Implements @ref transfer_api_t::disable.
344 *
345 * @retval FSP_SUCCESS Transfers will not occur on activation events.
346 * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DTC_Open to initialize the control block.
347 * @retval FSP_ERR_ASSERTION An input parameter is invalid.
348 **********************************************************************************************************************/
R_DTC_Disable(transfer_ctrl_t * const p_api_ctrl)349 fsp_err_t R_DTC_Disable (transfer_ctrl_t * const p_api_ctrl)
350 {
351 dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) p_api_ctrl;
352
353 #if DTC_CFG_PARAM_CHECKING_ENABLE
354 FSP_ASSERT(NULL != p_ctrl);
355 FSP_ERROR_RETURN(p_ctrl->open == DTC_OPEN, FSP_ERR_NOT_OPEN);
356 #endif
357
358 /* Disable transfer. */
359 r_dtc_disable_transfer(p_ctrl->irq);
360
361 return FSP_SUCCESS;
362 }
363
364 /*******************************************************************************************************************//**
365 * Provides information about this transfer. Implements @ref transfer_api_t::infoGet.
366 *
367 * @retval FSP_SUCCESS p_info updated with current instance information.
368 * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DTC_Open to initialize the control block.
369 * @retval FSP_ERR_ASSERTION An input parameter is invalid.
370 **********************************************************************************************************************/
R_DTC_InfoGet(transfer_ctrl_t * const p_api_ctrl,transfer_properties_t * const p_properties)371 fsp_err_t R_DTC_InfoGet (transfer_ctrl_t * const p_api_ctrl, transfer_properties_t * const p_properties)
372 {
373 dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) p_api_ctrl;
374
375 #if DTC_CFG_PARAM_CHECKING_ENABLE
376 FSP_ASSERT(NULL != p_ctrl);
377 FSP_ERROR_RETURN(p_ctrl->open == DTC_OPEN, FSP_ERR_NOT_OPEN);
378 FSP_ASSERT(NULL != p_properties);
379 #endif
380
381 transfer_info_t * p_info = gp_dtc_vector_table[p_ctrl->irq];
382
383 p_properties->block_count_max = 0U;
384 p_properties->block_count_remaining = 0U;
385
386 if (TRANSFER_MODE_NORMAL != p_info->transfer_settings_word_b.mode)
387 {
388 /* Repeat and Block Mode */
389
390 /* transfer_length_max is the same for Block and repeat mode. */
391 p_properties->transfer_length_max = DTC_MAX_REPEAT_TRANSFER_LENGTH;
392 p_properties->transfer_length_remaining = p_info->length & DTC_PRV_MASK_CRAL;
393
394 if (TRANSFER_MODE_BLOCK == p_info->transfer_settings_word_b.mode)
395 {
396 p_properties->block_count_max = DTC_MAX_BLOCK_COUNT;
397 p_properties->block_count_remaining = p_info->num_blocks;
398 }
399 }
400 else
401 {
402 p_properties->transfer_length_max = DTC_MAX_NORMAL_TRANSFER_LENGTH;
403 p_properties->transfer_length_remaining = p_info->length;
404 }
405
406 return FSP_SUCCESS;
407 }
408
409 /*******************************************************************************************************************//**
410 * To update next transfer information without interruption during transfer.
411 *
412 * @retval FSP_ERR_UNSUPPORTED This feature is not supported.
413 **********************************************************************************************************************/
R_DTC_Reload(transfer_ctrl_t * const p_api_ctrl,void const * p_src,void * p_dest,uint32_t const num_transfers)414 fsp_err_t R_DTC_Reload (transfer_ctrl_t * const p_api_ctrl,
415 void const * p_src,
416 void * p_dest,
417 uint32_t const num_transfers)
418 {
419 FSP_PARAMETER_NOT_USED(p_api_ctrl);
420 FSP_PARAMETER_NOT_USED(p_src);
421 FSP_PARAMETER_NOT_USED(p_dest);
422 FSP_PARAMETER_NOT_USED(num_transfers);
423
424 return FSP_ERR_UNSUPPORTED;
425 }
426
427 /*******************************************************************************************************************//**
428 * Placeholder for unsupported callbackset function. Implements @ref transfer_api_t::callbackSet.
429 *
430 * @retval FSP_ERR_UNSUPPORTED DTC does not support direct callbacks.
431 **********************************************************************************************************************/
R_DTC_CallbackSet(transfer_ctrl_t * const p_api_ctrl,void (* p_callback)(transfer_callback_args_t *),void const * const p_context,transfer_callback_args_t * const p_callback_memory)432 fsp_err_t R_DTC_CallbackSet (transfer_ctrl_t * const p_api_ctrl,
433 void ( * p_callback)(transfer_callback_args_t *),
434 void const * const p_context,
435 transfer_callback_args_t * const p_callback_memory)
436 {
437 /* This function isn't supported. It is defined only to implement a required function of transfer_api_t.
438 * Mark the input parameter as unused since this function isn't supported. */
439 FSP_PARAMETER_NOT_USED(p_api_ctrl);
440 FSP_PARAMETER_NOT_USED(p_callback);
441 FSP_PARAMETER_NOT_USED(p_context);
442 FSP_PARAMETER_NOT_USED(p_callback_memory);
443
444 return FSP_ERR_UNSUPPORTED;
445 }
446
447 /*******************************************************************************************************************//**
448 * Disables DTC activation in the ICU, then clears transfer data from the DTC vector table.
449 * Implements @ref transfer_api_t::close.
450 *
451 * @retval FSP_SUCCESS Successful close.
452 * @retval FSP_ERR_ASSERTION An input parameter is invalid.
453 * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DTC_Open to initialize the control block.
454 **********************************************************************************************************************/
R_DTC_Close(transfer_ctrl_t * const p_api_ctrl)455 fsp_err_t R_DTC_Close (transfer_ctrl_t * const p_api_ctrl)
456 {
457 dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) p_api_ctrl;
458 fsp_err_t err = FSP_SUCCESS;
459
460 #if DTC_CFG_PARAM_CHECKING_ENABLE
461 FSP_ASSERT(NULL != p_ctrl);
462 FSP_ERROR_RETURN(p_ctrl->open == DTC_OPEN, FSP_ERR_NOT_OPEN);
463 #endif
464
465 const IRQn_Type irq = p_ctrl->irq;
466
467 /* Clear DTC enable bit in ICU. */
468 r_dtc_disable_transfer(irq);
469
470 /* Clear pointer in vector table. */
471 gp_dtc_vector_table[irq] = NULL;
472
473 /* Mark instance as closed. */
474 p_ctrl->open = 0U;
475
476 return err;
477 }
478
479 /*******************************************************************************************************************//**
480 * @} (end addtogroup DTC)
481 **********************************************************************************************************************/
482
483 /*******************************************************************************************************************//**
484 * Verify that the source and destination pointers are valid then enable the DTC.
485 *
486 * @retval FSP_SUCCESS Successfully enabled
487 * @retval FSP_ERR_ASSERTION An input parameter is invalid.
488 * @retval FSP_ERR_UNSUPPORTED Address Mode Offset is selected.
489 **********************************************************************************************************************/
r_dtc_prv_enable(dtc_instance_ctrl_t * p_ctrl)490 static fsp_err_t r_dtc_prv_enable (dtc_instance_ctrl_t * p_ctrl)
491 {
492 #if DTC_CFG_PARAM_CHECKING_ENABLE
493 fsp_err_t err = r_dtc_source_destination_parameter_check(gp_dtc_vector_table[p_ctrl->irq]);
494 FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
495 #endif
496
497 /* Enable transfers on this activation source. */
498 #if BSP_FEATURE_ICU_HAS_IELSR
499 R_ICU->IELSR_b[p_ctrl->irq].DTCE = 1U;
500 #else
501 R_ICU->DTCENSET[(((uint32_t) p_ctrl->irq) >> 5UL)] = 1UL << ((uint32_t) p_ctrl->irq & (uint32_t) 0x1FUL);
502 #endif
503
504 return FSP_SUCCESS;
505 }
506
507 /*******************************************************************************************************************//**
508 * One time state initialization for all DTC instances.
509 **********************************************************************************************************************/
r_dtc_state_initialize(void)510 static void r_dtc_state_initialize (void)
511 {
512 /* Stores initialization state to skip initialization in ::R_DTC_Open after the first call. */
513 static bool g_dtc_state_initialized = false;
514
515 /* DTC requires a one time initialization. This will be handled only the first time this function
516 * is called. This initialization:
517 * -# Stores the register base addresses for DTC and ICU.
518 * -# Powers on the DTC block.
519 * -# Initializes the vector table to NULL pointers.
520 * -# Sets the vector table base address.
521 * -# Enables DTC transfers. */
522 if (!g_dtc_state_initialized)
523 {
524 g_dtc_state_initialized = true;
525
526 /** Power on DTC */
527 R_BSP_MODULE_START(FSP_IP_DTC, 0);
528
529 /* The DTC vector table must be cleared during initialization because it is located in
530 * its own section outside of the .BSS section which is cleared during startup. */
531 memset(&gp_dtc_vector_table, 0U, DTC_VECTOR_TABLE_ENTRIES * sizeof(transfer_info_t *));
532
533 /* Set DTC vector table. */
534 #if !BSP_TZ_NONSECURE_BUILD && BSP_FEATURE_TZ_HAS_TRUSTZONE
535 R_DTC->DTCVBR_SEC = (uint32_t) gp_dtc_vector_table;
536 #else
537 R_DTC->DTCVBR = (uint32_t) gp_dtc_vector_table;
538 #endif
539
540 #if BSP_FEATURE_TZ_HAS_TRUSTZONE && BSP_TZ_NONSECURE_BUILD
541 if (1 == R_CPSCU->DTCSAR_b.DTCSTSA)
542 {
543 /* Enable the DTC Peripheral */
544 R_DTC->DTCST = 1U;
545 }
546
547 #else
548
549 /* Enable the DTC Peripheral */
550 R_DTC->DTCST = 1U;
551 #endif
552 }
553 }
554
555 /*******************************************************************************************************************//**
556 * Configure the p_info state and write p_info to DTC vector table.
557 **********************************************************************************************************************/
r_dtc_set_info(dtc_instance_ctrl_t * p_ctrl,transfer_info_t * p_info)558 static void r_dtc_set_info (dtc_instance_ctrl_t * p_ctrl, transfer_info_t * p_info)
559 {
560 /* Update internal variables. */
561 r_dtc_block_repeat_initialize(p_info);
562
563 /* Disable read skip prior to modifying settings. It will be enabled later
564 * (See DTC Section 18.4.1 of the RA6M3 manual R01UH0886EJ0100). */
565 #if !BSP_TZ_NONSECURE_BUILD && BSP_FEATURE_TZ_HAS_TRUSTZONE
566 R_DTC->DTCCR_SEC = DTC_PRV_RRS_DISABLE;
567 #else
568 R_DTC->DTCCR = DTC_PRV_RRS_DISABLE;
569 #endif
570
571 /* Update the entry in the DTC Vector table. */
572 gp_dtc_vector_table[p_ctrl->irq] = p_info;
573
574 /* Enable read skip after all settings are written. */
575 #if !BSP_TZ_NONSECURE_BUILD && BSP_FEATURE_TZ_HAS_TRUSTZONE
576 R_DTC->DTCCR_SEC = DTC_PRV_RRS_ENABLE;
577 #else
578 R_DTC->DTCCR = DTC_PRV_RRS_ENABLE;
579 #endif
580 }
581
582 /*******************************************************************************************************************//**
583 * Configure the length setting for block and repeat mode.
584 **********************************************************************************************************************/
r_dtc_block_repeat_initialize(transfer_info_t * p_info)585 static void r_dtc_block_repeat_initialize (transfer_info_t * p_info)
586 {
587 uint32_t i = 0;
588 do
589 {
590 /* Update the CRA register to the desired settings */
591 if (TRANSFER_MODE_NORMAL != p_info[i].transfer_settings_word_b.mode)
592 {
593 uint8_t CRAL = p_info[i].length & DTC_PRV_MASK_CRAL;
594 p_info[i].length = (uint16_t) ((CRAL << DTC_PRV_OFFSET_CRAH) | CRAL);
595 }
596 } while (TRANSFER_CHAIN_MODE_DISABLED != p_info[i++].transfer_settings_word_b.chain_mode);
597 }
598
599 #if DTC_CFG_PARAM_CHECKING_ENABLE
600
601 #if BSP_CFG_ASSERT != 3
602
603 /*******************************************************************************************************************//**
604 * Check to make sure that the length is valid for block and repeat mode.
605 *
606 * @retval FSP_SUCCESS Parameters are valid.
607 * @retval FSP_ERR_ASSERTION Invalid length for block or repeat mode.
608 * @retval FSP_ERR_UNSUPPORTED Address Mode Offset is selected.
609 *
610 **********************************************************************************************************************/
r_dtc_length_assert(transfer_info_t * p_info)611 static fsp_err_t r_dtc_length_assert (transfer_info_t * p_info)
612 {
613 uint32_t i = 0;
614 do
615 {
616 FSP_ERROR_RETURN(TRANSFER_ADDR_MODE_OFFSET != p_info[i].transfer_settings_word_b.src_addr_mode,
617 FSP_ERR_UNSUPPORTED);
618 FSP_ERROR_RETURN(TRANSFER_ADDR_MODE_OFFSET != p_info[i].transfer_settings_word_b.dest_addr_mode,
619 FSP_ERR_UNSUPPORTED);
620
621 if (TRANSFER_MODE_NORMAL != p_info[i].transfer_settings_word_b.mode)
622 {
623 /* transfer_length_max is the same for Block and repeat mode. */
624 FSP_ASSERT(p_info[i].length <= DTC_MAX_REPEAT_TRANSFER_LENGTH);
625 }
626 } while (TRANSFER_CHAIN_MODE_DISABLED != p_info[i++].transfer_settings_word_b.chain_mode);
627
628 return FSP_SUCCESS;
629 }
630
631 #endif
632
633 /*******************************************************************************************************************//**
634 * Check that the source and destination are not NULL and that they are aligned correctly.
635 *
636 * @retval FSP_SUCCESS Parameters are valid.
637 * @retval FSP_ERR_ASSERTION An input parameter is invalid.
638 * @retval FSP_ERR_UNSUPPORTED Address Mode Offset is selected.
639 *
640 **********************************************************************************************************************/
r_dtc_source_destination_parameter_check(transfer_info_t * p_info)641 static fsp_err_t r_dtc_source_destination_parameter_check (transfer_info_t * p_info)
642 {
643 uint32_t i = 0;
644 do
645 {
646 FSP_ERROR_RETURN(TRANSFER_ADDR_MODE_OFFSET != p_info[i].transfer_settings_word_b.src_addr_mode,
647 FSP_ERR_UNSUPPORTED);
648 FSP_ERROR_RETURN(TRANSFER_ADDR_MODE_OFFSET != p_info[i].transfer_settings_word_b.dest_addr_mode,
649 FSP_ERR_UNSUPPORTED);
650 FSP_ASSERT(NULL != p_info[i].p_src);
651 FSP_ASSERT(NULL != p_info[i].p_dest);
652 FSP_ASSERT(0U ==
653 ((uint32_t) p_info[i].p_dest & DTC_PRV_MASK_ALIGN_N_BYTES(p_info[i].transfer_settings_word_b.size)));
654 FSP_ASSERT(0U ==
655 ((uint32_t) p_info[i].p_src & DTC_PRV_MASK_ALIGN_N_BYTES(p_info[i].transfer_settings_word_b.size)));
656 } while (TRANSFER_CHAIN_MODE_DISABLED != p_info[i++].transfer_settings_word_b.chain_mode);
657
658 return FSP_SUCCESS;
659 }
660
661 #endif
662
663 /*******************************************************************************************************************//**
664 * Wait for the current DTC transfer to complete.
665 **********************************************************************************************************************/
r_dtc_wait_for_transfer_complete(dtc_instance_ctrl_t * p_ctrl)666 static void r_dtc_wait_for_transfer_complete (dtc_instance_ctrl_t * p_ctrl)
667 {
668 uint32_t in_progress = (1U << DTC_PRV_OFFSET_IN_PROGRESS) | (uint32_t) p_ctrl->irq;
669
670 /* Wait for the DTCSTS.ACT flag to be clear if the current vector is the activation source.*/
671 FSP_HARDWARE_REGISTER_WAIT((FSP_STYPE3_REG16_READ(R_DTC->DTCSTS, !R_CPSCU->DTCSAR_b.DTCSTSA) == in_progress), 0);
672 }
673
674 /*******************************************************************************************************************//**
675 * Disable transfers on activation source.
676 **********************************************************************************************************************/
r_dtc_disable_transfer(const IRQn_Type irq)677 static void r_dtc_disable_transfer (const IRQn_Type irq)
678 {
679 #if BSP_FEATURE_ICU_HAS_IELSR
680 R_ICU->IELSR_b[((uint32_t) irq)].DTCE = 0U;
681 #else
682 R_ICU->DTCENCLR[(((uint32_t) irq) >> 5UL)] = 1UL << (((uint32_t) irq) & (uint32_t) 0x1FUL);
683 #endif
684 }
685