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
39 #if ( FEE_DEV_ERROR_DETECT == STD_ON )
\r
41 #define VALIDATE(_exp,_api,_err ) \
\r
43 Det_ReportError(MODULE_ID_FEE, 0, _api, _err); \
\r
46 #define VALIDATE_RV(_exp,_api,_err,_rv ) \
\r
48 Det_ReportError(MODULE_ID_FEE, 0, _api, _err); \
\r
52 #define VALIDATE_NO_RV(_exp,_api,_err ) \
\r
54 Det_ReportError(MODULE_ID_FEE, 0, _api, _err); \
\r
57 #define DET_REPORTERROR(_module,_instance,_api,_err) Det_ReportError(_module,_instance,_api,_err)
\r
60 #define VALIDATE(_exp,_api,_err )
\r
61 #define VALIDATE_RV(_exp,_api,_err,_rv )
\r
62 #define VALIDATE_NO_RV(_exp,_api,_err )
\r
63 #define DET_REPORTERROR(_module,_instance,_api,_err)
\r
67 #define GET_BLOCK_INDEX_FROM_BLOCK_NUMBER(blocknr) ((blocknr >> NVM_DATASET_SELECTION_BITS) - 1)
\r
68 #define GET_DATASET_FROM_BLOCK_NUMBER(blocknr) (blocknr & ((1 << NVM_DATASET_SELECTION_BITS) - 1))
\r
70 #define FLS_READY (FlsAdmin.State == FEE_FLS_STATE_READY)
\r
73 #define VALIDATE_POS (MAGIC_LEN + 0)
\r
75 uint8 Magic[MAGIC_LEN];
\r
79 static BlockHeaderType BlockHeader;
\r
80 #define BLOCK_HEADER_LEN (sizeof(BlockHeaderType))
\r
82 static const uint8 MagicMaster[MAGIC_LEN] = { 0xeb, 0xba, 0xba, 0xbe };
\r
83 static const BlockHeaderType BlockHeaderMaster = {
\r
84 .Magic = {0xeb, 0xba, 0xba, 0xbe },
\r
88 // Variables for quick reporting of status and job result
\r
89 static MemIf_StatusType ModuleStatus = MEMIF_UNINIT;
\r
90 static MemIf_JobResultType JobResult = MEMIF_JOB_OK;
\r
96 FEE_JOB_TYPE_CANCEL,
\r
97 FEE_JOB_TYPE_INVALIDATE,
\r
98 FEE_JOB_TYPE_ERASE_IMMEDIATE_BLOCK
\r
99 } CurrentJobTypeType;
\r
102 FEE_UNINITIALIZED = 0,
\r
104 FEE_WRITE_REQUESTED,
\r
105 FEE_WRITE_EREASE_PENDING,
\r
107 FEE_WRITE_HEADER_PENDING,
\r
108 FEE_READ_REQUESTED,
\r
109 FEE_READ_HEADER_PENDING,
\r
111 FEE_CANCEL_REQUESTED,
\r
112 FEE_CANCEL_PENDING,
\r
113 FEE_INVALIDATE_REQUESTED,
\r
114 FEE_INVALIDATE_PENDING,
\r
115 FEE_ERASE_IMMEDIATE_REQUESTED,
\r
116 FEE_ERASE_IMMEDIATE_PENDING
\r
117 } CurrentJobStateType;
\r
120 FEE_FLS_STATE_IDLE,
\r
121 FEE_FLS_STATE_PENDING,
\r
122 FEE_FLS_STATE_READY
\r
126 FlsStateType State;
\r
127 Std_ReturnType ErrorStatus;
\r
128 MemIf_JobResultType JobResult;
\r
131 static FlsAdminType FlsAdmin = {
\r
132 .State = FEE_FLS_STATE_IDLE,
\r
133 .ErrorStatus = E_OK,
\r
134 .JobResult = MEMIF_JOB_OK
\r
138 boolean Consistent;
\r
142 static BlockAdminType BlockAdminList[FEE_NUM_OF_BLOCKS];
\r
145 CurrentJobTypeType Type;
\r
146 CurrentJobStateType State;
\r
147 const Fee_BlockConfigType *BlockConfigPtr;
\r
148 BlockAdminType *BlockAdminPtr;
\r
151 uint32 FlsBlockAddr; // Flash source/Dest depending of operation
\r
152 uint8 *RamPtr; // RAM source/Dest depending of operation
\r
155 static CurrentJobType CurrentJob = {
\r
156 .Type = FEE_JOB_TYPE_NONE,
\r
160 #if (FEE_POLLING_MODE == STD_ON)
\r
161 void PollFlsJobResult(void)
\r
163 MemIf_JobResultType jobResult;
\r
165 if (FlsAdmin.State = FEE_FLS_STATE_PENDING) {
\r
166 jobResult = Fls_GetJobResult();
\r
168 if (jobResult == MEMIF_JOB_OK) {
\r
169 FlsAdmin.ErrorStatus = E_OK;
\r
170 FlsAdmin.JobResult = jobResult;
\r
171 FlsAdmin.State = FEE_FLS_STATE_READY;
\r
172 } else if (jobResult != MEMIF_JOB_PENDING) {
\r
173 FlsAdmin.ErrorStatus = E_NOT_OK;
\r
174 FlsAdmin.JobResult = jobResult;
\r
175 FlsAdmin.State = FEE_FLS_STATE_READY;
\r
180 #define PollFlsJobResult(...)
\r
182 void Fee_JobEndNotification(void)
\r
184 FlsAdmin.State = FEE_FLS_STATE_READY;
\r
185 FlsAdmin.ErrorStatus = E_OK;
\r
186 FlsAdmin.JobResult = Fls_GetJobResult();
\r
189 void Fee_JobErrorNotification(void)
\r
191 FlsAdmin.State = FEE_FLS_STATE_READY;
\r
192 FlsAdmin.ErrorStatus = E_NOT_OK;
\r
193 FlsAdmin.JobResult = Fls_GetJobResult();
\r
197 void FinnishJob(void)
\r
199 FlsAdmin.State = FEE_FLS_STATE_IDLE;
\r
200 CurrentJob.State = FEE_IDLE;
\r
202 ModuleStatus = MEMIF_IDLE;
\r
203 JobResult = FlsAdmin.JobResult;
\r
205 if (FlsAdmin.ErrorStatus == E_OK) {
\r
206 if (Fee_Config.General.NvmJobEndCallbackNotificationCallback != NULL) {
\r
207 Fee_Config.General.NvmJobEndCallbackNotificationCallback();
\r
210 if (Fee_Config.General.NvmJobErrorCallbackNotificationCallback != NULL) {
\r
211 Fee_Config.General.NvmJobErrorCallbackNotificationCallback();
\r
217 void Fee_Init(void)
\r
219 // Reporting information
\r
220 ModuleStatus = MEMIF_IDLE;
\r
221 JobResult = MEMIF_JOB_OK;
\r
224 CurrentJob.State = FEE_IDLE;
\r
225 FlsAdmin.State = FEE_FLS_STATE_IDLE;
\r
226 FlsAdmin.ErrorStatus = E_OK;
\r
227 FlsAdmin.JobResult = MEMIF_JOB_OK;
\r
231 void Fee_SetMode(MemIf_ModeType mode)
\r
233 #if ( FLS_SET_MODE_API == STD_ON )
\r
236 DET_REPORTERROR(MODULE_ID_FEE, 0, FEE_SET_MODE_ID, FEE_E_NOT_SUPPORTED);
\r
241 Std_ReturnType Fee_Read(uint16 blockNumber, uint16 blockOffset, uint8* dataBufferPtr, uint16 length)
\r
245 VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_READ_ID, FEE_E_UNINIT, E_NOT_OK);
\r
246 VALIDATE_RV(ModuleStatus == MEMIF_IDLE, FEE_READ_ID, FEE_E_BUSY, E_NOT_OK);
\r
248 VALIDATE_RV(blockNumber >= (1 << NVM_DATASET_SELECTION_BITS), FEE_READ_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);
\r
249 blockIndex = GET_BLOCK_INDEX_FROM_BLOCK_NUMBER(blockNumber);
\r
250 VALIDATE_RV(blockIndex < FEE_NUM_OF_BLOCKS, FEE_READ_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);
\r
251 VALIDATE_RV(dataBufferPtr != NULL, FEE_READ_ID, FEE_E_INVALID_DATA_PTR, E_NOT_OK);
\r
252 VALIDATE_RV(blockOffset < Fee_Config.BlockConfig[blockIndex].BlockSize, FEE_READ_ID, FEE_E_INVALID_BLOCK_OFS, E_NOT_OK);
\r
253 VALIDATE_RV(blockOffset + length <= Fee_Config.BlockConfig[blockIndex].BlockSize, FEE_READ_ID, FEE_E_INVALID_BLOCK_LEN, E_NOT_OK);
\r
257 ModuleStatus = MEMIF_BUSY;
\r
258 JobResult = MEMIF_JOB_PENDING;
\r
260 CurrentJob.Type = FEE_JOB_TYPE_READ;
\r
261 CurrentJob.BlockConfigPtr = &Fee_Config.BlockConfig[blockIndex];
\r
262 CurrentJob.BlockAdminPtr = &BlockAdminList[blockIndex];
\r
263 CurrentJob.Length = length;
\r
264 CurrentJob.Offset = blockOffset;
\r
265 CurrentJob.FlsBlockAddr = CurrentJob.BlockConfigPtr->PhysBaseAddress + GET_DATASET_FROM_BLOCK_NUMBER(blockNumber) * CurrentJob.BlockConfigPtr->BlockSize; /** @req FEE021 */
\r
266 CurrentJob.RamPtr = dataBufferPtr;
\r
267 CurrentJob.State = FEE_READ_REQUESTED;
\r
273 Std_ReturnType Fee_Write(uint16 blockNumber, uint8* dataBufferPtr)
\r
277 VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_WRITE_ID, FEE_E_UNINIT, E_NOT_OK);
\r
278 VALIDATE_RV(ModuleStatus == MEMIF_IDLE, FEE_WRITE_ID, FEE_E_BUSY, E_NOT_OK);
\r
280 VALIDATE_RV(blockNumber >= (1 << NVM_DATASET_SELECTION_BITS), FEE_WRITE_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);
\r
281 blockIndex = GET_BLOCK_INDEX_FROM_BLOCK_NUMBER(blockNumber);
\r
282 VALIDATE_RV(blockIndex < FEE_NUM_OF_BLOCKS, FEE_WRITE_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);
\r
283 VALIDATE_RV(dataBufferPtr != NULL, FEE_WRITE_ID, FEE_E_INVALID_DATA_PTR, E_NOT_OK);
\r
287 ModuleStatus = MEMIF_BUSY;
\r
288 JobResult = MEMIF_JOB_PENDING;
\r
290 CurrentJob.Type = FEE_JOB_TYPE_WRITE;
\r
291 CurrentJob.BlockConfigPtr = &Fee_Config.BlockConfig[blockIndex];
\r
292 CurrentJob.BlockAdminPtr = &BlockAdminList[blockIndex];
\r
293 CurrentJob.Length = CurrentJob.BlockConfigPtr->BlockSize;
\r
294 CurrentJob.FlsBlockAddr = CurrentJob.BlockConfigPtr->PhysBaseAddress + GET_DATASET_FROM_BLOCK_NUMBER(blockNumber) * CurrentJob.BlockConfigPtr->BlockSize; /** @req FEE024 */
\r
295 CurrentJob.RamPtr = dataBufferPtr;
\r
296 CurrentJob.State = FEE_WRITE_REQUESTED;
\r
302 void Fee_Cancel(void)
\r
308 MemIf_StatusType Fee_GetStatus(void)
\r
310 return ModuleStatus;
\r
314 MemIf_JobResultType Fee_GetJobResult(void)
\r
320 Std_ReturnType Fee_InvalidateBlock(uint16 blockNumber)
\r
324 VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_INVALIDATE_BLOCK_ID, FEE_E_UNINIT, E_NOT_OK);
\r
325 VALIDATE_RV(ModuleStatus == MEMIF_IDLE, FEE_INVALIDATE_BLOCK_ID, FEE_E_BUSY, E_NOT_OK);
\r
327 VALIDATE_RV(blockNumber >= (1 << NVM_DATASET_SELECTION_BITS), FEE_INVALIDATE_BLOCK_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);
\r
328 blockIndex = GET_BLOCK_INDEX_FROM_BLOCK_NUMBER(blockNumber);
\r
329 VALIDATE_RV(blockIndex < FEE_NUM_OF_BLOCKS, FEE_INVALIDATE_BLOCK_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);
\r
332 ModuleStatus = MEMIF_BUSY;
\r
333 JobResult = MEMIF_JOB_PENDING;
\r
335 CurrentJob.Type = FEE_JOB_TYPE_INVALIDATE;
\r
336 CurrentJob.BlockConfigPtr = &Fee_Config.BlockConfig[blockIndex];
\r
337 CurrentJob.BlockAdminPtr = &BlockAdminList[blockIndex];
\r
338 CurrentJob.Length = 0;
\r
339 CurrentJob.FlsBlockAddr = CurrentJob.BlockConfigPtr->PhysBaseAddress + GET_DATASET_FROM_BLOCK_NUMBER(blockNumber) * CurrentJob.BlockConfigPtr->BlockSize; /** @req FEE024 */
\r
340 CurrentJob.RamPtr = NULL;
\r
341 CurrentJob.State = FEE_INVALIDATE_REQUESTED;
\r
347 Std_ReturnType Fee_EraseImmediateBlock(uint16 blockNumber)
\r
349 VALIDATE_RV(blockNumber < FEE_NUM_OF_BLOCKS, FEE_ERASE_IMMEDIATE_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);
\r
350 VALIDATE_RV(Fee_Config.BlockConfig[blockNumber].ImmediateData, FEE_ERASE_IMMEDIATE_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);
\r
352 ModuleStatus = MEMIF_BUSY;
\r
353 JobResult = MEMIF_JOB_PENDING;
\r
354 CurrentJob.Type = FEE_JOB_TYPE_ERASE_IMMEDIATE_BLOCK;
\r
355 CurrentJob.State = FEE_ERASE_IMMEDIATE_REQUESTED;
\r
361 void ReadStartJob(void)
\r
363 if (FlsAdmin.State == FEE_FLS_STATE_IDLE) {
\r
364 FlsAdmin.State = FEE_FLS_STATE_PENDING;
\r
365 CurrentJob.State = FEE_READ_HEADER_PENDING;
\r
366 // Start by reading the header block
\r
367 if (Fls_Read(CurrentJob.FlsBlockAddr, (uint8*)&BlockHeader, BLOCK_HEADER_LEN) != E_OK) {
\r
368 FlsAdmin.State = FEE_FLS_STATE_READY;
\r
369 FlsAdmin.ErrorStatus = E_NOT_OK;
\r
370 FlsAdmin.JobResult = Fls_GetJobResult();
\r
375 void ReadCheckHeaderJob(void)
\r
377 if (FlsAdmin.ErrorStatus == E_OK) {
\r
378 if (memcmp(BlockHeader.Magic, MagicMaster, MAGIC_LEN) == 0) {
\r
379 if (BlockHeader.Valid) {
\r
380 if (FlsAdmin.State != FEE_FLS_STATE_PENDING) {
\r
381 FlsAdmin.State = FEE_FLS_STATE_PENDING;
\r
382 CurrentJob.State = FEE_READ_PENDING;
\r
383 // Read the actual data
\r
384 if (Fls_Read(CurrentJob.FlsBlockAddr + CurrentJob.Offset + BLOCK_HEADER_LEN, CurrentJob.RamPtr, CurrentJob.Length) != E_OK) {
\r
385 FlsAdmin.State = FEE_FLS_STATE_READY;
\r
386 FlsAdmin.ErrorStatus = E_NOT_OK;
\r
387 FlsAdmin.JobResult = Fls_GetJobResult();
\r
392 FlsAdmin.ErrorStatus = E_NOT_OK;
\r
393 FlsAdmin.JobResult = MEMIF_BLOCK_INVALID;
\r
397 FlsAdmin.ErrorStatus = E_NOT_OK;
\r
398 FlsAdmin.JobResult = MEMIF_BLOCK_INCONSISTENT;
\r
407 void WriteStartJob(void)
\r
409 if (FlsAdmin.State == FEE_FLS_STATE_IDLE) {
\r
410 FlsAdmin.State = FEE_FLS_STATE_PENDING;
\r
411 CurrentJob.State = FEE_WRITE_EREASE_PENDING;
\r
412 // Start by erasing the block
\r
413 if (Fls_Erase(CurrentJob.FlsBlockAddr, CurrentJob.Length + BLOCK_HEADER_LEN) != E_OK) {
\r
414 FlsAdmin.State = FEE_FLS_STATE_READY;
\r
415 FlsAdmin.ErrorStatus = E_NOT_OK;
\r
416 FlsAdmin.JobResult = Fls_GetJobResult();
\r
422 void WriteCheckEraseJob(void)
\r
424 if (FlsAdmin.ErrorStatus == E_OK) {
\r
425 if (FlsAdmin.State != FEE_FLS_STATE_PENDING) {
\r
426 FlsAdmin.State = FEE_FLS_STATE_PENDING;
\r
427 CurrentJob.State = FEE_WRITE_PENDING;
\r
428 // Write the actual data
\r
429 if (Fls_Write(CurrentJob.FlsBlockAddr + BLOCK_HEADER_LEN, CurrentJob.RamPtr, CurrentJob.Length) != E_OK) {
\r
430 FlsAdmin.State = FEE_FLS_STATE_READY;
\r
431 FlsAdmin.ErrorStatus = E_NOT_OK;
\r
432 FlsAdmin.JobResult = Fls_GetJobResult();
\r
442 void WriteCheckWriteJob(void)
\r
444 if (FlsAdmin.ErrorStatus == E_OK) {
\r
445 if (FlsAdmin.State != FEE_FLS_STATE_PENDING) {
\r
446 FlsAdmin.State = FEE_FLS_STATE_PENDING;
\r
447 CurrentJob.State = FEE_WRITE_HEADER_PENDING;
\r
448 // Write the block header (mark it as consistent and valid)
\r
449 if (Fls_Write(CurrentJob.FlsBlockAddr, (uint8*)&BlockHeaderMaster, BLOCK_HEADER_LEN) != E_OK) {
\r
450 FlsAdmin.State = FEE_FLS_STATE_READY;
\r
451 FlsAdmin.ErrorStatus = E_NOT_OK;
\r
452 FlsAdmin.JobResult = Fls_GetJobResult();
\r
462 void InvalidateStartJob(void)
\r
464 static const uint8 zero = 0;
\r
466 if (FlsAdmin.State == FEE_FLS_STATE_IDLE) {
\r
467 FlsAdmin.State = FEE_FLS_STATE_PENDING;
\r
468 CurrentJob.State = FEE_INVALIDATE_PENDING;
\r
469 // Write a zero to the Validate flag
\r
470 if (Fls_Write(CurrentJob.FlsBlockAddr + VALIDATE_POS, &zero, 1) != E_OK) {
\r
471 FlsAdmin.State = FEE_FLS_STATE_READY;
\r
472 FlsAdmin.ErrorStatus = E_NOT_OK;
\r
473 FlsAdmin.JobResult = Fls_GetJobResult();
\r
479 void Fee_MainFunction(void)
\r
481 switch (CurrentJob.State) {
\r
482 case FEE_UNINITIALIZED:
\r
486 case FEE_READ_REQUESTED:
\r
490 case FEE_READ_HEADER_PENDING:
\r
491 PollFlsJobResult();
\r
493 ReadCheckHeaderJob();
\r
497 case FEE_READ_PENDING:
\r
498 PollFlsJobResult();
\r
504 case FEE_WRITE_REQUESTED:
\r
508 case FEE_WRITE_EREASE_PENDING:
\r
509 PollFlsJobResult();
\r
511 WriteCheckEraseJob();
\r
515 case FEE_WRITE_PENDING:
\r
516 PollFlsJobResult();
\r
518 WriteCheckWriteJob();
\r
522 case FEE_WRITE_HEADER_PENDING:
\r
523 PollFlsJobResult();
\r
529 case FEE_INVALIDATE_REQUESTED:
\r
530 InvalidateStartJob();
\r
533 case FEE_INVALIDATE_PENDING:
\r
534 PollFlsJobResult();
\r