1 /* -------------------------------- Arctic Core ------------------------------
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
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>.
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
14 * -------------------------------- Arctic Core ------------------------------*/
25 * @breif Autosar Flash driver for Freescale MPC55xx.
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
39 * 1. Bootloader, self replace
40 * 2. Bootloader, application loading
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 ).
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 ??
55 /* Freescale driver */
56 #include "ssd_types.h"
65 #include "h7f_types.h"
71 /* Flash layout for MPC5516 */
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
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)
90 static inline int Fls_Validate( uint32 addr,uint32 length, uint32 api,uint32 rv ) {
94 const Fls_SectorType* sector;
95 Fls_ConfigType *cfg = Fls_Global.config;
98 if( flags & VFLAGS_LEN_SECT ) {
99 if( (addr + length) > FLS_TOTAL_SIZE ) {
104 for(i=0;i<cfg->FlsSectorListSize;i++) {
105 sector = &cfg->FlsSectorList[sectorIndex];
106 if( addr > (sector->FlsSectorStartaddress + sector->FlsNumberOfSectors * sector->FlsNumberOfSectors) ) {
109 if( flags & VFLAGS_ADDR_SECT ) {
110 if( (addr % sector->FlsSectorSize) == 0) {
111 flags &= ~VFLAGS_ADDR_SECT;
114 if( flags & VFLAGS_ADDR_PAGE ) {
115 if( (addr % sector->FlsPageSize) == 0) {
116 flags &= ~VFLAGS_ADDR_PAGE;
119 if( flags & VFLAGS_LEN_SECT ) {
121 if( (0!= length) && (length < sectorPtr->FlsSectorSize) ) {
122 flags &= ~VFLAGS_ADDR_SECT;
125 if( flags & VFLAGS_LEN_PAGE ) {
126 if( (0!= length) && (length < sectorPtr->FlsPageSize)) {
127 flags &= ~VFLAGS_ADDR_PAGE;
134 #if ( FLS_DEV_ERROR_DETECT == STD_ON )
135 #define FLS_VALIDATE_PARAM_ADDRESS_SECTOR_W_RV(_addr, _api, _rv)\
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 */\
151 Det_ReportError(MODULE_ID_FLS,0,_api,FLS_E_PARAM_ADDRESS ); \
155 #define FLS_VALIDATE_PARAM_ADDRESS_PAGE_W_RV(_addr, _api, _rv)\
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 */\
171 Det_ReportError(MODULE_ID_FLS,0,_api,FLS_E_PARAM_ADDRESS ); \
175 #define FLS_VALIDATE_PARAM_LENGTH_PAGE_W_RV(_addr, _length, _api, _rv)\
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)){\
189 Det_ReportError(MODULE_ID_FLS,0,_api,FLS_E_PARAM_LENGTH ); \
193 #define FLS_VALIDATE_PARAM_LENGTH_SECTOR_W_RV(_addr, _length, _api, _rv)\
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)){\
207 Det_ReportError(MODULE_ID_FLS,0,_api,FLS_E_PARAM_LENGTH ); \
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); \
217 #define FLS_VALIDATE_STATUS_BUSY(_status, _api)\
218 if (MEMIF_BUSY == _status){\
219 Det_ReportError(MODULE_ID_FLS,0,_api,FLS_E_BUSY); \
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); \
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); \
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)
245 #if ( FLS_DEV_ERROR_DETECT == STD_ON )
246 #define DET_REPORTERROR(_x,_y,_z,_q) Det_ReportError(MODULE_ID_FLS, _y, _z, _q)
248 #define DET_REPORTERROR(_x,_y,_z,_q)
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(); \
256 #define FEE_JOB_ERROR_NOTIFICATION() \
257 if( Fls_Global.config->FlsJobErrorNotification != NULL ) { \
258 Fls_Global.config->FlsJobErrorNotification(); \
261 #define FEE_JOB_END_NOTIFICATION()
262 #define FEE_JOB_ERROR_NOTIFICATION()
269 * Since you can't read the PC on PPC, do the next best thing.
270 * Ensure that the function is not inlined
272 static uint32 Fls_GetPc( void ) __attribute__ ((noinline));
274 static uint32 Fls_GetPc( void )
276 return get_spr(SPR_LR);
283 } Fls_InternalSectorType;
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 */
296 FALSE, /* debug mode selection */
299 static Std_VersionInfoType _Fls_VersionInfo = {
300 .vendorID = (uint16)1,
301 .moduleID = (uint16) MODULE_ID_FLS,
302 .instanceID = (uint8)1,
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,
323 MemIf_StatusType status;
324 MemIf_JobResultType jobResultType;
325 Fls_Arc_JobType jobType;
326 MemIf_AddressType sourceAddr;
328 MemIf_LengthType length;
330 Fls_ProgInfoType flashWriteInfo;
337 static FlsUnit_t privData = {
338 .status = MEMIF_UNINIT,
339 .jobResultType = MEMIF_JOB_OK,
340 .jobType = FLS_JOB_NONE,
347 const Fls_ConfigType * configDataPtr = &FlsConfigSet[0];
350 // TODO: Comment and cleanup
352 const Fls_ConfigType * config;
353 Fls_EraseBlockType lockBits;
355 MemIf_StatusType status;
356 MemIf_JobResultType jobResultType;
357 Fls_Arc_JobType jobType;
358 MemIf_AddressType sourceAddr;
360 MemIf_LengthType length;
362 Fls_ProgInfoType flashWriteInfo;
365 Fls_GlobalType Fls_Global = {
366 .status = MEMIF_UNINIT,
367 .jobResultType = MEMIF_JOB_OK,
368 .jobType = FLS_JOB_NONE,
373 static inline uint32 rlwimi(uint32 val, uint16 sh, uint16 mb,uint16 me)
376 asm volatile("rlwimi %0,%1,8,16,23"
378 : "r" (val),"g" (sh), "g" (mb), "g" (me) );
382 #define CREATE_MASK(_start,_stop) rlwimi(0xffffffff,0x0,0x0,0x10)
386 * Converts an address to a freescale erase block.
387 * Assumes addr is located from FLS_BASE_ADDRESS
389 * @param addr address to convert
390 * @param rem pointer to reminder that gets filled in by the function
391 * @return A block number
394 // TODO: This have hardcoded limits. Get from config instead
395 static uint32 address_to_block( uint32 addr, uint32 *rem ) {
398 if( addr < 0x20000) {
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 ) {
408 block = 10 + ( addr - 0x40000 ) / 0x20000;
409 *rem = addr % 0x20000;
410 } else if( addr < 0x180000 ) {
412 block = 12 + ( addr - 0x80000 ) / 0x20000;
413 *rem = addr % 0x20000;
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.
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
431 static void address_to_erase_blocks( Fls_EraseBlockType *eraseBlocks, uint32 addr, uint32 size ) {
432 // EraseBlock_t eraseBlocks;
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 );
444 // Check so our implementation holds..
445 assert( endBlock<=32 );
447 #define BLOCK_MASK 0x0003ffffUL
450 mask1 = ((-1UL)<<(31-endBlock))>>(31-endBlock);
451 mask2 = ((-1UL)>>startBlock)<<startBlock;
452 mask = mask1 & mask2;
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;
465 void Fls_Init( const Fls_ConfigType *ConfigPtr )
467 FLS_VALIDATE_STATUS_BUSY(Fls_Global.status, FLS_INIT_ID);
468 Fls_Global.status = MEMIF_UNINIT;
469 Fls_Global.jobResultType = MEMIF_JOB_PENDING;
471 Fls_EraseBlockType eraseBlocks;
472 // TODO: FLS_E_PARAM_CONFIG
473 Fls_Global.config = ConfigPtr;
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__);
482 returnCode = FlashInit( &ssdConfig );
485 eraseBlocks.lowEnabledBlocks = 0;
486 eraseBlocks.midEnabledBlocks = 0;
487 eraseBlocks.highEnabledBlocks = 0;
488 eraseBlocks.shadowBlocks = 1;
490 Fls_H7F_SetLock(&eraseBlocks,1);
492 Fls_Global.status = MEMIF_IDLE;
493 Fls_Global.jobResultType = MEMIF_JOB_OK;
497 /* TargetAddress always from 0 to FLS_TOTAL_SIZE */
498 Std_ReturnType Fls_Erase( MemIf_AddressType TargetAddress,
499 MemIf_LengthType Length )
504 Fls_EraseBlockType eraseBlock;
505 Fls_EraseInfoType eraseInfo;
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);
513 // Always check if status is not busy
514 if (Fls_Global.status == MEMIF_BUSY )
518 sBlock = address_to_block(TargetAddress,&rem);
520 if( (sBlock == (-1)) || (rem!=0) ) {
521 DET_REPORTERROR(MODULE_ID_FLS,0,0x0,FLS_E_PARAM_ADDRESS );
525 block = address_to_block(TargetAddress+Length,&rem);
527 // Check if we trying to erase a partition that we are executing in
529 if( (pc >= FLS_BASE_ADDRESS) && ( pc <= (FLS_BASE_ADDRESS + FLS_TOTAL_SIZE) ) ) {
531 uint32 pcBlock = address_to_block(pc,&rem);
532 uint8 *partMap = Fls_Global.config->FlsBlockToPartitionMap;
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
541 Fls_Global.status = MEMIF_BUSY;
542 Fls_Global.jobResultType = MEMIF_JOB_PENDING;
543 Fls_Global.jobType = FLS_JOB_ERASE;
545 address_to_erase_blocks(&eraseBlock,TargetAddress,Length);
547 eraseBlock.shadowBlocks = 0;
549 Fls_H7F_SetLock(&eraseBlock,0);
551 eraseInfo.state = 0; // Always set this
555 Fls_H7F_FlashErase ( &ssdConfig ,
557 eraseBlock.lowEnabledBlocks,
558 eraseBlock.midEnabledBlocks,
559 eraseBlock.highEnabledBlocks,
566 Std_ReturnType Fls_Write ( MemIf_AddressType TargetAddress,
567 const uint8 *SourceAddressPtr,
568 MemIf_LengthType Length )
570 Fls_EraseBlockType eraseBlock;
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)
578 // Always check if status is not busy
579 if (Fls_Global.status == MEMIF_BUSY )
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;
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;
593 address_to_erase_blocks(&eraseBlock,TargetAddress,Length);
594 eraseBlock.shadowBlocks = 0;
595 Fls_H7F_SetLock(&eraseBlock,0);
600 #if ( FLS_CANCEL_API == STD_ON )
601 void Fls_Cancel( void )
603 /* API NOT SUPPORTED */
608 #if ( FLS_GET_STATUS_API == STD_ON )
609 MemIf_StatusType Fls_GetStatus( void )
611 return Fls_Global.status;
616 #if ( FLS_GET_JOB_RESULT_API == STD_ON )
617 MemIf_JobResultType Fls_GetJobResult( void )
619 return Fls_Global.jobResultType;
623 void Fls_MainFunction( void )
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 )
633 result = memcmp(Fls_Global.targetAddr,(void *)Fls_Global.sourceAddr,Fls_Global.length);
635 Fls_Global.jobResultType = MEMIF_JOB_OK;
637 Fls_Global.jobResultType = MEMIF_JOB_FAILED;
639 Fls_Global.status = MEMIF_IDLE;
640 Fls_Global.jobType = FLS_JOB_NONE;
645 // uint32 failAddress;
648 flashStatus = Fls_H7F_EraseStatus(&ssdConfig);
649 if( flashStatus == H7F_OK ) {
650 Fls_EraseBlockType blocks;
652 blocks.highEnabledBlocks = (-1UL);
653 blocks.midEnabledBlocks = (-1UL);
654 blocks.highEnabledBlocks = (-1UL);
655 blocks.shadowBlocks = (-1UL);
657 Fls_H7F_SetLock(&blocks,1);
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 */
667 Fls_Global.jobResultType = MEMIF_JOB_FAILED;
668 Fls_Global.jobType = FLS_JOB_NONE;
669 Fls_Global.status = MEMIF_IDLE;
671 Dem_ReportErrorStatus(FLS_E_WRITE_FAILED, DEM_EVENT_STATUS_FAILED);
673 FEE_JOB_ERROR_NOTIFICATION();
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;
688 // NOT implemented. Hardware error = FLS_E_READ_FAILED
690 flashStatus = Fls_H7F_Program( &ssdConfig,&Fls_Global.flashWriteInfo);
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);
700 Fls_H7F_SetLock(&blocks,1);
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 */
710 Fls_Global.jobResultType = MEMIF_JOB_FAILED;
711 Fls_Global.jobType = FLS_JOB_NONE;
712 Fls_Global.status = MEMIF_IDLE;
714 Dem_ReportErrorStatus(FLS_E_WRITE_FAILED, DEM_EVENT_STATUS_FAILED);
716 FEE_JOB_ERROR_NOTIFICATION();
728 Std_ReturnType Fls_Read ( MemIf_AddressType SourceAddress,
729 uint8 *TargetAddressPtr,
730 MemIf_LengthType Length )
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)
738 // Always check if status is not busy
739 if (Fls_Global.status == MEMIF_BUSY )
742 Fls_Global.status = MEMIF_BUSY;
743 Fls_Global.jobResultType = MEMIF_JOB_PENDING;
744 Fls_Global.jobType = FLS_JOB_READ;
746 Fls_Global.sourceAddr = SourceAddress;
747 Fls_Global.targetAddr = TargetAddressPtr;
748 Fls_Global.length = Length;
753 #if ( FLS_COMPARE_API == STD_ON )
754 Std_ReturnType Fls_Compare( MemIf_AddressType SourceAddress,
755 uint8 *TargetAddressPtr,
756 MemIf_LengthType Length )
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)
764 // Always check if status is not busy
765 if (Fls_Global.status == MEMIF_BUSY )
768 Fls_Global.status = MEMIF_BUSY;
769 Fls_Global.jobResultType = MEMIF_JOB_PENDING;
770 Fls_Global.jobType = FLS_JOB_COMPARE;
772 Fls_Global.sourceAddr = SourceAddress;
773 Fls_Global.targetAddr = TargetAddressPtr;
774 Fls_Global.length = Length;
780 #if ( FLS_SET_MODE_API == STD_ON )
781 void Fls_SetMode( MemIf_ModeType Mode )
783 /* API NOT SUPPORTED */
787 void Fls_GetVersionInfo( Std_VersionInfoType *VersioninfoPtr )
789 memcpy(VersioninfoPtr, &_Fls_VersionInfo, sizeof(Std_VersionInfoType));