]> rtime.felk.cvut.cz Git - arc.git/blob - arch/ppc/mpc55xx/drivers/Fls.c
Merged with dem-dev
[arc.git] / arch / ppc / mpc55xx / drivers / Fls.c
1 /* -------------------------------- Arctic Core ------------------------------
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com
3  *
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>
5  *
6  * This source code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 as published by the
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * for more details.
14  * -------------------------------- Arctic Core ------------------------------*/
15
16
17
18
19
20
21
22
23 /**
24  * @file Fls.c
25  * @breif Autosar Flash driver for Freescale MPC55xx.
26  */
27
28
29 /*
30  * IMPLEMENTATION NOTES
31  * - It seems that the Autosar specification is not consistent. For
32  *   FLS_AC_LOAD_ON_JOB_START == STD_ON it seems that the driver suddenly
33  *   becomes blocking.
34  *
35  */
36
37 /*
38  * Use cases:
39  * 1. Bootloader, self replace
40  * 2. Bootloader, application loading
41  *
42  * In case 2 it's very straight forward and you can just use all the functions
43  * as intended. In case 1. there are some problems understanding how Autosar
44  * want to implement it. What is given from spec is.
45  * - If FLS_AC_LOAD_ON_JOB_START == STD_ON we copy the flash access routines
46  *   to RAM( to FlsAcErase and FlsAcWrite ).
47  *
48  * Strange things:
49  * - What happens to all the other functions that is needed to get the status
50  *   for the flash driver. Did the driver just get blocking ??
51  *
52  */
53
54 #include "Fls.h"
55 /* Freescale driver */
56 #include "ssd_types.h"
57 #include "ssd_h7f.h"
58 #include <stdlib.h>
59 #include <assert.h>
60 #include <string.h>
61 #include "Det.h"
62 #if defined(USE_DEM)
63 #include "Dem.h"
64 #endif
65 #include "h7f_types.h"
66 #include "Cpu.h"
67 #include "mpc55xx.h"
68 #include "Fls_H7F.h"
69
70
71 /* Flash layout for MPC5516 */
72 /*
73  * Low:  8x16K + 2x64k
74  * Mid:  2x128K
75  * High: 8x128K
76  */
77
78 #define H7F_REG_BASE                    0xFFFF8000
79 #define MAIN_ARRAY_BASE                 0x00000000
80 #define SHADOW_ROW_BASE         0x00FF8000
81 #define SHADOW_ROW_SIZE                 0x00008000
82 #define FLASH_PAGE_SIZE    H7FB_PAGE_SIZE
83
84 #if 0
85 #define VFLAGS_ADDR_SECT                (1<<0)
86 #define VFLAGS_ADDR_PAGE                (1<<1)
87 #define VFLAGS_LEN_SECT                 (1<<2)
88 #define VFLAGS_LEN_PAGE                 (1<<3)
89
90 static inline int Fls_Validate( uint32 addr,uint32 length, uint32 api,uint32 rv ) {
91   int i;
92   int addrOk=0;
93   uint32 flags_ok;
94   const Fls_SectorType* sector;
95   Fls_ConfigType *cfg = Fls_Global.config;
96
97   // Pre checks.
98         if( flags & VFLAGS_LEN_SECT ) {
99                 if( (addr + length) > FLS_TOTAL_SIZE ) {
100                         return (-1);
101                 }
102         }
103
104   for(i=0;i<cfg->FlsSectorListSize;i++) {
105         sector = &cfg->FlsSectorList[sectorIndex];
106         if( addr > (sector->FlsSectorStartaddress + sector->FlsNumberOfSectors * sector->FlsNumberOfSectors) ) {
107                 continue;
108         }
109         if( flags & VFLAGS_ADDR_SECT ) {
110                 if( (addr % sector->FlsSectorSize) == 0) {
111                         flags &= ~VFLAGS_ADDR_SECT;
112                 }
113         }
114         if( flags & VFLAGS_ADDR_PAGE ) {
115                 if( (addr % sector->FlsPageSize) == 0) {
116                         flags &= ~VFLAGS_ADDR_PAGE;
117                 }
118         }
119         if( flags & VFLAGS_LEN_SECT ) {
120                 // Check
121                 if( (0!= length) && (length < sectorPtr->FlsSectorSize) ) {
122                         flags &= ~VFLAGS_ADDR_SECT;
123                 }
124         }
125         if( flags & VFLAGS_LEN_PAGE ) {
126                 if( (0!= length) && (length < sectorPtr->FlsPageSize)) {
127                         flags &= ~VFLAGS_ADDR_PAGE;
128                 }
129         }
130   }
131 }
132 #endif
133
134 #if ( FLS_DEV_ERROR_DETECT == STD_ON )
135 #define FLS_VALIDATE_PARAM_ADDRESS_SECTOR_W_RV(_addr, _api, _rv)\
136   int sectorIndex;\
137   int addrOk=0;\
138   const Fls_SectorType* sector;\
139   for (sectorIndex=0; sectorIndex<Fls_Global.config->FlsSectorListSize;sectorIndex++) {\
140     sector = &Fls_Global.config->FlsSectorList[sectorIndex];\
141     if((((uint32)_addr-sector->FlsSectorStartaddress) / sector->FlsSectorSize)<sector->FlsNumberOfSectors){\
142       /* Within the right adress space */\
143       if (!(((uint32)_addr-sector->FlsSectorStartaddress) % sector->FlsSectorSize)){\
144         /* Address is correctly aligned */\
145         addrOk=1;\
146         break;\
147       }\
148     }\
149   }\
150   if (1!=addrOk){\
151   Det_ReportError(MODULE_ID_FLS,0,_api,FLS_E_PARAM_ADDRESS ); \
152   return _rv; \
153   }
154
155 #define FLS_VALIDATE_PARAM_ADDRESS_PAGE_W_RV(_addr, _api, _rv)\
156   int sectorIndex;\
157   int addrOk=0;\
158   const Fls_SectorType* sector;\
159   for (sectorIndex=0; sectorIndex<Fls_Global.config->FlsSectorListSize;sectorIndex++) {\
160     sector = &Fls_Global.config->FlsSectorList[sectorIndex];\
161     if((((uint32)_addr-sector->FlsSectorStartaddress) / sector->FlsSectorSize)<sector->FlsNumberOfSectors){\
162       /* Within the right adress space */\
163       if (!(((uint32)_addr-sector->FlsSectorStartaddress) % sector->FlsPageSize)){\
164         /* Address is correctly aligned */\
165         addrOk=1;\
166         break;\
167       }\
168     }\
169   }\
170   if (1!=addrOk){\
171   Det_ReportError(MODULE_ID_FLS,0,_api,FLS_E_PARAM_ADDRESS ); \
172   return _rv; \
173   }
174
175 #define FLS_VALIDATE_PARAM_LENGTH_PAGE_W_RV(_addr, _length, _api, _rv)\
176   int i;\
177   int lengthOk=0;\
178   const Fls_SectorType* sectorPtr= &Fls_Global.config->FlsSectorList[0];\
179   for (i=0; i<Fls_Global.config->FlsSectorListSize;i++) {\
180     if ((sectorPtr->FlsSectorStartaddress + (sectorPtr->FlsNumberOfSectors * sectorPtr->FlsSectorSize))>=(uint32_t)(_addr+(_length))){\
181       if ((0!=_length)&&!(_length % sectorPtr->FlsPageSize)){\
182         lengthOk=1;\
183         break;\
184       }\
185     }\
186     sectorPtr++;\
187   }\
188   if (!lengthOk){\
189     Det_ReportError(MODULE_ID_FLS,0,_api,FLS_E_PARAM_LENGTH ); \
190     return _rv; \
191   }
192
193 #define FLS_VALIDATE_PARAM_LENGTH_SECTOR_W_RV(_addr, _length, _api, _rv)\
194   int i;\
195   int lengthOk=0;\
196   const Fls_SectorType* sectorPtr= &Fls_Global.config->FlsSectorList[0];\
197   for (i=0; i<Fls_Global.config->FlsSectorListSize;i++) {\
198     if ((sectorPtr->FlsSectorStartaddress + (sectorPtr->FlsNumberOfSectors * sectorPtr->FlsSectorSize))>=(uint32_t)(_addr+(_length))){\
199       if ((0!=_length)&& !(_length % sectorPtr->FlsSectorSize)){\
200         lengthOk=1;\
201         break;\
202       }\
203     }\
204     sectorPtr++;\
205   }\
206   if (!lengthOk){\
207     Det_ReportError(MODULE_ID_FLS,0,_api,FLS_E_PARAM_LENGTH ); \
208     return _rv; \
209   }
210
211 #define FLS_VALIDATE_STATUS_UNINIT_W_RV(_status, _api, _rv)\
212   if (MEMIF_UNINIT == _status){\
213     Det_ReportError(MODULE_ID_FLS,0,_api,FLS_E_UNINIT); \
214     return _rv; \
215   }
216
217 #define FLS_VALIDATE_STATUS_BUSY(_status, _api)\
218   if (MEMIF_BUSY == _status){\
219     Det_ReportError(MODULE_ID_FLS,0,_api,FLS_E_BUSY); \
220     return; \
221   }
222
223 #define FLS_VALIDATE_STATUS_BUSY_W_RV(_status, _api, _rv)\
224   if (MEMIF_BUSY == _status){\
225     Det_ReportError(MODULE_ID_FLS,0,_api,FLS_E_BUSY); \
226     return _rv; \
227   }
228
229 #define FLS_VALIDATE_PARAM_DATA_W_RV(_ptr,_api, _rv) \
230   if( (_ptr)==((void *)0)) { \
231     Det_ReportError(MODULE_ID_FLS,0,_api,FLS_E_PARAM_DATA); \
232     return _rv; \
233   }
234 #else
235   #define FLS_VALIDATE_PARAM_ADDRESS_SECTOR_W_RV(_addr, _api, _rv)
236   #define FLS_VALIDATE_PARAM_ADDRESS_PAGE_W_RV(_addr, _api, _rv)
237   #define FLS_VALIDATE_PARAM_LENGTH_SECTOR_W_RV(_addr, _length, _api, _rv)
238   #define FLS_VALIDATE_PARAM_LENGTH_PAGE_W_RV(_addr, _length, _api, _rv)
239   #define FLS_VALIDATE_STATUS_UNINIT_W_RV(_status, _api, _rv)
240   #define FLS_VALIDATE_STATUS_BUSY(_status, _api)
241   #define FLS_VALIDATE_STATUS_BUSY_W_RV(_status, _api, _rv)
242   #define FLS_VALIDATE_PARAM_DATA_W_RV(_ptr,_api,_rv)
243 #endif
244
245 #if ( FLS_DEV_ERROR_DETECT == STD_ON )
246 #define DET_REPORTERROR(_x,_y,_z,_q) Det_ReportError(MODULE_ID_FLS, _y, _z, _q)
247 #else
248 #define DET_REPORTERROR(_x,_y,_z,_q)
249 #endif
250
251 #if ( FLS_GET_JOB_RESULT_API == STD_ON)
252 #define FEE_JOB_END_NOTIFICATION() \
253   if( Fls_Global.config->FlsJobEndNotification != NULL ) { \
254     Fls_Global.config->FlsJobEndNotification(); \
255   }
256 #define FEE_JOB_ERROR_NOTIFICATION() \
257   if( Fls_Global.config->FlsJobErrorNotification != NULL ) { \
258     Fls_Global.config->FlsJobErrorNotification(); \
259   }
260 #else
261 #define FEE_JOB_END_NOTIFICATION()
262 #define FEE_JOB_ERROR_NOTIFICATION()
263 #endif
264
265
266
267 /**
268  * Get PC.
269  * Since you can't read the PC on PPC, do the next best thing.
270  * Ensure that the function is not inlined
271  */
272 static uint32 Fls_GetPc( void ) __attribute__ ((noinline));
273
274 static uint32 Fls_GetPc( void )
275 {
276   return get_spr(SPR_LR);
277 }
278
279
280 typedef struct {
281   uint32 addr;
282   uint32 size;
283 } Fls_InternalSectorType;
284
285
286 SSD_CONFIG ssdConfig = {
287     H7F_REG_BASE,           /* H7F control register base */
288     MAIN_ARRAY_BASE,        /* base of main array */
289     0,                      /* size of main array */
290     SHADOW_ROW_BASE,        /* base of shadow row */
291     SHADOW_ROW_SIZE,        /* size of shadow row */
292     0,                      /* block number in low address space */
293     0,                      /* block number in middle address space */
294     0,                      /* block number in high address space */
295     8,                                  /* page size */
296     FALSE,                   /* debug mode selection */
297 };
298
299 static Std_VersionInfoType _Fls_VersionInfo = {
300     .vendorID                   = (uint16)1,
301     .moduleID                   = (uint16) MODULE_ID_FLS,
302     .instanceID                 = (uint8)1,
303     /* Vendor numbers */
304     .sw_major_version   = (uint8)FLS_SW_MAJOR_VERSION,
305     .sw_minor_version   = (uint8)FLS_SW_MINOR_VERSION,
306     .sw_patch_version   = (uint8)FLS_SW_PATCH_VERSION,
307     .ar_major_version   = (uint8)FLS_AR_MAJOR_VERSION,
308     .ar_minor_version   = (uint8)FLS_AR_MINOR_VERSION,
309     .ar_patch_version   = (uint8)FLS_AR_PATCH_VERSION,
310 };
311
312 //
313 typedef enum {
314   FLS_JOB_NONE,
315   FLS_JOB_COMPARE,
316   FLS_JOB_ERASE,
317   FLS_JOB_READ,
318   FLS_JOB_WRITE,
319 } Fls_Arc_JobType;
320
321 #if 0
322 typedef struct {
323   MemIf_StatusType    status;
324   MemIf_JobResultType jobResultType;
325   Fls_Arc_JobType       jobType;
326   MemIf_AddressType   sourceAddr;
327   uint8 *targetAddr;
328   MemIf_LengthType length;
329
330   Fls_ProgInfoType flashWriteInfo;
331
332 } FlsUnit_t;
333 #endif
334
335
336 #if 0
337 static FlsUnit_t privData = {
338     .status = MEMIF_UNINIT,
339     .jobResultType = MEMIF_JOB_OK,
340     .jobType = FLS_JOB_NONE,
341
342 };
343 #endif
344
345 // Default Config
346 #if 0
347 const Fls_ConfigType * configDataPtr = &FlsConfigSet[0];
348 #endif
349
350 // TODO: Comment and cleanup
351 typedef struct {
352   const Fls_ConfigType * config;
353   Fls_EraseBlockType lockBits;
354
355   MemIf_StatusType    status;
356   MemIf_JobResultType jobResultType;
357   Fls_Arc_JobType       jobType;
358   MemIf_AddressType   sourceAddr;
359   uint8 *targetAddr;
360   MemIf_LengthType length;
361
362   Fls_ProgInfoType flashWriteInfo;
363 } Fls_GlobalType;
364
365 Fls_GlobalType Fls_Global = {
366     .status = MEMIF_UNINIT,
367     .jobResultType = MEMIF_JOB_OK,
368     .jobType = FLS_JOB_NONE,
369 };
370
371
372 #if 0
373 static inline uint32 rlwimi(uint32 val, uint16 sh, uint16 mb,uint16 me)
374 {
375   uint32 result;
376   asm volatile("rlwimi %0,%1,8,16,23"
377           : "=r" (result)
378           : "r" (val),"g" (sh), "g" (mb), "g" (me) );
379   return result;
380 }
381
382 #define CREATE_MASK(_start,_stop) rlwimi(0xffffffff,0x0,0x0,0x10)
383 #endif
384
385 /**
386  * Converts an address to a freescale erase block.
387  * Assumes addr is located from FLS_BASE_ADDRESS
388  *
389  * @param addr address to convert
390  * @param rem pointer to reminder that gets filled in by the function
391  * @return A block number
392  */
393
394 // TODO: This have hardcoded limits. Get from config instead
395 static uint32 address_to_block( uint32 addr, uint32 *rem ) {
396   uint32 block;
397
398   if( addr < 0x20000) {
399     // Low range, 8x16K
400     block = addr / 0x4000;
401     *rem   = addr % 0x4000;
402   } else if ( addr < 0x40000) {
403     // Low range, 2x64k range
404     block = 8 + ( addr - 0x20000 ) / 0x10000;
405     *rem   = addr % 0x10000;
406   } else if( addr < 0x80000 ) {
407     // mid range
408     block = 10 + ( addr - 0x40000 ) / 0x20000;
409     *rem = addr % 0x20000;
410   } else if( addr < 0x180000 ) {
411     // high range
412     block = 12 + ( addr - 0x80000 ) / 0x20000;
413     *rem = addr % 0x20000;
414   } else {
415     block = (-1);
416     *rem = (-1);
417   }
418   return block;
419 }
420
421
422 /**
423  * Converts an address range( addr to addr + size) to freescale bit erase
424  * blocks. The function adds the erase block information to eraseBlocks ptr.
425  *
426  * @param eraseBlocks Ptr to an erase structure
427  * @param addr The start-address to convert
428  * @param size The size of the block
429  * @return The test results
430  */
431 static void address_to_erase_blocks( Fls_EraseBlockType *eraseBlocks, uint32 addr, uint32 size ) {
432 //      EraseBlock_t eraseBlocks;
433   uint32 startBlock;
434   uint32 endBlock;
435   uint32 mask1;
436   uint32 mask2;
437   uint32 mask;
438   uint32 rem;
439
440   /* Create a mask with continuous set of 1's */
441   startBlock = address_to_block( addr,&rem );
442   endBlock = address_to_block( addr + size - 1,&rem );
443
444   // Check so our implementation holds..
445   assert( endBlock<=32 );
446
447 #define BLOCK_MASK 0x0003ffffUL
448
449   // create the mask
450   mask1 = ((-1UL)<<(31-endBlock))>>(31-endBlock);
451   mask2 = ((-1UL)>>startBlock)<<startBlock;
452   mask = mask1 & mask2;
453
454
455   // shift things in to make freescale driver happy
456   eraseBlocks->lowEnabledBlocks = mask&0x3f; // ????
457   eraseBlocks->midEnabledBlocks = (mask>>10)&3; // ????
458   eraseBlocks->highEnabledBlocks = mask>>12;
459
460
461   return ;
462 }
463
464
465 void Fls_Init( const Fls_ConfigType *ConfigPtr )
466 {
467   FLS_VALIDATE_STATUS_BUSY(Fls_Global.status, FLS_INIT_ID);
468   Fls_Global.status             = MEMIF_UNINIT;
469   Fls_Global.jobResultType      = MEMIF_JOB_PENDING;
470   uint32 returnCode;
471   Fls_EraseBlockType eraseBlocks;
472   // TODO: FLS_E_PARAM_CONFIG
473   Fls_Global.config = ConfigPtr;
474
475 #if (FLS_AC_LOAD_ON_JOB_START == STD_ON )
476   /* Copy fls routines to RAM */
477   memcpy(__FLS_ERASE_RAM__,__FLS_ERASE_ROM__, (size_t)&__FLS_SIZE__);
478
479 #endif
480
481
482   returnCode = FlashInit( &ssdConfig );
483
484   // Lock shadow row..
485   eraseBlocks.lowEnabledBlocks = 0;
486   eraseBlocks.midEnabledBlocks = 0;
487   eraseBlocks.highEnabledBlocks = 0;
488   eraseBlocks.shadowBlocks = 1;
489
490   Fls_H7F_SetLock(&eraseBlocks,1);
491
492   Fls_Global.status             = MEMIF_IDLE;
493   Fls_Global.jobResultType      = MEMIF_JOB_OK;
494   return;
495 }
496
497 /* TargetAddress always from 0 to FLS_TOTAL_SIZE */
498 Std_ReturnType Fls_Erase(       MemIf_AddressType   TargetAddress,
499                           MemIf_LengthType    Length )
500 {
501   uint32 block;
502   uint32 sBlock;
503   uint32 rem;
504   Fls_EraseBlockType eraseBlock;
505   Fls_EraseInfoType eraseInfo;
506   uint32 pc;
507
508   FLS_VALIDATE_STATUS_UNINIT_W_RV(Fls_Global.status, FLS_ERASE_ID, E_NOT_OK);
509   FLS_VALIDATE_STATUS_BUSY_W_RV(Fls_Global.status, FLS_ERASE_ID, E_NOT_OK);
510   FLS_VALIDATE_PARAM_ADDRESS_SECTOR_W_RV(TargetAddress, FLS_ERASE_ID, E_NOT_OK);
511   FLS_VALIDATE_PARAM_LENGTH_SECTOR_W_RV(TargetAddress, Length, FLS_ERASE_ID, E_NOT_OK);
512
513   // Always check if status is not busy
514   if (Fls_Global.status == MEMIF_BUSY )
515      return E_NOT_OK;
516
517   // TargetAddress
518   sBlock = address_to_block(TargetAddress,&rem);
519
520   if( (sBlock == (-1)) || (rem!=0) ) {
521     DET_REPORTERROR(MODULE_ID_FLS,0,0x0,FLS_E_PARAM_ADDRESS );
522     return E_NOT_OK;
523   }
524
525   block = address_to_block(TargetAddress+Length,&rem);
526
527   // Check if we trying to erase a partition that we are executing in
528   pc = Fls_GetPc();
529   if( (pc >= FLS_BASE_ADDRESS) && ( pc <= (FLS_BASE_ADDRESS + FLS_TOTAL_SIZE) ) ) {
530     // In flash erase
531         uint32 pcBlock = address_to_block(pc,&rem);
532         uint8 *partMap = Fls_Global.config->FlsBlockToPartitionMap;
533
534         if( (partMap[pcBlock] >= partMap[sBlock]) && (partMap[pcBlock] <= partMap[block]) ) {
535 //    if( address_to_block(pc,&rem) == Fls_Global.config->FlsBlockToPartitionMap[block] ) {
536         // Can't erase and in the same partition we are executing
537         assert(0);
538     }
539   }
540
541   Fls_Global.status = MEMIF_BUSY;
542   Fls_Global.jobResultType = MEMIF_JOB_PENDING;
543   Fls_Global.jobType = FLS_JOB_ERASE;
544
545   address_to_erase_blocks(&eraseBlock,TargetAddress,Length);
546
547   eraseBlock.shadowBlocks = 0;
548   // Unlock
549   Fls_H7F_SetLock(&eraseBlock,0);
550
551   eraseInfo.state  = 0; // Always set this
552
553
554
555   Fls_H7F_FlashErase (  &ssdConfig ,
556           0, // shadowFlag...
557           eraseBlock.lowEnabledBlocks,
558           eraseBlock.midEnabledBlocks,
559           eraseBlock.highEnabledBlocks,
560           &eraseInfo
561                   );
562   return E_OK;
563 }
564
565
566 Std_ReturnType Fls_Write (    MemIf_AddressType   TargetAddress,
567                         const uint8         *SourceAddressPtr,
568                         MemIf_LengthType    Length )
569 {
570   Fls_EraseBlockType eraseBlock;
571
572   FLS_VALIDATE_STATUS_UNINIT_W_RV(Fls_Global.status, FLS_WRITE_ID, E_NOT_OK);
573   FLS_VALIDATE_STATUS_BUSY_W_RV(Fls_Global.status, FLS_WRITE_ID, E_NOT_OK);
574   FLS_VALIDATE_PARAM_ADDRESS_PAGE_W_RV(TargetAddress, FLS_WRITE_ID, E_NOT_OK);
575   FLS_VALIDATE_PARAM_LENGTH_PAGE_W_RV(TargetAddress, Length, FLS_WRITE_ID, E_NOT_OK);
576   FLS_VALIDATE_PARAM_DATA_W_RV(SourceAddressPtr, FLS_WRITE_ID, E_NOT_OK)
577
578   // Always check if status is not busy
579   if (Fls_Global.status == MEMIF_BUSY )
580      return E_NOT_OK;
581
582   // Destination is FLS_BASE_ADDRESS + TargetAddress
583   Fls_Global.jobResultType = MEMIF_JOB_PENDING;
584   Fls_Global.status = MEMIF_BUSY;
585   Fls_Global.jobType = FLS_JOB_WRITE;
586
587   // Fill in the required fields for programming...
588   Fls_Global.flashWriteInfo.source = (uint32)SourceAddressPtr;
589   Fls_Global.flashWriteInfo.dest = TargetAddress;
590   Fls_Global.flashWriteInfo.size = Length;
591
592   // unlock flash....
593   address_to_erase_blocks(&eraseBlock,TargetAddress,Length);
594   eraseBlock.shadowBlocks = 0;
595   Fls_H7F_SetLock(&eraseBlock,0);
596
597   return E_OK;
598 }
599
600 #if ( FLS_CANCEL_API == STD_ON )
601 void Fls_Cancel( void )
602 {
603         /* API NOT SUPPORTED */
604 }
605 #endif
606
607
608 #if ( FLS_GET_STATUS_API == STD_ON )
609 MemIf_StatusType Fls_GetStatus( void )
610 {
611   return Fls_Global.status;
612 }
613 #endif
614
615
616 #if ( FLS_GET_JOB_RESULT_API == STD_ON )
617 MemIf_JobResultType Fls_GetJobResult( void )
618 {
619   return Fls_Global.jobResultType;
620 }
621 #endif
622
623 void Fls_MainFunction( void )
624 {
625   uint32 flashStatus;
626   int result;
627   if( Fls_Global.jobResultType == MEMIF_JOB_PENDING ) {
628     switch(Fls_Global.jobType) {
629     case FLS_JOB_COMPARE:
630       // NOT implemented. Hardware error = FLS_E_COMPARE_FAILED
631       // ( we are reading directly from flash so it makes no sense )
632
633       result = memcmp(Fls_Global.targetAddr,(void *)Fls_Global.sourceAddr,Fls_Global.length);
634       if( result == 0 ) {
635         Fls_Global.jobResultType = MEMIF_JOB_OK;
636       } else {
637         Fls_Global.jobResultType = MEMIF_JOB_FAILED;
638       }
639       Fls_Global.status = MEMIF_IDLE;
640       Fls_Global.jobType = FLS_JOB_NONE;
641
642       break;
643     case FLS_JOB_ERASE:
644     {
645 //      uint32 failAddress;
646 //      uint32 failData;
647
648       flashStatus = Fls_H7F_EraseStatus(&ssdConfig);
649       if( flashStatus == H7F_OK ) {
650         Fls_EraseBlockType blocks;
651         // Lock all.
652         blocks.highEnabledBlocks = (-1UL);
653         blocks.midEnabledBlocks = (-1UL);
654         blocks.highEnabledBlocks = (-1UL);
655         blocks.shadowBlocks = (-1UL);
656
657         Fls_H7F_SetLock(&blocks,1);
658
659         Fls_Global.jobResultType = MEMIF_JOB_OK;
660         Fls_Global.jobType = FLS_JOB_NONE;
661         Fls_Global.status = MEMIF_IDLE;
662         FEE_JOB_END_NOTIFICATION();
663       } else if( flashStatus == H7F_BUSY )  {
664         /* Busy, Do nothing */
665       } else {
666         // Error
667         Fls_Global.jobResultType = MEMIF_JOB_FAILED;
668         Fls_Global.jobType = FLS_JOB_NONE;
669         Fls_Global.status = MEMIF_IDLE;
670 #if defined(USE_DEM)
671                 Dem_ReportErrorStatus(FLS_E_WRITE_FAILED, DEM_EVENT_STATUS_FAILED);
672 #endif
673         FEE_JOB_ERROR_NOTIFICATION();
674       }
675       break;
676     }
677     case FLS_JOB_READ:
678
679       // NOT implemented. Hardware error = FLS_E_READ_FAILED
680       // ( we are reading directly from flash so it makes no sense )
681       memcpy(Fls_Global.targetAddr,(void *)Fls_Global.sourceAddr,Fls_Global.length);
682       Fls_Global.jobResultType = MEMIF_JOB_OK;
683       Fls_Global.status = MEMIF_IDLE;
684       Fls_Global.jobType = FLS_JOB_NONE;
685       break;
686     case FLS_JOB_WRITE:
687     {
688       // NOT implemented. Hardware error = FLS_E_READ_FAILED
689
690       flashStatus = Fls_H7F_Program( &ssdConfig,&Fls_Global.flashWriteInfo);
691
692       if( flashStatus == H7F_OK ) {
693         Fls_EraseBlockType blocks;
694         blocks.highEnabledBlocks = (-1UL);
695         blocks.midEnabledBlocks = (-1UL);
696         blocks.highEnabledBlocks = (-1UL);
697         blocks.shadowBlocks = (-1UL);
698
699         // Lock all
700         Fls_H7F_SetLock(&blocks,1);
701
702         Fls_Global.jobResultType = MEMIF_JOB_OK;
703         Fls_Global.jobType = FLS_JOB_NONE;
704         Fls_Global.status = MEMIF_IDLE;
705         FEE_JOB_END_NOTIFICATION();
706       } else if( flashStatus == H7F_BUSY )  {
707         /* Busy, Do nothing */
708       } else {
709         // Error
710         Fls_Global.jobResultType = MEMIF_JOB_FAILED;
711         Fls_Global.jobType = FLS_JOB_NONE;
712         Fls_Global.status = MEMIF_IDLE;
713 #if defined(USE_DEM)
714                 Dem_ReportErrorStatus(FLS_E_WRITE_FAILED, DEM_EVENT_STATUS_FAILED);
715 #endif
716                 FEE_JOB_ERROR_NOTIFICATION();
717       }
718
719       break;
720     }
721     case FLS_JOB_NONE:
722       assert(0);
723       break;
724     }
725   }
726 }
727
728 Std_ReturnType Fls_Read (       MemIf_AddressType SourceAddress,
729               uint8 *TargetAddressPtr,
730               MemIf_LengthType Length )
731 {
732   FLS_VALIDATE_STATUS_UNINIT_W_RV(Fls_Global.status, FLS_READ_ID, E_NOT_OK);
733   FLS_VALIDATE_STATUS_BUSY_W_RV(Fls_Global.status, FLS_READ_ID, E_NOT_OK);
734   FLS_VALIDATE_PARAM_ADDRESS_PAGE_W_RV(SourceAddress, FLS_READ_ID, E_NOT_OK);
735   FLS_VALIDATE_PARAM_LENGTH_PAGE_W_RV(SourceAddress, Length, FLS_READ_ID, E_NOT_OK);
736   FLS_VALIDATE_PARAM_DATA_W_RV((void*)SourceAddress, FLS_READ_ID, E_NOT_OK)
737
738   // Always check if status is not busy
739   if (Fls_Global.status == MEMIF_BUSY )
740      return E_NOT_OK;
741
742   Fls_Global.status = MEMIF_BUSY;
743   Fls_Global.jobResultType = MEMIF_JOB_PENDING;
744   Fls_Global.jobType = FLS_JOB_READ;
745
746   Fls_Global.sourceAddr = SourceAddress;
747   Fls_Global.targetAddr = TargetAddressPtr;
748   Fls_Global.length = Length;
749
750   return E_OK;
751 }
752
753 #if ( FLS_COMPARE_API == STD_ON )
754 Std_ReturnType Fls_Compare( MemIf_AddressType SourceAddress,
755               uint8 *TargetAddressPtr,
756               MemIf_LengthType Length )
757 {
758   FLS_VALIDATE_STATUS_UNINIT_W_RV(Fls_Global.status, FLS_COMPARE_ID, E_NOT_OK);
759   FLS_VALIDATE_STATUS_BUSY_W_RV(Fls_Global.status, FLS_COMPARE_ID, E_NOT_OK);
760   FLS_VALIDATE_PARAM_ADDRESS_PAGE_W_RV(SourceAddress, FLS_COMPARE_ID, E_NOT_OK);
761   FLS_VALIDATE_PARAM_LENGTH_PAGE_W_RV(SourceAddress, Length, FLS_COMPARE_ID, E_NOT_OK);
762   FLS_VALIDATE_PARAM_DATA_W_RV((void*)SourceAddress,FLS_COMPARE_ID, E_NOT_OK)
763
764   // Always check if status is not busy
765   if (Fls_Global.status == MEMIF_BUSY )
766      return E_NOT_OK;
767
768   Fls_Global.status = MEMIF_BUSY;
769   Fls_Global.jobResultType = MEMIF_JOB_PENDING;
770   Fls_Global.jobType = FLS_JOB_COMPARE;
771
772   Fls_Global.sourceAddr = SourceAddress;
773   Fls_Global.targetAddr = TargetAddressPtr;
774   Fls_Global.length = Length;
775
776   return E_OK;
777 }
778 #endif
779
780 #if ( FLS_SET_MODE_API == STD_ON )
781 void Fls_SetMode(               MemIf_ModeType Mode )
782 {
783         /* API NOT SUPPORTED */
784 }
785 #endif
786
787 void Fls_GetVersionInfo( Std_VersionInfoType *VersioninfoPtr )
788 {
789   memcpy(VersioninfoPtr, &_Fls_VersionInfo, sizeof(Std_VersionInfoType));
790 }
791
792
793