본문 바로가기
mobilgene/NvM

[NvM] NvM 주요 API 완전 정리 (Read / Write / GetErrorStatus 동작 방식)

by Autosar 2026. 4. 24.
반응형

NvM을 처음 접하면 가장 먼저 드는 착각이 있다.

“ReadBlock 하면 바로 읽히고, WriteBlock 하면 바로 저장된다”

 

하지만 실제 구조는 전혀 다르다.

 

NvM은 즉시 실행 함수 집합이 아니라,

요청을 받아서 내부 Job Queue에 적재하고, 주기적으로 처리하는 비동기 시스템이다.

 

즉 API를 호출하는 순간 실제 동작이 끝나는 것이 아니라, “해야 할 작업을 등록하는 것”에 가깝다.

 

그래서 NvM을 제대로 이해하려면 API 자체보다

“이 API가 내부에서 어떤 흐름으로 처리되는가”를 봐야 한다.

 

1. NvM_ReadBlock 동작 방식

 

NvM_ReadBlock은 NV 메모리에 저장된 데이터를 RAM으로 가져오는 역할을 한다.

하지만 여기서 중요한 점은, 이 함수는 데이터를 즉시 가져오는 함수가 아니라는 것이다.

 

ReadBlock이 호출되면 NvM은 해당 요청을 하나의 Job으로 만들어 내부 Queue에 넣는다.

이후 NvM_MainFunction이 주기적으로 실행되면서 이 Job을 하나씩 처리하고,

실제로 EEPROM이나 Flash에서 데이터를 읽어 RAM에 복사한다.

 

이 과정이 끝난 뒤에야 애플리케이션이 원하는 데이터가 RAM에 반영된다.

 

즉, ReadBlock은 “데이터를 읽어달라”는 요청이고, 실제 데이터 반영은 이후 비동기적으로 수행된다.

/* NvM_ReadBlock API Prototype Declarations */
extern FUNC(Std_ReturnType, NVM_CODE)NvM_ReadBlock
(
    VAR(NvM_BlockIdType, AUTOMATIC) BlockId, P2VAR(void, AUTOMATIC, NVM_APPL_DATA) NvM_DstPtr
);

 

실제 동작 흐름

NvM_ReadBlock 호출 → Read Job 생성 → Queue 저장
→ NvM_MainFunction 실행 → Fee/Ea Read 수행 → RAM Buffer 업데이트

 

핵심은 Read 호출 직후 NvM_RamBuffer 값이 바로 바뀌지 않는다는 점이다. MainFunction 이후에 반영된다.

 

2. NvM_WriteBlock 동작 방식

 

NvM_WriteBlock은 RAM에 있는 데이터를 NV 영역으로 저장하는 역할을 한다.

 

여기서도 중요한 포인트는 동일하다.

WriteBlock은 즉시 저장이 아니라 “저장 요청”이다.

 

호출이 발생하면 NvM은 현재 RAM 데이터를 기준으로 Write Job을 생성하고 Queue에 적재한다.

이후 MainFunction이 해당 Job을 처리하면서 실제로 Fee 또는 Ea를 통해 Flash 또는 EEPROM에 데이터를 기록한다.

 

그래서 WriteBlock 직후 전원을 차단(OFF)하면 데이터가 저장되지 않았을 가능성도 존재한다.

아직 Job이 처리되지 않았을 수 있기 때문이다.

 

결국 NvM Write는 “즉시 저장”이 아니라 “스케줄 기반 저장”이다.

/* NvM_WriteBlock API Prototype Declarations */
extern FUNC(Std_ReturnType, NVM_CODE)NvM_WriteBlock
(
    VAR(NvM_BlockIdType, AUTOMATIC) BlockId, P2CONST(void, AUTOMATIC, NVM_APPL_DATA) NvM_SrcPtr
);

 

실제 동작 흐름

NvM_WriteBlock 호출 →  Write Job 생성 → Queue 저장
→ NvM_MainFunction 실행 → Fee/Ea Write 수행 → NV 영역 저장 완료

 

3. NvM_RestoreBlockDefaults 의미

 

RestoreBlockDefaults는 NV 영역 데이터가 유효하지 않을 때 기본값으로 복구하는 기능이다.

 

예를 들어 CRC 오류가 발생하거나 데이터가 손상된 경우 NvM은 정상 데이터 대신 ROM에 정의된 기본값을 RAM으로 복사한다.

 

이 기능은 단순히 값을 초기화하는 것이 아니라,

“시스템이 정상 상태로 복구되도록 만드는 안전 장치” 역할을 한다.

/* NvM_RestoreBlockDefaults API Prototype Declarations */
extern FUNC(Std_ReturnType, NVM_CODE) NvM_RestoreBlockDefaults
(
    VAR(NvM_BlockIdType, AUTOMATIC) BlockId, P2VAR(void, AUTOMATIC, NVM_APPL_DATA) NvM_DestPtr
);

 

4. NvM_SetRamBlockStatus 의미

 

이 API는 NvM 구조에서 매우 중요하지만 자주 놓치는 부분이다.

이 함수는 “RAM 데이터가 변경되었는지 여부를 NvM에 알려주는 역할”을 한다.

 

NvM은 내부적으로 WriteBlock 요청이 들어왔을 때, “이 블록이 실제로 변경되었는가?”를 판단한다.

이때 기준이 되는 것이 SetRamBlockStatus이다.

 

즉 이 API를 호출하지 않으면 NvM 입장에서는

“변경된 데이터가 없다”고 판단하여 Write 작업이 수행되지 않을 수 있다.

/* NvM_SetRamBlockStatus API Prototype Declarations */
extern FUNC(Std_ReturnType, NVM_CODE)NvM_SetRamBlockStatus
(
    VAR(NvM_BlockIdType, AUTOMATIC) BlockId, VAR(boolean, AUTOMATIC) BlockChanged
);

 

5. NvM_MainFunction의 핵심 역할

 

NvM은 이벤트 기반이 아니라 주기 실행 기반 시스템이며, NvM_MainFunction은 NvM 시스템의 실제 실행 엔진이다.

 

앞에서 설명한 Read, Write, Restore 모든 요청은 즉시 처리되지 않고 Queue에 쌓인다.

이 Queue를 실제로 하나씩 꺼내서 처리하는 것이 MainFunction이다.

 

동작 흐름은 다음과 같다.

1. Queue에서 Job 하나를 가져온다.
2. Job 종류(Read / Write / Restore)를 확인한다.
3. 해당 작업을 Lower Layer(Fee/Ea)에 전달한다.
4. 결과를 저장하고 상태를 업데이트한다.
5. 필요하면 Callback을 호출한다.

 

즉 NvM_MainFunction이 없으면 NvM은 아무 작업도 진행되지 않는다.

FUNC(void, NVM_CODE) NvM_MainFunction(void);

 

6. NvM_GetErrorStatus 동작 구조 (상태 확인 핵심 API)

 

NvM_GetErrorStatus는 NvM 블록의 마지막 요청 결과 상태를 확인하는 API이다.

 

NvM_GetErrorStatus는 NvM에서 수행된 Read / Write / Restore 작업의 결과 상태를 확인하는 API이다.

즉, “요청이 실제로 성공했는지”를 확인하는 용도로 사용된다.

 

NvM은 비동기 구조이기 때문에 API 호출 시점에는 작업이 끝나지 않은 경우가 많다.

그래서 단순히 WriteBlock이나 ReadBlock만 호출해서는 결과를 신뢰할 수 없고, 반드시 상태 확인이 필요하다.

/* NvM_GetErrorStatus API Prototype Declarations */
extern FUNC(Std_ReturnType, NVM_CODE)NvM_GetErrorStatus
(
    VAR(NvM_BlockIdType, AUTOMATIC) BlockId,
    P2VAR(NvM_RequestResultType,
    AUTOMATIC, NVM_APPL_DATA) RequestResultPtr
);

 

6.1 주요 상태 값 정의

#define NVM_REQ_OK                	0U
#define NVM_REQ_NOT_OK           	1U
#define NVM_REQ_PENDING           	2U
#define NVM_REQ_INTEGRITY_FAILED  	3U
#define NVM_REQ_BLOCK_SKIPPED     	4U
#define NVM_REQ_NV_INVALIDATED    	5U
#define NVM_REQ_CANCELED          	6U
#define NVM_REQ_REDUNDANCY_FAILED 	7U
#define NVM_REQ_RESTORED_FROM_ROM 	8U

 

6.2 상태 값 해석 (실무 기준)

NVM_REQ_OK (0U): 정상적으로 Job이 완료된 상태이다.

NVM_REQ_NOT_OK (1U): Job 수행 중 오류가 발생한 경우이다.

NVM_REQ_PENDING (2U): 아직 Job이 처리 중인 상태이다.

NVM_REQ_INTEGRITY_FAILED (3U): 데이터 무결성 오류 발생

NVM_REQ_BLOCK_SKIPPED (4U): 해당 Block이 처리 대상에서 제외된 경우이다.

NVM_REQ_NV_INVALIDATED (5U): NV 데이터가 무효화된 상태이다.

NVM_REQ_CANCELED (6U): Job이 중간에 취소된 상태이다.

NVM_REQ_REDUNDANCY_FAILED (7U): Redundant Block 구조에서 두 데이터 모두 실패한 경우이다.

NVM_REQ_RESTORED_FROM_ROM (8U): NV 데이터 대신 ROM 기본값으로 복구된 상태이다.

 

6.3 동작 관점에서의 의미

NvM_GetErrorStatus는 단순 상태 조회 함수가 아니라

“NvM 내부 Job 상태 머신의 결과를 외부로 노출하는 인터페이스”이다.

동작 흐름으로 보면 다음과 같다.

NvM_WriteBlock / NvM_ReadBlock 호출 → Job Queue 적재
→ NvM_MainFunction 처리 → Lower Layer(Fee/Ea) 실행 → 결과 상태 저장 → NvM_GetErrorStatus로 조회

 

정리

 

NvM API는 각각 독립된 기능처럼 보이지만 실제로는 하나의 구조 안에서 동작한다.

API는 단순 실행 함수가 아니라 Job을 생성하고 Queue에 등록하는 “요청 인터페이스”이며,

실제 동작은 즉시 수행되지 않는다.

 

Queue는 이러한 Job들이 대기하는 구조이며,

NvM_MainFunction은 Queue에 쌓인 Job을 하나씩 처리하는 실행 엔진 역할을 한다.

 

이 과정에서 NvM은 MemIf를 통해 Fee 또는 Ea와 같은 하위 메모리 추상화 계층을 호출하고,

최종적으로 Flash 또는 EEPROM과 같은 실제 하드웨어에 접근한다.

 

즉, NvM은 단순 함수 호출 기반 구조가 아니라 Queue 기반 Job 처리 상태 머신 구조이다.

 

NvM을 이해할 때 가장 중요한 관점은 API 자체가 아니라 “전체 동작 흐름”이다.

 

각 API는 개별적으로 보면 단순하지만,

실제 시스템에서는 Queue, Job, MainFunction이 결합되어 비동기적으로 동작한다.

이 구조를 이해하면 Write가 수행되지 않는 문제나 Read 지연과 같은 현상도 자연스럽게 해석할 수 있다.

반응형