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 : hw_flash_lp.c
22 * Description : LLD Interface for the Low power Flash peripheral on SC32 MCUs.
23 **********************************************************************************************************************/
24
25 /***********************************************************************************************************************
26 * Includes
27 **********************************************************************************************************************/
28
29 /***********************************************************************************************************************
30 * Includes
31 **********************************************************************************************************************/
32 #include "bsp_api.h"
33
34 #include "r_flash_lp.h"
35 #include "hw_flash_lp_private.h"
36 #include "r_flash_cfg.h"
37 #include "r_cgc_api.h"
38 #include "r_cgc.h"
39 #include "flash_lp_core/hw_dataflash.h"
40 #include "flash_lp_core/hw_codeflash.h"
41 #include "flash_lp_core/hw_codeflash_extra.h"
42
43 /*******************************************************************************************************************//**
44 * @addtogroup FLASH
45 * @{
46 **********************************************************************************************************************/
47
48 /*******************************************************************************************************************//**
49 * @} (end FLASH)
50 **********************************************************************************************************************/
51
52 /***********************************************************************************************************************
53 * Typedef definitions
54 **********************************************************************************************************************/
55
56 /***********************************************************************************************************************
57 * Macro definitions
58 **********************************************************************************************************************/
59 /* The number of CPU cycles per each timeout loop. */
60 #ifndef R_FLASH_LP_CYCLES_MINIMUM_PER_TIMEOUT_LOOP
61 #if defined(__GNUC__)
62 #define R_FLASH_LP_CYCLES_MINIMUM_PER_TIMEOUT_LOOP (6U)
63 #elif defined(__ICCARM__)
64 #define R_FLASH_LP_CYCLES_MINIMUM_PER_TIMEOUT_LOOP (6U)
65 #endif
66 #endif
67
68 #define R_FLASH_LP_HZ_IN_MHZ (1000000U)
69
70 /***********************************************************************************************************************
71 * Private function prototypes
72 **********************************************************************************************************************/
73
74 /***********************************************************************************************************************
75 * Private global variables
76 **********************************************************************************************************************/
77 static current_parameters_t * gp_flash_parameters = NULL; // passed in via flash_init()
78
79 static inline bool HW_FLASH_LP_frdyi_df_bgo_write (flash_lp_instance_ctrl_t *p_ctrl, flash_callback_args_t *p_cb_data);
80 static inline bool HW_FLASH_LP_frdyi_df_bgo_erase (flash_lp_instance_ctrl_t *p_ctrl, flash_callback_args_t *p_cb_data);
81 static inline bool HW_FLASH_LP_frdyi_df_bgo_blankcheck (flash_lp_instance_ctrl_t *p_ctrl, flash_callback_args_t *p_cb_data);
82
83 /***********************************************************************************************************************
84 * Functions
85 **********************************************************************************************************************/
86
87 /*******************************************************************************************************************//**
88 * @brief This function enables or disables the Flash interrupt. The flash interrupt, if enabled, is called when a
89 * Flash operation completes, or when an Error condition is detected. If the caller has provided a callback
90 * function as part of the provided p_cfg pointer, then that function will be called as a result of the
91 * interrupt.
92 * @param[in] state Control for the FLASH device context.
93 * @param[in] p_cfg Pointer to the FLASH configuration structure.
94 * @param[in] irq Flash interrupt irq number.
95 * @retval SSP_SUCCESS Successful.
96 * @retval SSP_ERR_IRQ_BSP_DISABLED Caller is requesting BGO but the Flash interrupts are not enabled.
97 **********************************************************************************************************************/
HW_FLASH_LP_irq_cfg(bool state,flash_cfg_t const * const p_cfg,IRQn_Type irq)98 ssp_err_t HW_FLASH_LP_irq_cfg (bool state, flash_cfg_t const * const p_cfg, IRQn_Type irq)
99 {
100 SSP_PARAMETER_NOT_USED(state);
101
102 /** If BGO is being used then we require the Flash Rdy interrupt be enabled. If it
103 * is not enabled then we are not going to be doing BGO and we won't generate an ISR routine */
104 if (SSP_INVALID_VECTOR != irq)
105 {
106 /** Enable the Interrupt */
107 if (true == state)
108 {
109 /** Enable FCU interrupts if callback is not null, clear the Interrupt Request bit */
110 NVIC_ClearPendingIRQ(irq);
111 R_BSP_IrqStatusClear(irq);
112 NVIC_EnableIRQ(irq);
113 }
114 /** Disable the Interrupts */
115 else
116 {
117 /** Disable interrupt in ICU*/
118 NVIC_DisableIRQ(irq);
119
120 /** Clear the Interrupt Request bit */
121 R_BSP_IrqStatusClear(irq);
122 }
123
124 return SSP_SUCCESS;
125 }
126 else
127 {
128 /** The Flash Interrupt has not been enabled. If the caller is requesting BGO then we'll flag this as an error. */
129 if (p_cfg->data_flash_bgo == true)
130 {
131 return SSP_ERR_IRQ_BSP_DISABLED;
132 }
133 else
134 {
135 return SSP_SUCCESS;
136 }
137 }
138 }
139
140 /*******************************************************************************************************************//**
141 * @brief This function will initialize the FCU and set the FCU Clock based on the current FCLK frequency.
142 * @param[in] p_ctrl Pointer to the Flash control block
143 * @param[in, out] p_current_parameters Pointer to the g_current_parameters structure created by the HLD layer.
144 **********************************************************************************************************************/
HW_FLASH_LP_init(flash_lp_instance_ctrl_t * const p_ctrl,current_parameters_t * p_current_parameters)145 void HW_FLASH_LP_init (flash_lp_instance_ctrl_t * const p_ctrl, current_parameters_t * p_current_parameters)
146 {
147 R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
148
149 gp_flash_parameters = p_current_parameters; // our copy from now on
150
151 gp_flash_parameters->current_operation = FLASH_OPERATION_FCU_INIT;
152
153 /* Round up the frequency to a whole number */
154 uint32_t system_clock_freq_mhz = (gp_flash_parameters->system_clock_freq + (R_FLASH_LP_HZ_IN_MHZ - 1)) / R_FLASH_LP_HZ_IN_MHZ;
155
156 gp_flash_parameters->flash_clock_freq = gp_flash_parameters->flash_clock_freq / 1000000; // Scale it down
157 gp_flash_parameters->system_clock_freq = gp_flash_parameters->system_clock_freq / 1000000; // Scale it down
158
159 /* According to HW Manual the Max Programming Time for 4 bytes(S124/S128) or 8 bytes(S1JA/S3A*)(ROM)
160 * is 1411us. This is with a FCLK of 1MHz. The calculation below
161 * calculates the number of ICLK ticks needed for the timeout delay.
162 */
163 gp_flash_parameters->wait_max_write_cf = (uint32_t) (1411 * system_clock_freq_mhz)/R_FLASH_LP_CYCLES_MINIMUM_PER_TIMEOUT_LOOP;
164
165 /* According to HW Manual the Max Programming Time for 1 byte
166 * (Data Flash) is 886us. This is with a FCLK of 4MHz. The calculation
167 * below calculates the number of ICLK ticks needed for the timeout delay.
168 */
169 gp_flash_parameters->wait_max_write_df = (uint32_t) (886 * system_clock_freq_mhz)/R_FLASH_LP_CYCLES_MINIMUM_PER_TIMEOUT_LOOP;
170
171 /* According to HW Manual the Max Blank Check time for 2 bytes (S12*) or 8 bytes (S1JA/S3A*)
172 * (Code Flash) is 87.7 usec. This is with a FCLK of 1MHz. The calculation
173 * below calculates the number of ICLK ticks needed for the timeout delay.
174 */
175 gp_flash_parameters->wait_max_blank_check = (uint32_t) (88 * system_clock_freq_mhz)/R_FLASH_LP_CYCLES_MINIMUM_PER_TIMEOUT_LOOP;
176
177 /* According to HW Manual the Max Erasure Time for a 1KB block (S12*) or 2KB bytes (S1JA/S3A*) is
178 * around 289ms. This is with a FCLK of 1MHz. The calculation below
179 * calculates the number of ICLK ticks needed for the timeout delay.
180 */
181 gp_flash_parameters->wait_max_erase_cf_block = (uint32_t) (289000 * system_clock_freq_mhz)/R_FLASH_LP_CYCLES_MINIMUM_PER_TIMEOUT_LOOP;
182
183 /* According to HW Manual the Max Erasure Time for a 1KB Data Flash block is
184 * around 299ms. This is with a FCLK of 4MHz. The calculation below
185 * calculates the number of ICLK ticks needed for the timeout delay.
186 */
187 gp_flash_parameters->wait_max_erase_df_block = (uint32_t) (299000 * system_clock_freq_mhz)/R_FLASH_LP_CYCLES_MINIMUM_PER_TIMEOUT_LOOP;
188
189 /** Per the Flash spec, update the FLWAIT register if FCLK is being changed */
190 p_faci_reg->FLWAITR = 0U;
191 }
192
193 /*******************************************************************************************************************//**
194 * @brief This function erases a specified number of Code or Data Flash blocks
195 * @param[in] p_ctrl Pointer to the Flash control block
196 * @param[in] block_address The starting address of the first block to erase.
197 * @param[in] num_blocks The number of blocks to erase.
198 * @param[in] block_size The Flash block size.
199 * @retval SSP_SUCCESS Successfully erased (non-BGO) mode or operation successfully started (BGO).
200 * @retval SSP_ERR_ERASE_FAILED Status is indicating a Erase error.
201 * @retval SSP_ERR_CMD_LOCKED FCU is in locked state, typically as a result of having received an illegal
202 * command.
203 * @retval SSP_ERR_WRITE_FAILED Status is indicating a Programming error for the requested operation.
204 * @retval SSP_ERR_TIMEOUT Timed out waiting for the FCU to become ready.
205 **********************************************************************************************************************/
HW_FLASH_LP_erase(flash_lp_instance_ctrl_t * const p_ctrl,uint32_t block_address,uint32_t num_blocks,uint32_t block_size)206 ssp_err_t HW_FLASH_LP_erase (flash_lp_instance_ctrl_t * const p_ctrl, uint32_t block_address, uint32_t num_blocks, uint32_t block_size)
207 {
208 ssp_err_t err = SSP_SUCCESS;
209 R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
210
211 gp_flash_parameters->block_size = block_size;
212
213 /* We're already in the appropriate P/E mode from the caller */
214 /** If the module is configured for Data Flash P/E mode */
215 if (p_faci_reg->FENTRYR == 0x0080U)
216 {
217 /** Erase a block of data flash. */
218 HW_FLASH_LP_dataflash_erase(p_ctrl, block_address, num_blocks, block_size); // Set the start and end and do first block
219
220 /** If configured for Blocking mode then don't return until the entire operation is complete */
221 if (gp_flash_parameters->bgo_enabled_df == false)
222 {
223 do
224 {
225 /** Waits for the erase commands to be completed and verifies the result of the command execution. */
226 err = HW_FLASH_LP_dataflash_erase_monitor(p_ctrl, block_size);
227 } while (SSP_ERR_IN_USE == err);
228 }
229 }
230
231 #if (FLASH_CFG_PARAM_CODE_FLASH_PROGRAMMING_ENABLE == 1)
232 /** Else if the module is configured for code flash P/E mode */
233 else if (p_faci_reg->FENTRYR == 0x0001U)
234 {
235 /** Erase a block of code flash */
236 HW_FLASH_LP_codeflash_erase(p_ctrl, block_address, num_blocks, block_size); // Set the start and end and do first block
237
238 /* Code Flash is always blocking mode */
239 do
240 {
241 /** Waits for the erase commands to be completed and verifies the result of the command execution. */
242 err = HW_FLASH_LP_codeflash_erase_monitor(p_ctrl, block_size);
243 } while (SSP_ERR_IN_USE == err);
244 }
245 #endif /* if (FLASH_CFG_PARAM_CODE_FLASH_PROGRAMMING_ENABLE == 1) */
246 else
247 {
248 /** Otherwise the module is not configured for data or code flash P/E mode. return failure */
249 /* should never get here */
250 return SSP_ERR_ERASE_FAILED;
251 }
252
253 return err;
254 }
255
256 /*******************************************************************************************************************//**
257 * @brief This function writes a specified number of bytes to Code or Data Flash.
258 * @param[in] p_ctrl Pointer to the Flash control block
259 * @param[in] src_start_address The starting address of the first byte (from source) to write.
260 * @param[in] dest_start_address The starting address of the Flash (to destination) to write.
261 * @param[in] num_bytes The number of bytes to write.
262 * @param[in] min_program_size The minimum Flash programming size.
263 *
264 * @retval SSP_SUCCESS Data successfully written (non-BGO) mode or operation successfully started (BGO).
265 * @retval SSP_ERR_IN_USE Command still executing.
266 * @retval SSP_ERR_WRITE_FAILED Status is indicating a Programming error for the requested operation. This
267 * may be returned if the requested Flash area is not blank.
268 * @retval SSP_ERR_TIMEOUT Timed out waiting for the Flash sequencer to become ready.
269 * @retval SSP_ERR_PE_FAILURE Unable to enter Programming mode. Flash may be locked (FSPR bit).
270 **********************************************************************************************************************/
HW_FLASH_LP_write(flash_lp_instance_ctrl_t * const p_ctrl,uint32_t const src_start_address,uint32_t dest_start_address,uint32_t num_bytes,uint32_t min_program_size)271 ssp_err_t HW_FLASH_LP_write (flash_lp_instance_ctrl_t * const p_ctrl, uint32_t const src_start_address,
272 uint32_t dest_start_address,
273 uint32_t num_bytes,
274 uint32_t min_program_size)
275 {
276 ssp_err_t err = SSP_SUCCESS;
277 R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
278
279 gp_flash_parameters->dest_addr = dest_start_address;
280 gp_flash_parameters->src_addr = src_start_address;
281 gp_flash_parameters->current_count = (uint32_t)0;
282
283 /** If flash is in PE mode for Data Flash. */
284 if (p_faci_reg->FENTRYR == 0x0080U)
285 {
286 gp_flash_parameters->total_count = num_bytes; // NPP7 and NPP4 both have DF write size of 1.
287
288 /** Start the write operation */
289 HW_FLASH_LP_dataflash_write(p_ctrl, src_start_address, dest_start_address, num_bytes, min_program_size);
290
291 /** If configured for Blocking mode then don't return until the entire operation is complete */
292 if (gp_flash_parameters->bgo_enabled_df == false)
293 {
294 do
295 {
296 /** Wait for the write commands to be completed and verifies the result of the command execution. */
297 err = HW_FLASH_LP_dataflash_write_monitor(p_ctrl, min_program_size);
298 } while (SSP_ERR_IN_USE == err);
299
300 /** Disable P/E mode for data flash. */
301 HW_FLASH_LP_dataflash_enter_read_mode(p_ctrl);
302 }
303 }
304
305 #if (FLASH_CFG_PARAM_CODE_FLASH_PROGRAMMING_ENABLE == 1)
306 /** If flash is in P/E mode for code flash */
307 else if (p_faci_reg->FENTRYR == 0x0001U)
308 {
309 uint32_t temp = min_program_size;
310 uint32_t right_shift = 0U;
311 while (1U != temp)
312 {
313 temp >>= 1;
314 right_shift++;
315 }
316 /** Calculate the total number of writes. */
317 /* This is done with right shift instead of division to avoid using the division library, which would be in flash
318 * and cause a jump from RAM to flash. */
319 gp_flash_parameters->total_count = num_bytes >> right_shift;
320
321 /** Start the write operation */
322 HW_FLASH_LP_codeflash_write(p_ctrl, src_start_address, dest_start_address, num_bytes, min_program_size);
323
324 /** Code Flash is always blocking mode, so we don't return until the entire operation is complete */
325 do
326 {
327 err = HW_FLASH_LP_codeflash_write_monitor(p_ctrl, min_program_size);
328 } while (SSP_ERR_IN_USE == err);
329
330 /** Disable P/E mode for code flash. */
331 HW_FLASH_LP_codeflash_enter_read_mode(p_ctrl); // We're done, return to read mode
332 }
333 #endif /* if (FLASH_CFG_PARAM_CODE_FLASH_PROGRAMMING_ENABLE == 1) */
334 else
335 {
336 /** Otherwise return error. */
337 //Flash locked (FSPR bit?)
338 return SSP_ERR_PE_FAILURE;
339 }
340 return err;
341 }
342
343 /*******************************************************************************************************************//**
344 * @brief This function checks if the specified Data Flash address range is blank.
345 * @param[in] p_ctrl Pointer to the Flash control block
346 * @param[in] start_address The starting address of the Flash area to blank check.
347 * @param[in] num_bytes Specifies the number of bytes that need to be checked.
348 * @param[out] result Pointer that will be populated by the API with the results of the blank check
349 * operation in non-BGO (blocking) mode. In this case the blank check operation
350 * completes here and the result is returned. In Data Flash BGO mode the blank check
351 * operation is only started here and the result obtained later when the
352 * supplied callback routine is called.
353 * @retval SSP_SUCCESS Blankcheck operation completed with result in result,
354 * or blankcheck started and in-progess (BGO mode).
355 * @retval SSP_ERR_ERASE_FAILED Status is indicating an erase error. Possibly from a prior operation.
356 * @retval SSP_ERR_CMD_LOCKED FCU is in locked state, typically as a result of having received an illegal command.
357 * @retval SSP_ERR_WRITE_FAILED Status is indicating a Programming error for the requested operation.
358 * @retval SSP_ERR_TIMEOUT Timed out waiting for the FCU to become ready.
359 **********************************************************************************************************************/
HW_FLASH_LP_blankcheck(flash_lp_instance_ctrl_t * const p_ctrl,uint32_t start_address,uint32_t num_bytes,flash_result_t * result)360 ssp_err_t HW_FLASH_LP_blankcheck (flash_lp_instance_ctrl_t * const p_ctrl, uint32_t start_address, uint32_t num_bytes, flash_result_t * result)
361 {
362 ssp_err_t err = SSP_SUCCESS;
363 R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
364
365 /* We're already in the appropriate P/E mode from the caller */
366 /** If flash is configured for data flash P/E mode */
367 if (p_faci_reg->FENTRYR == 0x0080U)
368 {
369 /** Execute blank check command. */
370 HW_FLASH_LP_dataflash_blank_check(p_ctrl, start_address, (start_address + num_bytes) - 1); // We want to blank check 0
371 // - num_bytes-1
372 /** If in DF BGO mode, exit here; remaining processing if any will be done in ISR */
373 if (gp_flash_parameters->bgo_enabled_df == true)
374 {
375 *result = FLASH_RESULT_BGO_ACTIVE;
376 return err;
377 }
378
379 /** If not in DF BGO mode wait for the command to complete. */
380 do
381 {
382 err = HW_FLASH_LP_dataflash_blank_check_monitor(p_ctrl);
383 } while (SSP_ERR_IN_USE == err);
384
385 /** If successful check the result of the blank check. */
386 if (err == SSP_SUCCESS)
387 {
388 if (0U != p_faci_reg->FSTATR00_b.BCERR0) // Tested Flash Area is not blank
389 {
390 *result = FLASH_RESULT_NOT_BLANK;
391 }
392 else
393 {
394 *result = FLASH_RESULT_BLANK;
395 }
396
397 /** Reset the flash. */
398 HW_FLASH_LP_reset(p_ctrl); // Make sure we clear the BCERR bit that reflects the result of
399 // our blank check
400 /** Return the data flash to P/E mode. */
401 HW_FLASH_LP_dataflash_enter_read_mode(p_ctrl); // We're done, return to read mode
402 }
403 }
404 /** If flash is configured for code flash P/E mode */
405 else if (p_faci_reg->FENTRYR == 0x0001U)
406 {
407 /** Give the initial (and possibly only) Blank check command to the FACI. */
408 err = HW_FLASH_LP_codeflash_blank_check(p_ctrl, start_address, num_bytes);
409 if (err == SSP_SUCCESS)
410 {
411 do
412 {
413 /** Wait for the blank check to complete and return result in control block. */
414 err = HW_FLASH_LP_codeflash_blank_check_monitor(p_ctrl);
415 } while (SSP_ERR_IN_USE == err);
416
417 /** If succeessful reset the flash and put the code flash into read mode. */
418 if (err == SSP_SUCCESS)
419 {
420 *result = gp_flash_parameters->bc_result;
421 HW_FLASH_LP_reset(p_ctrl); // Make sure we clear the BCERR bit that reflects the result of our bc
422 HW_FLASH_LP_codeflash_enter_read_mode(p_ctrl); // We're done, return to read mode
423 }
424 }
425 }
426
427 /** Return status. Blank status is in result. */
428 return err;
429 }
430
431 /*******************************************************************************************************************//**
432 * @brief This function switches the peripheral to P/E mode for Code Flash or Data Flash.
433 * @param[in] p_ctrl Pointer to the Flash control block
434 * @param[in] flash_type Specifies Code or Data Flash.
435 * Valid selections are: FLASH_TYPE_CODE_FLASH or FLASH_TYPE_DATA_FLASH
436 * @retval SSP_SUCCESS Successfully entered P/E mode.
437 * @retval SSP_ERR_PE_FAILURE Failed to enter P/E mode
438 * @retval SSP_ERR_INVALID_ARGUMENT Supplied flash_type was something other than FLASH_TYPE_CODE_FLASH or
439 * FLASH_TYPE_DATA_FLASH, or Code Flash Programming is not enabled and a request to
440 * is for a CF operation.
441 *
442 **********************************************************************************************************************/
HW_FLASH_LP_pe_mode_enter(flash_lp_instance_ctrl_t * const p_ctrl,flash_type_t flash_type)443 ssp_err_t HW_FLASH_LP_pe_mode_enter (flash_lp_instance_ctrl_t * const p_ctrl, flash_type_t flash_type)
444 {
445 ssp_err_t err = SSP_SUCCESS;
446 R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
447
448 /** If the flas type is data flash put the data flash in PE mode. */
449 if (flash_type == FLASH_TYPE_DATA_FLASH)
450 {
451 HW_FLASH_LP_dataflash_enter_pe_mode(p_ctrl); // Sets PCKA clock
452
453 /** Verify that we actually did enter DF P/E mode. If not return error */
454 if (p_faci_reg->FENTRYR != 0x0080U)
455 {
456 err = SSP_ERR_PE_FAILURE;
457 }
458 }
459 #if (FLASH_CFG_PARAM_CODE_FLASH_PROGRAMMING_ENABLE == 1)
460 /** If the flash type is code flash put the code flash in PE mode */
461 else if (flash_type == FLASH_TYPE_CODE_FLASH)
462 {
463 HW_FLASH_LP_codeflash_enter_pe_mode(p_ctrl);
464
465 /** Verify that we actually did enter CF P/E mode. If not return error */
466 if (p_faci_reg->FENTRYR != 0x0001U)
467 {
468 err = SSP_ERR_PE_FAILURE;
469 }
470 }
471 #endif /* if (FLASH_CFG_PARAM_CODE_FLASH_PROGRAMMING_ENABLE == 1) */
472 else
473 {
474 /** If neither code flash or data flash command return error. */
475 err = SSP_ERR_INVALID_ARGUMENT;
476 }
477
478 return err;
479 }
480
481 /*******************************************************************************************************************//**
482 * @brief This function switches the peripheral from P/E mode for Code Flash or Data Flash to Read mode.
483 * @param[in] p_ctrl Pointer to the Flash control block
484 * @retval SSP_SUCCESS Successfully entered P/E mode.
485 * @retval SSP_ERR_PE_FAILURE Failed to exited P/E mode
486 * @retval SSP_FLASH_ERR_PARAMETERS Supplied flash_type was something other than FLASH_TYPE_CODE_FLASH or
487 * FLASH_TYPE_DATA_FLASH.
488 *
489 **********************************************************************************************************************/
HW_FLASH_LP_pe_mode_exit(flash_lp_instance_ctrl_t * const p_ctrl)490 ssp_err_t HW_FLASH_LP_pe_mode_exit (flash_lp_instance_ctrl_t * const p_ctrl)
491 {
492 R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
493
494 /** If device is configured for P/E mode for data flash exit P/E mode */
495 if (p_faci_reg->FENTRYR == 0x0080U)
496 {
497 HW_FLASH_LP_dataflash_enter_read_mode(p_ctrl);
498 }
499
500 #if (FLASH_CFG_PARAM_CODE_FLASH_PROGRAMMING_ENABLE == 1)
501 /** Otherwise if device is configured for P/E mode for code flash exit P/E mode. */
502 else if (p_faci_reg->FENTRYR == 0x0001U)
503 {
504 HW_FLASH_LP_codeflash_enter_read_mode(p_ctrl);
505 }
506 #endif
507 return (SSP_SUCCESS);
508 }
509
510 /*******************************************************************************************************************//**
511 * @brief This function resets the Flash sequencer.
512 * @param[in] p_ctrl Pointer to the Flash control block
513 **********************************************************************************************************************/
HW_FLASH_LP_reset(flash_lp_instance_ctrl_t * const p_ctrl)514 void HW_FLASH_LP_reset (flash_lp_instance_ctrl_t * const p_ctrl)
515 {
516 R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
517
518 /** If not currently in PE mode then enter P/E mode. */
519 if (p_faci_reg->FENTRYR == 0x0000UL)
520 {
521 /* Enter P/E mode so that we can execute some FACI commands. Either Code or Data Flash P/E mode would work
522 * but Code Flash P/E mode requires FLASH_CFG_PARAM_CODE_FLASH_PROGRAMMING_ENABLE ==1, which may not be true */
523 HW_FLASH_LP_pe_mode_enter(p_ctrl, FLASH_TYPE_DATA_FLASH);
524 }
525
526 /** Reset the flash. */
527 p_faci_reg->FRESETR_b.FRESET = 1U;
528 p_faci_reg->FRESETR_b.FRESET = 0U;
529
530 /** Transition to Read mode */
531 HW_FLASH_LP_pe_mode_exit(p_ctrl);
532
533 /** If DF BGO is enabled and we have an interrupt defined for FACI, re-enable it */
534 if (gp_flash_parameters->bgo_enabled_df == true)
535 {
536 /** Indicate that we just reset the FCU */
537 gp_flash_parameters->current_operation = FLASH_OPERATION_FCU_RESET;
538 }
539
540 }
541
542 /*******************************************************************************************************************//**
543 * @brief Handle the FACI frdyi interrupt when the operation is Data Flash BGO write.
544 * @param[in] p_ctrl Pointer to the Flash control block
545 * @param[in] p_cb_data Pointer to the Flash callback event structure.
546 * @retval true, when operation is completed or error has occurred.
547 *
548 **********************************************************************************************************************/
HW_FLASH_LP_frdyi_df_bgo_write(flash_lp_instance_ctrl_t * p_ctrl,flash_callback_args_t * p_cb_data)549 static inline bool HW_FLASH_LP_frdyi_df_bgo_write (flash_lp_instance_ctrl_t *p_ctrl, flash_callback_args_t *p_cb_data)
550 {
551 bool operation_complete = false;
552 ssp_err_t result = SSP_SUCCESS;
553
554 /** We are handling the interrupt indicating the last write operation has completed. */
555 /** Whether we are done or not we want to check the status */
556
557 result = HW_FLASH_LP_dataflash_write_monitor(p_ctrl, gp_flash_parameters->min_pgm_size);
558 if ((result != SSP_SUCCESS) && (result != SSP_ERR_IN_USE))
559 {
560 HW_FLASH_LP_reset(p_ctrl);
561 p_cb_data->event = FLASH_EVENT_ERR_FAILURE; ///< Pass result back to callback
562 operation_complete = true;
563 }
564 else
565 {
566 /*If there are still bytes to write*/
567 if (gp_flash_parameters->total_count == (uint32_t)0)
568 {
569 p_cb_data->event = FLASH_EVENT_WRITE_COMPLETE;
570 operation_complete = true;
571 }
572 }
573 return(operation_complete);
574 }
575
576 /*******************************************************************************************************************//**
577 * @brief Handle the FACI frdyi interrupt when the operation is Data Flash BGO erase.
578 * @param[in] p_ctrl Pointer to the Flash control block
579 * @param[in] p_cb_data Pointer to the Flash callback event structure.
580 * @retval true, when operation is completed or error has occurred.
581 *
582 **********************************************************************************************************************/
HW_FLASH_LP_frdyi_df_bgo_erase(flash_lp_instance_ctrl_t * p_ctrl,flash_callback_args_t * p_cb_data)583 static inline bool HW_FLASH_LP_frdyi_df_bgo_erase (flash_lp_instance_ctrl_t *p_ctrl, flash_callback_args_t *p_cb_data)
584 {
585 bool operation_complete = false;
586 ssp_err_t result = SSP_SUCCESS;
587
588 /** We are handling the interrupt indicating the last erase operation has completed. */
589 /** Whether we are done or not we want to check the status */
590 result = HW_FLASH_LP_dataflash_erase_monitor(p_ctrl, gp_flash_parameters->block_size);
591 if ((result != SSP_SUCCESS) && (result != SSP_ERR_IN_USE))
592 {
593 HW_FLASH_LP_reset(p_ctrl);
594 p_cb_data->event = FLASH_EVENT_ERR_FAILURE; ///< Pass result back to callback
595 operation_complete = true;
596 }
597 else
598 {
599 if (gp_flash_parameters->current_count > gp_flash_parameters->total_count)
600 {
601 p_cb_data->event = FLASH_EVENT_ERASE_COMPLETE;
602 operation_complete = true;
603 }
604 }
605 return(operation_complete);
606 }
607
608
609 /*******************************************************************************************************************//**
610 * @brief Handle the FACI frdyi interrupt when the operation is Data Flash BGO blankcheck.
611 * @param[in] p_ctrl Pointer to the Flash control block
612 * @param[in] p_cb_data Pointer to the Flash callback event structure.
613 * @retval true, when operation is completed or error has occurred.
614 *
615 **********************************************************************************************************************/
HW_FLASH_LP_frdyi_df_bgo_blankcheck(flash_lp_instance_ctrl_t * p_ctrl,flash_callback_args_t * p_cb_data)616 static inline bool HW_FLASH_LP_frdyi_df_bgo_blankcheck (flash_lp_instance_ctrl_t *p_ctrl, flash_callback_args_t *p_cb_data)
617 {
618 bool operation_complete = false;
619 ssp_err_t result = SSP_SUCCESS;
620 R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
621
622 /** We are handling the interrupt indicating the last blank check operation has completed. */
623 /** Whether we are done or not we want to check the status */
624 result = HW_FLASH_LP_dataflash_blank_check_monitor(p_ctrl);
625
626 /// All of the following are valid returns.
627 if ((result != SSP_SUCCESS) && (result != SSP_ERR_IN_USE))
628 {
629 HW_FLASH_LP_reset(p_ctrl);
630 p_cb_data->event = FLASH_EVENT_ERR_FAILURE; ///< Pass result back to callback
631 operation_complete = true;
632 }
633 else
634 {
635 operation_complete = true;
636 p_cb_data->event = FLASH_EVENT_BLANK;
637 if (p_faci_reg->FSTATR00_b.BCERR0 == 1U)
638 {
639 p_cb_data->event = FLASH_EVENT_NOT_BLANK;
640 }
641 }
642
643 return(operation_complete);
644 }
645
646 /*******************************************************************************************************************//**
647 * @brief FLASH ready interrupt routine.
648 *
649 * @details This function implements the FLASH ready isr. The function clears the interrupt request source on entry
650 * populates the callback structure with the relevant event, and providing
651 * a callback routine has been provided, calls the callback function with the event. <br>
652 *
653 **********************************************************************************************************************/
fcu_frdyi_isr(void)654 void fcu_frdyi_isr (void)
655 {
656 SF_CONTEXT_SAVE
657 flash_callback_args_t cb_data;
658 bool operation_completed = false;
659
660 ssp_vector_info_t * p_vector_info = NULL;
661 R_SSP_VectorInfoGet(R_SSP_CurrentIrqGet(), &p_vector_info);
662 flash_lp_instance_ctrl_t * p_ctrl = (flash_lp_instance_ctrl_t *) *(p_vector_info->pp_ctrl);
663
664 /** Clear the Interrupt Request*/
665 R_BSP_IrqStatusClear(R_SSP_CurrentIrqGet());
666
667 /** Continue the current operation. If unknown operation set callback event to failure. */
668 if (FLASH_OPERATION_DF_BGO_WRITE == gp_flash_parameters->current_operation)
669 {
670 operation_completed = HW_FLASH_LP_frdyi_df_bgo_write(p_ctrl, &cb_data);
671 }
672 else if ((FLASH_OPERATION_DF_BGO_ERASE == gp_flash_parameters->current_operation))
673 {
674 operation_completed = HW_FLASH_LP_frdyi_df_bgo_erase(p_ctrl, &cb_data);
675 }
676 else if (FLASH_OPERATION_DF_BGO_BLANKCHECK == gp_flash_parameters->current_operation)
677 {
678 operation_completed = HW_FLASH_LP_frdyi_df_bgo_blankcheck(p_ctrl, &cb_data);
679 }
680 else
681 {
682 /* This case could only be reached by a memory corruption of some type. */
683 cb_data.event = FLASH_EVENT_ERR_FAILURE;
684 }
685
686 /** If the operation completed exit read mode, release the flash, and call the callback if available. */
687 if (operation_completed == true)
688 {
689 /* finished current operation. Exit P/E mode*/
690 HW_FLASH_LP_pe_mode_exit(p_ctrl);
691
692 /* Release lock and Set current state to Idle*/
693 flash_ReleaseState();
694 gp_flash_parameters->current_operation = FLASH_OPERATION_IDLE;
695
696 if (NULL != p_ctrl->p_callback)
697 {
698 /** Set data to identify callback to user, then call user callback. */
699 p_ctrl->p_callback(&cb_data);
700 }
701 }
702 SF_CONTEXT_RESTORE
703 } /* End of function fcu_frdyi_isr() */
704