bootloader流程OK

This commit is contained in:
sunbeam 2024-05-13 08:14:17 +08:00
parent 1c0d34995d
commit acac69d9a8
292 changed files with 218864 additions and 123 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
Debug
Debug_FLASH

View File

@ -9,7 +9,7 @@ btnFresh={cls="button";text="刷新";left=204;top=28;right=288;bottom=54;z=2};
btnOpen={cls="button";text="打开文件";left=37;top=282;right=136;bottom=310;z=8};
btnOpenFlashdrv={cls="button";text="打开FlashDriver";left=149;top=282;right=248;bottom=310;z=24};
btnReadF186={cls="button";text="读取当前会话";left=37;top=349;right=136;bottom=377;z=13};
btnReadF198={cls="button";text="读取F198";left=37;top=415;right=136;bottom=443;z=19};
btnReadF191={cls="button";text="读取F191";left=37;top=415;right=136;bottom=443;z=19};
btnReadF199={cls="button";text="读取F199";left=149;top=415;right=248;bottom=443;z=20};
btnReadHw={cls="button";text="读取硬件版本号";left=149;top=381;right=248;bottom=409;z=12};
btnReadSw={cls="button";text="读取软件版本号";left=37;top=382;right=136;bottom=410;z=10};
@ -226,8 +226,8 @@ mainForm.onClose = function(hwnd,message,wParam,lParam){
//console.pause()
}
mainForm.btnReadF198.oncommand = function(id,event){
DiagReadDID(0x1701);
mainForm.btnReadF191.oncommand = function(id,event){
DiagReadDID(0xF191);
}
mainForm.btnReadF199.oncommand = function(id,event){
@ -256,6 +256,9 @@ mainForm.onClose = function(hwnd,message,wParam,lParam){
}
mainForm.button.oncommand = function(id,event){
DiagReadDID(0xF191);
}
mainForm.show();
return win.loopMessage();

View File

@ -25,15 +25,19 @@ FuncDiag22Pro = function(data){
}
case 0xF193 {
FuncDisplay("硬件版本号");
FuncDisplay(string.pack(table.slice(data,3)));
FuncDisplay(string.str(string.pack(table.slice(data,3))));
}
case 0xF195 {
FuncDisplay("软件版本号");
FuncDisplay(string.pack(table.slice(data,3)));
FuncDisplay(string.str(string.pack(table.slice(data,3))));
}
case 0xF191 {
FuncDisplay("编译时间");
FuncDisplay(string.str(string.pack(table.slice(data,3))));
}
case 0xF198 {
FuncDisplay("repair_shopcode");
FuncDisplay(string.pack(table.slice(data,3)));
FuncDisplay(string.str(string.pack(table.slice(data,3))));
}
case 0xF199 {
FuncDisplay("installation_date");

View File

@ -218,7 +218,7 @@ FuncBootSeq = function(){
FuncClearState();
}
else {
var ret = FuncWait(0x22);
//var ret = FuncWait(0x22);
nextstate(0);
}
}
@ -228,7 +228,7 @@ FuncBootSeq = function(){
FuncClearState();
}
else {
var ret = FuncWait(0x22);
//var ret = FuncWait(0x22);
nextstate(0);
}
}
@ -273,6 +273,19 @@ FuncBootSeq = function(){
}
}
case 7 {
if(sendstate == 0){//等待复位完成
delaycount = 0;
FuncClearState();
}
else {
delaycount += 1;
if(delaycount > 20){
nextstate(0);//延时1S
}
}
}
case 8 {
if(sendstate == 0){
FuncReq27(0x09);//解密
FuncClearState();
@ -282,7 +295,7 @@ FuncBootSeq = function(){
nextstate(ret);
}
}
case 8 {
case 9 {
if(sendstate == 0){
//FuncReq27(02);//发送key
FuncClearState();
@ -294,7 +307,7 @@ FuncBootSeq = function(){
nextstate(ret);
}
}
case 9 {
case 10 {
if(sendstate == 0){
FuncReq31EraseFlash(0x1FFFF000,0x1000);
FuncClearState();
@ -306,7 +319,7 @@ FuncBootSeq = function(){
}
}
case 10 {
case 11 {
if(sendstate == 0){//写入installation_date
FuncReq3103(0xFD01);
FuncClearState();
@ -316,7 +329,7 @@ FuncBootSeq = function(){
nextstate(ret);
}
}
case 11 {
case 12 {
if(sendstate == 0){//发送数据
FuncSendBlockInit(1);
FuncDisplay("开始发送FlashDrv数据");
@ -327,7 +340,7 @@ FuncBootSeq = function(){
nextstate(ret);
}
}
case 12 {
case 13 {
if(sendstate == 0){//CheckLogicBlock
//var crc = FuncGetFlashCRC(0);
//FuncReq31CheckLogicBlock(crc);
@ -339,8 +352,8 @@ FuncBootSeq = function(){
nextstate(ret);
}
}
case 13 {
if(sendstate == 0){//写入installation_date
case 14 {
if(sendstate == 0){//
FuncReq3103(0xFD02);
FuncClearState();
}
@ -349,7 +362,7 @@ FuncBootSeq = function(){
nextstate(ret);
}
}
case 14 {
case 15 {
if(sendstate == 0){//CheckLogicBlock
FuncReq31EraseFlash(0x00010000,0x70000);
FuncClearState();
@ -360,7 +373,7 @@ FuncBootSeq = function(){
}
}
case 15 {
case 16 {
if(sendstate == 0){//发送数据
FuncSendBlockInit(2);
FuncDisplay("开始发送App数据");
@ -371,7 +384,7 @@ FuncBootSeq = function(){
nextstate(ret);
}
}
case 16 {
case 17 {
if(sendstate == 0){//CheckLogicBlock
FuncReq3101FD03();
FuncClearState();
@ -381,7 +394,7 @@ FuncBootSeq = function(){
nextstate(ret);
}
}
case 17 {
case 18 {
if(sendstate == 0){////Programming Dependencies
FuncReq3103(0xFD03);
FuncClearState();
@ -391,7 +404,7 @@ FuncBootSeq = function(){
nextstate(ret);
}
}
case 18 {
case 19 {
if(sendstate == 0){//复位
FuncClearState();
FuncReq11(0x03);
@ -402,7 +415,7 @@ FuncBootSeq = function(){
}
}
case 19 {
case 20 {
if(sendstate == 0){//等待复位完成
delaycount = 0;
FuncClearState();
@ -416,7 +429,7 @@ FuncBootSeq = function(){
}
}
case 20 {
case 21 {
if(sendstate == 0){
FuncReq10(true,0x03);//进入扩展会话
FuncClearState();
@ -426,7 +439,7 @@ FuncBootSeq = function(){
nextstate(ret);
}
}
case 21 {
case 22 {
if(sendstate == 0){
FuncReq28(0x00,0x01);//开启发送
FuncClearState();
@ -436,7 +449,7 @@ FuncBootSeq = function(){
nextstate(ret);
}
}
case 22 {
case 23 {
if(sendstate == 0){
FuncReq85(0x01);//开启DTC
FuncClearState();
@ -446,7 +459,7 @@ FuncBootSeq = function(){
nextstate(ret);
}
}
case 23 {
case 24 {
if(sendstate == 0){
FuncReq10(true,0x01);//进入默认会话
FuncClearState();

View File

@ -150,33 +150,34 @@ FuncOpenS19File = function(id,path){
}
s19crc = null;
FuncDisplay(string.format("addr=%x ,len = %x",block.address,#block.data))//显示
if(block.address == 0x10000 && #block.data==0xf0000){
if(block.address == 0x10000){
var last_data_addr = 0;
for(i=1;0x90840-5;1){
if(block.data[0x90840-5-i] != 0xff){
last_data_addr = 0x90840-5-i + 0x10000;
var temp = last_data_addr%2048;
if(temp != 0){
last_data_addr += 2048-temp;
}
s19crc = {};
s19crc["address"] = 0x7F800;
s19crc["data"] = table.slice(block.data,-0x800,);
s19crc.data[0x7FC] = last_data_addr>>24;
s19crc.data[0x7FB] = last_data_addr>>16;
s19crc.data[0x7FA] = last_data_addr>>8;
s19crc.data[0x7F9] = last_data_addr&0XFF;
block.data = table.slice(block.data,,last_data_addr-0x10000);
//FuncDisplay(string.format("addr=%x ,Data = %x",last_data_addr,block.data[last_data_addr-0x10000]))//显示
var crc32temp = FuncCRC32Calc(block.data);
s19crc.data[0x800] = crc32temp>>24;
s19crc.data[0x7FF] = crc32temp>>16;
s19crc.data[0x7FE] = crc32temp>>8;
s19crc.data[0x7FD] = crc32temp&0XFF;
break;
}
last_data_addr = #block.data;
var temp = last_data_addr%2048;
if(temp != 0){
last_data_addr += 2048-temp;
}
for(i=#block.data+1;last_data_addr;1){
block.data[i] = 0xff;
}
s19crc = {};
s19crc["address"] = 0x7F800;
s19crc["data"] = {};
for(i=1;0x800;1){
s19crc.data[i] = 0xff;
}
last_data_addr+=0x10000;
s19crc.data[0x7FC] = last_data_addr>>24;
s19crc.data[0x7FB] = last_data_addr>>16;
s19crc.data[0x7FA] = last_data_addr>>8;
s19crc.data[0x7F9] = last_data_addr&0XFF;
var crc32temp = FuncCRC32Calc(block.data);
s19crc.data[0x800] = crc32temp>>24;
s19crc.data[0x7FF] = crc32temp>>16;
s19crc.data[0x7FE] = crc32temp>>8;
s19crc.data[0x7FD] = crc32temp&0XFF;
}
if(block != null){
table.push(FlashData,block)

6
cva_asw_m0146/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,6 @@
{
"files.associations": {
"mcu.h": "c",
"segger_rtt.h": "c"
}
}

View File

@ -0,0 +1,146 @@
/*
* 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.
*/
#ifndef _CRC_H_
#define _CRC_H_
/*! \brief Contains public interface to various functions related
* to the CRC algorithms
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*! \brief The CRC table
*/
static const uint16_t c_crcTable[] =
{
0X0000, 0XC0C1, 0XC181, 0X0140, 0XC301, 0X03C0, 0X0280, 0XC241,
0XC601, 0X06C0, 0X0780, 0XC741, 0X0500, 0XC5C1, 0XC481, 0X0440,
0XCC01, 0X0CC0, 0X0D80, 0XCD41, 0X0F00, 0XCFC1, 0XCE81, 0X0E40,
0X0A00, 0XCAC1, 0XCB81, 0X0B40, 0XC901, 0X09C0, 0X0880, 0XC841,
0XD801, 0X18C0, 0X1980, 0XD941, 0X1B00, 0XDBC1, 0XDA81, 0X1A40,
0X1E00, 0XDEC1, 0XDF81, 0X1F40, 0XDD01, 0X1DC0, 0X1C80, 0XDC41,
0X1400, 0XD4C1, 0XD581, 0X1540, 0XD701, 0X17C0, 0X1680, 0XD641,
0XD201, 0X12C0, 0X1380, 0XD341, 0X1100, 0XD1C1, 0XD081, 0X1040,
0XF001, 0X30C0, 0X3180, 0XF141, 0X3300, 0XF3C1, 0XF281, 0X3240,
0X3600, 0XF6C1, 0XF781, 0X3740, 0XF501, 0X35C0, 0X3480, 0XF441,
0X3C00, 0XFCC1, 0XFD81, 0X3D40, 0XFF01, 0X3FC0, 0X3E80, 0XFE41,
0XFA01, 0X3AC0, 0X3B80, 0XFB41, 0X3900, 0XF9C1, 0XF881, 0X3840,
0X2800, 0XE8C1, 0XE981, 0X2940, 0XEB01, 0X2BC0, 0X2A80, 0XEA41,
0XEE01, 0X2EC0, 0X2F80, 0XEF41, 0X2D00, 0XEDC1, 0XEC81, 0X2C40,
0XE401, 0X24C0, 0X2580, 0XE541, 0X2700, 0XE7C1, 0XE681, 0X2640,
0X2200, 0XE2C1, 0XE381, 0X2340, 0XE101, 0X21C0, 0X2080, 0XE041,
0XA001, 0X60C0, 0X6180, 0XA141, 0X6300, 0XA3C1, 0XA281, 0X6240,
0X6600, 0XA6C1, 0XA781, 0X6740, 0XA501, 0X65C0, 0X6480, 0XA441,
0X6C00, 0XACC1, 0XAD81, 0X6D40, 0XAF01, 0X6FC0, 0X6E80, 0XAE41,
0XAA01, 0X6AC0, 0X6B80, 0XAB41, 0X6900, 0XA9C1, 0XA881, 0X6840,
0X7800, 0XB8C1, 0XB981, 0X7940, 0XBB01, 0X7BC0, 0X7A80, 0XBA41,
0XBE01, 0X7EC0, 0X7F80, 0XBF41, 0X7D00, 0XBDC1, 0XBC81, 0X7C40,
0XB401, 0X74C0, 0X7580, 0XB541, 0X7700, 0XB7C1, 0XB681, 0X7640,
0X7200, 0XB2C1, 0XB381, 0X7340, 0XB101, 0X71C0, 0X7080, 0XB041,
0X5000, 0X90C1, 0X9181, 0X5140, 0X9301, 0X53C0, 0X5280, 0X9241,
0X9601, 0X56C0, 0X5780, 0X9741, 0X5500, 0X95C1, 0X9481, 0X5440,
0X9C01, 0X5CC0, 0X5D80, 0X9D41, 0X5F00, 0X9FC1, 0X9E81, 0X5E40,
0X5A00, 0X9AC1, 0X9B81, 0X5B40, 0X9901, 0X59C0, 0X5880, 0X9841,
0X8801, 0X48C0, 0X4980, 0X8941, 0X4B00, 0X8BC1, 0X8A81, 0X4A40,
0X4E00, 0X8EC1, 0X8F81, 0X4F40, 0X8D01, 0X4DC0, 0X4C80, 0X8C41,
0X4400, 0X84C1, 0X8581, 0X4540, 0X8701, 0X47C0, 0X4680, 0X8641,
0X8201, 0X42C0, 0X4380, 0X8341, 0X4100, 0X81C1, 0X8081, 0X4040
};
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Calculates the CRC16 result
*
* This function implements the CRC16 calculation
*
* \param[in] pData : the input byte array
* \param[in] length : the length of input array
* \return the CRC16 result
*/
static inline uint16_t Crc_CalcCrc16(const uint8_t *pData, uint32_t length)
{
uint8_t tmp;
uint16_t crcWord = 0xFFFF;
while(length--)
{
tmp = *pData++ ^ crcWord;
crcWord >>= 8;
crcWord ^= c_crcTable[tmp];
}
return crcWord;
}
/*! \brief Calculates the CRC8 result
*
* This function implements the CRC8 calculation
*
* \param[in] pData : the input byte array
* \param[in] length : the length of input array
* \param[in] polynomial : the polynomial used for the calculation
* \return the CRC8 result
*/
static inline uint8_t Crc_CalcCrc8(const uint8_t *pData, uint32_t length, uint8_t polynomial)
{
uint8_t bitIndex = 0;
uint8_t byteIndex = 0;
uint8_t crc = 0xFF;
for(byteIndex = 0; byteIndex < length; ++byteIndex)
{
crc ^= pData[byteIndex];
for(bitIndex = 0; bitIndex < 8; ++bitIndex)
{
if((crc & 0x80) != 0)
{
crc = (crc << 1) ^ polynomial;
}
else
{
crc = (crc << 1);
}
}
}
return ~crc;
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _CRC_H_ */

View File

@ -0,0 +1,333 @@
/*
* 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.
*/
#ifndef _LIST_H_
#define _LIST_H_
/*! \brief Contains public interface to various functions related
* to a wrapped linked-list
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Declaration of LIST object
*/
typedef struct _ListNode_
{
int32_t nextIndex; /*!< next index value */
void *pElement; /*!< the pointer to the element */
} ListNode;
/*! \brief Declaration of LIST object
*/
typedef struct _ListType_
{
ListNode *nodeArray; /*!< the pointer to the nodes, which must be an 1-D array */
uint32_t containerSize; /*!< the size of the container */
uint32_t length; /*!< the length of list */
ListNode head; /*!< the head node */
} ListType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the LIST object.
*
* This function initialize the LIST instance
*
* \param[in] obj : pointer to List instance
* \param[in] pNodes : pointer to node
* \param[in] pContainer : pointer to container
* \param[in] elemSize : element size in byte
* \param[in] containerSize : the size of the container
*/
static inline void List_Init(ListType *obj, ListNode *pNodes, void *pContainer, uint32_t elemSize, uint32_t containerSize)
{
obj->nodeArray = pNodes;
obj->containerSize = containerSize;
uint32_t i = 0;
for(i = 0; i < obj->containerSize; ++i)
{
obj->nodeArray[i].pElement = (void *)((unsigned char *)pContainer + i * elemSize);
obj->nodeArray[i].nextIndex = -1; /* Next index is -1 representing not occupied */
}
obj->head.nextIndex = obj->containerSize; /* next index = containerSize Mark the list */
obj->head.pElement = NULL;
obj->length = 0;
}
/*! \brief Get the length of the list
*
* This function get the length of the list
*
* \param[in] obj : pointer to List instance
* \return The length
*/
static inline uint32_t List_Length(const ListType *obj)
{
return obj->length;
}
/*! \brief Insert the element at the given index
*
* This function insert the element at the given index.
*
* \note If the given index is larger than the last element index+1,
* or the vector is full, the function will do nothing
*
* \param[in] obj : pointer to List instance
* \param[in] pElem : the pointer to the element
* \param[in] elemSize : the element size
* \param[in] index : the index to insert
* \return the result of the operation
* - true : success
* - false : fail
*/
static inline bool List_Insert(ListType *obj, const void *pElem, uint32_t elemSize, uint32_t index)
{
/* If full, we cannot insert more elements */
if(obj->length == obj->containerSize)
{
return false;
}
/* If no enough elements*/
if(index > obj->length)
{
return false;
}
/* Find first node not occupied*/
uint32_t actualIndex = 0;
bool actualIndexFound = false;
uint32_t i = 0;
for(i = 0; i < obj->containerSize; ++i)
{
if(obj->nodeArray[i].nextIndex == -1)
{
actualIndexFound = true;
actualIndex = i;
break;
}
}
if(actualIndexFound == false)
{
return false; /* Must found */
}
/* Assign the value */
unsigned char *src = (unsigned char *)pElem;
unsigned char *dest = (unsigned char *)(obj->nodeArray[actualIndex].pElement);
uint32_t byte;
for(byte = 0; byte < elemSize; byte++)
{
*dest++ = *src++;
}
/* Find the previous node */
if(index == 0)
{
/* Insert at the first node */
obj->nodeArray[actualIndex].nextIndex = obj->head.nextIndex; /* Replace the first valid data node */
obj->head.nextIndex = actualIndex; /* Mark the new first node */
}
else
{
uint32_t prevIndex = obj->head.nextIndex;
for(i = 0; i < index - 1; ++i)
{
prevIndex = obj->nodeArray[prevIndex].nextIndex;
}
obj->nodeArray[actualIndex].nextIndex = obj->nodeArray[prevIndex].nextIndex;
obj->nodeArray[prevIndex].nextIndex = actualIndex;
}
/* Increase the length */
obj->length++;
return true;
}
/*! \brief Get the element at the given index
*
* This function gets the element at the given index
*
* \note index must be in the range of 0-size
*
* \param[in] obj : pointer to List instance
* \param[out] pElem : pointer to the element to get
* \param[in] elemSize : size of element
* \param[in] index : index of the element to get
* \return result of the operation
* - true : success
* - false : failed
*/
static inline bool List_GetElement(const ListType *obj, void *pElem, uint32_t elemSize, uint32_t index)
{
if(index >= obj->length)
{
return false;
}
uint32_t i = 0;
uint32_t actualIndex = obj->head.nextIndex;
for(i = 0; i < index; ++i)
{
actualIndex = obj->nodeArray[actualIndex].nextIndex;
}
unsigned char *dest = (unsigned char *)pElem;
unsigned char *src = (unsigned char *)(obj->nodeArray[actualIndex].pElement);
for(i = 0; i < elemSize; i++)
{
*dest++ = *src++;
}
return true;
}
/*! \brief Get the element at the given index
*
* This function gets the element at the given index
*
* \note index must be in the range of 0-size-1
*
* \param[in] obj : pointer to List instance
* \param[in] elemSize : the element size
* \param[in] index : the index to get
* \return the pointer to the element
*/
static inline const void *List_At(const ListType *obj, uint32_t elemSize, uint32_t index)
{
if(index >= obj->length)
{
return ((void *)0);
}
uint32_t i = 0;
uint32_t actualIndex = obj->head.nextIndex;
for(i = 0; i < index; ++i)
{
actualIndex = obj->nodeArray[actualIndex].nextIndex;
}
return obj->nodeArray[actualIndex].pElement;
}
/*! \brief Clear the whole vector
*
* This function clears the whole vector
*
* \param[in] obj : pointer to List instance
*/
static inline void List_Clear(ListType *obj)
{
uint32_t i = 0;
for(i = 0; i < obj->containerSize; ++i)
{
obj->nodeArray[i].nextIndex = -1; /* Next index is -1 representing not occupied */
}
obj->head.nextIndex = obj->containerSize;
obj->head.pElement = NULL;
obj->length = 0;
}
/*! \brief Remove the element at the given index
*
* This function removes the element at the given index
*
* \param[in] obj : pointer to List instance
*/
static inline bool List_Remove(ListType *obj, uint32_t elemSize, uint32_t index)
{
/* If empty, we cannot remove any elements */
if(obj->length == 0)
{
return false;
}
/* If no enough elements */
if(index >= obj->length)
{
return false;
}
/* Find the previous node */
if(index == 0)
{
/* Remove the first node */
uint32_t currentIndex = obj->head.nextIndex;
obj->head.nextIndex = obj->nodeArray[obj->head.nextIndex].nextIndex;
obj->nodeArray[currentIndex].nextIndex = -1; /* Mark unoccupied */
}
else
{
uint32_t prevIndex = obj->head.nextIndex;
uint32_t i = 0;
for(i = 0; i < index - 1; ++i)
{
prevIndex = obj->nodeArray[prevIndex].nextIndex;
}
uint32_t currentIndex = obj->nodeArray[prevIndex].nextIndex;
obj->nodeArray[prevIndex].nextIndex = obj->nodeArray[currentIndex].nextIndex;
obj->nodeArray[currentIndex].nextIndex = -1; /* Mark unoccupied */
}
/* Decrease the length */
obj->length--;
return true;
}
/*! \brief Whether the list is full
*
* This function returns whether the list is full.
*
* \param[in] obj : pointer to List instance
*/
static inline bool List_IsFull(const ListType *obj)
{
return obj->length == obj->containerSize;
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _LIST_H_ */

View File

@ -0,0 +1,194 @@
/*
* 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.
*/
#ifndef _RINGBUFFER_H_
#define _RINGBUFFER_H_
/*! \brief Contains public interface to various functions related
* to the ring buffer template
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief RingBuffer prototype definition
*/
typedef struct _RingBufferType_
{
void *pBuffer; /*!< The actual buffer holder */
int32_t readIndex; /*!< The current index for the read */
int32_t writeIndex; /*!< The current index for the write */
int32_t usedNum; /*!< The number of used elements */
int32_t totalNum; /*!< The number of total elements */
} RingBufferType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initializes the ringbuffer instance
*
* This function initializes a ringbuffer instance
*
* \param[in] obj : pointer to RingBuffer instance
* \param[in] pBuffer : the actual buffer holder
* \param[in] size : the size of actual buffer holder
*/
static inline void RingBuffer_Init(RingBufferType *obj, void *pBuffer, uint32_t size)
{
obj->pBuffer = pBuffer;
obj->readIndex = 0;
obj->writeIndex = 0;
obj->usedNum = 0;
obj->totalNum = size;
}
/*! \brief Puts an element to the ringbuffer.
*
* This function puts an element to the ringbuffer.
*
* \param[in] obj : pointer to RingBuffer instance
* \param[in] pElem : pointer to the element to push into the buffer
* \param[in] size : the size of the element in bytes
* \return the result of the put operation
* true : success
* false : failed because the buffer is full
*/
static inline bool RingBuffer_Put(RingBufferType *obj, const void *pElem, uint32_t size)
{
uint32_t i = 0;
unsigned char *src;
unsigned char *dest;
/* Check if the buffer is full */
if(obj->usedNum >= obj->totalNum)
{
return false;
}
/* Copy the element */
src = (unsigned char *)pElem;
dest = (unsigned char *)obj->pBuffer + (obj->writeIndex * size);
for(i = 0; i < size; i++)
{
*dest++ = *src++;
}
/* Move the index */
obj->writeIndex++;
if(obj->writeIndex >= obj->totalNum)
{
obj->writeIndex = 0;
}
obj->usedNum++;
return true;
}
/*! \brief Gets an element from the ringbuffer.
*
* This function gets an element from the ringbuffer.
*
* \param[in] obj : pointer to RingBuffer instance
* \param[in] pElem : pointer to the element to get from the buffer
* \param[in] size : the size of the element in bytes
* \return the result of the put operation
* true : success
* false : failed because the buffer is empty
*/
static inline bool RingBuffer_Get(RingBufferType *obj, void *pElem, uint32_t size)
{
uint32_t i = 0;
unsigned char *src;
unsigned char *dest;
/* Check if the buffer is empty */
if(obj->usedNum <= 0)
{
return false;
}
/* Copy the element */
dest = (unsigned char *)pElem;
src = (unsigned char *)obj->pBuffer + (obj->readIndex * size);
for(i = 0; i < size; i++)
{
*dest++ = *src++;
}
/* Move the index */
obj->readIndex++;
if(obj->readIndex >= obj->totalNum)
{
obj->readIndex = 0;
}
obj->usedNum--;
return true;
}
/*! \brief See if the ringbuffer is full.
*
* This function gets if the ringbuffer is full
*
* \param[in] obj : pointer to RingBuffer instance
* \return whether the buffer is full
* true : the buffer is full
* false : the buffer is not full
*/
static inline bool RingBuffer_IsFull(const RingBufferType *obj)
{
return (obj->usedNum >= obj->totalNum);
}
/*! \brief See if the ringbuffer is empty.
*
* This function gets if the ringbuffer is empty
*
* \param[in] obj : pointer to RingBuffer instance
* \return whether the buffer is empty
* true : the buffer is empty
* false : the buffer is not empty
*/
static inline bool RingBuffer_IsEmpty(const RingBufferType *obj)
{
return (obj->usedNum <= 0);
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _RINGBUFFER_H_ */

View File

@ -0,0 +1,118 @@
/*
* 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.
*/
#ifndef _TABLE_H_
#define _TABLE_H_
/*! \brief Contains public interface to various functions related
* to the table template
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Declaration of table prototype
* The container should be an array in the form of buffer[rowNum][columnNum]
*/
typedef struct _TableType_
{
void *pContainer; /*!< The pointer to the container, which must be a 2-D array */
uint16_t rowNum; /*!< Total row number of the container */
uint16_t columnNum; /*!< Total column number of the container */
} TableType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the TABLE object.
*
* This function initializes a 2-D table instance
*
* \note The container should be the 2-D array
*
* \param[in] obj : pointer to Table instance
* \param[in] pContainer : the container (2-D array) for this table
* \param[in] rowNum : the total row count of the table
* \param[in] columnNum : the total column count of the table
*/
static inline void Table_Init(TableType *obj, void *pContainer, uint16_t rowNum, uint16_t columnNum)
{
obj->pContainer = pContainer;
obj->rowNum = rowNum;
obj->columnNum = columnNum;
}
/*! \brief Get a certain element determined by row and column from the table
*
* This function gets a certain element determined by row and column from the table
*
* \param[in] obj : pointer to Table instance
* \param[out] pElem : pointer to the element
* \param[in] elemSize : the size of element in byte
* \param[in] row : the row of the output element
* \param[in] column : the column of the output element
* \return the result of the get operation
* - true : succees
* - false : fail to get the element
*/
static inline bool Table_GetElement(const TableType *obj, void *pElem, uint16_t elemSize, uint16_t row, uint16_t column)
{
if(row > obj->rowNum - 1 || column > obj->columnNum - 1)
{
return false;
}
int i = 0;
unsigned char *src;
unsigned char *dest;
dest = (unsigned char *)pElem;
src = (unsigned char *)(obj->pContainer) + elemSize * (row * obj->columnNum + column);
for(i = 0; i < elemSize; i++)
{
*dest++ = *src++;
}
return true;
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _TABLE_H_ */

View File

@ -0,0 +1,122 @@
/*
* 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.
*/
#ifndef _TABLE3D_H_
#define _TABLE3D_H_
/*! \brief Contains public interface to various functions related
* to the 3-D table template
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Declaration of 3-D table prototype
* \note The container should be an array in the form of buffer[depthNum][rowNum][columnNum]
*/
typedef struct _Table3DType_
{
void *pContainer; /*!< The pointer to the container, which must be a 3-D array */
uint16_t rowNum; /*!< Total row number of the container */
uint16_t columnNum; /*!< Total column number of the container */
uint16_t depthNum; /*!< Total depth number of the container */
} Table3DType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the TABLE 3D object.
*
* This function initializes a 3-D table instance
*
* \note The container should be the 3-D array
*
* \param[in] obj : pointer to 3-D Table instance
* \param[in] pContainer : the container (3-D array) for this table
* \param[in] rowNum : the total row count of the table
* \param[in] columnNum : the total column count of the table
* \param[in] depthNum : the total depth count of the table
*/
static inline void Table3D_Init(Table3DType *obj, void *pContainer, uint16_t rowNum, uint16_t columnNum, uint16_t depthNum)
{
obj->pContainer = pContainer;
obj->rowNum = rowNum;
obj->columnNum = columnNum;
obj->depthNum = depthNum;
}
/*! \brief Get a certain element determined by row, column, depth from the table
*
* This function gets a certain element determined by row, column, depth from the table
*
* \param[in] obj : pointer to 3-D Table instance
* \param[out] pElem : pointer to the element
* \param[in] elemSize : the size of element in byte
* \param[in] row : the row of the output element
* \param[in] column : the column of the output element
* \param[in] depth : the depth of the output element
* \return the result of the get operation
* - true : succees
* - false : fail to get the element
*/
static inline bool Table3D_GetElement(const Table3DType *obj, void *pElem, uint16_t elemSize, uint16_t row, uint16_t column, uint16_t depth)
{
if(row > obj->rowNum - 1 || column > obj->columnNum - 1 || depth > obj->depthNum - 1)
{
return false;
}
int i = 0;
unsigned char *src;
unsigned char *dest;
dest = (unsigned char *)pElem;
src = (unsigned char *)(obj->pContainer) + elemSize * (depth * obj->rowNum * obj->columnNum + row * obj->columnNum + column);
for(i = 0; i < elemSize; i++)
{
*dest++ = *src++;
}
return true;
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _TABLE3D_H_ */

View File

@ -0,0 +1,301 @@
/*
* 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.
*/
#ifndef _VECTOR_H_
#define _VECTOR_H_
/*! \brief Contains public interface to various functions related
* to a wrapped fix-size array
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Declaration of Vector prototype
*/
typedef struct _VectorType_
{
void *pContainer; /*!< The pointer to the container, which must be an 1-D array */
uint32_t containerSize; /*!< The size of the container */
uint32_t length; /*!< The current occupied length */
} VectorType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initializes the Vector instance.
*
* This function initializes the Vector instance
*
* \param[in] obj : pointer to Vector instance
* \param[in] pContainer : the container (1-D array) for this table
* \param[in] size : the size of the container array
*/
static inline void Vector_Init(VectorType *obj, void *pContainer, uint32_t size)
{
obj->pContainer = pContainer;
obj->containerSize = size;
obj->length = 0;
}
/*! \brief Gets the current length of the vector
*
* This function gets the current length of the vector
*
* \param[in] obj : pointer to Vector instance
* \return the current length of the vector
*/
static inline uint32_t Vector_Length(const VectorType *obj)
{
return obj->length;
}
/*! \brief Inserts an element at the given index
*
* This function inserts an element at the given index
*
* \note If the given index is larger than the last element index+1,
* or the vector is full, the function will do nothing
*
* \param[in] obj : pointer to Vector instance
* \param[in] pElem : pointer to the element
* \param[in] elemSize : the size of element in byte
* \param[in] index : index where the element is inserted
* \return the result of the insert operation
* - true : success
* - false : failed
*/
static inline bool Vector_Insert(VectorType *obj, const void *pElem, uint32_t elemSize, uint32_t index)
{
/* If full, we cannot insert more elements */
if(obj->length == obj->containerSize)
{
return false;
}
/* If no enough elements */
if(index > obj->length)
{
return false;
}
unsigned char *src;
unsigned char *dest;
/* Move items by one position in memory */
if(obj->length > 0)
{
uint32_t i = 0;
for(i = obj->length; i > index; --i)
{
src = (unsigned char *)(obj->pContainer) + elemSize * (i - 1);
dest = (unsigned char *)(obj->pContainer) + elemSize * i;
uint32_t byte;
for(byte = 0; byte < elemSize; byte++)
{
*dest++ = *src++;
}
}
}
/* Assign the value */
src = (unsigned char *)pElem;
dest = (unsigned char *)(obj->pContainer) + elemSize * index;
uint32_t byte;
for(byte = 0; byte < elemSize; byte++)
{
*dest++ = *src++;
}
/* Increase the length */
obj->length++;
return true;
}
/*! \brief Gets the element at the given index
*
* This function gets the element at the given index
*
* \note index must be in the range of 0-size
*
* \param[in] obj : pointer to Vector instance
* \param[in] pElem : pointer to the element
* \param[in] elemSize : the size of element in byte
* \param[in] index : index of the element to get
* \return the result of the get operation
* - true : success
* - false : failed
*/
static inline bool Vector_GetElement(const VectorType *obj, void *pElem, uint32_t elemSize, uint32_t index)
{
if(index >= obj->length)
{
return false;
}
int i = 0;
unsigned char *src;
unsigned char *dest;
dest = (unsigned char *)pElem;
src = (unsigned char *)(obj->pContainer) + elemSize * index;
for(i = 0; i < elemSize; i++)
{
*dest++ = *src++;
}
return true;
}
/*! \brief Get the pointer to the element at the given index
*
* This function gets the pointer to the element at the given index
*
* \note index must be in the range of 0-size
*
* \param[in] obj : pointer to Vector instance
* \param[in] elemSize : the size of element in byte
* \param[in] index : index of the element to get
* \return pointer to the element
*/
static inline const void *Vector_At(const VectorType *obj, uint32_t elemSize, uint32_t index)
{
if(index >= obj->length)
{
return ((void *)0);
}
return (void *)((unsigned char *)(obj->pContainer) + elemSize * index);
}
/*! \brief Clears the whole vector
*
* This function clears the whole vector
*
* \param[in] obj : pointer to Vector instance
*/
static inline void Vector_Clear(VectorType *obj)
{
obj->length = 0;
}
/*! \brief Remove the element at the given index
*
* This function removes the element at the at the given index
*
* \param[in] obj : pointer to Vector instance
* \param[in] elemSize : the size of element in byte
* \param[in] index : index of the element to remove
* \return the result of the remove operation
* - true : success
* - false : failed
*/
static inline bool Vector_Remove(VectorType *obj, uint32_t elemSize, uint32_t index)
{
/* If empty, we cannot remove any elements */
if(obj->length == 0)
{
return false;
}
/* If no enough elements */
if(index >= obj->length)
{
return false;
}
unsigned char *src;
unsigned char *dest;
/* Move items by one position in memory */
if(obj->length - 1 > index)
{
uint32_t i = 0;
for(i = index; i < obj->length; ++i)
{
src = (unsigned char *)(obj->pContainer) + elemSize * (i + 1);
dest = (unsigned char *)(obj->pContainer) + elemSize * i;
uint32_t byte;
for(byte = 0; byte < elemSize; byte++)
{
*dest++ = *src++;
}
}
}
/* Decrease the length */
obj->length--;
return true;
}
/*! \brief Whether the vector is full
*
* This function gets whether the vector is full
*
* \param[in] obj : pointer to Vector instance
* \return whether the vector is full
* - true : full
* - false : not full
*/
static inline bool Vector_IsFull(const VectorType *obj)
{
return obj->length == obj->containerSize;
}
/*! \brief Whether the vector is empty
*
* This function gets whether the vector is empty
*
* \param[in] obj : pointer to Vector instance
* \return whether the vector is empty
* - true : empty
* - false : not empty
*/
static inline bool Vector_IsEmpty(const VectorType *obj)
{
return obj->length == 0;
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _VECTOR_H_ */

View File

@ -0,0 +1,157 @@
/*
* 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.
*/
#ifndef _GRADIENT_H_
#define _GRADIENT_H_
/*! \brief Contains public interface to various functions related
* to the 1st order linear curve with GRADIENT
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Declaration of Gradient Class
*
*/
typedef struct _GradientType_
{
_iq target; /*!< Input: target input */
_iq upStep; /*!< Parameter: up step of ramp */
_iq downStep; /*!< Parameter: down step of ramp */
_iq output; /*!< Output: output value */
} GradientType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the Gradient instance
*
* This function initializes the Gradient instance
*
* \param[in] obj : pointer to Gradient instance
* \param[in] upStep : step when going up
* \param[in] downStep : step when going down
*/
static inline void Gradient_Init(GradientType *obj, _iq upStep, _iq downStep)
{
obj->target = 0;
obj->output = 0;
obj->upStep = upStep;
obj->downStep = downStep;
}
/*! \brief Calculates the output
*
* This function calculates the output
*
* \param[in] obj : pointer to Gradient instance
*/
static inline void Gradient_Calc(GradientType *obj)
{
_iq upStep = _IQabs(obj->upStep); /* step must be a positive value */
_iq downStep = _IQabs(obj->downStep); /* step must be a positive value */
if(obj->target > obj->output)
{
if((obj->target - obj->output) > upStep)
{
obj->output += upStep;
}
else
{
obj->output = obj->target; /* less than one step needed, just jump to the target */
}
}
else if(obj->target < obj->output)
{
if((obj->output - obj->target) > downStep)
{
obj->output -= downStep;
}
else
{
obj->output = obj->target; /* less than one step needed, just jump to the target */
}
}
}
/*! \brief Calculate the output using the external reference
*
* This function calculates the output using the external reference,
* instead of the internal output
*
* \param[in] obj : pointer to Gradient instance
* \param[in] pOutput : pointer to external output
*/
static inline void Gradient_CalcExternal(GradientType *obj, _iq *pOutput)
{
_iq upStep = _IQabs(obj->upStep); /* step must be a positive value */
_iq downStep = _IQabs(obj->downStep); /* step must be a positive value */
if(obj->target > (*pOutput))
{
if((obj->target - (*pOutput)) > upStep)
{
(*pOutput) += upStep;
}
else
{
(*pOutput) = obj->target; /* less than one step needed, just jump to the target */
}
}
else if(obj->target < (*pOutput))
{
if(((*pOutput) - obj->target) > downStep)
{
(*pOutput) -= downStep;
}
else
{
(*pOutput) = obj->target; /* less than one step needed, just jump to the target */
}
}
obj->output = *pOutput; /* We don't use the obj->output normally in this function, just be safe */
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _GRADIENT_H_ */

View File

@ -0,0 +1,107 @@
/*
* 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.
*/
#ifndef _RAMP_H_
#define _RAMP_H_
/*! \brief Contains public interface to various functions related
* to the ramp object
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Declaration of Ramp Class
*/
typedef struct _RampType_
{
_iq target; /*!< Input: target input */
_iq step; /*!< Parameter: step of ramp */
_iq output; /*!< Output: output value */
} RampType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the Ramp instance
*
* This function initializes the Ramp instance
*
* \param[in] obj : pointer to Ramp instance
* \param[in] Step : step of going up and down
*/
static inline void Ramp_Init(RampType *obj, _iq step)
{
obj->target = 0;
obj->output = 0;
obj->step = step;
}
/*! \brief Calculates the output
*
* This function calculates the output
*
* \param[in] obj : pointer to Ramp instance
*/
static inline void Ramp_Calc(RampType *obj)
{
_iq step = _IQabs(obj->step); /* step must be a positive value */
if(_IQabs(obj->target - obj->output) > step)
{
if(obj->target > obj->output)
{
obj->output += step;
}
else
{
obj->output -= step;
}
}
else
{
/* less than one step needed, just jump to the target */
obj->output = obj->target;
}
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _RAMP_H_ */

View File

@ -0,0 +1,148 @@
/*
* 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.
*/
#ifndef _AVERAGE_H_
#define _AVERAGE_H_
/*! \brief Contains public interface to various functions related
* to the Averaging with sliding window (AVERAGE) filter object
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
typedef struct _AverageType_
{
bool isInitial; /*!< Internal variable: Flag to indicate initial state */
_iq *pBuffer; /*!< Internal variable: The pointer to the buffer */
uint16_t winSize; /*!< Internal variable: window length */
uint16_t index; /*!< Internal variable: index of the value ready to pop */
_iq sum; /*!< Internal variable: the sum of all the values in buffer */
_iq output; /*!< Output: The output value */
} AverageType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the AVERAGE object
*
* This function initializes the average instance.
*
* \param[in] obj : pointer to Average instance
* \param[in] buffer : filter buffer
* \param[in] bufferSize : size of buffer
*/
static inline void Average_Init(AverageType *obj, _iq buffer[], uint16_t bufferSize)
{
obj->pBuffer = &buffer[0];
obj->winSize = bufferSize;
for(obj->index = 0; obj->index < obj->winSize; obj->index++)
{
obj->pBuffer[obj->index] = 0;
}
obj->index = 0;
obj->isInitial = true;
obj->sum = 0;
obj->output = 0;
}
/*! \brief Push input to the filter
*
* This function pushes input to the filter.
*
* \param[in] obj : pointer to Average instance
* \param[in] input : input value to be filter
*/
static inline void Average_PushInput(AverageType *obj, _iq input)
{
if(obj->isInitial)
{
obj->output = input;
obj->isInitial = false;
}
else
{
obj->sum = obj->sum - obj->pBuffer[obj->index] + input;
obj->pBuffer[obj->index] = input;
obj->index++;
if(obj->index > obj->winSize - 1)
{
obj->index = 0;
}
obj->output = obj->sum / obj->winSize;
}
}
/*! \brief Get the output value
*
* This function gets the filter result.
*
* \param[in] obj : pointer to Average instance
* \return the filter result in IQ format
*/
static inline _iq Average_GetOutput(const AverageType *obj)
{
return obj->output;
}
/*! \brief Reset the filter
*
* This function resets the filter to the initial state.
*
* \param[in] obj : pointer to Average instance
*/
static inline void Average_Reset(AverageType *obj)
{
for(obj->index = 0; obj->index < obj->winSize; obj->index++)
{
obj->pBuffer[obj->index] = 0;
}
obj->index = 0;
obj->isInitial = true;
obj->output = 0;
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _AVERAGE_H_ */

View File

@ -0,0 +1,246 @@
/*
* 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.
*/
#ifndef _BP_SO_H_
#define _BP_SO_H_
/*! \brief Contains public interface to various functions related
* to the 2nd-Order band-pass (BpSo) filter object
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include <math.h>
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines the BpSo object
*
* The transfer function is as follows:
*
* 1 - Z^-2
* H(z) = (1-b)-------------------------------------
* 1 - 2*b*cosWn*z^-1 + (2*b - 1)*z^-2
*
* 1
* b = ---------------
* 1+tan(deltaW/2)
*
*
* a1= -2*b*cosWn
*
* a2= 2*b - 1
*
* a3= 1 - b
*/
typedef struct _BpSoType_
{
_iq coeff1; /*!< Parameter: The coefficient of Y(k-1) */
_iq coeff2; /*!< Parameter: The coefficient of Y(k-2) */
_iq coeff3; /*!< Parameter: The coefficient of X(k)-X(k-2) */
bool isInitial; /*!< Internal variable: Has the filter got the first input */
_iq prevOutput; /*!< Internal variable: The previous output cached */
_iq prevPrevOutput; /*!< Internal variable: The previous previous output cached */
_iq prevInput; /*!< Internal variable: The previous input cached */
_iq prevPrevInput; /*!< Internal variable: The previous previous input cached */
_iq output; /*!< Output: The output value */
} BpSoType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initializes the BpSo instance
*
* This function initializes the BpSo instance using the unit of rad/s
*
* \param[in] obj : pointer to BpSo instance
* \param[in] Wc_rps : the center frequency in rad/s
* \param[in] runFreq_kHz : the frequency pushing the data in
* \param[in] deltaW : 3-dB bandwidth in rad/s
*/
static inline void BpSo_Init(BpSoType *obj, float Wc_rps, float runFreq_kHz, float deltaW)
{
float b = 1 / (tan((deltaW / runFreq_kHz * 0.001) * 0.5) + 1);
float a1 = -2 * b * cos(Wc_rps / runFreq_kHz * 0.001);
float a2 = 2 * b - 1;
float a3 = 1 - b;
obj->coeff1 = _IQ(a1);
obj->coeff2 = _IQ(a2);
obj->coeff3 = _IQ(a3);
obj->isInitial = true;
obj->output = 0;
obj->prevOutput = 0;
obj->prevPrevOutput = 0;
obj->prevInput = 0;
obj->prevPrevInput = 0;
}
/*! \brief Initializes the BpSo instance, 2nd interface
*
* This function is an overload initialization that
* initialize the BpSo instance using the unit of Hz
*
* \param[in] obj : pointer to BpSo instance
* \param[in] fc_Hz : the center frequency in Hz
* \param[in] runFreq_kHz : the frequency pushing the data in
* \param[in] deltaF : 3 dB bandwidth in Hz
*/
static inline void BpSo_Init2(BpSoType *obj, float fc_Hz, float runFreq_kHz, float deltaF)
{
float b = 1 / (tan((MATH_2PI * deltaF / runFreq_kHz * 0.001) * 0.5) + 1);
float a1 = -2 * b * cos(MATH_2PI * fc_Hz / runFreq_kHz * 0.001);
float a2 = 2 * b - 1;
float a3 = 1 - b;
obj->coeff1 = _IQ(a1);
obj->coeff2 = _IQ(a2);
obj->coeff3 = _IQ(a3);
obj->isInitial = true;
obj->output = 0;
obj->prevOutput = 0;
obj->prevPrevOutput = 0;
obj->prevInput = 0;
obj->prevPrevInput = 0;
}
/*! \brief Push input to the filter
*
* This function is used to push data into the filter
*
* \param[in] obj : pointer to BpSo instance
* \param[in] input : the input data in IQ format
*/
static inline void BpSo_PushInput(BpSoType *obj, _iq input)
{
if(obj->isInitial)
{
obj->output = input;
obj->prevOutput = input;
obj->prevPrevOutput = input;
obj->prevInput = input;
obj->prevPrevInput = input;
obj->isInitial = false;
}
else
{
obj->output = -_IQmpy(obj->prevOutput, obj->coeff1) - _IQmpy(obj->prevPrevOutput, obj->coeff2)
+ _IQmpy(input - obj->prevPrevInput, obj->coeff3);
obj->prevPrevInput = obj->prevInput;
obj->prevInput = input;
obj->prevPrevOutput = obj->prevOutput;
obj->prevOutput = obj->output;
}
}
/*! \brief Gets the output value
*
* This function gets the output of the filter
*
* \param[in] obj : pointer to BpSo instance
* \return the result of the filter in IQ format
*/
static inline _iq BpSo_GetOutput(const BpSoType *obj)
{
return obj->output;
}
/*! \brief Resets the filter
*
* This function resets the filter to initial state
*
* \param[in] obj : pointer to BpSo instance
*/
static inline void BpSo_Reset(BpSoType *obj)
{
obj->isInitial = true;
obj->output = 0;
obj->prevOutput = 0;
obj->prevPrevOutput = 0;
obj->prevInput = 0;
obj->prevPrevInput = 0;
}
/*! \brief Update the parameters of the filter
*
* This function updates the parameters of the filter using the unit of rad/s
*
* \param[in] obj : pointer to BpSo instance
* \param[in] Wc_rps : the center frequency in rad/s
* \param[in] runFreq_kHz : the frequency pushing the data in
* \param[in] deltaW : 3-dB bandwidth in rad/s
*/
static inline void BpSo_UpdateParams(BpSoType *obj, float Wc_rps, float runFreq_kHz, float deltaW)
{
float b = 1 / (tan((deltaW / runFreq_kHz * 0.001) * 0.5) + 1);
float a1 = -2 * b * cos(Wc_rps / runFreq_kHz * 0.001);
float a2 = 2 * b - 1;
float a3 = 1 - b;
obj->coeff1 = _IQ(a1);
obj->coeff2 = _IQ(a2);
obj->coeff3 = _IQ(a3);
}
/*! \brief Update the parameters of the filter
*
* This function updates the parameters of the filter using the unit of Hz
*
* \param[in] obj : pointer to BpSo instance
* \param[in] fc_Hz : the center frequency in Hz
* \param[in] runFreq_kHz : the frequency pushing the data in
* \param[in] deltaF : 3 dB bandwidth in Hz
*/
static inline void BpSo_UpdateParams2(BpSoType *obj, float fc_Hz, float runFreq_kHz, float deltaF)
{
float b = 1 / (tan((MATH_2PI * deltaF / runFreq_kHz * 0.001) * 0.5) + 1);
float a1 = -2 * b * cos(MATH_2PI * fc_Hz / runFreq_kHz * 0.001);
float a2 = 2 * b - 1;
float a3 = 1 - b;
obj->coeff1 = _IQ(a1);
obj->coeff2 = _IQ(a2);
obj->coeff3 = _IQ(a3);
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _BP_SO_H_ */

View File

@ -0,0 +1,245 @@
/*
* 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.
*/
#ifndef _BS_SO_H_
#define _BS_SO_H_
/*! \brief Contains public interface to various functions related
* to the Band-stop (NOTCH) filter object
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines the BS_SO object
* \note The transfer function is as follows:
*
* 1-2*cosWn*z^-1 + z^-2
* H(z) = b-----------------------------------
* 1 - 2*b*cosWn*z^-1 + (2*b -1)*z^-2
*
* 1
* b = ---------------
* 1+tan(deltaW/2)
*
* a1= -2*b*cosWn
*
* a2= 2*b - 1
*
*/
typedef struct _BsSoType_
{
_iq coeff1; /*!< Parameter: The coefficient of Y(k-1) */
_iq coeff2; /*!< Parameter: The coefficient of Y(k-2) */
_iq coeff3; /*!< Parameter: The coefficient of X(k) */
_iq coeff4; /*!< Parameter: The coefficient of X(k-1) */
_iq coeff5; /*!< Parameter: The coefficient of X(k-2) */
bool isInitial; /*!< Internal variable: Has the filter got the first input */
_iq prevOutput; /*!< Internal variable: The previous output cached */
_iq prevPrevOutput; /*!< Internal variable: The previous previous output cached */
_iq prevInput; /*!< Internal variable: The previous input cached */
_iq prevPrevInput; /*!< Internal variable: The previous previous input cached */
_iq output; /*!< Output: The output value */
} BsSoType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Theoretically initialize the BS_SO object with detailed parameters
*
* This function initializes the BsSo instance using the unit of rad/s
*
* \param[in] obj : pointer to BsSo instance
* \param[in] Wc_rps : the center frequency in rad/s
* \param[in] runFreq_kHz : the frequency pushing the data in
* \param[in] deltaW : 3-dB bandwidth in rad/s
*/
static inline void BsSo_Init(BsSoType *obj, float Wc_rps, float runFreq_kHz, float deltaW)
{
float b = 1 / (tan((deltaW / runFreq_kHz * 0.001) / 2) + 1);
float a2 = 2 * b - 1;
float a1 = -2 * b * cos(Wc_rps / runFreq_kHz * 0.001);
obj->coeff1 = _IQ(a1);
obj->coeff2 = _IQ(a2);
obj->coeff3 = _IQ(b);
obj->coeff4 = obj->coeff1;
obj->coeff5 = obj->coeff3;
obj->isInitial = true;
obj->output = 0;
obj->prevOutput = 0;
obj->prevPrevOutput = 0;
obj->prevInput = 0;
obj->prevPrevInput = 0;
}
/*! \brief Theoretically initialize the BS_SO object with detailed parameters, 2nd interface
*
* This function is an overload initialization that
* initialize the BsSo instance using the unit of Hz
*
* \param[in] obj : pointer to BsSo instance
* \param[in] fc_Hz : the center frequency in Hz
* \param[in] runFreq_kHz : the frequency pushing the data in
* \param[in] deltaF : 3 dB bandwidth in Hz
*/
static inline void BsSo_Init2(BsSoType *obj, float fc_Hz, float runFreq_kHz, float deltaF)
{
float b = 1 / (tan((MATH_2PI * deltaF / runFreq_kHz * 0.001) / 2) + 1);
float a2 = 2 * b - 1;
float a1 = -2 * b * cos(MATH_2PI * fc_Hz / runFreq_kHz * 0.001);
obj->coeff1 = _IQ(a1);
obj->coeff2 = _IQ(a2);
obj->coeff3 = _IQ(b);
obj->coeff4 = obj->coeff1;
obj->coeff5 = obj->coeff3;
obj->isInitial = true;
obj->output = 0;
obj->prevOutput = 0;
obj->prevPrevOutput = 0;
obj->prevInput = 0;
obj->prevPrevInput = 0;
}
/*! \brief Push input to the filter
*
* This function is used to push data into the filter
*
* \param[in] obj : pointer to BsSo instance
* \param[in] input : the input data in IQ format
*/
static inline void BsSo_PushInput(BsSoType *obj, _iq input)
{
if(obj->isInitial)
{
obj->output = input;
obj->prevOutput = input;
obj->prevPrevOutput = input;
obj->prevInput = input;
obj->prevPrevInput = input;
obj->isInitial = false;
}
else
{
obj->output = -_IQmpy(obj->prevOutput, obj->coeff1) - _IQmpy(obj->prevPrevOutput, obj->coeff2)
+ _IQmpy(input, obj->coeff3) + _IQmpy(obj->prevInput, obj->coeff4)
+ _IQmpy(obj->prevPrevInput, obj->coeff5);
obj->prevPrevInput = obj->prevInput;
obj->prevInput = input;
obj->prevPrevOutput = obj->prevOutput;
obj->prevOutput = obj->output;
}
}
/*! \brief Gets the output value
*
* This function gets the output of the filter
*
* \param[in] obj : pointer to BsSo instance
* \return the result of the filter in IQ format
*/
static inline _iq BsSo_GetOutput(const BsSoType *obj)
{
return obj->output;
}
/*! \brief Resets the filter
*
* This function resets the filter to initial state
*
* \param[in] obj : pointer to BsSo instance
*/
static inline void BsSo_Reset(BsSoType *obj)
{
obj->isInitial = true;
obj->output = 0;
obj->prevOutput = 0;
obj->prevPrevOutput = 0;
obj->prevInput = 0;
obj->prevPrevInput = 0;
}
/*! \brief Update the parameters of the filter
*
* This function updates the parameters of the filter with unit rad/s
*
* \param[in] obj : pointer to BsSo instance
* \param[in] Wc_rps : the center frequency in rad/s
* \param[in] runFreq_kHz : the frequency pushing the data in
* \param[in] deltaW : 3-dB bandwidth in rad/s
*/
static inline void BsSo_UpdateParams(BsSoType *obj, float Wc_rps, float runFreq_kHz, float deltaW)
{
float b = 1 / (tan((deltaW / runFreq_kHz * 0.001) / 2) + 1);
float a2 = 2 * b - 1;
float a1 = -2 * b * cos(Wc_rps / runFreq_kHz * 0.001);
obj->coeff1 = _IQ(a1);
obj->coeff2 = _IQ(a2);
obj->coeff3 = _IQ(b);
obj->coeff4 = obj->coeff1;
obj->coeff5 = obj->coeff3;
}
/*! \brief Update the parameters of the filter
*
* This function update the parameters of the filter with unit Hz
*
* \param[in] obj : pointer to BsSo instance
* \param[in] fc_Hz : the center frequency in Hz
* \param[in] runFreq_kHz : the frequency pushing the data in
* \param[in] deltaF : 3 dB bandwidth in Hz
*/
static inline void BsSo_UpdateParams2(BsSoType *obj, float fc_Hz, float runFreq_kHz, float deltaF)
{
float b = 1 / (tan((MATH_2PI * deltaF / runFreq_kHz * 0.001) / 2) + 1);
float a2 = 2 * b - 1;
float a1 = -2 * b * cos(MATH_2PI * fc_Hz / runFreq_kHz * 0.001);
obj->coeff1 = _IQ(a1);
obj->coeff2 = _IQ(a2);
obj->coeff3 = _IQ(b);
obj->coeff4 = obj->coeff1;
obj->coeff5 = obj->coeff3;
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _BS_SO_H_ */

View File

@ -0,0 +1,159 @@
/*
* 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.
*/
#ifndef _DEBOUNCE_H_
#define _DEBOUNCE_H_
/*! \brief Contains public interface to various functions related
* to the debounce (DEBOUNCE) object
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "common/iqmath/iqmath.h"
#include "common/sort/compare.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
typedef enum
{
DEBOUNCE_TYPE_OVER, /*!< Over the threshold is active */
DEBOUNCE_TYPE_UNDER, /*!< Under the threshold is active */
} Debounce_ModeType;
/*! \brief Defines all the parameters used to initialize DEBOUNCE object
*/
typedef struct _Debounce_ParamsType_
{
uint32_t debounceConfirmCntMax; /*!< The max value of the debounce count */
uint32_t debounceRehabCntMax; /*!< The max value of the debounce count */
_iq threshold; /*!< The threshold of the input compare */
Debounce_ModeType compType; /*!< The compare type */
} Debounce_ParamsType;
/*! \brief Defines the DEBOUNCE object
*/
typedef struct _DebounceType_
{
_iq input; /*!< Input: The input value of the debounce */
uint32_t countConfirmMax; /*!< Parameters: The max value of the debounce count */
uint32_t countRehabMax; /*!< Parameters: The max value of the debounce count */
_iq threshold; /*!< Parameters: The threshold of the input compare */
uint32_t count; /*!< Internal variable: The count of the debouncing process */
bool (*comp)(_iq, _iq); /*!< Internal Variable: The compare function pointer */
bool isActive; /*!< Output: Is active after debounce */
} DebounceType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the DEBOUNCE object
*
* This function initialize the debounce instance.
*
* \param[in] obj : pointer to Debounce instance
* \param[in] pParams : The pointer to initial parameters
*/
static inline void Debounce_Init(DebounceType *obj, const Debounce_ParamsType *pParams)
{
obj->countConfirmMax = pParams->debounceConfirmCntMax;
obj->countRehabMax = pParams->debounceRehabCntMax;
obj->threshold = pParams->threshold;
if(pParams->compType == DEBOUNCE_TYPE_UNDER)
{
obj->comp = Compare_SmallerThan;
}
else if(pParams->compType == DEBOUNCE_TYPE_OVER)
{
obj->comp = Compare_GreaterThan;
}
obj->count = 0;
obj->isActive = false;
}
/*! \brief Run the DEBOUNCE process
*
* This function is the calculation of debounce process.
*
* \param[in] obj :pointer to Debounce instance
*/
static inline void Debounce_Run(DebounceType *obj)
{
if(obj->comp(obj->input, obj->threshold))
{
if(obj->isActive)
{
obj->count = 0;
}
else if(++obj->count >= obj->countConfirmMax)
{
obj->isActive = true;
obj->count = 0;
}
}
else
{
if(!obj->isActive)
{
obj->count = 0;
}
else if(++obj->count >= obj->countRehabMax)
{
obj->isActive = false;
obj->count = 0;
}
}
}
/*! \brief Reset the DEBOUNCE object
*
* This function resets the debounce instance to intial state.
*
* \param[in] obj : pointer to Debounce instance
*/
static inline void Debounce_Reset(DebounceType *obj)
{
obj->count = 0;
obj->isActive = false;
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _DEBOUNCE_H_ */

View File

@ -0,0 +1,179 @@
/*
* 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.
*/
#ifndef _IIR_FO_H_
#define _IIR_FO_H_
/*! \brief Contains public interface to various functions related
* to the 1st-Order IIR (IirFo) low-pass filter object
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
typedef struct _IirFoType_
{
_iq output; /*!< the output value */
bool isInitial; /*!< the flag to indicate whether the instance is initialized */
_iq filterCoeff; /*!< 1st order IIR, y[n] = y[n-1] + coeff*(x[n]-y[n-1]) */
} IirFoType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the IirFo object
*
* This function initializes the 1st-order IIR filter instance
*
* \param[in] obj : pointer to IirFo instance
* \param[in] filterCoeff : the coefficient of the filter
*/
static inline void IirFo_Init(IirFoType *obj, _iq filterCoeff)
{
obj->isInitial = true;
obj->output = 0;
if(filterCoeff > 0 && filterCoeff < _IQ(1.0))
{
obj->filterCoeff = filterCoeff;
}
else
{
obj->filterCoeff = _IQ(1.0); /* Just for protection, normally we don't want this */
}
}
/*! \brief Theoretically initialize the IirFo object with detailed parameters
*
* This function initialize the IirFo object in the theoretical way using the unit rad/s
*
* \note The Wc_rps is the cutoff frequency in the unit of rad/s
*
* \param[in] obj : pointer to IirFo instance
* \param[in] Wc_rps : the cut-off frequency in rad/s
* \param[in] runFreq_kHz : the calculation frequency of the filter
*/
static inline void IirFo_InitTheo(IirFoType *obj, float Wc_rps, float runFreq_kHz)
{
obj->isInitial = true;
obj->output = 0;
_iq filterCoeff = _IQ(Wc_rps / runFreq_kHz * 0.001);
if(filterCoeff > 0 && filterCoeff < _IQ(1.0))
{
obj->filterCoeff = filterCoeff;
}
else
{
obj->filterCoeff = _IQ(1.0); /* Just for protection, normally we don't want this */
}
}
/*! \brief Theoretically initialize the IirFo object with detailed parameters, 2nd interface
*
* This function initialize the IirFo object in the theoretical way using the unit Hz
*
* \note The fc_Hz is the cutoff frequency in the unit of Hz
*
* \param[in] obj : pointer to IirFo instance
* \param[in] fc_Hz : the cut-off frequency in Hz
* \param[in] runFreq_kHz : the calculation frequency of the filter
*/
static inline void IirFo_InitTheo2(IirFoType *obj, float fc_Hz, float runFreq_kHz)
{
obj->isInitial = true;
obj->output = 0;
_iq filterCoeff = _IQ(MATH_2PI * fc_Hz / runFreq_kHz * 0.001);
if(filterCoeff > 0 && filterCoeff < _IQ(1.0))
{
obj->filterCoeff = filterCoeff;
}
else
{
obj->filterCoeff = _IQ(1.0); /* Just for protection, normally we don't want this */
}
}
/*! \brief Push input to the filter
*
* This function push data into the filter
*
* \param[in] obj : pointer to IirFo instance
* \param[in] input : the input data
*/
static inline void IirFo_PushInput(IirFoType *obj, _iq input)
{
if(obj->isInitial)
{
obj->output = input;
obj->isInitial = false;
}
else
{
obj->output = obj->output + _IQmpy(input - obj->output, obj->filterCoeff);
}
}
/*! \brief Get the output value
*
* This function gets the output value.
*
* \param[in] obj : pointer to IirFo instance
* \return the filter result of the filter in IQ format.
*/
static inline _iq IirFo_GetOutput(const IirFoType *obj)
{
return obj->output;
}
/*! \brief Reset the filter
*
* This function reset the filter to the initial state.
*
* \param[in] obj : pointer to IirFo instance
*/
static inline void IirFo_Reset(IirFoType *obj)
{
obj->isInitial = true;
obj->output = 0;
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _IIR_FO_H_ */

View File

@ -0,0 +1,271 @@
/*
* 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.
*/
#ifndef _IIR_SO_H_
#define _IIR_SO_H_
/*! \brief Contains public interface to various functions related
* to the 1st-Order IIR (IirSo) low-pass filter object
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines the IirSo object
* \note The transfer function is as follows:
*
* Wc^2
* H(s) = -------------------------
* s^2 + 2*Zeta*Wc*s + Wc^2
*
* The discrete equation uses Tustin method, in which
*
* 2 z - 1
* s = --- * -------
* T z + 1
*
* We add pre-warping to compensate the frequency, in which
*
* 2 T
* W' = --- * tan(W*---)
* T 2
*/
typedef struct _IirSoType_
{
_iq coeff1; /*!< Parameter: The coefficient of Y(k-1) */
_iq coeff2; /*!< Parameter: The coefficient of Y(k-2) */
_iq coeff3; /*!< Parameter: The coefficient of X(k)+2*X(k-1)+X(k-2) */
bool isInitial; /*!< Internal variable: Has the filter got the first input */
_iq prevOutput; /*!< Internal variable: The previous output cached */
_iq prevPrevOutput; /*!< Internal variable: The previous previous output cached */
_iq prevInput; /*!< Internal variable: The previous input cached */
_iq prevPrevInput; /*!< Internal variable: The previous previous input cached */
_iq output;
} IirSoType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the IirSo object
*
* This function initialize the IirSo instance with parameters
*
* \note The Wc_rps is the cutoff frequency in the unit of rad/s
*
* \param[in] obj : pointer to IirSo instance
* \param[in] Wc_rps : the cut-off frequency in rad/s
* \param[in] runFreq_kHz : the frequency pushing the data in
* \param[in] zeta : the zeta coefficient
*/
static inline void IirSo_Init(IirSoType *obj, float Wc_rps, float runFreq_kHz, float zeta)
{
/* Prewarping */
float twoph = 2000 * runFreq_kHz;
float hptwo = 0.0005 / runFreq_kHz;
Wc_rps = twoph * tan(Wc_rps * hptwo);
_iq tmp = _IQ(Wc_rps / runFreq_kHz * 0.001);
_iq c1 = _IQmpy(tmp, tmp);
_iq c2 = _IQ(zeta * Wc_rps / runFreq_kHz * 0.001);
_iq k = _IQ(1) + c2 + _IQdiv4(c1);
obj->coeff1 = _IQdiv(_IQ(2) - _IQdiv2(c1), k);
obj->coeff2 = _IQdiv(-_IQdiv4(c1) - _IQ(1) + c2, k);
obj->coeff3 = _IQdiv(_IQdiv4(c1), k);
obj->isInitial = true;
obj->output = 0;
obj->prevOutput = 0;
obj->prevPrevOutput = 0;
obj->prevInput = 0;
obj->prevPrevInput = 0;
}
/*! \brief Theoretically initialize the IirSo object with detailed parameters, 2nd interface
*
* This function theoretically initialize the IirSo object with detailed parameters
* This is an overload function.
*
* \note The fc_Hz is the cutoff frequency in the unit of Hz
*
* \param[in] obj : pointer to IirSo instance
* \param[in] fc_Hz : the cut-off frequency in Hz
* \param[in] runFreq_kHz : the frequency pushing the data in
* \param[in] zeta : the zeta coefficient
*/
static inline void IirSo_Init2(IirSoType *obj, float fc_Hz, float runFreq_kHz, float zeta)
{
/* Prewarping */
float twoph = 2000 * runFreq_kHz;
float hptwo = 0.0005 / runFreq_kHz;
float Wc_rps = twoph * tan(MATH_2PI * fc_Hz * hptwo);
_iq tmp = _IQ(Wc_rps / runFreq_kHz * 0.001);
_iq c1 = _IQmpy(tmp, tmp);
_iq c2 = _IQ(zeta * Wc_rps / runFreq_kHz * 0.001);
_iq k = _IQ(1) + c2 + _IQdiv4(c1);
obj->coeff1 = _IQdiv(_IQ(2) - _IQdiv2(c1), k);
obj->coeff2 = _IQdiv(-_IQdiv4(c1) - _IQ(1) + c2, k);
obj->coeff3 = _IQdiv(_IQdiv4(c1), k);
obj->isInitial = true;
obj->output = 0;
obj->prevOutput = 0;
obj->prevPrevOutput = 0;
obj->prevInput = 0;
obj->prevPrevInput = 0;
}
/*! \brief Push input to the filter
*
* This function push data into the filter
*
* \param[in] obj : pointer to IirSo instance
* \param[in] input : input data in IQ format
*/
static inline void IirSo_PushInput(IirSoType *obj, _iq input)
{
if(obj->isInitial)
{
obj->output = input;
obj->prevOutput = input;
obj->prevPrevOutput = input;
obj->prevInput = input;
obj->prevPrevInput = input;
obj->isInitial = false;
}
else
{
obj->output = _IQmpy(obj->prevOutput, obj->coeff1) + _IQmpy(obj->prevPrevOutput, obj->coeff2)
+ _IQmpy(input + _IQmpy2(obj->prevInput) + obj->prevPrevInput, obj->coeff3);
obj->prevPrevInput = obj->prevInput;
obj->prevInput = input;
obj->prevPrevOutput = obj->prevOutput;
obj->prevOutput = obj->output;
}
}
/*! \brief Get the output value
*
* This function gets the filter result
*
* \param[in] obj : pointer to IirSo instance
* \return the filter result
*/
static inline _iq IirSo_GetOutput(const IirSoType *obj)
{
return obj->output;
}
/*! \brief Reset the filter
*
* This function resets the filter to the initial state
*
* \param[in] obj : pointer to IirSo instance
*/
static inline void IirSo_Reset(IirSoType *obj)
{
obj->isInitial = true;
obj->output = 0;
obj->prevOutput = 0;
obj->prevPrevOutput = 0;
obj->prevInput = 0;
obj->prevPrevInput = 0;
}
/*! \brief Update the parameters of the filter
*
* This function updates the parameter of the filter in the runtime.
*
* \param[in] obj : pointer to IirSo instance
* \param[in] Wc_rps : the cut-off frequency in rad/s
* \param[in] runFreq_kHz : the frequency pushing the data in
* \param[in] zeta : the zeta coefficient
*/
static inline void IirSo_UpdateParams(IirSoType *obj, float Wc_rps, float runFreq_kHz, float zeta)
{
/* Prewarping */
float twoph = 2000 * runFreq_kHz;
float hptwo = 0.0005 / runFreq_kHz;
Wc_rps = twoph * tan(Wc_rps * hptwo);
_iq tmp = _IQ(Wc_rps / runFreq_kHz * 0.001);
_iq c1 = _IQmpy(tmp, tmp);
_iq c2 = _IQ(zeta * Wc_rps / runFreq_kHz * 0.001);
_iq k = _IQ(1) + c2 + _IQdiv4(c1);
obj->coeff1 = _IQdiv(_IQ(2) - _IQdiv2(c1), k);
obj->coeff2 = _IQdiv(-_IQdiv4(c1) - _IQ(1) + c2, k);
obj->coeff3 = _IQdiv(_IQdiv4(c1), k);
}
/*! \brief Update the parameters of the filter
*
* This function updates the parameter of the filter in the runtime.
* This is an overload function.
*
* \param[in] obj : pointer to IirSo instance
* \param[in] fc_Hz : the cut-off frequency in Hz
* \param[in] runFreq_kHz : the frequency pushing the data in
* \param[in] zeta : the zeta coefficient
*/
static inline void IirSo_UpdateParams2(IirSoType *obj, float fc_Hz, float runFreq_kHz, float zeta)
{
/* Prewarping */
float twoph = 2000 * runFreq_kHz;
float hptwo = 0.0005 / runFreq_kHz;
float Wc_rps = twoph * tan(MATH_2PI * fc_Hz * hptwo);
_iq tmp = _IQ(Wc_rps / runFreq_kHz * 0.001);
_iq c1 = _IQmpy(tmp, tmp);
_iq c2 = _IQ(zeta * Wc_rps / runFreq_kHz * 0.001);
_iq k = _IQ(1) + c2 + _IQdiv4(c1);
obj->coeff1 = _IQdiv(_IQ(2) - _IQdiv2(c1), k);
obj->coeff2 = _IQdiv(-_IQdiv4(c1) - _IQ(1) + c2, k);
obj->coeff3 = _IQdiv(_IQdiv4(c1), k);
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _IIR_SO_H_ */

View File

@ -0,0 +1,197 @@
/*
* 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.
*/
#ifndef _INTERP1D_H_
#define _INTERP1D_H_
/*! \brief Contains public interface to various functions related
* to the 1-D Linear Interpolation
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
typedef struct _Interp1d_PointType_
{
_iq x; /*!< x. */
_iq y; /*!< y. */
} Interp1d_PointType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief This is an linear interpolate calculation function using 2 x and the scale as input
* The result x should satisfy: scale = (x-x1) / (x2-x1)
*
* \param[in] x1 : x value of point 1
* \param[in] x2 : x value of point 2
* \param[in] scale : the scale = (x-x1) / (x2-x1)
* \return the value x in the scale equation
*/
static inline _iq Interp1d(_iq x1, _iq x2, _iq scale)
{
return (_IQmpy(scale, x2 - x1) + x1);
}
/*! \brief This is an linear interpolate calculation function using 2 points as input
* Calculate y for the given x, based on two points - (x1, y1) and (x2, y2)
*
* \note If x1 is equal to x2, which is not actually allowed, it will return
* (y1+y2)/2 instead. User should prevent this situation.
*
* \param[in] x1 : x value of point 1
* \param[in] y1 : y value of point 1
* \param[in] x2 : x value of point 2
* \param[in] y2 : y value of point 2
* \param[in] x : x value of the target point
* \return the y value of the target point
*/
static inline _iq Interp1dPoints(_iq x1, _iq y1, _iq x2, _iq y2, _iq x)
{
return (x2 != x1) ? (_IQmpy(_IQdiv(y2 - y1, x2 - x1), x - x1) + y1) : _IQdiv2(y2 + y1);
}
/*! \brief This is an linear interpolate calculation function using the whole table as input
*
* \note The values in x[] must be from smallest to biggest
*
* \param[in] u0 : x value of the target point
* \param[in] x[] : the x value array
* \param[in] y[] : the y value array
* \param[in] maxIndex : max index of the array
* \return the y value of the target point
*/
static inline _iq Interp1dTable(_iq u0, const _iq x[], const _iq y[], uint32_t maxIndex)
{
_iq frac;
uint32_t right;
uint32_t left;
uint32_t bpIdx;
if(u0 <= x[0U])
{
left = 0U;
frac = (x[1U] == x[0U]) ? _IQ(0.5) : _IQdiv(u0 - x[0U], x[1U] - x[0U]);
}
else if(u0 < x[maxIndex])
{
/* Binary Search */
bpIdx = maxIndex >> 1U;
left = 0U;
right = maxIndex;
while(right - left > 1U)
{
if(u0 < x[bpIdx])
{
right = bpIdx;
}
else
{
left = bpIdx;
}
bpIdx = (right + left) >> 1U;
}
frac = (x[left + 1U] != x[left]) ? _IQdiv(u0 - x[left], x[left + 1U] - x[left]) : _IQ(0.5);
}
else
{
left = maxIndex - 1U;
frac = (x[maxIndex] != x[maxIndex - 1U]) ? _IQdiv(u0 - x[maxIndex - 1U], x[maxIndex] - x[maxIndex - 1U]) : _IQ(0.5);
}
return (_IQmpy(_IQ(1.0) - frac, y[left]) + _IQmpy(y[left + 1U], frac));
}
/*! \brief This is an linear interpolate calculation function using the whole table as input
*
* \note The values in pPt[].x must be from smallest to biggest
*
* \param[in] u0 : x value of the target point
* \param[in] pPt : the pointer to the points array
* \param[in] maxIndex : max index of the array
* \return the y value of the target point
*/
static inline _iq Interp1dPtArray(_iq u0, const Interp1d_PointType *pPt, uint32_t maxIndex)
{
_iq frac;
uint32_t right;
uint32_t left;
uint32_t bpIdx;
if(u0 <= pPt[0U].x)
{
left = 0U;
frac = (pPt[1U].x == pPt[0U].x) ? _IQ(0.5) : _IQdiv(u0 - pPt[0U].x, pPt[1U].x - pPt[0U].x);
}
else if(u0 < pPt[maxIndex].x)
{
/* Binary Search */
bpIdx = maxIndex >> 1U;
left = 0U;
right = maxIndex;
while(right - left > 1U)
{
if(u0 < pPt[bpIdx].x)
{
right = bpIdx;
}
else
{
left = bpIdx;
}
bpIdx = (right + left) >> 1U;
}
frac = (pPt[left + 1U].x != pPt[left].x) ? _IQdiv(u0 - pPt[left].x, pPt[left + 1U].x - pPt[left].x) : _IQ(0.5);
}
else
{
left = maxIndex - 1U;
frac = (pPt[maxIndex].x != pPt[maxIndex - 1U].x) ? _IQdiv(u0 - pPt[maxIndex - 1U].x, pPt[maxIndex].x - pPt[maxIndex - 1U].x) : _IQ(0.5);
}
return (_IQmpy(_IQ(1.0) - frac, pPt[left].y) + _IQmpy(pPt[left + 1U].y, frac));
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _INTERP1D_H_ */

View File

@ -0,0 +1,72 @@
/*
* 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.
*/
#ifndef _INTERP2D_H_
#define _INTERP2D_H_
/*! \brief Contains public interface to various functions related
* to the 2-D linear interpolation
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include "common/iqmath/iqmath.h"
#include "interp1d.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief This is an 2-D linear interpolate calculation function using the row and column scale as input
*
* \param[in] x00 : the x value of (0, 0) point
* \param[in] x01 : the x value of (0, 1) point
* \param[in] x10 : the x value of (1, 0) point
* \param[in] x11 : the x value of (1, 1) point
* \param[in] rowScale : the scale of row
* \param[in] columnScale : the scale of column
* \return the x value of the target point
*/
static inline _iq Interp2d(_iq x00, _iq x01, _iq x10, _iq x11, _iq rowScale, _iq columnScale)
{
return Interp1d(Interp1d(x00, x10, rowScale),
Interp1d(x01, x11, rowScale),
columnScale);
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _INTERP2D_H_ */

View File

@ -0,0 +1,189 @@
/*
* 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.
*/
#ifndef _IQMATH_H_
#define _IQMATH_H_
//! \brief This is the default floating point implementation of IQ math library.
//! Almost all the platforms can use it, but some may come across
//! the performance issue. So use it carefully unless you know what
//! you are doing.
//!
//###########################################################################
#ifndef _USING_CUSTOM_IQMATH_
//###########################################################################
// The default floating point IQ math
//===========================================================================
/*******************************************************************************
* the includes
******************************************************************************/
#include <math.h>
#include <stdlib.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
#define MATH_PI (3.1415926535897932384626433832795f)
#define MATH_2PI (6.283185307179586476925286766559f)
#define MATH_ONE_OVER_THREE (0.3333333333f)
#define MATH_ONE_OVER_SQRT_THREE (0.5773502692f)
#define MATH_SQRT_THREE_OVER_TWO (0.8660254038f)
#define IQMATH_ONE_OVER_THREE (0.3333333333f)
#define IQMATH_ONE_OVER_SQRT_THREE (0.5773502692f)
#define IQMATH_SQRT_THREE_OVER_TWO (0.8660254038f)
/*******************************************************************************
* the typedefs
******************************************************************************/
typedef float _iq;
/*******************************************************************************
* the function prototypes
******************************************************************************/
#define _IQmpy2(A) ((A)*2.0f)
#define _IQmpy4(A) ((A)*4.0f)
#define _IQmpy8(A) ((A)*8.0f)
#define _IQmpy16(A) ((A)*16.0f)
#define _IQmpy32(A) ((A)*32.0f)
#define _IQmpy64(A) ((A)*64.0f)
#define _IQdiv2(A) ((A)*0.5f)
#define _IQdiv4(A) ((A)*0.25f)
#define _IQdiv8(A) ((A)*0.125f)
#define _IQdiv16(A) ((A)*0.0625f)
#define _IQdiv32(A) ((A)*0.03125f)
#define _IQdiv64(A) ((A)*0.015625f)
#define _IQ(A) (A)
#define _IQtoF(A) (A)
//! \note In case for some compiler version, __fmax and __fmin are not defined
//! Add a simple implementation here
#ifndef __fmax
#define __fmax(A, B) (A>B ? A : B)
#endif
#ifndef __fmin
#define __fmin(A, B) (A<B ? A : B)
#endif
#define _IQsat(A, Pos, Neg) (__fmax(((__fmin((A),(Pos)))),(Neg)))
#define _IQtoQ15(A) (int) ((A) * 32768.0f)
#define _IQtoQ14(A) (int) ((A) * 16384.0f)
#define _IQtoQ13(A) (int) ((A) * 8192.0f)
#define _IQtoQ12(A) (int) ((A) * 4096.0f)
#define _IQtoQ11(A) (int) ((A) * 2048.0f)
#define _IQtoQ10(A) (int) ((A) * 1024.0f)
#define _IQtoQ9(A) (int) ((A) * 512.0f)
#define _IQtoQ8(A) (int) ((A) * 256.0f)
#define _IQtoQ7(A) (int) ((A) * 128.0f)
#define _IQtoQ6(A) (int) ((A) * 64.0f)
#define _IQtoQ5(A) (int) ((A) * 32.0f)
#define _IQtoQ4(A) (int) ((A) * 16.0f)
#define _IQtoQ3(A) (int) ((A) * 8.0f)
#define _IQtoQ2(A) (int) ((A) * 4.0f)
#define _IQtoQ1(A) (int) ((A) * 2.0f)
#define _Q15toIQ(A) (((float) (A)) * 0.000030518f)
#define _Q14toIQ(A) (((float) (A)) * 0.000061035f)
#define _Q13toIQ(A) (((float) (A)) * 0.000122070f)
#define _Q12toIQ(A) (((float) (A)) * 0.000244141f)
#define _Q11toIQ(A) (((float) (A)) * 0.000488281f)
#define _Q10toIQ(A) (((float) (A)) * 0.000976563f)
#define _Q9toIQ(A) (((float) (A)) * 0.001953125f)
#define _Q8toIQ(A) (((float) (A)) * 0.003906250f)
#define _Q7toIQ(A) (((float) (A)) * 0.007812500f)
#define _Q6toIQ(A) (((float) (A)) * 0.015625000f)
#define _Q5toIQ(A) (((float) (A)) * 0.031250000f)
#define _Q4toIQ(A) (((float) (A)) * 0.062500000f)
#define _Q3toIQ(A) (((float) (A)) * 0.125000000f)
#define _Q2toIQ(A) (((float) (A)) * 0.250000000f)
#define _Q1toIQ(A) (((float) (A)) * 0.500000000f)
#define _IQmpy(A,B) ((A) * (B))
#define _IQrmpy(A,B) ((A) * (B))
#define _IQrsmpy(A,B) ((A) * (B))
#define _IQdiv(A,B) ((float)(A) / (float)(B))
#define _IQsin(A) sinf(A)
#define _IQsinPU(A) sinf((A)*6.283185307f)
#define _IQasin(A) asinf(A)
#define _IQcos(A) cosf(A)
#define _IQcosPU(A) cosf((A)*6.283185307f)
#define _IQacos(A) acosf(A)
#define _IQatan(A) atanf(A)
#define _IQatan2(A,B) atan2f(A,B)
#define _IQatan2PU(A,B) ((atan2f(A,B)*(1.0f/6.283185307f)) >= 0.0f ? (atan2f(A,B)*(1.0f/6.283185307f)) : (1.0f + (atan2f(A,B)*(1.0f/6.283185307f))))
#define _IQsqrt(A) sqrtf(A)
#define _IQisqrt(A) (1.0f/sqrtf(A))
#define _IQexp(A) expf(A)
#define _IQint(A) ((long) (A))
#define _IQfrac(A) ((A) - (float)((long) (A)))
#define _IQmag(A,B) sqrtf((A)*(A) + (B)*(B))
#define _IQabs(A) fabsf(A)
#define _IQlog(A) logf(A)
#ifdef __cplusplus
}
#endif /* extern "C" */
//###########################################################################
#else
//###########################################################################
// The custom IQ math
//===========================================================================
//! \note It's the user's duty to undefine the macros that are different with ones
//! defined above in the "iqmathcustom.h", which must be put in this folder.
//! \note When building some kind of library and we cannot access the BSW, just create
//! and fake the MCU folder.
//!
#include "iqmathcustom.h"
#endif
#endif /* _IQMATH_H_ */

View File

@ -0,0 +1,237 @@
/*
* 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.
*/
#ifndef _MATRIX_H_
#define _MATRIX_H_
/*! \brief Contains public interface to various functions related
* to the matrix object.
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines the initial parameters for matrix object
*/
typedef struct _MatrixType_
{
_iq *pContainer; /*!< Pointer to the matrix table container */
uint16_t rowNum; /*!< Total row number of the container */
uint16_t columnNum; /*!< Total column number of the container */
} MatrixType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the MATRIX object.
*
* This function initialize the MATRIX object.
*
* \note The container should be the 2-D array
*
* \param[in] obj : pointer to MATRIX instance
* \param[in] pContainer : pointer to the container
* \param[in] rowNum : the row number of the 2-D array
* \param[in] columnNum : the column number of the 2-D array
*/
static inline void Matrix_Init(MatrixType *obj, _iq *pContainer, uint16_t rowNum, uint16_t columnNum)
{
obj->pContainer = pContainer;
obj->rowNum = rowNum;
obj->columnNum = columnNum;
}
/*! \brief Set the value to the MATRIX element.
*
* This function sets the value to the specific position.
*
* \note The row and column start with 0
* The first element is row 0 and column 0
*
* \param[in] obj : pointer to MATRIX instance
* \param[in] value : the value to be set
* \param[in] row : the row index to set value
* \param[in] column : the column index to set value
* \return the result of the operation
* - true : success
* - false : failed
*/
static inline bool Matrix_SetValue(MatrixType *obj, _iq value, uint16_t row, uint16_t column)
{
if(row >= obj->rowNum || column >= obj->columnNum)
{
return false;
}
(*(obj->pContainer + column + row * obj->columnNum)) = value;
return true;
}
/*! \brief Set the "other" matrix to this MATRIX.
*
* This function set the whole matrix values with another matrix
*
* \param[in] obj : pointer to MATRIX instance
* \param[in] other : the pointer to the other matrix
* \return the result of the operation
* - true : success
* - false : failed
*/
static inline bool Matrix_SetMatrix(MatrixType *obj, const MatrixType *other)
{
if(obj->rowNum != other->rowNum || obj->columnNum != other->columnNum)
{
return false;
}
uint16_t i;
uint16_t j;
for(i = 0; i < obj->rowNum; i++)
{
for(j = 0; j < obj->columnNum; j++)
{
(*(obj->pContainer + j + i * obj->columnNum)) = (*(other->pContainer + j + i * obj->columnNum));
}
}
return true;
}
/*! \brief Get the value of the MATRIX element.
*
* This function gets the value of the specific position
*
* \note The row and column start with 0
* The first element is row 0 and column 0
*
* \param[in] obj : pointer to MATRIX instance
* \param[out] pValue : pointer to the output value
* \param[in] row : the row index
* \param[in] column : the column index
* \return the result of the operation
* - true : success
* - false : failed
*/
static inline bool Matrix_GetValue(MatrixType *obj, _iq *pValue, uint16_t row, uint16_t column)
{
if(row >= obj->rowNum || column >= obj->columnNum)
{
return false;
}
*pValue = (*(obj->pContainer + column + row * obj->columnNum));
return true;
}
/*! \brief multiply 2 matrix
*
* This function multiply 2 matrix
*
* \note The formula is S = LR, return false if mismatch, else return true.
*
* \param[in] pL : pointer to the left matrix
* \param[in] pR : pointer to the right matrix
* \param[out] pS : pointer to the product matrix
* \return the result of the operation
* - true : success
* - false : failed
*/
static inline bool Matrix_Multiply(const MatrixType *pL, const MatrixType *pR, MatrixType *pS)
{
uint16_t i;
uint16_t j;
if((pL->columnNum != pR->rowNum) || (pR->columnNum > 1))
{
return false;
}
for(i = 0; i < pL->rowNum; i++)
{
*(pS->pContainer + i) = 0;
for(j = 0; j < pR->rowNum; j++)
{
(*(pS->pContainer + i)) += _IQmpy((*(pL->pContainer + j + i * pR->rowNum)), (*(pR->pContainer + j)));
}
}
return true;
}
/*! \brief Add 2 matrix
*
* This function add 2 matrix.
*
* \note The formula is S = L+R, return false if mismatch, else return true.
*
* \param[in] pL : pointer to the left matrix
* \param[in] pR : pointer to the right matrix
* \param[out] pS : pointer to the sum matrix
* \return the result of the operation
* - true : success
* - false : failed
*/
static inline bool Matrix_Add(MatrixType *pL, MatrixType *pR, MatrixType *pS)
{
uint16_t i;
uint16_t j;
if((pL->columnNum != pR->columnNum) && (pL->rowNum != pR->rowNum))
{
return false;
}
for(i = 0; i < pL->rowNum; i++)
{
for(j = 0; j < pL->columnNum; j++)
{
(*(pS->pContainer + j + i * pL->columnNum))
= (*(pL->pContainer + j + i * pL->columnNum)) + (*(pR->pContainer + j + i * pL->columnNum));
}
}
return true;
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _MATRIX_H_ */

View File

@ -0,0 +1,236 @@
/*
* 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.
*/
#ifndef _MATRIX_F32_H_
#define _MATRIX_F32_H_
/*! \brief Contains public interface to various functions related
* to the matrix object using float32_t.
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines the initial parameters for matrix object
*/
typedef struct _MatrixF32Type_
{
float *pContainer; /*!< Pointer to the matrix table container */
uint16_t rowNum; /*!< Total row number of the container */
uint16_t columnNum; /*!< Total column number of the container */
} MatrixF32Type;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the MATRIX_F32 object.
*
* This function initialize the MATRIX_F32 object.
*
* \note The container should be the 2-D array
*
* \param[in] obj : pointer to Matrix_f32 instance
* \param[in] pContainer : pointer to the container
* \param[in] rowNum : the row number of the 2-D array
* \param[in] columnNum : the column number of the 2-D array
*/
static inline void MatrixF32_Init(MatrixF32Type *obj, float *pContainer, uint16_t rowNum, uint16_t columnNum)
{
obj->pContainer = pContainer;
obj->rowNum = rowNum;
obj->columnNum = columnNum;
}
/*! \brief Set the value to the MATRIX_F32 element.
*
* This function sets the value to the specific position.
*
* \note The row and column start with 0
* The first element is row 0 and column 0
*
* \param[in] obj : pointer to Matrix_f32 instance
* \param[in] value : the value to be set
* \param[in] row : the row index to set value
* \param[in] column : the column index to set value
* \return the result of the operation
* - true : success
* - false : failed
*/
static inline bool MatrixF32_SetValue(MatrixF32Type *obj, float value, uint16_t row, uint16_t column)
{
if(row >= obj->rowNum || column >= obj->columnNum)
{
return false;
}
(*(obj->pContainer + column + row * obj->columnNum)) = value;
return true;
}
/*! \brief Set the "other" matrix to this MATRIX.
*
* This function set the whole matrix values with another matrix
*
* \param[in] obj : pointer to Matrix_f32 instance
* \param[in] other : the pointer to the other matrix
* \return the result of the operation
* - true : success
* - false : failed
*/
static inline bool MatrixF32_SetMatrix(MatrixF32Type *obj, const MatrixF32Type *other)
{
if(obj->rowNum != other->rowNum || obj->columnNum != other->columnNum)
{
return false;
}
uint16_t i;
uint16_t j;
for(i = 0; i < obj->rowNum; i++)
{
for(j = 0; j < obj->columnNum; j++)
{
(*(obj->pContainer + j + i * obj->columnNum)) = (*(other->pContainer + j + i * obj->columnNum));
}
}
return true;
}
/*! \brief Get the value of the MATRIX_F32 element.
*
* This function gets the value of the specific position
*
* \note The row and column start with 0
* The first element is row 0 and column 0
*
* \param[in] obj : pointer to Matrix_f32 instance
* \param[out] pValue : pointer to the output value
* \param[in] row : the row index
* \param[in] column : the column index
* \return the result of the operation
* - true : success
* - false : failed
*/
static inline bool MatrixF32_GetValue(const MatrixF32Type *obj, float *pValue, uint16_t row, uint16_t column)
{
if(row >= obj->rowNum || column >= obj->columnNum)
{
return false;
}
*pValue = (*(obj->pContainer + column + row * obj->columnNum));
return true;
}
/*! \brief multiply 2 matrix
*
* This function multiply 2 matrix
*
* \note The formula is S = LR, return false if mismatch, else return true.
*
* \param[in] pL : pointer to the left matrix
* \param[in] pR : pointer to the right matrix
* \param[out] pS : pointer to the product matrix
* \return the result of the operation
* - true : success
* - false : failed
*/
static inline bool MatrixF32_Multiply(const MatrixF32Type *pL, const MatrixF32Type *pR, MatrixF32Type *pS)
{
uint16_t i;
uint16_t j;
if((pL->columnNum != pR->rowNum) || (pR->columnNum > 1))
{
return false;
}
for(i = 0; i < pL->rowNum; i++)
{
*(pS->pContainer + i) = 0;
for(j = 0; j < pR->rowNum; j++)
{
(*(pS->pContainer + i)) += ((*(pL->pContainer + j + i * pR->rowNum)) * (*(pR->pContainer + j)));
}
}
return true;
}
/*! \brief Add 2 matrix
*
* This function add 2 matrix.
*
* \note The formula is S = L+R, return false if mismatch, else return true.
*
* \param[in] pL : pointer to the left matrix
* \param[in] pR : pointer to the right matrix
* \param[out] pS : pointer to the sum matrix
* \return the result of the operation
* - true : success
* - false : failed
*/
static inline bool MatrixF32_Add(const MatrixF32Type *pL, const MatrixF32Type *pR, MatrixF32Type *pS)
{
uint16_t i;
uint16_t j;
if((pL->columnNum != pR->columnNum) && (pL->rowNum != pR->rowNum))
{
return false;
}
for(i = 0; i < pL->rowNum; i++)
{
for(j = 0; j < pL->columnNum; j++)
{
(*(pS->pContainer + j + i * pL->columnNum))
= (*(pL->pContainer + j + i * pL->columnNum)) + (*(pR->pContainer + j + i * pL->columnNum));
}
}
return true;
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _MATRIX_F32_H_ */

View File

@ -0,0 +1,118 @@
/*
* 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.
*/
#ifndef _IPI_H_
#define _IPI_H_
/*! \brief Contains public interface to various functions related
* to the Incremental PI (IPI) object.
* \note The form of this PID is parallel.
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
typedef struct _IpiType_
{
_iq ref; /*!< Input: Reference input */
_iq fdb; /*!< Input: Feedback input */
_iq Kp; /*!< Parameter: Proportional gain */
_iq Ki; /*!< Parameter: Integral gain */
_iq lastError; /*!< Internal Variable: last error */
_iq delta; /*!< Output: The output of increment value */
} IpiType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the IPI object
*
* This function intialize the IPI object
*
* \param[in] obj : pointer to IPI instance
* \param[in] Kp : Kp value in IQ format
* \param[in] Ki : Ki value in IQ format
*/
static inline void Ipi_Init(IpiType *obj, _iq Kp, _iq Ki)
{
obj->ref = 0;
obj->fdb = 0;
obj->delta = 0;
obj->Kp = Kp;
obj->Ki = Ki;
obj->lastError = 0;
}
/*! \brief Run the IPI control
*
* This function run the IPI calculation
*
* \param[in] obj : pointer to IPI instance
*/
static inline void Ipi_Run(IpiType *obj)
{
/* Compute the error */
_iq error = obj->ref - obj->fdb;
/* Compute the proportional output */
_iq Up = _IQmpy(obj->Kp, error - obj->lastError);
/* Compute the integral output */
_iq Ui = _IQmpy(obj->Ki, error);
/* Remember error for next time */
obj->lastError = error;
/* Assign the output */
obj->delta = Up + Ui;
}
/*! \brief Reset the IPI variables
*
* This function reset the IPI instance to the initial state
*
* \param[in] obj : pointer to IPI instance
*/
static inline void Ipi_Reset(IpiType *obj)
{
obj->lastError = 0;
obj->delta = 0;
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _IPI_H_ */

View File

@ -0,0 +1,165 @@
/*
* 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.
*/
#ifndef _PID_H_
#define _PID_H_
/*! \brief Contains public interface to various functions related
* to the PID object.
* \note The form of this PID is parallel.
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Declaration of PID object
*/
typedef struct _PidType_
{
_iq ref; /*!< Input: Reference input */
_iq fdb; /*!< Input: Feedback input */
_iq Kp; /*!< Parameter: Proportional gain */
_iq Ki; /*!< Parameter: Integral gain */
_iq Kd; /*!< Parameter: Derivative gain */
_iq outMax; /*!< Parameter: Maximum output */
_iq outMin; /*!< Parameter: Minimum output */
_iq Ui; /*!< Internal Variable: Integral output */
_iq lastError; /*!< Internal Variable: last error */
_iq output; /*!< Output: PID output */
} PidType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the PID object
*
* This function initializes the PID instance
*
* \param[in] obj : pointer to Pid instance
* \param[in] Kp : the Kp value in IQ format
* \param[in] Ki : the Ki value in IQ format
* \param[in] Kd : the Kd value in IQ format
* \param[in] min : the min value allowed in output
* \param[in] max : the max value allowed in output
*/
static inline void Pid_Init(PidType *obj, _iq Kp, _iq Ki, _iq Kd, _iq min, _iq max)
{
obj->Kp = Kp;
obj->Ki = Ki;
obj->Kd = Kd;
obj->outMin = min;
obj->outMax = max;
obj->ref = 0;
obj->fdb = 0;
obj->Ui = 0;
obj->lastError = 0;
obj->output = 0;
}
/*! \brief Run the PID control
*
* This fucntion runs the PID control
*
* \note The form of this PID is parallel
*
* \param[in] obj : pointer to Pid instance
*/
static inline void Pid_Run(PidType *obj)
{
/* Compute the error */
_iq error = obj->ref - obj->fdb;
/* Compute the proportional output */
_iq Up = _IQmpy(obj->Kp, error);
/* Compute the integral output */
obj->Ui = obj->Ui + _IQmpy(obj->Ki, error);
/* Saturate Ui */
if(obj->Ui > obj->outMax)
{
obj->Ui = obj->outMax;
}
if(obj->Ui < obj->outMin)
{
obj->Ui = obj->outMin;
}
/* Compute the derivative output */
_iq Ud = _IQmpy(obj->Kd, (error - obj->lastError));
obj->lastError = error;
/* Compute the pre-saturated output */
_iq tmpOutput = Up + obj->Ui + Ud;
/* Saturate the output */
if(tmpOutput > obj->outMax)
{
obj->output = obj->outMax;
}
else if(tmpOutput < obj->outMin)
{
obj->output = obj->outMin;
}
else
{
obj->output = tmpOutput;
}
}
/*! \brief Reset the PID variables
*
* This function reset the PID to initial state
*
* \note The form of this PID is parallel
*
* \param[in] obj : pointer to Pid instance
*/
static inline void Pid_Reset(PidType *obj)
{
obj->lastError = 0;
obj->output = 0;
obj->Ui = 0;
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _PID_H_ */

View File

@ -0,0 +1,154 @@
/*
* 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.
*/
#ifndef _SMC_H_
#define _SMC_H_
/*! \brief Contains public interface to various functions related
* to the Sliding Mode Control (SMC) object.
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines all the parameters used to initialize SMC object
* \note We use 2 coefficients to determine the current output:
*
* accumulator(k) = coeff1 * accumulator(k-1) + coeff2 * Z(k)
*
* If coeff1 + coeff2 = 1, this will act like a normal LPF
* whose gain will be 1. But sometimes we need this algorithm's
* gain NOT equal to 1. So 2 coefficients are put here for the
* user to set freely.
*/
typedef struct _Smc_ParamsType_
{
float Kslide; /*!< The gain of the sliding mode */
float maxError; /*!< The max error of input */
float coeff1; /*!< The coefficient of last output */
float coeff2; /*!< The coefficient of bang-bang control value */
} Smc_ParamsType;
/*! \brief Declaration of SMC object
*/
typedef struct _SmcType_
{
_iq error; /*!< Input: Reference input */
_iq Kslide; /*!< Parameter: The gain of the sliding mode */
_iq maxError; /*!< Parameter: The max error of input */
_iq gain; /*!< Parameter: The max error of input */
_iq coeff1; /*!< Parameter: The coefficient of last output */
_iq coeff2; /*!< Parameter: The coefficient of bang-bang control value */
_iq accum; /*!< Internal variable: The accumulator of bang-bang control value */
_iq output; /*!< Output: The output of the sliding-mode control */
} SmcType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the SMC object
*
* This function initialize the SMC instance
*
* \param[in] obj : pointer to Smc instance
* \param[in] pParams :
*/
static inline void Smc_Init(SmcType *obj, const Smc_ParamsType *pParams)
{
/* Initialize all parameters */
obj->Kslide = _IQ(pParams->Kslide);
obj->maxError = _IQ(pParams->maxError);
obj->gain = _IQdiv(obj->Kslide, obj->maxError);
obj->coeff1 = _IQ(pParams->coeff1);
obj->coeff2 = _IQ(pParams->coeff2);
/* Initialize all internal variables */
obj->accum = 0;
/* Reset the outputs */
obj->output = 0;
}
/*! \brief Run the SMC control
*
* This function run the SMC algorithm.
*
* \param[in] obj : pointer to Smc instance
*/
static inline void Smc_Run(SmcType *obj)
{
/* Bang-bang control with linear treatment around zero */
_iq Z;
if(_IQabs(obj->error) < obj->maxError)
{
Z = _IQmpy(obj->gain, obj->error);
}
else if(obj->error > 0)
{
Z = obj->Kslide;
}
else
{
Z = -obj->Kslide;
}
/* Filter the bang-bang control value */
obj->accum = _IQmpy(obj->accum, obj->coeff1) + _IQmpy(Z, obj->coeff2);
/* Put together the final output */
obj->output = obj->accum + Z;
}
/*! \brief Reset the SMC variables
*
* This function reset the SMC instance to the initial state.
*
* \param[in] obj : pointer to Smc instance
*/
static inline void Smc_Reset(SmcType *obj)
{
obj->accum = 0;
obj->output = 0;
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _SMC_H_ */

View File

@ -0,0 +1,128 @@
/*
* 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.
*/
#ifndef _COMPARE_H_
#define _COMPARE_H_
/*! \brief Contains public interface to various functions related
* to the compare object
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
#define FLOAT_EQUAL_DEADBAND (0.0001)
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief The greater than (>) comparison
*
* This function do the greater comparison between 2 IQ value
*
* \param[in] A : value A in IQ format
* \param[in] B : value B in IQ format
*/
static inline bool Compare_GreaterThan(_iq A, _iq B)
{
return A > B;
}
/*! \brief The smaller than (<) comparison
*
* This function do the smaller comparison between 2 IQ value
*
* \param[in] A : value A in IQ format
* \param[in] B : value B in IQ format
*/
static inline bool Compare_SmallerThan(_iq A, _iq B)
{
return A < B;
}
/*! \brief The greater than or equal (>=) comparison
*
* This function do the greater than or equal (>=) comparison between 2 IQ value
*
* \param[in] A : value A in IQ format
* \param[in] B : value B in IQ format
*/
static inline bool Compare_GreaterOrEqual(_iq A, _iq B)
{
return A >= B;
}
/*! \brief The smaller than or equal (<=) comparison
*
* This function do the smaller than or equal (<=) comparison between 2 IQ value
*
* \param[in] A : value A in IQ format
* \param[in] B : value B in IQ format
*/
static inline bool Compare_SmallerOrEqual(_iq A, _iq B)
{
return A <= B;
}
/*! \brief The equal (==) comparison
*
* This function do the equal (==) comparison between 2 IQ value
*
* \note If the IQ is floating value, it's not the exact equal because of the precision
* of floating value.
*
* \param[in] A : value A in IQ format
* \param[in] B : value B in IQ format
*/
static inline bool Compare_Equal(_iq A, _iq B)
{
if((long)_IQ(0.1))
{ /* Fix-point IQ math */
return (A == B);
}
else
{
return (_IQabs(A - B) < _IQ(FLOAT_EQUAL_DEADBAND));
}
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _COMPARE_H_ */

View File

@ -0,0 +1,139 @@
/*
* 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.
*/
#ifndef _SORT_H_
#define _SORT_H_
/*! \brief Contains public interface to various functions related
* to the sort algorithms
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Return the max value in an array
*
* This function returns the max value in an array
*
* \param[in] array[] : the array to search
* \param[in] len : the length of the array
*/
static inline _iq MaxInArray(const _iq array[], uint16_t len)
{
_iq retval = array[0];
uint16_t i = 0;
for(i = 0; i < len; i++)
{
if(array[i] > retval)
{
retval = array[i];
}
}
return retval;
}
/*! \brief Return the minimum value in an array
*
* This function returns the minimun value in an array
*
* \param[in] array[] : the array to search
* \param[in] len : the length of the array
*/
static inline _iq MinInArray(const _iq array[], uint16_t len)
{
_iq retval = array[0];
uint16_t i = 0;
for(i = 0; i < len; i++)
{
if(array[i] < retval)
{
retval = array[i];
}
}
return retval;
}
/*! \brief Return the max absolute value in an array
*
* This function returns the max absolute value in an array
*
* \param[in] array[] : the array to search
* \param[in] len : the length of the array
*/
static inline _iq MaxAbsInArray(const _iq array[], uint16_t len)
{
_iq retval = _IQabs(array[0]);
uint16_t i = 0;
for(i = 0; i < len; i++)
{
if(_IQabs(array[i]) > retval)
{
retval = _IQabs(array[i]);
}
}
return retval;
}
/*! \brief Return the minimum absolute value in an array
*
* This function returns the minimum absolute value in an array
*
* \param[in] array[] : the array to search
* \param[in] len : the length of the array
*/
static inline _iq MinAbsInArray(const _iq array[], uint16_t len)
{
_iq retval = _IQabs(array[0]);
uint16_t i = 0;
for(i = 0; i < len; i++)
{
if(_IQabs(array[i]) < retval)
{
retval = _IQabs(array[i]);
}
}
return retval;
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _SORT_H_ */

View File

@ -0,0 +1,147 @@
/*
* 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.
*/
#ifndef _STIMER_H_
#define _STIMER_H_
/*! \brief Contains public interface to various functions related
* to the Software Timer (STIMER) object.
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Declaration of STIMER object
*/
typedef struct _StimerType_
{
uint32_t counter; /*!< The counter register */
uint32_t period; /*!< The period, time out will occur when count reach period */
bool enable; /*!< Whether the timer is started */
bool overflow; /*!< Whether the timer is overflow */
} StimerType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief The constructor of the timer object
*
* This function initialize the Stimer object
*
* \param[in] obj : pointer to Stimer instance
*/
static inline void Stimer_Init(StimerType *obj)
{
obj->counter = 0;
obj->period = 0;
obj->enable = false;
obj->overflow = false;
}
/*! \brief Start the timer for the period, this is one shot
*
* This function start the timer. This is one-shot.
*
* \note The real time is based on the time base running Ticker()
* \note Call this function if already started will restart the timer
*
* \param[in] obj : pointer to Stimer instance
* \param[in] period : the period value
*/
static inline void Stimer_Start(StimerType *obj, uint32_t period)
{
obj->counter = 0;
obj->period = period;
obj->enable = true;
obj->overflow = false;
}
/*! \brief The time base of the timer object
*
* This function provide the real time base of the stimer instance.
*
* \param[in] obj : pointer to Stimer instance
*/
static inline void Stimer_Tick(StimerType *obj)
{
if(obj->enable && obj->overflow == false)
{
if(obj->counter < obj->period)
{
obj->counter++;
if(obj->counter == obj->period)
{
obj->overflow = true;
}
}
}
}
/*! \brief Whether timeout
*
* This function returns whether it's timeout
*
* \param[in] obj : pointer to Stimer instance
* \return Whether it's timeout
* - true : the timer is time-out
* - false : the timer is not time-out
*/
static inline bool Stimer_Timeout(const StimerType *obj)
{
return obj->overflow;
}
/*! \brief Whether it's started
*
* This function returns whether the Timer instance is started
*
* \param[in] obj : pointer to Stimer instance
* \return Whether it's started
* - true : the timer is started
* - false : the timer is not started
*/
static inline bool Stimer_IsActive(StimerType *obj)
{
return obj->enable;
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _STIMER_H_ */

View File

@ -0,0 +1,189 @@
/*
* 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.
*/
#ifndef _TRIGGER_H_
#define _TRIGGER_H_
/*! \brief Contains public interface to various functions related
* to the Trigger object
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "common/iqmath/iqmath.h"
#include "common/sort/compare.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief The definition of Compare mode
*/
typedef enum
{
TRIGGER_COMPTYPE_OVER,
TRIGGER_COMPTYPE_UNDER,
} Trigger_CompModeType;
/*! \brief The definition of parameters of Trigger class
*/
typedef struct _Trigger_ParamsType_
{
Trigger_CompModeType compType;
_iq threshold;
_iq recoverValue;
uint16_t trigCntMax;
uint16_t recoverCntMax;
bool isRecoverable;
} Trigger_ParamsType;
/*! \brief The definition of Trigger prototype
*/
typedef struct _TriggerType_
{
_iq input; /*!< Input: The input for scan */
_iq threshold; /*!< Parameter: The threshold for compare */
_iq recoverValue; /*!< Parameter: The recover value that will reverse trigger */
uint16_t trigCntMax; /*!< Parameter: The max counts for the compare */
uint16_t recoverCntMax; /*!< Parameter: The max counts for the recover */
bool isRecoverable; /*!< Parameter: Whether the trigger can be recovered */
uint16_t trigCnt; /*!< Internal Variable: The count for the compare */
uint16_t recoverCnt; /*!< Internal Variable: The count for the recover */
bool (*comp)(_iq, _iq); /*!< Internal Variable: The compare function pointer */
bool (*recover)(_iq, _iq); /*!< Internal Variable: The recover function pointer */
bool compSatisfied; /*!< Output: Whether compare satisfied without debounce */
bool isTriggered; /*!< Output: Whether it's triggered based on compare and debounce */
} TriggerType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief The initialization of Trigger
*
* This function initializes the trigger instance
*
* \param[in] obj : pointer to Trigger instance
* \param[in] pParams : pointer to the parameters
*/
static inline void Trigger_Init(TriggerType *obj, const Trigger_ParamsType *pParams)
{
obj->trigCntMax = pParams->trigCntMax;
obj->recoverCntMax = pParams->recoverCntMax;
obj->threshold = pParams->threshold;
obj->recoverValue = pParams->recoverValue;
obj->isRecoverable = pParams->isRecoverable;
if(pParams->compType == TRIGGER_COMPTYPE_OVER)
{
obj->comp = Compare_GreaterThan;
obj->recover = Compare_SmallerThan;
}
else if(pParams->compType == TRIGGER_COMPTYPE_UNDER)
{
obj->comp = Compare_SmallerThan;
obj->recover = Compare_GreaterThan;
}
obj->trigCnt = 0;
obj->recoverCnt = 0;
obj->compSatisfied = false;
obj->isTriggered = false;
}
/*! \brief Run the trigger algorithm
*
* This function runs the trigger algorithm
*
* \param[in] obj : pointer to Trigger instance
*/
static inline void Trigger_Run(TriggerType *obj)
{
if(obj->comp(obj->input, obj->threshold))
{
obj->compSatisfied = true;
obj->recoverCnt = 0;
if(obj->trigCnt < obj->trigCntMax)
{
obj->trigCnt++;
}
if(obj->trigCnt >= obj->trigCntMax)
{
obj->isTriggered = true;
}
}
else
{
obj->compSatisfied = false;
obj->trigCnt = 0;
if(obj->isRecoverable)
{
if(obj->recover(obj->input, obj->recoverValue))
{
if(obj->recoverCnt < obj->recoverCntMax)
{
obj->recoverCnt++;
}
if(obj->recoverCnt >= obj->recoverCntMax)
{
obj->isTriggered = false;
}
}
else
{
obj->recoverCnt = 0;
}
}
}
}
/*! \brief Reset the trigger instance
*
* This function reset the trigger to the initial state
*
* \param[in] obj : pointer to Trigger instance
*/
static inline void Trigger_Reset(TriggerType *obj)
{
obj->trigCnt = 0;
obj->recoverCnt = 0;
obj->compSatisfied = false;
obj->isTriggered = false;
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _TRIGGER_H_ */

View File

@ -0,0 +1,164 @@
/*
* 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 "dbc_comm.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void DbcComm_Init(DbcCommType *obj, const DbcComm_ParamsType *pParams)
{
uint8_t node = 0;
for(node = 0; node < DBCCOMM_NODE_NUM; ++node)
{
obj->enableNodeTx[node] = false;
obj->enableNodeRx[node] = false;
}
obj->sendCanMsg = pParams->sendCanMsg;
uint16_t i = 0;
/* Process send message */
for(i = 0; i < obj->txMsgNum; ++i)
{
obj->txMsgArray[i].periodCntMax = (uint32_t)(pParams->runFreq_kHz * obj->txMsgArray[i].pInfo->period_ms);
obj->txMsgArray[i].periodCnt = i; /* Stagger the start timing */
}
/* Process received message */
for(i = 0; i < obj->rxMsgNum; ++i)
{
obj->rxMsgArray[i].timeoutCntMax = (uint32_t)(pParams->runFreq_kHz * obj->rxMsgArray[i].pInfo->timeout_ms);
obj->rxMsgArray[i].timeoutCnt = 0;
obj->rxMsgArray[i].isTimeout = false;
}
}
void DbcComm_Run(DbcCommType *obj)
{
uint16_t i = 0;
/* Process send message */
for(i = 0; i < obj->txMsgNum; ++i)
{
DbcComm_CanNodeType node = obj->txMsgArray[i].pInfo->node;
if(obj->enableNodeTx[node])
{
if(obj->txMsgArray[i].periodCntMax > 0)
{
obj->txMsgArray[i].periodCnt++;
if(obj->txMsgArray[i].periodCnt >= obj->txMsgArray[i].periodCntMax)
{
obj->txMsgArray[i].periodCnt = 0;
/* Pack message and send it */
DbcComm_CanMsgType msg = CAN_MSG_DEFAULT;
obj->txMsgArray[i].pInfo->packMsg(obj, &msg);
obj->sendCanMsg(node, &msg);
}
}
}
}
/* Process received message */
for(i = 0; i < obj->rxMsgNum; ++i)
{
DbcComm_CanNodeType node = obj->rxMsgArray[i].pInfo->node;
if(obj->enableNodeRx[node])
{
if(obj->rxMsgArray[i].timeoutCntMax > 0 && false == obj->rxMsgArray[i].isTimeout)
{
obj->rxMsgArray[i].timeoutCnt++;
if(obj->rxMsgArray[i].timeoutCnt >= obj->rxMsgArray[i].timeoutCntMax)
{
obj->rxMsgArray[i].timeoutCnt = 0;
obj->rxMsgArray[i].isTimeout = true;
}
}
}
}
}
void DbcComm_ReceiveCanMsg(DbcCommType *obj, DbcComm_CanNodeType node, const DbcComm_CanMsgType *pMsg)
{
uint16_t i = 0;
for(i = 0; i < obj->rxMsgNum; ++i)
{
if(pMsg->id == obj->rxMsgArray[i].pInfo->id && node == obj->rxMsgArray[i].pInfo->node)
{
obj->rxMsgArray[i].timeoutCnt = 0;
obj->rxMsgArray[i].isTimeout = false;
obj->rxMsgArray[i].pInfo->unpackMsg(obj, pMsg);
break;
}
}
}
void DbcComm_EnableRx(DbcCommType *obj, DbcComm_CanNodeType node, bool enable)
{
if(obj->enableNodeRx[node] != enable)
{
/* Change the enable status */
uint16_t i = 0;
for(i = 0; i < obj->rxMsgNum; ++i)
{
if(obj->rxMsgArray[i].pInfo->node == node)
{
if(obj->rxMsgArray[i].timeoutCntMax > 0)
{
obj->rxMsgArray[i].timeoutCnt = 0;
obj->rxMsgArray[i].isTimeout = false;
}
}
}
obj->enableNodeRx[node] = enable;
}
}
void DbcComm_EnableTx(DbcCommType *obj, DbcComm_CanNodeType node, bool enable)
{
if(obj->enableNodeTx[node] != enable)
{
/* Change the enable status */
uint16_t i = 0;
for(i = 0; i < obj->txMsgNum; ++i)
{
if(obj->txMsgArray[i].pInfo->node == node)
{
if(obj->txMsgArray[i].periodCntMax > 0)
{
obj->txMsgArray[i].periodCnt = obj->txMsgArray[i].periodCntMax;
}
}
}
obj->enableNodeTx[node] = enable;
}
}

View File

@ -0,0 +1,239 @@
/*
* 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.
*/
#ifndef _DBC_COMM_H_
#define _DBC_COMM_H_
/*! \brief Contains public interface to various functions related
* to the CAN communication using the CAN dbc file
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*! \brief The default value used for initialization
*/
#define CAN_MSG_DEFAULT { \
404, \
{0, 0, 0, 0, 0, 0, 0, 0}, \
8, \
0, \
0 \
}
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief CAN message type definition
*
* The identifier field may have 11 bits for standard frames
* (CAN specification 2.0A) or 29 bits for extended frames
* (CAN specification 2.0B).
*/
typedef struct _DbcComm_CanMsgType_
{
uint32_t id; /*!< the CAN ID, 11 bits for standard frames (CAN SPEC 2.0A) or 29 bits for extended frames (CAN SPEC 2.0B) */
uint8_t data[8]; /*!< The data field has up to 8 bytes (64 bit) of message data */
uint8_t length; /*!< The data length code denotes the number of data bytes, 0 to 8 (bytes) */
uint8_t extended; /*!< Extended Frame if set to 1, else Standard Frame. */
uint8_t remote; /*!< Remote Frame if set to 1, else Data Frame. */
} DbcComm_CanMsgType;
/*! \brief Defines all the CAN node
*/
typedef enum
{
DBCCOMM_NODE_0 = 0,
DBCCOMM_NODE_1,
DBCCOMM_NODE_2,
DBCCOMM_NODE_3,
DBCCOMM_NODE_4,
DBCCOMM_NODE_5,
DBCCOMM_NODE_6,
DBCCOMM_NODE_7,
DBCCOMM_NODE_8,
DBCCOMM_NODE_NUM
} DbcComm_CanNodeType;
/*! \brief Forward declaration of DBCCOMM class
*/
struct _DbcCommType_;
/*! \brief Tx message information
*/
typedef struct _DbcComm_TxMsgInfoType_
{
DbcComm_CanNodeType node; /*!< the node for this message */
uint32_t id; /*!< the CAN id of this message */
float period_ms; /*!< Period for transmit messages, 0 for single-shot */
void (*packMsg)(struct _DbcCommType_ *obj, DbcComm_CanMsgType *pMsg); /*!< pointer to the function to pack this message */
} DbcComm_TxMsgInfoType;
/*! \brief Rx message information
*/
typedef struct _DbcComm_RxMsgInfoType_
{
DbcComm_CanNodeType node; /*!< the node for this message */
uint32_t id; /*!< the CAN id of this message */
float timeout_ms; /*!< Time out threshold for receive messages, 0 for single-shot */
void (*unpackMsg)(struct _DbcCommType_ *obj, const DbcComm_CanMsgType *pMsg); /*!< pointer to the function to unpack this message */
} DbcComm_RxMsgInfoType;
/*! \brief Tx message definition
*/
typedef struct _DbcComm_TxMsgType_
{
uint32_t periodCntMax; /*!< the period count max value, determined by period*/
uint32_t periodCnt; /*!< the period counter */
const DbcComm_TxMsgInfoType *pInfo; /*!< the informatin of TX message */
} DbcComm_TxMsgType;
/*! \brief Rx message definition
*/
typedef struct _DbcComm_RxMsgType_
{
uint16_t timeoutCntMax; /*!< the counter max value, determined by timeout period */
uint16_t timeoutCnt; /*!< the timeout counter */
bool isTimeout; /*!< whether is timeout */
const DbcComm_RxMsgInfoType *pInfo; /*!< the informatin of RX message */
} DbcComm_RxMsgType;
/*! \brief The adapter of CAN send implementation
*/
typedef void (*DbcComm_SendCanMsgShimType)(DbcComm_CanNodeType node, const DbcComm_CanMsgType *pMsg);
/*! \brief Type definition of TX message array
*/
typedef DbcComm_TxMsgType *DbcComm_TxMsgArray;
/*! \brief Type definition of RX message array
*/
typedef DbcComm_RxMsgType *DbcComm_RxMsgArray;
/*! \brief Defines all the parameters used to initialize power CAN communication object
*/
typedef struct _DbcComm_ParamsType_
{
float runFreq_kHz; /*!< Frequency to run this module */
DbcComm_SendCanMsgShimType sendCanMsg; /*!< function to implement CAN send */
} DbcComm_ParamsType;
/*! \brief Defines all the inputs for DBCCOMM object
*/
struct _DbcComm_InputsType_;
typedef struct _DbcComm_InputsType_ DbcComm_InputsType;
/*! \brief Defines all the outputs for DBCCOMM object
*/
struct _DbcComm_OutputsType_;
typedef struct _DbcComm_OutputsType_ DbcComm_OutputsType;
/*! \brief Defines the DBCCOMM object
*/
typedef struct _DbcCommType_
{
bool enableNodeTx[DBCCOMM_NODE_NUM]; /*!< TX enable flag for all nodes */
bool enableNodeRx[DBCCOMM_NODE_NUM]; /*!< RX enalbe flag for all nodes */
DbcComm_TxMsgArray txMsgArray; /*!< TX message array */
DbcComm_RxMsgArray rxMsgArray; /*!< RX message array */
uint16_t txMsgNum; /*!< Total TX message number */
uint16_t rxMsgNum; /*!< Total RX message number */
DbcComm_InputsType *pInputs; /*!< pointer to the inputs */
DbcComm_OutputsType *pOutputs; /*!< pointer to the outputs */
DbcComm_SendCanMsgShimType sendCanMsg; /*!< function to implement CAN send */
} DbcCommType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the DBCCOMM object
*
* This function initialize the DbcComm object using the given parameters
*
* \param[in] obj : pointer to DbcComm instance
* \param[in] pParams :
*/
extern void DbcComm_Init(DbcCommType *obj, const DbcComm_ParamsType *pParams);
/*! \brief Run the DBCCOMM
*
* This function process the DbcComm main logic
*
* \param[in] obj : pointer to DbcComm instance
*/
extern void DbcComm_Run(DbcCommType *obj);
/*! \brief Receive the can message
*
* This function receive the can message for dbc logic to analyze.
*
* \note IMPORTANT!!! This interface should be called in the same thread as DbcComm_Run
*
* \param[in] obj : pointer to DbcComm instance
* \param[in] node : the CAN node to receive the message
* \param[in] pMsg : the pointer to the message to receive
*/
extern void DbcComm_ReceiveCanMsg(DbcCommType *obj, DbcComm_CanNodeType node, const DbcComm_CanMsgType *pMsg);
/*! \brief Enable/Disable RX of the node
*
* This function enables or disables the RX of the given node
*
* \param[in] obj : pointer to DbcComm instance
* \param[in] node : the node to operate
* \param[in] enable : whether to enable or disable the RX function
* - true : enable the RX
* - false : disable the RX
*/
extern void DbcComm_EnableRx(DbcCommType *obj, DbcComm_CanNodeType node, bool enable);
/*! \brief Enable/Disable TX of the node
*
* This function enables or disables the TX of the given node
*
* \param[in] obj : pointer to DbcComm instance
* \param[in] node : the node to operate
* \param[in] enable : whether to enable or disable the TX function
* - true : enable the TX
* - false : disable the TX
*/
extern void DbcComm_EnableTx(DbcCommType *obj, DbcComm_CanNodeType node, bool enable);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _DBC_COMM_H_ */

View File

@ -0,0 +1,842 @@
/*
* 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 <stddef.h>
#include "isotp.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*! \brief Protocol Control Information (PCI) types, for identifying each frame of an ISO-TP message.
*/
#define ISOTP_PCI_TYPE_SINGLE_FRAME (0x0)
#define ISOTP_PCI_TYPE_FIRST_FRAME (0x1)
#define ISOTP_PCI_TYPE_CONSECUTIVE_FRAME (0x2)
#define ISOTP_PCI_TYPE_FLOW_CONTROL_FRAME (0x3)
/*! \brief Protocol Control Information (PCI) flow control identifiers.
*/
#define ISOTP_PCI_FLOW_STATUS_CONTINUE (0x0)
#define ISOTP_PCI_FLOW_STATUS_WAIT (0x1)
#define ISOTP_PCI_FLOW_STATUS_OVERFLOW (0x2)
/* invalid bs */
#define ISOTP_INVALID_BS 0xFFFF
/*! \brief Network layer result code
*/
#define ISOTP_PROTOCOL_RESULT_OK (0)
#define ISOTP_PROTOCOL_RESULT_TIMEOUT_A (-1)
#define ISOTP_PROTOCOL_RESULT_TIMEOUT_BS (-2)
#define ISOTP_PROTOCOL_RESULT_TIMEOUT_CR (-3)
#define ISOTP_PROTOCOL_RESULT_WRONG_SN (-4)
#define ISOTP_PROTOCOL_RESULT_INVALID_FS (-5)
#define ISOTP_PROTOCOL_RESULT_UNEXP_PDU (-6)
#define ISOTP_PROTOCOL_RESULT_WFT_OVRN (-7)
#define ISOTP_PROTOCOL_RESULT_BUFFER_OVFLW (-8)
#define ISOTP_PROTOCOL_RESULT_ERROR (-9)
/*! \brief Return logic true if 'a' is after 'b'
*/
#define IsoTp_TimeAfter(a, b) ((int64_t)((int64_t)(b) - (int64_t)(a)) < 0)
#define IsoTp_SetPciType(byte, type) (byte[0] = (0xFF & ((((uint8_t)type) << 4) | 0x0f)))
#define IsoTp_GetPciType(byte) ((uint8_t)(byte[0] >> 4))
/*! \brief single frame
* +-------------------------+-----+
* | byte #0 | ... |
* +-------------------------+-----+
* | nibble #0 | nibble #1 | ... |
* +-------------+-----------+ ... +
* | PCIType = 0 | SF_DL | ... |
* +-------------+-----------+-----+
*/
#define IsoTp_SetSFDataLen(byte, len) (byte[0] &= (((uint8_t)len) | 0xf0))
#define IsoTp_GetSFDataLen(byte) (byte[0] & 0x0f)
/*! \brief first frame
* +-------------------------+-----------------------+-----+
* | byte #0 | byte #1 | ... |
* +-------------------------+-----------+-----------+-----+
* | nibble #0 | nibble #1 | nibble #2 | nibble #3 | ... |
* +-------------+-----------+-----------+-----------+-----+
* | PCIType = 1 | FF_DL | ... |
* +-------------+-----------+-----------------------+-----+
*/
#define IsoTp_SetFFDataLen(byte, len) \
do \
{ \
byte[0] &= ((len >> 8) | 0xf0); \
byte[1] = (len & 0xff); \
} while(0)
#define IsoTp_GetFFDataLen(byte) (((((uint16_t)byte[0]) & 0x0f) << 8) + byte[1])
/*! \brief consecutive frame
* +-------------------------+-----+
* | byte #0 | ... |
* +-------------------------+-----+
* | nibble #0 | nibble #1 | ... |
* +-------------+-----------+ ... +
* | PCIType = 2 | SN | ... |
* +-------------+-----------+-----+
*/
#define IsoTp_SetCFSn(byte, sn) (byte[0] &= (((uint8_t)sn) | 0xf0))
#define IsoTp_GetCFSn(byte) (byte[0] & 0x0f)
/*! \brief flow control frame
* +-------------------------+-----------------------+-----------------------+-----+
* | byte #0 | byte #1 | byte #2 | ... |
* +-------------------------+-----------+-----------+-----------+-----------+-----+
* | nibble #0 | nibble #1 | nibble #2 | nibble #3 | nibble #4 | nibble #5 | ... |
* +-------------+-----------+-----------+-----------+-----------+-----------+-----+
* | PCIType = 1 | FS | BS | STmin | ... |
* +-------------+-----------+-----------------------+-----------------------+-----+
*/
#define IsoTp_SetFCFlowState(byte, fs) (byte[0] &= (((uint8_t)fs) | 0xf0))
#define IsoTp_GetFCFlowState(byte) (byte[0] & 0x0f)
#define IsoTp_SetFCBlockSize(byte, bs) (byte[1] = bs)
#define IsoTp_GetFCBlockSize(byte) (byte[1])
#define IsoTp_SetFCStmin(byte, STmin) (byte[2] = STmin)
#define IsoTp_GetFCStmin(byte) (byte[2])
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief ISOTP sender status
*/
typedef enum
{
ISOTP_SEND_STATUS_IDLE,
ISOTP_SEND_STATUS_INPROGRESS,
ISOTP_SEND_STATUS_ERROR,
} IsoTp_SendStatusType;
/*! \brief ISOTP receiver status
*/
typedef enum
{
ISOTP_RECEIVE_STATUS_IDLE,
ISOTP_RECEIVE_STATUS_INPROGRESS,
ISOTP_RECEIVE_STATUS_FULL,
} IsoTp_ReceiveStatusType;
/*! \brief ISOTP message
*/
typedef struct _IsoTp_MsgType_
{
uint8_t byte[8];
} IsoTp_MsgType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
/* st_min to microsecond */
static uint8_t IsoTp_MsToStMin(uint8_t ms)
{
uint8_t stMin;
stMin = ms;
if(stMin > 0x7F)
{
stMin = 0x7F;
}
return stMin;
}
/* st_min to msec */
static uint8_t IsoTp_StMinToMs(uint8_t stMin)
{
uint8_t ms;
if(stMin >= 0xF1 && stMin <= 0xF9)
{
ms = 1; /* Actually it should be 0.1 - 0.9 ms */
}
else if(stMin <= 0x7F)
{
ms = stMin;
}
else
{
ms = 0;
}
return ms;
}
static int8_t IsoTp_SendFlowControl(IsoTpType *obj, uint8_t flow_status, uint8_t block_size, uint8_t st_min_ms)
{
int8_t ret;
uint8_t index = 0;
IsoTp_MsgType msg;
/* Setup message */
IsoTp_SetPciType(msg.byte, ISOTP_PCI_TYPE_FLOW_CONTROL_FRAME);
IsoTp_SetFCFlowState(msg.byte, flow_status);
IsoTp_SetFCBlockSize(msg.byte, block_size);
IsoTp_SetFCStmin(msg.byte, IsoTp_MsToStMin(st_min_ms));
/* Send message */
if(obj->framePadding)
{
/* All pad with 0 */
for(index = 3; index < 8; ++index)
{
msg.byte[index] = 0;
}
ret = obj->sendCanMsg(obj->sendArbitrationId, msg.byte, 8);
}
else
{
ret = obj->sendCanMsg(obj->sendArbitrationId, msg.byte, 3);
}
return ret;
}
static int8_t IsoTp_SendSingleFrame(IsoTpType *obj)
{
int8_t ret;
uint8_t i = 0;
uint8_t index = 0;
IsoTp_MsgType msg;
/* Setup message */
IsoTp_SetPciType(msg.byte, ISOTP_PCI_TYPE_SINGLE_FRAME);
IsoTp_SetSFDataLen(msg.byte, (uint8_t)obj->sendSize);
for(index = 0; index < obj->sendSize; ++index)
{
msg.byte[index + 1] = obj->sendBuffer[index];
}
/* Send message */
if(obj->framePadding)
{
/* All pad with 0 */
for(i = 0; i < 7 - obj->sendSize; ++i)
{
msg.byte[i + obj->sendSize + 1] = 0;
}
ret = obj->sendCanMsg(obj->sendArbitrationId, msg.byte, 8);
}
else
{
ret = obj->sendCanMsg(obj->sendArbitrationId, msg.byte, obj->sendSize + 1);
}
return ret;
}
static int8_t IsoTp_SendFirstFrame(IsoTpType *obj)
{
int8_t ret;
IsoTp_MsgType msg;
/* Setup message */
IsoTp_SetPciType(msg.byte, ISOTP_PCI_TYPE_FIRST_FRAME);
IsoTp_SetFFDataLen(msg.byte, obj->sendSize);
uint8_t index = 0;
for(index = 0; index < 6; ++index) /* 6 data bytes for the first frame */
{
msg.byte[index + 2] = obj->sendBuffer[index];
}
/* Send message */
ret = obj->sendCanMsg(obj->sendArbitrationId, msg.byte, 8);
if(ISOTP_RET_OK == ret)
{
obj->sendOffset += 6; /* 6 data bytes for the first frame */
obj->sendSN = 1;
}
return ret;
}
static int8_t IsoTp_SendConsecutiveFrame(IsoTpType *obj)
{
int8_t ret;
IsoTp_MsgType msg;
uint16_t dataLength;
uint8_t index = 0;
/* setup message */
IsoTp_SetPciType(msg.byte, ISOTP_PCI_TYPE_CONSECUTIVE_FRAME);
IsoTp_SetCFSn(msg.byte, obj->sendSN);
dataLength = obj->sendSize - obj->sendOffset;
if(dataLength > 7) /* Max 7 data bytes for the consecutive frame */
{
dataLength = 7;
}
for(index = 0; index < dataLength; ++index)
{
msg.byte[index + 1] = obj->sendBuffer[obj->sendOffset + index];
}
/* Send message */
if(obj->framePadding)
{
/* All pad with 0 */
uint8_t i = 0;
for(i = 0; i < 7 - dataLength; ++i)
{
msg.byte[i + 1 + dataLength] = 0;
}
ret = obj->sendCanMsg(obj->sendArbitrationId, msg.byte, 8);
}
else
{
ret = obj->sendCanMsg(obj->sendArbitrationId, msg.byte, dataLength + 1);
}
if(ISOTP_RET_OK == ret)
{
obj->sendOffset += dataLength;
if(++(obj->sendSN) > 0x0F)
{
obj->sendSN = 0;
}
}
return ret;
}
static int8_t IsoTp_ReceiveSingleFrame(IsoTpType *obj, const IsoTp_MsgType *pMsg, uint8_t len)
{
uint8_t index = 0;
/* Check data length */
if((0 == IsoTp_GetSFDataLen(pMsg->byte))
|| (IsoTp_GetSFDataLen(pMsg->byte) > (len - 1)))
{
if(obj->debug != NULL)
{
obj->debug("Single-frame length too small or too large.");
}
return ISOTP_RET_LENGTH;
}
/* Copying data */
/* polyspace-begin DEFECT:OUT_BOUND_ARRAY [No action planned:High] "Still keep default because one frame max length is 8" */
obj->receiveSize = IsoTp_GetSFDataLen(pMsg->byte);
for(index = 0; index < obj->receiveSize; ++index)
{
obj->receiveBuffer[index] = pMsg->byte[index + 1];
}
/* polyspace-end DEFECT:OUT_BOUND_ARRAY [No action planned:High] "Still keep default because one frame max length is 8" */
return ISOTP_RET_OK;
}
static int8_t IsoTp_ReceiveFirstFrame(IsoTpType *obj, const IsoTp_MsgType *pMsg, uint8_t len)
{
uint16_t payloadLength;
uint8_t index = 0;
if(8 != len)
{
if(obj->debug != NULL)
{
obj->debug("First frame should be 8 bytes in length.");
}
return ISOTP_RET_LENGTH;
}
/* Check data length */
payloadLength = IsoTp_GetFFDataLen(pMsg->byte);
/* Should not use multiple frame transmission */
if(payloadLength <= 7)
{
if(obj->debug != NULL)
{
obj->debug("First frame should not use multiple frame transmission.");
}
return ISOTP_RET_LENGTH;
}
if(payloadLength > obj->receiveBufferSize)
{
if(obj->debug != NULL)
{
obj->debug("Multi-frame response too large for receiving buffer.");
}
return ISOTP_RET_OVERFLOW;
}
/* Copying data */
obj->receiveSize = payloadLength;
for(index = 0; index < 6; ++index) /* 6 data bytes for the first frame */
{
obj->receiveBuffer[index] = pMsg->byte[index + 2];
}
obj->receiveOffset = 6; /* 6 data bytes for the first frame */
obj->receiveSN = 1;
return ISOTP_RET_OK;
}
static int8_t IsoTp_ReceiveConsecutiveFrame(IsoTpType *obj, const IsoTp_MsgType *pMsg, uint8_t len)
{
uint16_t remaining_bytes;
uint8_t index = 0;
/* Check SN */
if(obj->receiveSN != IsoTp_GetCFSn(pMsg->byte))
{
return ISOTP_RET_WRONG_SN;
}
/* Check data length */
remaining_bytes = obj->receiveSize - obj->receiveOffset;
if(remaining_bytes > 7) /* Max 7 data bytes for the consecutive frame */
{
remaining_bytes = 7;
}
if(remaining_bytes > len - 1)
{
if(obj->debug != NULL)
{
obj->debug("Consecutive frame too short.");
}
return ISOTP_RET_LENGTH;
}
/* Copying data */
for(index = 0; index < remaining_bytes; ++index)
{
obj->receiveBuffer[index + obj->receiveOffset] = pMsg->byte[index + 1];
}
obj->receiveOffset += remaining_bytes;
if(++(obj->receiveSN) > 0x0F)
{
obj->receiveSN = 0;
}
return ISOTP_RET_OK;
}
static int8_t IsoTp_ReceiveFlowControlFrame(IsoTpType *obj, const IsoTp_MsgType *pMsg, uint8_t len)
{
/* Check message length */
if(len < 3)
{
if(obj->debug != NULL)
{
obj->debug("Flow control frame too short.");
}
return ISOTP_RET_LENGTH;
}
return ISOTP_RET_OK;
}
int8_t IsoTp_Send(IsoTpType *obj, const uint8_t payload[], uint16_t size)
{
return IsoTp_SendWithId(obj, obj->sendArbitrationId, payload, size);
}
int8_t IsoTp_SendWithId(IsoTpType *obj, uint32_t id, const uint8_t payload[], uint16_t size)
{
int8_t ret;
uint8_t i = 0;
if(obj == NULL)
{
return ISOTP_RET_ERROR;
}
if(size > obj->sendBufferSize)
{
if(obj->debug != NULL)
{
obj->debug("Message size too large. Set a larger send buffer\n");
}
return ISOTP_RET_OVERFLOW;
}
if(ISOTP_SEND_STATUS_INPROGRESS == obj->sendStatus)
{
if(obj->debug != NULL)
{
obj->debug("Abort previous message, transmission in progress.\n");
}
return ISOTP_RET_INPROGRESS;
}
/* Copy into local buffer */
obj->sendSize = size;
obj->sendOffset = 0;
for(i = 0; i < size; ++i)
{
obj->sendBuffer[i] = payload[i];
}
if(obj->sendSize < 8)
{
/* Send single frame */
ret = IsoTp_SendSingleFrame(obj);
}
else
{
/* Send multiple frames */
ret = IsoTp_SendFirstFrame(obj);
/* Initialize multi-frame control flags */
if(ISOTP_RET_OK == ret)
{
obj->sendBsRemain = 0;
obj->sendSTMin = 0;
obj->sendWaitFrameCount = 0;
obj->sendTimerSeptime = obj->getTimeMs();
/* Refresh BS timer */
obj->sendTimerBlockSize = obj->getTimeMs() + ISOTP_DEFAULT_RESPONSE_TIMEOUT;
obj->sendProtocolResult = ISOTP_PROTOCOL_RESULT_OK;
obj->sendStatus = ISOTP_SEND_STATUS_INPROGRESS;
}
}
/* polyspace-end DEFECT:NULL_PTR [No action planned:High] "Still keep default because the null pointer is handled" */
return ret;
}
void IsoTp_HandleIncomingCanMsg(IsoTpType *obj, uint32_t id, const uint8_t *data, uint8_t len)
{
int8_t ret;
IsoTp_MsgType msg;
if(len < 2 || len > 8)
{
return;
}
uint8_t i = 0;
for(i = 0; i < len; ++i)
{
msg.byte[i] = data[i];
}
for(i = 0; i < 8 - len; ++i) /* len will NOT > 8 */
{
msg.byte[i + len] = 0; /* Padding */
}
switch(IsoTp_GetPciType(msg.byte))
{
case ISOTP_PCI_TYPE_SINGLE_FRAME:
{
/* Update protocol result */
if(ISOTP_RECEIVE_STATUS_INPROGRESS == obj->receiveStatus)
{
obj->receiveProtocolResult = ISOTP_PROTOCOL_RESULT_UNEXP_PDU;
}
else
{
obj->receiveProtocolResult = ISOTP_PROTOCOL_RESULT_OK;
}
/* Handle message */
ret = IsoTp_ReceiveSingleFrame(obj, &msg, len);
if(ISOTP_RET_OK == ret)
{
obj->receiveArbitrationId = id;
/* Change status */
obj->receiveStatus = ISOTP_RECEIVE_STATUS_FULL;
}
break;
}
case ISOTP_PCI_TYPE_FIRST_FRAME:
{
/* Update protocol result */
if(ISOTP_RECEIVE_STATUS_INPROGRESS == obj->receiveStatus)
{
obj->receiveProtocolResult = ISOTP_PROTOCOL_RESULT_UNEXP_PDU;
}
else
{
obj->receiveProtocolResult = ISOTP_PROTOCOL_RESULT_OK;
}
/* Handle message */
ret = IsoTp_ReceiveFirstFrame(obj, &msg, len);
/* If overflow happened */
if(ISOTP_RET_OVERFLOW == ret)
{
/* Update protocol result */
obj->receiveProtocolResult = ISOTP_PROTOCOL_RESULT_BUFFER_OVFLW;
/* Change status */
obj->receiveStatus = ISOTP_RECEIVE_STATUS_IDLE;
/* Send error message */
IsoTp_SendFlowControl(obj, ISOTP_PCI_FLOW_STATUS_OVERFLOW, 0, 0);
break;
}
/* If receive successful */
if(ISOTP_RET_OK == ret)
{
obj->receiveArbitrationId = id;
/* Change status */
obj->receiveStatus = ISOTP_RECEIVE_STATUS_INPROGRESS;
/* Send FC frame */
obj->receiveBlockSizeCount = obj->blockSize;
IsoTp_SendFlowControl(obj, ISOTP_PCI_FLOW_STATUS_CONTINUE, obj->receiveBlockSizeCount, ISOTP_DEFAULT_ST_MIN);
/* Refresh timer CR */
obj->receiveTimerCr = obj->getTimeMs() + ISOTP_DEFAULT_RESPONSE_TIMEOUT;
}
break;
}
case ISOTP_PCI_TYPE_CONSECUTIVE_FRAME:
{
/* Check if in receiving status */
if(ISOTP_RECEIVE_STATUS_INPROGRESS != obj->receiveStatus)
{
obj->receiveProtocolResult = ISOTP_PROTOCOL_RESULT_UNEXP_PDU;
break;
}
if(id != obj->receiveArbitrationId)
{
break;
}
/* Handle message */
ret = IsoTp_ReceiveConsecutiveFrame(obj, &msg, len);
/* If wrong SN */
if(ISOTP_RET_WRONG_SN == ret)
{
obj->receiveProtocolResult = ISOTP_PROTOCOL_RESULT_WRONG_SN;
obj->receiveStatus = ISOTP_RECEIVE_STATUS_IDLE;
break;
}
/* If success */
if(ISOTP_RET_OK == ret)
{
/* Refresh timer CR */
obj->receiveTimerCr = obj->getTimeMs() + ISOTP_DEFAULT_RESPONSE_TIMEOUT;
/* Receive finished */
if(obj->receiveOffset >= obj->receiveSize)
{
obj->receiveStatus = ISOTP_RECEIVE_STATUS_FULL;
}
else
{
/* Send FC when BS reaches limit */
if(0 == --obj->receiveBlockSizeCount)
{
obj->receiveBlockSizeCount = obj->blockSize;
IsoTp_SendFlowControl(obj, ISOTP_PCI_FLOW_STATUS_CONTINUE, obj->receiveBlockSizeCount, ISOTP_DEFAULT_ST_MIN);
}
}
}
break;
}
case ISOTP_PCI_TYPE_FLOW_CONTROL_FRAME:
{
/* Handle fc frame only when sending in progress */
if(ISOTP_SEND_STATUS_INPROGRESS != obj->sendStatus)
{
break;
}
/* Handle message */
ret = IsoTp_ReceiveFlowControlFrame(obj, &msg, len);
if(ISOTP_RET_OK == ret)
{
/* Refresh BS timer */
obj->sendTimerBlockSize = obj->getTimeMs() + ISOTP_DEFAULT_RESPONSE_TIMEOUT;
/* Overflow */
if(ISOTP_PCI_FLOW_STATUS_OVERFLOW == IsoTp_GetFCFlowState(msg.byte))
{
obj->sendProtocolResult = ISOTP_PROTOCOL_RESULT_BUFFER_OVFLW;
obj->sendStatus = ISOTP_SEND_STATUS_ERROR;
}
/* Wait */
else if(ISOTP_PCI_FLOW_STATUS_WAIT == IsoTp_GetFCFlowState(msg.byte))
{
obj->sendWaitFrameCount += 1;
/* Wait exceed allowed count */
if(obj->sendWaitFrameCount > ISOTP_MAX_WFT_NUMBER)
{
obj->sendProtocolResult = ISOTP_PROTOCOL_RESULT_WFT_OVRN;
obj->sendStatus = ISOTP_SEND_STATUS_ERROR;
}
}
/* Permit send */
else if(ISOTP_PCI_FLOW_STATUS_CONTINUE == IsoTp_GetFCFlowState(msg.byte))
{
if(0 == IsoTp_GetFCBlockSize(msg.byte))
{
obj->sendBsRemain = ISOTP_INVALID_BS;
}
else
{
obj->sendBsRemain = IsoTp_GetFCBlockSize(msg.byte);
}
obj->sendSTMin = IsoTp_StMinToMs(IsoTp_GetFCStmin(msg.byte));
obj->sendWaitFrameCount = 0;
}
}
break;
}
default:
break;
};
return;
}
int8_t IsoTp_Receive(IsoTpType *link, bool *IsFuncAddr, uint8_t *payload, uint16_t payload_size, uint16_t *out_size)
{
uint16_t copylen;
uint16_t i = 0;
if(ISOTP_RECEIVE_STATUS_FULL != link->receiveStatus)
{
return ISOTP_RET_NO_DATA;
}
*IsFuncAddr = (link->receiveArbitrationId == link->funcId) ? true : false;
copylen = link->receiveSize;
if(copylen > payload_size)
{
copylen = payload_size;
}
for(i = 0; i < copylen; ++i)
{
payload[i] = link->receiveBuffer[i];
}
*out_size = copylen;
link->receiveStatus = ISOTP_RECEIVE_STATUS_IDLE;
return ISOTP_RET_OK;
}
void IsoTp_Init(IsoTpType *obj, const IsoTp_Params *pParams)
{
obj->framePadding = pParams->framePadding;
obj->blockSize = pParams->blockSize;
obj->physId = pParams->recvPhysId;
obj->funcId = pParams->recvFuncId;
obj->sendArbitrationId = pParams->sendid;
obj->sendBuffer = pParams->sendBuf;
obj->sendBufferSize = pParams->sendBufSize;
obj->sendSize = 0;
obj->sendOffset = 0;
obj->sendSN = 0;
obj->sendBsRemain = 0;
obj->sendSTMin = 0;
obj->sendWaitFrameCount = 0;
obj->sendTimerSeptime = 0;
obj->sendTimerBlockSize = 0;
obj->sendProtocolResult = 0;
obj->sendStatus = ISOTP_SEND_STATUS_IDLE;
obj->receiveBuffer = pParams->recvBuf;
obj->receiveBufferSize = pParams->recvBufSize;
obj->receiveSize = 0;
obj->receiveOffset = 0;
obj->receiveSN = 0;
obj->receiveBlockSizeCount = 0;
obj->receiveTimerCr = 0;
obj->receiveProtocolResult = ISOTP_PROTOCOL_RESULT_OK;
obj->receiveStatus = ISOTP_RECEIVE_STATUS_IDLE;
obj->debug = pParams->debug;
obj->sendCanMsg = pParams->sendCanMsg;
obj->getTimeMs = pParams->getTimeMs;
}
void IsoTp_Poll(IsoTpType *obj)
{
int8_t ret;
/* Only polling when operation in progress */
if(ISOTP_SEND_STATUS_INPROGRESS == obj->sendStatus)
{
/* Continue send data */
if((ISOTP_INVALID_BS == obj->sendBsRemain || obj->sendBsRemain > 0) /* send data if bs_remain is invalid or bs_remain large than zero */
&& (0 == obj->sendSTMin || (0 != obj->sendSTMin && IsoTp_TimeAfter(obj->getTimeMs(), obj->sendTimerSeptime))))
{ /* st_min is zero or go beyond interval time */
ret = IsoTp_SendConsecutiveFrame(obj);
if(ISOTP_RET_OK == ret)
{
if(ISOTP_INVALID_BS != obj->sendBsRemain)
{
obj->sendBsRemain -= 1;
}
/* Refresh BS timer */
obj->sendTimerBlockSize = obj->getTimeMs() + ISOTP_DEFAULT_RESPONSE_TIMEOUT;
obj->sendTimerSeptime = obj->getTimeMs() + obj->sendSTMin;
/* Check if send finish */
if(obj->sendOffset >= obj->sendSize)
{
obj->sendStatus = ISOTP_SEND_STATUS_IDLE;
}
}
else
{
obj->sendStatus = ISOTP_SEND_STATUS_ERROR;
}
}
/* Check timeout */
if(IsoTp_TimeAfter(obj->getTimeMs(), obj->sendTimerBlockSize))
{
obj->sendProtocolResult = ISOTP_PROTOCOL_RESULT_TIMEOUT_BS;
obj->sendStatus = ISOTP_SEND_STATUS_ERROR;
}
}
/* Only polling when operation in progress */
if(ISOTP_RECEIVE_STATUS_INPROGRESS == obj->receiveStatus)
{
/* check timeout */
if(IsoTp_TimeAfter(obj->getTimeMs(), obj->receiveTimerCr))
{
obj->receiveProtocolResult = ISOTP_PROTOCOL_RESULT_TIMEOUT_CR;
obj->receiveStatus = ISOTP_RECEIVE_STATUS_IDLE;
}
}
return;
}

View File

@ -0,0 +1,221 @@
/*
* 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.
*/
#ifndef _ISOTP_H_
#define _ISOTP_H_
/*! \brief Contains public interface to various functions related
* to the ISO TP (ISO 15765-2)
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*! \brief Defines all the return values
*/
#define ISOTP_RET_OK (0)
#define ISOTP_RET_ERROR (-1)
#define ISOTP_RET_INPROGRESS (-2)
#define ISOTP_RET_OVERFLOW (-3)
#define ISOTP_RET_WRONG_SN (-4)
#define ISOTP_RET_NO_DATA (-5)
#define ISOTP_RET_TIMEOUT (-6)
#define ISOTP_RET_LENGTH (-7)
/*! \brief The default timeout to use when waiting for a response during a multi-frame send or receive.
*/
#define ISOTP_DEFAULT_RESPONSE_TIMEOUT (100)
/*! \brief The STmin parameter value specifies the minimum time gap allowed between
* the transmission of consecutive frame network protocol data units
*/
#define ISOTP_DEFAULT_ST_MIN (0)
/*! \brief This parameter indicate how many FC N_PDU WTs can be transmitted by the
* receiver in a row.
*/
#define ISOTP_MAX_WFT_NUMBER (1)
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief The declaration of the buffer used for both send and receive
*/
typedef uint8_t *IsoTp_Buffer;
/*! \brief User implemented, print debug message
*/
typedef void (*IsoTp_DebugShim)(const char *message, ...);
/*! \brief User implemented, send can message
*/
typedef int8_t (*IsoTp_SendCanMsgShim)(const uint32_t arbitrationId, const uint8_t *pData, const uint8_t size);
/*! \brief User implemented, get millisecond
*/
typedef int64_t (*IsoTp_GetTimeShimMs)(void);
/*! \brief Defines all the parameters used to initialize ISOTP object
*/
typedef struct _IsoTp_Params_
{
bool framePadding;
uint8_t blockSize;
uint32_t recvPhysId;
uint32_t recvFuncId;
uint32_t sendid;
uint8_t *sendBuf;
uint16_t sendBufSize;
uint8_t *recvBuf;
uint16_t recvBufSize;
IsoTp_DebugShim debug;
IsoTp_SendCanMsgShim sendCanMsg;
IsoTp_GetTimeShimMs getTimeMs;
} IsoTp_Params;
/*! \brief Structure containing the data for linking an application to a CAN instance.
* The data stored in this structure is used internally and may be used by software programs
* using this library.
*/
typedef struct _IsoTpType_
{
bool framePadding; /*!< whether need frame padding */
uint8_t blockSize; /*!< Max number of messages the receiver can receive at one time, this value is affected by CAN driver queue length */
uint32_t physId; /*!< physical addressing id */
uint32_t funcId; /*!< functional addressing id */
uint32_t sendArbitrationId; /*! used to reply consecutive frame */
IsoTp_Buffer sendBuffer; /*!< send buffer */
uint16_t sendBufferSize; /*!< the size of send buffer */
uint16_t sendSize; /*!< the size of data to send */
uint16_t sendOffset; /*!< the offset of current send process */
uint8_t sendSN; /*!< serial number of send message */
uint16_t sendBsRemain; /*!< Remaining block size */
uint8_t sendSTMin; /*!< Separation Time between consecutive frames, unit millisecond */
uint8_t sendWaitFrameCount; /*!< Maximum number of FC.Wait frame transmissions */
int64_t sendTimerSeptime; /*!< Last time send consecutive frame */
int64_t sendTimerBlockSize; /*!< Time until transmission of the next FlowControl N_PDU start at sending FF, CF, receive FC end at receive FC */
int sendProtocolResult; /*!< the result of send protocol */
uint8_t sendStatus; /*!< the send status */
uint32_t receiveArbitrationId; /*! used to determine whether physical or functional addressing */
IsoTp_Buffer receiveBuffer; /*!< message receive buffer */
uint16_t receiveBufferSize; /*!< the size of RX buffer */
uint16_t receiveSize; /*!< the size to receive */
uint16_t receiveOffset; /*!< the offset of receive process */
uint8_t receiveSN; /*!< serial number of receive message */
uint8_t receiveBlockSizeCount; /*!< Maximum number of FC.Wait frame transmissions */
int64_t receiveTimerCr; /*!< Time until reception of the next ConsecutiveFrame N_PDU start at sending FC, receive CF end at receive FC */
int8_t receiveProtocolResult; /*!< the result of receive protocol */
uint8_t receiveStatus; /*!< the receive status */
IsoTp_DebugShim debug; /*!< the adapter of debug function */
IsoTp_SendCanMsgShim sendCanMsg; /*!< the adapter of can-send-message function */
IsoTp_GetTimeShimMs getTimeMs; /*!< the adapter of get-time-stamp function */
} IsoTpType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initializes the ISO-TP library.
*
* This function intiliaze the ISO-TP instance
*
* \param[in] obj : pointer to ISOTP instance
* \param[in] pParams : pointer to the initialization parameters
*/
extern void IsoTp_Init(IsoTpType *obj, const IsoTp_Params *pParams);
/*! \brief Polling function
*
* Call this function periodically to handle timeouts, send consecutive frames, etc.
*
* \param[in] obj : pointer to ISOTP instance
*/
extern void IsoTp_Poll(IsoTpType *obj);
/*! \brief Handles incoming CAN messages.
*
* Determines whether an incoming message is a valid ISO-TP frame or not and handles it accordingly.
*
* \param[in] obj : pointer to ISOTP instance
* \param[in] id : the incoming CAN frame ID
* \param[in] pData : pointer to data of incoming CAN frame
* \param[in] len : the length of data of incoming CAN frame
*/
extern void IsoTp_HandleIncomingCanMsg(IsoTpType *obj, uint32_t id, const uint8_t *pData, uint8_t len);
/*! \brief Sends ISO-TP frames via CAN, using the ID set in the initializing function.
*
* Single-frame messages will be sent immediately when calling this function.
* Multi-frame messages will be sent consecutively when calling isotp_poll.
*
* \param[in] obj : pointer to ISOTP instance
* \param[in] pPayload : the incoming CAN frame ID
* \param[in] size : pointer to data of incoming CAN frame
*/
extern int8_t IsoTp_Send(IsoTpType *obj, const uint8_t pPayload[], uint16_t size);
/*! \brief Send with message ID
*
* With the exception that this function is used only for functional addressing.
*
* \param[in] obj : pointer to ISOTP instance
* \param[in] id : the message ID to send
* \param[in] pPayload : pointer to data to send
* \param[in] size : the size of data to send
*/
extern int8_t IsoTp_SendWithId(IsoTpType *obj, uint32_t id, const uint8_t pPayload[], uint16_t size);
/*! \brief Receives and parses the received data and copies the parsed data in to the internal buffer.
*
* This function receives and parses the received data and copies the parsed data in to the internal buffer.
*
* \param[in] obj : pointer to ISOTP instance
* \param[out] IsFuncAddr : pointer the result of whether is functional addressing
* \param[out] pPayload : pointer to the payload
* \param[in] payloadSize : the payload size
* \param[out] pOutSize : the size of actual output payload
*/
extern int8_t IsoTp_Receive(IsoTpType *obj, bool *IsFuncAddr, uint8_t *pPayload, uint16_t payloadSize, uint16_t *pOutSize);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _ISOTP_H_ */

View File

@ -0,0 +1,893 @@
/*
* 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 <stddef.h>
#include "fee.h"
#include "fee_initialization.h"
#include "fee_trace.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*! \brief Macro for the start address of the block data
*/
#define FEE_BLOCK_DATA_START_ADDR (((Fee_AddressType)obj->runtime->activeSector->startAddr) + FEE_SECTOR_HEAD_SIZE)
/*! \brief Macro for the end address of the block data
*/
#define FEE_BLOCK_DATA_ADDR (obj->runtime->activeSector->endAddr)
/*! \brief Macro for the start address of the block info
*/
#define FEE_BLOCK_INFO_START_ADDR (((Fee_AddressType)obj->runtime->activeSector->endAddr) - FEE_SECTOR_HEAD_SIZE - FEE_BLOCK_HEAD_INFO_SIZE)
/*! \brief Macro for the end address of the block info
*/
#define FEE_BLOCK_INFO_END_ADDR (obj->runtime->activeSector->startAddr + FEE_SECTOR_HEAD_SIZE)
/*! \brief Get a macro for a block object
*/
#define Fee_GetBlock(obj, idx) (&obj->blocks[idx])
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the static
******************************************************************************/
static bool Fee_OnEntryRetrievalJob(const FeeType *obj);
static void Fee_ExitRetrievalJob(const FeeType *obj);
static bool Fee_RetrievalActiveSector(const FeeType *obj);
static bool Fee_ReadJob(const FeeType *obj);
static bool Fee_WriteJob(const FeeType *obj);
static void FEE_OnEntryGcJob(const FeeType *obj);
static bool Fee_GcJob(const FeeType *obj);
static void Fee_OnEntryGcCopyJob(const FeeType *obj);
static bool Fee_GcCopyJob(const FeeType *obj);
static bool Fee_GcInitBlockInfo(const FeeType *obj, const Fee_BlockType *block);
static bool Fee_GcWriteBlockToNewSector(const FeeType *obj);
static const Fee_SectorConfigType *Fee_FoundBackupSector(const FeeType *obj);
static uint16_t Fee_SearchBlock(const Fee_SectorType *obj, uint16_t blockNumber);
/*******************************************************************************
* the functions
******************************************************************************/
void Fee_Configure(const FeeType *obj)
{
/* Initialize system job request. */
Fee_InitJob(obj->runtime->jobs->sysJob);
/* Initialize user job request. */
Fee_InitJob(obj->runtime->jobs->userJob);
/* Initialize to reject request status. */
obj->runtime->jobs->accept = false;
/* Initialize the status of the main function. */
obj->runtime->mainFunFsm = FEE_MAIN_FUN_FSM_INITIALIZATION;
Fee_EntryInitialization(obj);
}
void Fee_MainFunction(const FeeType *obj)
{
switch(obj->runtime->mainFunFsm)
{
case FEE_MAIN_FUN_FSM_INITIALIZATION:
{
if(Fee_InitializationJob(obj))
{
if(Fee_OnEntryRetrievalJob(obj))
{
obj->runtime->mainFunFsm = FEE_MAIN_FUN_FSM_RETRIEVAL;
}
else
{
obj->runtime->mainFunFsm = FEE_MAIN_FUN_FSM_ERROR;
}
}
break;
}
case FEE_MAIN_FUN_FSM_RETRIEVAL:
{
if(Fee_RetrievalActiveSector(obj))
{
Fee_ExitRetrievalJob(obj);
Fee_EnableJobs(obj->runtime->jobs);
obj->runtime->mainFunFsm = FEE_MAIN_FUN_FSM_IDLE;
}
break;
}
case FEE_MAIN_FUN_FSM_IDLE:
{
if(Fee_GetSysJob(obj->runtime->jobs, obj->runtime->job))
{
if(obj->runtime->job->op == FEE_JOB_OP_GC)
{
FEE_OnEntryGcJob(obj);
}
}
else if(Fee_GetUserJob(obj->runtime->jobs, obj->runtime->job))
{
if(obj->runtime->job->op == FEE_JOB_OP_READ)
{
obj->runtime->mainFunFsm = FEE_MAIN_FUN_FSM_READ;
}
else if(obj->runtime->job->op == FEE_JOB_OP_WRITE)
{
obj->runtime->mainFunFsm = FEE_MAIN_FUN_FSM_WRITE;
}
else
{
/* Do nothing. */
}
}
break;
}
case FEE_MAIN_FUN_FSM_READ:
{
/* polyspace-begin DEFECT:USELESS_IF [ Not a defect: Medium ] "Ensure consistent code style between top and bottom." */
if(Fee_ReadJob(obj))
{
/* Clear current request job. */
Fee_InitJob(obj->runtime->jobs->userJob);
obj->runtime->mainFunFsm = FEE_MAIN_FUN_FSM_IDLE;
}
/* polyspace-end DEFECT:USELESS_IF [ Not a defect: Medium ] "Ensure consistent code style between top and bottom." */
break;
}
case FEE_MAIN_FUN_FSM_WRITE:
{
/* polyspace-begin DEFECT:USELESS_IF [ Not a defect: Medium ] "Ensure consistent code style between top and bottom." */
if(Fee_WriteJob(obj))
{
/* Clear current request job. */
Fee_InitJob(obj->runtime->jobs->userJob);
obj->runtime->mainFunFsm = FEE_MAIN_FUN_FSM_IDLE;
}
/* polyspace-end DEFECT:USELESS_IF [ Not a defect: Medium ] "Ensure consistent code style between top and bottom." */
break;
}
case FEE_MAIN_FUN_FSM_GC:
{
if(Fee_GcJob(obj))
{
/* Clear current request job. */
Fee_InitJob(obj->runtime->jobs->sysJob);
if(FEE_GC_ERROR == obj->runtime->gcRuntime->gcFsm)
{
Fee_EntryInitialization(obj);
obj->runtime->mainFunFsm = FEE_MAIN_FUN_FSM_INITIALIZATION;
}
else if(FEE_GC_FINISH == obj->runtime->gcRuntime->gcFsm)
{
obj->runtime->mainFunFsm = FEE_MAIN_FUN_FSM_IDLE;
}
}
break;
}
default:
{
FEE_DBG_MAIN_FSM_ERROR_ENTRY();
break;
}
}
}
Fee_ReturnType Fee_Read(const FeeType *obj, uint16_t blockNumber, uint16_t blockOffset, uint8_t *dataBuffer, NotificationPtrType notificationPtr)
{
Fee_ReturnType ret = FEE_RETURN_NOT_OK;
Fee_JobControlBlockType config;
uint16_t blockIdx;
/* Find the index of the block. */
blockIdx = Fee_SearchBlock(obj->sector, blockNumber);
/* Check whether the index is invalid. */
if(FEE_INVALID_BLOCK_INDEX != blockIdx)
{
/* Initialize read request configuration. */
config.blockIdx = blockIdx;
config.blockOffset = blockOffset;
config.dataBuffPtr = dataBuffer;
config.notificationPtr = notificationPtr;
config.op = FEE_JOB_OP_READ;
config.lock = FEE_JOB_LOCK;
/* Check if there is already a request. */
if(false == Fee_QueryUserJobIsLock(obj->runtime->jobs))
{
/* Configuration Request. */
if(Fee_SetUserJob(obj->runtime->jobs, &config))
{
/* Configure job Status. */
obj->runtime->jobResult = FEE_JOB_RESULT_PENDING;
ret = FEE_RETURN_OK;
}
}
}
else
{
/* Configure job Status. */
obj->runtime->jobResult = FEE_JOB_RESULT_BL_INVALID;
}
return ret;
}
Fee_ReturnType Fee_Write(const FeeType *obj, uint16_t blockNumber, uint8_t *dataBuffer, NotificationPtrType notificationPtr)
{
Fee_ReturnType ret = FEE_RETURN_NOT_OK;
Fee_JobControlBlockType config;
uint16_t blockIdx;
/* Find the index of the block. */
blockIdx = Fee_SearchBlock(obj->sector, blockNumber);
/* Check whether the index is invalid. */
if(0xFFFF != blockIdx)
{
/* Check whether the remaining space is sufficient for storage. */
if(Fee_CheckRemSpace(obj->runtime->activeSector, Fee_GetBlock(obj->sector, blockIdx)))
{
/* Initialize write request configuration. */
config.blockIdx = blockIdx;
config.dataBuffPtr = dataBuffer;
config.notificationPtr = notificationPtr;
config.op = FEE_JOB_OP_WRITE;
config.lock = FEE_JOB_LOCK;
/* Check if there is already a request. */
if(false == Fee_QueryUserJobIsLock(obj->runtime->jobs))
{
/* Configuration User Request. */
if(Fee_SetUserJob(obj->runtime->jobs, &config))
{
/* Configure job Status. */
obj->runtime->jobResult = FEE_JOB_RESULT_PENDING;
ret = FEE_RETURN_OK;
}
}
}
else
{
/* Configure Request Recycling. */
config.op = FEE_JOB_OP_GC;
/* Check if there are already system requests. */
if(false == Fee_QuerySysJobIsLock(obj->runtime->jobs))
{
/* Configuration System Request. */
Fee_SetSysJob(obj->runtime->jobs, &config);
}
}
}
else
{
obj->runtime->jobResult = FEE_JOB_RESULT_BL_INVALID;
}
return ret;
}
Fee_JobResultType Fee_GetJobResult(const FeeType *obj)
{
return obj->runtime->jobResult;
}
Fee_StatusType Fee_GetStatus(const FeeType *obj)
{
Fee_StatusType ret = FEE_STATUS_UNKNOW;
if(FEE_MAIN_FUN_FSM_GC == obj->runtime->mainFunFsm)
{
ret = FEE_STATUS_GC;
}
else if(FEE_MAIN_FUN_FSM_READ == obj->runtime->mainFunFsm)
{
ret = FEE_STATUS_READ;
}
else if(FEE_MAIN_FUN_FSM_WRITE == obj->runtime->mainFunFsm)
{
ret = FEE_STATUS_WRITE;
}
else if(FEE_MAIN_FUN_FSM_IDLE == obj->runtime->mainFunFsm)
{
ret = FEE_STATUS_IDLE;
}
else if(FEE_MAIN_FUN_FSM_ERROR == obj->runtime->mainFunFsm)
{
ret = FEE_STATUS_ERROR;
}
else if(FEE_MAIN_FUN_FSM_INITIALIZATION == obj->runtime->mainFunFsm)
{
ret = FEE_STATUS_UNINIT;
}
else if(FEE_MAIN_FUN_FSM_RETRIEVAL == obj->runtime->mainFunFsm)
{
ret = FEE_STATUS_UNINIT;
}
else
{
ret = FEE_STATUS_UNKNOW;
}
return ret;
}
void Fee_GetVersionInfo(Fee_VersionInfoType *versionInfoPtr)
{
if(NULL != versionInfoPtr)
{
versionInfoPtr->sw_major_version = FEE_SW_MAJOR_VERSION;
versionInfoPtr->sw_minor_version = FEE_SW_MINOR_VERSION;
versionInfoPtr->sw_patch_version = FEE_SW_PATCH_VERSION;
}
}
static bool Fee_OnEntryRetrievalJob(const FeeType *obj)
{
bool ret = false;
int blockIdx;
if(NULL != obj)
{
if(NULL != obj->runtime->activeSector)
{
/* Initialize the block index table. */
for(blockIdx = 0; blockIdx < obj->sector->blockSize; blockIdx++)
{
Fee_BlockSetPhyAddr(obj->sector->blocks[blockIdx].info, NULL);
}
/* The variable search points to the bottom of the sector. */
obj->runtime->activeSector->info->searchAddr = FEE_BLOCK_INFO_START_ADDR;
/* Prepare to find the starting address of the remaining space. */
obj->runtime->activeSector->info->remAddr = FEE_BLOCK_DATA_START_ADDR;
/* Return true. */
ret = true;
}
}
return ret;
}
static void Fee_ExitRetrievalJob(const FeeType *obj)
{
/* Find the starting address of the remaining space. */
for(; FLS_STATE_NOT_WRITABLE == obj->flsMethod->isWriteable(obj->runtime->activeSector->info->remAddr, Fee_BLOCK_WRITE_ALIGNED_SIZE); obj->runtime->activeSector->info->remAddr += Fee_BLOCK_WRITE_ALIGNED_SIZE)
{
}
}
static bool Fee_RetrievalActiveSector(const FeeType *obj)
{
bool ret = false;
const Fee_BlockType *block = NULL;
/* Check the range of index addresses. */
if(obj->runtime->activeSector->info->searchAddr > FEE_BLOCK_INFO_END_ADDR)
{
/* Check whether the flash space is not writable. */
if(FLS_STATE_NOT_WRITABLE == obj->flsMethod->isWriteable(obj->runtime->activeSector->info->searchAddr, FEE_BLOCK_HEAD_INFO_SIZE))
{
/* Read flash data. */
if(FLS_STATE_OK == obj->flsMethod->read(obj->runtime->activeSector->info->searchAddr, (uint8_t *)obj->buff, FEE_BLOCK_HEAD_INFO_SIZE))
{
/* Analyze the data and find the described block configuration. */
block = Fee_MatchBlock(obj->sector, obj->flsMethod, (uint8_t *)obj->buff);
/* If the block points to a null pointer, no matching block was found. */
if(NULL != block)
{
/* Create a block index table. */
Fee_BlockSetPhyAddr(block->info, Fee_GetBlockHeadPhyAddr((uint8_t *)obj->buff));
obj->runtime->activeSector->info->remAddr = block->info->phyAddr + FEE_BLOCKSIZE(block->cfg);
}
}
/* Point to the next block info. */
obj->runtime->activeSector->info->searchAddr -= FEE_BLOCK_HEAD_INFO_SIZE;
}
else
{
/* If a writable flash address is found, the traversal is considered complete. */
obj->runtime->activeSector->info->headInfoAddr = obj->runtime->activeSector->info->searchAddr;
ret = true;
}
}
else
{
FEE_DBG_STORAGE_ERROR_ENTRY();
}
return ret;
}
static bool Fee_ReadJob(const FeeType *obj)
{
bool ret = true;
Fee_NotificationType notificationRet = FEE_JOBERRORNOTIFICATION;
const Fee_BlockType *block;
/* Reset job processing status. */
obj->runtime->jobResult = FEE_JOB_RESULT_NOT_OK;
/* Get block configuration. */
block = Fee_GetBlock(obj->sector, obj->runtime->job->blockIdx);
/* Check whether the block configuration is valid. */
if(block != NULL)
{
/* Check whether the block has been assigned a flash address. */
if(NULL != block->info->phyAddr)
{
/* Check the validity of the data stored on the flash by the block. */
if(FLS_STATE_OK == obj->flsMethod->read(block->info->phyAddr, obj->runtime->job->dataBuffPtr, FEE_BLOCKSIZE(block->cfg)))
{
obj->runtime->jobResult = FEE_JOB_RESULT_OK;
notificationRet = FEE_JOBENDNOTIFICATION;
}
else
{
obj->runtime->jobResult = FEE_JOB_RESULT_BL_INCONSISTENT;
}
}
else
{
obj->runtime->jobResult = FEE_JOB_RESULT_BL_INVALID;
}
}
/* Callback notification function. */
if(obj->runtime->job->notificationPtr != NULL)
{
obj->runtime->job->notificationPtr(notificationRet);
}
return ret;
}
static bool Fee_WriteJob(const FeeType *obj)
{
bool ret = true;
Fee_NotificationType notificationRet = FEE_JOBERRORNOTIFICATION;
const Fee_BlockType *block;
uint16_t blocksize;
Fee_AddressType tempPhyAddr;
/* Reset job processing status. */
obj->runtime->jobResult = FEE_JOB_RESULT_NOT_OK;
block = Fee_GetBlock(obj->sector, obj->runtime->job->blockIdx);
if(NULL != block)
{
blocksize = FEE_BLOCKSIZE(block->cfg);
/* First write the block data to the flash, ensure safe writing, and then write the block header information. */
if(FLS_STATE_OK == obj->flsMethod->write(obj->runtime->activeSector->info->remAddr, obj->runtime->job->dataBuffPtr, blocksize))
{
tempPhyAddr = block->info->phyAddr;
Fee_BlockSetPhyAddr(block->info, obj->runtime->activeSector->info->remAddr);
Fee_WriteBlockHeadInfo(block, obj->flsMethod->crc8, (uint8_t *)obj->buff);
if(FLS_STATE_OK == obj->flsMethod->write(obj->runtime->activeSector->info->headInfoAddr, obj->buff, FEE_BLOCK_HEAD_INFO_SIZE))
{
obj->runtime->jobResult = FEE_JOB_RESULT_OK;
notificationRet = FEE_JOBENDNOTIFICATION;
}
else
{
block->info->phyAddr = tempPhyAddr;
}
obj->runtime->activeSector->info->headInfoAddr -= FEE_BLOCK_HEAD_INFO_SIZE;
}
else
{
(void)obj->runtime->activeSector->info->remAddr;
}
obj->runtime->activeSector->info->remAddr += blocksize;
}
else
{
obj->runtime->jobResult = FEE_JOB_RESULT_BL_INVALID;
notificationRet = FEE_JOBENDNOTIFICATION;
}
/* Callback notification function. */
if(obj->runtime->job->notificationPtr != NULL)
{
obj->runtime->job->notificationPtr(notificationRet);
}
return ret;
}
static void FEE_OnEntryGcJob(const FeeType *obj)
{
obj->runtime->gcRuntime->state = FEE_GC_STATE_NO_ERROR;
obj->runtime->gcRuntime->gcFsm = FEE_GC_INIT;
obj->runtime->mainFunFsm = FEE_MAIN_FUN_FSM_GC;
}
static bool Fee_GcJob(const FeeType *obj)
{
bool ret = false;
switch(obj->runtime->gcRuntime->gcFsm)
{
case FEE_GC_INIT:
{
/* Find backup sector. */
obj->runtime->gcRuntime->backupSector = Fee_FoundBackupSector(obj);
if(obj->runtime->gcRuntime->backupSector != NULL)
{
/* Information about initializing the backup sector. */
Fee_SectorInitInfo(obj->runtime->gcRuntime->backupSector);
/* Check whether all sectors have been erased. */
if(false == Fee_SectorIsErase(obj->runtime->gcRuntime->backupSector, obj->flsMethod))
{
/* Execute the sector erase action. */
obj->runtime->gcRuntime->gcFsm = FEE_GC_ERASE_BACKUPSECTOR;
Fee_InitEraseSector(obj->runtime->gcRuntime->backupSector);
}
else
{
obj->runtime->gcRuntime->backupSector->info->status = FEE_SECTOR_UNUSED;
obj->runtime->gcRuntime->gcFsm = FEE_GC_START;
}
}
else
{
/* If the backup sector is not found, it is considered a major configuration defect. */
obj->runtime->gcRuntime->state = FEE_GC_STATE_NOT_FOUND_BACKUPSECTOR;
obj->runtime->gcRuntime->gcFsm = FEE_GC_ERROR;
}
break;
}
case FEE_GC_ERASE_BACKUPSECTOR:
{
/* Erase the backed up sector. */
Fee_EraseSector(obj->runtime->gcRuntime->backupSector, obj->flsMethod);
if((FEE_SECTOR_NOT_ERROR == obj->runtime->gcRuntime->backupSector->info->errors) && (FEE_SECTOR_ERASE == obj->runtime->gcRuntime->backupSector->info->status))
{
obj->runtime->gcRuntime->gcFsm = FEE_GC_START;
}
else if(FEE_SECTOR_NOT_ERROR != obj->runtime->gcRuntime->backupSector->info->errors)
{
obj->runtime->gcRuntime->state = FEE_GC_STATE_ERASE_BACKUP_SECTOR_ERROR;
obj->runtime->gcRuntime->gcFsm = FEE_GC_ERROR;
}
break;
}
case FEE_GC_START:
{
/* Write initialization completion flag bit. */
Fee_SectorWriteInitMark(obj->runtime->gcRuntime->backupSector, obj->flsMethod, obj->buff);
if(FEE_SECTOR_NOT_ERROR != obj->runtime->gcRuntime->backupSector->info->errors)
{
obj->runtime->gcRuntime->state = FEE_GC_STATE_WRITE_INIT_MARK_ERROR;
obj->runtime->gcRuntime->gcFsm = FEE_GC_ERROR;
FEE_DBG_GC_WRITE_INIT_MARK_ERROR_ENTRY();
}
else
{
Fee_OnEntryGcCopyJob(obj);
obj->runtime->gcRuntime->gcFsm = FEE_GC_COPY;
}
break;
}
case FEE_GC_COPY:
{
/* Handling data job. */
if(Fee_GcCopyJob(obj))
{
/* Erase the active sector after data GC is completed. */
Fee_InitEraseSector(obj->runtime->activeSector);
obj->runtime->activeSector->info->status = FEE_SECTOR_UNUSED;
obj->runtime->gcRuntime->gcFsm = FEE_GC_ERASE_ACTIVESECTOR;
}
if(FEE_GC_COPY_ERROR == obj->runtime->gcRuntime->copyFsm)
{
obj->runtime->gcRuntime->state = FEE_GC_STATE_COPY_ERROR;
obj->runtime->gcRuntime->gcFsm = FEE_GC_ERROR;
}
else if(FEE_SECTOR_NOT_ERROR != obj->runtime->gcRuntime->backupSector->info->errors)
{
obj->runtime->gcRuntime->state = FEE_GC_STATE_COPY_ERROR;
obj->runtime->gcRuntime->gcFsm = FEE_GC_ERROR;
}
else if(FEE_GC_STATE_NO_ERROR != obj->runtime->gcRuntime->state)
{
obj->runtime->gcRuntime->gcFsm = FEE_GC_ERROR;
}
break;
}
case FEE_GC_ERASE_ACTIVESECTOR:
{
/* Erase the active sector after data transfer is completed. */
Fee_EraseSector(obj->runtime->activeSector, obj->flsMethod);
if((FEE_SECTOR_NOT_ERROR == obj->runtime->activeSector->info->errors) && (FEE_SECTOR_ERASE == obj->runtime->activeSector->info->status))
{
obj->runtime->gcRuntime->gcFsm = FEE_GC_FINISH;
}
else if(FEE_SECTOR_NOT_ERROR != obj->runtime->activeSector->info->errors)
{
obj->runtime->gcRuntime->state = FEE_GC_STATE_ERASE_ACTIVE_SECTOR_ERROR;
obj->runtime->gcRuntime->gcFsm = FEE_GC_ERROR;
FEE_DBG_GC_ERASE_ACTIVE_SECTOR_ERROR_ENTRY();
}
break;
}
case FEE_GC_FINISH:
{
/* Write the flag bit of the active sector to the sector info. */
Fee_SectorWriteEnableSectorMark(obj->runtime->gcRuntime->backupSector, obj->flsMethod, obj->buff);
Fee_SectorFillHeadInfo(obj->runtime->gcRuntime->backupSector, obj->flsMethod, obj->buff);
if(FEE_SECTOR_NOT_ERROR != obj->runtime->gcRuntime->backupSector->info->errors)
{
obj->runtime->gcRuntime->state = FEE_GC_STATE_WRITE_ENA_MARK_ERROR;
obj->runtime->gcRuntime->gcFsm = FEE_GC_ERROR;
FEE_DBG_GC_WRITE_ENABLE_MARK_ERROR_ENTRY();
}
else
{
obj->runtime->activeSector = obj->runtime->gcRuntime->backupSector;
obj->runtime->gcRuntime->backupSector = NULL;
obj->runtime->activeSector->info->status = FEE_SECTOR_ACTIVE;
ret = true;
}
break;
}
default:
{
ret = true;
FEE_DBG_GC_FSM_ERROR_ENTRY();
break;
}
}
return ret;
}
static void Fee_OnEntryGcCopyJob(const FeeType *obj)
{
obj->runtime->gcRuntime->copyFsm = FEE_GC_COPY_WRITE_MARK;
obj->runtime->gcRuntime->blockCnt = 0;
}
static bool Fee_GcCopyJob(const FeeType *obj)
{
bool ret = false;
switch(obj->runtime->gcRuntime->copyFsm)
{
case FEE_GC_COPY_WRITE_MARK:
{
/* Write the start transport flag bit to the backup sector. */
Fee_SectorWriteStartHandMark(obj->runtime->gcRuntime->backupSector, obj->flsMethod, obj->buff);
if(FEE_SECTOR_NOT_ERROR != obj->runtime->gcRuntime->backupSector->info->errors)
{
obj->runtime->gcRuntime->copyFsm = FEE_GC_COPY_ERROR;
FEE_DBG_GC_WRITE_START_MARK_ERROR_ENTRY();
}
else
{
obj->runtime->gcRuntime->copyFsm = FEE_GC_COPY_INIT;
}
break;
}
case FEE_GC_COPY_INIT:
{
/* Latest data of index block. */
if(obj->runtime->gcRuntime->blockCnt < obj->sector->blockSize)
{
if(Fee_GcInitBlockInfo(obj, &(obj->sector->blocks[obj->runtime->gcRuntime->blockCnt])))
{
obj->runtime->gcRuntime->copyFsm = FEE_GC_COPY_WRITEBLOCK;
}
else if(FEE_GC_STATE_READ_ERROR == obj->runtime->gcRuntime->state)
{
obj->runtime->gcRuntime->copyFsm = FEE_GC_COPY_ERROR;
}
obj->runtime->gcRuntime->blockCnt++;
}
else
{
obj->runtime->gcRuntime->copyFsm = FEE_GC_COPY_FINISH;
}
break;
}
case FEE_GC_COPY_WRITEBLOCK:
{
/* Write to backup sector. */
if(Fee_GcWriteBlockToNewSector(obj))
{
obj->runtime->gcRuntime->copyFsm = FEE_GC_COPY_INIT;
}
break;
}
case FEE_GC_COPY_FINISH:
{
/* Write the completion handling flag bit to backup sector info. */
Fee_SectorWriteEndHandMark(obj->runtime->gcRuntime->backupSector, obj->flsMethod, obj->buff);
if(FEE_SECTOR_NOT_ERROR != obj->runtime->gcRuntime->backupSector->info->errors)
{
obj->runtime->gcRuntime->copyFsm = FEE_GC_COPY_ERROR;
FEE_DBG_GC_WRITE_END_MARK_ERROR_ENTRY();
}
else
{
ret = true;
}
break;
}
default:
{
FEE_DBG_GC_COPY_FSM_ERROR_ENTRY();
break;
}
}
return ret;
}
static bool Fee_GcInitBlockInfo(const FeeType *obj, const Fee_BlockType *block)
{
bool ret = false;
uint16_t blocksize;
/* Calculate the location and data size of the valid data stored in the block. */
if(NULL != block)
{
obj->runtime->gcRuntime->currentBlock = block;
blocksize = FEE_BLOCKSIZE(obj->runtime->gcRuntime->currentBlock->cfg);
if(NULL != Fee_BlockGetPhyAddr(obj->runtime->gcRuntime->currentBlock->info))
{
if(FLS_STATE_OK != obj->flsMethod->read(obj->runtime->gcRuntime->currentBlock->info->phyAddr, (uint8_t *)obj->buff, blocksize))
{
obj->runtime->gcRuntime->state = FEE_GC_STATE_READ_ERROR;
}
else
{
ret = true;
}
}
}
return ret;
}
static bool Fee_GcWriteBlockToNewSector(const FeeType *obj)
{
bool ret = false;
uint16_t blocksize;
Fee_AddressType tempPhyaddr;
/* Obtain the assigned address of the block in the backup sector. */
blocksize = FEE_BLOCKSIZE(obj->runtime->gcRuntime->currentBlock->cfg);
/* First write the block data to the flash, ensure safe writing, and then write the block header information. */
if(FLS_STATE_OK == obj->flsMethod->write(obj->runtime->gcRuntime->backupSector->info->remAddr, (uint8_t *)obj->buff, blocksize))
{
tempPhyaddr = Fee_BlockGetPhyAddr(obj->runtime->gcRuntime->currentBlock->info);
Fee_BlockSetPhyAddr(obj->runtime->gcRuntime->currentBlock->info, obj->runtime->gcRuntime->backupSector->info->remAddr);
Fee_WriteBlockHeadInfo(obj->runtime->gcRuntime->currentBlock, obj->flsMethod->crc8, obj->buff);
if(FLS_STATE_OK == obj->flsMethod->write(obj->runtime->gcRuntime->backupSector->info->headInfoAddr, (uint8_t *)obj->buff, FEE_BLOCK_HEAD_INFO_SIZE))
{
obj->runtime->gcRuntime->backupSector->info->headInfoAddr -= FEE_BLOCK_HEAD_INFO_SIZE;
ret = true;
}
else
{
Fee_BlockSetPhyAddr(obj->runtime->gcRuntime->currentBlock->info, tempPhyaddr);
obj->runtime->gcRuntime->state = FEE_GC_STATE_WRITE_ERROR;
FEE_DBG_GC_WRITE_BLOCK_HEAD_INFO_ERROR_ENTRY();
}
obj->runtime->gcRuntime->backupSector->info->remAddr += blocksize;
}
else
{
obj->runtime->gcRuntime->state = FEE_GC_STATE_WRITE_ERROR;
FEE_DBG_GC_WRITE_BLOCK_DATA_ERROR_ENTRY();
}
return ret;
}
static const Fee_SectorConfigType *Fee_FoundBackupSector(const FeeType *obj)
{
const Fee_SectorConfigType *backupSector = NULL;
int sectorIdx;
/* Find the backup sector by checking the status of the sector. */
for(sectorIdx = 0; sectorIdx < obj->sector->sectorSize; sectorIdx++)
{
if(FEE_SECTOR_ACTIVE != obj->sector->sectors[sectorIdx].info->status)
{
backupSector = &obj->sector->sectors[sectorIdx];
break;
}
}
return backupSector;
}
static uint16_t Fee_SearchBlock(const Fee_SectorType *obj, uint16_t blockNumber)
{
uint16_t retBlock = FEE_INVALID_BLOCK_INDEX;
uint16_t blockStartIdx = 0;
uint16_t blockMiddleIdx = (obj->blockSize - 1) / 2;
uint16_t blockEndIdx = obj->blockSize - 1;
bool finishFlag = false;
while(false == finishFlag)
{
/* If the current block and the input block are the same. */
if(Fee_BlockCheckBlockNumber(obj->blocks[blockMiddleIdx].cfg, blockNumber))
{
/* Returns the index of the block. */
retBlock = blockMiddleIdx;
finishFlag = true;
}
else
{
/* Currently, there are only two or fewer blocks left that are not found, then check the other block. */
if((blockEndIdx - blockStartIdx) <= 1)
{
finishFlag = true;
if(Fee_BlockCheckBlockNumber(obj->blocks[blockEndIdx].cfg, blockNumber))
{
retBlock = blockEndIdx;
}
}
else
{
/* In descending order, first determine whether it is in the right range, */
/* and then check whether it is in the left range. */
if(obj->blocks[blockMiddleIdx].cfg->number < blockNumber)
{
blockStartIdx = blockMiddleIdx + 1;
}
else
{
blockEndIdx = blockMiddleIdx - 1;
}
/* Calculate Median. */
blockMiddleIdx = blockEndIdx + blockStartIdx;
blockMiddleIdx /= 2;
}
}
}
return retBlock;
}

View File

@ -0,0 +1,136 @@
/*
* 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.
*/
#ifndef _FEE_H_
#define _FEE_H_
/*! \brief Contains public interface to various functions related
* to the FEE (Flash EEPROM Emulation) module
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "fee_types.h"
#include "fee_extra.h"
#include "fee_version.h"
/*! \addtogroup Flash EEPROM Emulation
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Configures the FEE driver
*
* This function configures the FEE driver
*
* \param[in] obj : pointer to FEE driver instance
*/
extern void Fee_Configure(const FeeType *obj);
/*! \brief Main function of FEE driver
*
* This function is the main process of running the FEE driver
*
* \param[in] obj : pointer to FEE driver instance
*/
extern void Fee_MainFunction(const FeeType *obj);
/*! \brief Read the data from FEE
*
* This function reads the data from FEE with given parameters
*
* \param[in] obj : pointer to FEE driver instance
* \param[in] blockNumber : block number to read
* \param[in] blockOffset : offset of dataset defined by user in block
* \param[out] dataBuffer : pointer to the result data buffer
* \param[in] notificationPtr : pointer to the notification callback function
*/
extern Fee_ReturnType Fee_Read(const FeeType *obj, uint16_t blockNumber, uint16_t blockOffset, uint8_t *dataBuffer, NotificationPtrType notificationPtr);
/*! \brief Write the data to FEE
*
* This function writed the data to FEE with given parameters
*
* \param[in] obj : pointer to FEE driver instance
* \param[in] blockNumber : block number to write
* \param[in] dataBuffer : pointer to the data buffer to write
* \param[in] notificationPtr : pointer to the notification callback function
*/
extern Fee_ReturnType Fee_Write(const FeeType *obj, uint16_t blockNumber, uint8_t *dataBuffer, NotificationPtrType notificationPtr);
/*! \brief Cancel the newest request
*
* This function cancels the newest request in the request buffer
*
* \param[in] obj : pointer to FEE driver instance
*/
extern Fee_ReturnType Fee_Cancel(const FeeType *obj);
/*! \brief Get the prev job result
*
* This function gets the prev job result of block
*
* \param[in] obj : pointer to FEE driver instance
*/
extern Fee_JobResultType Fee_GetJobResult(const FeeType *obj);
/*! \brief Get the current running status
*
* This function gets the current running status of FEE
*
* \param[in] obj : pointer to FEE driver instance
*/
extern Fee_StatusType Fee_GetStatus(const FeeType *obj);
/*! \brief Get the version information of this driver
*
* This function gets the version information of this driver.
*
* \param[out] versionInfoPtr : pointer to the version object
*/
extern void Fee_GetVersionInfo(Fee_VersionInfoType *versionInfoPtr);
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _FEE_H_ */

View File

@ -0,0 +1,223 @@
/*
* 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.
*/
#ifndef _FEE_BLOCK_H_
#define _FEE_BLOCK_H_
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "fee_extra.h"
#include "fee_types.h"
/*! \addtogroup Flash EEPROM Emulation
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Macro that defines the size of block info.
*/
#if(defined FEE_BLOCK_HEAD_INFO_SIZE)
#error FEE_BLOCK_HEAD_INFO_SIZE already defined
#endif
#define FEE_BLOCK_HEAD_INFO_SIZE (16)
/*! \brief Macro defining the calculated length of crc8 in block info.
*/
#if(defined FEE_BLOCK_CALC_HEAD_INFO_CRC8_LEN)
#error FEE_BLOCK_CALC_HEAD_INFO_CRC8_LEN already defined
#endif
#define FEE_BLOCK_CALC_HEAD_INFO_CRC8_LEN (12)
/*! \brief Macro that defines the start flag bit index in block info.
*/
#if(defined FEE_BLOCK_HEAD_INFO_START_INFO_IDX)
#error FEE_BLOCK_HEAD_INFO_START_INFO_IDX already defined
#endif
#define FEE_BLOCK_HEAD_INFO_START_INFO_IDX (0)
/*! \brief Macro that defines the index of number in block info.
*/
#if(defined FEE_BLOCK_HEAD_INFO_BLOCK_NUMBER_IDX)
#error FEE_BLOCK_HEAD_INFO_BLOCK_NUMBER_IDX already defined
#endif
#define FEE_BLOCK_HEAD_INFO_BLOCK_NUMBER_IDX (4)
/*! \brief Define the index representing the data address in block info.
*/
#if(defined FEE_BLOCK_HEAD_INFO_PHY_ADDR_IDX)
#error FEE_BLOCK_HEAD_INFO_PHY_ADDR_IDX already defined
#endif
#define FEE_BLOCK_HEAD_INFO_PHY_ADDR_IDX (8)
/*! \brief Define a macro in block info that represents the index of the crc8 result.
*/
#if(defined FEE_BLOCK_HEAD_INFO_CRC8_IDX)
#error FEE_BLOCK_HEAD_INFO_CRC8_IDX already defined
#endif
#define FEE_BLOCK_HEAD_INFO_CRC8_IDX (12)
/*! \brief Macro that defines the start flag bit in block info.
*/
#if(defined FEE_BLOCK_HEAD_INFO_START_INFO)
#error FEE_BLOCK_HEAD_INFO_START_INFO already defined
#endif
#define FEE_BLOCK_HEAD_INFO_START_INFO (0XAAAAAAAA)
/*! \brief Define flash write aligned macros.
*/
#if(defined Fee_BLOCK_WRITE_ALIGNED_SIZE)
#error Fee_BLOCK_WRITE_ALIGNED_SIZE already defined
#endif
#define Fee_BLOCK_WRITE_ALIGNED_SIZE (8)
/*! \brief Macro that defines the valid flag bits of a block.
*/
#if(defined FEE_BLOCK_VALID_WORD)
#error FEE_BLOCK_VALID_WORD already defined
#endif
#define FEE_BLOCK_VALID_WORD (0xAA)
/*! \brief Macro defining block invalid byte padding.
*/
#if(defined FEE_BLOCK_FILL_WORD)
#error FEE_BLOCK_FILL_WORD already defined
#endif
#define FEE_BLOCK_FILL_WORD (0xDD)
/*! \brief Macro that defines an invalid index for a block definition block.
*/
#if(defined FEE_INVALID_BLOCK_INDEX)
#error FEE_INVALID_BLOCK_INDEX already defined
#endif
#define FEE_INVALID_BLOCK_INDEX (0xFFFF)
/*! \brief Define macros for calculating block sizes.
*/
#define FEE_BLOCKSIZE(obj) (ALIGN8BYTE(obj->dataSize))
/*! \brief Used to define whether crc is required in a block.
*/
typedef enum
{
FEE_CRC_NONE = 0x00,
FEE_CRC8 = 0x01,
} Fee_BlockCrcType;
/*! \brief Define the type of block configuration.
*/
typedef struct _Fee_BlockConfigType_
{
uint16_t number;
uint16_t dataSize;
} Fee_BlockConfigType;
/*! \brief Define the type of block runtime information.
*/
typedef struct _Fee_BlockInfoType_
{
Fee_AddressType phyAddr;
} Fee_BlockInfoType;
/*! \brief Define a block type.
*/
typedef struct _Fee_BlockType_
{
const struct _Fee_BlockConfigType_ * cfg;
struct _Fee_BlockInfoType_ * info;
} Fee_BlockType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
__attribute__((always_inline)) static inline void Fee_BlockSetPhyAddr(Fee_BlockInfoType *obj, Fee_AddressType phyAddr)
{
obj->phyAddr = phyAddr;
}
__attribute__((always_inline)) static inline Fee_AddressType Fee_BlockGetPhyAddr(Fee_BlockInfoType *obj)
{
return obj->phyAddr;
}
__attribute__((always_inline)) static inline bool Fee_BlockCheckBlockNumber(const Fee_BlockConfigType *obj, uint16_t blockNumber)
{
bool ret = false;
/* Determine whether the numbers of the incoming blocks are the same. */
if(obj->number == blockNumber)
{
ret = true;
}
return ret;
}
__attribute__((always_inline)) static inline Fee_AddressType Fee_GetBlockHeadPhyAddr(uint8_t *data)
{
uint32_t *phyAddr;
phyAddr = (uint32_t *)&data[FEE_BLOCK_HEAD_INFO_PHY_ADDR_IDX];
return (Fee_AddressType)*phyAddr;
}
__attribute__((always_inline)) static inline void Fee_WriteBlockHeadInfo(const Fee_BlockType *obj, Fee_calcCrc8Type crc8Method, uint8_t *cache)
{
uint32_t *startInfo;
uint16_t *blockNumber;
Fee_AddressType *phyAddr;
uint8_t *crc8;
/* Initialize cache. */
memset((void *)cache, 0x00, FEE_BLOCK_HEAD_INFO_SIZE);
startInfo = (uint32_t *)&cache[FEE_BLOCK_HEAD_INFO_START_INFO_IDX];
blockNumber = (uint16_t *)&cache[FEE_BLOCK_HEAD_INFO_BLOCK_NUMBER_IDX];
phyAddr = (Fee_AddressType *)&cache[FEE_BLOCK_HEAD_INFO_PHY_ADDR_IDX];
crc8 = (uint8_t *)&cache[FEE_BLOCK_HEAD_INFO_CRC8_IDX];
*startInfo = FEE_BLOCK_HEAD_INFO_START_INFO;
*blockNumber = obj->cfg->number;
*phyAddr = obj->info->phyAddr;
*crc8 = crc8Method((void *)cache, FEE_BLOCK_CALC_HEAD_INFO_CRC8_LEN);
}
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _FEE_BLOCK_H_ */

View File

@ -0,0 +1,147 @@
/*
* 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.
*/
#ifndef _FEE_EXTRA_H_
#define _FEE_EXTRA_H_
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
/*! \addtogroup Flash EEPROM Emulation
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*! \brief Define macros that express the address of a feed.
*/
#define Fee_AddressType uint8_t *
/*! \brief Define N-byte aligned macros.
*/
#ifndef ALIGNBYTE
#define ALIGNBYTE(size, n) ((size + n - 1) & ~(n - 1))
#endif
/*! \brief Define 4-byte aligned macros.
*/
#ifndef ALIGN4BYTE
#define ALIGN4BYTE(size) (ALIGNBYTE(size, 4))
#endif
/*! \brief Define 8-byte aligned macros.
*/
#ifndef ALIGN8BYTE
#define ALIGN8BYTE(size) (ALIGNBYTE(size, 8))
#endif
/*! \brief Define 64-byte aligned macros.
*/
#ifndef ALIGN64BYTE
#define ALIGN64BYTE(size) (ALIGNBYTE(size, 64))
#endif
/*! \brief Define address aligned macros.
*/
#ifndef ALIGNED
#define ALIGNED(val, alncnt) (((uint32_t)val) & ~(alncnt - 1))
#endif
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Define the type of the Notification return value.
*/
typedef enum
{
FEE_JOBENDNOTIFICATION = 0x00,
FEE_JOBERRORNOTIFICATION = 0x01,
} Fee_NotificationType;
/*! \brief Define the type of return value for flash operations.
*/
typedef enum
{
FLS_STATE_OK = 0x00,
FLS_STATE_NOT_WRITABLE = 0x01,
FLS_STATE_ECC_ERROR = 0x02,
FLS_STATE_READ_BACK_FAIL = 0x04,
FLS_STATE_PROGRAM_FAIL = 0x05,
FLS_STATE_ERASE_FAIL = 0x05,
FLS_STATE_NOT_WRITTEN = 0x07,
FLS_STATE_UNKNOW = 0x08,
}Fls_StateType;
/*! \brief Define the type of virtual function for Notification.
*/
typedef void (*NotificationPtrType)(Fee_NotificationType notificationNumber);
/*! \brief Define the type of virtual function for writing flash operations.
*/
typedef Fls_StateType (*Fee_writeMethodType)(Fee_AddressType sAddr, uint8_t *buff, uint32_t size);
/*! \brief Define virtual function types for read flash operations.
*/
typedef Fls_StateType (*Fee_readMethodType)(Fee_AddressType sAddr, uint8_t *buff, uint32_t size);
/*! \brief Define virtual function types for erasing flash operations.
*/
typedef Fls_StateType (*Fee_eraseMethodType)(Fee_AddressType eraseAddr);
/*! \brief Define virtual function types to check whether flash is writable.
*/
typedef Fls_StateType (*Fee_isWriteableType)(Fee_AddressType sAddr, uint32_t size);
/*! \brief Define virtual function types for calculating crc8.
*/
typedef uint8_t (*Fee_calcCrc8Type)(void *sAddr, uint32_t size);
/*! \brief Define the type of the feed operation flash method.
*/
typedef struct _Fee_MethodType_
{
Fee_writeMethodType write;
Fee_readMethodType read;
Fee_eraseMethodType erase;
Fee_isWriteableType isWriteable;
Fee_calcCrc8Type crc8;
} Fee_MethodType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _FEE_EXTRA_H_ */

View File

@ -0,0 +1,271 @@
/*
* 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 <stddef.h>
#include "fee_initialization.h"
#include "fee_extra.h"
#include "fee_types.h"
#include "fee_trace.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the static
******************************************************************************/
static void Fee_InitializationCheckSector(const FeeType *obj);
static void Fee_InitializationSector(const FeeType *obj);
static void Fee_InitializationFindActiveSector(const FeeType *obj);
static void Fee_InitializationGcRepairSector(const FeeType *obj);
static void Fee_InitializationFirstSector(const FeeType *obj);
static void Fee_InitializationUnEraseSector(const FeeType *obj);
static void Fee_InitializationEraseSector(const FeeType *obj);
static void Fee_InitializationFinish(const FeeType *obj);
/*******************************************************************************
* the functions
******************************************************************************/
void Fee_EntryInitialization(const FeeType *obj)
{
obj->runtime->initializationFsm = FEE_INITIALIZATION_SECTOR;
}
bool Fee_InitializationJob(const FeeType *obj)
{
bool ret = false;
switch(obj->runtime->initializationFsm)
{
case FEE_INITIALIZATION_SECTOR:
{
Fee_InitializationSector(obj);
break;
}
case FEE_INITIALIZATION_CHECK_SECTOR:
{
Fee_InitializationCheckSector(obj);
break;
}
case FEE_INITIALIZATION_FIND_ACTIVE_SECTOR:
{
Fee_InitializationFindActiveSector(obj);
break;
}
case FEE_INITIALIZATION_ERASE_SECTOR:
{
Fee_InitializationEraseSector(obj);
break;
}
case FEE_INITIALIZATION_UNINITIALIZATION_ERASE_SECTOR:
{
Fee_InitializationUnEraseSector(obj);
break;
}
case FEE_INITIALIZATION_UNINITIALIZATION:
{
Fee_InitializationFirstSector(obj);
break;
}
case FEE_INITIALIZATION_GC_REPAIR_SECTOR:
{
Fee_InitializationGcRepairSector(obj);
break;
}
case FEE_INITIALIZATION_FINISH:
{
Fee_InitializationFinish(obj);
ret = true;
break;
}
default:
{
FEE_DBG_INITIALIZATION_FSM_ERROR_ENTRY();
break;
}
}
return ret;
}
static void Fee_InitializationCheckSector(const FeeType *obj)
{
int sectorIdx;
for(sectorIdx = 0; sectorIdx < obj->sector->sectorSize; sectorIdx++)
{
Fee_SectorCheckErase(&obj->sector->sectors[sectorIdx], obj->flsMethod);
if (FEE_SECTOR_ERASE != Fee_SectorGetStatus(&obj->sector->sectors[sectorIdx]))
{
Fee_CheckSectorIsValid(&obj->sector->sectors[sectorIdx], obj->flsMethod, (uint8_t *)obj->buff);
}
}
/* Initialize the state machine to the next state */
obj->runtime->initializationFsm = FEE_INITIALIZATION_FIND_ACTIVE_SECTOR;
}
static void Fee_InitializationSector(const FeeType *obj)
{
/* Initialize sector runtime data. */
Fee_SectorsInit(obj->sector, obj->flsMethod, obj->buff);
/* Initialize the state machine to the default state. */
obj->runtime->initializationFsm = FEE_INITIALIZATION_CHECK_SECTOR;
}
static void Fee_InitializationFindActiveSector(const FeeType *obj)
{
const Fee_SectorConfigType *activeSector;
const Fee_SectorConfigType *gcSector;
/* Initialize the state machine. */
obj->runtime->initializationFsm = FEE_INITIALIZATION_UNINITIALIZATION;
/* The activity sector value is NULL. */
obj->runtime->activeSector = NULL;
/* Find the active sector. */
activeSector = Fee_SearchValidSector(obj->sector);
/* Check if the active sector is found. */
if(activeSector != NULL)
{
obj->runtime->activeSector = activeSector;
obj->runtime->initializationFsm = FEE_INITIALIZATION_FINISH;
}
/* The backup sector value is NULL. */
obj->runtime->gcRuntime->backupSector = NULL;
/* Find the backup sector. */
gcSector = Fee_SearchGcSector(obj->sector);
/* Check if the backup sector is found. */
if(gcSector != NULL)
{
/* Check whether the backup section is in the transportation completion state. */
/* If not, check whether it is in the state before the transportation is completed. */
if(FEE_SECTOR_END_HAND_FINISH == gcSector->info->status)
{
/* Execute the sector repair program. */
obj->runtime->gcRuntime->backupSector = gcSector;
obj->runtime->initializationFsm = FEE_INITIALIZATION_GC_REPAIR_SECTOR;
}
else if(FEE_SECTOR_END_HAND_FINISH > gcSector->info->status)
{
/* Check whether there is an active sector. */
if(NULL == obj->runtime->activeSector)
{
/* Execute the reinitialization of the sector program. */
obj->runtime->initializationFsm = FEE_INITIALIZATION_UNINITIALIZATION;
}
}
}
}
static void Fee_InitializationGcRepairSector(const FeeType *obj)
{
/* If there is no active sector, flip the backup sector to the active state. */
if(NULL == obj->runtime->activeSector)
{
obj->runtime->activeSector = obj->runtime->gcRuntime->backupSector;
}
obj->runtime->initializationFsm = FEE_INITIALIZATION_FINISH;
}
static void Fee_InitializationFirstSector(const FeeType *obj)
{
const Fee_SectorConfigType *activeSector;
/* Get the first sector. */
activeSector = Fee_GetFirstSector(obj->sector);
/* Check whether the active sector is found. */
if(activeSector != NULL)
{
/* Initialize the active sector. */
obj->runtime->activeSector = activeSector;
Fee_InitEraseSector(obj->runtime->activeSector);
obj->runtime->initializationFsm = FEE_INITIALIZATION_UNINITIALIZATION_ERASE_SECTOR;
}
else
{
obj->runtime->initializationFsm = FEE_INITIALIZATION_ERROR;
}
}
static void Fee_InitializationUnEraseSector(const FeeType *obj)
{
/* Erase active sector. */
Fee_EraseSector(obj->runtime->activeSector, obj->flsMethod);
/* Check whether the active sector is in the error state. */
/* If not, check whether it is in the erase state. */
if(FEE_SECTOR_NOT_ERROR != obj->runtime->activeSector->info->errors)
{
obj->runtime->initializationFsm = FEE_INITIALIZATION_ERROR;
}
else if(FEE_SECTOR_ERASE == obj->runtime->activeSector->info->status)
{
/* Initialize the active sector. */
obj->runtime->activeSector->info->status = FEE_SECTOR_UNUSED;
Fee_SectorWriteHeadInfo(obj->runtime->activeSector, obj->flsMethod, obj->buff);
obj->runtime->initializationFsm = FEE_INITIALIZATION_FINISH;
}
}
static void Fee_InitializationEraseSector(const FeeType *obj)
{
/* Erase active sector. */
Fee_EraseSector(obj->runtime->activeSector, obj->flsMethod);
/* Check whether the active sector is in the error state. */
/* If not, check whether it is in the erase state. */
if(FEE_SECTOR_NOT_ERROR != obj->runtime->activeSector->info->errors)
{
obj->runtime->initializationFsm = FEE_INITIALIZATION_ERROR;
}
else if(FEE_SECTOR_ERASE == obj->runtime->activeSector->info->status)
{
obj->runtime->initializationFsm = FEE_INITIALIZATION_FINISH;
}
}
static void Fee_InitializationFinish(const FeeType *obj)
{
/* Check whether the active sector is NULL. */
if(obj->runtime->activeSector != NULL)
{
/* Set the state of the active sector to the actvie state. */
obj->runtime->activeSector->info->status = FEE_SECTOR_ACTIVE;
}
else
{
/* An irretrievable mistake. */
FEE_DBG_STORAGE_ERROR_ENTRY();
}
}

View File

@ -0,0 +1,74 @@
/*
* 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.
*/
#ifndef _FEE_INITIALIZATION_H_
#define _FEE_INITIALIZATION_H_
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "fee_types.h"
/*! \addtogroup Flash EEPROM Emulation
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Internal initializtion
*
* This function is the internal initializtion FEE driver
*
* \param[in] obj : pointer to FEE driver instance
*/
extern void Fee_EntryInitialization(const FeeType *obj);
/*! \brief Initialize job of FEE
*
* This function implemente the initialiazation job of FEE
*
* \param[in] obj : pointer to FEE driver instance
*/
extern bool Fee_InitializationJob(const FeeType *obj);
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _FEE_INITIALIZATION_H_ */

View File

@ -0,0 +1,205 @@
/*
* 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.
*/
#ifndef _FEE_JOBS_H_
#define _FEE_JOBS_H_
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "fee_extra.h"
/*! \addtogroup Flash EEPROM Emulation
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Job's request type definition.
*/
typedef enum
{
FEE_JOB_OP_UNDEFINE = 0x00,
FEE_JOB_OP_READ = 0x01,
FEE_JOB_OP_WRITE = 0x02,
FEE_JOB_OP_GC = 0x03,
} Fee_JobOpType;
/*! \brief Definition of mutex type for job.
*/
typedef enum
{
FEE_JOB_LOCK = 0x01,
FEE_JOB_UNLOCK = 0x02,
} Fee_JobLockType;
/*! \brief Control block type definition for job.
*/
typedef struct _Fee_JobControlBlockType_
{
Fee_JobLockType lock;
uint16_t blockIdx;
uint16_t blockOffset;
Fee_JobOpType op;
uint8_t *dataBuffPtr;
NotificationPtrType notificationPtr;
} Fee_JobControlBlockType;
/*! \brief Job object type definition.
*/
typedef struct _Fee_JobsType_
{
bool accept;
struct _Fee_JobControlBlockType_ *userJob;
struct _Fee_JobControlBlockType_ *sysJob;
} Fee_JobsType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
__attribute__((always_inline)) static inline void Fee_InitJob(Fee_JobControlBlockType *obj)
{
obj->lock = FEE_JOB_UNLOCK;
obj->blockIdx = 0x0000;
obj->blockOffset = 0x0000;
obj->op = FEE_JOB_OP_UNDEFINE;
obj->dataBuffPtr = NULL;
obj->notificationPtr = NULL;
}
__attribute__((always_inline)) static inline void Fee_DisableJobs(Fee_JobsType *obj)
{
obj->accept = false;
}
__attribute__((always_inline)) static inline void Fee_EnableJobs(Fee_JobsType *obj)
{
obj->accept = true;
}
__attribute__((always_inline)) static inline bool Fee_QueryUserJobIsLock(Fee_JobsType *obj)
{
bool result = false;
/* Check whether the mutex of the user job is locked. */
/* If it is locked, return true. */
if(FEE_JOB_LOCK == obj->userJob->lock)
{
result = true;
}
return result;
}
__attribute__((always_inline)) static inline bool Fee_QuerySysJobIsLock(Fee_JobsType *obj)
{
bool result = false;
/* Check whether the mutex of the system job is locked. */
/* If it is locked, return true. */
if(FEE_JOB_LOCK == obj->sysJob->lock)
{
result = true;
}
return result;
}
__attribute__((always_inline)) static inline bool Fee_GetUserJob(Fee_JobsType *obj, Fee_JobControlBlockType *config)
{
bool result = false;
if(Fee_QueryUserJobIsLock(obj))
{
(*config) = *obj->userJob;
result = true;
}
return result;
}
__attribute__((always_inline)) static inline bool Fee_GetSysJob(Fee_JobsType *obj, Fee_JobControlBlockType *config)
{
bool result = false;
if(Fee_QuerySysJobIsLock(obj))
{
(*config) = *obj->sysJob;
result = true;
}
return result;
}
__attribute__((always_inline)) static inline bool Fee_SetUserJob(Fee_JobsType *obj, Fee_JobControlBlockType *config)
{
bool result = false;
/* To check whether the user job can accept requests, */
/* it is necessary to check whether the user job is allowed to accept requests by the feed. */
/* In addition, it is also necessary to check whether the user job mutex is unlocked. */
if((obj->accept) && (false == Fee_QueryUserJobIsLock(obj)))
{
*obj->userJob = *config;
obj->userJob->lock = FEE_JOB_LOCK;
result = true;
}
return result;
}
__attribute__((always_inline)) static inline bool Fee_SetSysJob(Fee_JobsType *obj, Fee_JobControlBlockType *config)
{
bool result = false;
/* To check whether the system job can accept requests, */
/* it is necessary to check whether the user job is allowed to accept requests by the feed. */
/* In addition, it is also necessary to check whether the system job mutex is unlocked. */
if((obj->accept) && (false == Fee_QuerySysJobIsLock(obj)))
{
*obj->sysJob = *config;
obj->sysJob->lock = FEE_JOB_LOCK;
result = true;
}
return result;
}
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _FEE_JOBS_H_ */

View File

@ -0,0 +1,884 @@
/*
* 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.
*/
#ifndef _FEE_SECTOR_H_
#define _FEE_SECTOR_H_
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "fee_block.h"
#include "fee_extra.h"
#include "fee_trace.h"
#include "fee_types.h"
/*! \addtogroup Flash EEPROM Emulation
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*! \brief Macro that defines the number of flags contained in the section header.
*/
#if(defined FEE_SECTOR_HEAD_MARK_NUM)
#error FEE_SECTOR_HEAD_MARK_NUM already defined
#endif
#define FEE_SECTOR_HEAD_MARK_NUM (4)
/*! \brief Macro for the size of the sector header information flag header.
*/
#if(defined FEE_SECTOR_HEAD_SIZE)
#error FEE_SECTOR_HEAD_SIZE already defined
#endif
#define FEE_SECTOR_HEAD_SIZE (64)
/*! \brief Defines the minimum unit of sector size,
* which depends on the hardware of the flash and needs to be aligned with the flash section.
*/
#if(defined FEE_SECTION_LENGTH)
#error FEE_SECTION_LENGTH already defined
#endif
#define FEE_SECTION_LENGTH (1024)
/*! \brief Define the size of each flag bit in the sector header.
*/
#if(defined FEE_SECTOR_HEAD_INFO_LEN)
#error FEE_SECTOR_HEAD_INFO_LEN already defined
#endif
#define FEE_SECTOR_HEAD_INFO_LEN (8)
/*! \brief Define the size of the backup redundancy area for each flag bit in the sector header.
*/
#if(defined FEE_SECTOR_HEAD_INFO_BACKUP_AREA_LEN)
#error FEE_SECTOR_HEAD_INFO_BACKUP_AREA_LEN already defined
#endif
#define FEE_SECTOR_HEAD_INFO_BACKUP_AREA_LEN (4)
/*! \brief Defines the index of the header of the flag bit in the sector information header.
*/
#if(defined FEE_SECTOR_HEAD_MARK_IDX)
#error FEE_SECTOR_HEAD_MARK_IDX already defined
#endif
#define FEE_SECTOR_HEAD_MARK_IDX (0)
/*! \brief The index of the FLAG that defines the flag bits in the sector header.
*/
#if(defined FEE_SECTOR_HEAD_FLAG_IDX)
#error FEE_SECTOR_HEAD_FLAG_IDX already defined
#endif
#define FEE_SECTOR_HEAD_FLAG_IDX (1)
/*! \brief The index that defines the fill of the flag bit in the sector header.
*/
#if(defined FEE_SECTOR_HEAD_FILL_IDX)
#error FEE_SECTOR_HEAD_FILL_IDX already defined
#endif
#define FEE_SECTOR_HEAD_FILL_IDX (2)
/*! \brief Defines the index of the crc8 flag bit in the sector header.
*/
#if(defined FEE_SECTOR_HEAD_CRC_IDX)
#error FEE_SECTOR_HEAD_CRC_IDX already defined
#endif
#define FEE_SECTOR_HEAD_CRC_IDX (3)
/*! \brief Macro that defines the calculated length of the crc8 flag bit in the sector header.
*/
#if(defined FEE_SECTOR_HEAD_CRC_LEN)
#error FEE_SECTOR_HEAD_CRC_LEN already defined
#endif
#define FEE_SECTOR_HEAD_CRC_LEN (3)
/*! \brief Macro that defines the header of the flag bit in the sector information header.
*/
#if(defined FEE_SECTOR_VALID_WORD)
#error FEE_SECTOR_VALID_WORD already defined
#endif
#define FEE_SECTOR_VALID_WORD (0X5A)
/*! \brief Macro that defines the header of the flag bit in the sector information header.
*/
#if(defined FEE_SECTOR_INIT_FLAG_WORD)
#error FEE_SECTOR_INIT_FLAG_WORD already defined
#endif
#define FEE_SECTOR_INIT_FLAG_WORD (0X01)
/*! \brief Macro that defines the initialization status flag bits in the sector header.
*/
#if(defined FEE_SECTOR_INIT_START_FLAG_WORD)
#error FEE_SECTOR_INIT_START_FLAG_WORD already defined
#endif
#define FEE_SECTOR_INIT_START_FLAG_WORD (0X02)
/*! \brief Macro that defines the transport completion status flag bit in the sector header.
*/
#if(defined FEE_SECTOR_INIT_WRITE_END_FLAG_WORD)
#error FEE_SECTOR_INIT_WRITE_END_FLAG_WORD already defined
#endif
#define FEE_SECTOR_INIT_WRITE_END_FLAG_WORD (0X03)
/*! \brief Macro that defines the enable sector status flag bits in the sector header.
*/
#if(defined FEE_SECTOR_INIT_ENABLE_FLAG_WORD)
#error FEE_SECTOR_INIT_ENABLE_FLAG_WORD already defined
#endif
#define FEE_SECTOR_INIT_ENABLE_FLAG_WORD (0X04)
/*! \brief Define macros that need to be filled in the sector.
*/
#if(defined FEE_SECTOR_FILL_WORD)
#error FEE_SECTOR_FILL_WORD already defined
#endif
#define FEE_SECTOR_FILL_WORD (0x00)
/*! \brief Macro that defines the position of the sector initialization flag bit in the sector header information.
*/
#define FEE_SECTOR_INIT_IDX (0)
/*! \brief Macro that defines the position of the start moving flag bit in the sector header information.
*/
#define FEE_SECTOR_START_HAND_IDX (8)
/*! \brief A macro that defines the position of the transport end flag bit in the sector header information.
*/
#define FEE_SECTOR_END_HAND_IDX (16)
/*! \brief Macro that defines the position of the enable flag bit in the sector header information.
*/
#define FEE_SECTOR_EN_SECTOR_IDX (24)
/*! \brief Define macros for marking data addresses in the backup sector header.
*/
#define FEE_SECTOR_BACKUP_HEAD_ADDR(obj) (obj->endAddr - FEE_SECTOR_HEAD_SIZE)
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Define the type of sector state.
*/
typedef enum
{
FEE_SECTOR_INIT = 0x00,
FEE_SECTOR_INIT_FINISH = 0x01,
FEE_SECTOR_START_HAND = 0x02,
FEE_SECTOR_START_HAND_FINISH = 0x03,
FEE_SECTOR_END_HAND = 0x04,
FEE_SECTOR_END_HAND_FINISH = 0x05,
FEE_SECTOR_EN = 0x06,
FEE_SECTOR_EN_FINISH = 0x07,
FEE_SECTOR_UNUSED = 0x08,
FEE_SECTOR_ACTIVE = 0x09,
FEE_SECTOR_ERASE = 0x0A,
FEE_SECTOR_UNDEFINE = 0xFF,
} Fee_SectorStatusType;
/*! \brief Define sector error types.
*/
typedef enum
{
FEE_SECTOR_NOT_ERROR = 0x00000000,
FEE_SECTOR_READ_ERROR = 0x00000001,
FEE_SECTOR_WRITE_ERROR = 0x00000002,
FEE_SECTOR_ERASE_ERROR = 0x00000004,
FEE_SECTOR_ADDR_NOALIGNED = 0x00000008,
FEE_SECTOR_WRITE_EN_MARK_ERROR = 0x00000010,
FEE_SECTOR_WRITE_INIT_MARK_ERROR = 0x00000020,
FEE_SECTOR_WRITE_START_MARK_ERROR = 0x00000040,
FEE_SECTOR_WRITE_END_MARK_ERROR = 0x00000080,
FEE_SECTOR_WRITE_FINISH_MARK_ERROR = 0x00000100,
FEE_SECTOR_WRITE_HEAD_FILL_ERROR = 0x00000200,
FEE_SECTOR_UNDEFINE_ERROR = 0x00000400,
} Fee_SectorErrorType;
/*! \brief Define the type of external state feedback from the sector.
*/
typedef enum
{
FEE_SECTOR_RETURN_SECTOR1_ACTIVE = 0x01,
FEE_SECTOR_RETURN_SECTOR2_ACTIVE = 0x02,
FEE_SECTOR_RETURN_SECTOR1_ACTIVE_SECTOR2_UNERASE = 0x03,
FEE_SECTOR_RETURN_SECTOR2_ACTIVE_SECTOR1_UNERASE = 0x04,
FEE_SECTOR_RETURN_UNINITIALIZATION = 0x05,
FEE_SECTOR_RETURN_SECTOR1_UNERASE = 0x06,
FEE_SECTOR_RETURN_SECTOR2_UNERASE = 0x07,
FEE_SECTOR_RETURN_UNDEFINE = 0x08,
} Fee_SectorReturnType;
/*! \brief Define the type of sector runtime information.
*/
typedef struct _Fee_SectorInfoType_
{
Fee_AddressType searchAddr;
Fee_AddressType remAddr;
Fee_AddressType headInfoAddr;
uint32_t eraseSectionIdx;
Fee_SectorStatusType status;
Fee_SectorErrorType errors;
} Fee_SectorInfoType;
/*! \brief Define the type of sector configuration information.
*/
typedef struct _Fee_SectorConfigType_
{
Fee_AddressType startAddr;
Fee_AddressType endAddr;
uint32_t const eraseSectionNum;
struct _Fee_SectorInfoType_ *const info;
} Fee_SectorConfigType;
/*! \brief Define the type of the sector object.
*/
typedef struct _Fee_SectorType_
{
uint16_t sectorSize;
const struct _Fee_SectorConfigType_ *sectors;
uint16_t blockSize;
const struct _Fee_BlockType_ *blocks;
} Fee_SectorType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
__attribute__((always_inline)) static inline bool Fee_SectorIsErase(const Fee_SectorConfigType *obj, const Fee_MethodType *method)
{
bool ret = true;
uint32_t sectionIdx;
/* Check whether all the flash space of the sector is writable. */
for(sectionIdx = 0; sectionIdx < obj->eraseSectionNum; sectionIdx++)
{
if(FLS_STATE_NOT_WRITABLE == method->isWriteable((Fee_AddressType)(obj->startAddr + sectionIdx * FEE_SECTION_LENGTH), FEE_SECTION_LENGTH))
{
ret = false;
break;
}
}
return ret;
}
__attribute__((always_inline)) static inline void Fee_SectorCheckErase(const Fee_SectorConfigType *obj, const Fee_MethodType *method)
{
if (Fee_SectorIsErase(obj, method))
{
obj->info->status = FEE_SECTOR_ERASE;
}
}
__attribute__((always_inline)) static inline bool Fee_CheckSectorIsInitFinished(const Fee_calcCrc8Type method, uint8_t *cache)
{
bool ret = false;
uint8_t crc;
/* The flag bits of the sector header information are composed of a start flag, */
/* a status flag, an idle bit fill, and a crc8 check code to check the integrity of the flag bit data. */
crc = method(cache, FEE_SECTOR_HEAD_CRC_LEN);
if(cache[FEE_SECTOR_HEAD_CRC_IDX] == crc)
{
if(FEE_SECTOR_VALID_WORD == cache[FEE_SECTOR_HEAD_MARK_IDX])
{
if(FEE_SECTOR_INIT_FLAG_WORD == cache[FEE_SECTOR_HEAD_FLAG_IDX])
{
if(FEE_SECTOR_FILL_WORD == cache[FEE_SECTOR_HEAD_FILL_IDX])
{
ret = true;
}
}
}
}
return ret;
}
__attribute__((always_inline)) static inline bool Fee_CheckSectorIsStartHand(const Fee_calcCrc8Type method, uint8_t *cache)
{
bool ret = false;
uint8_t crc;
/* The flag bits of the sector header information are composed of a start flag, */
/* a status flag, an idle bit fill, and a crc8 check code to check the integrity of the flag bit data. */
crc = method(cache, FEE_SECTOR_HEAD_CRC_LEN);
if(cache[FEE_SECTOR_HEAD_CRC_IDX] == crc)
{
if(FEE_SECTOR_VALID_WORD == cache[FEE_SECTOR_HEAD_MARK_IDX])
{
if(FEE_SECTOR_INIT_START_FLAG_WORD == cache[FEE_SECTOR_HEAD_FLAG_IDX])
{
if(FEE_SECTOR_FILL_WORD == cache[FEE_SECTOR_HEAD_FILL_IDX])
{
ret = true;
}
}
}
}
return ret;
}
__attribute__((always_inline)) static inline bool Fee_CheckSectorIsEndHand(const Fee_calcCrc8Type method, uint8_t *cache)
{
bool ret = false;
uint8_t crc;
/* The flag bits of the sector header information are composed of a start flag, */
/* a status flag, an idle bit fill, and a crc8 check code to check the integrity of the flag bit data. */
crc = method(cache, FEE_SECTOR_HEAD_CRC_LEN);
if(cache[FEE_SECTOR_HEAD_CRC_IDX] == crc)
{
if(FEE_SECTOR_VALID_WORD == cache[FEE_SECTOR_HEAD_MARK_IDX])
{
if(FEE_SECTOR_INIT_WRITE_END_FLAG_WORD == cache[FEE_SECTOR_HEAD_FLAG_IDX])
{
if(FEE_SECTOR_FILL_WORD == cache[FEE_SECTOR_HEAD_FILL_IDX])
{
ret = true;
}
}
}
}
return ret;
}
__attribute__((always_inline)) static inline bool Fee_CheckSectorIsEnSector(const Fee_calcCrc8Type method, uint8_t *cache)
{
bool ret = false;
uint8_t crc;
/* The flag bits of the sector header information are composed of a start flag, */
/* a status flag, an idle bit fill, and a crc8 check code to check the integrity of the flag bit data. */
crc = method(cache, FEE_SECTOR_HEAD_CRC_LEN);
if(cache[FEE_SECTOR_HEAD_CRC_IDX] == crc)
{
if(FEE_SECTOR_VALID_WORD == cache[FEE_SECTOR_HEAD_MARK_IDX])
{
if(FEE_SECTOR_INIT_ENABLE_FLAG_WORD == cache[FEE_SECTOR_HEAD_FLAG_IDX])
{
if(FEE_SECTOR_FILL_WORD == cache[FEE_SECTOR_HEAD_FILL_IDX])
{
ret = true;
}
}
}
}
return ret;
}
__attribute__((always_inline)) static inline void Fee_UpdateSectorStatus(const Fee_SectorConfigType *obj, const Fee_calcCrc8Type method, uint8_t *data)
{
if(Fee_CheckSectorIsInitFinished(method, &data[FEE_SECTOR_INIT_IDX]) || Fee_CheckSectorIsInitFinished(method, &data[FEE_SECTOR_INIT_IDX + FEE_SECTOR_HEAD_INFO_BACKUP_AREA_LEN]))
{
obj->info->status = FEE_SECTOR_INIT_FINISH;
}
else
{
return;
}
if(Fee_CheckSectorIsStartHand(method, &data[FEE_SECTOR_START_HAND_IDX]) || Fee_CheckSectorIsStartHand(method, &data[FEE_SECTOR_START_HAND_IDX + FEE_SECTOR_HEAD_INFO_BACKUP_AREA_LEN]))
{
obj->info->status = FEE_SECTOR_START_HAND_FINISH;
}
else
{
return;
}
if(Fee_CheckSectorIsEndHand(method, &data[FEE_SECTOR_END_HAND_IDX]) || Fee_CheckSectorIsEndHand(method, &data[FEE_SECTOR_END_HAND_IDX + FEE_SECTOR_HEAD_INFO_BACKUP_AREA_LEN]))
{
obj->info->status = FEE_SECTOR_END_HAND_FINISH;
}
else
{
return;
}
if(Fee_CheckSectorIsEnSector(method, &data[FEE_SECTOR_EN_SECTOR_IDX]) || Fee_CheckSectorIsEnSector(method, &data[FEE_SECTOR_EN_SECTOR_IDX + FEE_SECTOR_HEAD_INFO_BACKUP_AREA_LEN]))
{
obj->info->status = FEE_SECTOR_EN_FINISH;
}
else
{
return;
}
}
__attribute__((always_inline)) static inline void Fee_CheckSectorIsValid(const Fee_SectorConfigType *obj, const Fee_MethodType *method, uint8_t *cache)
{
/* When it is detected that the header information of a sector is not writable, */
/* it will be checked to see if the sector is in an active state. */
/* The sector initialization flag, the start of transport flag, the transport completion flag, */
/* and the enable sector flag should be checked respectively. */
/* Only when all flag bits are checked to be valid can they be considered active sectors.*/
Fls_StateType flsState;
flsState = method->read(obj->startAddr, cache, FEE_SECTOR_HEAD_SIZE);
if(FLS_STATE_OK == flsState)
{
Fee_UpdateSectorStatus(obj, method->crc8, cache);
}
else if ((FLS_STATE_ECC_ERROR == flsState) || (FLS_STATE_READ_BACK_FAIL == flsState))
{
flsState = method->read(FEE_SECTOR_BACKUP_HEAD_ADDR(obj), cache, FEE_SECTOR_HEAD_SIZE);
if(FLS_STATE_OK == flsState)
{
Fee_UpdateSectorStatus(obj, method->crc8, cache);
}
else
{
obj->info->errors = FEE_SECTOR_READ_ERROR;
}
}
else if (FLS_STATE_NOT_WRITTEN == flsState)
{
obj->info->status = FEE_SECTOR_UNDEFINE;
}
else
{
obj->info->errors = FEE_SECTOR_READ_ERROR;
}
}
__attribute__((always_inline)) static inline void Fee_SectorInitInfo(const Fee_SectorConfigType *obj)
{
obj->info->remAddr = obj->startAddr + FEE_SECTOR_HEAD_SIZE;
obj->info->headInfoAddr = obj->endAddr - FEE_SECTOR_HEAD_SIZE - FEE_BLOCK_HEAD_INFO_SIZE;
obj->info->searchAddr = obj->endAddr - FEE_SECTOR_HEAD_SIZE - FEE_BLOCK_HEAD_INFO_SIZE;
obj->info->errors = FEE_SECTOR_NOT_ERROR;
obj->info->status = FEE_SECTOR_UNDEFINE;
}
__attribute__((always_inline)) static inline void Fee_SectorsInit(const Fee_SectorType *obj, const Fee_MethodType *method, void *cache)
{
int sectorIdx;
/* Reset the information of the sector runtime and check the status of the sector based on its header information. */
for(sectorIdx = 0; sectorIdx < obj->sectorSize; sectorIdx++)
{
Fee_SectorInitInfo(&obj->sectors[sectorIdx]);
}
}
__attribute__((always_inline)) static inline bool Fee_CheckRemSpace(const Fee_SectorConfigType *obj, const Fee_BlockType *block)
{
bool ret = false;
uint16_t freeSize;
int preFreeSize;
/* Calculation of sector free space size: */
/* Total space - Space occupied by block info - Space occupied by block data - 64Byte sector header information - 8-byte placeholder. */
/* In order to prevent the area of block info and block data from crossing each other's boundaries, */
/* at least one flash phrase size placeholder should be reserved. */
freeSize = obj->info->headInfoAddr - obj->info->remAddr;
preFreeSize = freeSize - FEE_BLOCKSIZE(block->cfg) - FEE_BLOCK_HEAD_INFO_SIZE - Fee_BLOCK_WRITE_ALIGNED_SIZE;
if(preFreeSize > 0)
{
ret = true;
}
return ret;
}
__attribute__((always_inline)) static inline const Fee_SectorConfigType *Fee_GetFirstSector(const Fee_SectorType *obj)
{
const Fee_SectorConfigType *ret = NULL;
if(obj->sectors != NULL)
{
ret = &obj->sectors[0];
}
return ret;
}
__attribute__((always_inline)) static inline const Fee_SectorConfigType *Fee_SearchValidSector(const Fee_SectorType *obj)
{
const Fee_SectorConfigType *ret = NULL;
int sectorEnFinshCnt = 0;
int sectorIdx;
for(sectorIdx = 0; sectorIdx < obj->sectorSize; sectorIdx++)
{
if((FEE_SECTOR_EN_FINISH == obj->sectors[sectorIdx].info->status) && (FEE_SECTOR_NOT_ERROR == obj->sectors[sectorIdx].info->errors))
{
sectorEnFinshCnt++;
ret = &obj->sectors[sectorIdx];
}
}
if(sectorEnFinshCnt != 1)
{
FEE_DBG_SEARCH_MULTIPLE_VALID_SECTOR_ERROR_ENTRY();
ret = NULL;
}
return ret;
}
__attribute__((always_inline)) static inline const Fee_SectorConfigType *Fee_SearchGcSector(const Fee_SectorType *obj)
{
const Fee_SectorConfigType *ret = NULL;
bool gcSectorCnt = 0;
int sectorIdx;
/* When switching from one sector to another, */
/* first look for sectors with a status of either unint or not active. */
for(sectorIdx = 0; sectorIdx < obj->sectorSize; sectorIdx++)
{
if((obj->sectors[sectorIdx].info->status < FEE_SECTOR_EN_FINISH) && (FEE_SECTOR_NOT_ERROR == obj->sectors[sectorIdx].info->errors))
{
gcSectorCnt++;
ret = &obj->sectors[sectorIdx];
}
}
if(gcSectorCnt != 1)
{
FEE_DBG_SEARCH_MULTIPLE_GC_SECTOR_ERROR_ENTRY();
ret = NULL;
}
return ret;
}
__attribute__((always_inline)) static inline void Fee_InitEraseSector(const Fee_SectorConfigType *obj)
{
obj->info->eraseSectionIdx = 0;
}
__attribute__((always_inline)) static inline void Fee_EraseSector(const Fee_SectorConfigType *obj, const Fee_MethodType *method)
{
Fee_AddressType eraseAddr;
/* When erasing a sector, */
/* erase the sections of the N flash files that make up the sector in a time-sharing manner. */
if((obj->info->status != FEE_SECTOR_ACTIVE) && (obj->info->status != FEE_SECTOR_ERASE))
{
if(obj->info->eraseSectionIdx < obj->eraseSectionNum)
{
eraseAddr = obj->startAddr + (obj->info->eraseSectionIdx * FEE_SECTION_LENGTH);
if(ALIGNED((eraseAddr) + FEE_SECTION_LENGTH - 1, FEE_SECTION_LENGTH) > ALIGNED(eraseAddr, FEE_SECTION_LENGTH))
{
obj->info->errors = FEE_SECTOR_ADDR_NOALIGNED;
}
else if(FLS_STATE_OK != method->erase(eraseAddr))
{
obj->info->errors = FEE_SECTOR_ERASE_ERROR;
}
else
{
obj->info->eraseSectionIdx++;
}
}
else
{
obj->info->status = FEE_SECTOR_ERASE;
}
}
}
__attribute__((always_inline)) static inline bool Fee_SectorWriteHeadMark(const Fee_MethodType *method, Fee_AddressType writeAddr, uint8_t *cache)
{
bool ret = false;
if(FLS_STATE_OK == method->write(writeAddr, cache, FEE_SECTOR_HEAD_INFO_LEN))
{
ret = true;
}
return ret;
}
__attribute__((always_inline)) static inline void Fee_SectorWriteInitMark(const Fee_SectorConfigType *obj, const Fee_MethodType *method, uint8_t *cache)
{
int idx;
/* The data format of the flag bit of the sector header information consists of a start flag bit, */
/* a status flag bit, a fill bit, and a crc check bit. */
/* When assembling a flag bit, the check value of crc8 is written last. */
if(((FEE_SECTOR_UNUSED == obj->info->status) || (FEE_SECTOR_ERASE == obj->info->status)) && (FEE_SECTOR_NOT_ERROR == obj->info->errors))
{
obj->info->status = FEE_SECTOR_INIT;
cache[FEE_SECTOR_HEAD_MARK_IDX] = FEE_SECTOR_VALID_WORD;
cache[FEE_SECTOR_HEAD_FLAG_IDX] = FEE_SECTOR_INIT_FLAG_WORD;
cache[FEE_SECTOR_HEAD_FILL_IDX] = FEE_SECTOR_FILL_WORD;
cache[FEE_SECTOR_HEAD_CRC_IDX] = method->crc8(cache, FEE_SECTOR_HEAD_CRC_LEN);
for(idx = 0; idx < FEE_SECTOR_HEAD_INFO_BACKUP_AREA_LEN; idx++)
{
cache[FEE_SECTOR_HEAD_INFO_BACKUP_AREA_LEN + idx] = cache[idx];
}
if(Fee_SectorWriteHeadMark(method, obj->startAddr + FEE_SECTOR_INIT_IDX, cache))
{
Fee_SectorWriteHeadMark(method, FEE_SECTOR_BACKUP_HEAD_ADDR(obj) + FEE_SECTOR_INIT_IDX, cache);
obj->info->status = FEE_SECTOR_INIT_FINISH;
}
else
{
obj->info->errors = FEE_SECTOR_WRITE_INIT_MARK_ERROR;
}
}
else
{
obj->info->errors = FEE_SECTOR_WRITE_INIT_MARK_ERROR;
}
}
__attribute__((always_inline)) static inline void Fee_SectorWriteStartHandMark(const Fee_SectorConfigType *obj, const Fee_MethodType *method, uint8_t *cache)
{
int idx;
/* The data format of the flag bit of the sector header information consists of a start flag bit, */
/* a status flag bit, a fill bit, and a crc check bit. */
/* When assembling a flag bit, the check value of crc8 is written last. */
if((FEE_SECTOR_INIT_FINISH == obj->info->status) && (FEE_SECTOR_NOT_ERROR == obj->info->errors))
{
obj->info->status = FEE_SECTOR_START_HAND;
cache[FEE_SECTOR_HEAD_MARK_IDX] = FEE_SECTOR_VALID_WORD;
cache[FEE_SECTOR_HEAD_FLAG_IDX] = FEE_SECTOR_INIT_START_FLAG_WORD;
cache[FEE_SECTOR_HEAD_FILL_IDX] = FEE_SECTOR_FILL_WORD;
cache[FEE_SECTOR_HEAD_CRC_IDX] = method->crc8(cache, FEE_SECTOR_HEAD_CRC_LEN);
for(idx = 0; idx < FEE_SECTOR_HEAD_INFO_BACKUP_AREA_LEN; idx++)
{
cache[FEE_SECTOR_HEAD_INFO_BACKUP_AREA_LEN + idx] = cache[idx];
}
if(Fee_SectorWriteHeadMark(method, obj->startAddr + FEE_SECTOR_START_HAND_IDX, cache))
{
Fee_SectorWriteHeadMark(method, FEE_SECTOR_BACKUP_HEAD_ADDR(obj) + FEE_SECTOR_START_HAND_IDX, cache);
obj->info->status = FEE_SECTOR_START_HAND_FINISH;
}
else
{
obj->info->errors = FEE_SECTOR_WRITE_START_MARK_ERROR;
}
}
else
{
obj->info->errors = FEE_SECTOR_WRITE_START_MARK_ERROR;
}
}
__attribute__((always_inline)) static inline void Fee_SectorWriteEndHandMark(const Fee_SectorConfigType *obj, const Fee_MethodType *method, uint8_t *cache)
{
int idx;
/* The data format of the flag bit of the sector header information consists of a start flag bit, */
/* a status flag bit, a fill bit, and a crc check bit. */
/* When assembling a flag bit, the check value of crc8 is written last. */
if(FEE_SECTOR_START_HAND_FINISH == obj->info->status)
{
obj->info->status = FEE_SECTOR_END_HAND;
cache[FEE_SECTOR_HEAD_MARK_IDX] = FEE_SECTOR_VALID_WORD;
cache[FEE_SECTOR_HEAD_FLAG_IDX] = FEE_SECTOR_INIT_WRITE_END_FLAG_WORD;
cache[FEE_SECTOR_HEAD_FILL_IDX] = FEE_SECTOR_FILL_WORD;
cache[FEE_SECTOR_HEAD_CRC_IDX] = method->crc8(cache, FEE_SECTOR_HEAD_CRC_LEN);
for(idx = 0; idx < FEE_SECTOR_HEAD_INFO_BACKUP_AREA_LEN; idx++)
{
cache[FEE_SECTOR_HEAD_INFO_BACKUP_AREA_LEN + idx] = cache[idx];
}
if(Fee_SectorWriteHeadMark(method, obj->startAddr + FEE_SECTOR_END_HAND_IDX, cache))
{
Fee_SectorWriteHeadMark(method, FEE_SECTOR_BACKUP_HEAD_ADDR(obj) + FEE_SECTOR_END_HAND_IDX, cache);
obj->info->status = FEE_SECTOR_END_HAND_FINISH;
}
else
{
obj->info->errors = FEE_SECTOR_WRITE_END_MARK_ERROR;
}
}
else
{
obj->info->errors = FEE_SECTOR_WRITE_END_MARK_ERROR;
}
}
__attribute__((always_inline)) static inline void Fee_SectorWriteEnableSectorMark(const Fee_SectorConfigType *obj, const Fee_MethodType *method, uint8_t *cache)
{
int idx;
/* The data format of the flag bit of the sector header information consists of a start flag bit, */
/* a status flag bit, a fill bit, and a crc check bit. */
/* When assembling a flag bit, the check value of crc8 is written last. */
if(FEE_SECTOR_END_HAND_FINISH == obj->info->status)
{
obj->info->status = FEE_SECTOR_EN;
cache[FEE_SECTOR_HEAD_MARK_IDX] = FEE_SECTOR_VALID_WORD;
cache[FEE_SECTOR_HEAD_FLAG_IDX] = FEE_SECTOR_INIT_ENABLE_FLAG_WORD;
cache[FEE_SECTOR_HEAD_FILL_IDX] = FEE_SECTOR_FILL_WORD;
cache[FEE_SECTOR_HEAD_CRC_IDX] = method->crc8(cache, FEE_SECTOR_HEAD_CRC_LEN);
for(idx = 0; idx < FEE_SECTOR_HEAD_INFO_BACKUP_AREA_LEN; idx++)
{
cache[FEE_SECTOR_HEAD_INFO_BACKUP_AREA_LEN + idx] = cache[idx];
}
if(Fee_SectorWriteHeadMark(method, obj->startAddr + FEE_SECTOR_EN_SECTOR_IDX, cache))
{
Fee_SectorWriteHeadMark(method, FEE_SECTOR_BACKUP_HEAD_ADDR(obj) + FEE_SECTOR_EN_SECTOR_IDX, cache);
obj->info->status = FEE_SECTOR_EN_FINISH;
}
else
{
obj->info->errors = FEE_SECTOR_WRITE_EN_MARK_ERROR;
}
}
else
{
obj->info->errors = FEE_SECTOR_WRITE_EN_MARK_ERROR;
}
}
__attribute__((always_inline)) static inline void Fee_SectorFillHeadInfo(const Fee_SectorConfigType *obj, const Fee_MethodType *method, uint8_t *cache)
{
Fee_AddressType writeAddr;
Fee_AddressType startWriteAddr = obj->startAddr + (FEE_SECTOR_HEAD_MARK_NUM * FEE_SECTOR_HEAD_INFO_LEN);
Fee_AddressType endWriteAddr = obj->startAddr + FEE_SECTOR_HEAD_SIZE;
/* After initializing the header information of the sector, */
/* in order to ensure the security of the sector's flash operation, */
/* the remaining unused header information should be filled in to initialize to ensure the certainty of the sector.*/
if(FEE_SECTOR_EN_FINISH == obj->info->status)
{
memset((void *)cache, FEE_SECTOR_FILL_WORD, ALIGN8BYTE(FEE_SECTOR_HEAD_INFO_LEN));
for(writeAddr = startWriteAddr; writeAddr < endWriteAddr; writeAddr = writeAddr + Fee_BLOCK_WRITE_ALIGNED_SIZE)
{
if(FLS_STATE_OK != method->write(writeAddr, cache, ALIGN8BYTE(FEE_SECTOR_HEAD_INFO_LEN)))
{
obj->info->errors |= FEE_SECTOR_WRITE_HEAD_FILL_ERROR;
break;
}
}
startWriteAddr = FEE_SECTOR_BACKUP_HEAD_ADDR(obj) + (FEE_SECTOR_HEAD_MARK_NUM * FEE_SECTOR_HEAD_INFO_LEN);
endWriteAddr = FEE_SECTOR_BACKUP_HEAD_ADDR(obj) + FEE_SECTOR_HEAD_SIZE;
for(writeAddr = startWriteAddr; writeAddr < endWriteAddr; writeAddr = writeAddr + Fee_BLOCK_WRITE_ALIGNED_SIZE)
{
if(FLS_STATE_OK != method->write(writeAddr, cache, ALIGN8BYTE(FEE_SECTOR_HEAD_INFO_LEN)))
{
obj->info->errors |= FEE_SECTOR_WRITE_HEAD_FILL_ERROR;
break;
}
}
}
else
{
obj->info->errors |= FEE_SECTOR_WRITE_HEAD_FILL_ERROR;
}
}
__attribute__((always_inline)) static inline Fee_SectorStatusType Fee_SectorGetStatus(const Fee_SectorConfigType *obj)
{
return obj->info->status;
}
__attribute__((always_inline)) static inline void Fee_SectorWriteHeadInfo(const Fee_SectorConfigType *obj, const Fee_MethodType *method, uint8_t *cache)
{
if(FEE_SECTOR_UNUSED == obj->info->status)
{
Fee_SectorWriteInitMark(obj, method, cache);
Fee_SectorWriteStartHandMark(obj, method, cache);
Fee_SectorWriteEndHandMark(obj, method, cache);
Fee_SectorWriteEnableSectorMark(obj, method, cache);
Fee_SectorFillHeadInfo(obj, method, cache);
}
}
__attribute__((always_inline)) static inline const Fee_BlockType *Fee_MatchBlock(const Fee_SectorType *obj, const Fee_MethodType *method, uint8_t *data)
{
const Fee_BlockType *ret = NULL;
uint8_t calcCrc;
uint8_t *blockCrc;
uint32_t *blockEnMark;
uint16_t *blockNumber;
int blockIdx;
/* Block info parses the format according to the protocol, */
/* and after performing integrity checks, the description information of the block will be paired to ensure that the description of the block info can access the corresponding block data. */
blockCrc = (uint8_t *)&(data[FEE_BLOCK_HEAD_INFO_CRC8_IDX]);
calcCrc = method->crc8((void *)data, FEE_BLOCK_CALC_HEAD_INFO_CRC8_LEN);
if((*blockCrc) == calcCrc)
{
blockEnMark = (uint32_t *)&(data[FEE_BLOCK_HEAD_INFO_START_INFO_IDX]);
blockNumber = (uint16_t *)&(data[FEE_BLOCK_HEAD_INFO_BLOCK_NUMBER_IDX]);
if(FEE_BLOCK_HEAD_INFO_START_INFO == (*blockEnMark))
{
for(blockIdx = 0; blockIdx < obj->blockSize; blockIdx++)
{
if(Fee_BlockCheckBlockNumber(obj->blocks[blockIdx].cfg, *blockNumber))
{
ret = &obj->blocks[blockIdx];
break;
}
}
}
}
return ret;
}
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _FEE_SECTOR_H_ */

View File

@ -0,0 +1,113 @@
/*
* 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.
*/
#ifndef _FEE_TRACE_H_
#define _FEE_TRACE_H_
/*******************************************************************************
* the includes
******************************************************************************/
/*! \addtogroup Flash EEPROM Emulation
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
#ifndef FEE_DBG_MAIN_FSM_ERROR_ENTRY
#define FEE_DBG_MAIN_FSM_ERROR_ENTRY()
#endif
#ifndef FEE_DBG_GC_FSM_ERROR_ENTRY
#define FEE_DBG_GC_FSM_ERROR_ENTRY()
#endif
#ifndef FEE_DBG_GC_COPY_FSM_ERROR_ENTRY
#define FEE_DBG_GC_COPY_FSM_ERROR_ENTRY()
#endif
#ifndef FEE_DBG_INITIALIZATION_FSM_ERROR_ENTRY
#define FEE_DBG_INITIALIZATION_FSM_ERROR_ENTRY()
#endif
#ifndef FEE_DBG_SEARCH_MULTIPLE_VALID_SECTOR_ERROR_ENTRY
#define FEE_DBG_SEARCH_MULTIPLE_VALID_SECTOR_ERROR_ENTRY()
#endif
#ifndef FEE_DBG_SEARCH_MULTIPLE_GC_SECTOR_ERROR_ENTRY
#define FEE_DBG_SEARCH_MULTIPLE_GC_SECTOR_ERROR_ENTRY()
#endif
#ifndef FEE_DBG_STORAGE_ERROR_ENTRY
#define FEE_DBG_STORAGE_ERROR_ENTRY()
#endif
#ifndef FEE_DBG_GC_WRITE_BLOCK_DATA_ERROR_ENTRY
#define FEE_DBG_GC_WRITE_BLOCK_DATA_ERROR_ENTRY()
#endif
#ifndef FEE_DBG_GC_WRITE_BLOCK_HEAD_INFO_ERROR_ENTRY
#define FEE_DBG_GC_WRITE_BLOCK_HEAD_INFO_ERROR_ENTRY()
#endif
#ifndef FEE_DBG_GC_READ_BLOCK_DATA_ERROR_ENTRY
#define FEE_DBG_GC_READ_BLOCK_DATA_ERROR_ENTRY()
#endif
#ifndef FEE_DBG_GC_ERASE_ACTIVE_SECTOR_ERROR_ENTRY
#define FEE_DBG_GC_ERASE_ACTIVE_SECTOR_ERROR_ENTRY()
#endif
#ifndef FEE_DBG_GC_WRITE_INIT_MARK_ERROR_ENTRY
#define FEE_DBG_GC_WRITE_INIT_MARK_ERROR_ENTRY()
#endif
#ifndef FEE_DBG_GC_WRITE_START_MARK_ERROR_ENTRY
#define FEE_DBG_GC_WRITE_START_MARK_ERROR_ENTRY()
#endif
#ifndef FEE_DBG_GC_WRITE_END_MARK_ERROR_ENTRY
#define FEE_DBG_GC_WRITE_END_MARK_ERROR_ENTRY()
#endif
#ifndef FEE_DBG_GC_WRITE_ENABLE_MARK_ERROR_ENTRY
#define FEE_DBG_GC_WRITE_ENABLE_MARK_ERROR_ENTRY()
#endif
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _FEE_TRACE_H_ */

View File

@ -0,0 +1,204 @@
/*
* 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.
*/
#ifndef _FEE_TYPES_H_
#define _FEE_TYPES_H_
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdio.h>
#include "fee_sector.h"
#include "fee_jobs.h"
#include "fee_extra.h"
/*! \addtogroup Flash EEPROM Emulation
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief The return value type of the public method of the fee module.
*/
typedef enum
{
FEE_RETURN_OK = 0X00,
FEE_RETURN_NOT_OK = 0X01,
} Fee_ReturnType;
/*! \brief fee module global state type.
*/
typedef enum
{
FEE_STATUS_UNINIT = 0x00,
FEE_STATUS_IDLE = 0x01,
FEE_STATUS_READ = 0x02,
FEE_STATUS_WRITE = 0x03,
FEE_STATUS_GC = 0x04,
FEE_STATUS_UNKNOW = 0x05,
FEE_STATUS_ERROR = 0x06,
} Fee_StatusType;
/*! \brief Returns the type of result that the module has processed this request.
*/
typedef enum
{
FEE_JOB_RESULT_OK = 0x00,
FEE_JOB_RESULT_NOT_OK = 0x01,
FEE_JOB_RESULT_PENDING = 0x02,
FEE_JOB_RESULT_BL_INCONSISTENT = 0x03,
FEE_JOB_RESULT_BL_INVALID = 0x04,
} Fee_JobResultType;
/*! \brief Internal main state type of the fee module.
*/
typedef enum
{
FEE_MAIN_FUN_FSM_INITIALIZATION = 0x00,
FEE_MAIN_FUN_FSM_RETRIEVAL = 0x01,
FEE_MAIN_FUN_FSM_IDLE = 0X02,
FEE_MAIN_FUN_FSM_READ = 0x03,
FEE_MAIN_FUN_FSM_WRITE = 0x04,
FEE_MAIN_FUN_FSM_GC = 0x05,
FEE_MAIN_FUN_FSM_ERROR = 0x06,
} Fee_MainFunFsmType;
/*! \brief The configuration type of the fee.
*/
typedef struct _Fee_ConfigType_
{
uint32_t blockSize;
} Fee_ConfigType;
/*! \brief The sub state type of the initialization main state of the fee module.
*/
typedef enum
{
FEE_INITIALIZATION_SECTOR = 0x00,
FEE_INITIALIZATION_CHECK_SECTOR = 0x01,
FEE_INITIALIZATION_FIND_ACTIVE_SECTOR = 0x02,
FEE_INITIALIZATION_GC_REPAIR_SECTOR = 0x03,
FEE_INITIALIZATION_ERASE_SECTOR = 0x04,
FEE_INITIALIZATION_UNINITIALIZATION_ERASE_SECTOR = 0x05,
FEE_INITIALIZATION_UNINITIALIZATION = 0X06,
FEE_INITIALIZATION_FINISH = 0x07,
FEE_INITIALIZATION_ERROR = 0x08,
} Fee_InitializationFsmType;
/*! \brief The sub state type of the feed's main page fee module state.
*/
typedef enum
{
FEE_GC_INIT = 0x00,
FEE_GC_ERASE_BACKUPSECTOR = 0x01,
FEE_GC_START = 0x02,
FEE_GC_FOUND_BLOCK = 0x03,
FEE_GC_COPY = 0x04,
FEE_GC_ERASE_ACTIVESECTOR = 0x05,
FEE_GC_FINISH = 0x06,
FEE_GC_ERROR = 0x07,
} Fee_GcFsmType;
/*! \brief The sub state type of the copy sub state of the feed's main page fee module state.
*/
typedef enum
{
FEE_GC_COPY_WRITE_MARK = 0x01,
FEE_GC_COPY_INIT = 0x02,
FEE_GC_COPY_WRITEBLOCK = 0x04,
FEE_GC_COPY_FINISH = 0x05,
FEE_GC_COPY_ERROR = 0x06,
} Fee_GcCopyFsmType;
/*! \brief Define the type of copy sub state execution results for the feed's main page fee module state.
*/
typedef enum
{
FEE_GC_STATE_NO_ERROR = 0x00,
FEE_GC_STATE_UNKNOW_ERROR = 0x01,
FEE_GC_STATE_WRITE_ERROR = 0x02,
FEE_GC_STATE_READ_ERROR = 0x03,
FEE_GC_STATE_NOT_FOUND_BACKUPSECTOR = 0x04,
FEE_GC_STATE_ERASE_BACKUP_SECTOR_ERROR = 0x05,
FEE_GC_STATE_WRITE_INIT_MARK_ERROR = 0x06,
FEE_GC_STATE_COPY_ERROR = 0x07,
FEE_GC_STATE_ERASE_ACTIVE_SECTOR_ERROR = 0x08,
FEE_GC_STATE_WRITE_ENA_MARK_ERROR = 0x09,
} Fee_GcCopyStateType;
/*! \brief Defines the type of runtime for page fee module.
*/
typedef struct _Fee_GcRuntimeType_
{
Fee_GcFsmType gcFsm;
Fee_GcCopyFsmType copyFsm;
const struct _Fee_SectorConfigType_* backupSector;
uint32_t blockCnt;
const struct _Fee_BlockType_* currentBlock;
Fee_AddressType searchAddr;
Fee_AddressType copySrcDataAddr;
Fee_GcCopyStateType state;
} Fee_GcRuntimeType;
/*! \brief Define the type of feed module runtime.
*/
typedef struct _Fee_RunTimeType_
{
Fee_MainFunFsmType mainFunFsm;
Fee_InitializationFsmType initializationFsm;
struct _Fee_JobsType_* const jobs;
const struct _Fee_SectorConfigType_* activeSector;
struct _Fee_JobControlBlockType_* const job;
struct _Fee_GcRuntimeType_* const gcRuntime;
Fee_JobResultType jobResult;
} Fee_RunTimeType;
/*! \brief Define the type of the fee object.
*/
typedef struct _FeeType_
{
const struct _Fee_SectorType_* sector;
const struct _Fee_MethodType_* flsMethod;
struct _Fee_RunTimeType_* runtime;
void* const buff;
} FeeType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _FEE_TYPES_H_ */

View File

@ -0,0 +1,86 @@
/*
* 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.
*/
#ifndef _FEE_VERSION_H_
#define _FEE_VERSION_H_
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdio.h>
/*! \addtogroup Flash EEPROM Emulation
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*! \brief Macro for the major version number of the software of the fee module.
*/
#if(defined FEE_SW_MAJOR_VERSION)
#error FEE_SW_MAJOR_VERSION already defined
#endif
#define FEE_SW_MAJOR_VERSION (1U)
/*! \brief Macro for the software version number of the fee module.
*/
#if(defined FEE_SW_MINOR_VERSION)
#error FEE_SW_MINOR_VERSION already defined
#endif
#define FEE_SW_MINOR_VERSION (0U)
/*! \brief Macro for the software patch version number of the fee module.
*/
#if(defined FEE_SW_PATCH_VERSION)
#error FEE_SW_PATCH_VERSION already defined
#endif
#define FEE_SW_PATCH_VERSION (0U)
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Type of software version number of the fee module.
*/
typedef struct _Fee_VersionInfoType_
{
uint8_t sw_major_version;
uint8_t sw_minor_version;
uint8_t sw_patch_version;
} Fee_VersionInfoType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _FEE_VERSION_H_ */

View File

@ -0,0 +1,303 @@
/*
* 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;
}
}

View File

@ -0,0 +1,189 @@
/*
* 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.
*/
#ifndef _NVM_H_
#define _NVM_H_
/*! \brief Contains public interface to various functions related
* to the NVM (NVRAM Manager) module
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "nvm_types.h"
#include "nvm_version.h"
/*! \addtogroup NVRAM Manager
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*! \brief Macro for the value range of the nvm module dataset section.
*/
#ifndef NVM_DATASET_SELECTION_BITS
#define NVM_DATASET_SELECTION_BITS (4)
#endif
/*! \brief Macro for masking the value range of the nvm module dataset section.
*/
#define NVM_DATASET_SELECTION_MASK ((1 << NVM_DATASET_SELECTION_BITS) - 1)
/*! \brief Macro for masking the value range of the nvm module dataset section.
*/
#define NVM_NUMBER_SELECTION_MASK (~NVM_DATASET_SELECTION_MASK)
/*! \brief Macro for NVM module to obtain block id field in blocknumber.
*/
#define NVM_GET_BLOCKNUMBER(blockNumber) (blockNumber & NVM_NUMBER_SELECTION_MASK)
/*! \brief NVM module obtains macro for dataset field in blocknumber.
*/
#define NVM_GET_BLOCKDATASETNUMBER(blockNumber) (blockNumber & NVM_DATASET_SELECTION_MASK)
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Configures the NVM driver
*
* This function configures the NVM driver
*
* \param[in] obj : pointer to NVM driver instance
*/
extern void Nvm_Configure(const NvmType *obj);
/*! \brief Main function of NVM driver
*
* This function is the main process of running the NVM driver
*
* \param[in] obj : pointer to NVM driver instance
*/
extern void Nvm_MainFunction(const NvmType *obj);
/*! \brief Read the data from NVM
*
* This function reads the data from NVM with given parameters
*
* \param[in] obj : pointer to NVM driver instance
* \param[in] block : block to read
* \param[out] dataBuffer : pointer to the result data buffer
* \param[in] notificationPtr : pointer to the notification callback function
*/
extern Nvm_ReturnType Nvm_Read(const NvmType *obj, uint16_t blockNumber, uint8_t *dataBuffer);
/*! \brief Read the all block data to NVM
*
* This function reads the data from NVM with given parameters
*
* \param[in] obj : pointer to NVM driver instance
*/
extern Nvm_ReturnType Nvm_ReadAll(const NvmType *obj);
/*! \brief Write the data to NVM
*
* This function writed the data to NVM with given parameters
*
* \param[in] obj : pointer to FEE driver instance
* \param[in] block : block number to write
* \param[in] dataBuffer : pointer to the data buffer to write
* \param[in] notificationPtr : pointer to the notification callback function
*/
extern Nvm_ReturnType Nvm_Write(const NvmType *obj, uint16_t blockNumber, uint8_t *dataBuffer);
/*! \brief Write the all block data
*
* This function writed the data to NVM with given parameters
*
* \param[in] obj : pointer to FEE driver instance
*/
extern Nvm_ReturnType Nvm_WriteAll(const NvmType *obj);
/*! \brief Erase NVM Block
*
* This function Erase NVM Block with given parameters
*
* \param[in] obj : pointer to FEE driver instance
* \param[in] blockNumber : block to write
*/
extern Nvm_ReturnType Nvm_Erase(const NvmType *obj, uint16_t blockNumber);
/*! \brief Erase NVM All Block
*
* This function Erase NVM All Block with given parameters
*
* \param[in] obj : pointer to FEE driver instance
*/
extern Nvm_ReturnType Nvm_EraseAll(const NvmType *obj);
/*! \brief Get Nvm Status
*
* This function Get NVM module status with given parameters
*
* \param[in] obj : pointer to FEE driver instance
*/
extern Nvm_stateType Nvm_GetStatus(const NvmType *obj);
/*! \brief Cancel Nvm Job
*
* This function Cancel NVM Queue Last Job
*
* \param[in] obj : pointer to FEE driver instance
*/
extern void Nvm_CancelJob(const NvmType *obj);
/*! \brief Get Block Status
*
* This function Get NVM Block status with given parameters
*
* \param[in] obj : pointer to FEE driver instance
* \param[in] blockNumber : block
*/
extern Nvm_BlockState Nvm_GetBlockStatus(const NvmType *obj, uint16_t blockNumber);
/*! \brief Get the version information of this driver
*
* This function gets the version information of this driver.
*
* \param[out] versionInfoPtr : pointer to the version object
*/
extern void Nvm_GetVersionInfo(Nvm_VersionInfoType *versionInfoPtr);
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _NVM_H_ */

View File

@ -0,0 +1,404 @@
/*
* 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 <string.h>
#include "nvm_block.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the static
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void Nvm_Block_DataRepair(const Nvm_BlockType *obj, const Nvm_MethodType *method, uint16_t blockIdx, uint16_t datasetIdx)
{
bool writeFlag = false;
uint8_t *mainBuff;
uint8_t *backupBuff;
uint8_t *tempBuff;
uint8_t *romBuff;
uint32_t copySize;
uint32_t dataSize;
/* Obtain necessary data for performing block data validity checks. */
mainBuff = NVM_BLOCK_GET_RAM_BUFF_PTR(obj, blockIdx, datasetIdx);
tempBuff = NVM_BLOCK_GET_TEMP_RAM_BUFF_PTR(obj, blockIdx);
romBuff = NVM_BLOCK_GET_ROM_BUFF_PTR(obj, blockIdx, datasetIdx);
copySize = Nvm_Block_CalcUseSize(obj, blockIdx);
dataSize = NVM_BLOCK_GET_DATASIZE(obj, blockIdx);
/* Check if the block is configured with verification function. */
if(NVM_BLOCK_IS_CRC(obj, blockIdx))
{
/* Check if the block type is redundant. */
if(NVM_BLOCK_IS_REDUNDANT(obj, blockIdx))
{
/* Perform data checks on the main area. */
Nvm_Block_IntegrityCheck(obj, blockIdx, NVM_BLOCK_MAIN_IDX, method);
/* Check whether the data validation result of the main area is invalid. */
if(NVM_BLOCK_CRC_FAIL_MASK == NVM_BLOCK_GET_INTEGRITY(obj, blockIdx, NVM_BLOCK_MAIN_IDX))
{
/* Obtain the backup data address of the redundant type block. */
backupBuff = NVM_BLOCK_GET_RAM_BUFF_PTR(obj, blockIdx, NVM_BLOCK_BACKUP_IDX);
/* Perform data checks on the backup area */
Nvm_Block_IntegrityCheck(obj, blockIdx, NVM_BLOCK_BACKUP_IDX, method);
/* Check whether the data validation result of the backup area is valid. */
if(NVM_BLOCK_CRC_OK_MASK == NVM_BLOCK_GET_INTEGRITY(obj, blockIdx, NVM_BLOCK_BACKUP_IDX))
{
/* Restore the data in the backup area to the main area. */
memcpy(tempBuff, backupBuff, copySize);
writeFlag = true;
}
else
{
/* Restore data from the ROM region to the main region. */
memcpy(tempBuff, romBuff, dataSize);
writeFlag = true;
}
}
}
else
{
/* Perform data checks on the main area. */
Nvm_Block_IntegrityCheck(obj, blockIdx, datasetIdx, method);
/* Check whether the data validation result of the main area is invalid. */
if(NVM_BLOCK_CRC_OK_MASK != NVM_BLOCK_GET_INTEGRITY(obj, blockIdx, datasetIdx))
{
/* Restore data from the ROM region to the main region. */
memcpy((void *)tempBuff, (void *)romBuff, dataSize);
writeFlag = true;
}
}
}
else
{
/* Initialize tempbuff. */
memset((void *)tempBuff, NVM_BLOCK_RAMBUFF_DEFAULT_VALUE, ALIGN8BYTE(copySize));
/* Check if the data in the main area is uninitialized. */
if (0 == memcmp((void *)mainBuff, (void *)tempBuff, ALIGN8BYTE(copySize)))
{
/* Check if the block type is redundant. */
if(NVM_BLOCK_IS_REDUNDANT(obj, blockIdx))
{
/* Obtain the backup data address of the redundant type block. */
backupBuff = NVM_BLOCK_GET_RAM_BUFF_PTR(obj, blockIdx, NVM_BLOCK_BACKUP_IDX);
/* Check if the data in the backup area is uninitialized. */
if (0 == memcmp((void *)backupBuff, tempBuff, ALIGN8BYTE(copySize)))
{
/* Restore data from ROM area to main and backup areas. */
memcpy(tempBuff, romBuff, dataSize);
writeFlag = true;
}
else
{
/* Restore the data in the backup area to the main area. */
memcpy(tempBuff, backupBuff, copySize);
writeFlag = true;
}
}
else
{
/* Restore data from ROM area to main and backup areas. */
memcpy(tempBuff, romBuff, dataSize);
writeFlag = true;
}
}
else
{
/* Restore data from main area to block all area data. */
memcpy(tempBuff, mainBuff, dataSize);
writeFlag = true;
}
}
if(writeFlag)
{
/* Perform data recovery. */
Nvm_Block_WriteDataToRamBlock(obj, method, blockIdx, datasetIdx, tempBuff);
}
}
void Nvm_Block_SetDefaultVal(const Nvm_BlockType *obj, const Nvm_MethodType *method, uint16_t blockIdx, uint16_t datasetIdx)
{
uint8_t *buff;
/* Initialize all data regions of the block with data from non rom regions. */
buff = NVM_BLOCK_GET_TEMP_RAM_BUFF_PTR(obj, blockIdx);
Nvm_Block_GetRomData(obj, blockIdx, datasetIdx, buff);
Nvm_Block_WriteDataToRamBlock(obj, method, blockIdx, datasetIdx, buff);
}
void Nvm_Block_ClrRamBuff(const Nvm_BlockType *obj, uint16_t blockIdx, uint16_t datasetIdx)
{
uint8_t *mainRamBuff;
uint32_t dataSize;
/* Initialize all initializable data regions of the dataset in the block. */
dataSize = ALIGN8BYTE(Nvm_Block_CalcUseSize(obj, blockIdx));
mainRamBuff = NVM_BLOCK_GET_RAM_BUFF_PTR(obj, blockIdx, datasetIdx);
memset((void *)mainRamBuff, NVM_BLOCK_RAMBUFF_DEFAULT_VALUE, dataSize);
}
void Nvm_Block_ClrBlockRamBuff(const Nvm_BlockType *obj, uint16_t blockIdx, uint16_t datasetIdx)
{
/* Initialize all initializable data regions of the block. */
if(NVM_BLOCK_IS_REDUNDANT(obj, blockIdx))
{
Nvm_Block_ClrRamBuff(obj, blockIdx, NVM_BLOCK_MAIN_IDX);
Nvm_Block_ClrRamBuff(obj, blockIdx, NVM_BLOCK_BACKUP_IDX);
}
else
{
Nvm_Block_ClrRamBuff(obj, blockIdx, datasetIdx);
}
}
void Nvm_Block_SetState(const Nvm_BlockType *obj, uint16_t blockIdx, uint16_t datasetIdx, Nvm_BlockState state)
{
/* Set the status of the dataset in the block. */
obj->items[blockIdx].info[datasetIdx].state = state;
}
void Nvm_Block_SetInternalState(const Nvm_BlockType *obj, uint16_t blockIdx, uint16_t datasetIdx, Nvm_BlockState state)
{
/* Set the internal processing status of the NVM for the dataset in the block. */
obj->items[blockIdx].info[datasetIdx].internalState = state;
}
void Nvm_Block_SetTempRamBuffDefaultVal(const Nvm_BlockType *obj, uint16_t blockIdx, uint16_t datasetIdx)
{
/* Initialize the tempbuff of the block. */
memset((void *)obj->items[blockIdx].tempRamBuffPtr, NVM_BLOCK_RAMBUFF_DEFAULT_VALUE, ALIGN8BYTE(Nvm_Block_CalcUseSize(obj, blockIdx)));
}
uint32_t Nvm_Block_CalcUseSize(const Nvm_BlockType *obj, uint16_t blockIdx)
{
uint32_t ret;
/* Check if the block is configured with crc verification. */
if(NVM_CRC8 == obj->items[blockIdx].crc)
{
/* Calculate the size used to store valid data in BLCOK. */
ret = obj->items[blockIdx].dataSize + NVM_BLOCK_PLACEHOLDER_BYTES + NVM_BLOCK_CRC_BYTES;
}
else
{
/* Calculate the size used to store valid data in BLCOK. */
ret = obj->items[blockIdx].dataSize + NVM_BLOCK_PLACEHOLDER_BYTES;
}
return ret;
}
void Nvm_Block_GetRomData(const Nvm_BlockType *obj, uint16_t blockIdx, uint8_t datasetIdx, uint8_t *data)
{
uint8_t *romBuff;
/* Obtain data from the rom area of the dataset in the block. */
romBuff = NVM_BLOCK_GET_ROM_BUFF_PTR(obj, blockIdx, datasetIdx);
memcpy((void *)data, (void *)romBuff, NVM_BLOCK_GET_DATASIZE(obj, blockIdx));
}
bool Nvm_Block_GetWriteData(const Nvm_BlockType *obj, uint16_t blockIdx, uint8_t datasetIdx, const Nvm_MethodType *method, uint8_t *data)
{
bool ret = true;
uint8_t integrity;
/* Check if the block type is redundant. */
if(NVM_BLOCK_IS_REDUNDANT(obj, blockIdx))
{
/* Perform data checks on the main area. */
Nvm_Block_IntegrityCheck(obj, blockIdx, NVM_BLOCK_MAIN_IDX, method);
/* Perform data checks on the main area. */
integrity = NVM_BLOCK_GET_INTEGRITY(obj, blockIdx, NVM_BLOCK_MAIN_IDX);
/* Check whether the data validation result of the main area is invalid. */
if(NVM_BLOCK_CRC_OK_MASK == integrity)
{
/* Copy valid data */
memcpy((void *)data, (void *)NVM_BLOCK_GET_RAM_BUFF_PTR(obj, blockIdx, NVM_BLOCK_MAIN_IDX), NVM_BLOCK_GET_DATASIZE(obj, blockIdx));
}
else
{
/* Perform data checks on the backup area. */
Nvm_Block_IntegrityCheck(obj, blockIdx, datasetIdx, method);
/* Perform data checks on the backup area. */
integrity = NVM_BLOCK_GET_INTEGRITY(obj, blockIdx, NVM_BLOCK_BACKUP_IDX);
/* Check whether the data validation result of the backup area is invalid. */
if(NVM_BLOCK_CRC_OK_MASK == integrity)
{
/* Copy valid data. */
memcpy((void *)data, (void *)NVM_BLOCK_GET_RAM_BUFF_PTR(obj, blockIdx, NVM_BLOCK_BACKUP_IDX), NVM_BLOCK_GET_DATASIZE(obj, blockIdx));
}
else
{
ret = false;
}
}
}
else
{
/* Perform data checks on the dataset area. */
Nvm_Block_IntegrityCheck(obj, blockIdx, datasetIdx, method);
/* Perform data checks on the dataset area. */
integrity = NVM_BLOCK_GET_INTEGRITY(obj, blockIdx, datasetIdx);
/* Check whether the data validation result of the dataset area is invalid. */
if(NVM_BLOCK_CRC_OK_MASK == integrity)
{
/* Copy valid data. */
memcpy((void *)data, (void *)NVM_BLOCK_GET_RAM_BUFF_PTR(obj, blockIdx, datasetIdx), NVM_BLOCK_GET_DATASIZE(obj, blockIdx));
}
else
{
ret = false;
}
}
return ret;
}
void Nvm_Block_IntegrityCheck(const Nvm_BlockType *obj, uint16_t blockIdx, uint8_t datasetIdx, const Nvm_MethodType *method)
{
uint8_t crc;
uint32_t crcLen;
uint8_t *mainRamBuff;
/* Set the data validity flag bit of the dataset in the block to error */
obj->items[blockIdx].info[datasetIdx].integrity = NVM_BLOCK_CRC_FAIL_MASK;
/* Check if the block is configured with crc verification */
if(NVM_BLOCK_IS_CRC(obj, blockIdx))
{
/* The required data length, starting address, and parity bits for obtaining verification data */
crcLen = NVM_BLOCK_GET_CRC_LEN(obj, blockIdx);
mainRamBuff = obj->items[blockIdx].buff[datasetIdx].ramBuffPtr;
crc = method->crc8(mainRamBuff, crcLen);
/* Compare check bits */
if(crc == mainRamBuff[crcLen])
{
/* Verification passed, configure the data validity flag as successful */
obj->items[blockIdx].info[datasetIdx].integrity = NVM_BLOCK_CRC_OK_MASK;
}
}
else
{
/* Verification passed, configure the data validity flag as successful */
obj->items[blockIdx].info[datasetIdx].integrity = NVM_BLOCK_CRC_OK_MASK;
}
}
void Nvm_Block_WriteDataToBuff(const Nvm_BlockType *obj, const Nvm_MethodType *method, uint16_t blockIdx, uint16_t datasetIdx, uint8_t *data)
{
uint8_t * buff;
uint32_t dataSize;
uint32_t crcLen;
/* Write data to the corresponding RAM area based on blockid and dataset */
buff = NVM_BLOCK_GET_RAM_BUFF_PTR(obj, blockIdx, datasetIdx);
dataSize = ALIGN8BYTE(Nvm_Block_CalcUseSize(obj, blockIdx));
memset((void *)buff, NVM_BLOCK_RAMBUFF_DEFAULT_VALUE, ALIGN8BYTE(Nvm_Block_CalcUseSize(obj, blockIdx)));
memcpy((void *)buff, (void *)data, dataSize);
if(NVM_BLOCK_IS_CRC(obj, blockIdx))
{
crcLen = NVM_BLOCK_GET_CRC_LEN(obj, blockIdx);
buff[crcLen] = method->crc8(buff, crcLen);
}
}
void Nvm_Block_WriteDataToRamBlock(const Nvm_BlockType *obj, const Nvm_MethodType *method, uint16_t blockIdx, uint16_t datasetIdx, uint8_t *data)
{
/* If the type of the block is redundant, the data will be written to the main and backup areas. */
/* Otherwise, the data will be written to the dataset area. */
if(NVM_BLOCK_IS_REDUNDANT(obj, blockIdx))
{
Nvm_Block_WriteDataToBuff(obj, method, blockIdx, NVM_BLOCK_MAIN_IDX, data);
Nvm_Block_WriteDataToBuff(obj, method, blockIdx, NVM_BLOCK_BACKUP_IDX, data);
}
else
{
Nvm_Block_WriteDataToBuff(obj, method, blockIdx, datasetIdx, data);
}
}
uint16_t Nvm_Block_Search(const Nvm_BlockType *obj, uint16_t blockNumber)
{
uint16_t retBlock = NVM_BLOCK_INVALID_IDX;
uint16_t blockStartIdx = 0;
uint16_t blockMiddleIdx = (obj->itemsNum - 1) / 2;
uint16_t blockEndIdx = obj->itemsNum - 1;
bool retFlag = false;
while(false == retFlag)
{
/* If the current block and the input block are the same */
if(blockNumber == obj->items[blockMiddleIdx].number)
{
/* Returns the index of the block */
retBlock = blockMiddleIdx;
retFlag = true;
}
else
{
/* Currently, there are only two or fewer blocks left that are not found, then check the other block */
if((blockEndIdx - blockStartIdx) <= 1)
{
retFlag = true;
if(blockNumber == obj->items[blockEndIdx].number)
{
retBlock = blockEndIdx;
}
}
else
{
/* In descending order, first determine whether it is in the right range, */
/* and then check whether it is in the left range */
if(obj->items[blockMiddleIdx].number < blockNumber)
{
blockStartIdx = blockMiddleIdx + 1;
}
else
{
blockEndIdx = blockMiddleIdx - 1;
}
/* Calculate Median */
blockMiddleIdx = blockEndIdx + blockStartIdx;
blockMiddleIdx /= 2;
}
}
}
return retBlock;
}

View File

@ -0,0 +1,181 @@
/*
* 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.
*/
#ifndef _NVM_BLOCK_H_
#define _NVM_BLOCK_H_
/*! \brief Contains public interface to various functions related
* to the NVM (NVRAM Manager) module
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "nvm_types.h"
/*! \addtogroup NVRAM Manager
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*! \brief Define a macro for rampoff initialization data.
*/
#define NVM_BLOCK_RAMBUFF_DEFAULT_VALUE (0x00)
/*! \brief Macro defining invalid block index.
*/
#define NVM_BLOCK_INVALID_IDX (0xFFFF)
/*! \brief Define macros with invalid datasets.
*/
#define NVM_DATASET_INVALID_IDX (0xFFFF)
/*! \brief The highest priority macro for the job.
*/
#define NVM_BLOCK_HIGHT_PRIORITY (0)
/*! \brief Define the placeholder length for the effective storage of data in a block.
*/
#define NVM_BLOCK_PLACEHOLDER_BYTES (0)
/*! \brief Define the CRC length for effective storage of data in a block.
*/
#define NVM_BLOCK_CRC_BYTES (1)
/*! \brief Define macros that failed data validation.
*/
#define NVM_BLOCK_CRC_FAIL_MASK (0x00)
/*! \brief Define macros for successful data validation.
*/
#define NVM_BLOCK_CRC_OK_MASK (0x01)
/*! \brief Macro that defines the dataset value of the main region.
*/
#define NVM_BLOCK_MAIN_IDX (0)
/*! \brief Macro that defines the dataset value of the backup region.
*/
#define NVM_BLOCK_BACKUP_IDX (1)
/*! \brief Macro defining the number of failed retry attempts for request feed operations.
*/
#define NVM_BLOCK_RETRY_NUM (3)
/*! \brief Define a macro to determine whether the block type is immediate.
*/
#define NVM_BLOCK_IS_IMMEDIATE(obj, blockIdx) (obj->items[blockIdx].immediate)
/*! \brief Define a macro to determine whether the block is configured with CRC.
*/
#define NVM_BLOCK_IS_CRC(obj, blockIdx) (NVM_CRC8 == obj->items[blockIdx].crc)
/*! \brief Define a macro to determine whether a block is of normal type.
*/
#define NVM_BLOCK_IS_NORMAL(obj, blockIdx) (NVM_BLOCK_NORMAL == obj->items[blockIdx].type)
/*! \brief Define a macro to determine whether a block is a redundant type.
*/
#define NVM_BLOCK_IS_REDUNDANT(obj, blockIdx) (NVM_BLOCK_REDUNDANT == obj->items[blockIdx].type)
/*! \brief Define a macro to determine whether a block is a dataset type.
*/
#define NVM_BLOCK_IS_DATASET(obj, blockIdx) (NVM_BLOCK_DATASET == obj->items[blockIdx].type)
/*! \brief Define a macro to obtain the datasetN checksum bit in a block.
*/
#define NVM_BLOCK_GET_INTEGRITY(obj, blockIdx, datasetIdx) (obj->items[blockIdx].info[datasetIdx].integrity)
/*! \brief Define a macro to obtain the status of datasetN in a block.
*/
#define NVM_BLOCK_GET_STATE(obj, blockIdx, datasetIdx) (obj->items[blockIdx].info[datasetIdx].state)
/*! \brief Define a macro to obtain the internal management status of datasetN in a block.
*/
#define NVM_BLOCK_GET_INT_STATE(obj, blockIdx, datasetIdx) (obj->items[blockIdx].info[datasetIdx].internalState)
/*! \brief Define a macro to obtain the number of datasets in a block.
*/
#define NVM_BLOCK_GET_DATASETNUM(obj, blockIdx) (obj->items[blockIdx].datasetNum)
/*! \brief Define macros for obtaining priority in blocks.
*/
#define NVM_BLOCK_GET_PRIORITY(obj, blockIdx) (obj->items[blockIdx].priority)
/*! \brief Define macros for obtaining blockrambuff addresses.
*/
#define NVM_BLOCK_GET_RAM_BUFF_PTR(obj, blockIdx, datasetIdx) ((uint8_t *)obj->items[blockIdx].buff[datasetIdx].ramBuffPtr)
/*! \brief Define macros for obtaining block tempbuff addresses.
*/
#define NVM_BLOCK_GET_TEMP_RAM_BUFF_PTR(obj, blockIdx) ((uint8_t *)obj->items[blockIdx].tempRamBuffPtr)
/*! \brief Define macros for obtaining block rombuff addresses.
*/
#define NVM_BLOCK_GET_ROM_BUFF_PTR(obj, blockIdx, datasetIdx) ((uint8_t *)obj->items[blockIdx].buff[datasetIdx].romBuffPtr)
/*! \brief Define macros for obtaining block data length.
*/
#define NVM_BLOCK_GET_DATASIZE(obj, blockIdx) (obj->items[blockIdx].dataSize)
/*! \brief Define macros for obtaining block crc length.
*/
#define NVM_BLOCK_GET_CRC_LEN(obj, blockIdx) (obj->items[blockIdx].dataSize + NVM_BLOCK_PLACEHOLDER_BYTES)
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
void Nvm_Block_Init(const Nvm_BlockType *obj);
void Nvm_Block_DataRepair(const Nvm_BlockType *obj, const Nvm_MethodType *method, uint16_t blockIdx, uint16_t datasetIdx);
void Nvm_Block_SetDefaultVal(const Nvm_BlockType *obj, const Nvm_MethodType *method, uint16_t blockIdx, uint16_t datasetIdx);
void Nvm_Block_ClrRamBuff(const Nvm_BlockType *obj, uint16_t blockIdx, uint16_t datasetIdx);
void Nvm_Block_ClrBlockRamBuff(const Nvm_BlockType *obj, uint16_t blockIdx, uint16_t datasetIdx);
void Nvm_Block_SetState(const Nvm_BlockType *obj, uint16_t blockIdx, uint16_t datasetIdx, Nvm_BlockState state);
void Nvm_Block_SetInternalState(const Nvm_BlockType *obj, uint16_t blockIdx, uint16_t datasetIdx, Nvm_BlockState state);
void Nvm_Block_SetTempRamBuffDefaultVal(const Nvm_BlockType *obj, uint16_t blockIdx, uint16_t datasetIdx);
uint32_t Nvm_Block_CalcUseSize(const Nvm_BlockType *obj, uint16_t blockIdx);
void Nvm_Block_GetRomData(const Nvm_BlockType *obj, uint16_t blockIdx, uint8_t datasetIdx, uint8_t *data);
bool Nvm_Block_GetWriteData(const Nvm_BlockType *obj, uint16_t blockIdx, uint8_t datasetIdx, const Nvm_MethodType *method, uint8_t *data);
void Nvm_Block_WriteDataToBuff(const Nvm_BlockType *obj, const Nvm_MethodType *method, uint16_t blockIdx, uint16_t datasetIdx, uint8_t *data);
void Nvm_Block_IntegrityCheck(const Nvm_BlockType *obj, uint16_t blockIdx, uint8_t ecu, const Nvm_MethodType *method);
void Nvm_Block_WriteDataToRamBlock(const Nvm_BlockType *obj, const Nvm_MethodType *method, uint16_t blockIdx, uint16_t datasetIdx, uint8_t *data);
uint16_t Nvm_Block_Search(const Nvm_BlockType *obj, uint16_t blockNumber);
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _NVM_BLOCK_H_ */

View File

@ -0,0 +1,149 @@
/*
* 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.
*/
#ifndef _NVM_EXTRA_H_
#define _NVM_EXTRA_H_
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
/*! \addtogroup NVRAM Manager
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*! \brief Define N-byte aligned macros.
*/
#ifndef ALIGNBYTE
#define ALIGNBYTE(size, n) ((size + n - 1) & ~(n - 1))
#endif
/*! \brief Define 4-byte aligned macros.
*/
#ifndef ALIGN4BYTE
#define ALIGN4BYTE(size) (ALIGNBYTE(size, 4))
#endif
/*! \brief Define 8-byte aligned macros.
*/
#ifndef ALIGN8BYTE
#define ALIGN8BYTE(size) (ALIGNBYTE(size, 8))
#endif
/*! \brief Define 64-byte aligned macros.
*/
#ifndef ALIGN64BYTE
#define ALIGN64BYTE(size) (ALIGNBYTE(size, 64))
#endif
/*! \brief Define address aligned macros.
*/
#ifndef ALIGNED
#define ALIGNED(val, alncnt) (((uint32_t)val) & ~(alncnt - 1))
#endif
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Define the type of the Notification return value.
*/
typedef enum
{
NVM_JOBFINISHNOTIFICATION = 0x00,
NVM_JOBERRORNOTIFICATION = 0x01,
} NVM_NotificationType;
/*! \brief Define the type of return value for lower level module operations.
*/
typedef enum
{
NVM_JOB_RESULT_OK = 0x00,
NVM_JOB_RESULT_NOT_OK = 0x01,
NVM_JOB_RESULT_PENDING = 0x02,
NVM_JOB_RESULT_BL_INCONSISTENT = 0x03,
NVM_JOB_RESULT_BL_INVALID = 0x04,
} NVM_JobResultType;
/*! \brief Define the type of return value for lower level module status.
*/
typedef enum
{
NVM_STATUS_IDLE = 0x00,
NVM_STATUS_READ = 0x01,
NVM_STATUS_WRITE = 0x02,
NVM_STATUS_GC = 0x03,
NVM_STATUS_UNKNOW = 0x04,
NVM_STATUS_ERROR = 0x05,
} Nvm_StatusType;
/*! \brief Define the type of virtual function for Notification.
*/
typedef void (*NvmNotificationPtrType)(NVM_NotificationType notificationNumber);
/*! \brief Define the type of virtual function for writing lower level module operations.
*/
typedef bool (*Nvm_writeMethodType)(uint16_t blockNumber, uint8_t *dataBuffer, NvmNotificationPtrType notificationPtr);
/*! \brief Define virtual function types for read lower level module operations.
*/
typedef bool (*Nvm_readMethodType)(uint16_t blockNumber, uint16_t blockOffset, uint8_t *dataBuffer, NvmNotificationPtrType notificationPtr);
/*! \brief Define virtual function types for calculating crc8.
*/
typedef uint8_t (*Nvm_calcCrc8Type)(void *sAddr, uint32_t size);
/*! \brief Define virtual function types for lower level module job handle result.
*/
typedef NVM_JobResultType (*Nvm_getJobResultType)(void);
/*! \brief Define virtual function types for lower level module module status.
*/
typedef Nvm_StatusType (*Nvm_GetStatusType)(void);
/*! \brief Define the type of the nvm operation lower level module method.
*/
typedef struct _Nvm_MethodType_
{
Nvm_writeMethodType write;
Nvm_readMethodType read;
Nvm_calcCrc8Type crc8;
Nvm_getJobResultType getJobResult;
Nvm_GetStatusType getStatus;
} Nvm_MethodType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _NVM_EXTRA_H_ */

View File

@ -0,0 +1,196 @@
/*
* 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 "nvm_queue.h"
/*******************************************************************************
* the defines
******************************************************************************/
#define NVM_QUEUE_FULL(OBJ) (OBJ->index >= OBJ->memberNum)
#define NVM_QUEUE_EMPTY(OBJ) (OBJ->index == 0)
#define NVM_QUEUE_BLOCK_UNVALID (0xFFFF)
#define NVM_QUEUE_DATASET_UNVALID (0xFFFF)
#define NVM_QUEUE_PRIORITY_UNVALID (0xFF)
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the static
******************************************************************************/
static void Nvm_Queue_Append(Nvm_QueueType *obj, Nvm_QueueMemberType *member);
/*******************************************************************************
* the functions
******************************************************************************/
void Nvm_Queue_Init(Nvm_QueueType *obj)
{
uint8_t idx;
/* Initialize all members of the queue. */
for(idx = 0; idx < obj->memberNum; idx++)
{
obj->members[idx].blockIdx = NVM_QUEUE_BLOCK_UNVALID;
obj->members[idx].datasetIdx = NVM_QUEUE_DATASET_UNVALID;
obj->members[idx].op = FEE_STATE_INVALID;
obj->members[idx].priority = NVM_QUEUE_PRIORITY_UNVALID;
obj->members[idx].state = NVM_QUEUEMEMBERSTATE_UNUSED;
}
/* The index value of the queue points to the header of the queue. */
obj->index = 0;
}
void Nvm_Queue_InitMember(Nvm_QueueMemberType *member, uint16_t blockIdx, uint16_t datasetIdx, Nvm_stateType op, uint8_t priority, uint8_t *databuff)
{
/* Initialize members of the queue. */
member->blockIdx = blockIdx;
member->datasetIdx = datasetIdx;
member->op = op;
member->databuff = databuff;
member->priority = priority;
member->state = NVM_QUEUEMEMBERSTATE_USED;
}
void Nvm_Queue_Insert(Nvm_QueueType *obj, Nvm_QueueMemberType *member)
{
uint8_t localIdx;
/* Check if the queue is empty. */
if(NVM_RETURN_NOT_OK == Nvm_Queue_CheckEmpty(obj))
{
/* Insert members into the queue according to priority. */
for(localIdx = obj->index; localIdx > 0; localIdx--)
{
if(obj->members[localIdx - 1].priority > member->priority)
{
if(NVM_QUEUEMEMBERSTATE_LOCK != obj->members[localIdx - 1].state)
{
obj->members[localIdx] = obj->members[localIdx - 1];
}
else
{
break;
}
}
else
{
break;
}
}
obj->members[localIdx] = *member;
obj->members[localIdx].state = NVM_QUEUEMEMBERSTATE_USED;
obj->index++;
}
else
{
/* Append member to queue. */
Nvm_Queue_Append(obj, member);
}
}
void Nvm_Queue_RemoveLastItem(Nvm_QueueType *obj)
{
Nvm_QueueMemberType member;
/* Set the member of the queue to the default value. */
member.blockIdx = NVM_QUEUE_BLOCK_UNVALID;
member.datasetIdx = NVM_QUEUE_DATASET_UNVALID;
member.op = FEE_STATE_INVALID;
member.priority = NVM_QUEUE_PRIORITY_UNVALID;
member.state = NVM_QUEUEMEMBERSTATE_UNUSED;
member.databuff = NULL;
/* Remove member from queue. */
if(NVM_QUEUEMEMBERSTATE_LOCK != obj->members[obj->index - 1].state)
{
obj->members[obj->index - 1] = member;
obj->index--;
}
}
void Nvm_Queue_RemoveFirstItem(Nvm_QueueType *obj)
{
uint8_t localIdx;
/* Check if the queue is not empty. */
if(NVM_RETURN_NOT_OK == Nvm_Queue_CheckEmpty(obj))
{
/* Remove member from queue. */
for(localIdx = 0; localIdx < obj->index; localIdx++)
{
if((localIdx + 1) >= obj->index)
{
/* Set the member of the queue to the default value. */
obj->members[localIdx].blockIdx = NVM_QUEUE_BLOCK_UNVALID;
obj->members[localIdx].datasetIdx = NVM_QUEUE_DATASET_UNVALID;
obj->members[localIdx].op = FEE_STATE_INVALID;
obj->members[localIdx].priority = NVM_QUEUE_PRIORITY_UNVALID;
obj->members[localIdx].state = NVM_QUEUEMEMBERSTATE_UNUSED;
}
else
{
obj->members[localIdx] = obj->members[localIdx + 1];
}
}
obj->index--;
}
}
Nvm_ReturnType Nvm_Queue_CheckFull(Nvm_QueueType *obj)
{
Nvm_ReturnType ret = NVM_RETURN_NOT_OK;
/* When the index value points to the end of the queue, it indicates that the queue is full. */
if(obj->index >= obj->memberNum)
{
ret = NVM_RETURN_OK;
}
return ret;
}
Nvm_ReturnType Nvm_Queue_CheckEmpty(Nvm_QueueType *obj)
{
Nvm_ReturnType ret = NVM_RETURN_NOT_OK;
/* When the index value points to the queue header, it indicates that the queue is empty. */
if(obj->index == 0)
{
ret = NVM_RETURN_OK;
}
return ret;
}
static void Nvm_Queue_Append(Nvm_QueueType *obj, Nvm_QueueMemberType *member)
{
/* Append member to the end of the queue. */
obj->members[obj->index] = (*member);
obj->members[obj->index].state = NVM_QUEUEMEMBERSTATE_USED;
obj->index++;
}

View File

@ -0,0 +1,89 @@
/*
* 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.
*/
#ifndef _NVM_QUEUE_H_
#define _NVM_QUEUE_H_
/*! \brief Contains public interface to various functions related
* to the NVM (NVRAM Manager) module
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "nvm_types.h"
/*! \addtogroup NVRAM Manager
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*! \brief Define macro to obtain whether queue header members already exist.
*/
#define NVM_QUEUE_FISTMEMBER_VALID(OBJ) (NVM_QUEUEMEMBERSTATE_UNUSED != OBJ->members[0].state)
/*! \brief Define a macro to obtain the operation attribute of queue header members.
*/
#define NVM_QUEUE_FISTMEMBER_OP(OBJ) (OBJ->members[0].op)
/*! \brief Define macros for adding system queue members.
*/
#define NVM_QUEUE_SYSMEMBER(member, op) Nvm_Queue_InitMember(member, NVM_BLOCK_INVALID_IDX, NVM_DATASET_INVALID_IDX, op, NVM_BLOCK_HIGHT_PRIORITY, NULL)
/*! \brief Define macros for locking queue header members.
*/
#define NVM_QUEUE_LOCK_FIRST_JOB(obj) obj->members[0].state = NVM_QUEUEMEMBERSTATE_LOCK
/*! \brief Define macros for obtaining queue header members.
*/
#define NVM_QUEUE_FIRST_JOB(obj) obj->members[0]
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
void Nvm_Queue_Init(Nvm_QueueType *obj);
void Nvm_Queue_InitMember(Nvm_QueueMemberType *member, uint16_t blockIdx, uint16_t datasetIdx, Nvm_stateType op, uint8_t priority, uint8_t *databuff);
void Nvm_Queue_Insert(Nvm_QueueType *obj, Nvm_QueueMemberType *member);
void Nvm_Queue_RemoveLastItem(Nvm_QueueType *obj);
void Nvm_Queue_RemoveFirstItem(Nvm_QueueType *obj);
Nvm_ReturnType Nvm_Queue_CheckFull(Nvm_QueueType *obj);
Nvm_ReturnType Nvm_Queue_CheckEmpty(Nvm_QueueType *obj);
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _NVM_QUEUE_H_ */

View File

@ -0,0 +1,908 @@
/*
* 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 <string.h>
#include "nvm_statemachine.h"
#include "nvm_queue.h"
#include "nvm_block.h"
#include "nvm_extra.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*! \brief Macro that defines whether to complete immediate writing.
*/
#define NVM_IMMEDIATE_WRITE_FINISH(obj) (NVM_IMMEDIATEWRITEFSM_FINISH == obj->runtime->immediateWriteJob->job)
/*! \brief Define macros that immediately fail to write.
*/
#define NVM_IMMEDIATE_WRITE_FAIL(obj) (NVM_IMMEDIATEWRITEFSM_WRITEERROR == obj->runtime->immediateWriteJob->job)
/*! \brief Define macros that immediately write errors.
*/
#define NVM_IMMEDIATE_WRITE_FATAL(obj) (NVM_IMMEDIATEWRITEFSM_ERROR == obj->runtime->immediateWriteJob->job)
/*! \brief Define immediate read completion macros.
*/
#define NVM_IMMEDIATE_READ_FINISH(obj) (NVM_IMMEDIATEREADFSM_FINISH == obj->runtime->immediateReadJob->job)
/*! \brief Define macros that immediately fail to read.
*/
#define NVM_IMMEDIATE_READ_FAIL(obj) (NVM_IMMEDIATEREADFSM_READERROR == obj->runtime->immediateReadJob->job)
/*! \brief Define macros for immediate read errors.
*/
#define NVM_IMMEDIATE_READ_FATAL(obj) (NVM_IMMEDIATEREADFSM_ERROR == obj->runtime->immediateReadJob->job)
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
static void Nvm_StateMachine_Immediate_Read_Entry(const NvmType *obj, uint16_t blockIdx, uint16_t datasetIdx, uint8_t retry, NvmNotificationPtrType notificationPtr);
static void Nvm_StateMachine_Immediate_Read(const NvmType *obj);
static void Nvm_StateMachine_Immediate_Write_Entry(const NvmType *obj, uint16_t blockIdx, uint16_t datasetIdx, uint8_t retry, NvmNotificationPtrType notificationPtr);
static void Nvm_StateMachine_Immediate_Write(const NvmType *obj);
/*******************************************************************************
* the functions
******************************************************************************/
void Nvm_StateMachine_Idle(const NvmType *obj)
{
/* Check if the lower level module status is idle. */
if(NVM_STATUS_IDLE == obj->method->getStatus())
{
/* Check if the job queue is empty. */
if(NVM_RETURN_NOT_OK == Nvm_Queue_CheckEmpty(obj->runtime->queue))
{
/* Check if the header members of the queue are valid. */
if(NVM_QUEUE_FISTMEMBER_VALID(obj->runtime->queue))
{
/* Lock the header member of the queue */
NVM_QUEUE_LOCK_FIRST_JOB(obj->runtime->queue);
/* Responding to job requests. */
obj->runtime->nextState = NVM_QUEUE_FISTMEMBER_OP(obj->runtime->queue);
}
else
{
/* When the header member of the queue is an invalid request, the member will be removed. */
Nvm_Queue_RemoveFirstItem(obj->runtime->queue);
}
}
}
}
void Nvm_StateMachine_Read_Entry(const NvmType *obj)
{
uint16_t localBlockIdx;
uint16_t localDatasetIdx;
localBlockIdx = NVM_QUEUE_FIRST_JOB(obj->runtime->queue).blockIdx;
localDatasetIdx = NVM_QUEUE_FIRST_JOB(obj->runtime->queue).datasetIdx;
Nvm_Block_SetState(obj->blockTable, localBlockIdx, localDatasetIdx, NVM_REQ_PENDING);
obj->runtime->readJob->blockIdx = localBlockIdx;
obj->runtime->readJob->datasetIdx = localDatasetIdx;
obj->runtime->readJob->cpyBuff = NVM_BLOCK_GET_RAM_BUFF_PTR(obj->blockTable, localBlockIdx, localDatasetIdx);
obj->runtime->readJob->userBuff = NVM_QUEUE_FIRST_JOB(obj->runtime->queue).databuff;
obj->runtime->readJob->datasize = NVM_BLOCK_GET_DATASIZE(obj->blockTable, localBlockIdx);
}
void Nvm_StateMachine_Read(const NvmType *obj)
{
/* Verify the data validity of the block. */
Nvm_Block_DataRepair(obj->blockTable, obj->method, obj->runtime->readJob->blockIdx, obj->runtime->readJob->datasetIdx);
/* Copy block data to user buff. */
memcpy((void *)obj->runtime->readJob->userBuff, obj->runtime->readJob->cpyBuff, obj->runtime->readJob->datasize);
/* Mark the external state of the block as NVM_REQ_OK. */
Nvm_Block_SetState(obj->blockTable, obj->runtime->readJob->blockIdx, obj->runtime->readJob->datasetIdx, NVM_REQ_OK);
/* Remove the request. */
Nvm_Queue_RemoveFirstItem(obj->runtime->queue);
/* Switch nvm state to idle. */
obj->runtime->nextState = NVM_STATE_IDLE;
}
void Nvm_StateMachine_Write_Entry(const NvmType *obj)
{
uint16_t localBlockIdx;
uint16_t localDatasetIdx;
localBlockIdx = NVM_QUEUE_FIRST_JOB(obj->runtime->queue).blockIdx;
localDatasetIdx = NVM_QUEUE_FIRST_JOB(obj->runtime->queue).datasetIdx;
Nvm_Block_SetState(obj->blockTable, localBlockIdx, localDatasetIdx, NVM_REQ_PENDING);
obj->runtime->writeJob->blockIdx = localBlockIdx;
obj->runtime->writeJob->datasetIdx = localDatasetIdx;
obj->runtime->writeJob->blockDatabuff = NVM_BLOCK_GET_TEMP_RAM_BUFF_PTR(obj->blockTable, localBlockIdx);
obj->runtime->writeJob->userBuff = NVM_QUEUE_FIRST_JOB(obj->runtime->queue).databuff;
obj->runtime->writeJob->useSize = NVM_BLOCK_GET_DATASIZE(obj->blockTable, localBlockIdx);
obj->runtime->writeJob->job = NVM_WRITEFSM_INIT;
Nvm_Block_SetTempRamBuffDefaultVal(obj->blockTable, localBlockIdx, localDatasetIdx);
}
void Nvm_StateMachine_Write(const NvmType *obj)
{
switch(obj->runtime->writeJob->job)
{
case NVM_WRITEFSM_INIT:
{
/* If the type of the block is REDUNDANT, the state machine will be marked as a redundant write state. */
/* If not, it will be judged whether it is an immediate write state. */
/* If not, the state machine will be marked as a normal write state. */
/* Otherwise, it will be marked as an immediate write state. */
memcpy((void *)obj->runtime->writeJob->blockDatabuff, (void *)obj->runtime->writeJob->userBuff, obj->runtime->writeJob->useSize);
if(NVM_BLOCK_IS_REDUNDANT(obj->blockTable, obj->runtime->writeJob->blockIdx))
{
obj->runtime->writeJob->job = NVM_WRITEFSM_REDUNDANT_MAIN;
}
else if(NVM_BLOCK_IS_IMMEDIATE(obj->blockTable, obj->runtime->writeJob->blockIdx))
{
Nvm_StateMachine_Immediate_Write_Entry(obj, obj->runtime->writeJob->blockIdx, obj->runtime->writeJob->datasetIdx, NVM_BLOCK_RETRY_NUM, NULL);
obj->runtime->writeJob->job = NVM_WRITEFSM_IMMEDIATE;
}
else
{
obj->runtime->writeJob->job = NVM_WRITEFSM_NORMAL;
}
break;
}
case NVM_WRITEFSM_IMMEDIATE:
{
/* If the immediate write execution is successful or an error occurs, */
/* mark the state machine to the read back state, otherwise mark the state machine to the normal state. */
Nvm_StateMachine_Immediate_Write(obj);
if(NVM_IMMEDIATE_WRITE_FINISH(obj) || NVM_IMMEDIATE_WRITE_FATAL(obj))
{
Nvm_StateMachine_Immediate_Read_Entry(obj, obj->runtime->writeJob->blockIdx, obj->runtime->writeJob->datasetIdx, NVM_BLOCK_RETRY_NUM, NULL);
obj->runtime->writeJob->job = NVM_WRITEFSM_READBACK;
}
else if(NVM_IMMEDIATE_WRITE_FAIL(obj))
{
obj->runtime->writeJob->job = NVM_WRITEFSM_NORMAL;
}
break;
}
case NVM_WRITEFSM_REDUNDANT_MAIN:
{
/* Execute the write main area of a REDUNDANT type block. */
obj->runtime->writeJob->blockBackUp = false;
obj->runtime->writeJob->datasetIdx = NVM_BLOCK_MAIN_IDX;
if(NVM_BLOCK_IS_IMMEDIATE(obj->blockTable, obj->runtime->writeJob->blockIdx))
{
Nvm_StateMachine_Immediate_Write_Entry(obj, obj->runtime->writeJob->blockIdx, obj->runtime->writeJob->datasetIdx, NVM_BLOCK_RETRY_NUM, NULL);
obj->runtime->writeJob->job = NVM_WRITEFSM_IMMEDIATE;
}
else
{
obj->runtime->writeJob->job = NVM_WRITEFSM_NORMAL;
}
break;
}
case NVM_WRITEFSM_REDUNDANT_BACKUP:
{
/* Execute the write backup area of a REDUNDANT type block. */
obj->runtime->writeJob->blockBackUp = true;
obj->runtime->writeJob->datasetIdx = NVM_BLOCK_BACKUP_IDX;
if(NVM_BLOCK_IS_IMMEDIATE(obj->blockTable, obj->runtime->writeJob->blockIdx))
{
Nvm_StateMachine_Immediate_Write_Entry(obj, obj->runtime->writeJob->blockIdx, obj->runtime->writeJob->datasetIdx, NVM_BLOCK_RETRY_NUM, NULL);
obj->runtime->writeJob->job = NVM_WRITEFSM_IMMEDIATE;
}
else
{
obj->runtime->writeJob->job = NVM_WRITEFSM_NORMAL;
}
break;
}
case NVM_WRITEFSM_READBACK:
{
/* Performing operations to read back data. */
Nvm_StateMachine_Immediate_Read(obj);
if(NVM_IMMEDIATE_READ_FINISH(obj) || NVM_IMMEDIATE_READ_FATAL(obj))
{
obj->runtime->writeJob->job = NVM_WRITEFSM_CHECK;
}
else if(NVM_IMMEDIATE_READ_FAIL(obj))
{
obj->runtime->writeJob->job = NVM_WRITEFSM_NORMAL;
}
break;
}
case NVM_WRITEFSM_CHECK:
{
/* Check the validity of data within the block. */
Nvm_Block_DataRepair(obj->blockTable, obj->method, obj->runtime->writeJob->blockIdx, obj->runtime->writeJob->datasetIdx);
Nvm_Block_SetState(obj->blockTable, obj->runtime->writeJob->blockIdx, obj->runtime->writeJob->datasetIdx, NVM_BLOCK_GET_INT_STATE(obj->blockTable, obj->runtime->writeJob->blockIdx, obj->runtime->writeJob->datasetIdx));
if(NVM_BLOCK_IS_REDUNDANT(obj->blockTable, obj->runtime->writeJob->blockIdx))
{
if(obj->runtime->writeJob->blockBackUp)
{
obj->runtime->writeJob->job = NVM_WRITEFSM_FINISH;
}else
{
obj->runtime->writeJob->job = NVM_WRITEFSM_REDUNDANT_BACKUP;
}
}
else
{
obj->runtime->writeJob->job = NVM_WRITEFSM_FINISH;
}
break;
}
case NVM_WRITEFSM_NORMAL:
{
/* Write data to the ram area of the block. */
Nvm_Block_WriteDataToRamBlock(obj->blockTable, obj->method, obj->runtime->writeJob->blockIdx, obj->runtime->writeJob->datasetIdx, obj->runtime->writeJob->userBuff);
Nvm_Block_SetState(obj->blockTable, obj->runtime->writeJob->blockIdx, obj->runtime->writeJob->datasetIdx, NVM_REQ_OK);
if(NVM_BLOCK_IS_REDUNDANT(obj->blockTable, obj->runtime->writeJob->blockIdx))
{
if(obj->runtime->writeJob->blockBackUp)
{
obj->runtime->writeJob->job = NVM_WRITEFSM_FINISH;
}
else
{
obj->runtime->writeJob->job = NVM_WRITEFSM_REDUNDANT_BACKUP;
}
}
else
{
obj->runtime->writeJob->job = NVM_WRITEFSM_FINISH;
}
break;
}
case NVM_WRITEFSM_FINISH:
{
/* Complete response request. */
Nvm_Queue_RemoveFirstItem(obj->runtime->queue);
obj->runtime->nextState = NVM_STATE_IDLE;
break;
}
case NVM_WRITEFSM_WRITEERROR:
{
/* Complete response request. */
Nvm_Queue_RemoveFirstItem(obj->runtime->queue);
obj->runtime->nextState = NVM_STATE_IDLE;
break;
}
default:
{
break;
}
}
}
void Nvm_StateMachine_ReadAll_Entry(const NvmType *obj)
{
obj->runtime->readAllJob->job = NVM_READALLFSM_READBLOCK;
obj->runtime->readAllJob->blockIdx = 0;
}
void Nvm_StateMachine_ReadAll(const NvmType *obj)
{
switch(obj->runtime->readAllJob->job)
{
case NVM_READALLFSM_READBLOCK:
{
/* Mark the state machine as finished after traversing all blocks. */
if(obj->runtime->readAllJob->blockIdx < obj->blockTable->itemsNum)
{
obj->runtime->readAllJob->datasetIdx = 0;
obj->runtime->readAllJob->job = NVM_READALLFSM_READENTRY;
}
else
{
obj->runtime->readAllJob->job = NVM_READALLFSM_FINISH;
}
break;
}
case NVM_READALLFSM_READENTRY:
{
/* Execute the preparation program before immediate reading. */
if(obj->runtime->readAllJob->datasetIdx < NVM_BLOCK_GET_DATASETNUM(obj->blockTable, obj->runtime->readAllJob->blockIdx))
{
Nvm_Block_SetState(obj->blockTable, obj->runtime->readAllJob->blockIdx, obj->runtime->readAllJob->datasetIdx, NVM_REQ_PENDING);
Nvm_StateMachine_Immediate_Read_Entry(obj, obj->runtime->readAllJob->blockIdx, obj->runtime->readAllJob->datasetIdx, NVM_BLOCK_RETRY_NUM, NULL);
obj->runtime->readAllJob->job = NVM_READALLFSM_READ;
}
else
{
obj->runtime->readAllJob->blockIdx++;
obj->runtime->readAllJob->job = NVM_READALLFSM_READBLOCK;
}
break;
}
case NVM_READALLFSM_READ:
{
/* Execute immediate read. */
Nvm_StateMachine_Immediate_Read(obj);
if(NVM_IMMEDIATE_READ_FINISH(obj) || NVM_IMMEDIATE_READ_FAIL(obj) || NVM_IMMEDIATE_READ_FATAL(obj))
{
obj->runtime->readAllJob->job = NVM_READALLFSM_CHECK;
}
break;
}
case NVM_READALLFSM_CHECK:
{
/* Check the validity of data within the block. */
Nvm_Block_DataRepair(obj->blockTable, obj->method, obj->runtime->readAllJob->blockIdx, obj->runtime->readAllJob->datasetIdx);
Nvm_Block_SetState(obj->blockTable, obj->runtime->readAllJob->blockIdx, obj->runtime->readAllJob->datasetIdx, NVM_BLOCK_GET_INT_STATE(obj->blockTable, obj->runtime->readAllJob->blockIdx, obj->runtime->readAllJob->datasetIdx));
obj->runtime->readAllJob->datasetIdx++;
obj->runtime->readAllJob->job = NVM_READALLFSM_READENTRY;
break;
}
case NVM_READALLFSM_FINISH:
{
/* Complete response request. */
Nvm_Queue_RemoveFirstItem(obj->runtime->queue);
obj->runtime->nextState = NVM_STATE_IDLE;
break;
}
case NVM_READALLFSM_ERROR:
{
/* Complete response request. */
Nvm_Queue_RemoveFirstItem(obj->runtime->queue);
obj->runtime->nextState = NVM_STATE_IDLE;
break;
}
default:
{
break;
}
}
}
void Nvm_StateMachine_WriteAll_Entry(const NvmType *obj)
{
obj->runtime->writeAllJob->job = NVM_WRITEALLFSM_WRITEBLOCK;
obj->runtime->writeAllJob->blockIdx = 0;
}
void Nvm_StateMachine_WriteAll(const NvmType *obj)
{
switch(obj->runtime->writeAllJob->job)
{
case NVM_WRITEALLFSM_WRITEBLOCK:
{
/* Mark the state machine as finished after traversing all blocks. */
if(obj->runtime->writeAllJob->blockIdx < obj->blockTable->itemsNum)
{
if(NVM_BLOCK_IS_NORMAL(obj->blockTable, obj->runtime->writeAllJob->blockIdx))
{
obj->runtime->writeAllJob->datasetIdx = 0;
obj->runtime->writeAllJob->job = NVM_WRITEALLFSM_WRITEENTRY;
}
else
{
obj->runtime->writeAllJob->blockIdx++;
}
}
else
{
obj->runtime->writeAllJob->job = NVM_WRITEALLFSM_FINISH;
}
break;
}
case NVM_WRITEALLFSM_WRITEENTRY:
{
/* Execute the preparation program before immediate writeing. */
if(obj->runtime->writeAllJob->datasetIdx < NVM_BLOCK_GET_DATASETNUM(obj->blockTable, obj->runtime->writeAllJob->blockIdx))
{
obj->runtime->writeAllJob->blockDatabuff = NVM_BLOCK_GET_TEMP_RAM_BUFF_PTR(obj->blockTable, obj->runtime->writeAllJob->blockIdx);
if(Nvm_Block_GetWriteData(obj->blockTable, obj->runtime->writeAllJob->blockIdx, obj->runtime->writeAllJob->datasetIdx, obj->method, obj->runtime->writeAllJob->blockDatabuff))
{
Nvm_Block_SetState(obj->blockTable, obj->runtime->writeAllJob->blockIdx, obj->runtime->writeAllJob->datasetIdx, NVM_REQ_PENDING);
Nvm_StateMachine_Immediate_Write_Entry(obj, obj->runtime->writeAllJob->blockIdx, obj->runtime->writeAllJob->datasetIdx, NVM_BLOCK_RETRY_NUM, NULL);
obj->runtime->writeAllJob->job = NVM_WRITEALLFSM_WRITE;
}
else
{
obj->runtime->writeAllJob->datasetIdx++;
}
}
else
{
obj->runtime->writeAllJob->blockIdx++;
obj->runtime->writeAllJob->job = NVM_WRITEALLFSM_WRITEBLOCK;
}
break;
}
case NVM_WRITEALLFSM_WRITE:
{
/* Execute immediate write. */
Nvm_StateMachine_Immediate_Write(obj);
if(NVM_IMMEDIATE_WRITE_FINISH(obj) || NVM_IMMEDIATE_WRITE_FAIL(obj) || NVM_IMMEDIATE_WRITE_FATAL(obj))
{
Nvm_Block_SetState(obj->blockTable, obj->runtime->writeAllJob->blockIdx, obj->runtime->writeAllJob->datasetIdx, NVM_BLOCK_GET_INT_STATE(obj->blockTable, obj->runtime->writeAllJob->blockIdx, obj->runtime->writeAllJob->datasetIdx));
obj->runtime->writeAllJob->datasetIdx++;
obj->runtime->writeAllJob->job = NVM_WRITEALLFSM_WRITEENTRY;
}
break;
}
case NVM_WRITEALLFSM_FINISH:
{
/* Complete response request. */
Nvm_Queue_RemoveFirstItem(obj->runtime->queue);
obj->runtime->nextState = NVM_STATE_IDLE;
break;
}
case NVM_WRITEALLFSM_ERROR:
{
/* Complete response request. */
Nvm_Queue_RemoveFirstItem(obj->runtime->queue);
obj->runtime->nextState = NVM_STATE_IDLE;
break;
}
default:
{
break;
}
}
}
void Nvm_StateMachine_EraseAll_Entry(const NvmType *obj)
{
obj->runtime->eraseAllJob->blockIdx = 0;
obj->runtime->eraseAllJob->job = NVM_ERASEALLFSM_ERASEBLOCK;
}
void Nvm_StateMachine_EraseAll(const NvmType *obj)
{
switch(obj->runtime->eraseAllJob->job)
{
case NVM_ERASEALLFSM_ERASEBLOCK:
{
/* Mark the state machine as finished after traversing all blocks. */
if(obj->runtime->eraseAllJob->blockIdx < obj->blockTable->itemsNum)
{
obj->runtime->eraseAllJob->datasetIdx = 0;
obj->runtime->eraseAllJob->job = NVM_ERASEALLFSM_ERASEENTRY;
}
else
{
obj->runtime->eraseAllJob->job = NVM_ERASEALLFSM_FINISH;
}
break;
}
case NVM_ERASEALLFSM_ERASEENTRY:
{
/* Execute the preparation program before erasing immediately. */
if(obj->runtime->eraseAllJob->datasetIdx < NVM_BLOCK_GET_DATASETNUM(obj->blockTable, obj->runtime->eraseAllJob->blockIdx))
{
obj->runtime->eraseAllJob->blockDatabuff = NVM_BLOCK_GET_TEMP_RAM_BUFF_PTR(obj->blockTable, obj->runtime->eraseAllJob->blockIdx);
Nvm_Block_GetRomData(obj->blockTable, obj->runtime->eraseAllJob->blockIdx, obj->runtime->eraseAllJob->datasetIdx, obj->runtime->eraseAllJob->blockDatabuff);
Nvm_Block_SetState(obj->blockTable, obj->runtime->eraseAllJob->blockIdx, obj->runtime->eraseAllJob->datasetIdx, NVM_REQ_PENDING);
Nvm_StateMachine_Immediate_Write_Entry(obj, obj->runtime->eraseAllJob->blockIdx, obj->runtime->eraseAllJob->datasetIdx, NVM_BLOCK_RETRY_NUM, NULL);
obj->runtime->eraseAllJob->job = NVM_ERASEALLFSM_ERASE;
}
else
{
obj->runtime->eraseAllJob->blockIdx++;
obj->runtime->eraseAllJob->job = NVM_ERASEALLFSM_ERASEBLOCK;
}
break;
}
case NVM_ERASEALLFSM_ERASE:
{
/* Execute immediate erase. */
Nvm_StateMachine_Immediate_Write(obj);
if(NVM_IMMEDIATE_WRITE_FINISH(obj) || NVM_IMMEDIATE_WRITE_FAIL(obj) || NVM_IMMEDIATE_WRITE_FATAL(obj))
{
obj->runtime->eraseAllJob->job = NVM_ERASEALLFSM_READBACK;
}
break;
}
case NVM_ERASEALLFSM_READBACK:
{
/* Performing operations to read back data. */
obj->runtime->eraseAllJob->blockRombuff = NVM_BLOCK_GET_ROM_BUFF_PTR(obj->blockTable, obj->runtime->eraseAllJob->blockIdx, obj->runtime->eraseAllJob->datasetIdx);
Nvm_Block_WriteDataToRamBlock(obj->blockTable, obj->method, obj->runtime->eraseAllJob->blockIdx, obj->runtime->eraseAllJob->datasetIdx, obj->runtime->eraseAllJob->blockRombuff);
Nvm_Block_SetState(obj->blockTable, obj->runtime->eraseAllJob->blockIdx, obj->runtime->eraseAllJob->datasetIdx, NVM_BLOCK_GET_INT_STATE(obj->blockTable, obj->runtime->eraseAllJob->blockIdx, obj->runtime->eraseAllJob->datasetIdx));
obj->runtime->eraseAllJob->datasetIdx++;
obj->runtime->eraseAllJob->job = NVM_ERASEALLFSM_ERASEENTRY;
break;
}
case NVM_ERASEALLFSM_FINISH:
{
/* Complete response request. */
Nvm_Queue_RemoveFirstItem(obj->runtime->queue);
obj->runtime->nextState = NVM_STATE_IDLE;
break;
}
case NVM_WRITEALLFSM_ERROR:
{
/* Complete response request. */
Nvm_Queue_RemoveFirstItem(obj->runtime->queue);
obj->runtime->nextState = NVM_STATE_IDLE;
break;
}
default:
{
break;
}
}
}
void Nvm_StateMachine_Erase_Entry(const NvmType *obj)
{
uint16_t localBlockIdx;
uint16_t localDatasetIdx;
localBlockIdx = obj->runtime->queue->members[0].blockIdx;
localDatasetIdx = obj->runtime->queue->members[0].datasetIdx;
Nvm_Block_SetState(obj->blockTable, localBlockIdx, localDatasetIdx, NVM_REQ_PENDING);
obj->runtime->eraseJob->blockIdx = localBlockIdx;
obj->runtime->eraseJob->datasetIdx = localDatasetIdx;
obj->runtime->eraseJob->blockDatabuff = NVM_BLOCK_GET_TEMP_RAM_BUFF_PTR(obj->blockTable, localBlockIdx);
obj->runtime->eraseJob->job = NVM_ERASEFSM_INIT;
Nvm_Block_GetRomData(obj->blockTable, obj->runtime->eraseJob->blockIdx, obj->runtime->eraseJob->datasetIdx, obj->runtime->eraseJob->blockDatabuff);
}
void Nvm_StateMachine_Erase(const NvmType *obj)
{
switch(obj->runtime->eraseJob->job)
{
case NVM_ERASEFSM_INIT:
{
/* If the type of the block is REDUNDANT, the state machine will be marked as a redundant state. */
/* If not, it will be judged whether it is an immediate state. */
/* Otherwise, it will be marked as an immediate state. */
if(NVM_BLOCK_IS_REDUNDANT(obj->blockTable, obj->runtime->eraseJob->blockIdx))
{
obj->runtime->eraseJob->job = NVM_ERASEFSM_REDUNDANT_MAIN;
}
else
{
Nvm_StateMachine_Immediate_Write_Entry(obj, obj->runtime->eraseJob->blockIdx, obj->runtime->eraseJob->datasetIdx, NVM_BLOCK_RETRY_NUM, NULL);
obj->runtime->eraseJob->job = NVM_ERASEFSM_IMMEDIATE;
}
break;
}
case NVM_ERASEFSM_IMMEDIATE:
{
/* If the immediate execution is successful or an error occurs, */
/* mark the state machine to the read back state.*/
Nvm_StateMachine_Immediate_Write(obj);
if(NVM_IMMEDIATE_WRITE_FINISH(obj) || NVM_IMMEDIATE_WRITE_FAIL(obj) || NVM_IMMEDIATE_WRITE_FATAL(obj))
{
Nvm_StateMachine_Immediate_Read_Entry(obj, obj->runtime->eraseJob->blockIdx, obj->runtime->eraseJob->datasetIdx, NVM_BLOCK_RETRY_NUM, NULL);
obj->runtime->eraseJob->job = NVM_ERASEFSM_READBACK;
}
break;
}
case NVM_ERASEFSM_REDUNDANT_MAIN:
{
/* Execute the erase main area of a REDUNDANT type block. */
obj->runtime->writeJob->blockBackUp = false;
obj->runtime->writeJob->datasetIdx = NVM_BLOCK_MAIN_IDX;
Nvm_StateMachine_Immediate_Write_Entry(obj, obj->runtime->writeJob->blockIdx, obj->runtime->writeJob->datasetIdx, NVM_BLOCK_RETRY_NUM, NULL);
obj->runtime->writeJob->job = NVM_WRITEFSM_IMMEDIATE;
break;
}
case NVM_ERASEFSM_REDUNDANT_BACKUP:
{
/* Execute the erase backup area of a REDUNDANT type block. */
obj->runtime->writeJob->blockBackUp = true;
obj->runtime->writeJob->datasetIdx = NVM_BLOCK_BACKUP_IDX;
Nvm_StateMachine_Immediate_Write_Entry(obj, obj->runtime->writeJob->blockIdx, obj->runtime->writeJob->datasetIdx, NVM_BLOCK_RETRY_NUM, NULL);
obj->runtime->writeJob->job = NVM_WRITEFSM_IMMEDIATE;
break;
}
case NVM_ERASEFSM_READBACK:
{
/* Performing operations to read back data. */
Nvm_StateMachine_Immediate_Read(obj);
if(NVM_IMMEDIATE_READ_FINISH(obj) || NVM_IMMEDIATE_READ_FAIL(obj) || NVM_IMMEDIATE_READ_FATAL(obj))
{
obj->runtime->eraseJob->job = NVM_ERASEFSM_CHECK;
}
break;
}
case NVM_ERASEFSM_CHECK:
{
/* Check the validity of data within the block. */
Nvm_Block_DataRepair(obj->blockTable, obj->method, obj->runtime->eraseJob->blockIdx, obj->runtime->eraseJob->datasetIdx);
Nvm_Block_SetState(obj->blockTable, obj->runtime->eraseJob->blockIdx, obj->runtime->eraseJob->datasetIdx, NVM_BLOCK_GET_INT_STATE(obj->blockTable, obj->runtime->eraseJob->blockIdx, obj->runtime->eraseJob->datasetIdx));
/* Determine the type of block. */
if(NVM_BLOCK_IS_REDUNDANT(obj->blockTable, obj->runtime->eraseJob->blockIdx))
{
if(obj->runtime->eraseJob->blockBackUp)
{
obj->runtime->eraseJob->job = NVM_ERASEFSM_FINISH;
}
else
{
obj->runtime->eraseJob->job = NVM_ERASEFSM_REDUNDANT_BACKUP;
}
}
else
{
obj->runtime->eraseJob->job = NVM_ERASEFSM_FINISH;
}
break;
}
case NVM_ERASEFSM_FINISH:
{
/* Complete response request. */
Nvm_Queue_RemoveFirstItem(obj->runtime->queue);
obj->runtime->nextState = NVM_STATE_IDLE;
break;
}
case NVM_ERASEFSM_ERASEERROR:
{
/* Complete response request. */
Nvm_Queue_RemoveFirstItem(obj->runtime->queue);
obj->runtime->nextState = NVM_STATE_IDLE;
break;
}
default:
{
break;
}
}
}
void Nvm_StateMachine_Immediate_Read_Entry(const NvmType *obj, uint16_t blockIdx, uint16_t datasetIdx, uint8_t retry, NvmNotificationPtrType notificationPtr)
{
obj->runtime->immediateReadJob->job = NVM_IMMEDIATEREADFSM_MAIN;
Nvm_Block_SetInternalState(obj->blockTable, blockIdx, datasetIdx, NVM_REQ_PENDING);
Nvm_Block_ClrRamBuff(obj->blockTable, blockIdx, datasetIdx);
obj->runtime->immediateReadJob->mainRetryCnt = retry;
obj->runtime->immediateReadJob->backupRetryCnt = retry;
obj->runtime->immediateReadJob->notificationPtr = notificationPtr;
obj->runtime->immediateReadJob->blockIdx = blockIdx;
obj->runtime->immediateReadJob->datasetIdx = datasetIdx;
obj->runtime->immediateReadJob->blockNumber = obj->blockTable->items[blockIdx].number + datasetIdx;
obj->runtime->immediateReadJob->blockDatabuff = NVM_BLOCK_GET_TEMP_RAM_BUFF_PTR(obj->blockTable, blockIdx);
obj->runtime->immediateReadJob->blockUseSize = ALIGN8BYTE(Nvm_Block_CalcUseSize(obj->blockTable, blockIdx));
}
static void Nvm_StateMachine_Immediate_Read(const NvmType *obj)
{
switch(obj->runtime->immediateReadJob->job)
{
case NVM_IMMEDIATEREADFSM_MAIN:
{
/* Obtain lower level module status. */
if(NVM_STATUS_IDLE == obj->method->getStatus())
{
/* Request lower level module to read data. */
if(obj->method->read(obj->runtime->immediateReadJob->blockNumber, NVM_BLOCK_MAIN_IDX, obj->runtime->immediateReadJob->blockDatabuff, obj->runtime->immediateReadJob->notificationPtr))
{
/* Request successful, waiting for the response from the lower level module to complete. */
obj->runtime->immediateReadJob->job = NVM_IMMEDIATEREADFSM_WMF;
}
else
{
/* If the request fails, it will be retried. */
Nvm_Block_SetInternalState(obj->blockTable, obj->runtime->immediateReadJob->blockIdx, obj->runtime->immediateReadJob->datasetIdx, NVM_REQ_NOT_OK);
obj->runtime->immediateReadJob->job = NVM_IMMEDIATEREADFSM_MAIN_RETRY;
}
}
break;
}
case NVM_IMMEDIATEREADFSM_MAIN_RETRY:
{
/* Wait for an attempt to resend the request to the lower module. */
if(obj->runtime->immediateReadJob->mainRetryCnt > 0)
{
obj->runtime->immediateReadJob->mainRetryCnt--;
obj->runtime->immediateReadJob->job = NVM_IMMEDIATEREADFSM_MAIN;
}
else
{
/* If the retry count exceeds the threshold, mark the state machine as an error. */
obj->runtime->immediateReadJob->job = NVM_IMMEDIATEREADFSM_READERROR;
}
break;
}
case NVM_IMMEDIATEREADFSM_WMF:
{
/* Waiting for lower level request status to respond successfully, response not successful, response error. */
if(NVM_JOB_RESULT_OK == obj->method->getJobResult())
{
/* Wait for the lower level request status to respond successfully, then mark the internal management status of the block as FINISH. */
Nvm_Block_WriteDataToBuff(obj->blockTable, obj->method, obj->runtime->immediateReadJob->blockIdx, obj->runtime->immediateReadJob->datasetIdx, obj->runtime->immediateReadJob->blockDatabuff);
Nvm_Block_SetInternalState(obj->blockTable, obj->runtime->immediateReadJob->blockIdx, obj->runtime->immediateReadJob->datasetIdx, NVM_REQ_OK);
obj->runtime->immediateReadJob->job = NVM_IMMEDIATEREADFSM_FINISH;
}
else if(NVM_JOB_RESULT_NOT_OK == obj->method->getJobResult())
{
/* If the request status at the lower level is unsuccessful, mark the internal management status of the block as ERROR. */
Nvm_Block_ClrBlockRamBuff(obj->blockTable, obj->runtime->immediateReadJob->blockIdx, obj->runtime->immediateReadJob->datasetIdx);
Nvm_Block_SetInternalState(obj->blockTable, obj->runtime->immediateReadJob->blockIdx, obj->runtime->immediateReadJob->datasetIdx, NVM_REQ_NOT_OK);
obj->runtime->immediateReadJob->job = NVM_IMMEDIATEREADFSM_READERROR;
}
else if(NVM_JOB_RESULT_BL_INCONSISTENT == obj->method->getJobResult())
{
/* Wait for the lower level request status to be block integrity error, then mark the internal management status of the block as ERROR. */
Nvm_Block_ClrBlockRamBuff(obj->blockTable, obj->runtime->immediateReadJob->blockIdx, obj->runtime->immediateReadJob->datasetIdx);
Nvm_Block_SetInternalState(obj->blockTable, obj->runtime->immediateReadJob->blockIdx, obj->runtime->immediateReadJob->datasetIdx, NVM_REQ_INTEGRITY_FAILED);
obj->runtime->immediateReadJob->job = NVM_IMMEDIATEREADFSM_READERROR;
}
else if(NVM_JOB_RESULT_BL_INVALID == obj->method->getJobResult())
{
/* If the request status of the lower level is an undefined block, the internal management status of the block will be marked as ERROR. */
Nvm_Block_ClrBlockRamBuff(obj->blockTable, obj->runtime->immediateReadJob->blockIdx, obj->runtime->immediateReadJob->datasetIdx);
Nvm_Block_SetInternalState(obj->blockTable, obj->runtime->immediateReadJob->blockIdx, obj->runtime->immediateReadJob->datasetIdx, NVM_REQ_UNINT);
obj->runtime->immediateReadJob->job = NVM_IMMEDIATEREADFSM_READERROR;
}
break;
}
case NVM_IMMEDIATEREADFSM_FINISH:
{
break;
}
case NVM_IMMEDIATEREADFSM_READERROR:
{
break;
}
default:
{
break;
}
}
}
static void Nvm_StateMachine_Immediate_Write_Entry(const NvmType *obj, uint16_t blockIdx, uint16_t datasetIdx, uint8_t retry, NvmNotificationPtrType notificationPtr)
{
uint16_t crcLen;
obj->runtime->immediateWriteJob->job = NVM_IMMEDIATEWRITEFSM_MAIN;
Nvm_Block_SetInternalState(obj->blockTable, blockIdx, datasetIdx, NVM_REQ_PENDING);
obj->runtime->immediateWriteJob->retry = retry;
obj->runtime->immediateWriteJob->notificationPtr = notificationPtr;
obj->runtime->immediateWriteJob->blockIdx = blockIdx;
obj->runtime->immediateWriteJob->datasetIdx = datasetIdx;
obj->runtime->immediateWriteJob->blockNumber = obj->blockTable->items[blockIdx].number + datasetIdx;
obj->runtime->immediateWriteJob->blockDatabuff = NVM_BLOCK_GET_TEMP_RAM_BUFF_PTR(obj->blockTable, blockIdx);
if(NVM_BLOCK_IS_CRC(obj->blockTable, obj->runtime->writeJob->blockIdx))
{
crcLen = NVM_BLOCK_GET_CRC_LEN(obj->blockTable, obj->runtime->writeJob->blockIdx);
obj->runtime->immediateWriteJob->blockDatabuff[crcLen] = obj->method->crc8(obj->runtime->immediateWriteJob->blockDatabuff, crcLen);
}
}
static void Nvm_StateMachine_Immediate_Write(const NvmType *obj)
{
switch(obj->runtime->immediateWriteJob->job)
{
case NVM_IMMEDIATEWRITEFSM_MAIN:
{
/* Obtain lower level module status. */
if(NVM_STATUS_IDLE == obj->method->getStatus())
{
/* Request lower level module to write data. */
if(obj->method->write(obj->runtime->immediateWriteJob->blockNumber, obj->runtime->immediateWriteJob->blockDatabuff, obj->runtime->immediateWriteJob->notificationPtr))
{
/* Request successful, waiting for the response from the lower level module to complete. */
obj->runtime->immediateWriteJob->job = NVM_IMMEDIATEWRITEFSM_WMF;
}
else
{
/* If the request fails, it will be retried. */
obj->runtime->immediateWriteJob->job = NVM_IMMEDIATEWRITEFSM_RETRY;
}
}
/* If the lower level module is in a state of responding to a request, calibrate the state machine to WAITMANAGE. */
else if(NVM_STATUS_GC == obj->method->getStatus())
{
obj->runtime->immediateWriteJob->job = NVM_IMMEDIATEWRITEFSM_WAITMANAGE;
}
else if(NVM_STATUS_READ == obj->method->getStatus())
{
obj->runtime->immediateWriteJob->job = NVM_IMMEDIATEWRITEFSM_WAITMANAGE;
}
else if(NVM_STATUS_WRITE == obj->method->getStatus())
{
obj->runtime->immediateWriteJob->job = NVM_IMMEDIATEWRITEFSM_WAITMANAGE;
}
else
{
obj->runtime->immediateWriteJob->job = NVM_IMMEDIATEWRITEFSM_ERROR;
}
break;
}
case NVM_IMMEDIATEWRITEFSM_RETRY:
{
/* Wait for an attempt to resend the request to the lower module. */
if(obj->runtime->immediateWriteJob->retry > 0)
{
obj->runtime->immediateWriteJob->retry--;
obj->runtime->immediateWriteJob->job = NVM_IMMEDIATEWRITEFSM_MAIN;
}
else
{
/* If the retry count exceeds the threshold, mark the state machine as an error. */
obj->runtime->immediateWriteJob->job = NVM_IMMEDIATEWRITEFSM_WRITEERROR;
}
break;
}
case NVM_IMMEDIATEWRITEFSM_WMF:
{
/* Waiting for lower level request status to respond successfully, response not successful, response error. */
if(NVM_JOB_RESULT_OK == obj->method->getJobResult())
{
/* Wait for the lower level request status to respond successfully, then mark the internal management status of the block as FINISH. */
Nvm_Block_SetInternalState(obj->blockTable, obj->runtime->immediateWriteJob->blockIdx, obj->runtime->immediateWriteJob->datasetIdx, NVM_REQ_OK);
obj->runtime->immediateWriteJob->job = NVM_IMMEDIATEWRITEFSM_FINISH;
}
else if(NVM_JOB_RESULT_NOT_OK == obj->method->getJobResult())
{
/* If the request status at the lower level is unsuccessful, mark the internal management status of the block as ERROR. */
Nvm_Block_SetInternalState(obj->blockTable, obj->runtime->immediateWriteJob->blockIdx, obj->runtime->immediateWriteJob->datasetIdx, NVM_REQ_NOT_OK);
obj->runtime->immediateWriteJob->job = NVM_IMMEDIATEWRITEFSM_WRITEERROR;
}
else if(NVM_JOB_RESULT_BL_INCONSISTENT == obj->method->getJobResult())
{
/* Wait for the lower level request status to be block integrity error, then mark the internal management status of the block as ERROR. */
Nvm_Block_SetInternalState(obj->blockTable, obj->runtime->immediateWriteJob->blockIdx, obj->runtime->immediateWriteJob->datasetIdx, NVM_REQ_INTEGRITY_FAILED);
obj->runtime->immediateWriteJob->job = NVM_IMMEDIATEWRITEFSM_WRITEERROR;
}
else if(NVM_JOB_RESULT_BL_INVALID == obj->method->getJobResult())
{
/* If the request status of the lower level is an undefined block, the internal management status of the block will be marked as ERROR. */
Nvm_Block_SetInternalState(obj->blockTable, obj->runtime->immediateWriteJob->blockIdx, obj->runtime->immediateWriteJob->datasetIdx, NVM_REQ_UNINT);
obj->runtime->immediateWriteJob->job = NVM_IMMEDIATEWRITEFSM_WRITEERROR;
}
break;
}
case NVM_IMMEDIATEWRITEFSM_FINISH:
{
break;
}
case NVM_IMMEDIATEWRITEFSM_WRITEERROR:
{
break;
}
case NVM_IMMEDIATEWRITEFSM_WAITMANAGE:
{
/* When waiting for the status of the lower level module to be idle, mark the status as requesting the lower level module to write. */
if(NVM_STATUS_IDLE == obj->method->getStatus())
{
obj->runtime->immediateWriteJob->job = NVM_IMMEDIATEWRITEFSM_MAIN;
}
break;
}
default:
{
break;
}
}
}

View File

@ -0,0 +1,78 @@
/*
* 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.
*/
#ifndef _NVM_STATEMACHINE_H_
#define _NVM_STATEMACHINE_H_
/*! \brief Contains public interface to various functions related
* to the NVM (NVRAM Manager) module
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "nvm_types.h"
/*! \addtogroup NVRAM Manager
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
void Nvm_StateMachine_Idle(const NvmType *obj);
void Nvm_StateMachine_Read_Entry(const NvmType *obj);
void Nvm_StateMachine_Read(const NvmType *obj);
void Nvm_StateMachine_Write_Entry(const NvmType *obj);
void Nvm_StateMachine_Write(const NvmType *obj);
void Nvm_StateMachine_ReadAll_Entry(const NvmType *obj);
void Nvm_StateMachine_ReadAll(const NvmType *obj);
void Nvm_StateMachine_WriteAll_Entry(const NvmType *obj);
void Nvm_StateMachine_WriteAll(const NvmType *obj);
void Nvm_StateMachine_EraseAll_Entry(const NvmType *obj);
void Nvm_StateMachine_EraseAll(const NvmType *obj);
void Nvm_StateMachine_Erase_Entry(const NvmType *obj);
void Nvm_StateMachine_Erase(const NvmType *obj);
void Nvm_ReadNotification(const NvmType *obj, NVM_NotificationType notificationNumber);
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _NVM_STATEMACHINE_H_ */

View File

@ -0,0 +1,419 @@
/*
* 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.
*/
#ifndef _NVM_TYPES_H_
#define _NVM_TYPES_H_
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdio.h>
#include "nvm_extra.h"
/*! \addtogroup NVRAM Manager
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
struct _NvmType_;
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief The return value type of the public method of the nvm module.
*/
typedef enum
{
NVM_RETURN_OK = 0X00,
NVM_RETURN_NOT_OK = 0X01,
} Nvm_ReturnType;
/*! \brief Define block types.
*/
typedef enum
{
NVM_BLOCK_NORMAL = 0x00,
NVM_BLOCK_REDUNDANT = 0x01,
NVM_BLOCK_DATASET = 0x02,
} Nvm_BlockOpType;
/*! \brief Used to define whether crc is required in a block.
*/
typedef enum
{
NVM_CRC_NONE = 0x00,
NVM_CRC8 = 0x01,
} Nvm_BlockCrcType;
/*! \brief Define the type of block state.
*/
typedef enum
{
NVM_REQ_UNINT = 0X00,
NVM_REQ_PENDING = 0X01,
NVM_REQ_ERASE = 0x02,
NVM_REQ_NOT_OK = 0x03,
NVM_REQ_INTEGRITY_FAILED = 0x04,
NVM_REQ_OK = 0x05,
NVM_REQ_ERROR = 0xFF,
} Nvm_BlockState;
/*! \brief Define the type of NVM module state.
*/
typedef enum
{
NVM_STATE_UNINIT = 0x00,
NVM_STATE_IDLE = 0x01,
NVM_STATE_READ = 0x02,
NVM_STATE_WRITE = 0x03,
NVM_STATE_READALL = 0x04,
NVM_STATE_WRITEALL = 0x05,
NVM_STATE_ERASE = 0x06,
NVM_STATE_ERASEALL = 0x07,
FEE_STATE_INVALID = 0x08,
} Nvm_stateType;
/*! \brief Define the type of queue member status markers.
*/
typedef enum
{
NVM_QUEUEMEMBERSTATE_UNUSED = 0x01,
NVM_QUEUEMEMBERSTATE_USED = 0x02,
NVM_QUEUEMEMBERSTATE_LOCK = 0x03,
} Nvm_QueueMemberStateType;
/*! \brief Define the type of state for NVM erase tasks.
*/
typedef enum
{
NVM_ERASEFSM_INIT = 0x01,
NVM_ERASEFSM_IMMEDIATE = 0x02,
NVM_ERASEFSM_REDUNDANT_MAIN = 0X03,
NVM_ERASEFSM_REDUNDANT_BACKUP = 0X04,
NVM_ERASEFSM_READBACK = 0x05,
NVM_ERASEFSM_CHECK = 0x06,
NVM_ERASEFSM_FINISH = 0x07,
NVM_ERASEFSM_ERASEERROR = 0x08,
NVM_ERASEFSM_ERROR = 0xFF,
} NVM_EraseFsmType;
/*! \brief Define the type of state that NVM writes to the job.
*/
typedef enum
{
NVM_WRITEFSM_INIT = 0x01,
NVM_WRITEFSM_IMMEDIATE = 0x02,
NVM_WRITEFSM_READBACK = 0x03,
NVM_WRITEFSM_CHECK = 0x04,
NVM_WRITEFSM_NORMAL = 0x05,
NVM_WRITEFSM_REDUNDANT_MAIN = 0x06,
NVM_WRITEFSM_REDUNDANT_BACKUP = 0X07,
NVM_WRITEFSM_FINISH = 0x08,
NVM_WRITEFSM_WRITEERROR = 0x09,
NVM_WRITEFSM_ERROR = 0xFF,
} NVM_WriteFsmType;
/*! \brief Define the type of NVM immediate read job status.
*/
typedef enum
{
NVM_IMMEDIATEREADFSM_MAIN = 0x01,
NVM_IMMEDIATEREADFSM_MAIN_RETRY = 0x02,
NVM_IMMEDIATEREADFSM_WMF = 0x03,
NVM_IMMEDIATEREADFSM_FINISH = 0x04,
NVM_IMMEDIATEREADFSM_READERROR = 0x05,
NVM_IMMEDIATEREADFSM_ERROR = 0xFF,
} NVM_ImmediateReadFsmType;
/*! \brief Define the type of state where NVM immediately writes jobs.
*/
typedef enum
{
NVM_IMMEDIATEWRITEFSM_MAIN = 0x01,
NVM_IMMEDIATEWRITEFSM_RETRY = 0x02,
NVM_IMMEDIATEWRITEFSM_WMF = 0x03,
NVM_IMMEDIATEWRITEFSM_FINISH = 0x04,
NVM_IMMEDIATEWRITEFSM_WRITEERROR = 0x05,
NVM_IMMEDIATEWRITEFSM_WAITMANAGE = 0X06,
NVM_IMMEDIATEWRITEFSM_ERROR = 0xFF,
} NVM_ImmediateWriteFsmType;
/*! \brief Define the type of state for nvm readAll job.
*/
typedef enum
{
NVM_READALLFSM_READBLOCK = 0x01,
NVM_READALLFSM_READENTRY = 0x02,
NVM_READALLFSM_READ = 0x03,
NVM_READALLFSM_CHECK = 0x04,
NVM_READALLFSM_FINISH = 0x05,
NVM_READALLFSM_ERROR = 0xFF,
} NVM_ReadAllFsmType;
/*! \brief Define the type of state for nvm writeAll job.
*/
typedef enum
{
NVM_WRITEALLFSM_WRITEBLOCK = 0x01,
NVM_WRITEALLFSM_WRITEENTRY = 0x02,
NVM_WRITEALLFSM_WRITE = 0x03,
NVM_WRITEALLFSM_FINISH = 0x04,
NVM_WRITEALLFSM_ERROR = 0xFF,
} NVM_WriteAllFsmType;
/*! \brief Define the type of state for nvm eraseAll job.
*/
typedef enum
{
NVM_ERASEALLFSM_ERASEBLOCK = 0x01,
NVM_ERASEALLFSM_ERASEENTRY = 0x02,
NVM_ERASEALLFSM_ERASE = 0x03,
NVM_ERASEALLFSM_READBACK = 0x04,
NVM_ERASEALLFSM_FINISH = 0x05,
NVM_ERASEALLFSM_ERROR = 0xFF,
} NVM_EraseAllFsmType;
/*! \brief Define the type of block management data.
*/
typedef struct _Nvm_BlockInfoType_
{
Nvm_BlockState state;
Nvm_BlockState internalState;
uint8_t integrity;
} Nvm_BlockInfoType;
/*! \brief Define the type of block buff.
*/
typedef struct _Nvm_BlockBuffType_
{
const uint8_t* const romBuffPtr;
uint8_t* const ramBuffPtr;
} Nvm_BlockBuffType;
/*! \brief Define the type of state function.
*/
typedef void (*Nvm_StateMachine_Fun_Type)(const struct _NvmType_ *obj);
/*! \brief Define the types of queue members.
*/
typedef struct _Nvm_QueueMemberType_
{
uint16_t blockIdx;
uint8_t* databuff;
uint16_t datasetIdx;
Nvm_stateType op;
uint8_t priority;
Nvm_QueueMemberStateType state;
} Nvm_QueueMemberType;
/*! \brief Define the type of queue.
*/
typedef struct _Nvm_QueueType_
{
uint16_t index;
const uint8_t memberNum;
struct _Nvm_QueueMemberType_* const members;
} Nvm_QueueType;
/*! \brief Define the type of description block.
*/
typedef struct _Nvm_BlockItemType_
{
uint16_t number;
uint16_t dataSize;
Nvm_BlockOpType type;
uint8_t datasetNum;
bool immediate;
Nvm_BlockCrcType crc;
uint8_t priority;
const struct _Nvm_BlockBuffType_* buff;
struct _Nvm_BlockInfoType_* const info;
uint8_t* const tempRamBuffPtr;
} Nvm_BlockItemType;
/*! \brief Define the type of blocks.
*/
typedef struct _Nvm_BlockType_
{
uint16_t itemsNum;
const struct _Nvm_BlockItemType_* items;
} Nvm_BlockType;
/*! \brief Define the type of state machine.
*/
typedef struct _Nvm_StateMachineType_
{
Nvm_StateMachine_Fun_Type onEntry;
Nvm_StateMachine_Fun_Type fn;
} Nvm_StateMachineType;
/*! \brief Define the type of erase job.
*/
typedef struct _Nvm_EraseJobType_
{
NVM_EraseFsmType job;
NVM_NotificationType result;
uint16_t blockIdx;
uint16_t blockNumber;
uint8_t datasetIdx;
bool blockBackUp;
uint8_t* blockDatabuff;
uint8_t* userBuff;
uint32_t useSize;
} Nvm_EraseJobType;
/*! \brief Define the type of write job.
*/
typedef struct _Nvm_WriteJobType_
{
NVM_WriteFsmType job;
NVM_NotificationType result;
uint16_t blockIdx;
uint16_t blockNumber;
uint8_t datasetIdx;
bool blockBackUp;
uint8_t* blockDatabuff;
uint8_t* userBuff;
uint32_t useSize;
} Nvm_WriteJobType;
/*! \brief Define the type of read job.
*/
typedef struct _Nvm_ReadJobType_
{
uint16_t blockIdx;
uint8_t datasetIdx;
uint32_t datasize;
uint8_t* userBuff;
uint8_t* cpyBuff;
} Nvm_ReadJobType;
/*! \brief Define the type of writeAll job.
*/
typedef struct _Nvm_WriteAllJobType_
{
NVM_WriteAllFsmType job;
uint16_t blockIdx;
uint16_t blockNumber;
uint8_t datasetIdx;
bool blockBackUp;
uint8_t* blockDatabuff;
uint32_t blockUseSize;
} Nvm_WriteAllJobType;
/*! \brief Define the type of eraseAll job.
*/
typedef struct _Nvm_EraseAllJobType_
{
NVM_EraseAllFsmType job;
uint16_t blockIdx;
uint16_t blockNumber;
uint8_t datasetIdx;
bool blockBackUp;
uint8_t* blockDatabuff;
uint8_t* blockRombuff;
uint32_t blockUseSize;
} Nvm_EraseAllJobType;
/*! \brief Define the type of readAll job.
*/
typedef struct _Nvm_ReadAllJobType_
{
NVM_ReadAllFsmType job;
uint16_t blockIdx;
uint16_t blockNumber;
uint8_t datasetIdx;
bool blockBackUp;
uint8_t* blockDatabuff;
uint32_t blockUseSize;
} Nvm_ReadAllJobType;
/*! \brief Define the type of immediateWrite job.
*/
typedef struct _Nvm_ImmediateWriteJobType_
{
NVM_ImmediateWriteFsmType job;
NvmNotificationPtrType notificationPtr;
uint16_t blockIdx;
uint16_t blockNumber;
uint8_t datasetIdx;
uint8_t* blockDatabuff;
uint8_t retry;
} Nvm_ImmediateWriteJobType;
/*! \brief Define the type of immediateRead job.
*/
typedef struct _Nvm_ImmediateReadJobType_
{
NVM_ImmediateReadFsmType job;
NvmNotificationPtrType notificationPtr;
uint16_t blockIdx;
uint16_t blockNumber;
uint8_t datasetIdx;
uint8_t* blockDatabuff;
uint32_t blockUseSize;
uint8_t mainRetryCnt;
uint8_t backupRetryCnt;
} Nvm_ImmediateReadJobType;
/*! \brief Define the type of NVM module runtime.
*/
typedef struct _Nvm_RunTimeType_
{
Nvm_stateType state;
Nvm_stateType nextState;
struct _Nvm_QueueType_* queue;
struct _Nvm_EraseJobType_* eraseJob;
struct _Nvm_ReadJobType_* readJob;
struct _Nvm_WriteJobType_* writeJob;
struct _Nvm_ReadAllJobType_* readAllJob;
struct _Nvm_WriteAllJobType_* writeAllJob;
struct _Nvm_EraseAllJobType_* eraseAllJob;
struct _Nvm_ImmediateReadJobType_* immediateReadJob;
struct _Nvm_ImmediateWriteJobType_* immediateWriteJob;
} Nvm_RunTimeType;
/*! \brief Define the type of nvm.
*/
typedef struct _NvmType_
{
const struct _Nvm_BlockType_* blockTable;
const struct _Nvm_StateMachineType_* stateMachine;
const struct _Nvm_MethodType_* method;
struct _Nvm_RunTimeType_* runtime;
} NvmType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _NVM_TYPES_H_ */

View File

@ -0,0 +1,84 @@
/*
* 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.
*/
#ifndef _NVM_VERSION_H_
#define _NVM_VERSION_H_
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdio.h>
/*! \addtogroup NVRAM Manager
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*! \brief Macro for the major version number of the software of the nvm module.
*/
#if(defined NVM_SW_MAJOR_VERSION)
#error NVM_SW_MAJOR_VERSION already defined
#endif
#define NVM_SW_MAJOR_VERSION (1U)
/*! \brief Macro for the software version number of the nvm module.
*/
#if(defined NVM_SW_MINOR_VERSION)
#error NVM_SW_MINOR_VERSION already defined
#endif
#define NVM_SW_MINOR_VERSION (0U)
/*! \brief Macro for the software patch version number of the nvm module.
*/
#if(defined NVM_SW_PATCH_VERSION)
#error NVM_SW_PATCH_VERSION already defined
#endif
#define NVM_SW_PATCH_VERSION (0U)
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Type of software version number of the nvm module.
*/
typedef struct _Nvm_VersionInfoType_
{
uint8_t sw_major_version;
uint8_t sw_minor_version;
uint8_t sw_patch_version;
} Nvm_VersionInfoType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _NVM_VERSION_H_ */

View File

@ -0,0 +1,147 @@
/*
* 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.
*/
#ifndef _STIMER_H_
#define _STIMER_H_
/*! \brief Contains public interface to various functions related
* to the Software Timer (STIMER) object.
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Declaration of STIMER object
*/
typedef struct _StimerType_
{
uint32_t counter; /*!< The counter register */
uint32_t period; /*!< The period, time out will occur when count reach period */
bool enable; /*!< Whether the timer is started */
bool overflow; /*!< Whether the timer is overflow */
} StimerType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief The constructor of the timer object
*
* This function initialize the Stimer object
*
* \param[in] obj : pointer to Stimer instance
*/
static inline void Stimer_Init(StimerType *obj)
{
obj->counter = 0;
obj->period = 0;
obj->enable = false;
obj->overflow = false;
}
/*! \brief Start the timer for the period, this is one shot
*
* This function start the timer. This is one-shot.
*
* \note The real time is based on the time base running Ticker()
* \note Call this function if already started will restart the timer
*
* \param[in] obj : pointer to Stimer instance
* \param[in] period : the period value
*/
static inline void Stimer_Start(StimerType *obj, uint32_t period)
{
obj->counter = 0;
obj->period = period;
obj->enable = true;
obj->overflow = false;
}
/*! \brief The time base of the timer object
*
* This function provide the real time base of the stimer instance.
*
* \param[in] obj : pointer to Stimer instance
*/
static inline void Stimer_Tick(StimerType *obj)
{
if(obj->enable && obj->overflow == false)
{
if(obj->counter < obj->period)
{
obj->counter++;
if(obj->counter == obj->period)
{
obj->overflow = true;
}
}
}
}
/*! \brief Whether timeout
*
* This function returns whether it's timeout
*
* \param[in] obj : pointer to Stimer instance
* \return Whether it's timeout
* - true : the timer is time-out
* - false : the timer is not time-out
*/
static inline bool Stimer_Timeout(const StimerType *obj)
{
return obj->overflow;
}
/*! \brief Whether it's started
*
* This function returns whether the Timer instance is started
*
* \param[in] obj : pointer to Stimer instance
* \return Whether it's started
* - true : the timer is started
* - false : the timer is not started
*/
static inline bool Stimer_IsActive(StimerType *obj)
{
return obj->enable;
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _STIMER_H_ */

View File

@ -0,0 +1,132 @@
/*
* 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 "uds.h"
/*******************************************************************************
* the defines
******************************************************************************/
#define UDS_GET_SUB_FUNCTION_SUPPRESS_POSRSP(byte) (((byte) >> 7u)&0x01u)
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
static bool Uds_IsSidValid(UdsType *obj, uint8_t sid)
{
uint16_t i=0;
for(i=0; i<obj->serviceNum; ++i)
{
if(obj->seviceTable[i].sid == sid)
{
return true;
}
}
return false;
}
void Uds_Init(UdsType *obj, const Uds_ParamsType *pParams)
{
IsoTp_Init(&obj->isotp, &pParams->isotpParams);
obj->session = 0x01; /* Default session */
obj->securityLevel = 0; /* None security level */
obj->suppressPosRsp = false;
obj->timeStamp_ms = 0;
obj->p2Server_ms = pParams->p2Server_ms;
obj->p2xServer_10ms = pParams->p2xServer_10ms;
obj->s3Server_ms = pParams->s3Server_ms;
Stimer_Init(&obj->p2ServerTimer);
Stimer_Init(&obj->p2xServerTimer);
Stimer_Init(&obj->s3ServerTimer);
uint32_t i=0;
for(i=0; i<UDS_MAX_PAYLOAD_SIZE; ++i)
{
obj->payload[i] = 0;
}
}
void Uds_Run(UdsType *obj)
{
uint16_t outSize = 0;
int8_t result = 0;
uint8_t sid = 0;
uint32_t i=0;
IsoTp_Poll(&obj->isotp);
result = IsoTp_Receive(&obj->isotp, &obj->isFuncAddr, obj->payload, UDS_MAX_PAYLOAD_SIZE, &outSize);
if (ISOTP_RET_OK == result)
{
/* Handle received message */
sid = obj->payload[0];
if(Uds_IsSidValid(obj, sid))
{
for(i=0; i<obj->serviceNum; ++i)
{
if(obj->seviceTable[i].sid == sid)
{
if(obj->seviceTable[i].subFuncOwner)
{
obj->suppressPosRsp = UDS_GET_SUB_FUNCTION_SUPPRESS_POSRSP(obj->payload[1]);
}
else
{
obj->suppressPosRsp = 0;
}
obj->curServiceIdx = i;
obj->seviceTable[i].service(obj, obj->payload, outSize);
break;
}
}
}
else
{
Uds_NegativeResponse(obj, sid, NRC_SERVICE_NOT_SUPPORTED);
}
}
if(true == Stimer_Timeout(&obj->s3ServerTimer))
{
obj->session = 0x01; /* Default session */
obj->securityLevel = 0; /* None security level */
Stimer_Init(&obj->s3ServerTimer);
}
}

View File

@ -0,0 +1,253 @@
/*
* 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.
*/
#ifndef _UDS_H_
#define _UDS_H_
/*! \brief Contains public interface to various functions related
* to the Unified Diagnostic Services (UDS) following ISO 14229
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <stddef.h>
#include "stimer.h"
#include "isotp.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
#define NRC_GENERAL_REJECT (0x10)
#define NRC_SERVICE_NOT_SUPPORTED (0x11)
#define NRC_SUBFUNCTION_NOT_SUPPORTED (0x12)
#define NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT (0x13)
#define NRC_RESPONSE_TOO_LONG (0x14)
#define NRC_CONDITIONS_NOT_CORRECT (0x22)
#define NRC_REQUEST_SEQUENCE_ERROR (0x24)
#define NRC_REQUEST_OUT_OF_RANGE (0x31)
#define NRC_SECURITY_ACCESS_DENIED (0x33)
#define NRC_INVALID_KEY (0x35)
#define NRC_EXCEEDED_NUMBER_OF_ATTEMPTS (0x36)
#define NRC_REQUIRED_TIME_DELAY_NOT_EXPIRED (0x37)
#define NRC_UPLOAD_DOWNNLOAD_NOT_ACCEPTED (0x70)
#define NRC_TRANSFER_DATA_SUSPENDED (0x71)
#define NRC_GENERAL_PROGRAMMING_FAILURE (0x72)
#define NRC_WRONG_BLOCK_SEQUENCE_COUNTER (0x73)
#define NRC_SERVICE_BUSY (0x78)
#define NRC_SUBFUNC_NOT_SUPPORTED_IN_ACTIVE_SESSION (0x7E)
#define NRC_SERVICE_NOT_SUPPORTED_IN_ACTIVE_SESSION (0x7F)
#define POSITIVE_RSP (0x40)
#define NEGATIVE_RSP (0x7F)
#define UDS_GET_POSITIVE_RSP(sid) (POSITIVE_RSP + sid)
#define UDS_MAX_PAYLOAD_SIZE (4096)
#define UDS_SA_NONE (0)
#define UDS_SA_LEVEL_1 (0x01)
#define UDS_SA_LEVEL_3 (0x03)
#define UDS_SA_LEVEL_11 (0x11)
#define UDS_SA_LEVEL_63 (0x63)
#define UDS_SESSION_DEFAULT (0x01)
#define UDS_SESSION_PROGRAMMING (0x02)
#define UDS_SESSION_EXTENDED (0x03)
#define UDS_SESSION_SAFTY (0x04)
#define UDS_SESSION_SUPPLIER (0x60)
#define UDS_SERVICE_NUM (15)
#define UDS_SA_LEVEL_NUM (3)
#define UDS_GET_SUB_FUNCTION(byte) ((byte)&0x7fu)
#define BYTES_OF(x) (sizeof(x) / sizeof(uint8_t))
#define UDS_RSP_LEN_MAX (512)
/* DID type */
#define UDS_VAR_TYPE_NONVOL_STORAGE (1 << 0) /* set if non-volatile data */
#define UDS_VAR_TYPE_MAY_READ (1 << 1) /* set if readable */
#define UDS_VAR_TYPE_MAY_WRITE (1 << 2) /* set if writable */
#define UDS_DID_TYPE_RAM_RW (UDS_VAR_TYPE_MAY_READ | UDS_VAR_TYPE_MAY_WRITE)
#define UDS_DID_TYPE_NVM_RW (UDS_VAR_TYPE_NONVOL_STORAGE | UDS_VAR_TYPE_MAY_READ | UDS_VAR_TYPE_MAY_WRITE)
#define UDS_DID_TYPE_NVM_WO (UDS_VAR_TYPE_NONVOL_STORAGE | UDS_VAR_TYPE_MAY_WRITE)
#define UDS_DID_TYPE_NVM_RO (UDS_VAR_TYPE_NONVOL_STORAGE | UDS_VAR_TYPE_MAY_READ)
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Forward declaration of UDS object
*/
struct _UdsType_;
typedef struct _UdsType_ UdsType;
/*! \brief The Data-by-ID definition of UDS
*/
typedef struct _Uds_DidType_
{
uint16_t did;
uint8_t type;
uint8_t sessionLevel;
uint8_t securityLevel;
uint8_t *pBytes;
uint16_t length;
void (*function)(UdsType *obj,uint8_t dataBuf[], uint8_t dataLen);
} Uds_DidType;
/*! \brief The definition of UDS DID table
*/
typedef Uds_DidType *Uds_DidTable;
/*! \brief UDS service definition
*/
typedef struct _Uds_ServiceType_
{
uint8_t sid;
uint8_t minLen;
bool subFuncOwner;
void (*service)(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen);
} Uds_ServiceType;
/*! \brief The definition of UDS service table
*/
typedef const Uds_ServiceType *Uds_ServiceTable;
/*! \brief The definition of UDS security table
* \note The table should be like table[SID number][security level number]
*/
typedef const bool *Uds_SecurityTableType;
/*! \brief The definition of UDS initialization parameters
*/
typedef struct _Uds_ParamsType_
{
IsoTp_Params isotpParams;
uint16_t p2Server_ms;
uint16_t p2xServer_10ms;
uint16_t s3Server_ms;
} Uds_ParamsType;
/*! \brief The UDS prototype definition
*/
struct _UdsType_
{
bool active;
uint8_t session;
uint8_t securityLevel;
uint32_t serviceNum;
Uds_ServiceTable seviceTable;
Uds_SecurityTableType securityTable;
Uds_DidTable didTable;
uint16_t didNum;
IsoTpType isotp;
bool suppressPosRsp;
bool isFuncAddr;
uint8_t curServiceIdx;
uint8_t payload[UDS_MAX_PAYLOAD_SIZE];
int64_t timeStamp_ms;
uint16_t p2Server_ms;
uint16_t p2xServer_10ms;
uint16_t s3Server_ms;
StimerType p2ServerTimer;
StimerType p2xServerTimer;
StimerType s3ServerTimer;
};
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initializes the UDS object.
*/
extern void Uds_Init(UdsType *obj, const Uds_ParamsType *pParams);
/*! \brief The main service of UDS object.
* \note Suggest run every 1ms
*/
extern void Uds_Run(UdsType *obj);
/*! \brief This function gives a positive response
*/
static inline void Uds_PositiveResponse(UdsType *obj, const uint8_t data[], uint16_t len)
{
Stimer_Start(&obj->s3ServerTimer, obj->s3Server_ms);
if(obj->suppressPosRsp == true)
{
return;
}
IsoTp_Send(&obj->isotp, data, len);
return;
}
/*! \brief This function gives a nagative response
*/
static inline void Uds_NegativeResponse(UdsType *obj, uint8_t sid, uint8_t rsp_nrc)
{
uint8_t temp_buf[8] = {0};
if(rsp_nrc != NRC_SERVICE_BUSY)
{
Stimer_Start(&obj->s3ServerTimer, obj->s3Server_ms);
}
if(obj->isFuncAddr && (rsp_nrc == NRC_SERVICE_NOT_SUPPORTED || rsp_nrc == NRC_SUBFUNCTION_NOT_SUPPORTED || rsp_nrc == NRC_REQUEST_OUT_OF_RANGE || rsp_nrc == NRC_SUBFUNC_NOT_SUPPORTED_IN_ACTIVE_SESSION || rsp_nrc == NRC_SERVICE_NOT_SUPPORTED_IN_ACTIVE_SESSION))
{
return;
}
temp_buf[0] = NEGATIVE_RSP;
temp_buf[1] = sid;
temp_buf[2] = rsp_nrc;
IsoTp_Send(&obj->isotp, temp_buf, 3);
}
/*! \brief This function provide the time base for the UDS process
*/
static inline void Uds_Tick(UdsType *obj)
{
obj->timeStamp_ms++;
Stimer_Tick(&obj->p2ServerTimer);
Stimer_Tick(&obj->p2xServerTimer);
Stimer_Tick(&obj->s3ServerTimer);
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_H_ */

View File

@ -0,0 +1,221 @@
/*
* 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 "uds_dtc.h"
/*******************************************************************************
* the defines
******************************************************************************/
#define DTCG_EMISSION_START (0x00000000ul) /* 24Bit DTC define ISO-15031-6 DTC + ISO-15031-6 Failure Type, ISO14229-1 format */
#define DTCG_EMISSION_END (0x000FFFFFul)
#define DTCG_POWERTRAIN_START (0x00100000ul)
#define DTCG_POWERTRAIN_END (0x003FFFFFul)
#define DTCG_CHASSIS_START (0x00400000ul)
#define DTCG_CHASSIS_END (0x007FFFFFul)
#define DTCG_BODY_START (0x00800000ul)
#define DTCG_BODY_END (0x00BFFFFFul)
#define DTCG_NETWORK_START (0x00C00000ul)
#define DTCG_NETWORK_END (0x00FFFFFFul)
#define FAULTDT_MAX (127) /* refers to ISO14229-1 D.6 */
#define FAULTDT_MIN (-128) /* refers to ISO14229-1 D.6 */
#define AGING_MAX (40) /* refers to ISO14229-1 D.7 */
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/* the meaning of UDS DTC value refers to ISO 15031-6 */
static Uds_DtcType udsDtcTable[DTC_MAX_COUNT] = {
{0x04621A, 0x50, 0x00, 0x00}, /* P0462 fuel level sensor "A" circuit resistance low */
{0x04631B, 0x50, 0x00, 0x00}, /* P0463 fuel level sensor "A" circuit resistance high */
{0xF00316, 0x50, 0x00, 0x00}, /* U3003 battery voltage low */
{0xF00317, 0x50, 0x00, 0x00}, /* U3003 battery voltage high */
{0xC07388, 0x50, 0x00, 0x00}, /* U0073 control module communication bus off */
{0xC10001, 0x50, 0x00, 0x00}, /* U0100 lost communication with ECM/PCM "A" */
{0xC10101, 0x50, 0x00, 0x00}, /* U0101 lost communication with TCM */
{0xC12101, 0x50, 0x00, 0x00}, /* U0121 lost communication with ABS control module */
{0xC12701, 0x50, 0x00, 0x00}, /* U0127 lost communication with tire pressure monitor module */
{0xC12801, 0x50, 0x00, 0x00}, /* U0128 lost communication with park brake control module */
{0xC12901, 0x50, 0x00, 0x00}, /* U0129 lost communication with brake system control module */
{0xC13101, 0x50, 0x00, 0x00}, /* U0131 lost communication with power sterring control module */
{0xC14100, 0x50, 0x00, 0x00}, /* U0141 lost communication with body control module "A" */
{0xC15101, 0x50, 0x00, 0x00}, /* U0151 lost communication with restraints control module */
{0xC16300, 0x50, 0x00, 0x00}, /* U0163 lost communication with navigation control module */
{0xC16900, 0x50, 0x00, 0x00}, /* U0169 lost communication with sunroof control module */
{0xC18101, 0x50, 0x00, 0x00}, /* U0181 lost communication with headlamp leveling control module */
{0xC23601, 0x50, 0x00, 0x00}, /* U0236 lost communication with column lock module */
{0xC16400, 0x50, 0x00, 0x00}, /* U0164 lost communication with HVAC control module */
{0xC16700, 0x50, 0x00, 0x00}, /* U0167 lost communication with vehicle immobilizer control module */
};
static bool dtcOffCtrl = false;
/*******************************************************************************
* the constants
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void Uds_SetDtcOffCtrl(bool val)
{
dtcOffCtrl = val;
}
bool Uds_GetDtcOffCtrlState(void)
{
return dtcOffCtrl;
}
void Uds_ClearDtcByDtcIndex(uint16_t dtcIndex)
{
if(dtcIndex >= DTC_MAX_COUNT)
{
return;
}
udsDtcTable[dtcIndex].dtcStatus.all = 0;
udsDtcTable[dtcIndex].dtcStatus.bit.testNcmpSlc = 1;
udsDtcTable[dtcIndex].dtcStatus.bit.testNcmpToc = 1;
udsDtcTable[dtcIndex].faultDtCnt = 0;
udsDtcTable[dtcIndex].AgingCnt = 0;
}
void Uds_LoadDtc(void)
{
/* code implemented by the user */
}
void Uds_SaveDtc(void)
{
/* code implemented by the user */
}
uint16_t Uds_GetDtcNumberByStatusMask(uint8_t mask)
{
uint16_t dtcCnt = 0;
uint8_t dtcState = 0;
uint16_t dtcNum = 0;
for(dtcCnt = 0; dtcCnt < DTC_MAX_COUNT; dtcCnt++)
{
dtcState = (udsDtcTable[dtcCnt].dtcStatus.all & DTC_AVAILABILITY_STATUS_MASK);
if(0 != (dtcState & mask))
{
dtcNum++;
}
}
return dtcNum;
}
uint16_t Uds_GetDtcByStatusMask(uint8_t *pDtcBuf, uint16_t bufLen, uint8_t mask)
{
uint16_t dtcCnt = 0;
uint8_t dtcState = 0;
uint16_t dtcDlc = 0;
for(dtcCnt = 0; dtcCnt < DTC_MAX_COUNT; dtcCnt++)
{
dtcState = udsDtcTable[dtcCnt].dtcStatus.all;
if(0 != (dtcState & mask))
{
if((dtcDlc + 4) <= bufLen)
{
pDtcBuf[dtcDlc++] = (uint8_t)(udsDtcTable[dtcCnt].dtcCode >> 16);
pDtcBuf[dtcDlc++] = (uint8_t)(udsDtcTable[dtcCnt].dtcCode >> 8);
pDtcBuf[dtcDlc++] = (uint8_t)(udsDtcTable[dtcCnt].dtcCode >> 0);
pDtcBuf[dtcDlc++] = (dtcState & DTC_AVAILABILITY_STATUS_MASK);
}
else
{
break;
}
}
}
return dtcDlc;
}
uint16_t Uds_GetSupportedDtc(uint8_t *pDtcBuf, uint16_t bufLen)
{
uint16_t dtcCnt = 0;
uint8_t dtcState = 0;
uint16_t dtcDlc = 0;
for(dtcCnt = 0; dtcCnt < DTC_MAX_COUNT; dtcCnt++)
{
dtcState = udsDtcTable[dtcCnt].dtcStatus.all;
if((dtcDlc + 4) <= bufLen)
{
pDtcBuf[dtcDlc++] = (uint8_t)(udsDtcTable[dtcCnt].dtcCode >> 16);
pDtcBuf[dtcDlc++] = (uint8_t)(udsDtcTable[dtcCnt].dtcCode >> 8);
pDtcBuf[dtcDlc++] = (uint8_t)(udsDtcTable[dtcCnt].dtcCode >> 0);
pDtcBuf[dtcDlc++] = (dtcState & DTC_AVAILABILITY_STATUS_MASK);
}
else
{
break;
}
}
return dtcDlc;
}
void Uds_ClearDtcByGroup(uint32_t group)
{
uint16_t dtcCnt = 0;
switch(group)
{
case EMISSION_SYSTEM_GROUP:
for(dtcCnt = 0; dtcCnt < DTC_MAX_COUNT; dtcCnt++)
{
if(udsDtcTable[dtcCnt].dtcCode <= DTCG_EMISSION_END)
{
Uds_ClearDtcByDtcIndex(dtcCnt);
}
}
break;
case SAFETY_SYSTEM_GROUP:
for(dtcCnt = 0; dtcCnt < DTC_MAX_COUNT; dtcCnt++)
{
if((udsDtcTable[dtcCnt].dtcCode >= DTCG_CHASSIS_START) && (udsDtcTable[dtcCnt].dtcCode <= DTCG_CHASSIS_END))
{
Uds_ClearDtcByDtcIndex(dtcCnt);
}
}
break;
case ALL_FUNC_SYSTEM_GROUP:
for(dtcCnt = 0; dtcCnt < DTC_MAX_COUNT; dtcCnt++)
{
Uds_ClearDtcByDtcIndex(dtcCnt);
}
break;
}
}

View File

@ -0,0 +1,175 @@
/*
* 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.
*/
#ifndef _UDS_DTC_H_
#define _UDS_DTC_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS application
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
#define EMISSION_SYSTEM_GROUP (0x00FFFF33)
#define SAFETY_SYSTEM_GROUP (0x00FFFFD0)
#define ALL_FUNC_SYSTEM_GROUP (0x00FFFFFF)
#define REPORT_DTC_NUMBER_BY_STATUS_MASK (0x01)
#define REPORT_DTC_BY_STATUS_MASK (0x02)
#define REPORT_DTC_SNOPSHOT_IDENTIFICATION (0x03)
#define REPORT_DTC_SNOPSHOT_RECORD_BY_DTC_NUMBER (0x04)
#define REPORT_DTC_STORE_DATA_BY_RECORD_NUMBER (0x05)
#define REPORT_DTC_EXT_DATA_RECORD_BY_DTC_NUMBER (0x06)
#define REPORT_DTC_NUMBER_BY_SEVERITY_MASK_RECORD (0x07)
#define REPORT_DTC_BY_SEVERITY_MASK_RECORD (0x08)
#define REPORT_SUPPORTED_DTC (0x0a)
#define DTC_FORMAT_15031 (0x00)
#define DTC_FORMAT_14229 (0x01)
#define DTC_FORMAT_J1939 (0x02)
#define DTC_FORMAT_11992 (0x03)
#define DTC_AVAILABILITY_STATUS_MASK (0x7F)
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief The DTC Index name of UDS supported
*/
typedef enum _Uds_DtcIndexNameType_
{
DTC_FUEL_SENSOR_BELOW = 0,
DTC_FUEL_SENSOR_ABOVE,
DTC_BATT_VOLTAG_BELOW,
DTC_BATT_VOLTAG_ABOVE,
DTC_CAN_BUS_OFF,
DTC_COM_LOST_EMS,
DTC_COM_LOST_TCU,
DTC_COM_LOST_ABS,
DTC_COM_LOST_TPMS,
DTC_COM_LOST_EPB,
DTC_COM_LOST_ESP,
DTC_COM_LOST_EPS,
DTC_COM_LOST_BCM,
DTC_COM_LOST_SRS,
DTC_COM_LOST_DVD,
DTC_COM_LOST_PDC,
DTC_COM_LOST_ALS,
DTC_COM_LOST_PEPS,
DTC_COM_LOST_AC,
DTC_COM_LOST_AVM,
DTC_MAX_COUNT
} Uds_DtcIndexNameType;
/*! \brief The DTC status definition refers to ISO14229-1 D.2.4
* \note Bit 0, testFailed, clear by test pass or ClearDiagnosticInformation
* Bit 1, testFailedThisOperationCycle, clear by new OC or ClearDiagnosticInformation
* Bit 2, latch, pendingDTC, clear by fault never happened in cur OC or ClearDiagnosticInformation, if test not completed, must hold.
* Bit 3, latch, confirmedDTC, clear by ClearDiagnosticInformation, one(only by normal fault) or 40 OC not detect any fault.
* Bit 4, latch, testNotCompletedSinceLastClear, set by a new OC start or ClearDiagnosticInformation
* Bit 5, latch, testFailedSinceLastClear, clear by ClearDiagnosticInformation
* Bit 6, testNotCompletedThisOperationCycle
* Bit 7, warningIndicatorRequested(unsupported)
*/
typedef union _Uds_DtcStatusType_
{
uint8_t all;
struct
{
uint8_t testFailed : 1;
uint8_t testFailToc : 1;
uint8_t pending : 1;
uint8_t confirmed : 1;
uint8_t testNcmpSlc : 1;
uint8_t testFailSlc : 1;
uint8_t testNcmpToc : 1;
uint8_t wnIndreq : 1;
} bit;
} Uds_DtcStatusType;
/*! \brief The DTC definition of UDS
*/
typedef struct _Uds_DtcType_
{
uint32_t dtcCode;
Uds_DtcStatusType dtcStatus;
int16_t faultDtCnt; /* refers to ISO14229-1 D.6 */
uint8_t AgingCnt; /* refers to ISO14229-1 D.7 */
} Uds_DtcType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief control DTC status updata stop and start
*/
extern void Uds_SetDtcOffCtrl(bool val);
/*! \brief get control DTC status
*/
extern bool Uds_GetDtcOffCtrlState(void);
/*! \brief clear DTC by dtc index
*/
extern void Uds_ClearDtcByDtcIndex(uint16_t dtcIndex);
/*! \brief load dtc data from EEPROM
*/
extern void Uds_LoadDtc(void);
/*! \brief save dtc data to EEPROM
*/
extern void Uds_SaveDtc(void);
/*! \brief get DTC counter by dtc status mask
*/
extern uint16_t Uds_GetDtcNumberByStatusMask(uint8_t mask);
/*! \brief get DTC data by dtc status mask
*/
extern uint16_t Uds_GetDtcByStatusMask(uint8_t *pDtcBuf, uint16_t bufLen, uint8_t mask);
/*! \brief get all supported DTC data
*/
extern uint16_t Uds_GetSupportedDtc(uint8_t *pDtcBuf, uint16_t bufLen);
/*! \brief clear DTC by dtc group
*/
extern void Uds_ClearDtcByGroup(uint32_t group);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_DTC_H_ */

View File

@ -0,0 +1,90 @@
/*
* 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 "uds_service10.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the constants
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void UdsService10_SessionControl(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen)
{
uint8_t subFunction;
uint8_t rspBuffer[8] = {0}; /* polyspace DEFECT:PARTIALLY_ACCESSED_ARRAY [No action planned:Low] "Still keep default though member6~7 is not written" */
if(msgLen != obj->seviceTable[obj->curServiceIdx].minLen)
{
Uds_NegativeResponse(obj, 0x10, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
subFunction = UDS_GET_SUB_FUNCTION (msgBuf[1]);
rspBuffer[0] = UDS_GET_POSITIVE_RSP(0x10);
rspBuffer[1] = subFunction;
rspBuffer[2] = (uint8_t)(obj->p2Server_ms >> 8);
rspBuffer[3] = (uint8_t)(obj->p2Server_ms & 0x00ff);
rspBuffer[4] = (uint8_t)(obj->p2xServer_10ms >> 8);
rspBuffer[5] = (uint8_t)(obj->p2xServer_10ms & 0x00ff);
switch(subFunction)
{
case UDS_SESSION_DEFAULT:
obj->securityLevel = UDS_SA_NONE;
obj->session = subFunction;
Uds_PositiveResponse(obj, rspBuffer, 6);
break;
case UDS_SESSION_EXTENDED:
obj->securityLevel = UDS_SA_NONE;
obj->session = subFunction;
Uds_PositiveResponse(obj, rspBuffer, 6);
break;
case UDS_SESSION_PROGRAMMING:
obj->securityLevel = UDS_SA_NONE;
obj->session = subFunction;
Uds_PositiveResponse(obj, rspBuffer, 6);
break;
case UDS_SESSION_SAFTY:
obj->securityLevel = UDS_SA_NONE;
obj->session = subFunction;
Uds_PositiveResponse(obj, rspBuffer, 6);
break;
default:
Uds_NegativeResponse(obj, 0x10, NRC_SUBFUNCTION_NOT_SUPPORTED);
break;
}
}

View File

@ -0,0 +1,60 @@
/*
* 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.
*/
#ifndef _UDS_SERVICE10_H_
#define _UDS_SERVICE10_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS service 10
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "../stack/uds.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Uds Service 10 processing
*/
extern void UdsService10_SessionControl(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_SERVICE10_H_ */

View File

@ -0,0 +1,91 @@
/*
* 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 "uds_service11.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief The Reset type definition of Uds
*/
typedef enum _UdsResetType_
{
UDS_RESET_NONE = 0,
UDS_RESET_HARD,
UDS_RESET_KEYOFFON,
UDS_RESET_SOFT
} UdsResetType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the constants
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void UdsService11_ResetEcu(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen)
{
uint8_t subFunction;
uint8_t rspBuffer[8] = {0}; /* polyspace DEFECT:PARTIALLY_ACCESSED_ARRAY [No action planned:Low] "Still keep default though member3~7 is not written" */
uint8_t powerDownTime = 0xFF;
if(msgLen != obj->seviceTable[obj->curServiceIdx].minLen)
{
Uds_NegativeResponse(obj, 0x11, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
subFunction = UDS_GET_SUB_FUNCTION(msgBuf[1]);
rspBuffer[0] = UDS_GET_POSITIVE_RSP(0x11);
rspBuffer[1] = subFunction;
rspBuffer[2] = powerDownTime;
switch(subFunction)
{
case UDS_RESET_HARD:
Uds_PositiveResponse(obj, rspBuffer, 3);
/*add hardware reset code*/
break;
case UDS_RESET_KEYOFFON:
Uds_PositiveResponse(obj, rspBuffer, 3);
/*add keyoffon reset code*/
break;
case UDS_RESET_SOFT:
Uds_PositiveResponse(obj, rspBuffer, 3);
/*add software reset code*/
break;
default:
Uds_NegativeResponse(obj, 0x11, NRC_SUBFUNCTION_NOT_SUPPORTED);
break;
}
}

View File

@ -0,0 +1,59 @@
/*
* 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.
*/
#ifndef _UDS_SERVICE11_H_
#define _UDS_SERVICE11_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS service 11
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "../stack/uds.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Uds Service 11 processing
*/
extern void UdsService11_ResetEcu(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_SERVICE11_H_ */

View File

@ -0,0 +1,76 @@
/*
* 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 "uds_service14.h"
#include "uds_dtc.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the constants
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void UdsService14_ClearDiagInfo(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen)
{
uint32_t dtcGroup = 0;
uint8_t rspBuffer[8] = {0};
if(msgLen != obj->seviceTable[obj->curServiceIdx].minLen)
{
Uds_NegativeResponse(obj, 0x14, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
dtcGroup |= ((uint32_t)msgBuf[1]) << 16;
dtcGroup |= ((uint32_t)msgBuf[2]) << 8;
dtcGroup |= ((uint32_t)msgBuf[3]) << 0;
rspBuffer[0] = UDS_GET_POSITIVE_RSP(0x14);
switch(dtcGroup)
{
case EMISSION_SYSTEM_GROUP:
case SAFETY_SYSTEM_GROUP:
case ALL_FUNC_SYSTEM_GROUP:
Uds_ClearDtcByGroup(dtcGroup);
Uds_PositiveResponse(obj, rspBuffer, 1);
break;
default:
Uds_NegativeResponse(obj, 0x14, NRC_REQUEST_OUT_OF_RANGE);
break;
}
}

View File

@ -0,0 +1,60 @@
/*
* 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.
*/
#ifndef _UDS_SERVICE14_H_
#define _UDS_SERVICE14_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS service 14
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "../stack/uds.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Uds Service 14 processing
*/
extern void UdsService14_ClearDiagInfo(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_SERVICE14_H_ */

View File

@ -0,0 +1,163 @@
/*
* 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 "uds_service19.h"
#include "uds_dtc.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the constants
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void UdsService19_ReadDtcInformation(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen)
{
uint8_t subFunction = 0;
uint8_t dtcStatusMask = 0;
uint16_t dtcCount = 0;
uint16_t dtcDlc = 0;
uint8_t rspBuffer[UDS_RSP_LEN_MAX] = {0};
if(msgLen < obj->seviceTable[obj->curServiceIdx].minLen)
{
Uds_NegativeResponse(obj, 0x19, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
subFunction = UDS_GET_SUB_FUNCTION (msgBuf[1]);
rspBuffer[0] = UDS_GET_POSITIVE_RSP(0x19);
rspBuffer[1] = subFunction;
switch(subFunction)
{
case REPORT_DTC_NUMBER_BY_STATUS_MASK:
if(msgLen != 3)
{
Uds_NegativeResponse(obj, 0x19, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
dtcStatusMask = msgBuf[2];
dtcCount = Uds_GetDtcNumberByStatusMask(dtcStatusMask);
rspBuffer[2] = DTC_AVAILABILITY_STATUS_MASK;
rspBuffer[3] = DTC_FORMAT_14229;
rspBuffer[4] = (dtcCount >> 8) & 0xFF;
rspBuffer[5] = (dtcCount >> 0) & 0xFF;
Uds_PositiveResponse(obj, rspBuffer, 6);
break;
case REPORT_DTC_BY_STATUS_MASK:
if(msgLen != 3)
{
Uds_NegativeResponse(obj, 0x19, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
dtcStatusMask = msgBuf[2];
rspBuffer[2] = DTC_AVAILABILITY_STATUS_MASK;
dtcDlc = Uds_GetDtcByStatusMask(&rspBuffer[3], UDS_RSP_LEN_MAX - 3, dtcStatusMask);
Uds_PositiveResponse(obj, rspBuffer, dtcDlc + 3);
break;
#if 0
case REPORT_DTC_SNOPSHOT_IDENTIFICATION:
if(msgLen != 6)
{
UDS_negativeResponse(obj, 0x19, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
/* add user code */
break;
case REPORT_DTC_SNOPSHOT_RECORD_BY_DTC_NUMBER:
if(msgLen != 6)
{
UDS_negativeResponse(obj, 0x19, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
/* add user code */
break;
case REPORT_DTC_STORE_DATA_BY_RECORD_NUMBER:
if(msgLen != 3)
{
UDS_negativeResponse(obj, 0x19, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
/* add user code */
break;
case REPORT_DTC_EXT_DATA_RECORD_BY_DTC_NUMBER:
if(msgLen != 6)
{
UDS_negativeResponse(obj, 0x19, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
/* add user code */
break;
case REPORT_DTC_NUMBER_BY_SEVERITY_MASK_RECORD:
if(msgLen != 4)
{
UDS_negativeResponse(obj, 0x19, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
/* add user code */
break;
case REPORT_DTC_BY_SEVERITY_MASK_RECORD:
if(msgLen != 4)
{
UDS_negativeResponse(obj, 0x19, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
/* add user code */
break;
#endif
case REPORT_SUPPORTED_DTC:
if(msgLen != 2)
{
Uds_NegativeResponse(obj, 0x19, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
dtcDlc = Uds_GetSupportedDtc(&rspBuffer[3], UDS_RSP_LEN_MAX - 3);
Uds_PositiveResponse(obj, rspBuffer, dtcDlc + 3);
break;
default:
Uds_NegativeResponse(obj, 0x19, NRC_SUBFUNCTION_NOT_SUPPORTED);
break;
}
}

View File

@ -0,0 +1,60 @@
/*
* 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.
*/
#ifndef _UDS_SERVICE19_H_
#define _UDS_SERVICE19_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS service 19
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "../stack/uds.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Uds Service 19 processing
*/
extern void UdsService19_ReadDtcInformation(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_SERVICE19_H_ */

View File

@ -0,0 +1,126 @@
/*
* 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 <string.h>
#include "uds_service22.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the constants
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void UdsService22_ReadDataByIdentifier(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen)
{
uint16_t didNum = 0;
uint16_t didValue = 0;
uint16_t rspLen = 0;
uint16_t msgPos = 0, didIdx = 0;
bool findDid = false;
uint8_t rspBuffer[UDS_RSP_LEN_MAX] = {0};
if(msgLen < obj->seviceTable[obj->curServiceIdx].minLen)
{
Uds_NegativeResponse(obj, 0x22, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
if(0 != (msgLen - 1) % sizeof(uint16_t))
{
Uds_NegativeResponse(obj, 0x22, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
didNum = msgLen / sizeof(uint16_t);
if(0 == didNum)
{
Uds_NegativeResponse(obj, 0x22, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
rspBuffer[rspLen++] = UDS_GET_POSITIVE_RSP(0x22);
for(msgPos = 1; msgPos < msgLen; msgPos += 2)
{
didValue = ((uint16_t)msgBuf[msgPos]) << 8;
didValue |= msgBuf[msgPos + 1];
findDid = false;
for(didIdx = 0; didIdx < obj->didNum; didIdx++)
{
if(obj->didTable[didIdx].did == didValue)
{
if(obj->securityLevel != obj->didTable[didIdx].securityLevel)
{
Uds_NegativeResponse(obj, 0x22, NRC_SECURITY_ACCESS_DENIED);
return;
}
else if((rspLen + 2 + obj->didTable[didIdx].length) > UDS_RSP_LEN_MAX)
{
Uds_NegativeResponse(obj, 0x22, NRC_RESPONSE_TOO_LONG);
return;
}
if((UDS_DID_TYPE_NVM_WO == obj->didTable[didIdx].type) || (obj->session < obj->didTable[didIdx].sessionLevel))
{
Uds_NegativeResponse(obj, 0x22, NRC_CONDITIONS_NOT_CORRECT);
return;
}
obj->didTable[didIdx].function(obj, obj->didTable[didIdx].pBytes, obj->didTable[didIdx].length);
findDid = true;
rspBuffer[rspLen++] = msgBuf[msgPos];
rspBuffer[rspLen++] = msgBuf[msgPos + 1];
memcpy(&rspBuffer[rspLen], obj->didTable[didIdx].pBytes, obj->didTable[didIdx].length);
rspLen += obj->didTable[didIdx].length;
break;
}
}
if(false == findDid)
{
break;
}
}
if(true == findDid)
{
Uds_PositiveResponse(obj, rspBuffer, rspLen);
}
else
{
Uds_NegativeResponse(obj, 0x22, NRC_REQUEST_OUT_OF_RANGE);
}
}

View File

@ -0,0 +1,60 @@
/*
* 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.
*/
#ifndef _UDS_SERVICE22_H_
#define _UDS_SERVICE22_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS service 22
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "../stack/uds.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Uds Service 22 processing
*/
extern void UdsService22_ReadDataByIdentifier(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_SERVICE22_H_ */

View File

@ -0,0 +1,213 @@
/*
* 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 <string.h>
#include "uds_service27.h"
/*******************************************************************************
* the defines
******************************************************************************/
#define SUPPORT_LEVEL_NUM 4 /* supported security level number */
#define MAX_ALLOW_ERROR_NUM 5 /* the max allow number of key error */
#define STARTUP_DELAY_MS 2000 /* the service allow access time delay after UDS start */
#define ERR_EXCEED_DELAY_MS 10000 /* the service allow access time delay after error number exceed */
/*******************************************************************************
* the typedefs
******************************************************************************/
typedef struct _SecurityLevel_Param_
{
uint8_t level;
uint8_t keyErrorCnt;
uint8_t maxErrNum;
int64_t MaxErrTimeStamp;
} SecurityLevel_Param;
/*******************************************************************************
* the globals
******************************************************************************/
SecurityLevel_Param scrtParam[SUPPORT_LEVEL_NUM] = {
{UDS_SA_LEVEL_1, 0, MAX_ALLOW_ERROR_NUM, 0},
{UDS_SA_LEVEL_3, 0, MAX_ALLOW_ERROR_NUM, 0},
{UDS_SA_LEVEL_11, 0, MAX_ALLOW_ERROR_NUM, 0},
{UDS_SA_LEVEL_63, 0, MAX_ALLOW_ERROR_NUM, 0},
};
/*******************************************************************************
* the constants
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
static void UdsSecurityAccess_GenerateSeed(UdsType *obj, uint8_t newLevel, uint8_t *outData, uint8_t outBufsize, uint16_t *outLen)
{
/* seed is defined by user, It's usually a random value */
uint8_t seed[4] = {1, 2, 3, 4};
if(outBufsize < sizeof(seed))
{
return;
}
*outLen = sizeof(seed);
if(newLevel == obj->securityLevel)
{
memset(outData, 0, sizeof(seed));
}
else
{
memcpy(outData, seed, sizeof(seed));
}
}
static bool UdsSecurityAccess_ValidateKey(uint8_t seedLevel, const uint8_t *seed, uint16_t seedLen, const uint8_t *key, uint16_t keyLen)
{
/* The encryption algorithm is provided by the vehicle manufacturer */
return true;
}
void UdsService27_SecurityAccess(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen)
{
static uint8_t seedLevel = 0;
static uint8_t seedValue[8] = {0};
static uint16_t seedLen = 0;
uint8_t subFunction;
uint8_t udx = 0;
uint8_t rspBuffer[8] = {0};
uint16_t dataLen = 0, remainSize = 0;
bool ret = false;
if(msgLen < obj->seviceTable[obj->curServiceIdx].minLen)
{
Uds_NegativeResponse(obj, 0x27, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
if(obj->session == UDS_SESSION_DEFAULT)
{
Uds_NegativeResponse(obj, 0x27, NRC_CONDITIONS_NOT_CORRECT);
return;
}
if(obj->timeStamp_ms < STARTUP_DELAY_MS)
{
Uds_NegativeResponse(obj, 0x27, NRC_REQUIRED_TIME_DELAY_NOT_EXPIRED);
return;
}
subFunction = UDS_GET_SUB_FUNCTION(msgBuf[1]);
rspBuffer[0] = UDS_GET_POSITIVE_RSP(0x27);
rspBuffer[1] = subFunction;
if(subFunction % 2)
{
seedLevel = 0;
for(udx = 0; udx < SUPPORT_LEVEL_NUM; udx++)
{
if(subFunction == scrtParam[udx].level)
{
if(scrtParam[udx].keyErrorCnt > scrtParam[udx].maxErrNum)
{
if(obj->timeStamp_ms - scrtParam[udx].MaxErrTimeStamp < ERR_EXCEED_DELAY_MS)
{
Uds_NegativeResponse(obj, 0x27, NRC_EXCEEDED_NUMBER_OF_ATTEMPTS);
return;
}
else
{
scrtParam[udx].keyErrorCnt = 0;
}
}
break;
}
}
if(udx >= SUPPORT_LEVEL_NUM)
{
Uds_NegativeResponse(obj, 0x27, NRC_REQUEST_OUT_OF_RANGE);
return;
}
remainSize = sizeof(rspBuffer) - 2;
UdsSecurityAccess_GenerateSeed(obj, subFunction, &rspBuffer[2], remainSize, &dataLen);
if(dataLen > 0)
{
Uds_PositiveResponse(obj, rspBuffer, dataLen + 2);
seedLevel = subFunction;
seedLen = dataLen;
memcpy(seedValue, &rspBuffer[2], dataLen);
}
else
{
Uds_NegativeResponse(obj, 0x27, NRC_REQUEST_OUT_OF_RANGE);
}
}
else
{
if(subFunction != seedLevel + 1)
{
Uds_NegativeResponse(obj, 0x27, NRC_REQUEST_SEQUENCE_ERROR);
return;
}
/* polyspace-begin DEFECT:DEAD_CODE [No action planned:Low] "Still reserve though it's maybe unreachable" */
ret = UdsSecurityAccess_ValidateKey(seedLevel, seedValue, seedLen, &msgBuf[2], msgLen - 2);
if(ret == true)
{
Uds_PositiveResponse(obj, rspBuffer, 2);
seedLevel = 0;
obj->securityLevel = subFunction - 1;
for(udx = 0; udx < SUPPORT_LEVEL_NUM; udx++)
{
if(subFunction == scrtParam[udx].level)
{
scrtParam[udx].keyErrorCnt = 0;
}
}
}
else
{
Uds_NegativeResponse(obj, 0x27, NRC_INVALID_KEY);
for(udx = 0; udx < SUPPORT_LEVEL_NUM; udx++)
{
if(seedLevel == scrtParam[udx].level)
{
scrtParam[udx].keyErrorCnt++;
if(scrtParam[udx].keyErrorCnt > scrtParam[udx].maxErrNum)
{
scrtParam[udx].MaxErrTimeStamp = obj->timeStamp_ms;
}
}
}
}
/* polyspace-end DEFECT:DEAD_CODE [No action planned:Low] "Still reserve though it's maybe unreachable" */
}
}

View File

@ -0,0 +1,60 @@
/*
* 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.
*/
#ifndef _UDS_SERVICE27_H_
#define _UDS_SERVICE27_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS service 27
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "../stack/uds.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Uds Service 27 processing
*/
extern void UdsService27_SecurityAccess(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_SERVICE27_H_ */

View File

@ -0,0 +1,147 @@
/*
* 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 "uds_service28.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief The uds communication type definition of UDS
*/
typedef enum _UdsComType_
{
UDS_CC_TYPE_NONE = 0,
UDS_CC_TYPE_NORMAL, /* normal message */
UDS_CC_TYPE_NM, /* network management */
UDS_CC_TYPE_NOR_NM, /* normal and network management message */
} UdsComType;
/*! \brief The uds communication control mode definition of UDS
*/
typedef enum _UdsComCtrlMode_
{
UDS_CC_MODE_RX_TX = 0,
UDS_CC_MODE_RX_NO,
UDS_CC_MODE_NO_TX,
UDS_CC_MODE_NO_NO
} UdsComCtrMode;
/*******************************************************************************
* the globals
******************************************************************************/
static uint8_t udsComCtrlType = 0;
/*******************************************************************************
* the constants
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
uint8_t Uds_GetCommunicationControlMode(void)
{
return udsComCtrlType;
}
void UdsService28_CommunicationControl(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen)
{
uint8_t subFunction;
uint8_t rspBuffer[8] = {0}; /* polyspace DEFECT:PARTIALLY_ACCESSED_ARRAY [No action planned:Low] "Still keep default though member2~7 is not written" */
uint8_t ccType = 0;
if(msgLen < obj->seviceTable[obj->curServiceIdx].minLen)
{
Uds_NegativeResponse(obj, 0x28, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
if(obj->session == UDS_SESSION_DEFAULT)
{
Uds_NegativeResponse(obj, 0x28, NRC_CONDITIONS_NOT_CORRECT);
return;
}
subFunction = UDS_GET_SUB_FUNCTION(msgBuf[1]);
ccType = msgBuf[2];
rspBuffer[0] = UDS_GET_POSITIVE_RSP(0x28);
rspBuffer[1] = subFunction;
switch(subFunction)
{
case UDS_CC_MODE_RX_TX:
if(ccType == UDS_CC_TYPE_NORMAL || ccType == UDS_CC_TYPE_NM || ccType == UDS_CC_TYPE_NOR_NM)
{
udsComCtrlType = UDS_CC_MODE_RX_TX;
Uds_PositiveResponse(obj, rspBuffer, 2);
}
else
{
Uds_NegativeResponse(obj, 0x28, NRC_REQUEST_OUT_OF_RANGE);
}
break;
case UDS_CC_MODE_RX_NO:
if(ccType == UDS_CC_TYPE_NORMAL || ccType == UDS_CC_TYPE_NM || ccType == UDS_CC_TYPE_NOR_NM)
{
udsComCtrlType = UDS_CC_MODE_RX_NO;
Uds_PositiveResponse(obj, rspBuffer, 2);
}
else
{
Uds_NegativeResponse(obj, 0x28, NRC_REQUEST_OUT_OF_RANGE);
}
break;
case UDS_CC_MODE_NO_TX:
if(ccType == UDS_CC_TYPE_NORMAL || ccType == UDS_CC_TYPE_NM || ccType == UDS_CC_TYPE_NOR_NM)
{
udsComCtrlType = UDS_CC_MODE_NO_TX;
Uds_PositiveResponse(obj, rspBuffer, 2);
}
else
{
Uds_NegativeResponse(obj, 0x28, NRC_REQUEST_OUT_OF_RANGE);
}
break;
case UDS_CC_MODE_NO_NO:
if(ccType == UDS_CC_TYPE_NORMAL || ccType == UDS_CC_TYPE_NM || ccType == UDS_CC_TYPE_NOR_NM)
{
udsComCtrlType = UDS_CC_MODE_NO_NO;
Uds_PositiveResponse(obj, rspBuffer, 2);
}
else
{
Uds_NegativeResponse(obj, 0x28, NRC_REQUEST_OUT_OF_RANGE);
}
break;
default:
Uds_NegativeResponse(obj, 0x28, NRC_SUBFUNCTION_NOT_SUPPORTED);
break;
}
}

View File

@ -0,0 +1,64 @@
/*
* 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.
*/
#ifndef _UDS_SERVICE28_H_
#define _UDS_SERVICE28_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS service 28
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "../stack/uds.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Get Communication Control Mode
*/
uint8_t Uds_GetCommunicationControlMode(void);
/*! \brief Uds Service 28 processing
*/
extern void UdsService28_CommunicationControl(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_SERVICE28_H_ */

View File

@ -0,0 +1,107 @@
/*
* 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 <string.h>
#include "uds_service2E.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the constants
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void UdsService2E_WriteDataByIdentifier(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen)
{
uint16_t didValue = 0;
uint16_t didIdx = 0;
uint8_t rspBuffer[8] = {0};
if(msgLen < obj->seviceTable[obj->curServiceIdx].minLen)
{
Uds_NegativeResponse(obj, 0x2E, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
didValue = ((uint16_t)msgBuf[1]) << 8;
didValue |= msgBuf[2];
rspBuffer[0] = UDS_GET_POSITIVE_RSP(0x2E);
rspBuffer[1] = msgBuf[1];
rspBuffer[2] = msgBuf[2];
for(didIdx = 0; didIdx < obj->didNum; didIdx++)
{
if(obj->didTable[didIdx].did == didValue)
{
if((obj->didTable[didIdx].securityLevel != UDS_SA_NONE) && (obj->securityLevel != obj->didTable[didIdx].securityLevel))
{
Uds_NegativeResponse(obj, 0x22, NRC_SECURITY_ACCESS_DENIED);
return;
}
else if((msgLen - 3) != obj->didTable[didIdx].length)
{
Uds_NegativeResponse(obj, 0x2E, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
if((UDS_DID_TYPE_NVM_RO == obj->didTable[didIdx].type) || (obj->session < obj->didTable[didIdx].sessionLevel))
{
Uds_NegativeResponse(obj, 0x2E, NRC_CONDITIONS_NOT_CORRECT);
return;
}
memcpy(obj->didTable[didIdx].pBytes, &msgBuf[3], obj->didTable[didIdx].length);
/* add user code to save data */
/* check save data success */
/* polyspace-begin DEFECT:DEAD_CODE [No action planned:Low] "Still reserve though it's maybe unreachable" */
if(1)
{
Uds_PositiveResponse(obj, rspBuffer, 3);
return;
}
else
{
Uds_NegativeResponse(obj, 0x2E, NRC_GENERAL_PROGRAMMING_FAILURE);
return;
}
/* polyspace-end DEFECT:DEAD_CODE [No action planned:Low] "Still reserve though it's maybe unreachable" */
}
}
Uds_NegativeResponse(obj, 0x2E, NRC_REQUEST_OUT_OF_RANGE);
}

View File

@ -0,0 +1,60 @@
/*
* 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.
*/
#ifndef _UDS_SERVICE2E_H_
#define _UDS_SERVICE2E_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS service 2E
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "../stack/uds.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Uds Service 2E processing
*/
extern void UdsService2E_WriteDataByIdentifier(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_SERVICE2E_H_ */

View File

@ -0,0 +1,189 @@
/*
* 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 <stddef.h>
#include <string.h>
#include "uds_service2F.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief The Uds IO control type
*/
typedef enum _UdsIoCtrlType_
{
UDS_IOCTRL_RETURN_TO_ECU = 0x00,
UDS_IOCTRL_RETSET_TO_DEFAULT = 0x01,
UDS_IOCTRL_FREEZE_CURRENT_STATE = 0x02,
UDS_IOCTRL_SHORT_ADJUSTMENT = 0x03
} UdsIoCtrlType;
/*! \brief The Uds IO control struct
*/
typedef struct _Uds_IoCtrl_
{
uint16_t did;
uint8_t securityLevel;
uint8_t *pData;
uint8_t dataLen;
uint8_t defaultValue;
uint8_t step;
bool enable;
void (*IoCtrl_Init)(void);
void (*IoCtrl_Stop)(void);
} Uds_IoCtrl;
/*! \brief The IoControl-by-ID definition of UDS
*/
typedef struct _Uds_IoCtrlBuf_
{
uint8_t backlightLevel[2];
uint8_t buzzer[2];
} Uds_IoCtrlBuf;
/*******************************************************************************
* the constants
******************************************************************************/
static void IoCtrl_InitBackLight(void);
static void IoCtrl_StopBacklight(void);
static void IoCtrl_InitBuzzer(void);
static void IoCtrl_StopBuzzer(void);
/*******************************************************************************
* the globals
******************************************************************************/
Uds_IoCtrlBuf udsIoCtrlBuffer;
Uds_IoCtrl udsIoCtrlTable[] = {
{0xF092, UDS_SA_NONE, udsIoCtrlBuffer.backlightLevel, 2, 0, 0, 0, &IoCtrl_InitBackLight, &IoCtrl_StopBacklight},
{0xF020, UDS_SA_NONE, udsIoCtrlBuffer.buzzer, 2, 0, 0, 0, &IoCtrl_InitBuzzer, &IoCtrl_StopBuzzer },
};
/*******************************************************************************
* the functions
******************************************************************************/
static void IoCtrl_InitBackLight(void)
{
/* user add back light control code */
}
static void IoCtrl_StopBacklight(void)
{
/* user add back light stop code */
}
static void IoCtrl_InitBuzzer(void)
{
/* user add buzzer control code */
}
static void IoCtrl_StopBuzzer(void)
{
/* user add buzzer stop code */
}
void UdsService2F_InputOutputCtrlById(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen)
{
uint16_t ioCtrlId = 0;
uint8_t ioCtrlParam = 0;
uint8_t ioCtrlIndex = 0;
uint8_t ioCtrlNum = sizeof(udsIoCtrlTable) / sizeof(udsIoCtrlTable[0]);
uint8_t rspBuffer[UDS_RSP_LEN_MAX] = {0};
if(msgLen < obj->seviceTable[obj->curServiceIdx].minLen)
{
Uds_NegativeResponse(obj, 0x2F, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
if(obj->session == UDS_SESSION_DEFAULT)
{
Uds_NegativeResponse(obj, 0x2F, NRC_CONDITIONS_NOT_CORRECT);
return;
}
ioCtrlId = ((uint16_t)msgBuf[1] << 8) + msgBuf[2];
ioCtrlParam = msgBuf[3];
for(ioCtrlIndex = 0; ioCtrlIndex < ioCtrlNum; ioCtrlIndex++)
{
if(udsIoCtrlTable[ioCtrlIndex].did == ioCtrlId)
{
if((udsIoCtrlTable[ioCtrlIndex].securityLevel != UDS_SA_NONE) && (udsIoCtrlTable[ioCtrlIndex].securityLevel != obj->securityLevel))
{
Uds_NegativeResponse(obj, 0x2F, NRC_SECURITY_ACCESS_DENIED);
return;
}
break;
}
}
if(ioCtrlIndex >= ioCtrlNum)
{
Uds_NegativeResponse(obj, 0x2F, NRC_REQUEST_OUT_OF_RANGE);
return;
}
rspBuffer[0] = UDS_GET_POSITIVE_RSP(0x2F);
rspBuffer[1] = msgBuf[1];
rspBuffer[2] = msgBuf[2];
rspBuffer[3] = msgBuf[3];
switch(ioCtrlParam)
{
case UDS_IOCTRL_RETURN_TO_ECU:
/* add user code */
udsIoCtrlTable[ioCtrlIndex].enable = false;
if(udsIoCtrlTable[ioCtrlIndex].IoCtrl_Stop != NULL)
{
udsIoCtrlTable[ioCtrlIndex].IoCtrl_Stop();
Uds_PositiveResponse(obj, rspBuffer, 4);
}
break;
case UDS_IOCTRL_SHORT_ADJUSTMENT:
/* add user code */
if(msgLen < (udsIoCtrlTable[ioCtrlIndex].dataLen + 4))
{
Uds_NegativeResponse(obj, 0x2F, NRC_CONDITIONS_NOT_CORRECT);
return;
}
udsIoCtrlTable[ioCtrlIndex].enable = true;
memcpy(udsIoCtrlTable[ioCtrlIndex].pData, &msgBuf[4], udsIoCtrlTable[ioCtrlIndex].dataLen);
if(udsIoCtrlTable[ioCtrlIndex].IoCtrl_Init != NULL)
{
udsIoCtrlTable[ioCtrlIndex].IoCtrl_Init();
Uds_PositiveResponse(obj, rspBuffer, 4);
}
break;
default:
Uds_NegativeResponse(obj, 0x2F, NRC_REQUEST_OUT_OF_RANGE);
break;
}
}

View File

@ -0,0 +1,60 @@
/*
* 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.
*/
#ifndef _UDS_SERVICE2F_H_
#define _UDS_SERVICE2F_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS service 2F
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "../stack/uds.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Uds Service 2F processing
*/
extern void UdsService2F_InputOutputCtrlById(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_SERVICE2F_H_ */

View File

@ -0,0 +1,278 @@
/*
* 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 "uds_service31.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief The Uds routine control type
*/
typedef enum _UdsRoutineCtrlType_
{
UDS_ROUTINE_CTRL_NONE = 0,
UDS_ROUTINE_CTRL_START = 0x01,
UDS_ROUTINE_CTRL_STOP = 0x02,
UDS_ROUTINE_CTRL_REQUEST_RESULT = 0x03
} UdsRoutineCtrlType;
/*! \brief The Uds routine control status
*/
typedef enum _UdsRtnCtrlStatus_
{
UDS_RTN_ST_IDLE = 0x00,
UDS_RTN_ST_RUNNING = 0x01,
} UdsRtnCtrlStatus;
/*! \brief The Uds routine control struct
*/
typedef struct _Uds_RtnCtrl_
{
uint16_t rtnCtrlId;
uint8_t sessionLevel;
uint8_t securityLevel;
UdsRtnCtrlStatus rtnStatus;
void (*Routine_Start)(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
void (*Routine_Stop)(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
void (*Routine_Result)(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
} Uds_RtnCtrl;
/*******************************************************************************
* the constants
******************************************************************************/
static void Routine_StartEreaseMemory(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
static void Routine_StopEreaseMemory(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
static void Routine_EreaseMemoryResult(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
static void Routine_StartCheckProgramDependencies(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
static void Routine_StopCheckProgramDependencies(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
static void Routine_CheckProgramDependenciesResult(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
static void Routine_StartEreaseMirrorMemDtcs(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
static void Routine_StopEreaseMirrorMemDtcs(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
static void Routine_EreaseMirrorMemDtcsResult(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
/*******************************************************************************
* the globals
******************************************************************************/
Uds_RtnCtrl udsRtnCtrlTable[] = {
{0xFF00, UDS_SESSION_EXTENDED, UDS_SA_LEVEL_1, UDS_RTN_ST_IDLE, &Routine_StartEreaseMemory, &Routine_StopEreaseMemory, &Routine_EreaseMemoryResult },
{0xFF01, UDS_SESSION_EXTENDED, UDS_SA_LEVEL_1, UDS_RTN_ST_IDLE, &Routine_StartCheckProgramDependencies, &Routine_StopCheckProgramDependencies, &Routine_CheckProgramDependenciesResult},
{0xFF02, UDS_SESSION_EXTENDED, UDS_SA_LEVEL_1, UDS_RTN_ST_IDLE, &Routine_StartEreaseMirrorMemDtcs, &Routine_StopEreaseMirrorMemDtcs, &Routine_EreaseMirrorMemDtcsResult },
};
/*******************************************************************************
* the functions
******************************************************************************/
void Routine_StatusInit(uint16_t routineId)
{
uint8_t rtnIndex = 0;
uint8_t rntNum = sizeof(udsRtnCtrlTable) / sizeof(Uds_RtnCtrl);
for(rtnIndex = 0; rtnIndex < rntNum; rtnIndex++)
{
if(udsRtnCtrlTable[rtnIndex].rtnCtrlId == routineId)
{
udsRtnCtrlTable[rtnIndex].rtnStatus = UDS_RTN_ST_IDLE;
}
}
}
static void Routine_StartEreaseMemory(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen)
{
if(pdata == NULL)
{
return;
}
/* user add start erease memory code */
}
static void Routine_StopEreaseMemory(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen)
{
if(pdata == NULL)
{
return;
}
/* user add stop erease memory code */
}
static void Routine_EreaseMemoryResult(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen)
{
if(pdata == NULL)
{
return;
}
/* user add erease memory result code */
}
static void Routine_StartCheckProgramDependencies(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen)
{
if(pdata == NULL)
{
return;
}
/* user add start check program dependencies code */
}
static void Routine_StopCheckProgramDependencies(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen)
{
if(pdata == NULL)
{
return;
}
/* user add stop check program dependencies code */
}
static void Routine_CheckProgramDependenciesResult(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen)
{
if(pdata == NULL)
{
return;
}
/* user add check program dependencies result code */
}
static void Routine_StartEreaseMirrorMemDtcs(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen)
{
if(pdata == NULL)
{
return;
}
/* user add start erease mirror memory Dtcs code */
}
static void Routine_StopEreaseMirrorMemDtcs(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen)
{
if(pdata == NULL)
{
return;
}
/* user add stop erease mirror memory Dtcs code */
}
static void Routine_EreaseMirrorMemDtcsResult(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen)
{
if(pdata == NULL)
{
return;
}
/* user add erease mirror memory Dtcs resultl code */
}
void UdsService31_RoutineControl(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen)
{
const uint8_t *pOptionParam = NULL;
uint8_t subFunction = 0;
uint16_t optionParamLen = 0;
uint16_t routineId = 0;
uint8_t rtnIndex = 0;
uint8_t rntNum = sizeof(udsRtnCtrlTable) / sizeof(Uds_RtnCtrl);
uint8_t rspBuffer[UDS_RSP_LEN_MAX] = {0};
uint16_t rspLen = 0;
if(msgLen < obj->seviceTable[obj->curServiceIdx].minLen)
{
Uds_NegativeResponse(obj, 0x31, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
subFunction = UDS_GET_SUB_FUNCTION(msgBuf[1]);
routineId = ((uint16_t)msgBuf[2] << 8) + msgBuf[3];
optionParamLen = msgLen - 4;
if(optionParamLen > 0)
{
pOptionParam = &msgBuf[4];
}
for(rtnIndex = 0; rtnIndex < rntNum; rtnIndex++)
{
if(udsRtnCtrlTable[rtnIndex].rtnCtrlId == routineId)
{
if(obj->session == udsRtnCtrlTable[rtnIndex].sessionLevel)
{
if((udsRtnCtrlTable[rtnIndex].securityLevel != UDS_SA_NONE) && (udsRtnCtrlTable[rtnIndex].securityLevel != obj->securityLevel))
{
Uds_NegativeResponse(obj, 0x31, NRC_SECURITY_ACCESS_DENIED);
return;
}
break;
}
else
{
Uds_NegativeResponse(obj, 0x31, NRC_CONDITIONS_NOT_CORRECT);
return;
}
}
}
if(rtnIndex >= rntNum)
{
Uds_NegativeResponse(obj, 0x31, NRC_REQUEST_OUT_OF_RANGE);
return;
}
memset(rspBuffer, 0, UDS_RSP_LEN_MAX);
switch(subFunction)
{
case UDS_ROUTINE_CTRL_START:
udsRtnCtrlTable[rtnIndex].Routine_Start(pOptionParam, optionParamLen, rspBuffer, UDS_RSP_LEN_MAX, &rspLen);
udsRtnCtrlTable[rtnIndex].rtnStatus = UDS_RTN_ST_RUNNING;
break;
case UDS_ROUTINE_CTRL_STOP:
if(udsRtnCtrlTable[rtnIndex].rtnStatus != UDS_RTN_ST_IDLE)
{
udsRtnCtrlTable[rtnIndex].Routine_Stop(pOptionParam, optionParamLen, rspBuffer, UDS_RSP_LEN_MAX, &rspLen);
udsRtnCtrlTable[rtnIndex].rtnStatus = UDS_RTN_ST_IDLE;
}
break;
case UDS_ROUTINE_CTRL_REQUEST_RESULT:
if(udsRtnCtrlTable[rtnIndex].rtnStatus != UDS_RTN_ST_IDLE)
{
udsRtnCtrlTable[rtnIndex].Routine_Result(pOptionParam, optionParamLen, rspBuffer, UDS_RSP_LEN_MAX, &rspLen);
}
break;
default:
Uds_NegativeResponse(obj, 0x31, NRC_SUBFUNCTION_NOT_SUPPORTED);
return;
}
/* polyspace-begin DEFECT:DEAD_CODE [No action planned:Low] "Still reserve though it's maybe unreachable" */
if((rspLen >= 4) && (rspBuffer[0] == UDS_GET_POSITIVE_RSP(0x31)))
{
Uds_PositiveResponse(obj, rspBuffer, rspLen);
}
else if((rspLen == 3) && (rspBuffer[0] == NEGATIVE_RSP))
{
Uds_NegativeResponse(obj, 0x31, rspBuffer[2]);
}
else
{
Uds_NegativeResponse(obj, 0x31, NRC_REQUEST_SEQUENCE_ERROR);
}
/* polyspace-end DEFECT:DEAD_CODE [No action planned:Low] "Still reserve though it's maybe unreachable" */
}

View File

@ -0,0 +1,62 @@
/*
* 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.
*/
#ifndef _UDS_SERVICE31_H_
#define _UDS_SERVICE31_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS service 31
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include "../stack/uds.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Uds Service 31 processing
*/
extern void UdsService31_RoutineControl(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen);
/*! \brief Routine status init
*/
extern void Routine_StatusInit(uint16_t routineId);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_SERVICE31_H_ */

View File

@ -0,0 +1,146 @@
/*
* 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 "uds_service34.h"
#include "uds_service36.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the constants
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
uint32_t Uds_GetMaxfBlockSize(void)
{
/* user add code to get max num of block length */
return 128;
}
uint8_t Uds_GetValidBytesNumOfData(uint32_t data)
{
uint8_t index = 0;
uint8_t bytesNum = 0;
for(index = 1; index <= 4; index++)
{
if(data >> ((4 - index) * 8))
{
bytesNum = 4 - index + 1;
break;
}
}
return bytesNum;
}
void UdsService34_RequestDownload(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen)
{
uint32_t memAddress = 0;
uint8_t memAddrLen = 0;
uint32_t memSize = 0;
uint8_t memSizeLen = 0;
uint8_t maxBlockSizeLen = 0;
uint32_t maxBlockSize = 0;
uint8_t index = 0;
uint16_t rspLen = 0;
uint8_t rspBuffer[8];
if(obj->session == UDS_SESSION_DEFAULT)
{
Uds_NegativeResponse(obj, 0x34, NRC_CONDITIONS_NOT_CORRECT);
return;
}
if(msgLen < obj->seviceTable[obj->curServiceIdx].minLen)
{
Uds_NegativeResponse(obj, 0x34, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
memAddrLen = msgBuf[2] & 0x0F;
memSizeLen = msgBuf[2] >> 4;
if((memAddrLen == 0) || (memAddrLen > sizeof(memAddress)) || (memSizeLen == 0) || (memSizeLen > sizeof(memSize)))
{
Uds_NegativeResponse(obj, 0x34, NRC_REQUEST_OUT_OF_RANGE);
return;
}
for(index = 0; index < memAddrLen; index++)
{
memAddress <<= 8;
memAddress += msgBuf[3 + index];
}
for(index = 0; index < memSizeLen; index++)
{
memSize <<= 8;
memSize += msgBuf[3 + memAddrLen + index];
}
if(memSize == 0)
{
Uds_NegativeResponse(obj, 0x34, NRC_CONDITIONS_NOT_CORRECT);
return;
}
/* user add judge code for the security level */
if(0)
{
Uds_NegativeResponse(obj, 0x34, NRC_SECURITY_ACCESS_DENIED);
return;
}
Uds_SetMemAddr(memAddress);
Uds_SetMemSize(memSize);
Uds_SetDataTransferDirect(UDS_TRANSFER_DIR_DOWNLOAD);
maxBlockSize = Uds_GetMaxfBlockSize();
maxBlockSizeLen = Uds_GetValidBytesNumOfData(maxBlockSize);
rspBuffer[rspLen++] = UDS_GET_POSITIVE_RSP(0x34);
rspBuffer[rspLen++] = maxBlockSizeLen << 4;
for(index = 1; index <= maxBlockSizeLen; index++)
{
rspBuffer[rspLen++] = maxBlockSize >> (8 * (maxBlockSizeLen - index));
}
Uds_PositiveResponse(obj, rspBuffer, rspLen);
}

View File

@ -0,0 +1,61 @@
/*
* 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.
*/
#ifndef _UDS_SERVICE34_H_
#define _UDS_SERVICE34_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS service 34
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "../stack/uds.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Uds Service 34 processing
*/
extern void UdsService34_RequestDownload(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_SERVICE34_H_ */

View File

@ -0,0 +1,160 @@
/*
* 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 "uds_service36.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
static uint32_t s_memAddr = 0;
static uint32_t s_memSize = 0;
static UdsTransDirType s_dataTransDir = UDS_TRANSFER_DIR_NONE;
static uint8_t s_curRcvSequence = 0;
static uint8_t s_lastRcvSqunce = 0;
static uint32_t s_rcvDataTotalLen = 0;
/*******************************************************************************
* the constants
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void Uds_SetMemAddr(uint32_t addr)
{
s_memAddr = addr;
}
uint32_t Uds_GetMemAddr(void)
{
return s_memAddr;
}
void Uds_SetMemSize(uint32_t size)
{
s_memSize = size;
}
uint32_t Uds_GetMemSize(void)
{
return s_memSize;
}
void Uds_SetDataTransferDirect(UdsTransDirType dirType)
{
s_dataTransDir = dirType;
/* clear sequence number */
s_lastRcvSqunce = 0x00;
s_curRcvSequence = 0x00;
/* clear receive data total number */
s_rcvDataTotalLen = 0x00;
}
UdsTransDirType Uds_GetDataTransferDirect(void)
{
return s_dataTransDir;
}
uint32_t Uds_GetRcvDataTotalLen(void)
{
return s_rcvDataTotalLen;
}
void UdsService36_TransferData(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen)
{
uint16_t rspLen = 0;
uint8_t rspBuffer[UDS_RSP_LEN_MAX] = {0}; /* polyspace DEFECT:PARTIALLY_ACCESSED_ARRAY [No action planned:Low] "Still reserve though member2~511 is not written" */
if(obj->session == UDS_SESSION_DEFAULT)
{
Uds_NegativeResponse(obj, 0x36, NRC_CONDITIONS_NOT_CORRECT);
return;
}
if(msgLen < obj->seviceTable[obj->curServiceIdx].minLen)
{
Uds_NegativeResponse(obj, 0x36, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
switch(s_dataTransDir)
{
case UDS_TRANSFER_DIR_DOWNLOAD:
s_curRcvSequence = msgBuf[1];
if((s_curRcvSequence != s_lastRcvSqunce) && (s_curRcvSequence != ((uint8_t)(s_lastRcvSqunce + 1))))
{
Uds_NegativeResponse(obj, 0x36, NRC_WRONG_BLOCK_SEQUENCE_COUNTER);
return;
}
rspBuffer[rspLen++] = UDS_GET_POSITIVE_RSP(0x36);
rspBuffer[rspLen++] = msgBuf[1];
if(s_curRcvSequence == s_lastRcvSqunce)
{
Uds_PositiveResponse(obj, rspBuffer, rspLen);
return;
}
if((s_rcvDataTotalLen + msgLen - 2) > s_memSize)
{
Uds_NegativeResponse(obj, 0x36, NRC_TRANSFER_DATA_SUSPENDED);
return;
}
/* user add code to deal with download data */
/* polyspace-begin DEFECT:DEAD_CODE [No action planned:Low] "Still reserve though it's maybe unreachable" */
if(1) /* deal success */
{
s_rcvDataTotalLen += msgLen - 2;
s_lastRcvSqunce = s_curRcvSequence;
Uds_PositiveResponse(obj, rspBuffer, rspLen);
}
else
{
Uds_NegativeResponse(obj, 0x36, NRC_GENERAL_PROGRAMMING_FAILURE);
}
/* polyspace-end DEFECT:DEAD_CODE [No action planned:Low] "Still reserve though it's maybe unreachable" */
break;
case UDS_TRANSFER_DIR_UPLOAD:
Uds_NegativeResponse(obj, 0x36, NRC_REQUEST_OUT_OF_RANGE);
break;
default:
Uds_NegativeResponse(obj, 0x36, NRC_REQUEST_SEQUENCE_ERROR);
break;
}
}

View File

@ -0,0 +1,97 @@
/*
* 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.
*/
#ifndef _UDS_SERVICE36_H_
#define _UDS_SERVICE36_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS service 36
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "../stack/uds.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief The Uds IO control type
*/
typedef enum _UdsTransDirType_
{
UDS_TRANSFER_DIR_NONE = 0x00,
UDS_TRANSFER_DIR_DOWNLOAD = 0x01,
UDS_TRANSFER_DIR_UPLOAD = 0x02,
} UdsTransDirType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief set memery start address
*/
extern void Uds_SetMemAddr(uint32_t addr);
/*! \brief get memery start address
*/
extern uint32_t Uds_GetMemAddr(void);
/*! \brief set memery size
*/
extern void Uds_SetMemSize(uint32_t size);
/*! \brief get memery size
*/
extern uint32_t Uds_GetMemSize(void);
/*! \brief set data transfer direct
*/
extern void Uds_SetDataTransferDirect(UdsTransDirType dirType);
/*! \brief get data transfer direct
*/
extern UdsTransDirType Uds_GetDataTransferDirect(void);
/*! \brief get receive data total len
*/
extern uint32_t Uds_GetRcvDataTotalLen(void);
/*! \brief Uds Service 10 processing
*/
extern void UdsService36_TransferData(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_SERVICE36_H_ */

View File

@ -0,0 +1,95 @@
/*
* 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 "uds_service36.h"
#include "uds_service37.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the constants
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void UdsService37_RequestTransferExit(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen)
{
uint16_t rspLen = 0;
uint8_t rspBuffer[8] ={0}; /* polyspace DEFECT:PARTIALLY_ACCESSED_ARRAY [No action planned:Low] "Still reserve though member1~7 is not written" */
if(obj->session == UDS_SESSION_DEFAULT)
{
Uds_NegativeResponse(obj, 0x37, NRC_CONDITIONS_NOT_CORRECT);
return;
}
if(msgLen < obj->seviceTable[obj->curServiceIdx].minLen)
{
Uds_NegativeResponse(obj, 0x37, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
rspBuffer[rspLen++] = UDS_GET_POSITIVE_RSP(0x37);
switch(Uds_GetDataTransferDirect())
{
case UDS_TRANSFER_DIR_DOWNLOAD:
if(Uds_GetRcvDataTotalLen() != Uds_GetMemSize())
{
Uds_NegativeResponse(obj, 0x37, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
break;
}
/* user add process code, example data CRC */
/* polyspace-begin DEFECT:DEAD_CODE [No action planned:Low] "Still reserve though it's maybe unreachable" */
if(1) /* result check correct */
{
Uds_PositiveResponse(obj, rspBuffer, rspLen);
}
else
{
Uds_NegativeResponse(obj, 0x37, NRC_GENERAL_PROGRAMMING_FAILURE);
}
/* polyspace-end DEFECT:DEAD_CODE [No action planned:Low] "Still reserve though it's maybe unreachable" */
break;
case UDS_TRANSFER_DIR_UPLOAD:
Uds_NegativeResponse(obj, 0x37, NRC_REQUEST_OUT_OF_RANGE);
break;
default:
Uds_NegativeResponse(obj, 0x37, NRC_REQUEST_SEQUENCE_ERROR);
break;
}
Uds_SetDataTransferDirect(UDS_TRANSFER_DIR_NONE);
}

View File

@ -0,0 +1,60 @@
/*
* 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.
*/
#ifndef _UDS_SERVICE37_H_
#define _UDS_SERVICE37_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS service 37
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "../stack/uds.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Uds Service 37 processing
*/
void UdsService37_RequestTransferExit(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_SERVICE37_H_ */

View File

@ -0,0 +1,70 @@
/*
* 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 "uds_service3E.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the constants
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void UdsService3E_TesterPresent(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen)
{
uint8_t subFunction;
uint8_t rspBuffer[8] = {0}; /* polyspace DEFECT:PARTIALLY_ACCESSED_ARRAY [No action planned:Low] "Still keep default though member2~7 is not written" */
if(msgLen != obj->seviceTable[obj->curServiceIdx].minLen)
{
Uds_NegativeResponse(obj, 0x3E, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
subFunction = UDS_GET_SUB_FUNCTION (msgBuf[1]);
if(subFunction == 0)
{
rspBuffer[0] = UDS_GET_POSITIVE_RSP(0x3E);
rspBuffer[1] = subFunction;
Uds_PositiveResponse(obj, rspBuffer, 2);
}
else
{
Uds_NegativeResponse(obj, 0x3E, NRC_SUBFUNCTION_NOT_SUPPORTED);
}
}

View File

@ -0,0 +1,60 @@
/*
* 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.
*/
#ifndef _UDS_SERVICE3E_H_
#define _UDS_SERVICE3E_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS service 3E
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "../stack/uds.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Uds Service 3E processing
*/
extern void UdsService3E_TesterPresent(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_SERVICE3E_H_ */

View File

@ -0,0 +1,81 @@
/*
* 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 "uds_service85.h"
#include "uds_dtc.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the constants
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void UdsService85_ControlDtcSetting(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen)
{
uint8_t subFunction;
uint8_t rspBuffer[8] = {0}; /* polyspace DEFECT:PARTIALLY_ACCESSED_ARRAY [No action planned:Low] "Still keep default though member2~7 is not written" */
if(msgLen < obj->seviceTable[obj->curServiceIdx].minLen)
{
Uds_NegativeResponse(obj, 0x85, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
if(obj->session == UDS_SESSION_DEFAULT)
{
Uds_NegativeResponse(obj, 0x85, NRC_CONDITIONS_NOT_CORRECT);
return;
}
subFunction = UDS_GET_SUB_FUNCTION (msgBuf[1]);
rspBuffer[0] = UDS_GET_POSITIVE_RSP(0x85);
rspBuffer[1] = subFunction;
switch(subFunction)
{
case 1:
Uds_SetDtcOffCtrl(true);
Uds_PositiveResponse(obj, rspBuffer, 2);
break;
case 2:
Uds_SetDtcOffCtrl(false);
Uds_PositiveResponse(obj, rspBuffer, 2);
break;
default:
Uds_NegativeResponse(obj, 0x85, NRC_SUBFUNCTION_NOT_SUPPORTED);
break;
}
}

View File

@ -0,0 +1,60 @@
/*
* 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.
*/
#ifndef _UDS_SERVICE85_H_
#define _UDS_SERVICE85_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS service 85
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "../stack/uds.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Uds Service 85 processing
*/
extern void UdsService85_ControlDtcSetting(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_SERVICE85_H_ */

View File

@ -0,0 +1,140 @@
/*
* 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 "uds_user.h"
#include "extern.h"
/*******************************************************************************
* the defines
******************************************************************************/
void DID_F180_func(UdsType *obj,uint8_t dataBuf[], uint8_t dataLen);
void DID_F186_func(UdsType *obj,uint8_t dataBuf[], uint8_t dataLen);
void DID_F193_func(UdsType *obj,uint8_t dataBuf[], uint8_t dataLen);
void DID_F195_func(UdsType *obj,uint8_t dataBuf[], uint8_t dataLen);
void DID_F191_func(UdsType *obj,uint8_t dataBuf[], uint8_t dataLen);
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief The Data-by-ID definition of UDS
*/
typedef struct _Uds_DidBuffer_
{
uint8_t buffer_F186[1];
uint8_t buffer_F180[4];
uint8_t buffer_F193[8];
uint8_t buffer_F195[16];
uint8_t buffer_F191[24];
} Uds_DidBuffer;
/*******************************************************************************
* the globals
******************************************************************************/
Uds_DidBuffer udsDidBuf;
/*******************************************************************************
* the constants
******************************************************************************/
static const Uds_ServiceType udsServiceTable[UDS_SERVICE_NUM] = {
{0x10, 2, true, UdsService10_SessionControl },
{0x11, 2, true, UdsService11_ResetEcu },
{0x27, 2, true, UdsService27_SecurityAccess },
{0x28, 3, true, UdsService28_CommunicationControl },
{0x3E, 2, true, UdsService3E_TesterPresent },
{0x85, 2, true, UdsService85_ControlDtcSetting },
{0x22, 3, false, UdsService22_ReadDataByIdentifier },
{0x2E, 4, false, UdsService2E_WriteDataByIdentifier},
{0x14, 4, false, UdsService14_ClearDiagInfo },
{0x19, 3, true, UdsService19_ReadDtcInformation },
{0x2F, 3, false, UdsService2F_InputOutputCtrlById },
{0x31, 4, true, UdsService31_RoutineControl },
{0x34, 5, false, UdsService34_RequestDownload },
{0x36, 2, false, UdsService36_TransferData },
{0x37, 1, false, UdsService37_RequestTransferExit },
};
static const bool udsSecurityTable[UDS_SERVICE_NUM][UDS_SA_LEVEL_NUM] = {
{false, false, false}, /* 0x10 */
{false, false, false}, /* 0x11 */
{false, false, false}, /* 0x27 */
{false, false, false}, /* 0x28 */
{false, false, false}, /* 0x3E */
{false, false, false}, /* 0x85 */
{false, false, false}, /* 0x22 */
{false, false, false}, /* 0x2E */
{false, false, false}, /* 0x14 */
{false, false, false}, /* 0x19 */
{false, false, false}, /* 0x2F */
{false, false, false}, /* 0x31 */
{false, false, false}, /* 0x34 */
{false, false, false}, /* 0x36 */
{false, false, false}, /* 0x37 */
};
Uds_DidType udsDidTable[] = {
{0xF186, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_F186, BYTES_OF(udsDidBuf.buffer_F186),DID_F186_func},
{0xF180, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_F180, BYTES_OF(udsDidBuf.buffer_F180),DID_F180_func},
{0xF193, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_F193, BYTES_OF(udsDidBuf.buffer_F193),DID_F193_func},
{0xF195, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_F195, BYTES_OF(udsDidBuf.buffer_F195),DID_F195_func},
{0xF191, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_F191, BYTES_OF(udsDidBuf.buffer_F191),DID_F191_func},
};
/*******************************************************************************
* the functions
******************************************************************************/
void Uds_UserInit(UdsType *obj, const Uds_ParamsType *pParams)
{
Uds_Init(obj, pParams);
obj->seviceTable = udsServiceTable;
obj->securityTable = &udsSecurityTable[0][0];
obj->serviceNum = UDS_SERVICE_NUM;
obj->didTable = udsDidTable;
obj->didNum = sizeof(udsDidTable) / sizeof(Uds_DidType);
}
/******************************DID FUNC****************************************/
void DID_F180_func(UdsType *obj,uint8_t dataBuf[], uint8_t dataLen)
{
uint8_t * pdata;
pdata = (uint8_t *)0x0000400;
memcpy(dataBuf, pdata, dataLen);
}
void DID_F186_func(UdsType *obj,uint8_t dataBuf[], uint8_t dataLen)
{
dataBuf[0] = obj->session;
}
void DID_F193_func(UdsType *obj,uint8_t dataBuf[], uint8_t dataLen)
{
getHW_VERSION(dataBuf);
}
void DID_F195_func(UdsType *obj,uint8_t dataBuf[], uint8_t dataLen)
{
getSW_VERSION(dataBuf);
}
void DID_F191_func(UdsType *obj,uint8_t dataBuf[], uint8_t dataLen)
{
getBuildTime(dataBuf);
}

View File

@ -0,0 +1,77 @@
/*
* 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.
*/
#ifndef _UDS_USER_H_
#define _UDS_USER_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS application
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "../stack/uds.h"
#include "uds_service10.h"
#include "uds_service11.h"
#include "uds_service14.h"
#include "uds_service19.h"
#include "uds_service22.h"
#include "uds_service27.h"
#include "uds_service28.h"
#include "uds_service2E.h"
#include "uds_service2F.h"
#include "uds_service31.h"
#include "uds_service34.h"
#include "uds_service36.h"
#include "uds_service37.h"
#include "uds_service3E.h"
#include "uds_service85.h"
#include "uds_dtc.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the UDS object
*/
extern void Uds_UserInit(UdsType *obj, const Uds_ParamsType *pParams);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_USER_H_ */

View File

@ -0,0 +1,338 @@
/*
* 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.
*/
#ifndef _CVM014X_FEATURES_H_
#define _CVM014X_FEATURES_H_
/*! \brief Contains public interface to various functions related
* to the features definition of CVM014x series chips
*/
/*******************************************************************************
* the includes
******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
#if defined(MCU_CVM0146FMLQ) || defined(MCU_CVM0146LMLQ)
#ifdef FEATURE_PFLASH_SIZE
#undef FEATURE_PFLASH_SIZE
#endif
#define FEATURE_PFLASH_SIZE (0x100000)
#ifdef FEATURE_RAM_SIZE
#undef FEATURE_RAM_SIZE
#endif
#define FEATURE_RAM_SIZE (0x20000)
#ifdef FEATURE_DFLASH_SIZE
#undef FEATURE_DFLASH_SIZE
#endif
#define FEATURE_DFLASH_SIZE (0x20000)
#ifdef FEATURE_EEPROM_SIZE
#undef FEATURE_EEPROM_SIZE
#endif
#define FEATURE_EEPROM_SIZE (0x1000)
#ifdef FEATURE_CAN_FD_INSTANCE_NUM
#undef FEATURE_CAN_FD_INSTANCE_NUM
#endif
#define FEATURE_CAN_FD_INSTANCE_NUM (4)
#ifdef FEATURE_MFT_INSTANCE_NUM
#undef FEATURE_MFT_INSTANCE_NUM
#endif
#define FEATURE_MFT_INSTANCE_NUM (6)
#ifdef FEATURE_UART_INSTANCE_NUM
#undef FEATURE_UART_INSTANCE_NUM
#endif
#define FEATURE_UART_INSTANCE_NUM (4)
#ifdef FEATURE_SPI_INSTANCE_NUM
#undef FEATURE_SPI_INSTANCE_NUM
#endif
#define FEATURE_SPI_INSTANCE_NUM (4)
#ifdef FEATURE_LAST_IRQn
#undef FEATURE_LAST_IRQn
#endif
#define FEATURE_LAST_IRQn (CAN3_EdgeWakeup_IRQn)
#elif defined(MCU_CVM0146FMLL) || defined(MCU_CVM0146LMLL)
#ifdef FEATURE_PFLASH_SIZE
#undef FEATURE_PFLASH_SIZE
#endif
#define FEATURE_PFLASH_SIZE (0x100000)
#ifdef FEATURE_RAM_SIZE
#undef FEATURE_RAM_SIZE
#endif
#define FEATURE_RAM_SIZE (0x20000)
#ifdef FEATURE_DFLASH_SIZE
#undef FEATURE_DFLASH_SIZE
#endif
#define FEATURE_DFLASH_SIZE (0x20000)
#ifdef FEATURE_EEPROM_SIZE
#undef FEATURE_EEPROM_SIZE
#endif
#define FEATURE_EEPROM_SIZE (0x1000)
#ifdef FEATURE_CAN_FD_INSTANCE_NUM
#undef FEATURE_CAN_FD_INSTANCE_NUM
#endif
#define FEATURE_CAN_FD_INSTANCE_NUM (4)
#ifdef FEATURE_MFT_INSTANCE_NUM
#undef FEATURE_MFT_INSTANCE_NUM
#endif
#define FEATURE_MFT_INSTANCE_NUM (6)
#ifdef FEATURE_UART_INSTANCE_NUM
#undef FEATURE_UART_INSTANCE_NUM
#endif
#define FEATURE_UART_INSTANCE_NUM (4)
#ifdef FEATURE_SPI_INSTANCE_NUM
#undef FEATURE_SPI_INSTANCE_NUM
#endif
#define FEATURE_SPI_INSTANCE_NUM (4)
#ifdef FEATURE_LAST_IRQn
#undef FEATURE_LAST_IRQn
#endif
#define FEATURE_LAST_IRQn (CAN3_EdgeWakeup_IRQn)
#elif defined(MCU_CVM0146FMLH) || defined(MCU_CVM0146LMLH)
#ifdef FEATURE_PFLASH_SIZE
#undef FEATURE_PFLASH_SIZE
#endif
#define FEATURE_PFLASH_SIZE (0x100000)
#ifdef FEATURE_RAM_SIZE
#undef FEATURE_RAM_SIZE
#endif
#define FEATURE_RAM_SIZE (0x20000)
#ifdef FEATURE_DFLASH_SIZE
#undef FEATURE_DFLASH_SIZE
#endif
#define FEATURE_DFLASH_SIZE (0x20000)
#ifdef FEATURE_EEPROM_SIZE
#undef FEATURE_EEPROM_SIZE
#endif
#define FEATURE_EEPROM_SIZE (0x1000)
#ifdef FEATURE_CAN_FD_INSTANCE_NUM
#undef FEATURE_CAN_FD_INSTANCE_NUM
#endif
#define FEATURE_CAN_FD_INSTANCE_NUM (3)
#ifdef FEATURE_MFT_INSTANCE_NUM
#undef FEATURE_MFT_INSTANCE_NUM
#endif
#define FEATURE_MFT_INSTANCE_NUM (4)
#ifdef FEATURE_UART_INSTANCE_NUM
#undef FEATURE_UART_INSTANCE_NUM
#endif
#define FEATURE_UART_INSTANCE_NUM (3)
#ifdef FEATURE_SPI_INSTANCE_NUM
#undef FEATURE_SPI_INSTANCE_NUM
#endif
#define FEATURE_SPI_INSTANCE_NUM (3)
#ifdef FEATURE_LAST_IRQn
#undef FEATURE_LAST_IRQn
#endif
#define FEATURE_LAST_IRQn (CAN2_EdgeWakeup_IRQn)
#elif defined(MCU_CVM0144FMLL) || defined(MCU_CVM0144LMLL)
#ifdef FEATURE_PFLASH_SIZE
#undef FEATURE_PFLASH_SIZE
#endif
#define FEATURE_PFLASH_SIZE (0x80000)
#ifdef FEATURE_RAM_SIZE
#undef FEATURE_RAM_SIZE
#endif
#define FEATURE_RAM_SIZE (0x20000)
#ifdef FEATURE_DFLASH_SIZE
#undef FEATURE_DFLASH_SIZE
#endif
#define FEATURE_DFLASH_SIZE (0x10000)
#ifdef FEATURE_EEPROM_SIZE
#undef FEATURE_EEPROM_SIZE
#endif
#define FEATURE_EEPROM_SIZE (0x1000)
#ifdef FEATURE_CAN_FD_INSTANCE_NUM
#undef FEATURE_CAN_FD_INSTANCE_NUM
#endif
#define FEATURE_CAN_FD_INSTANCE_NUM (4)
#ifdef FEATURE_MFT_INSTANCE_NUM
#undef FEATURE_MFT_INSTANCE_NUM
#endif
#define FEATURE_MFT_INSTANCE_NUM (4)
#ifdef FEATURE_UART_INSTANCE_NUM
#undef FEATURE_UART_INSTANCE_NUM
#endif
#define FEATURE_UART_INSTANCE_NUM (4)
#ifdef FEATURE_SPI_INSTANCE_NUM
#undef FEATURE_SPI_INSTANCE_NUM
#endif
#define FEATURE_SPI_INSTANCE_NUM (4)
#ifdef FEATURE_LAST_IRQn
#undef FEATURE_LAST_IRQn
#endif
#define FEATURE_LAST_IRQn (CAN3_EdgeWakeup_IRQn)
#elif defined(MCU_CVM0144FMLH) || defined(MCU_CVM0144LMLH)
#ifdef FEATURE_PFLASH_SIZE
#undef FEATURE_PFLASH_SIZE
#endif
#define FEATURE_PFLASH_SIZE (0x80000)
#ifdef FEATURE_RAM_SIZE
#undef FEATURE_RAM_SIZE
#endif
#define FEATURE_RAM_SIZE (0x20000)
#ifdef FEATURE_DFLASH_SIZE
#undef FEATURE_DFLASH_SIZE
#endif
#define FEATURE_DFLASH_SIZE (0x10000)
#ifdef FEATURE_EEPROM_SIZE
#undef FEATURE_EEPROM_SIZE
#endif
#define FEATURE_EEPROM_SIZE (0x1000)
#ifdef FEATURE_CAN_FD_INSTANCE_NUM
#undef FEATURE_CAN_FD_INSTANCE_NUM
#endif
#define FEATURE_CAN_FD_INSTANCE_NUM (3)
#ifdef FEATURE_MFT_INSTANCE_NUM
#undef FEATURE_MFT_INSTANCE_NUM
#endif
#define FEATURE_MFT_INSTANCE_NUM (4)
#ifdef FEATURE_UART_INSTANCE_NUM
#undef FEATURE_UART_INSTANCE_NUM
#endif
#define FEATURE_UART_INSTANCE_NUM (3)
#ifdef FEATURE_SPI_INSTANCE_NUM
#undef FEATURE_SPI_INSTANCE_NUM
#endif
#define FEATURE_SPI_INSTANCE_NUM (3)
#ifdef FEATURE_LAST_IRQn
#undef FEATURE_LAST_IRQn
#endif
#define FEATURE_LAST_IRQn (CAN2_EdgeWakeup_IRQn)
#elif defined(MCU_CVM0142FMLH) || defined(MCU_CVM0142LMLH)
#ifdef FEATURE_PFLASH_SIZE
#undef FEATURE_PFLASH_SIZE
#endif
#define FEATURE_PFLASH_SIZE (0x40000)
#ifdef FEATURE_RAM_SIZE
#undef FEATURE_RAM_SIZE
#endif
#define FEATURE_RAM_SIZE (0x10000)
#ifdef FEATURE_DFLASH_SIZE
#undef FEATURE_DFLASH_SIZE
#endif
#define FEATURE_DFLASH_SIZE (0x10000)
#ifdef FEATURE_EEPROM_SIZE
#undef FEATURE_EEPROM_SIZE
#endif
#define FEATURE_EEPROM_SIZE (0x1000)
#ifdef FEATURE_CAN_FD_INSTANCE_NUM
#undef FEATURE_CAN_FD_INSTANCE_NUM
#endif
#define FEATURE_CAN_FD_INSTANCE_NUM (3)
#ifdef FEATURE_MFT_INSTANCE_NUM
#undef FEATURE_MFT_INSTANCE_NUM
#endif
#define FEATURE_MFT_INSTANCE_NUM (4)
#ifdef FEATURE_UART_INSTANCE_NUM
#undef FEATURE_UART_INSTANCE_NUM
#endif
#define FEATURE_UART_INSTANCE_NUM (3)
#ifdef FEATURE_SPI_INSTANCE_NUM
#undef FEATURE_SPI_INSTANCE_NUM
#endif
#define FEATURE_SPI_INSTANCE_NUM (3)
#ifdef FEATURE_LAST_IRQn
#undef FEATURE_LAST_IRQn
#endif
#define FEATURE_LAST_IRQn (CAN2_EdgeWakeup_IRQn)
#else
#error "No correct chip defined"
#endif
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _CVM014X_FEATURES_H_ */

View File

@ -0,0 +1,439 @@
/*
* 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 "adc_drv.h"
#include "adc_reg.h"
#include "sim_reg.h"
#include "../cpu/cpu_drv.h"
/*******************************************************************************
* the defines
******************************************************************************/
#define ADC_INTERLEAVE_ENABLE (1U)
#define ADC_LEN_PWR_ON_DEFAULT (11U)
#define ADC_LEN_SMPL_1ST_DEFAULT (48U)
#define ADC_LEN_SMPL_DEFAULT (4U)
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief ADC type of enable selection
*/
typedef enum
{
ADCDRV_POWER_ON = 0x0U,
ADCDRV_POWER_DOWN = 0x1U,
} AdcDrv_PowerEnable;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void AdcDrv_Init(AdcDrvType *obj, struct _AdcRegType_ *adcReg, struct _SimRegType_ *simReg, const AdcDrv_InitParamsType *initParams)
{
obj->adcReg = adcReg;
obj->simReg = simReg;
obj->adcNumber = initParams->adcNumber;
}
void AdcDrv_SetInterleave(AdcDrvType *obj, const AdcDrv_InterleaveType *userConfig)
{
uint8_t interleave = 0;
uint8_t i;
for(i = ADCDRV_INTERLEAVE_ADC0SE4_ADC1SE14; i < ADCDRV_INTERLEAVE_CHANNEL_NUMBER; i++)
{
if(userConfig->state[i])
{
interleave |= ADC_INTERLEAVE_ENABLE << i;
}
}
SimReg_SetAdcILSrc(obj->simReg, interleave);
}
void AdcDrv_GetInterleave(AdcDrvType *obj, AdcDrv_InterleaveType *interleaveState)
{
uint8_t interleave = SimReg_GetAdcILSrc(obj->simReg);
uint8_t i;
for(i = ADCDRV_INTERLEAVE_ADC0SE4_ADC1SE14; i < ADCDRV_INTERLEAVE_CHANNEL_NUMBER; i++)
{
uint8_t tmp;
tmp = (interleave >> i) & ADC_INTERLEAVE_ENABLE;
if(tmp == ADC_INTERLEAVE_ENABLE)
{
interleaveState->state[i] = true;
}
else
{
interleaveState->state[i] = false;
}
}
}
void AdcDrv_GetCmpCfg(AdcDrvType *obj, AdcDrv_CmpCfgType *currentConfig)
{
bool acfe = AdcReg_GetSc2Acfe(obj->adcReg);
bool acfgt = AdcReg_GetSc2AcFgt(obj->adcReg);
bool acren = AdcReg_GetSc2AcREn(obj->adcReg);
uint16_t cv1 = AdcReg_GetCv1Cv(obj->adcReg);
uint16_t cv2 = AdcReg_GetCv2Cv(obj->adcReg);
if(acfe == false)
{
currentConfig->cmpMode = ADCDRV_CMPMODE_NO_COMPARE;
currentConfig->lowerLim = 0;
currentConfig->upperLim = 0;
}
else
{
if(acfgt == false && acren == false)
{
currentConfig->cmpMode = ADCDRV_CMPMODE_LESSTHAN;
currentConfig->lowerLim = cv1;
currentConfig->upperLim = 0;
}
else if(acfgt == true && acren == false)
{
currentConfig->cmpMode = ADCDRV_CMPMODE_GREATER_OR_EQUTHAN;
currentConfig->lowerLim = cv1;
currentConfig->upperLim = 0;
}
else if(acfgt == false && acren == true && cv1 <= cv2)
{
currentConfig->cmpMode = ADCDRV_CMPMODE_OUTSIDE_EXCLUDE_BOUNDARIES;
currentConfig->lowerLim = cv1;
currentConfig->upperLim = cv2;
}
else if(acfgt == false && acren == true && cv1 > cv2)
{
currentConfig->cmpMode = ADCDRV_CMPMODE_INSIDE_EXCLUDE_BOUNDARIES;
currentConfig->lowerLim = cv2;
currentConfig->upperLim = cv1;
}
else if(acfgt == true && acren == true && cv1 <= cv2)
{
currentConfig->cmpMode = ADCDRV_CMPMODE_INSIDE_INCLUDE_BOUNDARIES;
currentConfig->lowerLim = cv1;
currentConfig->upperLim = cv2;
}
else if(acfgt == true && acren == true && cv1 > cv2)
{
currentConfig->cmpMode = ADCDRV_CMPMODE_OUTSIDE_INCLUDE_BOUNDARIES;
currentConfig->lowerLim = cv2;
currentConfig->upperLim = cv1;
}
}
}
void AdcDrv_CfgCompare(AdcDrvType *obj, const AdcDrv_CmpCfgType *userConfig)
{
switch(userConfig->cmpMode)
{
case(ADCDRV_CMPMODE_NO_COMPARE):
AdcReg_SetSc2Acfe(obj->adcReg, false);
break;
case(ADCDRV_CMPMODE_LESSTHAN):
AdcReg_SetSc2Acfe(obj->adcReg, true);
AdcReg_SetSc2AcFgt(obj->adcReg, false);
AdcReg_SetSc2AcREn(obj->adcReg, false);
AdcReg_SetCv1Cv(obj->adcReg, userConfig->lowerLim);
AdcReg_SetCv2Cv(obj->adcReg, 0u);
break;
case(ADCDRV_CMPMODE_GREATER_OR_EQUTHAN):
AdcReg_SetSc2Acfe(obj->adcReg, true);
AdcReg_SetSc2AcFgt(obj->adcReg, true);
AdcReg_SetSc2AcREn(obj->adcReg, false);
AdcReg_SetCv1Cv(obj->adcReg, userConfig->lowerLim);
AdcReg_SetCv2Cv(obj->adcReg, 0u);
break;
case(ADCDRV_CMPMODE_OUTSIDE_EXCLUDE_BOUNDARIES):
AdcReg_SetSc2Acfe(obj->adcReg, true);
AdcReg_SetSc2AcFgt(obj->adcReg, false);
AdcReg_SetSc2AcREn(obj->adcReg, true);
AdcReg_SetCv1Cv(obj->adcReg, userConfig->lowerLim);
AdcReg_SetCv2Cv(obj->adcReg, userConfig->upperLim);
break;
case(ADCDRV_CMPMODE_INSIDE_EXCLUDE_BOUNDARIES):
AdcReg_SetSc2Acfe(obj->adcReg, true);
AdcReg_SetSc2AcFgt(obj->adcReg, false);
AdcReg_SetSc2AcREn(obj->adcReg, true);
AdcReg_SetCv1Cv(obj->adcReg, userConfig->upperLim);
AdcReg_SetCv2Cv(obj->adcReg, userConfig->lowerLim);
break;
case(ADCDRV_CMPMODE_INSIDE_INCLUDE_BOUNDARIES):
AdcReg_SetSc2Acfe(obj->adcReg, true);
AdcReg_SetSc2AcFgt(obj->adcReg, true);
AdcReg_SetSc2AcREn(obj->adcReg, true);
AdcReg_SetCv1Cv(obj->adcReg, userConfig->lowerLim);
AdcReg_SetCv2Cv(obj->adcReg, userConfig->upperLim);
break;
case(ADCDRV_CMPMODE_OUTSIDE_INCLUDE_BOUNDARIES):
AdcReg_SetSc2Acfe(obj->adcReg, true);
AdcReg_SetSc2AcFgt(obj->adcReg, true);
AdcReg_SetSc2AcREn(obj->adcReg, true);
AdcReg_SetCv1Cv(obj->adcReg, userConfig->upperLim);
AdcReg_SetCv2Cv(obj->adcReg, userConfig->lowerLim);
break;
default:
/* Impossible case */
break;
}
}
void AdcDrv_Configure(AdcDrvType *obj, const AdcDrv_ConfigType *userConfig)
{
/* disable ADC first */
AdcReg_SetSc3AdcPD(obj->adcReg, ADCDRV_POWER_DOWN);
/* select the conversion conversionMode */
AdcReg_SetCfg1Mode(obj->adcReg, (uint8_t)userConfig->conversionMode);
/* select the ADC sample length */
AdcReg_SetCfg2LenSmpl(obj->adcReg, userConfig->sampleLen);
/* select the ADC sample length after the 1st cycle
* change the input channel select(ADCH) */
AdcReg_SetCfg2LenSmpl1st(obj->adcReg, userConfig->firstSampleLen);
/* select the ADC sample length after power on */
AdcReg_SetCfg2LenPwrOn(obj->adcReg, userConfig->pwrOnLen);
/* select ADC reference voltage */
AdcReg_SetSc2RefSel(obj->adcReg, (uint8_t)userConfig->refVolSel);
/* enable DMA */
AdcReg_SetSc2DmaEn(obj->adcReg, userConfig->dmaEnable);
/* select the conversion trigger source */
AdcReg_SetSc2AdTrg(obj->adcReg, (uint8_t)userConfig->trgSrcCfg.trgSrc);
/*! \note If ADCDRV_SW_TRIGGER is selected, hwTrgSrc, pretrgSrc, swPretrgSrc will be ignored.*/
if(obj->adcNumber == ADCDRV_INSTANCE_0)
{
/* select hardware trigger source */
SimReg_SetAdcTrg0Src(obj->simReg, (uint8_t)userConfig->trgSrcCfg.hwTrgSrc);
/* select software pretrigger source */
SimReg_SetAdcPreTrg0SwSrc(obj->simReg, (uint8_t)userConfig->trgSrcCfg.swPretrgSrc);
/* set pretrigger source */
SimReg_SetAdcPreTrg0Src(obj->simReg, (uint8_t)userConfig->trgSrcCfg.pretrgSrc);
}
else if(obj->adcNumber == ADCDRV_INSTANCE_1)
{
/* select hardware trigger source */
SimReg_SetAdcTrg1Src(obj->simReg, (uint8_t)userConfig->trgSrcCfg.hwTrgSrc);
/* select software pretrigger source */
SimReg_SetAdcPreTrg1SwSrc(obj->simReg, (uint8_t)userConfig->trgSrcCfg.swPretrgSrc);
/* select pretrigger source */
SimReg_SetAdcPreTrg1Src(obj->simReg, (uint8_t)userConfig->trgSrcCfg.pretrgSrc);
}
/* select the continuous / one shot conversion */
AdcReg_SetSc3Adco(obj->adcReg, (uint8_t)userConfig->continuousMode);
/* configure the ADC compare function */
AdcDrv_CfgCompare(obj, &(userConfig->cmpCfg));
/* enable hardware average sample */
AdcReg_SetSc3AvgE(obj->adcReg, userConfig->avgEnable);
if(userConfig->avgEnable)
{
/* select the hardware average sample number */
AdcReg_SetSc3AvgS(obj->adcReg, (uint8_t)userConfig->avgSamplesSel);
}
/* configure for each ADC channel */
uint8_t i;
for(i = 0; i < ADCDRV_CHANNEL_NUM; i++)
{
/* select the ADC channel input */
AdcReg_SetScAdCh(obj->adcReg, i, (uint8_t)userConfig->chnCfg[i].chnSel);
/* enable the interrupt for ADC channel */
AdcReg_SetScAIEn(obj->adcReg, i, userConfig->chnCfg[i].intEnable);
}
/* select interleave channel state */
AdcDrv_SetInterleave(obj, &(userConfig->interleaveMode));
/* enable ADC */
AdcReg_SetSc3AdcPD(obj->adcReg, ADCDRV_POWER_ON);
}
void AdcDrv_GetDefaultConfig(AdcDrv_ConfigType *userConfig)
{
uint8_t i = 0U;
userConfig->conversionMode = ADCDRV_CONVERSION_12BIT;
userConfig->sampleLen = ADC_LEN_SMPL_DEFAULT;
userConfig->firstSampleLen = ADC_LEN_SMPL_1ST_DEFAULT;
userConfig->pwrOnLen = ADC_LEN_PWR_ON_DEFAULT;
userConfig->refVolSel = ADCDRV_REFVOLT_VDDA;
userConfig->dmaEnable = false;
userConfig->cmpCfg.lowerLim = 0;
userConfig->cmpCfg.upperLim = 0;
userConfig->cmpCfg.cmpMode = ADCDRV_CMPMODE_NO_COMPARE;
userConfig->continuousMode = ADCDRV_ONESHOT;
userConfig->avgSamplesSel = ADCDRV_AVERAGE_4;
userConfig->avgEnable = true;
for(i = ADCDRV_INTERLEAVE_ADC0SE4_ADC1SE14; i < ADCDRV_INTERLEAVE_CHANNEL_NUMBER; i++)
{
userConfig->interleaveMode.state[i] = false;
}
/*! \note If ADCDRV_SW_TRIGGER is selected, hwTrgSrc, pretrgSrc, swPretrgSrc will be ignored.*/
userConfig->trgSrcCfg.trgSrc = ADCDRV_SW_TRIGGER;
userConfig->trgSrcCfg.hwTrgSrc = ADCDRV_HW_TRGSRC_PDB;
userConfig->trgSrcCfg.swPretrgSrc = ADCDRV_SWPRETRG_PRETRIGGER_0;
userConfig->trgSrcCfg.pretrgSrc = ADCDRV_PRETRG_PDB_PRETRIGGER;
for(i = 0; i < ADCDRV_CHANNEL_NUM; i++)
{
userConfig->chnCfg[i].chnSel = (AdcDrv_InChnType)i;
userConfig->chnCfg[i].intEnable = false;
}
}
void AdcDrv_SwTrg(AdcDrvType *obj)
{
AdcReg_SwTrig(obj->adcReg);
}
void AdcDrv_ClrLockTrg(AdcDrvType *obj)
{
AdcReg_ClrTrg(obj->adcReg);
}
uint16_t AdcDrv_GetRn(AdcDrvType *obj, uint8_t chn)
{
return (AdcReg_GetRData(obj->adcReg, (uint8_t)chn));
}
bool AdcDrv_GetCocon(AdcDrvType *obj, uint8_t chn)
{
if(AdcReg_GetScCoCo(obj->adcReg, (uint8_t)chn) > 0)
{
return (true);
}
else
{
return (false);
}
}
void AdcDrv_DisableAdc(AdcDrvType *obj)
{
AdcReg_SetSc3AdcPD(obj->adcReg, ADCDRV_POWER_DOWN);
}
void AdcDrv_EnableAdc(AdcDrvType *obj)
{
AdcReg_SetSc3AdcPD(obj->adcReg, ADCDRV_POWER_ON);
}
void AdcDrv_AbortChn(AdcDrvType *obj, uint8_t chn)
{
AdcReg_AbortChn(obj->adcReg, chn);
}
void AdcDrv_ConfigureChn(AdcDrvType *obj, uint8_t chn, AdcDrv_InChnType state)
{
AdcReg_SetScAdCh(obj->adcReg, chn, state);
}
void AdcDrv_GetConfig(AdcDrvType *obj, AdcDrv_ConfigType *currentConfig)
{
/* get the conversion conversionMode */
currentConfig->conversionMode = (AdcDrv_ConversionMode)AdcReg_GetCfg1Mode(obj->adcReg);
/* get the ADC sample length */
currentConfig->sampleLen = AdcReg_GetCfg2LenSmpl(obj->adcReg);
/* get the ADC sample length after the 1st cycle
* change the input channel select(ADCH) */
currentConfig->firstSampleLen = AdcReg_GetCfg2LenSmpl1st(obj->adcReg);
/* get the ADC sample length after power on */
currentConfig->pwrOnLen = AdcReg_GetCfg2LenPwrOn(obj->adcReg);
/* get ADC reference voltage */
currentConfig->refVolSel = (AdcDrv_RefVolt)AdcReg_GetSc2RefSel(obj->adcReg);
/* get enable DMA */
currentConfig->dmaEnable = AdcReg_GetSc2DmaEn(obj->adcReg);
/* get the conversion trigger source */
currentConfig->trgSrcCfg.trgSrc = (AdcDrv_TrgMode)AdcReg_GetSc2AdTrg(obj->adcReg);
/*! \note If ADCDRV_SW_TRIGGER is selected, hwTrgSrc, pretrgSrc, swPretrgSrc will be ignored.*/
if(obj->adcNumber == ADCDRV_INSTANCE_0)
{
/* get hardware trigger source */
currentConfig->trgSrcCfg.hwTrgSrc = (AdcDrv_HwTrgSrc)SimReg_GetAdcTrg0Src(obj->simReg);
/* get software pretrigger source */
currentConfig->trgSrcCfg.swPretrgSrc = (ADCDRV_SwPretrgSrc)SimReg_GetAdcPreTrg0SwSrc(obj->simReg);
/* get pretrigger source */
currentConfig->trgSrcCfg.pretrgSrc = (ADCDRV_PretrgSrc)SimReg_GetAdcPreTrg0Src(obj->simReg);
}
else if(obj->adcNumber == ADCDRV_INSTANCE_1)
{
/* get hardware trigger source */
currentConfig->trgSrcCfg.hwTrgSrc = (AdcDrv_HwTrgSrc)SimReg_GetAdcTrg1Src(obj->simReg);
/* get software pretrigger source */
currentConfig->trgSrcCfg.swPretrgSrc = (ADCDRV_SwPretrgSrc)SimReg_GetAdcPreTrg1SwSrc(obj->simReg);
/* get pretrigger source */
currentConfig->trgSrcCfg.pretrgSrc = (ADCDRV_PretrgSrc)SimReg_GetAdcPreTrg1Src(obj->simReg);
}
/* get the continuous mode */
currentConfig->continuousMode = (AdcDrv_ContinuousMode)AdcReg_GetSc3Adco(obj->adcReg);
/* get configuration the ADC compare function */
AdcDrv_GetCmpCfg(obj, &currentConfig->cmpCfg);
/* get hardware average sample configuration*/
currentConfig->avgEnable = AdcReg_GetSc3AvgE(obj->adcReg);
/* get the hardware average sample number */
currentConfig->avgSamplesSel = (AdcDrv_AverageMode)AdcReg_GetSc3AvgS(obj->adcReg);
/* get configuration for each ADC channel */
uint8_t i;
for(i = 0; i < ADCDRV_CHANNEL_NUM; i++)
{
/* get the ADC channel input */
currentConfig->chnCfg[i].chnSel = (AdcDrv_InChnType)AdcReg_GetScAdCh(obj->adcReg, i);
/* get the interrupt for ADC channel state*/
currentConfig->chnCfg[i].intEnable = AdcReg_GetScAIEn(obj->adcReg, i);
}
/* get interleave channel state */
AdcDrv_GetInterleave(obj, &(currentConfig->interleaveMode));
}

View File

@ -0,0 +1,398 @@
/*
* 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.
*/
#ifndef _ADC_DRV_H_
#define _ADC_DRV_H_
/*! \brief Contains public interface to various functions related
* to the driver of ADC (Analog-to-digital conversion)
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
/*! \addtogroup adc_drv
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
#define ADCDRV_CHANNEL_NUM (24)
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief ADC type of hardware average times selection
*/
typedef enum
{
ADCDRV_AVERAGE_4 = 0x0U, /*!< Hardware average of 4 samples.*/
ADCDRV_AVERAGE_8 = 0x1U, /*!< Hardware average of 8 samples.*/
ADCDRV_AVERAGE_16 = 0x2U, /*!< Hardware average of 16 samples.*/
ADCDRV_AVERAGE_32 = 0x3U, /*!< Hardware average of 32 samples.*/
} AdcDrv_AverageMode;
/*! \brief ADC type of self-test channel selection
*/
typedef enum
{
ADCDRV_SELF_TEST_VALUE_AVSS = 0x0U, /*!< ADC self-test channel select AVSS.*/
ADCDRV_SELF_TEST_VALUE_ONE_EIGHTH_AVSS = 0x1U, /*!< ADC self-test channel select 1/8*VREF.*/
ADCDRV_SELF_TEST_VALUE_HALF_AVSS = 0x2U, /*!< ADC self-test channel select 1/2*VREF.*/
ADCDRV_SELF_TEST_VALUE_SEVEN_EIGHTH_AVSS = 0x3U, /*!< ADC self-test channel select 7/8*VREF.*/
} AdcDrv_SelfTestValue;
/*! \brief ADC type of conversion trigger selection
*/
typedef enum
{
ADCDRV_SW_TRIGGER = 0x0U, /*!< Conversion trigger select software trigger.*/
ADCDRV_HW_TRIGGER = 0x1U, /*!< Conversion trigger select hardware trigger.*/
} AdcDrv_TrgMode;
/*! \brief ADC type of resolution selection
*/
typedef enum
{
ADCDRV_CONVERSION_8BIT = 0x0U, /*!< Selects the ADC resolution to 8-bit conversion.*/
ADCDRV_CONVERSION_12BIT = 0x1U, /*!< Selects the ADC resolution to 12-bit conversion.*/
ADCDRV_CONVERSION_10BIT = 0x2U, /*!< Selects the ADC resolution to 10-bit conversion.*/
ADCDRV_CONVERSION_12BIT_2 = 0x3U, /*!< Selects the ADC resolution to 12-bit conversion.*/
} AdcDrv_ConversionMode;
/*! \brief ADC type of VREF selection
*/
typedef enum
{
/*! \note If VDDA is selected, VDDA needs to be shorted with VREFH by hardware.*/
ADCDRV_REFVOLT_VDDA = 0x0U, /*!< ADC VREF select VDDA.*/
ADCDRV_REFVOLT_VREF = 0x1U, /*!< ADC VREF select external VREF.*/
} AdcDrv_RefVolt;
/*! \brief ADC type of compare mode
*/
typedef enum
{
ADCDRV_CMPMODE_NO_COMPARE = 0x0U, /*!< ADC disable compare function.*/
ADCDRV_CMPMODE_LESSTHAN = 0x1U, /*!< Automatic compare with interrupt for less-than.*/
ADCDRV_CMPMODE_GREATER_OR_EQUTHAN = 0x2U, /*!< Automatic compare with interrupt for greater-than or equal-to.*/
ADCDRV_CMPMODE_OUTSIDE_EXCLUDE_BOUNDARIES = 0x3U, /*!< Automatic compare with interrupt for out-of-range(Does not contain boundaries).*/
ADCDRV_CMPMODE_INSIDE_EXCLUDE_BOUNDARIES = 0x4U, /*!< Automatic compare with interrupt for within range(Does not contain boundaries).*/
ADCDRV_CMPMODE_INSIDE_INCLUDE_BOUNDARIES = 0x5U, /*!< Automatic compare with interrupt for within range(Contain boundaries).*/
ADCDRV_CMPMODE_OUTSIDE_INCLUDE_BOUNDARIES = 0x6U, /*!< Automatic compare with interrupt for out-of-range range(Contain boundaries).*/
} AdcDrv_CmpMode;
/*! \brief ADC type of input channel selection.
*/
typedef enum
{
ADCDRV_INCHN_EXT0 = 0x0U, /*!< External channel 0.*/
ADCDRV_INCHN_EXT1 = 0x1U, /*!< External channel 1.*/
ADCDRV_INCHN_EXT2 = 0x2U, /*!< External channel 2.*/
ADCDRV_INCHN_EXT3 = 0x3U, /*!< External channel 3.*/
ADCDRV_INCHN_EXT4 = 0x4U, /*!< External channel 4.*/
ADCDRV_INCHN_EXT5 = 0x5U, /*!< External channel 5.*/
ADCDRV_INCHN_EXT6 = 0x6U, /*!< External channel 6.*/
ADCDRV_INCHN_EXT7 = 0x7U, /*!< External channel 7.*/
ADCDRV_INCHN_EXT8 = 0x8U, /*!< External channel 8.*/
ADCDRV_INCHN_EXT9 = 0x9U, /*!< External channel 9.*/
ADCDRV_INCHN_EXT10 = 0xAU, /*!< External channel 10.*/
ADCDRV_INCHN_EXT11 = 0xBU, /*!< External channel 11.*/
ADCDRV_INCHN_EXT12 = 0xCU, /*!< External channel 12.*/
ADCDRV_INCHN_EXT13 = 0xDU, /*!< External channel 13.*/
ADCDRV_INCHN_EXT14 = 0xEU, /*!< External channel 14.*/
ADCDRV_INCHN_EXT15 = 0xFU, /*!< External channel 15.*/
ADCDRV_INCHN_EXT16 = 0x10U, /*!< External channel 16.*/
ADCDRV_INCHN_EXT17 = 0x11U, /*!< External channel 17.*/
ADCDRV_INCHN_EXT18 = 0x12U, /*!< External channel 18.*/
ADCDRV_INCHN_EXT19 = 0x13U, /*!< External channel 19.*/
ADCDRV_INCHN_EXT20 = 0x14U, /*!< External channel 20.*/
ADCDRV_INCHN_EXT21 = 0x15U, /*!< External channel 21.*/
ADCDRV_INCHN_EXT22 = 0x16U, /*!< External channel 22.*/
ADCDRV_INCHN_EXT23 = 0x17U, /*!< External channel 23.*/
ADCDRV_INCHN_LPVBG = 0x19U, /*!< LPVBG.*/
ADCDRV_INCHN_VBG = 0x1AU, /*!< VBG.*/
ADCDRV_INCHN_LDO_VOLT = 0x1BU, /*!< monitor_ldo_volt.*/
ADCDRV_INCHN_SUPPLY_VOLT = 0x1CU, /*!< monitor_supply_volt.*/
ADCDRV_INCHN_SELF_TEST_VOLTAGE = 0x1DU, /*!< selftest_volt.*/
ADCDRV_INCHN_DISABLE = 0x1FU, /*!< Module is disabled.*/
} AdcDrv_InChnType;
/*! \brief ADC type of continuous conversion mode selection.
*/
typedef enum
{
ADCDRV_ONESHOT = 0x0U, /*!< One conversion will be performed (or one set of conversions, if AVGE is set) after a conversion is initiated.*/
ADCDRV_CONTINUOUS = 0x1U, /*!< Continuous conversions will be performed (or continuous sets of conversions, if AVGE is set) after a conversion is initiated.*/
} AdcDrv_ContinuousMode;
/*! \brief ADC type of instance selection.
*/
typedef enum
{
ADCDRV_INSTANCE_0 = 0x0U, /*!< ADC instance 0.*/
ADCDRV_INSTANCE_1 = 0x1U, /*!< ADC instance 1.*/
} AdcDrv_InstanceNumber;
/*! \brief ADC type of interleave channel selection.
*/
typedef enum
{
ADCDRV_INTERLEAVE_ADC0SE4_ADC1SE14 = 0x0U, /*!< ADC0_SE4 and ADC1_SE14 channels are interleaved on PTB0 pin.*/
ADCDRV_INTERLEAVE_ADC0SE5_ADC1SE15 = 0x1U, /*!< ADC0_SE5 and ADC1_SE15 channels are interleaved on PTB1 pin.*/
ADCDRV_INTERLEAVE_ADC0SE8_ADC1SE8 = 0x2U, /*!< ADC1_SE8 and ADC0_SE8 channels are interleaved on PTB13 pin.*/
ADCDRV_INTERLEAVE_ADC0SE9_ADC1SE9 = 0x3U, /*!< ADC1_SE9 and ADC0_SE9 channels are interleaved on PTB14 pin.*/
ADCDRV_INTERLEAVE_CHANNEL_NUMBER = 0x4U, /*!< The number of ADC channels that can be interleaved.*/
} AdcDrv_InterleaveChannel;
/*! \brief ADC type of hardware trigger source selection.
*/
typedef enum
{
ADCDRV_HW_TRGSRC_PDB = 0x0U, /*!< Select PDB output for trigger source.*/
ADCDRV_HW_TRGSRC_TRGMUX = 0x1U, /*!< Select TRGMUX output output for trigger source.*/
} AdcDrv_HwTrgSrc;
/*! \brief ADC type of software pretrigger source selection.
*/
typedef enum
{
ADCDRV_SWPRETRG_PRETRIGGER_0 = 0x4U, /*!< Select PRETRIGGER_0 for software pretrigger sources.*/
ADCDRV_SWPRETRG_PRETRIGGER_1 = 0x5U, /*!< Select PRETRIGGER_1 for software pretrigger sources.*/
ADCDRV_SWPRETRG_PRETRIGGER_2 = 0x6U, /*!< Select PRETRIGGER_2 for software pretrigger sources.*/
ADCDRV_SWPRETRG_PRETRIGGER_3 = 0x7U, /*!< Select PRETRIGGER_3 for software pretrigger sources.*/
} ADCDRV_SwPretrgSrc;
/*! \brief ADC type of hardware pretrigger source selection.
*/
typedef enum
{
ADCDRV_PRETRG_PDB_PRETRIGGER = 0x0U, /*!< Select PDB pretrigger for ADC pretrigger sources.*/
ADCDRV_PRETRG_TRGMUX_PRETRIGGER = 0x1U, /*!< Select TRGMUX pretrigger for ADC pretrigger sources.*/
ADCDRV_PRETRG_SOFTWARE_PRETRIGGER = 0x2U, /*!< Select SOFTWARE pretrigger for ADC pretrigger sources.*/
} ADCDRV_PretrgSrc;
/*! \brief Initial parameters
*/
typedef struct _AdcDrv_InitParamsType_
{
AdcDrv_InstanceNumber adcNumber; /*!< ADC instance number*/
} AdcDrv_InitParamsType;
/*! \brief Definition of configuration of ADC trigger/pretrigger.
*/
typedef struct _AdcDrv_TrgSrcCfgType_
{
AdcDrv_TrgMode trgSrc; /*!< Conversion trigger select*/
AdcDrv_HwTrgSrc hwTrgSrc; /*!< Selects hardware trigger source for ADC.*/
ADCDRV_SwPretrgSrc swPretrgSrc; /*!< Selects software pretrigger sources for ADC*/
ADCDRV_PretrgSrc pretrgSrc; /*!< Selects pretrigger sources for ADC*/
} AdcDrv_TrgSrcCfgType;
/*! \brief Definition of configuration of ADC channel
*/
typedef struct _AdcDrv_ChnCfgType_
{
AdcDrv_InChnType chnSel; /*!< Input channel select.*/
bool intEnable; /*!< Interrupt enable.*/
} AdcDrv_ChnCfgType;
/*! \brief Definition of configuration of ADC compare function
*/
typedef struct _AdcDrv_CmpCfgType_
{
uint16_t lowerLim; /*!< Lower limiting value in ADC compare function.*/
uint16_t upperLim; /*!< Upper limiting value in ADC compare function.*/
AdcDrv_CmpMode cmpMode; /*!< Select compare mode.*/
} AdcDrv_CmpCfgType;
/*! \brief Definition of configuration of ADC interleave channel
*/
typedef struct _AdcDrv_InterleaveType_
{
bool state[ADCDRV_INTERLEAVE_CHANNEL_NUMBER]; /*!< Selects each ADC channel interleave state.*/
} AdcDrv_InterleaveType;
/*! \brief Definition of configuration of ADC driver
*/
typedef struct _AdcDrv_ConfigType_
{
AdcDrv_ConversionMode conversionMode; /*!< Conversion mode select.*/
uint8_t sampleLen; /*!< ADC sampling time.*/
uint8_t firstSampleLen; /*!< First sample delay time.*/
uint8_t pwrOnLen; /*!< Power on sample delay time.*/
AdcDrv_RefVolt refVolSel; /*!< ADC VREF Select.*/
bool dmaEnable; /*!< Switch DMA enable.*/
AdcDrv_CmpCfgType cmpCfg; /*!< Compare function configuration*/
AdcDrv_ContinuousMode continuousMode; /*!< Switch continuous conversion enable*/
AdcDrv_AverageMode avgSamplesSel; /*!< Hardware average select*/
bool avgEnable; /*!< Switch hardware average enable*/
AdcDrv_ChnCfgType chnCfg[ADCDRV_CHANNEL_NUM]; /*!< ADC channel configuration*/
AdcDrv_InterleaveType interleaveMode; /*!< ADC interleave channel configuration*/
AdcDrv_TrgSrcCfgType trgSrcCfg; /*!< ADC trigger source configuration*/
} AdcDrv_ConfigType;
/* Forward declaration of ADC register */
struct _AdcRegType_;
/* Forward declaration of SIm register */
struct _SimRegType_;
/*! \brief The definition of ADC driver class
*/
typedef struct _AdcDrvType_
{
struct _AdcRegType_ *adcReg;
struct _SimRegType_ *simReg;
AdcDrv_InstanceNumber adcNumber;
} AdcDrvType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initializes the ADC driver module
*
* This function initializes ADC driver by setting the register
* instance to it.
*
* \param[in] obj : pointer to ADC driver instance
* \param[in] pdbReg : pointer to ADC register instance
* \param[in] simReg : pointer to SIM register instance
* \param[in] initParams : pointer to ADC initialization parameters
*/
extern void AdcDrv_Init(AdcDrvType *obj, struct _AdcRegType_ *adcReg, struct _SimRegType_ *simReg, const AdcDrv_InitParamsType *initParams);
/*! \brief Get default configures the ADC module for configuration structure
*
* This function gets default configures the ADC module for user configuration structure
*
* \param[out] userConfig : pointer to configuration structure
*/
extern void AdcDrv_GetDefaultConfig(AdcDrv_ConfigType *userConfig);
/*! \brief Configures the ADC module from a user configuration structure
*
* This function configures the ADC module from a user configuration structure
*
* \param[in] obj : pointer to ADC driver instance
* \param[in] userConfig : pointer to configuration structure
*/
extern void AdcDrv_Configure(AdcDrvType *obj, const AdcDrv_ConfigType *userConfig);
/*! \brief Get configures of the ADC module
*
* This function get configures of the ADC module
*
* \param[in] obj : pointer to ADC driver instance
* \param[out] currentConfig : pointer to configuration structure
*/
extern void AdcDrv_GetConfig(AdcDrvType *obj, AdcDrv_ConfigType *currentConfig);
/*! \brief ADC clear lock trigger
*
* This function for ADC clear lock trigger
*
* \param[in] obj : pointer to ADC driver instance
*/
extern void AdcDrv_ClrLockTrg(AdcDrvType *obj);
/*! \brief ADC software trigger
*
* This function for ADC clear lock trigger
*
* \param[in] obj : pointer to ADC driver instance
*/
extern void AdcDrv_SwTrg(AdcDrvType *obj);
/*! \brief Get ADC data result
*
* This function for get ADC data result
*
* \param[in] obj : pointer to ADC driver instance
* \param[in] chn : channel number
* \return ADC data result.
*/
extern uint16_t AdcDrv_GetRn(AdcDrvType *obj, uint8_t chn);
/*! \brief Get ADC conversion complete flag
*
* This function for get ADC conversion complete flag.
*
* \param[in] obj : pointer to ADC driver instance
* \param[in] chn : channel number
* \return ADC data result.
*/
extern bool AdcDrv_GetCocon(AdcDrvType *obj, uint8_t chn);
/*! \brief Disable ADC
*
* This function for disable ADC
*
* \param[in] obj : pointer to ADC driver instance
*/
extern void AdcDrv_DisableAdc(AdcDrvType *obj);
/*! \brief Enable ADC
*
* This function for enable ADC
*
* \param[in] obj : pointer to ADC driver instance
*/
extern void AdcDrv_EnableAdc(AdcDrvType *obj);
/*! \brief Abort ADC channel n
*
* This function for abort ADC channel n
*
* \param[in] obj : pointer to ADC driver instance
* \param[in] chn : channel number
*/
extern void AdcDrv_AbortChn(AdcDrvType *obj, uint8_t chn);
/*! \brief Selects one of the input channels.
*
* This function for selects one of the input channels.
*
* \param[in] obj : pointer to ADC driver instance
* \param[in] chn : channel number
* \param[in] state : input channel selection.
*/
extern void AdcDrv_ConfigureChn(AdcDrvType *obj, uint8_t chn, AdcDrv_InChnType state);
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _ADC_DRV_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,266 @@
/*
* 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.
*/
#ifndef _CLOCK_DRV_H_
#define _CLOCK_DRV_H_
/*! \brief Contains public interface to various functions related
* to the driver of Clock
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
/*! \addtogroup clock_drv
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/* TCLK clock number */
#define TCLK_INPUTS_NUM (3U)
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Definition of Clock names.
*/
typedef enum
{
/* Source clocks */
CLOCKDRV_SOSC = 0, /* system crystal oscillator clock*/
CLOCKDRV_SIRC, /* slow internal reference clock */
CLOCKDRV_FIRC, /* fast internal reference clock */
CLOCKDRV_PLL, /* PLL clock */
CLOCKDRV_SOSC_DIV1, /* SOSC_DIV1 clock */
CLOCKDRV_SOSC_DIV2, /* SOSC_DIV2 clock */
CLOCKDRV_SIRC_DIV1, /* SIRC_DIV1 clock */
CLOCKDRV_SIRC_DIV2, /* SIRC_DIV2 clock */
CLOCKDRV_FIRC_DIV1, /* FIRC_DIV1 clock */
CLOCKDRV_FIRC_DIV2, /* FIRC_DIV2 clock */
CLOCKDRV_PLL_DIV1, /* PLL_DIV1 clock */
CLOCKDRV_PLL_DIV2, /* PLL_DIV2 clock */
CLOCKDRV_SYS, /* system clock */
CLOCKDRV_CORE, /* core clock */
CLOCKDRV_APB, /* bus clock */
CLOCKDRV_FLS, /* flash clock */
CLOCKDRV_TRACE, /* trace clock */
CLOCKDRV_CLKOUT, /* CLKOUT clock */
CLOCKDRV_RTC_PADIN, /* RTC pad input clock */
CLOCKDRV_LPO_1K, /* LPO 1KHz clock */
CLOCKDRV_LPO_32K, /* LPO 32KHz clock */
CLOCKDRV_LPO_128K, /* LPO 128KHz clock */
/* Always-on clocks */
CLOCKDRV_RTC, /* RTC source clock, it's also used for other modules */
CLOCKDRV_EXT_FLT, /* External Reset pin digital Filter clock */
CLOCKDRV_LPIT, /* LPIT clock */
CLOCKDRV_LPTMR, /* LPTMR clock */
CLOCKDRV_RTC_CNT, /* RTC module clock for counter */
CLOCKDRV_PORTA_FLT, /* PORTA digital filter clock */
CLOCKDRV_PORTB_FLT, /* PORTB digital filter clock */
CLOCKDRV_PORTC_FLT, /* PORTC digital filter clock */
CLOCKDRV_PORTD_FLT, /* PORTD digital filter clock */
CLOCKDRV_PORTE_FLT, /* PORTE digital filter clock */
CLOCKDRV_PORTA, /* PORTA clock */
CLOCKDRV_PORTB, /* PORTB clock */
CLOCKDRV_PORTC, /* PORTC clock */
CLOCKDRV_PORTD, /* PORTD clock */
CLOCKDRV_PORTE, /* PORTE clock */
CLOCKDRV_CMP0, /* CMP clock */
/* Peripheral clocks */
CLOCKDRV_DMA, /* DMA clock */
CLOCKDRV_EIM, /* EIM clock */
CLOCKDRV_ERM, /* ERM clock */
CLOCKDRV_MPU, /* MPU clock */
CLOCKDRV_CRC, /* CRC clock */
CLOCKDRV_CSE, /* CSE clock */
CLOCKDRV_MFT0, /* MFT0 input clock, please note this is not MFT functional clock */
CLOCKDRV_MFT1, /* MFT1 input clock, please note this is not MFT functional clock */
CLOCKDRV_MFT2, /* MFT2 input clock, please note this is not MFT functional clock */
CLOCKDRV_MFT3, /* MFT3 input clock, please note this is not MFT functional clock */
CLOCKDRV_MFT4, /* MFT4 input clock, please note this is not MFT functional clock */
CLOCKDRV_MFT5, /* MFT5 input clock, please note this is not MFT functional clock */
CLOCKDRV_MSCM, /* MSCM clock */
CLOCKDRV_DMA_MUX, /* DMA_MUX clock */
CLOCKDRV_PDB0, /* PDB0 clock */
CLOCKDRV_PDB1, /* PDB1 clock */
CLOCKDRV_PWMLITE0, /* PWM_LITE0 clock */
CLOCKDRV_PWMLITE1, /* PWM_LITE1 clock */
CLOCKDRV_PWMLITE2, /* PWM_LITE2 clock */
CLOCKDRV_PWMLITE3, /* PWM_LITE3 clock */
CLOCKDRV_PWMLITE4, /* PWM_LITE4 clock */
CLOCKDRV_PRNG, /* PRNG clock */
CLOCKDRV_CMUS, /* CMUS clock */
CLOCKDRV_CMUF, /* CMUF clock */
CLOCKDRV_FCCU, /* FCCU clock */
CLOCKDRV_CMUP, /* CMUP clock */
CLOCKDRV_I2C, /* I2C clock */
CLOCKDRV_SPI0, /* SPI0 clock */
CLOCKDRV_SPI1, /* SPI1 clock */
CLOCKDRV_SPI2, /* SPI2 clock */
CLOCKDRV_SPI3, /* SPI3 clock */
CLOCKDRV_UART0, /* UART0 clock */
CLOCKDRV_UART1, /* UART1 clock */
CLOCKDRV_UART2, /* UART2 clock */
CLOCKDRV_UART3, /* UART3 clock */
CLOCKDRV_I2SM, /* I2S Mater clock */
CLOCKDRV_I2SS, /* I2S Slave clock */
CLOCKDRV_ADC0, /* ADC0 clock */
CLOCKDRV_ADC1, /* ADC1 clock */
CLOCKDRV_TCLK0, /* TCLK0 clock */
CLOCKDRV_TCLK1, /* TCLK1 clock */
CLOCKDRV_TCLK2, /* TCLK2 clock */
CLOCKDRV_EXT_MFT0, /* EXT_MFT0 clock */
CLOCKDRV_EXT_MFT1, /* EXT_MFT1 clock */
CLOCKDRV_EXT_MFT2, /* EXT_MFT2 clock */
CLOCKDRV_EXT_MFT3, /* EXT_MFT3 clock */
CLOCKDRV_EXT_MFT4, /* EXT_MFT4 clock */
CLOCKDRV_EXT_MFT5, /* EXT_MFT5 clock */
CLOCKDRV_EWM, /* EWM clock */
CLOCKDRV_CLOCK_NUM
} ClockDrv_NamesType;
/*! \brief module clock configuration.
*/
typedef struct _ClockDrv_ModuleClkConfigType_
{
bool gating; /*!< Clock gating. */
ClockDrv_NamesType source; /*!< Clock source input (some modules don't have protocol clock) */
uint16_t mult; /*!< Multiplier (some modules don't have fractional) */
uint16_t div; /*!< Divider (some modules don't have divider) */
/* Only PLL clock has following configures */
struct
{
uint32_t fblSel; /*!< feedback clock divider pre-scaler */
uint32_t preDiv; /*!< pre-divider */
uint32_t postDiv; /*!< post-divider */
} pllConfig; /*!< PLL related config */
} ClockDrv_ModuleClkConfigType;
/*! \brief Initial parameters
*/
typedef struct _ClockDrv_InitParamsType_
{
uint32_t fircFreq; /*!< FIRC frequency */
uint32_t sircFreq; /*!< SIRC frequency */
uint32_t xtalClkFreq; /*!< XTAL clock frequency. */
uint32_t rtcClkInFreq; /*!< RTC_CLKIN clock frequency. */
uint32_t tclkFreq[TCLK_INPUTS_NUM]; /*!< TCLKx clocks */
} ClockDrv_InitParamsType;
/* Forward declaration of related register */
struct _AcgRegType_;
struct _ApcRegType_;
struct _ScgRegType_;
struct _PccRegType_;
/*! \brief The definition of LPIT driver class
*/
typedef struct _ClockDrvType_
{
struct _AcgRegType_ *acgReg; /*!< pointer to RCSM register */
struct _ApcRegType_ *apcReg; /*!< pointer to RCSM register */
struct _ScgRegType_ *scgReg; /*!< pointer to SCG register */
struct _PccRegType_ *pccReg; /*!< pointer to PCC register */
uint32_t fircFreq; /*!< FIRC frequency */
uint32_t sircFreq; /*!< SIRC frequency */
uint32_t xtalClkFreq; /*!< XTAL clock frequency */
uint32_t rtcClkInFreq; /*!< RTC_CLKIN clock frequency */
uint32_t tclkFreq[TCLK_INPUTS_NUM]; /*!< TCLKx clocks */
} ClockDrvType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initializes the Clock driver module
*
* This function initializes Clock driver by setting the register
* instances to it.
*
* \param[in] obj : pointer to Clock driver instance
* \param[in] rcsmReg : pointer to RCSM register instance
* \param[in] scgReg : pointer to SCG register instance
* \param[in] pccReg : pointer to PCC register instance
* \param[in] initParams : pointer to clock initialization parameters
*/
extern void ClockDrv_Init(ClockDrvType *obj,
struct _AcgRegType_ *acgReg,
struct _ApcRegType_ *apcReg,
struct _ScgRegType_ *scgReg,
struct _PccRegType_ *pccReg,
const ClockDrv_InitParamsType *initParams);
/*! \brief Gets the clock frequency for a specific clock name.
*
* This function checks the current clock configurations and then calculates
* the clock frequency for a specific clock name defined in ClockDrv_NamesType.
* Clock modules must be properly configured before using this function.
* If it cannot find the clock name or the clock is not enabled or
* it's not configured properly, it returns false.
*
* \note If return false, don't trust the value of out parameter "frequency"
* even if it's changed.
*
* \param[in] obj : pointer to Clock driver instance
* \param[in] clockName : Clock names defined
* \param[out] frequency : clock frequency value in Hertz
* \return The result of the operation
* - false : Failed to get the frequency
* - true : Success
*/
extern bool ClockDrv_GetFreq(const ClockDrvType *obj, ClockDrv_NamesType clockName, uint32_t *frequency);
/*! \brief Configures module clock
*
* This function configures a module clock according to the configuration.
*
* \note If the target clock do not have mul or div, the corresponding configuration in
* moduleClkConfig will be ignored.
*
* \param[in] obj : pointer to Clock driver instance
* \param[in] clockName : Clock name of the configured module clock
* \param[in] moduleClkConfig : Pointer to the configuration structure.
* \return The result of the operation
* - false : configure failed
* - true : success
*/
extern bool ClockDrv_ConfigureClock(ClockDrvType *obj, ClockDrv_NamesType clockName, const ClockDrv_ModuleClkConfigType *moduleClkConfig);
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _CLOCK_DRV_H_ */

Some files were not shown because too many files have changed in this diff Show More