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_codeflash.c
22  * Description  : Code Flash Control processing for Low Power Flash
23  **********************************************************************************************************************/
24 
25 /******************************************************************************
26  * Includes   <System Includes> , “Project Includes”
27  ******************************************************************************/
28 #include "bsp_api.h"
29 #include "r_flash_lp.h"
30 #include "../hw_flash_lp_private.h"
31 #include "r_flash_cfg.h"
32 #include "hw_flash_common.h"
33 #include "hw_codeflash.h"
34 
35 /*******************************************************************************************************************//**
36  * @addtogroup FLASH
37  * @{
38  **********************************************************************************************************************/
39 /*******************************************************************************************************************//**
40  * @} (end FLASH)
41  **********************************************************************************************************************/
42 
43 /******************************************************************************
44  * Private global variables and functions
45  ******************************************************************************/
46 
47 static r_codeflash_data_t g_code_flash_info = {0U};
48 static void   HW_FLASH_LP_codeflash_write_fpmcr (flash_lp_instance_ctrl_t * const p_ctrl, uint8_t value) PLACE_IN_RAM_SECTION;
49 static current_parameters_t * gp_flash_settings = {0U};
50 static flash_lp_macro_info_t macro_info = {0U};
51 
52 
53 /*******************************************************************************************************************//**
54  * @brief   Transition to Code Flash P/E mode.
55  * @param[in]  p_ctrl       Pointer to the Flash control block
56  * @retval     none
57  **********************************************************************************************************************/
HW_FLASH_LP_codeflash_enter_pe_mode(flash_lp_instance_ctrl_t * const p_ctrl)58 void HW_FLASH_LP_codeflash_enter_pe_mode (flash_lp_instance_ctrl_t * const p_ctrl)
59 {
60     R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
61 
62     /** While the Flash API is in use we will disable the FLash Cache. */
63     p_ctrl->cache_state = BSP_CACHE_STATE_OFF;
64     R_BSP_CacheOff(&p_ctrl->cache_state);
65 
66     if (SSP_INVALID_VECTOR != p_ctrl->irq)
67     {
68         NVIC_DisableIRQ(p_ctrl->irq);           ///< We are not supporting Flash Rdy interrupts for Code Flash operations
69     }
70     p_faci_reg->FENTRYR = FENTRYR_CODEFLASH_PE_MODE;
71 
72     HW_FLASH_LP_codeflash_write_fpmcr(p_ctrl, DISCHARGE_1);
73 
74     /** Wait for 2us over (tDIS) */
75     HW_FLASH_LP_delay_us(WAIT_TDIS, gp_flash_settings->system_clock_freq);
76 
77     if (R_SYSTEM->OPCCR_b.OPCM == 0U)        ///< High speed mode?
78     {
79         HW_FLASH_LP_codeflash_write_fpmcr(p_ctrl, DISCHARGE_2);
80         HW_FLASH_LP_codeflash_write_fpmcr(p_ctrl, CODEFLASH_PE_MODE);
81 
82         /** Wait for 5us over (tMS) */
83         HW_FLASH_LP_delay_us(WAIT_TMS_HIGH, gp_flash_settings->system_clock_freq);
84     }
85     else
86     {
87         HW_FLASH_LP_codeflash_write_fpmcr(p_ctrl, DISCHARGE_2 | LVPE_MODE);
88         HW_FLASH_LP_codeflash_write_fpmcr(p_ctrl, CODEFLASH_PE_MODE | LVPE_MODE);
89 
90         /** Wait for 3us over (tMS) */
91         HW_FLASH_LP_delay_us(WAIT_TMS_MID, gp_flash_settings->system_clock_freq);
92 
93     }
94 
95     p_faci_reg->FISR_b.PCKA = (uint32_t)((gp_flash_settings->flash_clock_freq - 1UL) & (uint32_t)0x1F);
96 }
97 
98 /*******************************************************************************************************************//**
99  * @brief   This function switches the peripheral from P/E mode for Code Flash to Read mode.
100  * @param[in]  p_ctrl       Pointer to the Flash control block
101  * @retval SSP_SUCCESS              Successfully entered read mode.
102  * @retval SSP_ERR_TIMEOUT    Timed out waiting for confirmation of transition to read mode
103  *
104  **********************************************************************************************************************/
HW_FLASH_LP_codeflash_enter_read_mode(flash_lp_instance_ctrl_t * const p_ctrl)105 ssp_err_t HW_FLASH_LP_codeflash_enter_read_mode (flash_lp_instance_ctrl_t * const p_ctrl)
106 {
107     ssp_err_t         err = SSP_SUCCESS;
108     R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
109 
110     /** Timeout counter. */
111     volatile uint32_t wait_cnt = FLASH_FRDY_CMD_TIMEOUT;
112 
113     HW_FLASH_LP_codeflash_write_fpmcr(p_ctrl, DISCHARGE_2);
114 
115     /** Wait for 2us over (tDIS) */
116     HW_FLASH_LP_delay_us(WAIT_TDIS, gp_flash_settings->system_clock_freq);
117 
118     HW_FLASH_LP_codeflash_write_fpmcr(p_ctrl, DISCHARGE_1);
119     HW_FLASH_LP_codeflash_write_fpmcr(p_ctrl, READ_MODE);
120 
121     /** Wait for 5us over (tMS) */
122     HW_FLASH_LP_delay_us(WAIT_TMS_HIGH, gp_flash_settings->system_clock_freq);
123 
124     /** Clear the P/E mode register */
125     p_faci_reg->FENTRYR = FENTRYR_READ_MODE;
126 
127     /** Loop until the Flash P/E mode entry register is cleared or a timeout occurs. If timeout occurs return error. */
128     while (0x0000U != p_faci_reg->FENTRYR)
129     {
130         /* Confirm that the written value can be read correctly. */
131         if (wait_cnt <= (uint32_t)0)
132         {
133             /** Restore the FLash Cache state to what it was before we opened the Flash API. */
134             R_BSP_CacheSet(p_ctrl->cache_state);
135 
136             /* return timeout status*/
137             return SSP_ERR_TIMEOUT;
138         }
139         wait_cnt--;
140     }
141 
142     /** Restore the FLash Cache state to what it was before we opened the Flash API. */
143     R_BSP_CacheSet(p_ctrl->cache_state);
144 
145     return err;
146 }
147 
148 /*******************************************************************************************************************//**
149  * @brief   Initiates a Write sequence to the Low Power Code Flash data. Address validation has already been
150  *          performed by the caller.
151  * @param[in] p_ctrl              Pointer to the Flash control block
152  * @param[in] src_start_address   Start address of the (RAM) area which stores the programming data.
153  * @param[in] dest_start_address  Flash Start address which will be written.
154  * @param[in] num_bytes           Number of bytes to write.
155  * @param[in] min_program_size    Minimum flash programming size.
156  * @retval none.
157  **********************************************************************************************************************/
HW_FLASH_LP_codeflash_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)158 void HW_FLASH_LP_codeflash_write (flash_lp_instance_ctrl_t * const p_ctrl, uint32_t const src_start_address, uint32_t dest_start_address, uint32_t num_bytes,
159         uint32_t min_program_size)
160 {
161     R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
162     g_code_flash_info.start_addr = src_start_address;                // Ram Source for data to write
163     g_code_flash_info.end_addr   = dest_start_address;               // Flash Start address which will be written
164     uint32_t temp = min_program_size;
165     uint32_t right_shift = 0U;
166     while (1U != temp)
167     {
168         temp >>= 1;
169         right_shift++;
170     }
171     /** Calculate the number of writes needed. */
172     /* This is done with right shift instead of division to avoid using the division library, which would be in flash
173      * and cause a jump from RAM to flash. */
174     g_code_flash_info.write_cnt  = num_bytes >> right_shift;     //  Number of units to write
175 
176     /** Select User Area */
177     p_faci_reg->FASR_b.EXS = 0U;
178 
179     /** Initiate the code flash write operation. */
180     HW_FLASH_LP_codeflash_write_operation(p_ctrl, src_start_address, dest_start_address, min_program_size);
181 }
182 
183 /*******************************************************************************************************************//**
184  * @brief   Execute a single Write operation on the Low Power Code Flash data.
185  * @param[in] p_ctrl       Pointer to the Flash control block
186  * @param[in] psrc_addr    Source address for data to be written.
187  * @param[in] dest_addr    End address (read form) for writing.
188  * @param[in] min_program_size    Minimum flash programming size.
189  * @retval none.
190  **********************************************************************************************************************/
HW_FLASH_LP_codeflash_write_operation(flash_lp_instance_ctrl_t * const p_ctrl,const uint32_t psrc_addr,const uint32_t dest_addr,uint32_t min_program_size)191 void HW_FLASH_LP_codeflash_write_operation (flash_lp_instance_ctrl_t * const p_ctrl, const uint32_t psrc_addr, const uint32_t dest_addr,
192         uint32_t min_program_size)
193 {
194     R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
195     uint8_t * data8_ptr;
196     data8_ptr = (uint8_t *)psrc_addr;
197     uint16_t load_value;
198     uint8_t byteL;
199     uint8_t byteH;
200 
201     /** Write flash address setting */
202     p_faci_reg->FSARH = (uint16_t) ((dest_addr >> 16) & 0xFFFF);
203     p_faci_reg->FSARL = (uint16_t) (dest_addr & 0xFFFF);
204 
205     /** Write data address setting. */
206     /* Note that the caller could be providing a data buffer that was defined as a char[] buffer. As
207      * a result it might not be 16 bit aligned. For the CM0 data accesses that are not aligned will generate
208      * a fault. Therefore we will read the data 8 bits at a time.*/
209     byteL = *data8_ptr;
210     data8_ptr++;
211     byteH = *data8_ptr;
212     load_value = (uint16_t)(((uint16_t)byteH << 8) | (uint16_t)byteL);
213     data8_ptr++;
214 
215     p_faci_reg->FWBL0 = load_value;       // Move to bits 31 - 0 for next write.
216 
217     byteL = *data8_ptr;
218     data8_ptr++;
219     byteH = *data8_ptr;
220     load_value = (uint16_t)(((uint16_t)byteH << 8) | (uint16_t)byteL);
221     data8_ptr++;
222     p_faci_reg->FWBH0 = load_value;
223 
224     if (min_program_size > 4U)
225     {
226         byteL = *data8_ptr;
227         data8_ptr++;
228         byteH = *data8_ptr;
229         load_value = (uint16_t)(((uint16_t)byteH << 8) | (uint16_t)byteL);
230         data8_ptr++;
231         p_faci_reg->FWBL1 = load_value;
232 
233         byteL = *data8_ptr;
234         data8_ptr++;
235         byteH = *data8_ptr;
236         load_value = (uint16_t)(((uint16_t)byteH << 8) | (uint16_t)byteL);
237         data8_ptr++;
238         p_faci_reg->FWBH1 = load_value;
239     }
240 
241     /** Execute Write command */
242     p_faci_reg->FCR = FCR_WRITE;
243 }
244 
245 /*******************************************************************************************************************//**
246  * @brief   Waits for the write command to be completed and verifies the result of the command execution.
247  * @param[in]  p_ctrl       Pointer to the Flash control block
248  * @param[in]  min_program_size   Minimum flash programming size.
249  * @retval SSP_SUCCESS            Write command successfully completed.
250  * @retval SSP_ERR_IN_USE         Write command still in progress.
251  * @retval SSP_ERR_TIMEOUT        Timed out waiting for write command completion.
252  * @retval SSP_ERR_WRITE_FAILED   Write failed. Flash could be locked, area has not been erased or
253  *                                    address could be under access window control.
254  **********************************************************************************************************************/
HW_FLASH_LP_codeflash_write_monitor(flash_lp_instance_ctrl_t * const p_ctrl,uint32_t min_program_size)255 ssp_err_t HW_FLASH_LP_codeflash_write_monitor (flash_lp_instance_ctrl_t * const p_ctrl, uint32_t min_program_size)
256 {
257     ssp_err_t status;
258     R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
259 
260    /* Worst case timeout */
261     gp_flash_settings->wait_cnt = gp_flash_settings->wait_max_write_cf;
262 
263     /** Check the Flash Ready Flag bit*/
264     if (1U != p_faci_reg->FSTATR1_b.FRDY)
265     {
266         if (gp_flash_settings->wait_cnt <= (uint32_t)0)
267         {
268             /* if FRDY is not set to 0 after max timeout, return error*/
269             return SSP_ERR_TIMEOUT;
270         }
271         gp_flash_settings->wait_cnt--;
272         return SSP_ERR_IN_USE;
273     }
274 
275     /** Clear FCR register */
276     p_faci_reg->FCR = FCR_CLEAR;
277 
278     /* Worst case timeout */
279     gp_flash_settings->wait_cnt = gp_flash_settings->wait_max_write_cf;
280 
281     /** Wait for the Flash Ready Flag bit to indicate ready or a timeout to occur. If timeout return error. */
282     while (0U != p_faci_reg->FSTATR1_b.FRDY)
283     {
284         /** Check that execute command is completed. */
285         /** Wait until FRDY is 1 unless timeout occurs. */
286         if (gp_flash_settings->wait_cnt <= (uint32_t)0)
287         {
288             /** if FRDY is not set to 0 after max timeout, return error*/
289             return SSP_ERR_TIMEOUT;
290         }
291         gp_flash_settings->wait_cnt--;
292     }
293 
294     /** If invalid command status or programming failed status return error*/
295     if ((0U != p_faci_reg->FSTATR2_b.ILGLERR) || (0U != p_faci_reg->FSTATR2_b.PRGERR1))
296     {
297         HW_FLASH_LP_reset(p_ctrl);
298         status = SSP_ERR_WRITE_FAILED;
299     }
300     else
301     {
302         /** If there is more data to write then write the next data. */
303         g_code_flash_info.start_addr += min_program_size;
304         g_code_flash_info.end_addr   += min_program_size;
305         g_code_flash_info.write_cnt--;
306 
307         if (g_code_flash_info.write_cnt)
308         {
309             HW_FLASH_LP_codeflash_write_operation(p_ctrl, g_code_flash_info.start_addr, g_code_flash_info.end_addr,
310                     min_program_size);
311             status = SSP_ERR_IN_USE;
312         }
313         else
314         {
315             status = SSP_SUCCESS;
316         }
317     }
318 
319     /** Return status. */
320     return status;
321 }
322 
323 /*******************************************************************************************************************//**
324  * @brief   Initiates the Erase sequence to Erase the number of Code Flash blocks specified by num_blocks, starting with the
325  *          Block containing 'address'.
326  * @param[in] p_ctrl       Pointer to the Flash control block
327  * @param[in] start_addr - The block containing this address is the first block to be erased.
328  * @param[in] num_blocks - The # of blocks to be erased.
329  * @param[in] block_size - Size of this Flash block.
330  * @retval None.
331  **********************************************************************************************************************/
HW_FLASH_LP_codeflash_erase(flash_lp_instance_ctrl_t * const p_ctrl,const uint32_t start_addr,const uint32_t num_blocks,uint32_t block_size)332 void HW_FLASH_LP_codeflash_erase (flash_lp_instance_ctrl_t * const p_ctrl, const uint32_t start_addr, const uint32_t num_blocks, uint32_t block_size)
333 {
334     R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
335 
336     /** Configure the start and end addresses. */
337     g_code_flash_info.start_addr = start_addr;
338     g_code_flash_info.end_addr   = (start_addr + ((num_blocks * block_size) - 1U));
339 
340     /** Select User Area */
341     p_faci_reg->FASR_b.EXS = 0U;
342 
343     /** Start the code flash erase operation. */
344     HW_FLASH_LP_codeflash_erase_operation(p_ctrl, start_addr, block_size);
345 }
346 
347 /*******************************************************************************************************************//**
348  * @brief   Execute a single Erase operation on the Low Power Code Flash data.
349  * @param[in] p_ctrl       Pointer to the Flash control block
350  * @param[in] start_addr   Starting Code Flash address to erase.
351  * @param[in] block_size - Size of this Flash block.
352  * @retval none.
353  **********************************************************************************************************************/
HW_FLASH_LP_codeflash_erase_operation(flash_lp_instance_ctrl_t * const p_ctrl,const uint32_t start_addr,uint32_t block_size)354 void HW_FLASH_LP_codeflash_erase_operation (flash_lp_instance_ctrl_t * const p_ctrl, const uint32_t start_addr, uint32_t block_size)
355 {
356     uint32_t block_start_addr;
357     uint32_t block_end_addr;
358     R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
359 
360     block_start_addr = start_addr;
361     block_end_addr   = (block_start_addr + (block_size - 1U));
362 
363     /* Erase start address setting */
364     p_faci_reg->FSARH = (uint16_t) ((block_start_addr >> 16) & 0xFFFFU);
365     p_faci_reg->FSARL = (uint16_t) (block_start_addr & 0xFFFFU);
366 
367     /* Erase end address setting */
368     p_faci_reg->FEARH = ((block_end_addr >> 16) & 0xFFFFU);
369     p_faci_reg->FEARL = (uint16_t) (block_end_addr & 0xFFFFU);
370 
371     /* Execute Erase command */
372     p_faci_reg->FCR = FCR_ERASE;
373 }
374 
375 /*******************************************************************************************************************//**
376  * @brief   Waits for the erase command to be completed and verifies the result of the command execution.
377  * @param[in]  p_ctrl       Pointer to the Flash control block
378  * @param[in]  block_size - Size of this Flash block.
379  * @retval SSP_SUCCESS      Erase command successfully completed.
380  * @retval SSP_ERR_IN_USE   Erase command still in progress.
381  * @retval SSP_ERR_TIMEOUT  Timed out waiting for erase command completion.
382  * @retval SSP_ERR_WRITE_FAILED  Erase failed. Flash could be locked or address could be under access window
383  * control.
384  **********************************************************************************************************************/
HW_FLASH_LP_codeflash_erase_monitor(flash_lp_instance_ctrl_t * const p_ctrl,uint32_t block_size)385 ssp_err_t HW_FLASH_LP_codeflash_erase_monitor (flash_lp_instance_ctrl_t * const p_ctrl, uint32_t block_size)
386 {
387     ssp_err_t status;
388     R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
389 
390     /** If the flash operation has not completed return error. */
391     if (1U != p_faci_reg->FSTATR1_b.FRDY)
392     {
393         return SSP_ERR_IN_USE;
394     }
395 
396     /** Clear the Flash Control Register */
397     p_faci_reg->FCR = FCR_CLEAR;
398 
399     /** Prepare worst case timeout */
400     gp_flash_settings->wait_cnt = gp_flash_settings->wait_max_erase_cf_block;
401 
402     /** Wait until the ready flag is set or timeout. If timeout return error */
403     while (0U != p_faci_reg->FSTATR1_b.FRDY)
404     {
405         /** Check that execute command is completed. */
406         /** Wait until FRDY is 1 unless timeout occurs. */
407         if (gp_flash_settings->wait_cnt <= (uint32_t)0)
408         {
409             /* if FRDY is not set to 0 after max timeout, return error*/
410             return SSP_ERR_TIMEOUT;
411         }
412         gp_flash_settings->wait_cnt--;
413     }
414 
415     /** If invalid command or erase error flag is set reset and return error. */
416     if ((0U != p_faci_reg->FSTATR2_b.ILGLERR) || (0U != p_faci_reg->FSTATR2_b.ERERR))
417     {
418         HW_FLASH_LP_reset(p_ctrl);
419         return SSP_ERR_WRITE_FAILED;
420     }
421     else
422     {
423         /** If there are more blocks to erase initiate another erase operation. Otherwise return success. */
424         g_code_flash_info.start_addr += block_size;
425 
426         /* Check for CF0 overflow. */
427         if ((g_code_flash_info.start_addr < g_code_flash_info.end_addr) && (g_code_flash_info.start_addr != 0U))
428         {
429             HW_FLASH_LP_codeflash_erase_operation(p_ctrl, g_code_flash_info.start_addr, block_size);
430             status = SSP_ERR_IN_USE;
431         }
432         else
433         {
434             status = SSP_SUCCESS;
435         }
436     }
437 
438     return status;
439 }
440 
441 /*******************************************************************************************************************//**
442  * @brief   Initiates a Blank check sequence to the Low Power Code Flash data. Address validation has already been
443  *          performed by the caller.
444  * @param[in] p_ctrl       Pointer to the Flash control block
445  * @param[in] start_addr   Start address of the Code Flash area to blank check.
446  * @param[in] num_bytes    Number of bytes to blank check beginning at start_addr.
447  *
448  * @retval SSP_SUCCESS             Blank check command successfully issued to FACI controller.
449  * @retval SSP_ERR_INVALID_ADDRESS The address and num_bytes supplied do not exist in any of the Code Flash macros.
450  **********************************************************************************************************************/
HW_FLASH_LP_codeflash_blank_check(flash_lp_instance_ctrl_t * const p_ctrl,const uint32_t start_addr,uint32_t num_bytes)451 ssp_err_t HW_FLASH_LP_codeflash_blank_check (flash_lp_instance_ctrl_t * const p_ctrl, const uint32_t start_addr, uint32_t num_bytes)
452 {
453     ssp_err_t status = SSP_SUCCESS;
454 
455     gp_flash_settings->total_count   = num_bytes;  /*  Total Number of bytes to blank check */
456     gp_flash_settings->dest_addr     = start_addr;
457 
458     /** Get the macro information for this address. If failure skip blank check and return error. */
459     status = HW_FLASH_LP_code_get_macro_info(start_addr, num_bytes, &macro_info);
460 
461     gp_flash_settings->current_count = macro_info.allowed_bytes;
462 
463     /** If successful initiate the code flash blank check operation. */
464     if (status == SSP_SUCCESS)
465     {
466         HW_FLASH_LP_codeflash_blank_check_operation(p_ctrl, start_addr, macro_info.allowed_bytes);
467     }
468 
469     /** Return status */
470     return(status);
471 }
472 
473 /*******************************************************************************************************************//**
474  * @brief   Initiates a Blank check sequence to the Low Power Code Flash data. Address validation has already been
475  *          performed by the caller.
476  * @param[in] p_ctrl       Pointer to the Flash control block
477  * @param[in] start_addr   Start address of the Code Flash area to blank check.
478  * @param[in] num_bytes    Number of bytes to blank check beginning at start_addr.
479  *
480  * @retval none.
481  **********************************************************************************************************************/
HW_FLASH_LP_codeflash_blank_check_operation(flash_lp_instance_ctrl_t * const p_ctrl,const uint32_t start_addr,uint32_t num_bytes)482 void HW_FLASH_LP_codeflash_blank_check_operation (flash_lp_instance_ctrl_t * const p_ctrl, const uint32_t start_addr, uint32_t num_bytes)
483 {
484     uint32_t start_addr_idx;
485     uint32_t end_addr_idx;
486     R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
487 
488     start_addr_idx = start_addr;
489     end_addr_idx   = start_addr_idx + (num_bytes - 1U);
490 
491     /** Select User Area */
492     p_faci_reg->FASR_b.EXS = 0U;
493 
494     /** BlankCheck start address setting */
495     p_faci_reg->FSARH = (uint16_t) ((start_addr_idx >> 16) & 0xFFFFU);
496     p_faci_reg->FSARL = (uint16_t) (start_addr_idx & 0xFFFFU);
497 
498     /** BlankCheck end address setting */
499     p_faci_reg->FEARH = ((end_addr_idx >> 16) & 0xFFFFU);
500     p_faci_reg->FEARL = (uint16_t) (end_addr_idx & 0xFFFFU);
501 
502     /** Execute BlankCheck command */
503     p_faci_reg->FCR = FCR_BLANKCHECK;
504 }
505 
506 /*******************************************************************************************************************//**
507  * @brief   Waits for the blank check command to be completed and verifies the result of the command execution.
508  * @param[in]  p_ctrl       Pointer to the Flash control block
509  * @retval SSP_SUCCESS            Blank check command successfully completed.
510  * @retval SSP_ERR_IN_USE         Blank check command still in progress.
511  * @retval SSP_ERR_TIMEOUT       Timed out waiting for Blank check command completion.
512  **********************************************************************************************************************/
HW_FLASH_LP_codeflash_blank_check_monitor(flash_lp_instance_ctrl_t * const p_ctrl)513 ssp_err_t HW_FLASH_LP_codeflash_blank_check_monitor (flash_lp_instance_ctrl_t * const p_ctrl)
514 {
515     ssp_err_t status = SSP_SUCCESS;
516     R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
517     gp_flash_settings->bc_result = FLASH_RESULT_BLANK;
518 
519     /** If the flash has not completed the software command return error. */
520     if (1U != p_faci_reg->FSTATR1_b.FRDY)
521     {
522         return SSP_ERR_IN_USE;
523     }
524 
525     /** Clear the Flash Control Register */
526     p_faci_reg->FCR = FCR_CLEAR;
527 
528     /** Prepare worst case timeout counter */
529     gp_flash_settings->wait_cnt = gp_flash_settings->wait_max_blank_check;
530 
531     while (0U != p_faci_reg->FSTATR1_b.FRDY)
532     {
533         /** Check that execute command is completed. */
534         /** Wait until FRDY is 1 unless timeout occurs. If timeout return error. */
535         if (gp_flash_settings->wait_cnt <= 0U)
536         {
537             /** if FRDY is not set to 0 after max timeout, return error*/
538             return SSP_ERR_TIMEOUT;
539         }
540         gp_flash_settings->wait_cnt--;
541     }
542 
543     /** If illegal command, reset and return error. */
544     if (0U != p_faci_reg->FSTATR2_b.ILGLERR)
545     {
546         HW_FLASH_LP_reset(p_ctrl);
547         status = SSP_ERR_WRITE_FAILED;
548     }
549     else
550     {
551         if (0U != p_faci_reg->FSTATR00_b.BCERR0)           // Tested Flash Area is not blank
552         {
553             /** If the result is already NOT Blank there is no reason to continue with any subsequent checks, simply return */
554             gp_flash_settings->bc_result = FLASH_RESULT_NOT_BLANK;
555             status = SSP_SUCCESS;
556         }
557         else
558         {
559             /* Only S3A7 (2 CF macros) Code Flash blank checking is concerned with hardware macros and spanning boundaries. */
560             /** If the flash has more than one code flash macro */
561             if (gp_flash_settings->flash_cf_macros > 1U)
562             {
563                 /** If there is more data to blank check adjust the operation settings. */
564                 gp_flash_settings->total_count -= gp_flash_settings->current_count;  /*  Update remaining amount to BC. */
565                 gp_flash_settings->dest_addr += gp_flash_settings->current_count;
566 
567                 /** Get the macro information for this address */
568                 status = HW_FLASH_LP_code_get_macro_info(gp_flash_settings->dest_addr, gp_flash_settings->total_count, &macro_info);
569                 gp_flash_settings->current_count = macro_info.allowed_bytes;
570 
571                 /** If the original request was split as it spanms flash hardware macros */
572                 if (gp_flash_settings->total_count != 0U)
573                 {
574                     /** Begin next Blankcheck operation. */
575                     HW_FLASH_LP_codeflash_blank_check_operation(p_ctrl, gp_flash_settings->dest_addr, macro_info.allowed_bytes);
576                     status = SSP_ERR_IN_USE;
577                 }
578                 else
579                 {
580                     status = SSP_SUCCESS;
581                 }
582             }
583         }
584     }
585 
586     /** Return status. */
587     return status;
588 }
589 
590 /*******************************************************************************************************************//**
591  * @brief   Sets the FPMCR register, used to place the Flash sequencer in Code Flash P/E mode.
592  * @param[in] p_ctrl  Pointer to the Flash control block
593  * @param[in] value - 8 bit value to be written to the FPMCR register.
594  * @retval none.
595  **********************************************************************************************************************/
HW_FLASH_LP_codeflash_write_fpmcr(flash_lp_instance_ctrl_t * const p_ctrl,uint8_t value)596 static void HW_FLASH_LP_codeflash_write_fpmcr (flash_lp_instance_ctrl_t * const p_ctrl, uint8_t value)
597 {
598     R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
599 
600     p_faci_reg->FPR   = 0xA5U;
601 
602     p_faci_reg->FPMCR = value;
603     p_faci_reg->FPMCR = (uint8_t) ~value;
604     p_faci_reg->FPMCR = value;
605 
606     if (value == p_faci_reg->FPMCR)
607     {
608         __NOP();
609     }
610 }
611 
612 /*******************************************************************************
613  * Outline      : Give the Code Flash HW layer access to the flash settings
614  * Header       : none
615  * Function Name: set_flash_settings
616  * Description  : Give the HW layer access to the flash settings
617  * @param[in] p_current_parameters - Pointer the settings.
618  *             :
619  * Return Value : none
620  *******************************************************************************/
HW_FLASH_LP_code_flash_set_flash_settings(current_parameters_t * const p_current_parameters)621 void HW_FLASH_LP_code_flash_set_flash_settings (current_parameters_t * const p_current_parameters)
622 {
623     gp_flash_settings = p_current_parameters;
624 }
625 
626 
627 /*******************************************************************************************************************//**
628  * @brief   Given an address and number of bytes, determine how many of those bytes are in a single Flash macro.
629  * @param[in]  address      Address to query
630  * @param[in]  num_bytes    Number of byte starting at Address
631  * @param[in]  p_macro      Pointer to the Flash macro information
632  * @retval SSP_ERR_INVALID_ADDRESS The address and num_bytes supplied do not exist in any of the Code or Data Flash macros.
633  * @retval SSP_SUCCESS             Successful query. p_macro contains details.
634  **********************************************************************************************************************/
HW_FLASH_LP_code_get_macro_info(uint32_t const address,uint32_t num_bytes,flash_lp_macro_info_t * const p_macro)635 ssp_err_t HW_FLASH_LP_code_get_macro_info (uint32_t const address, uint32_t num_bytes, flash_lp_macro_info_t * const p_macro)
636 {
637     ssp_err_t err;
638 
639     p_macro->allowed_bytes = num_bytes;
640     p_macro->macro_st_addr = address;
641 
642     /* Only S3A7 (2 CF macros) Code Flash blank checking is concerned with hardware macros and spanning boundaries. */
643     /** If the MCU has more than one code flash macro determine the macro the requested address is in. */
644     if (gp_flash_settings->flash_cf_macros > 1U)
645     {
646         err = SSP_ERR_INVALID_ADDRESS;
647         p_macro->macro_size = gp_flash_settings->cf_macro_size;   // The size of the implemented Code Flash macro
648         p_macro->total_macros = gp_flash_settings->flash_cf_macros;
649         p_macro->macro_st_addr = gp_flash_settings->cf_memory_st_addr;
650         p_macro->macro_end_addr = (p_macro->macro_st_addr + p_macro->macro_size) - 1U;
651 
652         for (uint32_t i=0U; i<p_macro->total_macros; i++)
653         {
654             /* Is the address in the range of this macro? */
655             if ((address >= p_macro->macro_st_addr) && (address <= p_macro->macro_end_addr))
656             {
657                 /* Yes, how many bytes can be accommodated out of the request? */
658                 if (((p_macro->macro_end_addr - address) + 1U) < num_bytes)
659                 {
660                     p_macro->allowed_bytes = (p_macro->macro_end_addr - address) + 1U;
661                 }
662                 err = SSP_SUCCESS;
663                 break;
664             }
665             else
666             {
667                 p_macro->macro_st_addr = p_macro->macro_end_addr + 1U;
668                 p_macro->macro_end_addr = (p_macro->macro_st_addr + p_macro->macro_size) - 1U;
669             }
670         }
671     }
672     else
673     {
674         err = SSP_SUCCESS;
675     }
676     return err;
677 }
678