1 /**
2  * @file xmc4_flash.c
3  * @date 2016-01-08
4  *
5  * @cond
6  *********************************************************************************************************************
7  * XMClib v2.1.24 - XMC Peripheral Driver Library
8  *
9  * Copyright (c) 2015-2019, Infineon Technologies AG
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without modification,are permitted provided that the
13  * following conditions are met:
14  *
15  * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
16  * disclaimer.
17  *
18  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
19  * disclaimer in the documentation and/or other materials provided with the distribution.
20  *
21  * Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote
22  * products derived from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE  FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  * WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * To improve the quality of the software, users are encouraged to share modifications, enhancements or bug fixes with
33  * Infineon Technologies AG dave@infineon.com).
34  *********************************************************************************************************************
35  *
36  * Change History
37  * --------------
38  *
39  * 2015-02-10:
40  *     - Initial <br>
41  *
42  * 2015-06-20:
43  *     - Removed definition of GetDriverVersion API
44  *
45  * 2015-08-17:
46  *     - Added the below API's to the public interface.
47  *       1. XMC_FLASH_Reset
48  *       2. XMC_FLASH_ErasePhysicalSector
49  *       3. XMC_FLASH_EraseUCB
50  *       4. XMC_FLASH_ResumeProtection
51  *       5. XMC_FLASH_RepairPhysicalSector
52  *
53  * 2016-01-08:
54  *     - Wait until operation is finished for the next functions:
55  *       1. XMC_FLASH_InstallProtection
56  *       2. XMC_FLASH_ConfirmProtection
57  *       3. XMC_FLASH_ProgramPage
58  *       4. XMC_FLASH_EraseSector
59  *       5. XMC_FLASH_ErasePhysicalSector
60  *       6. XMC_FLASH_EraseUCB
61  *     - Fix XMC_FLASH_VerifyReadProtection and XMC_FLASH_VerifyWriteProtection
62  *
63  * 2018-02-08
64  *     - Added implementation of XMC_FLASH_InstallBMI()
65  *
66  * @endcond
67  *
68  */
69 
70 #include "xmc_flash.h"
71 
72 #if UC_FAMILY == XMC4
73 
74 /*********************************************************************************************************************
75  * MACROS
76  ********************************************************************************************************************/
77 
78 #define XMC_FLASH_PROTECTION_CONFIGURATION_WORDS (8UL) /* Used to upadte the assembly buffer during protection
79                                                           configuration */
80 #define XMC_FLASH_BMI_STRING_WORDS (10UL) /* Used to upadte the assembly buffer during BMI String
81                                                           configuration */
82 
83 #define XMC_FLASH_PROT_CONFIRM_OFFSET (512UL) /* Offset address for UCB page */
84 #define XMC_FLASH_PROT_CONFIRM_WORDS  (4UL)
85 #define XMC_FLASH_PROT_CONFIRM_CODE   (0x8AFE15C3UL)
86 
87 /*********************************************************************************************************************
88  * LOCAL FUNCTIONS
89  ********************************************************************************************************************/
90 void XMC_FLASH_lEnterPageModeCommand(void);
91 void XMC_FLASH_lLoadPageCommand(uint32_t low_word, uint32_t high_word);
92 void XMC_FLASH_lWritePageCommand(uint32_t *page_start_address);
93 void XMC_FLASH_lWriteUCBPageCommand(uint32_t *page_start_address);
94 void XMC_FLASH_lEraseSectorCommand(uint32_t *sector_start_address);
95 void XMC_FLASH_lDisableSectorWriteProtectionCommand(uint32_t user, uint32_t password_0, uint32_t password_1);
96 void XMC_FLASH_lDisableReadProtectionCommand(uint32_t password_0, uint32_t password_1);
97 void XMC_FLASH_lRepairPhysicalSectorCommand(void);
98 void XMC_FLASH_lErasePhysicalSectorCommand(uint32_t *sector_start_address);
99 void XMC_FLASH_lClearStatusCommand(void);
100 
101 /*
102  * Command to program the PFLASH in to page mode, so that assembly buffer is used
103  */
XMC_FLASH_lEnterPageModeCommand(void)104 void XMC_FLASH_lEnterPageModeCommand(void)
105 {
106   volatile uint32_t *address;
107 
108   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5554U);
109   *address = (uint32_t)0x50U;
110 }
111 
112 /*
113  * Command to load the data into the page assembly buffer
114  */
XMC_FLASH_lLoadPageCommand(uint32_t low_word,uint32_t high_word)115 void XMC_FLASH_lLoadPageCommand(uint32_t low_word, uint32_t high_word)
116 {
117   volatile uint32_t *address;
118 
119   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x55f0U);
120   *address = low_word;
121   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x55f4U);
122   *address = high_word;
123 }
124 
125 /*
126  * Command to start the programming of one page with data from the assembly buffer
127  */
XMC_FLASH_lWritePageCommand(uint32_t * page_start_address)128 void XMC_FLASH_lWritePageCommand(uint32_t *page_start_address)
129 {
130   volatile uint32_t *address;
131 
132   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5554U);
133   *address = 0xaaU;
134   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0xaaa8U);
135   *address = 0x55U;
136   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5554U);
137   *address = 0xa0U;
138   address = page_start_address;
139   *address = 0xaaU;
140 }
141 
142 /*
143  * Command to start the programming of UCB page with data from the assembly buffer
144  */
XMC_FLASH_lWriteUCBPageCommand(uint32_t * page_start_address)145 void XMC_FLASH_lWriteUCBPageCommand(uint32_t *page_start_address)
146 {
147   volatile uint32_t *address;
148 
149   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5554U);
150   *address = 0xaaU;
151   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0xaaa8U);
152   *address = 0x55U;
153   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5554U);
154   *address = 0xc0U;
155   address = page_start_address;
156   *address = 0xaaU;
157 }
158 
159 /*
160  * Command to erase sector which is starting with the specified address
161  */
XMC_FLASH_lEraseSectorCommand(uint32_t * sector_start_address)162 void XMC_FLASH_lEraseSectorCommand(uint32_t *sector_start_address)
163 {
164   volatile uint32_t *address;
165 
166   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5554U);
167   *address = 0xaaU;
168   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0xaaa8U);
169   *address = 0x55U;
170   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5554U);
171   *address = 0x80U;
172   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5554U);
173   *address = 0xaaU;
174   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0xaaa8U);
175   *address = 0x55U;
176   address = sector_start_address;
177   *address = 0x30U;
178 }
179 
180 
181 /*
182  * Command to temporarily disables the write protection belonging to the the USER specified, when passwords match with their
183  * configured values
184  */
XMC_FLASH_lDisableSectorWriteProtectionCommand(uint32_t user,uint32_t password_0,uint32_t password_1)185 void XMC_FLASH_lDisableSectorWriteProtectionCommand(uint32_t user, uint32_t password_0, uint32_t password_1)
186 {
187   volatile uint32_t *address;
188 
189   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5554U);
190   *address = 0xaaU;
191   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0xaaa8U);
192   *address = 0x55U;
193   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x553cU);
194   *address = user;
195   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0xaaa8U);
196   *address = password_0;
197   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0xaaa8U);
198   *address = password_1;
199   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5558U);
200   *address = 0x05U;
201 }
202 
203 /*
204  * Command to temporarily disables the read protection along with write protection, when passwords match with their
205  * configured values
206  */
XMC_FLASH_lDisableReadProtectionCommand(uint32_t password_0,uint32_t password_1)207 void XMC_FLASH_lDisableReadProtectionCommand(uint32_t password_0, uint32_t password_1)
208 {
209   volatile uint32_t *address;
210 
211   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5554U);
212   *address = 0xaaU;
213   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0xaaa8U);
214   *address = 0x55U;
215   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x553cU);
216   *address = 0x00U;
217   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0xaaa8U);
218   *address = password_0;
219   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0xaaa8U);
220   *address = password_1;
221   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5558U);
222   *address = 0x08U;
223 }
224 
225 /*
226  * Command to clear FSR.PROG and FSR.ERASE and the error flags in FSR such as PFOPER, SQER, PROER, PFDBER, ORIER, VER
227  */
XMC_FLASH_lClearStatusCommand(void)228 void XMC_FLASH_lClearStatusCommand(void)
229 {
230   volatile uint32_t *address;
231 
232   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5554U);
233   *address = 0xf5U;
234 }
235 
236 /*********************************************************************************************************************
237  * API IMPLEMENTATION
238  ********************************************************************************************************************/
239 
240  /*
241  * This API shall clear Program, erase and error flags(PFOPER, SQER, PROER, PFDBER, ORIER, VER) of FSR register.
242  */
XMC_FLASH_ClearStatus(void)243 void XMC_FLASH_ClearStatus(void)
244 {
245   XMC_FLASH_lClearStatusCommand();
246 }
247 
248 /*
249  * This API returns the FSR register value
250  */
XMC_FLASH_GetStatus(void)251 uint32_t XMC_FLASH_GetStatus(void)
252 {
253   return FLASH0->FSR;
254 }
255 
256 /*
257  * This API enables the events which required to trigger the ISR
258  */
XMC_FLASH_EnableEvent(const uint32_t event_msk)259 void XMC_FLASH_EnableEvent(const uint32_t event_msk)
260 {
261   FLASH0->FCON |= event_msk;
262 }
263 
264 /*
265  * This API disables the event generation
266  */
XMC_FLASH_DisableEvent(const uint32_t event_msk)267 void XMC_FLASH_DisableEvent(const uint32_t event_msk)
268 {
269   FLASH0->FCON &= ~event_msk;
270 }
271 
272 /*
273  * This API write the PFLASH page
274  */
XMC_FLASH_ProgramPage(uint32_t * address,const uint32_t * data)275 void XMC_FLASH_ProgramPage(uint32_t *address, const uint32_t *data)
276 {
277   uint32_t idx;
278 
279   XMC_FLASH_lClearStatusCommand();
280   XMC_FLASH_lEnterPageModeCommand();
281 
282   for (idx = 0U; idx < XMC_FLASH_WORDS_PER_PAGE; idx += 2U)
283   {
284     XMC_FLASH_lLoadPageCommand(data[idx], data[idx + 1U]);
285   }
286 
287   XMC_FLASH_lWritePageCommand(address);
288 
289   /* wait until the operation is completed */
290   while ((FLASH0->FSR & (uint32_t)FLASH_FSR_PBUSY_Msk) != 0U){}
291 }
292 
293 /*
294  * This API erase the logical sector
295  */
XMC_FLASH_EraseSector(uint32_t * address)296 void XMC_FLASH_EraseSector(uint32_t *address)
297 {
298   XMC_FLASH_lClearStatusCommand();
299   XMC_FLASH_lEraseSectorCommand(address);
300 
301   /* wait until the operation is completed */
302   while ((FLASH0->FSR & (uint32_t)FLASH_FSR_PBUSY_Msk) != 0U){}
303 }
304 
305 /*
306  * Command to erase physical sector which is starting with the specified address
307  */
XMC_FLASH_lErasePhysicalSectorCommand(uint32_t * sector_start_address)308 void XMC_FLASH_lErasePhysicalSectorCommand(uint32_t *sector_start_address)
309 {
310   volatile uint32_t *address;
311 
312   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5554U);
313   *address = 0xaaU;
314   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0xaaa8U);
315   *address = 0x55U;
316   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5554U);
317   *address = 0x80U;
318   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5554U);
319   *address = 0xaaU;
320   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0xaaa8U);
321   *address = 0x55U;
322   address = sector_start_address;
323   *address = 0x40U;
324 }
325 
326 /*
327  * Command to erase physical sector-4 which is starting with the specified address
328  * This command is only available if PROCON1.PRS = 1.
329  */
XMC_FLASH_lRepairPhysicalSectorCommand(void)330 void XMC_FLASH_lRepairPhysicalSectorCommand(void)
331 {
332   volatile uint32_t *address;
333 
334   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5554U);
335   *address = 0xaaU;
336   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0xaaa8U);
337   *address = 0x55U;
338   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5554U);
339   *address = 0x80U;
340   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5554U);
341   *address = 0xaaU;
342   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0xaaa8U);
343   *address = 0x55U;
344   address = XMC_FLASH_PHY_SECTOR_4;
345   *address = 0x40U;
346 }
347 
348  /*
349   * This API erase the physical sector
350   */
XMC_FLASH_ErasePhysicalSector(uint32_t * address)351 void XMC_FLASH_ErasePhysicalSector(uint32_t *address)
352 {
353   XMC_FLASH_lClearStatusCommand();
354   XMC_FLASH_lErasePhysicalSectorCommand(address);
355 
356   /* wait until the operation is completed */
357   while ((FLASH0->FSR & (uint32_t)FLASH_FSR_PBUSY_Msk) != 0U){}
358 }
359 
360 /*
361  * This API repair the physical sector
362  */
XMC_FLASH_RepairPhysicalSector(void)363 void XMC_FLASH_RepairPhysicalSector(void)
364 {
365   XMC_FLASH_lClearStatusCommand();
366   XMC_FLASH_lRepairPhysicalSectorCommand();
367 }
368 
369 /*
370  * Command to erase UCB sector which is starting with the specified address
371  */
XMC_FLASH_EraseUCB(uint32_t * ucb_sector_start_address)372 void XMC_FLASH_EraseUCB(uint32_t *ucb_sector_start_address)
373 {
374   volatile uint32_t *address;
375 
376   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5554U);
377   *address = 0xaaU;
378   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0xaaa8U);
379   *address = 0x55U;
380   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5554U);
381   *address = 0x80U;
382   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5554U);
383   *address = 0xaaU;
384   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0xaaa8U);
385   *address = 0x55U;
386   address = ucb_sector_start_address;
387   *address = 0xc0U;
388 
389   /* wait until the operation is completed */
390   while ((FLASH0->FSR & (uint32_t)FLASH_FSR_PBUSY_Msk) != 0U){}
391 }
392 
393 /*
394  * Command to reset the status of the PFLASH
395  */
XMC_FLASH_Reset(void)396 void XMC_FLASH_Reset(void)
397 {
398   volatile uint32_t *address;
399 
400   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5554U);
401   *address = 0xf0U;
402 }
403 
404 #define BMI_STRING_BYTE_CNT 30
405 
XMC_FLASH_InstallBMI(XMC_FLASH_BMI_STRING_t * const bmi_string)406 void XMC_FLASH_InstallBMI(XMC_FLASH_BMI_STRING_t *const bmi_string)
407 {
408   uint32_t checksum = 0;
409   for (int i = 0; i < BMI_STRING_BYTE_CNT; ++i)
410   {
411 	checksum ^= ((const uint8_t *)bmi_string)[i];
412   }
413 
414   bmi_string->reserved = checksum;
415 
416   XMC_FLASH_lEnterPageModeCommand();
417 
418   XMC_FLASH_lLoadPageCommand(((const uint32_t *)bmi_string)[0], ((const uint32_t *)bmi_string)[1]);
419   XMC_FLASH_lLoadPageCommand(((const uint32_t *)bmi_string)[2], ((const uint32_t *)bmi_string)[3]);
420   XMC_FLASH_lLoadPageCommand(((const uint32_t *)bmi_string)[4], ((const uint32_t *)bmi_string)[5]);
421   XMC_FLASH_lLoadPageCommand(((const uint32_t *)bmi_string)[6], ((const uint32_t *)bmi_string)[7]);
422   XMC_FLASH_lLoadPageCommand(((const uint32_t *)bmi_string)[8], 0);
423 
424   for (uint32_t idx = 0U; idx < (XMC_FLASH_WORDS_PER_PAGE - XMC_FLASH_BMI_STRING_WORDS); idx += 2U)
425   {
426     XMC_FLASH_lLoadPageCommand(0UL, 0UL);
427   }
428 
429   XMC_FLASH_lWriteUCBPageCommand((uint32_t *)((uint32_t)XMC_FLASH_UCB2 + XMC_FLASH_BYTES_PER_PAGE));
430 
431   /* wait until the operation is completed */
432   while ((FLASH0->FSR & (uint32_t)FLASH_FSR_PBUSY_Msk) != 0U){}
433 }
434 
435 /*
436  * This API install the global read and sector write protection for the specified user
437  */
XMC_FLASH_InstallProtection(uint8_t user,uint32_t protection_mask,uint32_t password_0,uint32_t password_1)438 void XMC_FLASH_InstallProtection(uint8_t user,
439                                  uint32_t protection_mask,
440 	                             uint32_t password_0,
441                                  uint32_t password_1)
442 {
443   uint32_t idx;
444 
445   XMC_ASSERT(" XMC_FLASH_ConfigureProtection: User level out of range", (user < 3U))
446 
447   XMC_FLASH_lEnterPageModeCommand();
448 
449   XMC_FLASH_lLoadPageCommand(protection_mask, 0UL);
450   XMC_FLASH_lLoadPageCommand(protection_mask, 0UL);
451   XMC_FLASH_lLoadPageCommand(password_0, password_1);
452   XMC_FLASH_lLoadPageCommand(password_0, password_1);
453 
454   for (idx = 0U; idx < (XMC_FLASH_WORDS_PER_PAGE - XMC_FLASH_PROTECTION_CONFIGURATION_WORDS); idx += 2U)
455   {
456     XMC_FLASH_lLoadPageCommand(0UL, 0UL);
457   }
458 
459   XMC_FLASH_lWriteUCBPageCommand((uint32_t *)((uint32_t)XMC_FLASH_UCB0 + (user * XMC_FLASH_BYTES_PER_UCB)));
460 
461   /* wait until the operation is completed */
462   while ((FLASH0->FSR & (uint32_t)FLASH_FSR_PBUSY_Msk) != 0U){}
463 }
464 
465 /*
466  * This API confirm the protection. So that This sectors are locked with the specified protection.
467  */
XMC_FLASH_ConfirmProtection(uint8_t user)468 void XMC_FLASH_ConfirmProtection(uint8_t user)
469 {
470   uint32_t idx;
471 
472   XMC_ASSERT(" XMC_FLASH_ConfirmProtection: User level out of range", (user < 3U))
473 
474   XMC_FLASH_lEnterPageModeCommand();
475 
476   XMC_FLASH_lLoadPageCommand(XMC_FLASH_PROT_CONFIRM_CODE, 0U);
477   XMC_FLASH_lLoadPageCommand(XMC_FLASH_PROT_CONFIRM_CODE, 0U);
478 
479   /* Fill the rest of page buffer with zeros*/
480   for (idx = 0UL; idx < (XMC_FLASH_WORDS_PER_PAGE - XMC_FLASH_PROT_CONFIRM_WORDS); idx += 2U)
481   {
482     XMC_FLASH_lLoadPageCommand(0UL, 0UL);
483   }
484 
485   XMC_FLASH_lWriteUCBPageCommand((uint32_t *)((uint32_t)XMC_FLASH_UCB0 +
486                                  (user * XMC_FLASH_BYTES_PER_UCB) + XMC_FLASH_PROT_CONFIRM_OFFSET));
487 
488   /* wait until the operation is completed */
489   while ((FLASH0->FSR & (uint32_t)FLASH_FSR_PBUSY_Msk) != 0U){}
490 }
491 
492 /*
493  * This API verify read protection configuration. And returns true if passwords are matching.
494  */
XMC_FLASH_VerifyReadProtection(uint32_t password_0,uint32_t password_1)495 bool XMC_FLASH_VerifyReadProtection(uint32_t password_0, uint32_t password_1)
496 {
497   bool status = false;
498 
499   /* Check if read protection is installed */
500   if ((XMC_FLASH_GetStatus() & (uint32_t)XMC_FLASH_STATUS_READ_PROTECTION_INSTALLED) != 0U)
501   {
502     XMC_FLASH_lClearStatusCommand();
503     XMC_FLASH_lDisableReadProtectionCommand(password_0, password_1);
504 
505     status = (bool)(XMC_FLASH_GetStatus() & (uint32_t)XMC_FLASH_STATUS_READ_PROTECTION_DISABLED_STATE);
506   }
507 
508   return status;
509 }
510 
511 /*
512  * This API verify sector write protection configuration. And returns true if passwords are matching for the
513  * specified user.
514  */
XMC_FLASH_VerifyWriteProtection(uint32_t user,uint32_t protection_mask,uint32_t password_0,uint32_t password_1)515 bool XMC_FLASH_VerifyWriteProtection(uint32_t user,
516                                      uint32_t protection_mask,
517                                      uint32_t password_0,
518                                      uint32_t password_1)
519 {
520   bool status = false;
521   uint32_t *flash_procon_ptr = (uint32_t *)(void*)(&(FLASH0->PROCON0) + user);
522 
523   XMC_ASSERT(" XMC_FLASH_VerifyWriteProtection: User level out of range", (user < 2U))
524 
525   /* Check if write protection for selected user is installed */
526   if ((XMC_FLASH_GetStatus() & (uint32_t)((uint32_t)1U << (uint32_t)((uint32_t)FLASH_FSR_WPROIN0_Pos + user))) != 0U)
527   {
528     XMC_FLASH_lClearStatusCommand();
529     XMC_FLASH_lDisableSectorWriteProtectionCommand(user, password_0, password_1);
530 
531     status = (bool)((XMC_FLASH_GetStatus() & (uint32_t)((uint32_t)1U << (uint32_t)((uint32_t)FLASH_FSR_WPRODIS0_Pos + user)))) &&
532              (*flash_procon_ptr == (protection_mask & (uint32_t)(~(uint32_t)XMC_FLASH_PROTECTION_READ_GLOBAL)));
533   }
534 
535   return status;
536 }
537 
538 /*
539  * Command to enables the protection as it was configured
540  */
XMC_FLASH_ResumeProtection(void)541 void XMC_FLASH_ResumeProtection(void)
542 {
543   volatile uint32_t *address;
544 
545   address = (uint32_t *)(XMC_FLASH_UNCACHED_BASE + 0x5554U);
546   *address = 0x5eU;
547 }
548 
549 #endif
550