1 /* -------------------------------- Arctic Core ------------------------------
\r
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
\r
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
\r
6 * This source code is free software; you can redistribute it and/or modify it
\r
7 * under the terms of the GNU General Public License version 2 as published by the
\r
8 * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
\r
10 * This program is distributed in the hope that it will be useful, but
\r
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
\r
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
\r
14 * -------------------------------- Arctic Core ------------------------------*/
\r
16 /** @req EA113 @req EA112 @req EA049 @req EA038 */
\r
17 /** @req EA116 @req EA117 @req EA083 @req EA097 */
\r
24 #include "Ea_Types.h"
\r
31 #if (STD_ON == EA_DEV_ERROR_DETECT)
\r
37 // States used by EA_MainFunction to control the internal state of the module.
\r
44 EA_PENDING_ADMIN_WRITE
\r
50 define EA module notification callback macro
\r
52 #define EA_JOB_END_NOTIFICATION() \
\r
53 if (Ea_Global.EaGeneralPtr->EaNvmJobEndNotification != NULL_PTR){ \
\r
54 Ea_Global.EaGeneralPtr->EaNvmJobEndNotification(); \
\r
57 #define EA_JOB_ERROR_NOTIFICATION() \
\r
58 if (Ea_Global.EaGeneralPtr->EaNvmJobErrorNotification != NULL_PTR) { \
\r
59 Ea_Global.EaGeneralPtr->EaNvmJobErrorNotification(); \
\r
63 * Defines for blockstates
66 #define BLOCK_INCONSISTENT 0x23
\r
67 #define BLOCK_CONSISTENT 0x45
\r
68 #define BLOCK_INVALIDATED 0x67
\r
71 * Definition of the Admin block type
77 uint8 check; // Simple checksum
\r
81 * Define EA Module Global Type
\r
84 const Ea_BlockConfigType *EaBlockConfig;
\r
85 const Ea_GeneralType *EaGeneralPtr;
\r
86 MemIf_StatusType ModuleStatus;
\r
87 MemIf_JobResultType JobResult;
\r
89 uint16 CurrentBlock; // The block we are currentlty working on
\r
90 Eep_AddressType EepAddress; // Start adress to read from
\r
91 uint16 Length; // The length to read i.e the blockSize
\r
92 Ea_JobStatus JobStatus; // Internal state to be used by main function.
\r
93 void* Address; // The adress to put the result into
\r
94 uint16 ReadLength; // The length of the block to read/write
\r
95 uint16 Offset; // The offset in the block to read from.
\r
99 * Define EA Module Global
\r
101 static Ea_GlobalType Ea_Global = {
\r
109 static uint8 Ea_TempBuffer[EA_MAX_BLOCK_SIZE + sizeof(Ea_AdminBlock)];
\r
112 * Function prototypes
114 static uint16 EA_GET_BLOCK(uint16 BlockNumber);
\r
115 static Eep_AddressType calculateEepAddress(uint16 BlockIndex);
\r
116 static uint16 calculateBlockLength(uint16 BlockIndex);
\r
117 static void handleLowerLayerRead(void);
\r
118 static void handleLowerLayerWrite(void);
\r
119 static void handleLowerLayerErase(void);
\r
120 static uint8 verifyChecksum(Ea_AdminBlock* block);
\r
121 static void addChecksum(Ea_AdminBlock* block);
\r
123 /* Local functions */
\r
124 static Std_ReturnType Ea_ValidateInitialized(Ea_APIServiceIDType apiId)
\r
126 Std_ReturnType result = E_OK;
\r
127 if( Ea_Global.ModuleStatus == MEMIF_UNINIT )
\r
129 #if EA_DEV_ERROR_DETECT==STD_ON
\r
130 Det_ReportError(EA_MODULE_ID,0, apiId, EA_E_NOT_INITIALIZED);
\r
137 static Std_ReturnType Ea_ValidateBlock(uint16 blockNumber, Ea_APIServiceIDType apiId)
\r
139 Std_ReturnType result = E_OK;
\r
140 if( (blockNumber == 0) || (blockNumber == 0xffff) )
\r
142 #if EA_DEV_ERROR_DETECT==STD_ON
\r
143 Det_ReportError(EA_MODULE_ID,0, apiId, EA_E_INVALID_BLOCK_NO);
\r
150 static Std_ReturnType Ea_ValidateBlockIndex(uint16 blockIndex, Ea_APIServiceIDType apiId)
\r
152 Std_ReturnType result = E_OK;
\r
153 if( blockIndex >= EA_NUMBER_OF_BLOCKS )
\r
155 #if EA_DEV_ERROR_DETECT==STD_ON
\r
156 Det_ReportError(EA_MODULE_ID,0, apiId, EA_E_INVALID_BLOCK_NO);
\r
167 /*init internal variables*/
\r
168 Ea_Global.EaBlockConfig = Ea_BlockConfigData;
\r
169 Ea_Global.EaGeneralPtr = &Ea_GeneralData;
\r
170 Ea_Global.JobResult = MEMIF_JOB_OK; /*@req <EA128> */
\r
171 Ea_Global.JobType = EA_JOB_NONE;
\r
172 Ea_Global.JobStatus = EA_PENDING_NONE;
\r
173 Ea_Global.ModuleStatus = MEMIF_IDLE; /*@req <EA128> */
\r
177 #if (STD_ON == EA_SET_MODE_SUPPORTED)
\r
180 void Ea_SetMode(MemIf_ModeType Mode)
\r
182 if (E_OK != Ea_ValidateInitialized(EA_SETMODE_ID))
\r
192 Std_ReturnType Ea_Read(uint16 BlockNumber, uint16 BlockOffset, uint8* DataBufferPtr, uint16 Length)
\r
195 const Ea_BlockConfigType *EaBlockCon;
\r
199 if (E_OK != Ea_ValidateInitialized(EA_READ_ID)){
\r
203 if (E_OK != Ea_ValidateBlock(BlockNumber, EA_READ_ID)){
\r
207 /* Lock down the module to ourself */
\r
209 if (Ea_Global.ModuleStatus != MEMIF_IDLE)
\r
211 Irq_Restore(state);
\r
214 /*set current state is internal busy*/
\r
215 Ea_Global.ModuleStatus = MEMIF_BUSY_INTERNAL;
\r
216 Irq_Restore(state);
\r
218 BlockIndex = EA_GET_BLOCK(BlockNumber);
\r
221 if (E_OK != Ea_ValidateBlockIndex(BlockIndex, EA_READ_ID))
\r
223 Ea_Global.ModuleStatus = MEMIF_IDLE;
\r
227 /*whether block device index match underlying driver in which Eep_Read will be invoked*/
\r
228 EaBlockCon = Ea_Global.EaBlockConfig;
\r
230 /*check whether BlockOffset add Length exceed the blocksize*/
\r
231 if (BlockOffset + Length > EaBlockCon[BlockIndex].EaBlockSize)
\r
236 Ea_Global.Address = DataBufferPtr;
\r
237 /*@req <EA021> :calculate the corresponding memory read address for underlying Eep_Read*/
\r
238 Ea_Global.EepAddress = calculateEepAddress(BlockIndex);
\r
239 Ea_Global.Length = EaBlockCon[BlockIndex].EaBlockSize + sizeof(Ea_AdminBlock);
\r
240 Ea_Global.Offset = BlockOffset;
\r
241 Ea_Global.ReadLength = Length;
\r
242 Ea_Global.CurrentBlock = BlockNumber;
\r
245 Ea_Global.ModuleStatus = MEMIF_BUSY;
\r
246 Ea_Global.JobType = EA_JOB_READ;
\r
247 Ea_Global.JobResult = MEMIF_JOB_PENDING;
\r
248 Ea_Global.JobStatus = EA_PENDING_NONE;
\r
256 Std_ReturnType Ea_Write(uint16 BlockNumber, uint8* DataBufferPtr)
\r
259 const Ea_BlockConfigType *EaBlockCon;
\r
260 Ea_AdminBlock* adminBlock;
\r
264 if (E_OK != Ea_ValidateInitialized(EA_WRITE_ID)){
\r
268 if (E_OK != Ea_ValidateBlock(BlockNumber, EA_WRITE_ID)){
\r
273 /* Lock down the module to ourself */
\r
275 if (Ea_Global.ModuleStatus != MEMIF_IDLE)
\r
277 Irq_Restore(state);
\r
280 /*set current state is internal busy*/
\r
281 Ea_Global.ModuleStatus = MEMIF_BUSY_INTERNAL;
\r
282 Irq_Restore(state);
\r
284 BlockIndex = EA_GET_BLOCK(BlockNumber);
\r
287 if (E_OK != Ea_ValidateBlockIndex(BlockIndex, EA_READ_ID))
\r
289 Ea_Global.ModuleStatus = MEMIF_IDLE;
\r
293 /*whether block device index match underlying driver in which Eep_Read will be invoked*/
\r
294 EaBlockCon = Ea_Global.EaBlockConfig;
\r
296 /*caculate the EepAddress*/
\r
297 Ea_Global.EepAddress = calculateEepAddress(BlockIndex);
\r
298 Ea_Global.Length = EaBlockCon[BlockIndex].EaBlockSize + sizeof(Ea_AdminBlock);
\r
299 Ea_Global.Address = (void*)DataBufferPtr;
\r
300 Ea_Global.CurrentBlock = BlockNumber;
\r
302 /* Setup the admin block */
\r
304 adminBlock = (Ea_AdminBlock*) Ea_TempBuffer;
\r
305 adminBlock->blockNum = BlockNumber;
\r
306 adminBlock->blockState = BLOCK_INCONSISTENT;
\r
307 addChecksum(adminBlock);
\r
309 /* Copy the data to the buffer */
\r
310 uint8* destMem = (uint8*) (Ea_TempBuffer + sizeof(Ea_AdminBlock));
\r
311 memcpy(destMem, DataBufferPtr, EaBlockCon[BlockIndex].EaBlockSize);
\r
313 /*@req <EA025> [set internal variables set the EA module status to MEMIF_BUSY, set the job result to MEMIF_JOB_PENDING.]*/
\r
314 Ea_Global.ModuleStatus = MEMIF_BUSY;
\r
315 Ea_Global.JobType = EA_JOB_WRITE;
\r
316 Ea_Global.JobResult = MEMIF_JOB_PENDING;
\r
317 Ea_Global.JobStatus = EA_PENDING_NONE;
\r
323 void Ea_Cancel(void)
\r
326 if (E_OK != Ea_ValidateInitialized(EA_CANCEL_ID)){
\r
329 /*@req <EA078> [Reset the Ea module's internal variables to make the module ready for a new job request.]*/
\r
330 Ea_Global.JobType = EA_JOB_NONE;
\r
331 Ea_Global.ModuleStatus = MEMIF_IDLE;
\r
332 Ea_Global.JobResult = MEMIF_JOB_CANCELLED;
\r
334 /*@req <EA077> [Call the cancel function of the underlying EEPROM driver.]*/
\r
342 MemIf_StatusType Ea_GetStatus(void)
\r
344 MemIf_StatusType rv;
\r
348 if (E_OK != Ea_ValidateInitialized(EA_GETSTATUS_ID)){
\r
352 else if (MEMIF_IDLE == Ea_Global.ModuleStatus){
\r
355 /*@req <EA073> [check if EA Module is busy with internal management operations.]*/
\r
356 else if (MEMIF_BUSY_INTERNAL == Ea_Global.ModuleStatus){
\r
357 rv = MEMIF_BUSY_INTERNAL;
\r
366 MemIf_JobResultType Ea_GetJobResult(void)
\r
368 MemIf_JobResultType rv;
\r
370 if (E_OK != Ea_ValidateInitialized(EA_GETJOBRESULT_ID)){
\r
371 rv = MEMIF_JOB_FAILED;
\r
374 rv = Ea_Global.JobResult;
\r
380 Std_ReturnType Ea_InvalidateBlock(uint16 BlockNumber)
\r
383 const Ea_BlockConfigType *EaBlockCon;
\r
384 Ea_AdminBlock* adminBlock;
\r
385 Std_ReturnType result;
\r
389 if (E_OK != Ea_ValidateInitialized(EA_INVALIDATEBLOCK_ID)){
\r
393 if (E_OK != Ea_ValidateBlock(BlockNumber, EA_INVALIDATEBLOCK_ID)){
\r
398 /* Lock down the module to ourself */
\r
400 if (Ea_Global.ModuleStatus != MEMIF_IDLE)
\r
402 Irq_Restore(state);
\r
405 /*set current state is internal busy*/
\r
406 Ea_Global.ModuleStatus = MEMIF_BUSY_INTERNAL;
\r
407 Irq_Restore(state);
\r
409 BlockIndex = EA_GET_BLOCK(BlockNumber);
\r
412 if (E_OK != Ea_ValidateBlockIndex(BlockIndex, EA_INVALIDATEBLOCK_ID))
\r
414 Ea_Global.ModuleStatus = MEMIF_IDLE;
\r
418 /*whether block device index match underlying driver in which Eep_Read will be invoked*/
\r
419 EaBlockCon = Ea_Global.EaBlockConfig;
\r
421 /*@req <EA036> [calculate address]*/
\r
422 Ea_Global.EepAddress = calculateEepAddress(BlockIndex);
\r
423 Ea_Global.Length = EaBlockCon[BlockIndex].EaBlockSize;
\r
424 Ea_Global.CurrentBlock = BlockNumber;
\r
425 Ea_Global.ModuleStatus = MEMIF_BUSY;
\r
426 Ea_Global.JobType = EA_JOB_WRITE;
\r
427 Ea_Global.JobStatus = EA_PENDING_ADMIN_WRITE;
\r
428 Ea_Global.JobResult = MEMIF_JOB_PENDING;
\r
430 /*@req <EA037> [now we calling the erase function of the underlying device driver]*/
\r
431 /* We just set the Invalidate status of the admin block */
\r
432 /* Setup the admin block to be consistent again*/
\r
434 adminBlock = (Ea_AdminBlock*) Ea_TempBuffer;
\r
435 adminBlock->blockNum = BlockNumber;
\r
436 adminBlock->blockState = BLOCK_INVALIDATED;
\r
437 addChecksum(adminBlock);
\r
439 result = Eep_Write(Ea_Global.EepAddress, (const uint8*) Ea_TempBuffer, sizeof(Ea_AdminBlock));
\r
440 if (E_OK == result)
\r
443 MemIf_StatusType status = Eep_GetStatus();
\r
444 if ((status == MEMIF_BUSY) || (status == MEMIF_BUSY_INTERNAL)){
\r
445 Ea_Global.JobStatus = EA_PENDING_ADMIN_WRITE;
\r
447 Irq_Restore(state);
\r
451 Ea_Global.JobType = EA_JOB_NONE;
\r
452 Ea_Global.JobResult = MEMIF_JOB_FAILED;
\r
453 Ea_Global.JobStatus = EA_PENDING_NONE;
\r
454 Ea_Global.ModuleStatus = MEMIF_IDLE;
\r
462 Std_ReturnType Ea_EraseImmediateBlock(uint16 BlockNumber)
\r
465 const Ea_BlockConfigType *EaBlockCon;
\r
469 if (E_OK != Ea_ValidateInitialized(EA_ERASEIMMEDIATEBLOCK_ID)){
\r
473 if (E_OK != Ea_ValidateBlock(BlockNumber, EA_ERASEIMMEDIATEBLOCK_ID)){
\r
478 /* Lock down the module to ourself */
\r
480 if (Ea_Global.ModuleStatus != MEMIF_IDLE)
\r
482 Irq_Restore(state);
\r
485 /*set current state is internal busy*/
\r
486 Ea_Global.ModuleStatus = MEMIF_BUSY_INTERNAL;
\r
487 Irq_Restore(state);
\r
489 BlockIndex = EA_GET_BLOCK(BlockNumber);
\r
492 if (E_OK != Ea_ValidateBlockIndex(BlockIndex, EA_ERASEIMMEDIATEBLOCK_ID))
\r
494 Ea_Global.ModuleStatus = MEMIF_IDLE;
\r
498 EaBlockCon = Ea_Global.EaBlockConfig;
\r
500 /*@req <EA065> [check whether the addressed logical block is configured as containing immediate data]*/
\r
501 if (false == EaBlockCon[BlockIndex].EaImmediateData)
\r
503 Det_ReportError(EA_MODULE_ID, 0, EA_ERASEIMMEDIATEBLOCK_ID, EA_E_INVALID_BLOCK_NO);
\r
505 Ea_Global.ModuleStatus = MEMIF_IDLE;
\r
509 /*@req <EA063> [take the block number and calculate the corresponding memory block address.]*/
\r
510 Ea_Global.EepAddress = calculateEepAddress(BlockIndex);
\r
511 Ea_Global.Length = calculateBlockLength(BlockIndex); // Calculate the block length in full pages
\r
512 Ea_Global.CurrentBlock = BlockNumber;
\r
514 /*@req <EA025> [set internal variables set the EA module status to MEMIF_BUSY, set the job result to MEMIF_JOB_PENDING.]*/
\r
515 Ea_Global.ModuleStatus = MEMIF_BUSY;
\r
516 Ea_Global.JobType = EA_JOB_ERASE;
\r
517 Ea_Global.JobResult = MEMIF_JOB_PENDING;
\r
518 Ea_Global.JobStatus = EA_PENDING_NONE;
\r
526 void Ea_MainFunction(void)
\r
528 Std_ReturnType result;
\r
531 if ((MEMIF_JOB_PENDING == Ea_Global.JobResult) && (Ea_Global.JobStatus == EA_PENDING_NONE))
\r
533 switch (Ea_Global.JobType)
\r
537 if (MEMIF_IDLE == Eep_GetStatus())
\r
539 result = Eep_Write(Ea_Global.EepAddress, (const uint8*) Ea_TempBuffer, Ea_Global.Length);
\r
540 if (E_OK == result)
\r
543 MemIf_StatusType status = Eep_GetStatus();
\r
544 if ((status == MEMIF_BUSY) || (status == MEMIF_BUSY_INTERNAL)){
\r
545 Ea_Global.JobStatus = EA_PENDING_WRITE;
\r
547 Irq_Restore(state);
\r
553 if (MEMIF_IDLE == Eep_GetStatus())
\r
555 result = Eep_Read(Ea_Global.EepAddress, (uint8*) Ea_TempBuffer, Ea_Global.Length);
\r
556 if (E_OK == result)
\r
559 MemIf_StatusType status = Eep_GetStatus();
\r
560 if ((status == MEMIF_BUSY) || (status == MEMIF_BUSY_INTERNAL)){
\r
561 Ea_Global.JobStatus = EA_PENDING_READ;
\r
563 Irq_Restore(state);
\r
568 if (MEMIF_IDLE == Eep_GetStatus())
\r
570 result = Eep_Erase(Ea_Global.EepAddress, Ea_Global.Length);
\r
571 if (E_OK == result)
\r
574 MemIf_StatusType status = Eep_GetStatus();
\r
575 if ((status == MEMIF_BUSY) || (status == MEMIF_BUSY_INTERNAL)){
\r
576 Ea_Global.JobStatus = EA_PENDING_ERASE;
\r
578 Irq_Restore(state);
\r
589 // We have pending jobs. Wait for them to finish.
\r
590 switch(Ea_Global.JobStatus)
\r
593 // Nothing to do for this state. Just wait
\r
600 /*Callback notifications of the Ea module*/
\r
604 void Ea_JobEndNotification(void)
\r
606 Ea_Global.JobResult = Eep_GetJobResult();
\r
608 if (Ea_Global.JobResult == MEMIF_JOB_CANCELLED)
\r
610 Ea_Global.JobType = EA_JOB_NONE;
\r
611 Ea_Global.JobResult = MEMIF_JOB_CANCELLED;
\r
612 Ea_Global.JobStatus = EA_PENDING_NONE;
\r
613 Ea_Global.ModuleStatus = MEMIF_IDLE;
\r
614 // Should we call upper layer here?
\r
618 switch(Ea_Global.JobStatus)
\r
620 case EA_PENDING_READ:
\r
621 handleLowerLayerRead();
\r
623 case EA_PENDING_WRITE:
\r
624 handleLowerLayerWrite();
\r
626 case EA_PENDING_ERASE:
\r
627 handleLowerLayerErase();
\r
629 case EA_PENDING_ADMIN_WRITE:
\r
630 Ea_Global.JobType = EA_JOB_NONE;
\r
631 Ea_Global.JobStatus = EA_PENDING_NONE;
\r
632 Ea_Global.ModuleStatus = MEMIF_IDLE;
\r
637 EA_JOB_END_NOTIFICATION();
\r
640 assert(0); // Should never come here
\r
647 static void handleLowerLayerRead()
\r
649 Ea_AdminBlock* adminBlock;
\r
651 /* Check the admin block i.e the block is consistent */
\r
653 adminBlock = (Ea_AdminBlock*) Ea_TempBuffer;
\r
654 if ((!verifyChecksum(adminBlock)) || (adminBlock->blockState == BLOCK_INCONSISTENT)
\r
655 || (adminBlock->blockNum != Ea_Global.CurrentBlock))
\r
657 Ea_Global.JobType = EA_JOB_NONE;
\r
659 Ea_Global.JobResult = MEMIF_BLOCK_INCONSISTENT;
\r
660 Ea_Global.JobStatus = EA_PENDING_NONE;
\r
661 Ea_Global.ModuleStatus = MEMIF_IDLE;
\r
662 EA_JOB_ERROR_NOTIFICATION();
\r
665 /* Check if block is invalidated */
\r
667 if (adminBlock->blockState == BLOCK_INVALIDATED)
\r
669 Ea_Global.JobType = EA_JOB_NONE;
\r
671 Ea_Global.JobResult = MEMIF_BLOCK_INVALID;
\r
672 Ea_Global.JobStatus = EA_PENDING_NONE;
\r
673 Ea_Global.ModuleStatus = MEMIF_IDLE;
\r
674 EA_JOB_ERROR_NOTIFICATION();
\r
678 // Copy the data to the destination
\r
679 uint8* srcadress = (uint8*) (Ea_TempBuffer + sizeof (Ea_AdminBlock) + Ea_Global.Offset);
\r
680 memcpy(Ea_Global.Address, srcadress, Ea_Global.ReadLength);
\r
683 Ea_Global.JobType = EA_JOB_NONE;
\r
684 Ea_Global.JobStatus = EA_PENDING_NONE;
\r
685 Ea_Global.ModuleStatus = MEMIF_IDLE;
\r
687 EA_JOB_END_NOTIFICATION();
\r
690 static void handleLowerLayerWrite()
\r
692 Ea_AdminBlock* adminBlock;
\r
693 Std_ReturnType result;
\r
696 if (Ea_Global.JobResult == MEMIF_JOB_OK)
\r
698 /* Setup the admin block to be consistent again*/
\r
700 adminBlock = (Ea_AdminBlock*) Ea_TempBuffer;
\r
701 adminBlock->blockNum = Ea_Global.CurrentBlock;
\r
702 adminBlock->blockState = BLOCK_CONSISTENT;
\r
703 addChecksum(adminBlock);
\r
705 result = Eep_Write(Ea_Global.EepAddress, (const uint8*) Ea_TempBuffer, sizeof(Ea_AdminBlock));
\r
706 if (E_OK == result)
\r
709 MemIf_StatusType status = Eep_GetStatus();
\r
710 if ((status == MEMIF_BUSY) || (status == MEMIF_BUSY_INTERNAL)){
\r
711 Ea_Global.JobStatus = EA_PENDING_ADMIN_WRITE;
\r
713 Irq_Restore(state);
\r
716 Ea_Global.JobResult = MEMIF_JOB_FAILED;
\r
717 Ea_Global.JobType = EA_JOB_NONE;
\r
718 Ea_Global.JobStatus = EA_PENDING_NONE;
\r
719 Ea_Global.ModuleStatus = MEMIF_IDLE;
\r
722 EA_JOB_END_NOTIFICATION();
\r
727 /* Report error upstreams */
\r
728 Ea_Global.JobType = EA_JOB_NONE;
\r
730 Ea_Global.JobResult = MEMIF_BLOCK_INVALID;
\r
731 Ea_Global.JobStatus = EA_PENDING_NONE;
\r
732 Ea_Global.ModuleStatus = MEMIF_IDLE;
\r
735 EA_JOB_END_NOTIFICATION();
\r
739 static void handleLowerLayerErase()
\r
741 Ea_AdminBlock* adminBlock;
\r
742 Std_ReturnType result;
\r
745 if (Ea_Global.JobResult == MEMIF_JOB_OK)
\r
747 /* Setup the admin block to be consistent again*/
\r
749 adminBlock = (Ea_AdminBlock*) Ea_TempBuffer;
\r
750 adminBlock->blockNum = Ea_Global.CurrentBlock;
\r
751 adminBlock->blockState = BLOCK_INCONSISTENT;
\r
752 addChecksum(adminBlock);
\r
754 result = Eep_Write(Ea_Global.EepAddress, (const uint8*) Ea_TempBuffer, sizeof(Ea_AdminBlock));
\r
755 if (E_OK == result)
\r
758 MemIf_StatusType status = Eep_GetStatus();
\r
759 if ((status == MEMIF_BUSY) || (status == MEMIF_BUSY_INTERNAL)){
\r
760 Ea_Global.JobStatus = EA_PENDING_ADMIN_WRITE;
\r
762 Irq_Restore(state);
\r
765 Ea_Global.JobResult = MEMIF_JOB_FAILED;
\r
766 Ea_Global.JobType = EA_JOB_NONE;
\r
767 Ea_Global.JobStatus = EA_PENDING_NONE;
\r
768 Ea_Global.ModuleStatus = MEMIF_IDLE;
\r
771 EA_JOB_END_NOTIFICATION();
\r
776 /* Report error upstreams */
\r
777 Ea_Global.JobType = EA_JOB_NONE;
\r
779 Ea_Global.JobResult = MEMIF_BLOCK_INVALID;
\r
780 Ea_Global.JobStatus = EA_PENDING_NONE;
\r
781 Ea_Global.ModuleStatus = MEMIF_IDLE;
\r
784 EA_JOB_END_NOTIFICATION();
\r
791 void Ea_JobErrorNotification(void)
\r
797 if (Ea_Global.JobResult == MEMIF_JOB_PENDING){
\r
798 Ea_Global.JobResult = MEMIF_JOB_FAILED;
\r
801 Ea_Global.JobType = EA_JOB_NONE;
\r
802 Ea_Global.JobStatus = EA_PENDING_NONE;
\r
803 Ea_Global.ModuleStatus = MEMIF_IDLE;
\r
804 Irq_Restore(state);
\r
812 EA_JOB_ERROR_NOTIFICATION();
\r
816 * Local service to get block index in Ea_Lcfg.c
\r
818 static uint16 EA_GET_BLOCK(uint16 BlockNumber)
\r
820 const Ea_BlockConfigType *EaBlockCon;
\r
823 EaBlockCon = Ea_Global.EaBlockConfig;
\r
824 for (BlockIndex = 0; BlockIndex < EA_NUMBER_OF_BLOCKS; BlockIndex++)
\r
826 if (EaBlockCon[BlockIndex].EaBlockNumber == BlockNumber)
\r
835 * Local service to calculate the actual eep address.
\r
838 static Eep_AddressType calculateEepAddress(uint16 BlockIndex)
\r
840 const Ea_BlockConfigType *EaBlockCon;
\r
841 uint32 totalNumOfBlocks = 0;
\r
844 EaBlockCon = Ea_Global.EaBlockConfig;
\r
845 uint16 blockNum = EaBlockCon[BlockIndex].EaBlockNumber;
\r
846 uint8 device = EaBlockCon[BlockIndex].EaDeviceIndex;
\r
848 for (i = 0; i < EA_NUMBER_OF_BLOCKS; i++)
\r
850 if (EaBlockCon[i].EaDeviceIndex == device) // Check that this is the same device
\r
852 if (EaBlockCon[i].EaBlockNumber < blockNum) // Check that blocknum is less than the searched one
\r
854 int blocksize = EaBlockCon[i].EaBlockSize + sizeof(Ea_AdminBlock);
\r
855 int numOfBlocks = blocksize / EA_VIRTUAL_PAGE_SIZE;
\r
856 if (blocksize % EA_VIRTUAL_PAGE_SIZE){
\r
860 totalNumOfBlocks = totalNumOfBlocks + numOfBlocks;
\r
865 return totalNumOfBlocks * EA_VIRTUAL_PAGE_SIZE;
\r
868 static uint16 calculateBlockLength(uint16 BlockIndex)
\r
870 const Ea_BlockConfigType *EaBlockCon;
\r
872 EaBlockCon = Ea_Global.EaBlockConfig;
\r
873 int blocksize = EaBlockCon[BlockIndex].EaBlockSize + sizeof(Ea_AdminBlock);
\r
874 int numOfBlocks = blocksize / EA_VIRTUAL_PAGE_SIZE;
\r
875 if (blocksize % EA_VIRTUAL_PAGE_SIZE){
\r
879 return numOfBlocks * EA_VIRTUAL_PAGE_SIZE;
\r
882 /* Some very simple checksum calculations */
\r
883 /* Better than nothing :-) */
\r
884 static uint8 verifyChecksum(Ea_AdminBlock* block)
\r
887 uint8* array = (uint8*) block;
\r
890 result += array[1];
\r
891 result += array[2];
\r
893 result = result ^ 0xaaU;
\r
895 return (result == block->check);
\r
898 static void addChecksum(Ea_AdminBlock* block)
\r
901 uint8* array = (uint8*) block;
\r
904 result += array[1];
\r
905 result += array[2];
\r
907 result = result ^ 0xaaU;
\r
909 block->check = result;
\r