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, ¯o_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, ¯o_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