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
26 #include "Fee_Cbk.h"
\r
29 #include "Rte.h" // ???
\r
30 #if defined(USE_DEM)
\r
33 //#include "SchM_NvM.h"
\r
40 // Validation macros
\r
41 #if ( FEE_DEV_ERROR_DETECT == STD_ON )
\r
43 #define VALIDATE(_exp,_api,_err ) \
\r
45 Det_ReportError(MODULE_ID_FEE, 0, _api, _err); \
\r
48 #define VALIDATE_RV(_exp,_api,_err,_rv ) \
\r
50 Det_ReportError(MODULE_ID_FEE, 0, _api, _err); \
\r
54 #define VALIDATE_NO_RV(_exp,_api,_err ) \
\r
56 Det_ReportError(MODULE_ID_FEE, 0, _api, _err); \
\r
59 #define DET_REPORTERROR(_module,_instance,_api,_err) Det_ReportError(_module,_instance,_api,_err)
\r
62 #define VALIDATE(_exp,_api,_err )
\r
63 #define VALIDATE_RV(_exp,_api,_err,_rv )
\r
64 #define VALIDATE_NO_RV(_exp,_api,_err )
\r
65 #define DET_REPORTERROR(_module,_instance,_api,_err)
\r
68 // Block numbering recalculation macros
\r
69 #define GET_BLOCK_INDEX_FROM_BLOCK_NUMBER(blocknr) ((blocknr >> NVM_DATASET_SELECTION_BITS) - 1)
\r
70 #define GET_DATASET_FROM_BLOCK_NUMBER(blocknr) (blocknr & ((1 << NVM_DATASET_SELECTION_BITS) - 1))
\r
72 // Macro for checking if the flash is ready
\r
73 #define FLASH_READY (FlsAdmin.State == FEE_FLS_STATE_READY)
\r
75 // Macros and variables for flash block administration
\r
76 #define BLOCK_ADMIN_STATUS_VALID 0x01
\r
77 #define BLOCK_ADMIN_STATUS_EMPTY 0x02
\r
79 #define BLOCK_ADMIN_MAGIC_LEN 4
\r
83 uint8 Magic[BLOCK_ADMIN_MAGIC_LEN];
\r
84 } FlsBlockAdminType;
\r
86 static FlsBlockAdminType FlsBlockAdmin;
\r
88 #define BLOCK_ADMIN_LEN (sizeof(FlsBlockAdminType))
\r
89 #define BLOCK_ADMIN_VALIDATE_POS 0
\r
90 #define BLOCK_ADMIN_MAGIC_POS 2
\r
92 static const uint8 MagicMaster[BLOCK_ADMIN_MAGIC_LEN] = { 0xeb, 0xba, 0xba, 0xbe };
\r
93 static const FlsBlockAdminType FlsBlockAdminMaster = {
\r
94 .Status = BLOCK_ADMIN_STATUS_VALID | ~BLOCK_ADMIN_STATUS_EMPTY,
\r
95 .Magic = { 0xeb, 0xba, 0xba, 0xbe }
\r
98 // Variables for keeping the state and status of the flash
\r
100 FEE_FLS_STATE_IDLE,
\r
101 FEE_FLS_STATE_PENDING,
\r
102 FEE_FLS_STATE_READY
\r
106 FlsStateType State;
\r
107 Std_ReturnType ErrorStatus;
\r
108 MemIf_JobResultType JobResult;
\r
111 static FlsAdminType FlsAdmin = {
\r
112 .State = FEE_FLS_STATE_IDLE,
\r
113 .ErrorStatus = E_OK,
\r
114 .JobResult = MEMIF_JOB_OK
\r
117 // Variables for quick reporting of status and job result
\r
118 static MemIf_StatusType ModuleStatus = MEMIF_UNINIT;
\r
119 static MemIf_JobResultType JobResult = MEMIF_JOB_OK;
\r
121 // Variables for the current job
\r
123 FEE_UNINITIALIZED = 0,
\r
125 FEE_WRITE_REQUESTED,
\r
126 FEE_WRITE_MAGIC_EREASE_PENDING,
\r
127 FEE_WRITE_EREASE_PENDING,
\r
129 FEE_WRITE_BLOCK_ADMIN_PENDING,
\r
130 FEE_READ_REQUESTED,
\r
131 FEE_READ_BLOCK_ADMIN_PENDING,
\r
133 FEE_CANCEL_REQUESTED,
\r
134 FEE_CANCEL_PENDING,
\r
135 FEE_INVALIDATE_REQUESTED,
\r
136 FEE_INVALIDATE_PENDING,
\r
137 FEE_ERASE_IMMEDIATE_REQUESTED,
\r
138 FEE_ERASE_IMMEDIATE_PENDING
\r
139 } CurrentJobStateType;
\r
142 CurrentJobStateType State;
\r
143 const Fee_BlockConfigType *BlockConfigPtr;
\r
146 Fls_AddressType FlsBlockAddr; // Flash source/Dest depending of operation
\r
147 Fls_AddressType FlsBlockAdminAddr; // Startadress of admin block
\r
148 uint8 *RamPtr; // RAM source/Dest depending of operation
\r
151 static CurrentJobType CurrentJob = {
\r
159 #if (FEE_POLLING_MODE == STD_ON)
\r
160 void PollFlsJobResult(void)
\r
162 MemIf_JobResultType jobResult;
\r
164 if (FlsAdmin.State == FEE_FLS_STATE_PENDING) {
\r
165 jobResult = Fls_GetJobResult();
\r
167 if (jobResult == MEMIF_JOB_OK) {
\r
168 FlsAdmin.ErrorStatus = E_OK;
\r
169 FlsAdmin.JobResult = jobResult;
\r
170 FlsAdmin.State = FEE_FLS_STATE_READY;
\r
171 } else if (jobResult != MEMIF_JOB_PENDING) {
\r
172 FlsAdmin.ErrorStatus = E_NOT_OK;
\r
173 FlsAdmin.JobResult = jobResult;
\r
174 FlsAdmin.State = FEE_FLS_STATE_READY;
\r
179 #define PollFlsJobResult(...)
\r
183 void FinnishJob(void)
\r
185 FlsAdmin.State = FEE_FLS_STATE_IDLE;
\r
186 CurrentJob.State = FEE_IDLE;
\r
188 ModuleStatus = MEMIF_IDLE;
\r
189 JobResult = FlsAdmin.JobResult;
\r
191 if (FlsAdmin.ErrorStatus == E_OK) {
\r
192 if (Fee_Config.General.NvmJobEndCallbackNotificationCallback != NULL) {
\r
193 Fee_Config.General.NvmJobEndCallbackNotificationCallback();
\r
196 if (Fee_Config.General.NvmJobErrorCallbackNotificationCallback != NULL) {
\r
197 Fee_Config.General.NvmJobErrorCallbackNotificationCallback();
\r
203 void ReadStartJob(void)
\r
205 if (FlsAdmin.State == FEE_FLS_STATE_IDLE) {
\r
206 FlsAdmin.State = FEE_FLS_STATE_PENDING;
\r
207 CurrentJob.State = FEE_READ_BLOCK_ADMIN_PENDING;
\r
208 // Start by reading the admin block
\r
209 if (Fls_Read(CurrentJob.FlsBlockAdminAddr, (uint8*)&FlsBlockAdmin, BLOCK_ADMIN_LEN) != E_OK) {
\r
210 FlsAdmin.State = FEE_FLS_STATE_READY;
\r
211 FlsAdmin.ErrorStatus = E_NOT_OK;
\r
212 FlsAdmin.JobResult = Fls_GetJobResult();
\r
218 void ReadCheckBlockAdminJob(void)
\r
220 if (FlsAdmin.ErrorStatus == E_OK) {
\r
221 if (memcmp(FlsBlockAdmin.Magic, MagicMaster, BLOCK_ADMIN_MAGIC_LEN) == 0) {
\r
222 if (FlsBlockAdmin.Status & BLOCK_ADMIN_STATUS_VALID) {
\r
223 if (FlsAdmin.State != FEE_FLS_STATE_PENDING) {
\r
224 FlsAdmin.State = FEE_FLS_STATE_PENDING;
\r
225 CurrentJob.State = FEE_READ_PENDING;
\r
226 // Read the actual data
\r
227 if (Fls_Read(CurrentJob.FlsBlockAddr + CurrentJob.Offset, CurrentJob.RamPtr, CurrentJob.Length) != E_OK) {
\r
228 FlsAdmin.State = FEE_FLS_STATE_READY;
\r
229 FlsAdmin.ErrorStatus = E_NOT_OK;
\r
230 FlsAdmin.JobResult = Fls_GetJobResult();
\r
235 FlsAdmin.ErrorStatus = E_NOT_OK;
\r
236 FlsAdmin.JobResult = MEMIF_BLOCK_INVALID;
\r
240 FlsAdmin.ErrorStatus = E_NOT_OK;
\r
241 FlsAdmin.JobResult = MEMIF_BLOCK_INCONSISTENT;
\r
250 void WriteStartJob(void)
\r
252 if (FlsAdmin.State == FEE_FLS_STATE_IDLE) {
\r
253 FlsAdmin.State = FEE_FLS_STATE_PENDING;
\r
254 CurrentJob.State = FEE_WRITE_MAGIC_EREASE_PENDING;
\r
255 // Start by erasing the magic
\r
256 if (Fls_Erase(CurrentJob.FlsBlockAdminAddr + BLOCK_ADMIN_MAGIC_POS, BLOCK_ADMIN_MAGIC_LEN) != E_OK) {
\r
257 FlsAdmin.State = FEE_FLS_STATE_READY;
\r
258 FlsAdmin.ErrorStatus = E_NOT_OK;
\r
259 FlsAdmin.JobResult = Fls_GetJobResult();
\r
266 void WriteCheckMagicEraseJob(void)
\r
268 if (FlsAdmin.ErrorStatus == E_OK) {
\r
269 if (FlsAdmin.State != FEE_FLS_STATE_PENDING) {
\r
270 FlsAdmin.State = FEE_FLS_STATE_PENDING;
\r
271 CurrentJob.State = FEE_WRITE_EREASE_PENDING;
\r
272 // Erase the rest of the block
\r
273 if (Fls_Erase(CurrentJob.FlsBlockAddr, CurrentJob.BlockConfigPtr->BlockSize + BLOCK_ADMIN_LEN - BLOCK_ADMIN_MAGIC_LEN) != E_OK) {
\r
274 FlsAdmin.State = FEE_FLS_STATE_READY;
\r
275 FlsAdmin.ErrorStatus = E_NOT_OK;
\r
276 FlsAdmin.JobResult = Fls_GetJobResult();
\r
286 void WriteCheckEraseJob(void)
\r
288 if (FlsAdmin.ErrorStatus == E_OK) {
\r
289 if (FlsAdmin.State != FEE_FLS_STATE_PENDING) {
\r
290 FlsAdmin.State = FEE_FLS_STATE_PENDING;
\r
291 CurrentJob.State = FEE_WRITE_PENDING;
\r
292 // Write the actual data
\r
293 if (Fls_Write(CurrentJob.FlsBlockAddr, CurrentJob.RamPtr, CurrentJob.Length) != E_OK) {
\r
294 FlsAdmin.State = FEE_FLS_STATE_READY;
\r
295 FlsAdmin.ErrorStatus = E_NOT_OK;
\r
296 FlsAdmin.JobResult = Fls_GetJobResult();
\r
306 void WriteCheckWriteJob(void)
\r
308 if (FlsAdmin.ErrorStatus == E_OK) {
\r
309 if (FlsAdmin.State != FEE_FLS_STATE_PENDING) {
\r
310 FlsAdmin.State = FEE_FLS_STATE_PENDING;
\r
311 CurrentJob.State = FEE_WRITE_BLOCK_ADMIN_PENDING;
\r
312 // Write the block admin (mark it as consistent, valid and not empty)
\r
313 if (Fls_Write(CurrentJob.FlsBlockAdminAddr, (uint8*)&FlsBlockAdminMaster, BLOCK_ADMIN_LEN) != E_OK) {
\r
314 FlsAdmin.State = FEE_FLS_STATE_READY;
\r
315 FlsAdmin.ErrorStatus = E_NOT_OK;
\r
316 FlsAdmin.JobResult = Fls_GetJobResult();
\r
326 void InvalidateStartJob(void)
\r
328 static const uint8 zero = 0;
\r
330 if (FlsAdmin.State == FEE_FLS_STATE_IDLE) {
\r
331 FlsAdmin.State = FEE_FLS_STATE_PENDING;
\r
332 CurrentJob.State = FEE_INVALIDATE_PENDING;
\r
333 // Write a zero to the Validate flag
\r
334 if (Fls_Write(CurrentJob.FlsBlockAdminAddr + BLOCK_ADMIN_VALIDATE_POS, &zero, 1) != E_OK) {
\r
335 FlsAdmin.State = FEE_FLS_STATE_READY;
\r
336 FlsAdmin.ErrorStatus = E_NOT_OK;
\r
337 FlsAdmin.JobResult = Fls_GetJobResult();
\r
343 /***************************************
\r
344 * External accessible functions *
345 ***************************************/
\r
347 * Procedure: Fee_Init
\r
350 void Fee_Init(void)
\r
352 // Reporting information
\r
353 ModuleStatus = MEMIF_IDLE;
\r
354 JobResult = MEMIF_JOB_OK;
\r
357 CurrentJob.State = FEE_IDLE;
\r
358 FlsAdmin.State = FEE_FLS_STATE_IDLE;
\r
359 FlsAdmin.ErrorStatus = E_OK;
\r
360 FlsAdmin.JobResult = MEMIF_JOB_OK;
\r
365 * Procedure: Fee_SetMode
\r
368 void Fee_SetMode(MemIf_ModeType mode)
\r
370 #if ( FLS_SET_MODE_API == STD_ON )
\r
373 DET_REPORTERROR(MODULE_ID_FEE, 0, FEE_SET_MODE_ID, FEE_E_NOT_SUPPORTED);
\r
378 * Procedure: Fee_Read
\r
381 Std_ReturnType Fee_Read(uint16 blockNumber, uint16 blockOffset, uint8* dataBufferPtr, uint16 length)
\r
385 VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_READ_ID, FEE_E_UNINIT, E_NOT_OK);
\r
386 VALIDATE_RV(ModuleStatus == MEMIF_IDLE, FEE_READ_ID, FEE_E_BUSY, E_NOT_OK);
\r
388 VALIDATE_RV(blockNumber >= (1 << NVM_DATASET_SELECTION_BITS), FEE_READ_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);
\r
389 blockIndex = GET_BLOCK_INDEX_FROM_BLOCK_NUMBER(blockNumber);
\r
390 VALIDATE_RV(blockIndex < FEE_NUM_OF_BLOCKS, FEE_READ_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);
\r
391 VALIDATE_RV(dataBufferPtr != NULL, FEE_READ_ID, FEE_E_INVALID_DATA_PTR, E_NOT_OK);
\r
392 VALIDATE_RV(blockOffset < Fee_Config.BlockConfig[blockIndex].BlockSize, FEE_READ_ID, FEE_E_INVALID_BLOCK_OFS, E_NOT_OK);
\r
393 VALIDATE_RV(blockOffset + length <= Fee_Config.BlockConfig[blockIndex].BlockSize, FEE_READ_ID, FEE_E_INVALID_BLOCK_LEN, E_NOT_OK);
\r
397 ModuleStatus = MEMIF_BUSY;
\r
398 JobResult = MEMIF_JOB_PENDING;
\r
400 CurrentJob.BlockConfigPtr = &Fee_Config.BlockConfig[blockIndex];
\r
401 CurrentJob.Length = length;
\r
402 CurrentJob.Offset = blockOffset;
\r
403 CurrentJob.FlsBlockAddr = (CurrentJob.BlockConfigPtr->PhysBlockBaseNumber - 1) * FEE_VIRTUAL_PAGE_SIZE + GET_DATASET_FROM_BLOCK_NUMBER(blockNumber) * CurrentJob.BlockConfigPtr->BlockSize; /** @req FEE021 */
\r
404 CurrentJob.FlsBlockAdminAddr = CurrentJob.FlsBlockAddr + CurrentJob.BlockConfigPtr->BlockSize;
\r
405 CurrentJob.RamPtr = dataBufferPtr;
\r
406 CurrentJob.State = FEE_READ_REQUESTED;
\r
413 * Procedure: Fee_Write
\r
416 Std_ReturnType Fee_Write(uint16 blockNumber, uint8* dataBufferPtr)
\r
420 VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_WRITE_ID, FEE_E_UNINIT, E_NOT_OK);
\r
421 VALIDATE_RV(ModuleStatus == MEMIF_IDLE, FEE_WRITE_ID, FEE_E_BUSY, E_NOT_OK);
\r
423 VALIDATE_RV(blockNumber >= (1 << NVM_DATASET_SELECTION_BITS), FEE_WRITE_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);
\r
424 blockIndex = GET_BLOCK_INDEX_FROM_BLOCK_NUMBER(blockNumber);
\r
425 VALIDATE_RV(blockIndex < FEE_NUM_OF_BLOCKS, FEE_WRITE_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);
\r
426 VALIDATE_RV(dataBufferPtr != NULL, FEE_WRITE_ID, FEE_E_INVALID_DATA_PTR, E_NOT_OK);
\r
430 ModuleStatus = MEMIF_BUSY;
\r
431 JobResult = MEMIF_JOB_PENDING;
\r
433 CurrentJob.BlockConfigPtr = &Fee_Config.BlockConfig[blockIndex];
\r
434 CurrentJob.Length = CurrentJob.BlockConfigPtr->BlockSize;
\r
435 CurrentJob.FlsBlockAddr = (CurrentJob.BlockConfigPtr->PhysBlockBaseNumber - 1) * FEE_VIRTUAL_PAGE_SIZE + GET_DATASET_FROM_BLOCK_NUMBER(blockNumber) * CurrentJob.BlockConfigPtr->BlockSize; /** @req FEE024 */
\r
436 CurrentJob.FlsBlockAdminAddr = CurrentJob.FlsBlockAddr + CurrentJob.BlockConfigPtr->BlockSize;
\r
437 CurrentJob.RamPtr = dataBufferPtr;
\r
438 CurrentJob.State = FEE_WRITE_REQUESTED;
\r
445 * Procedure: Fee_Cancel
\r
448 void Fee_Cancel(void)
\r
450 DET_REPORTERROR(MODULE_ID_FEE, 0, FEE_CANCEL_ID, FEE_E_NOT_IMPLEMENTED_YET);
\r
455 * Procedure: Fee_GetStatus
\r
458 MemIf_StatusType Fee_GetStatus(void)
\r
460 return ModuleStatus;
\r
465 * Procedure: Fee_GetJobResult
\r
468 MemIf_JobResultType Fee_GetJobResult(void)
\r
475 * Procedure: Fee_InvalidateBlock
\r
478 Std_ReturnType Fee_InvalidateBlock(uint16 blockNumber)
\r
482 VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_INVALIDATE_BLOCK_ID, FEE_E_UNINIT, E_NOT_OK);
\r
483 VALIDATE_RV(ModuleStatus == MEMIF_IDLE, FEE_INVALIDATE_BLOCK_ID, FEE_E_BUSY, E_NOT_OK);
\r
485 VALIDATE_RV(blockNumber >= (1 << NVM_DATASET_SELECTION_BITS), FEE_INVALIDATE_BLOCK_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);
\r
486 blockIndex = GET_BLOCK_INDEX_FROM_BLOCK_NUMBER(blockNumber);
\r
487 VALIDATE_RV(blockIndex < FEE_NUM_OF_BLOCKS, FEE_INVALIDATE_BLOCK_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);
\r
490 ModuleStatus = MEMIF_BUSY;
\r
491 JobResult = MEMIF_JOB_PENDING;
\r
493 CurrentJob.BlockConfigPtr = &Fee_Config.BlockConfig[blockIndex];
\r
494 CurrentJob.Length = 0;
\r
495 CurrentJob.FlsBlockAddr = (CurrentJob.BlockConfigPtr->PhysBlockBaseNumber - 1) * FEE_VIRTUAL_PAGE_SIZE + GET_DATASET_FROM_BLOCK_NUMBER(blockNumber) * CurrentJob.BlockConfigPtr->BlockSize; /** @req FEE024 */
\r
496 CurrentJob.FlsBlockAdminAddr = CurrentJob.FlsBlockAddr + CurrentJob.BlockConfigPtr->BlockSize;
\r
497 CurrentJob.RamPtr = NULL;
\r
498 CurrentJob.State = FEE_INVALIDATE_REQUESTED;
\r
505 * Procedure: Fee_EraseImmediateBlock
\r
508 Std_ReturnType Fee_EraseImmediateBlock(uint16 blockNumber)
\r
510 DET_REPORTERROR(MODULE_ID_FEE, 0, FEE_ERASE_IMMEDIATE_ID, FEE_E_NOT_IMPLEMENTED_YET);
\r
516 /***************************************
\r
517 * Scheduled functions *
518 ***************************************/
\r
520 * Procedure: Fee_MainFunction
\r
523 void Fee_MainFunction(void)
\r
525 switch (CurrentJob.State) {
\r
526 case FEE_UNINITIALIZED:
\r
531 case FEE_READ_REQUESTED:
\r
535 case FEE_READ_BLOCK_ADMIN_PENDING:
\r
536 PollFlsJobResult();
\r
538 ReadCheckBlockAdminJob();
\r
542 case FEE_READ_PENDING:
\r
543 PollFlsJobResult();
\r
550 case FEE_WRITE_REQUESTED:
\r
554 case FEE_WRITE_MAGIC_EREASE_PENDING:
\r
555 PollFlsJobResult();
\r
557 WriteCheckMagicEraseJob();
\r
561 case FEE_WRITE_EREASE_PENDING:
\r
562 PollFlsJobResult();
\r
564 WriteCheckEraseJob();
\r
568 case FEE_WRITE_PENDING:
\r
569 PollFlsJobResult();
\r
571 WriteCheckWriteJob();
\r
575 case FEE_WRITE_BLOCK_ADMIN_PENDING:
\r
576 PollFlsJobResult();
\r
582 // Invalidate states
\r
583 case FEE_INVALIDATE_REQUESTED:
\r
584 InvalidateStartJob();
\r
587 case FEE_INVALIDATE_PENDING:
\r
588 PollFlsJobResult();
\r
601 /***************************************
\r
602 * Call-back notifications functions *
603 ***************************************/
\r
604 #if (FEE_POLLING_MODE == STD_OFF)
\r
606 * Procedure: Fee_JobEndNotification
\r
609 void Fee_JobEndNotification(void)
\r
611 FlsAdmin.State = FEE_FLS_STATE_READY;
\r
612 FlsAdmin.ErrorStatus = E_OK;
\r
613 FlsAdmin.JobResult = Fls_GetJobResult();
\r
618 * Procedure: Fee_JobErrorNotification
\r
621 void Fee_JobErrorNotification(void)
\r
623 FlsAdmin.State = FEE_FLS_STATE_READY;
\r
624 FlsAdmin.ErrorStatus = E_NOT_OK;
\r
625 FlsAdmin.JobResult = Fls_GetJobResult();
\r