comparison eeprom.c @ 76:f1c9a51e368a

Add EEPROM emulation from AN2594. Fix emulated EEPROM size on large parts.
author Daniel O'Connor <darius@dons.net.au>
date Mon, 22 Apr 2013 23:17:40 +0930
parents
children 7dd28b96a716
comparison
equal deleted inserted replaced
75:85f16813c730 76:f1c9a51e368a
1 /**
2 ******************************************************************************
3 * @file EEPROM_Emulation/src/eeprom.c
4 * @author MCD Application Team
5 * @version V3.1.0
6 * @date 07/27/2009
7 * @brief This file provides all the EEPROM emulation firmware functions.
8 ******************************************************************************
9 * @copy
10 *
11 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
12 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
13 * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
14 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
15 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
16 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
17 *
18 * <h2><center>&copy; COPYRIGHT 2009 STMicroelectronics</center></h2>
19 */
20 /** @addtogroup EEPROM_Emulation
21 * @{
22 */
23
24 /* Includes ------------------------------------------------------------------*/
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include "eeprom.h"
29
30 /* Private typedef -----------------------------------------------------------*/
31 /* Private define ------------------------------------------------------------*/
32 /* Private macro -------------------------------------------------------------*/
33 /* Private variables ---------------------------------------------------------*/
34
35 /* Global variable used to store variable value in read sequence */
36 uint16_t DataVar = 0;
37
38 /* Virtual address defined by the user: 0xFFFF value is prohibited */
39 const uint16_t VirtAddVarTab[NumbOfVar] = { 1000, 1001, 1002 };
40
41 /* Private function prototypes -----------------------------------------------*/
42 /* Private functions ---------------------------------------------------------*/
43 static uint16_t EE_FindValidPage(uint8_t Operation);
44 static uint16_t EE_VerifyPageFullWriteVariable(uint16_t VirtAddress, uint16_t Data);
45 static uint16_t EE_PageTransfer(uint16_t VirtAddress, uint16_t Data);
46
47 /**
48 * @brief Restore the pages to a known good state in case of page's status
49 * corruption after a power loss.
50 * @param None.
51 * @retval - Flash error code: on write Flash error
52 * - FLASH_COMPLETE: on success
53 */
54 uint16_t EE_Init(void)
55 {
56 uint16_t PageStatus0 = 6, PageStatus1 = 6;
57 uint16_t VarIdx = 0;
58 uint16_t EepromStatus = 0, ReadStatus = 0;
59 int16_t x = -1;
60 uint16_t FlashStatus;
61
62 /* Get Page0 status */
63 PageStatus0 = *(__IO uint16_t*)PAGE0_BASE_ADDRESS;
64 /* Get Page1 status */
65 PageStatus1 = *(__IO uint16_t*)PAGE1_BASE_ADDRESS;
66
67 /* Check for invalid header states and repair if necessary */
68 switch (PageStatus0)
69 {
70 case ERASED:
71 if (PageStatus1 == VALID_PAGE) /* Page0 erased, Page1 valid */
72 {
73 /* Erase Page0 */
74 FlashStatus = FLASH_ErasePage(PAGE0_BASE_ADDRESS);
75 /* If erase operation was failed, a Flash error code is returned */
76 if (FlashStatus != FLASH_COMPLETE)
77 {
78 return FlashStatus;
79 }
80 }
81 else if (PageStatus1 == RECEIVE_DATA) /* Page0 erased, Page1 receive */
82 {
83 /* Erase Page0 */
84 FlashStatus = FLASH_ErasePage(PAGE0_BASE_ADDRESS);
85 /* If erase operation was failed, a Flash error code is returned */
86 if (FlashStatus != FLASH_COMPLETE)
87 {
88 return FlashStatus;
89 }
90 /* Mark Page1 as valid */
91 FlashStatus = FLASH_ProgramHalfWord(PAGE1_BASE_ADDRESS, VALID_PAGE);
92 /* If program operation was failed, a Flash error code is returned */
93 if (FlashStatus != FLASH_COMPLETE)
94 {
95 return FlashStatus;
96 }
97 }
98 else /* First EEPROM access (Page0&1 are erased) or invalid state -> format EEPROM */
99 {
100 /* Erase both Page0 and Page1 and set Page0 as valid page */
101 FlashStatus = EE_Format();
102 /* If erase/program operation was failed, a Flash error code is returned */
103 if (FlashStatus != FLASH_COMPLETE)
104 {
105 return FlashStatus;
106 }
107 }
108 break;
109
110 case RECEIVE_DATA:
111 if (PageStatus1 == VALID_PAGE) /* Page0 receive, Page1 valid */
112 {
113 /* Transfer data from Page1 to Page0 */
114 for (VarIdx = 0; VarIdx < NumbOfVar; VarIdx++)
115 {
116 if (( *(__IO uint16_t*)(PAGE0_BASE_ADDRESS + 6)) == VirtAddVarTab[VarIdx])
117 {
118 x = VarIdx;
119 }
120 if (VarIdx != x)
121 {
122 /* Read the last variables' updates */
123 ReadStatus = EE_ReadVariable(VirtAddVarTab[VarIdx], &DataVar);
124 /* In case variable corresponding to the virtual address was found */
125 if (ReadStatus != 0x1)
126 {
127 /* Transfer the variable to the Page0 */
128 EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[VarIdx], DataVar);
129 /* If program operation was failed, a Flash error code is returned */
130 if (EepromStatus != FLASH_COMPLETE)
131 {
132 return EepromStatus;
133 }
134 }
135 }
136 }
137 /* Mark Page0 as valid */
138 FlashStatus = FLASH_ProgramHalfWord(PAGE0_BASE_ADDRESS, VALID_PAGE);
139 /* If program operation was failed, a Flash error code is returned */
140 if (FlashStatus != FLASH_COMPLETE)
141 {
142 return FlashStatus;
143 }
144 /* Erase Page1 */
145 FlashStatus = FLASH_ErasePage(PAGE1_BASE_ADDRESS);
146 /* If erase operation was failed, a Flash error code is returned */
147 if (FlashStatus != FLASH_COMPLETE)
148 {
149 return FlashStatus;
150 }
151 }
152 else if (PageStatus1 == ERASED) /* Page0 receive, Page1 erased */
153 {
154 /* Erase Page1 */
155 FlashStatus = FLASH_ErasePage(PAGE1_BASE_ADDRESS);
156 /* If erase operation was failed, a Flash error code is returned */
157 if (FlashStatus != FLASH_COMPLETE)
158 {
159 return FlashStatus;
160 }
161 /* Mark Page0 as valid */
162 FlashStatus = FLASH_ProgramHalfWord(PAGE0_BASE_ADDRESS, VALID_PAGE);
163 /* If program operation was failed, a Flash error code is returned */
164 if (FlashStatus != FLASH_COMPLETE)
165 {
166 return FlashStatus;
167 }
168 }
169 else /* Invalid state -> format eeprom */
170 {
171 /* Erase both Page0 and Page1 and set Page0 as valid page */
172 FlashStatus = EE_Format();
173 /* If erase/program operation was failed, a Flash error code is returned */
174 if (FlashStatus != FLASH_COMPLETE)
175 {
176 return FlashStatus;
177 }
178 }
179 break;
180
181 case VALID_PAGE:
182 if (PageStatus1 == VALID_PAGE) /* Invalid state -> format eeprom */
183 {
184 /* Erase both Page0 and Page1 and set Page0 as valid page */
185 FlashStatus = EE_Format();
186 /* If erase/program operation was failed, a Flash error code is returned */
187 if (FlashStatus != FLASH_COMPLETE)
188 {
189 return FlashStatus;
190 }
191 }
192 else if (PageStatus1 == ERASED) /* Page0 valid, Page1 erased */
193 {
194 /* Erase Page1 */
195 FlashStatus = FLASH_ErasePage(PAGE1_BASE_ADDRESS);
196 /* If erase operation was failed, a Flash error code is returned */
197 if (FlashStatus != FLASH_COMPLETE)
198 {
199 return FlashStatus;
200 }
201 }
202 else /* Page0 valid, Page1 receive */
203 {
204 /* Transfer data from Page0 to Page1 */
205 for (VarIdx = 0; VarIdx < NumbOfVar; VarIdx++)
206 {
207 if ((*(__IO uint16_t*)(PAGE1_BASE_ADDRESS + 6)) == VirtAddVarTab[VarIdx])
208 {
209 x = VarIdx;
210 }
211 if (VarIdx != x)
212 {
213 /* Read the last variables' updates */
214 ReadStatus = EE_ReadVariable(VirtAddVarTab[VarIdx], &DataVar);
215 /* In case variable corresponding to the virtual address was found */
216 if (ReadStatus != 0x1)
217 {
218 /* Transfer the variable to the Page1 */
219 EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[VarIdx], DataVar);
220 /* If program operation was failed, a Flash error code is returned */
221 if (EepromStatus != FLASH_COMPLETE)
222 {
223 return EepromStatus;
224 }
225 }
226 }
227 }
228 /* Mark Page1 as valid */
229 FlashStatus = FLASH_ProgramHalfWord(PAGE1_BASE_ADDRESS, VALID_PAGE);
230 /* If program operation was failed, a Flash error code is returned */
231 if (FlashStatus != FLASH_COMPLETE)
232 {
233 return FlashStatus;
234 }
235 /* Erase Page0 */
236 FlashStatus = FLASH_ErasePage(PAGE0_BASE_ADDRESS);
237 /* If erase operation was failed, a Flash error code is returned */
238 if (FlashStatus != FLASH_COMPLETE)
239 {
240 return FlashStatus;
241 }
242 }
243 break;
244
245 default: /* Any other state -> format eeprom */
246 /* Erase both Page0 and Page1 and set Page0 as valid page */
247 FlashStatus = EE_Format();
248 /* If erase/program operation was failed, a Flash error code is returned */
249 if (FlashStatus != FLASH_COMPLETE)
250 {
251 return FlashStatus;
252 }
253 break;
254 }
255
256 return FLASH_COMPLETE;
257 }
258
259 /**
260 * @brief Returns the last stored variable data, if found, which correspond to
261 * the passed virtual address
262 * @param VirtAddress: Variable virtual address
263 * @param Data: Global variable contains the read variable value
264 * @retval Success or error status:
265 * - 0: if variable was found
266 * - 1: if the variable was not found
267 * - NO_VALID_PAGE: if no valid page was found.
268 */
269 uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data)
270 {
271 uint16_t ValidPage = PAGE0;
272 uint16_t AddressValue = 0x5555, ReadStatus = 1;
273 uint32_t Address = 0x08010000, PageStartAddress = 0x08010000;
274
275 /* Get active Page for read operation */
276 ValidPage = EE_FindValidPage(READ_FROM_VALID_PAGE);
277
278 /* Check if there is no valid page */
279 if (ValidPage == NO_VALID_PAGE)
280 {
281 return NO_VALID_PAGE;
282 }
283
284 /* Get the valid Page start Address */
285 PageStartAddress = (uint32_t)(EEPROM_START_ADDRESS + (uint32_t)(ValidPage * PAGE_SIZE));
286
287 /* Get the valid Page end Address */
288 Address = (uint32_t)((EEPROM_START_ADDRESS - 2) + (uint32_t)((1 + ValidPage) * PAGE_SIZE));
289
290 /* Check each active page address starting from end */
291 while (Address > (PageStartAddress + 2))
292 {
293 /* Get the current location content to be compared with virtual address */
294 AddressValue = (*(__IO uint16_t*)Address);
295
296 /* Compare the read address with the virtual address */
297 if (AddressValue == VirtAddress)
298 {
299 /* Get content of Address-2 which is variable value */
300 *Data = (*(__IO uint16_t*)(Address - 2));
301
302 /* In case variable value is read, reset ReadStatus flag */
303 ReadStatus = 0;
304
305 break;
306 }
307 else
308 {
309 /* Next address location */
310 Address = Address - 4;
311 }
312 }
313
314 /* Return ReadStatus value: (0: variable exist, 1: variable doesn't exist) */
315 return ReadStatus;
316 }
317
318 /**
319 * @brief Writes/upadtes variable data in EEPROM.
320 * @param VirtAddress: Variable virtual address
321 * @param Data: 16 bit data to be written
322 * @retval Success or error status:
323 * - FLASH_COMPLETE: on success
324 * - PAGE_FULL: if valid page is full
325 * - NO_VALID_PAGE: if no valid page was found
326 * - Flash error code: on write Flash error
327 */
328 uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data)
329 {
330 uint16_t Status = 0;
331
332 /* Write the variable virtual address and value in the EEPROM */
333 Status = EE_VerifyPageFullWriteVariable(VirtAddress, Data);
334
335 /* In case the EEPROM active page is full */
336 if (Status == PAGE_FULL)
337 {
338 /* Perform Page transfer */
339 Status = EE_PageTransfer(VirtAddress, Data);
340 }
341
342 /* Return last operation status */
343 return Status;
344 }
345
346 /**
347 * @brief Erases PAGE0 and PAGE1 and writes VALID_PAGE header to PAGE0
348 * @param None
349 * @retval Status of the last operation (Flash write or erase) done during
350 * EEPROM formating
351 */
352
353 FLASH_Status EE_Format(void)
354 {
355 FLASH_Status FlashStatus = FLASH_COMPLETE;
356
357 /* Erase Page0 */
358 FlashStatus = FLASH_ErasePage(PAGE0_BASE_ADDRESS);
359
360 /* If erase operation was failed, a Flash error code is returned */
361 if (FlashStatus != FLASH_COMPLETE)
362 {
363 return FlashStatus;
364 }
365
366 /* Set Page0 as valid page: Write VALID_PAGE at Page0 base address */
367 FlashStatus = FLASH_ProgramHalfWord(PAGE0_BASE_ADDRESS, VALID_PAGE);
368
369 /* If program operation was failed, a Flash error code is returned */
370 if (FlashStatus != FLASH_COMPLETE)
371 {
372 return FlashStatus;
373 }
374
375 /* Erase Page1 */
376 FlashStatus = FLASH_ErasePage(PAGE1_BASE_ADDRESS);
377
378 /* Return Page1 erase operation status */
379 return FlashStatus;
380 }
381
382 /**
383 * @brief Find valid Page for write or read operation
384 * @param Operation: operation to achieve on the valid page.
385 * This parameter can be one of the following values:
386 * @arg READ_FROM_VALID_PAGE: read operation from valid page
387 * @arg WRITE_IN_VALID_PAGE: write operation from valid page
388 * @retval Valid page number (PAGE0 or PAGE1) or NO_VALID_PAGE in case
389 * of no valid page was found
390 */
391 static uint16_t EE_FindValidPage(uint8_t Operation)
392 {
393 uint16_t PageStatus0 = 6, PageStatus1 = 6;
394
395 /* Get Page0 actual status */
396 PageStatus0 = (*(__IO uint16_t*)PAGE0_BASE_ADDRESS);
397
398 /* Get Page1 actual status */
399 PageStatus1 = (*(__IO uint16_t*)PAGE1_BASE_ADDRESS);
400
401 /* Write or read operation */
402 switch (Operation)
403 {
404 case WRITE_IN_VALID_PAGE: /* ---- Write operation ---- */
405 if (PageStatus1 == VALID_PAGE)
406 {
407 /* Page0 receiving data */
408 if (PageStatus0 == RECEIVE_DATA)
409 {
410 return PAGE0; /* Page0 valid */
411 }
412 else
413 {
414 return PAGE1; /* Page1 valid */
415 }
416 }
417 else if (PageStatus0 == VALID_PAGE)
418 {
419 /* Page1 receiving data */
420 if (PageStatus1 == RECEIVE_DATA)
421 {
422 return PAGE1; /* Page1 valid */
423 }
424 else
425 {
426 return PAGE0; /* Page0 valid */
427 }
428 }
429 else
430 {
431 return NO_VALID_PAGE; /* No valid Page */
432 }
433
434 case READ_FROM_VALID_PAGE: /* ---- Read operation ---- */
435 if (PageStatus0 == VALID_PAGE)
436 {
437 return PAGE0; /* Page0 valid */
438 }
439 else if (PageStatus1 == VALID_PAGE)
440 {
441 return PAGE1; /* Page1 valid */
442 }
443 else
444 {
445 return NO_VALID_PAGE ; /* No valid Page */
446 }
447
448 default:
449 return PAGE0; /* Page0 valid */
450 }
451 }
452
453 /**
454 * @brief Verify if active page is full and Writes variable in EEPROM.
455 * @param VirtAddress: 16 bit virtual address of the variable
456 * @param Data: 16 bit data to be written as variable value
457 * @retval Success or error status:
458 * - FLASH_COMPLETE: on success
459 * - PAGE_FULL: if valid page is full
460 * - NO_VALID_PAGE: if no valid page was found
461 * - Flash error code: on write Flash error
462 */
463 static uint16_t EE_VerifyPageFullWriteVariable(uint16_t VirtAddress, uint16_t Data)
464 {
465 FLASH_Status FlashStatus = FLASH_COMPLETE;
466 uint16_t ValidPage = PAGE0;
467 uint32_t Address = 0x08010000, PageEndAddress = 0x080107FF;
468
469 /* Get valid Page for write operation */
470 ValidPage = EE_FindValidPage(WRITE_IN_VALID_PAGE);
471
472 /* Check if there is no valid page */
473 if (ValidPage == NO_VALID_PAGE)
474 {
475 return NO_VALID_PAGE;
476 }
477
478 /* Get the valid Page start Address */
479 Address = (uint32_t)(EEPROM_START_ADDRESS + (uint32_t)(ValidPage * PAGE_SIZE));
480
481 /* Get the valid Page end Address */
482 PageEndAddress = (uint32_t)((EEPROM_START_ADDRESS - 2) + (uint32_t)((1 + ValidPage) * PAGE_SIZE));
483
484 /* Check each active page address starting from begining */
485 while (Address < PageEndAddress)
486 {
487 /* Verify if Address and Address+2 contents are 0xFFFFFFFF */
488 if ((*(__IO uint32_t*)Address) == 0xFFFFFFFF)
489 {
490 /* Set variable data */
491 FlashStatus = FLASH_ProgramHalfWord(Address, Data);
492 /* If program operation was failed, a Flash error code is returned */
493 if (FlashStatus != FLASH_COMPLETE)
494 {
495 return FlashStatus;
496 }
497 /* Set variable virtual address */
498 FlashStatus = FLASH_ProgramHalfWord(Address + 2, VirtAddress);
499 /* Return program operation status */
500 return FlashStatus;
501 }
502 else
503 {
504 /* Next address location */
505 Address = Address + 4;
506 }
507 }
508
509 /* Return PAGE_FULL in case the valid page is full */
510 return PAGE_FULL;
511 }
512
513 /**
514 * @brief Transfers last updated variables data from the full Page to
515 * an empty one.
516 * @param VirtAddress: 16 bit virtual address of the variable
517 * @param Data: 16 bit data to be written as variable value
518 * @retval Success or error status:
519 * - FLASH_COMPLETE: on success
520 * - PAGE_FULL: if valid page is full
521 * - NO_VALID_PAGE: if no valid page was found
522 * - Flash error code: on write Flash error
523 */
524 static uint16_t EE_PageTransfer(uint16_t VirtAddress, uint16_t Data)
525 {
526 FLASH_Status FlashStatus = FLASH_COMPLETE;
527 uint32_t NewPageAddress = 0x080103FF, OldPageAddress = 0x08010000;
528 uint16_t ValidPage = PAGE0, VarIdx = 0;
529 uint16_t EepromStatus = 0, ReadStatus = 0;
530
531 /* Get active Page for read operation */
532 ValidPage = EE_FindValidPage(READ_FROM_VALID_PAGE);
533
534 if (ValidPage == PAGE1) /* Page1 valid */
535 {
536 /* New page address where variable will be moved to */
537 NewPageAddress = PAGE0_BASE_ADDRESS;
538
539 /* Old page address where variable will be taken from */
540 OldPageAddress = PAGE1_BASE_ADDRESS;
541 }
542 else if (ValidPage == PAGE0) /* Page0 valid */
543 {
544 /* New page address where variable will be moved to */
545 NewPageAddress = PAGE1_BASE_ADDRESS;
546
547 /* Old page address where variable will be taken from */
548 OldPageAddress = PAGE0_BASE_ADDRESS;
549 }
550 else
551 {
552 return NO_VALID_PAGE; /* No valid Page */
553 }
554
555 /* Set the new Page status to RECEIVE_DATA status */
556 FlashStatus = FLASH_ProgramHalfWord(NewPageAddress, RECEIVE_DATA);
557 /* If program operation was failed, a Flash error code is returned */
558 if (FlashStatus != FLASH_COMPLETE)
559 {
560 return FlashStatus;
561 }
562
563 /* Write the variable passed as parameter in the new active page */
564 EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddress, Data);
565 /* If program operation was failed, a Flash error code is returned */
566 if (EepromStatus != FLASH_COMPLETE)
567 {
568 return EepromStatus;
569 }
570
571 /* Transfer process: transfer variables from old to the new active page */
572 for (VarIdx = 0; VarIdx < NumbOfVar; VarIdx++)
573 {
574 if (VirtAddVarTab[VarIdx] != VirtAddress) /* Check each variable except the one passed as parameter */
575 {
576 /* Read the other last variable updates */
577 ReadStatus = EE_ReadVariable(VirtAddVarTab[VarIdx], &DataVar);
578 /* In case variable corresponding to the virtual address was found */
579 if (ReadStatus != 0x1)
580 {
581 /* Transfer the variable to the new active page */
582 EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[VarIdx], DataVar);
583 /* If program operation was failed, a Flash error code is returned */
584 if (EepromStatus != FLASH_COMPLETE)
585 {
586 return EepromStatus;
587 }
588 }
589 }
590 }
591
592 /* Erase the old Page: Set old Page status to ERASED status */
593 FlashStatus = FLASH_ErasePage(OldPageAddress);
594 /* If erase operation was failed, a Flash error code is returned */
595 if (FlashStatus != FLASH_COMPLETE)
596 {
597 return FlashStatus;
598 }
599
600 /* Set new Page status to VALID_PAGE status */
601 FlashStatus = FLASH_ProgramHalfWord(NewPageAddress, VALID_PAGE);
602 /* If program operation was failed, a Flash error code is returned */
603 if (FlashStatus != FLASH_COMPLETE)
604 {
605 return FlashStatus;
606 }
607
608 /* Return last operation flash status */
609 return FlashStatus;
610 }
611
612 void
613 FLASH_UnlockClear(void) {
614 FLASH_Unlock();
615 FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
616 }
617
618 void
619 EE_Cmd(int argc, char **argv) {
620 uint16_t adr, val, err;
621
622 if (argc == 0) {
623 fputs("No command specified\n", stdout);
624 return;
625 }
626
627 if (!strcmp(argv[0], "in")) {
628 FLASH_UnlockClear();
629 printf("Init returned %d\n", EE_Init());
630 FLASH_Lock();
631 } else if (!strcmp(argv[0], "fm")) {
632 FLASH_UnlockClear();
633 printf("Format returned %d\n", EE_Format());
634 FLASH_Lock();
635 } else if (!strcmp(argv[0], "rd")) {
636 if (argc != 2) {
637 fputs("Incorrect number of arguments\n", stdout);
638 return;
639 }
640 adr = atoi(argv[1]);
641 err = EE_ReadVariable(adr, &val);
642 printf("Read 0x%04x => 0x%04x (status %d)\n", adr, val, err);
643 } else if (!strcmp(argv[0], "wr")) {
644 if (argc != 3) {
645 fputs("Incorrect number of arguments\n", stdout);
646 return;
647 }
648 adr = atoi(argv[1]);
649 val = atoi(argv[2]);
650 FLASH_UnlockClear();
651 err = EE_WriteVariable(adr, val);
652 FLASH_Lock();
653 printf("Write 0x%04x <= 0x%04x (status %d)\n", adr, val, err);
654 } else {
655 fputs("Unknown command\n", stdout);
656 }
657 }
658
659 /**
660 * @}
661 */
662
663 /******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/