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_extra.c
22  * Description  : Flash Control Access window and swap 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_dataflash.h"
34 #include "hw_codeflash.h"
35 #include "hw_codeflash_extra.h"
36 
37 /*******************************************************************************************************************//**
38  * @addtogroup FLASH
39  * @{
40  **********************************************************************************************************************/
41 /*******************************************************************************************************************//**
42  * @} (end FLASH)
43  **********************************************************************************************************************/
44 
45 /******************************************************************************
46  * Private global variables and functions
47  ******************************************************************************/
48 
49 /*******************************************************************************************************************//**
50  * @brief Temporarily sets the startup area to use the DEFAULT or ALTERNATE area as requested.
51  * On the next subsequent reset, the startup area will be determined by the state of the BTFLG.
52  * This command does NOT modify the configuration via The Configuration Set command, hence these changes are
53  * only in effect until the next reset.
54  * @param[in]  p_ctrl       Pointer to the Flash control block
55  * @param[in]  swap_type -  specifies the startup area swap being requested.
56  *
57  * @retval SSP_SUCCESS                StartUp area temporarily modified.
58  **********************************************************************************************************************/
HW_FLASH_LP_set_startup_area_temporary(flash_lp_instance_ctrl_t * const p_ctrl,flash_startup_area_swap_t swap_type)59 ssp_err_t HW_FLASH_LP_set_startup_area_temporary (flash_lp_instance_ctrl_t * const p_ctrl, flash_startup_area_swap_t swap_type)
60 {
61     ssp_err_t err = SSP_SUCCESS;
62     R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
63 
64     /** Set the Flash initial setting startup area select bit as requested. */
65     if (FLASH_STARTUP_AREA_BLOCK0 == swap_type)
66     {
67         p_faci_reg->FISR_b.SAS =  SAS_DEFAULT_AREA;
68     }
69     else if (FLASH_STARTUP_AREA_BLOCK1 == swap_type)
70     {
71         p_faci_reg->FISR_b.SAS =  SAS_ALTERNATE_AREA;
72     }
73     else
74     {
75         p_faci_reg->FISR_b.SAS =  (uint32_t)SAS_PER_BTFLG_AREA;
76     }
77 
78     return err;
79 }
80 
81 /*******************************************************************************************************************//**
82  * @brief  Configure an access window for the Code Flash memory using the provided start and end address. An access
83  *         window defines a contiguous area in Code Flash for which programming/erase is enabled. This area is
84  *         on block boundaries.
85  *         The block containing start_addr is the first block. The block containing end_addr is the last block.
86  *         The access window then becomes first block - last block inclusive. Anything outside this range
87  *         of Code Flash is then write protected.
88  *         This command DOES modify the configuration via The Configuration Set command to update the FAWS and FAWE.
89  *
90  * @param[in]  p_ctrl     Pointer to the Flash control block
91  * @param[in]  start_addr Determines the Starting block for the Code Flash access window.
92  * @param[in]  end_addr   Determines the Ending block for the Code Flash access window.
93  *
94  * @retval SSP_SUCCESS                Access window successfully configured.
95  * @retval SSP_ERR_ERASE_FAILED        Status is indicating an erase error. Possibly from a prior operation.
96  * @retval SSP_ERR_CMD_LOCKED   FCU is in locked state, typically as a result of having received an illegal
97  * command.
98  * @retval SSP_ERR_WRITE_FAILED  Status is indicating a Programming error for the requested operation.
99  * @retval SSP_ERR_TIMEOUT Timed out waiting for the FCU to become ready.
100  **********************************************************************************************************************/
HW_FLASH_LP_access_window_set(flash_lp_instance_ctrl_t * const p_ctrl,uint32_t const start_addr,uint32_t const end_addr)101 ssp_err_t HW_FLASH_LP_access_window_set (flash_lp_instance_ctrl_t * const p_ctrl, uint32_t const start_addr, uint32_t const end_addr)
102 {
103     ssp_err_t err = SSP_SUCCESS;
104     R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
105 
106     uint32_t  start_addr_idx;
107     uint32_t  end_addr_idx;
108 
109     start_addr_idx = start_addr;
110     end_addr_idx   = end_addr;
111 
112     /** Select The Extra Area */
113     p_faci_reg->FASR_b.EXS = 1U;
114 
115     /** Set the access window. */
116     HW_FLASH_LP_extra_operation(p_ctrl, start_addr_idx, end_addr_idx, FLASH_COMMAND_ACCESSWINDOW);
117 
118     /** Wait for the operation to complete or error. */
119     do
120     {
121         err = HW_FLASH_LP_extra_check(p_ctrl);
122     } while (SSP_ERR_IN_USE == err);
123 
124     /** Select User Area */
125     p_faci_reg->FASR_b.EXS = 0U;
126 
127     /** Return status. */
128     return err;
129 }
130 
131 /*******************************************************************************************************************//**
132  * @brief  Remove any access window that is currently configured in the Code Flash.
133  *         This command DOES modify the configuration via The Configuration Set command to update the FAWS and FAWE.
134  *         Subsequent to this call all Code Flash is writable.
135  *
136  * @retval SSP_SUCCESS              Access window successfully removed.
137  * @retval SSP_ERR_ERASE_FAILED      Status is indicating an erase error. Possibly from a prior operation.
138  * @retval SSP_ERR_CMD_LOCKED   FCU is in locked state, typically as a result of having received an illegal
139  * command.
140  * @retval SSP_ERR_WRITE_FAILED  Status is indicating a Programming error for the requested operation.
141  * @retval SSP_ERR_TIMEOUT      Timed out waiting for the FCU to become ready.
142  * @param[in]  p_ctrl           Pointer to the Flash control block
143  **********************************************************************************************************************/
HW_FLASH_LP_access_window_clear(flash_lp_instance_ctrl_t * const p_ctrl)144 ssp_err_t HW_FLASH_LP_access_window_clear (flash_lp_instance_ctrl_t * const p_ctrl)
145 {
146     ssp_err_t err = SSP_SUCCESS;
147     R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
148 
149     /** Select Extra Area */
150     p_faci_reg->FASR_b.EXS = 1U;
151 
152     // Setting the accesswindow to 0,0 will clear any configured access window.
153     /** Call extra operation to clear the access window. */
154     HW_FLASH_LP_extra_operation(p_ctrl, 0, 0, FLASH_COMMAND_ACCESSWINDOW);
155 
156     /** Wait until the operation is complete or an error. */
157     do
158     {
159         err = HW_FLASH_LP_extra_check(p_ctrl);
160     } while (SSP_ERR_IN_USE == err);
161 
162     /** Select User Area */
163     p_faci_reg->FASR_b.EXS = 0U;
164 
165     return err;
166 }
167 
168 /*******************************************************************************************************************//**
169  * @brief      Set the id code
170  *
171  * @param      p_ctrl                The p control
172  * @param      p_id_code             Pointer to the code to be written
173  * @param[in]  mode                  The id code mode
174  *
175  * @retval     SSP_SUCCESS           The id code have been written.
176  * @retval     SSP_ERR_WRITE_FAILED  Status is indicating a Programming error for the requested operation.
177  * @retval     SSP_ERR_TIMEOUT       Timed out waiting for completion of extra command.
178  **********************************************************************************************************************/
HW_FLASH_LP_set_id_code(flash_lp_instance_ctrl_t * const p_ctrl,uint8_t const * const p_id_code,flash_id_code_mode_t mode)179 ssp_err_t HW_FLASH_LP_set_id_code (flash_lp_instance_ctrl_t       * const p_ctrl,
180                                    uint8_t                  const * const p_id_code,
181                                    flash_id_code_mode_t                   mode)
182 {
183     ssp_err_t err = SSP_SUCCESS;
184     R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
185     uint32_t fexcr_command = FEXCR_OCDID1;
186 
187     uint16_t mode_mask = 0U;
188 
189     if(FLASH_ID_CODE_MODE_LOCKED_WITH_ALL_ERASE_SUPPORT == mode)
190     {
191         mode_mask = 0xC000U;
192     }
193 
194     if(FLASH_ID_CODE_MODE_LOCKED == mode)
195     {
196         mode_mask = 0x8000U;
197     }
198 
199     /* Timeout counter. */
200     volatile uint32_t wait_cnt = FLASH_FRDY_CMD_TIMEOUT;
201 
202     /** For each ID byte register */
203     for(uint32_t i = 0U; i < 16U; i+=4U)
204     {
205         /** Select Extra Area */
206         p_faci_reg->FASR_b.EXS = 1U;
207 
208         /** Write the ID Bytes. If mode is unlocked write all 0xFF. Write the mode mask to the MSB. */
209         if(FLASH_ID_CODE_MODE_UNLOCKED == mode)
210         {
211             p_faci_reg->FWBL0 = 0xFFFFU;
212             p_faci_reg->FWBH0 = 0xFFFFU;
213         }
214         else
215         {
216             /* The id code array may be unaligned. Do not attempt to optimize this code to prevent unaligned access. */
217             p_faci_reg->FWBL0 = (uint32_t)(p_id_code[i] | ((uint32_t)p_id_code[i+1] << 8));
218             if(12U == i)
219             {
220                 p_faci_reg->FWBH0 = (uint32_t)(p_id_code[i+2] | ((uint32_t)p_id_code[i+3] << 8)) | mode_mask;
221             }
222             else
223             {
224                 p_faci_reg->FWBH0 = (uint32_t)(p_id_code[i+2] | ((uint32_t)p_id_code[i+3] << 8));
225             }
226         }
227 
228         /** Execute OCDID command */
229         p_faci_reg->FEXCR = fexcr_command;
230 
231         /** Increment the command to write to the next OCDID bytes */
232         fexcr_command++;
233 
234         /** Wait until the operation is complete or an error. */
235         do
236         {
237             err = HW_FLASH_LP_extra_check(p_ctrl);
238             wait_cnt--;
239             if(wait_cnt == 0U)
240             {
241                 err = SSP_ERR_TIMEOUT;
242             }
243         } while (SSP_ERR_IN_USE == err);
244 
245         /** Select User Area */
246         p_faci_reg->FASR_b.EXS = 0U;
247 
248         /** If failure return error */
249         if(SSP_SUCCESS != err)
250         {
251             return err;
252         }
253     }
254 
255     return err;
256 }
257 
258 /*******************************************************************************************************************//**
259  * @brief Modifies the start-up program swap flag (BTFLG) based on the supplied parameters. These changes will
260  *        take effect on the next reset. This command DOES modify the configuration via The Configuration
261  *        Set command to update the BTFLG.
262  *
263  * @retval SSP_SUCCESS                Access window successfully removed.
264  * @retval SSP_ERR_ERASE_FAILED        Status is indicating an erase error. Possibly from a prior operation.
265  * @retval SSP_ERR_CMD_LOCKED   FCU is in locked state, typically as a result of having received an illegal
266  * command.
267  * @retval SSP_ERR_WRITE_FAILED  Status is indicating a Programming error for the requested operation.
268  * @retval SSP_ERR_TIMEOUT Timed out waiting for the FCU to become ready.
269  *
270  * @param[in]  p_ctrl       Pointer to the Flash control block
271  * @param[in]  swap_type -  specifies the startup area swap being requested.
272  **********************************************************************************************************************/
HW_FLASH_LP_set_startup_area_boot(flash_lp_instance_ctrl_t * const p_ctrl,flash_startup_area_swap_t swap_type)273 ssp_err_t HW_FLASH_LP_set_startup_area_boot (flash_lp_instance_ctrl_t * const p_ctrl, flash_startup_area_swap_t swap_type)
274 {
275     ssp_err_t err               = SSP_SUCCESS;
276     R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
277     uint32_t  startup_area_mask = (uint32_t)((uint32_t)swap_type << 8);       // move selection to bit 8
278 
279     /** Select Extra Area */
280     p_faci_reg->FASR_b.EXS = 1U;
281 
282     /** Call extra operation to set the startup area. */
283     HW_FLASH_LP_extra_operation(p_ctrl, startup_area_mask, 0, FLASH_COMMAND_STARTUPAREA);
284 
285     /** Wait until the operation is complete or an error occurs. */
286     do
287     {
288         err = HW_FLASH_LP_extra_check(p_ctrl);
289     } while (SSP_ERR_IN_USE == err);
290 
291     /** Select User Area */
292     p_faci_reg->FASR_b.EXS = 0U;
293 
294     return err;
295 }
296 
297 /*******************************************************************************************************************//**
298  * @brief  Command processing for the extra area.
299  *
300  * @param[in]  p_ctrl                    Pointer to the Flash control block
301  * @param[in]  start_addr_startup_value  Determines the Starting block for the Code Flash access window.
302  * @param[in]  end_addr                  Determines the Ending block for the Code Flash access window.
303  * @param[in]  command                   Select from R_FLASH_ACCESSWINDOW or R_FLASH_STARTUPAREA.
304  *
305  **********************************************************************************************************************/
HW_FLASH_LP_extra_operation(flash_lp_instance_ctrl_t * const p_ctrl,const uint32_t start_addr_startup_value,const uint32_t end_addr,r_flash_command_t command)306 void HW_FLASH_LP_extra_operation (flash_lp_instance_ctrl_t * const p_ctrl, const uint32_t    start_addr_startup_value,
307                                          const uint32_t    end_addr,
308                                          r_flash_command_t command)
309 {
310     R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
311     /* Per the spec: */
312     /* Setting data to the FWBL0 register, this command is allowed to select the start-up area from the */
313     /* default area (blocks 0-3) to the alternative area (blocks 4-7) and set the security. */
314     /* Bit 8 of the FWBL0 register is 0: the alternative area (blocks 4-7) are selected as the start-up area. */
315     /* Bit 8 of the FWBL0 register is 1: the default area (blocks 0-3) are selected as the start-up area. */
316     /* Bit 14 of the FWBL0 register MUST be 1! Setting this bit to zero will clear the FSPR register and lock the */
317     /* FLASH!!! It is not be possible to unlock it. */
318 
319     if (FLASH_COMMAND_ACCESSWINDOW == command)
320     {
321         /** Set the Access Window start and end addresses. */
322         /* FWBL0 reg sets the Start Block address. FWBH0 reg sets the end address. */
323         /* Convert the addresses to their respective block numbers */
324         p_faci_reg->FWBL0 = ((start_addr_startup_value >> 10) & 0xFFFFU);
325         p_faci_reg->FWBH0 = ((end_addr >> 10) & 0xFFFFU);
326 
327         /** Execute Access Window command */
328         p_faci_reg->FEXCR = FEXCR_AW;
329     }
330     else
331     {
332         /* Startup Area Flag value setting */
333         p_faci_reg->FWBH0 = 0xFFFFU;
334 
335         /* FSPR must be set. Unused bits write value should be 1. */
336         p_faci_reg->FWBL0 = (start_addr_startup_value | 0xFEFFU);
337 
338         /** Execute Startup Area Flag command */
339         p_faci_reg->FEXCR = FEXCR_STARTUP;
340     }
341 }
342 
343 /*******************************************************************************************************************//**
344  * @brief      Verifying the execution result for the extra area.
345  * @param[in]  p_ctrl                Pointer to the Flash control block
346  * @retval     SSP_SUCCESS           The extra command has successfully completed.
347  * @retval     SSP_ERR_WRITE_FAILED  Status is indicating a Programming error for the requested operation.
348  * @retval     SSP_ERR_TIMEOUT       Timed out waiting for completion of extra command.
349  **********************************************************************************************************************/
HW_FLASH_LP_extra_check(flash_lp_instance_ctrl_t * const p_ctrl)350 ssp_err_t HW_FLASH_LP_extra_check (flash_lp_instance_ctrl_t * const p_ctrl)
351 {
352     R_FACI_Type * p_faci_reg = (R_FACI_Type *) p_ctrl->p_reg;
353 
354     /* Timeout counter. */
355     volatile uint32_t wait_cnt = FLASH_FRDY_CMD_TIMEOUT;
356 
357     /** If the software command of the FEXCR register is not terminated return in use. */
358     if (1U != p_faci_reg->FSTATR1_b.EXRDY)
359     {
360         return SSP_ERR_IN_USE;
361     }
362 
363     /** Clear the Flash Extra Area Control Register. */
364     p_faci_reg->FEXCR = FEXCR_CLEAR;
365 
366     /** Wait until the command has completed or a timeout occurs. If timeout return error. */
367     while (0U != p_faci_reg->FSTATR1_b.EXRDY)
368     {
369         /* Check that execute command is completed. */
370         /* Confirm that the written value can be read correctly. */
371         if (wait_cnt <= (uint32_t)0)
372         {
373             /* return timeout status*/
374             return SSP_ERR_TIMEOUT;
375         }
376         wait_cnt--;
377     }
378 
379     /** If Extra Area Illegal Command Error Flag or Error during programming reset the flash and return error. */
380     if ((0U != p_faci_reg->FSTATR00_b.EILGLERR) || (0U != p_faci_reg->FSTATR00_b.PRGERR01))
381     {
382         HW_FLASH_LP_reset(p_ctrl);
383         return SSP_ERR_WRITE_FAILED;
384     }
385 
386     /** Return success. */
387     return SSP_SUCCESS;
388 }
389 
390