304 lines
11 KiB
C
304 lines
11 KiB
C
|
/*
|
||
|
* Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
|
||
|
* All rights reserved.
|
||
|
*
|
||
|
* Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
|
||
|
* exclusively with CVA's microcontroller products. This file can be freely
|
||
|
* distributed within development tools that are supporting such microcontroller
|
||
|
* products.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
|
||
|
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
|
||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
|
||
|
* CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
|
||
|
* OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
|
||
|
*/
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* the includes
|
||
|
******************************************************************************/
|
||
|
|
||
|
#include <stdint.h>
|
||
|
#include <stdbool.h>
|
||
|
#include <stddef.h>
|
||
|
#include "nvm_extra.h"
|
||
|
#include "nvm_block.h"
|
||
|
#include "nvm_queue.h"
|
||
|
#include "nvm.h"
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* the defines
|
||
|
******************************************************************************/
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* the typedefs
|
||
|
******************************************************************************/
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* the globals
|
||
|
******************************************************************************/
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* the functions
|
||
|
******************************************************************************/
|
||
|
void Nvm_Configure(const NvmType *obj)
|
||
|
{
|
||
|
/* Initialize job queue. */
|
||
|
Nvm_Queue_Init(obj->runtime->queue);
|
||
|
|
||
|
/* Initialize mainfunction state machine. */
|
||
|
obj->runtime->state = NVM_STATE_IDLE;
|
||
|
obj->runtime->nextState = FEE_STATE_INVALID;
|
||
|
}
|
||
|
|
||
|
void Nvm_MainFunction(const NvmType *obj)
|
||
|
{
|
||
|
/* Check if the state is illegal and if the state function is a null pointer. */
|
||
|
if((FEE_STATE_INVALID > obj->runtime->state) && (NULL != obj->stateMachine[obj->runtime->state].fn))
|
||
|
{
|
||
|
obj->stateMachine[obj->runtime->state].fn(obj);
|
||
|
}
|
||
|
|
||
|
/* Check if the jump state is illegal and determine if there is a state that needs to be jumped. */
|
||
|
if((FEE_STATE_INVALID > obj->runtime->nextState))
|
||
|
{
|
||
|
/* Jump Status Management. */
|
||
|
obj->runtime->state = obj->runtime->nextState;
|
||
|
obj->runtime->nextState = FEE_STATE_INVALID;
|
||
|
/* Check if there are entry functions for executing jump states. */
|
||
|
if(NULL != obj->stateMachine[obj->runtime->state].onEntry)
|
||
|
{
|
||
|
/* Entry function for executing jump state. */
|
||
|
obj->stateMachine[obj->runtime->state].onEntry(obj);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Nvm_ReturnType Nvm_Read(const NvmType *obj, uint16_t blockNumber, uint8_t *dataBuffer)
|
||
|
{
|
||
|
Nvm_ReturnType ret = NVM_RETURN_NOT_OK;
|
||
|
uint16_t blockIdx;
|
||
|
Nvm_QueueMemberType member;
|
||
|
uint8_t priority;
|
||
|
uint16_t blockBaseNumber;
|
||
|
uint16_t blockEcuNumber;
|
||
|
|
||
|
/* Check if mainfunction can respond to read job. */
|
||
|
if(NVM_STATE_UNINIT != obj->runtime->state)
|
||
|
{
|
||
|
/* Data required to initialize read job. */
|
||
|
blockBaseNumber = NVM_GET_BLOCKNUMBER(blockNumber);
|
||
|
blockEcuNumber = NVM_GET_BLOCKDATASETNUMBER(blockNumber);
|
||
|
blockIdx = Nvm_Block_Search(obj->blockTable, blockBaseNumber);
|
||
|
priority = NVM_BLOCK_GET_PRIORITY(obj->blockTable, blockIdx);
|
||
|
|
||
|
/* Check if the block is an undefined block. */
|
||
|
if(NVM_BLOCK_INVALID_IDX != blockIdx)
|
||
|
{
|
||
|
/* Initialize read job as a member of the user job queue. */
|
||
|
Nvm_Queue_InitMember(&member, blockIdx, blockEcuNumber, NVM_STATE_READ, priority, dataBuffer);
|
||
|
|
||
|
/* Check if the user job queue is full. */
|
||
|
if(NVM_RETURN_NOT_OK == Nvm_Queue_CheckFull(obj->runtime->queue))
|
||
|
{
|
||
|
/* Insert read job members into the user job queue based on priority. */
|
||
|
Nvm_Queue_Insert(obj->runtime->queue, &member);
|
||
|
ret = NVM_RETURN_OK;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
Nvm_ReturnType Nvm_ReadAll(const NvmType *obj)
|
||
|
{
|
||
|
Nvm_ReturnType ret = NVM_RETURN_NOT_OK;
|
||
|
Nvm_QueueMemberType member;
|
||
|
|
||
|
/* Check if mainfunction can respond to readAll job. */
|
||
|
if(NVM_STATE_UNINIT != obj->runtime->state)
|
||
|
{
|
||
|
/* Initialize readAll job as a member of the system job queue. */
|
||
|
NVM_QUEUE_SYSMEMBER(&member, NVM_STATE_READALL);
|
||
|
|
||
|
/* Check if the system job queue is full */
|
||
|
if(NVM_RETURN_NOT_OK == Nvm_Queue_CheckFull(obj->runtime->queue))
|
||
|
{
|
||
|
/* Insert readAll job members into the system job queue based on priority. */
|
||
|
Nvm_Queue_Insert(obj->runtime->queue, &member);
|
||
|
ret = NVM_RETURN_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
Nvm_ReturnType Nvm_Write(const NvmType *obj, uint16_t blockNumber, uint8_t *dataBuffer)
|
||
|
{
|
||
|
Nvm_ReturnType ret = NVM_RETURN_NOT_OK;
|
||
|
Nvm_QueueMemberType member;
|
||
|
uint8_t priority;
|
||
|
uint16_t blockIdx;
|
||
|
uint16_t blockBaseNumber;
|
||
|
uint16_t blockEcuNumber;
|
||
|
|
||
|
/* Check if mainfunction can respond to write job. */
|
||
|
if(NVM_STATE_UNINIT != obj->runtime->state)
|
||
|
{
|
||
|
/* Data required to initialize write job. */
|
||
|
blockBaseNumber = NVM_GET_BLOCKNUMBER(blockNumber);
|
||
|
blockEcuNumber = NVM_GET_BLOCKDATASETNUMBER(blockNumber);
|
||
|
blockIdx = Nvm_Block_Search(obj->blockTable, blockBaseNumber);
|
||
|
priority = NVM_BLOCK_GET_PRIORITY(obj->blockTable, blockIdx);
|
||
|
|
||
|
/* Check if the block is an undefined block. */
|
||
|
if(NVM_BLOCK_INVALID_IDX != blockIdx)
|
||
|
{
|
||
|
/* Initialize write job as a member of the user job queue. */
|
||
|
Nvm_Queue_InitMember(&member, blockIdx, blockEcuNumber, NVM_STATE_WRITE, priority, dataBuffer);
|
||
|
|
||
|
/* Check if the user job queue is full. */
|
||
|
if(NVM_RETURN_NOT_OK == Nvm_Queue_CheckFull(obj->runtime->queue))
|
||
|
{
|
||
|
/* Insert write job members into the user job queue based on priority. */
|
||
|
Nvm_Queue_Insert(obj->runtime->queue, &member);
|
||
|
ret = NVM_RETURN_OK;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
Nvm_ReturnType Nvm_WriteAll(const NvmType *obj)
|
||
|
{
|
||
|
Nvm_ReturnType ret = NVM_RETURN_NOT_OK;
|
||
|
Nvm_QueueMemberType member;
|
||
|
|
||
|
/* Check if mainfunction can respond to writeAll job. */
|
||
|
if(NVM_STATE_UNINIT != obj->runtime->state)
|
||
|
{
|
||
|
/* Initialize writeAll job as a member of the system job queue. */
|
||
|
NVM_QUEUE_SYSMEMBER(&member, NVM_STATE_WRITEALL);
|
||
|
|
||
|
/* Check if the system job queue is full. */
|
||
|
if(NVM_RETURN_NOT_OK == Nvm_Queue_CheckFull(obj->runtime->queue))
|
||
|
{
|
||
|
/* Insert writeAll job members into the system job queue based on priority. */
|
||
|
Nvm_Queue_Insert(obj->runtime->queue, &member);
|
||
|
ret = NVM_RETURN_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
Nvm_ReturnType Nvm_Erase(const NvmType *obj, uint16_t blockNumber)
|
||
|
{
|
||
|
Nvm_ReturnType ret = NVM_RETURN_NOT_OK;
|
||
|
Nvm_QueueMemberType member;
|
||
|
uint8_t priority;
|
||
|
uint16_t blockIdx;
|
||
|
uint16_t blockBaseNumber;
|
||
|
uint16_t blockEcuNumber;
|
||
|
uint8_t *dataBuffer;
|
||
|
|
||
|
/* Check if mainfunction can respond to erase job. */
|
||
|
if(NVM_STATE_UNINIT != obj->runtime->state)
|
||
|
{
|
||
|
/* Initialize the data required for erase job. */
|
||
|
blockBaseNumber = NVM_GET_BLOCKNUMBER(blockNumber);
|
||
|
blockEcuNumber = NVM_GET_BLOCKDATASETNUMBER(blockNumber);
|
||
|
blockIdx = Nvm_Block_Search(obj->blockTable, blockBaseNumber);
|
||
|
priority = NVM_BLOCK_GET_PRIORITY(obj->blockTable, blockIdx);
|
||
|
dataBuffer = NVM_BLOCK_GET_ROM_BUFF_PTR(obj->blockTable, blockIdx, blockEcuNumber);
|
||
|
|
||
|
/* Check if the block is an undefined block. */
|
||
|
if(NVM_BLOCK_INVALID_IDX != blockIdx)
|
||
|
{
|
||
|
/* Initialize write job as a member of the user job queue. */
|
||
|
Nvm_Queue_InitMember(&member, blockIdx, blockEcuNumber, NVM_STATE_ERASE, priority, dataBuffer);
|
||
|
|
||
|
/* Check if the user job queue is full. */
|
||
|
if(NVM_RETURN_NOT_OK == Nvm_Queue_CheckFull(obj->runtime->queue))
|
||
|
{
|
||
|
/* Insert write job members into the user job queue based on priority. */
|
||
|
Nvm_Queue_Insert(obj->runtime->queue, &member);
|
||
|
ret = NVM_RETURN_OK;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
Nvm_ReturnType Nvm_EraseAll(const NvmType *obj)
|
||
|
{
|
||
|
Nvm_ReturnType ret = NVM_RETURN_NOT_OK;
|
||
|
Nvm_QueueMemberType member;
|
||
|
|
||
|
/* Check if mainfunction can respond to writeAll job. */
|
||
|
if(NVM_STATE_UNINIT != obj->runtime->state)
|
||
|
{
|
||
|
/* Initialize writeAll job as a member of the system job queue. */
|
||
|
NVM_QUEUE_SYSMEMBER(&member, NVM_STATE_ERASEALL);
|
||
|
|
||
|
/* Check if the system job queue is full. */
|
||
|
if(NVM_RETURN_NOT_OK == Nvm_Queue_CheckFull(obj->runtime->queue))
|
||
|
{
|
||
|
/* Insert writeAll job members into the system job queue based on priority. */
|
||
|
Nvm_Queue_Insert(obj->runtime->queue, &member);
|
||
|
ret = NVM_RETURN_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void Nvm_CancelJob(const NvmType *obj)
|
||
|
{
|
||
|
/* Remove unresponsive jobs from the user queue. */
|
||
|
Nvm_Queue_RemoveLastItem(obj->runtime->queue);
|
||
|
}
|
||
|
|
||
|
Nvm_stateType Nvm_GetStatus(const NvmType *obj)
|
||
|
{
|
||
|
/* Obtain the internal state of NVM. */
|
||
|
return obj->runtime->state;
|
||
|
}
|
||
|
|
||
|
Nvm_BlockState Nvm_GetBlockStatus(const NvmType *obj, uint16_t blockNumber)
|
||
|
{
|
||
|
Nvm_BlockState ret = NVM_REQ_ERROR;
|
||
|
uint16_t blockBaseNumber;
|
||
|
uint16_t blockDatasetNumber;
|
||
|
uint16_t blockIdx;
|
||
|
|
||
|
blockBaseNumber = NVM_GET_BLOCKNUMBER(blockNumber);
|
||
|
blockDatasetNumber = NVM_GET_BLOCKDATASETNUMBER(blockNumber);
|
||
|
|
||
|
/* Find the index of the block. */
|
||
|
blockIdx = Nvm_Block_Search(obj->blockTable, blockBaseNumber);
|
||
|
|
||
|
/* Check if the block is an undefined block. */
|
||
|
if(NVM_BLOCK_INVALID_IDX != blockIdx)
|
||
|
{
|
||
|
/* Obtain the status of the block. */
|
||
|
ret = NVM_BLOCK_GET_STATE(obj->blockTable, blockIdx, blockDatasetNumber);
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void Nvm_GetVersionInfo(Nvm_VersionInfoType *versionInfoPtr)
|
||
|
{
|
||
|
/* Check if it is a null pointer. */
|
||
|
if(NULL != versionInfoPtr)
|
||
|
{
|
||
|
versionInfoPtr->sw_major_version = NVM_SW_MAJOR_VERSION;
|
||
|
versionInfoPtr->sw_minor_version = NVM_SW_MINOR_VERSION;
|
||
|
versionInfoPtr->sw_patch_version = NVM_SW_PATCH_VERSION;
|
||
|
}
|
||
|
}
|