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