This commit is contained in:
sunbeam 2024-12-26 15:39:22 +08:00
parent 947ad91fc8
commit f727f66c55
308 changed files with 118309 additions and 7882 deletions

View File

@ -5,28 +5,25 @@ mainForm.add(
btnConnect={cls="button";text="连接";left=204;top=64;right=289;bottom=90;z=4};
btnFlash={cls="button";text="开始刷写";left=37;top=315;right=136;bottom=343;z=9};
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};
btnOpen={cls="button";text="打开文件";left=184;top=222;right=283;bottom=250;z=8};
btnReadF180={cls="button";text="读取boot版本";left=37;top=415;right=136;bottom=443;z=19};
btnReadF186={cls="button";text="读取当前会话";left=37;top=349;right=136;bottom=377;z=13};
btnReadF187={cls="button";text="读取型号";left=149;top=416;right=248;bottom=444;z=20};
btnReadF191={cls="button";text="读取编译日期";left=149;top=347;right=248;bottom=375;z=25};
btnReadF191={cls="button";text="读取编译日期";left=149;top=347;right=248;bottom=375;z=22};
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};
btnTest={cls="button";text="停止";left=149;top=316;right=248;bottom=344;z=11};
cbbChannel={cls="combobox";left=58;top=64;right=191;bottom=90;edge=1;items={};mode="dropdown";z=3};
cbbDev={cls="combobox";left=58;top=27;right=191;bottom=53;edge=1;items={};mode="dropdown";z=1};
checkbox={cls="checkbox";text="CANFD设备";left=151;top=101;right=248;bottom=120;checked=1;z=21};
edFile={cls="richedit";left=8;top=131;right=288;bottom=187;border=1;disabled=1;edge=1;multiline=1;wrap=1;z=14};
edFile2={cls="richedit";left=8;top=213;right=288;bottom=269;border=1;disabled=1;edge=1;multiline=1;wrap=1;z=22};
edFile={cls="richedit";left=8;top=131;right=288;bottom=214;border=1;disabled=1;edge=1;multiline=1;wrap=1;z=14};
edit={cls="edit";left=294;top=19;right=596;bottom=401;autovscroll=false;edge=1;multiline=1;vscroll=1;z=5};
progress={cls="progress";left=296;top=436;right=596;bottom=464;edge=1;max=100;min=0;z=15};
static={cls="static";text="设备";left=1;top=28;right=61;bottom=52;align="center";center=1;transparent=1;z=6};
static2={cls="static";text="通道";left=1;top=66;right=61;bottom=90;align="center";center=1;transparent=1;z=7};
static3={cls="static";text="刷写进度";left=296;top=409;right=349;bottom=429;transparent=1;z=16};
static4={cls="static";text="烧录APP";left=13;top=108;right=85;bottom=132;center=1;transparent=1;z=17};
static5={cls="static";text="V0.1_20220518";left=451;top=1;right=595;bottom=17;align="right";center=1;transparent=1;z=18};
static6={cls="static";text="FlashDriver";left=13;top=195;right=101;bottom=218;transparent=1;z=23}
static5={cls="static";text="V0.1_20220518";left=451;top=1;right=595;bottom=17;align="right";center=1;transparent=1;z=18}
)
/*}}*/
@ -186,10 +183,7 @@ mainForm.btnFlash.oncommand = function(id,event){
Display("请打开烧写文件");
return;
}
if(io.exist(mainForm.edFile2.text) == null){
Display("请打开flashdriver文件");
return;
}
if(flag_connected == 0){
Display("请连接设备");
return;
@ -233,9 +227,6 @@ mainForm.btnReadF187.oncommand = function(id,event){
DiagReadDID(0xF187);
}
mainForm.btnOpenFlashdrv.oncommand = function(id,event){
::PostThreadMessage(thrdId,104,1,0)//自定义消息-打开flashdriver
}

View File

@ -43,19 +43,19 @@ FuncLoopMsg = function(msg){
case 104 {//打开s19文件
if(msg.wParam == 1){
FuncDisplay("打开FlashDriver");
var ret = FuncOpenS19File(msg.wParam);
var ret = FuncOpenS19File(2);
if(ret != null){
thread.command.$ShowFlashDrvPath(ret);
var crc32 = FuncGetFlashCRC(1);
var crc32 = FuncGetFlashCRC(2);
FuncDisplay("CRC = " ++ string.format("%X",crc32));
}
}
else {
FuncDisplay("打开烧写文件");
var ret = FuncOpenS19File(msg.wParam);
var ret = FuncOpenS19File(1);
if(ret != null){
thread.command.$ShowPath(ret);
var crc32 = FuncGetFlashCRC(2);
var crc32 = FuncGetFlashCRC(1);
FuncDisplay("CRC = " ++ string.format("%X",crc32));
}
}

View File

@ -8,7 +8,7 @@ FuncReq34 = function(addr,len){
FuncPushPackage(DiagReqID,table.slice(data,5));
}
var maxlen = 0;
var maxlen = 0x402;
//接收
FuncDiag34Pro = function(data){
//console.dumpJson(data);

View File

@ -91,9 +91,11 @@ FuncSendBlockInit = function(id){
return 1;
}
for(i=1;#alldata;1){
len += math.ceil(#alldata[i]["data"] / FuncGetSengLen())
len += math.ceil(#alldata[i]["data"])
}
alldata_blocknum = len;
alldata_blocknum = len / FuncGetSengLen();
FuncDisplay("len="++len);
FuncDisplay("FuncGetSengLen="++FuncGetSengLen());
block_sended = 0;
sendblockstate = 0;
FuncSendBlockApp_sendflag = 0;
@ -357,25 +359,25 @@ FuncBootSeq = function(){
}
case 12 {
if(sendstate == 0){//发送数据
FuncSendBlockInit(1);
FuncDisplay("开始发送FlashDrv数据");
//FuncSendBlockInit(1);
//FuncDisplay("开始发送FlashDrv数据");
FuncClearState();
}
else {
var ret = FuncSendBlockApp();
nextstate(ret);
//var ret = FuncSendBlockApp();
nextstate(0);
}
}
case 13 {
if(sendstate == 0){//CheckLogicBlock
var addr,len,crc = FuncGetFlashAddrLenCRC(1);
FuncReq31CheckLogicBlock(addr,len,crc);
//var addr,len,crc = FuncGetFlashAddrLenCRC(1);
//FuncReq31CheckLogicBlock(addr,len,crc);
//FuncReq3101FD02();
FuncClearState();
}
else {
var ret = FuncWait(0x31);
nextstate(ret);
//var ret = FuncWait(0x31);
nextstate(0);
}
}
case 14 {
@ -401,7 +403,7 @@ FuncBootSeq = function(){
case 16 {
if(sendstate == 0){//发送数据
FuncSendBlockInit(2);
FuncSendBlockInit(1);
FuncDisplay("开始发送App数据");
FuncClearState();
}
@ -413,7 +415,7 @@ FuncBootSeq = function(){
case 17 {
if(sendstate == 0){//CheckLogicBlock
//FuncReq3101FD03();
var addr,len,crc = FuncGetFlashAddrLenCRC(2);
var addr,len,crc = FuncGetFlashAddrLenCRC(1);
FuncReq31CheckLogicBlock(addr,len,crc);
FuncClearState();
}

23
cva_asw_m0128/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,23 @@
{
"files.associations": {
"hwctrl.h": "c"
},
"MicroPython.executeButton": [
{
"text": "▶",
"tooltip": "运行",
"alignment": "left",
"command": "extension.executeFile",
"priority": 3.5
}
],
"MicroPython.syncButton": [
{
"text": "$(sync)",
"tooltip": "同步",
"alignment": "left",
"command": "extension.execute",
"priority": 4
}
]
}

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,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 _IMEFE_H_
#define _IMEFE_H_
/*! \brief Contains public interface to various functions related
* to the Induction Motor Enhance Flux Estimator (IMEFE) object.
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include "common/iqmath/iqmath.h"
#include "common/filter/iir_fo.h"
#include "common/pid/pid.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines all the parameters used to initialize IMEFE object
*/
typedef struct _Imefe_ParamsType_
{
float Rs_ohm; /*!< Stator resistance (ohm) */
float Rr_ohm; /*!< Rotor resistance (ohm) */
float Ls_H; /*!< Stator inductance (H) */
float Lr_H; /*!< Rotor inductance (H) */
float Lm_H; /*!< Magnetizing inductance (H) */
float IBase_A; /*!< Base phase current (amp) */
float VBase_V; /*!< Base phase voltage (volt) */
float fBase_Hz; /*!< Base value of frequency used for P.U. */
float phaseCalcFreq_kHz; /*!< Frequency to run phase calculation */
float responseSpeed_rps; /*!< The response speed in rad/s */
float spdCalcFreq_kHz; /*!< Frequency to run phase calculation */
float spdFilterPole_rps; /*!< Pole value of speed filter calculation */
float gain; /*!< Controller Gain (0.0 to 0.9999) */
float linearError; /*!< Controller Max allowed linear error (0.0 to 0.9999) */
} Imefe_ParamsType;
/*! \brief Defines the IMEFE object
*/
typedef struct _ImefeType_
{
_iq Ialpha; /*!< Input: The stationary d-axis stator current */
_iq Ibeta; /*!< Input: The stationary q-axis stator current */
_iq Valpha; /*!< Input: The stationary d-axis stator voltage */
_iq Vbeta; /*!< Input: The stationary q-axis stator voltage */
_iq emfAs; /*!< Internal Variable: The stationary d-axis emf */
_iq emfBs; /*!< Internal Variable: The stationary q-axis emf */
_iq psiAs; /*!< Internal Variable: The stationary d-axis psi */
_iq psiBs; /*!< Internal Variable: The stationary q-axis psi */
_iq psiAr; /*!< Internal Variable: The stationary d-axis psi */
_iq psiBr; /*!< Internal Variable: The stationary q-axis psi */
_iq gain1; /*!< Parameter: Motor dependent control gain */
_iq sigma1; /*!< Parameter: Motor dependent control gain */
_iq gain2; /*!< Parameter: Motor dependent control gain */
_iq sigma2; /*!< Parameter: Motor dependent control gain */
_iq Rs; /*!< Parameter: Motor dependent control gain */
_iq model; /*!< Parameter: Motor dependent control gain */
_iq gain3; /*!< Parameter: Motor dependent control gain */
_iq gain4; /*!< Parameter: Motor dependent control gain */
_iq gain5; /*!< Parameter: Motor dependent control gain */
_iq factor; /*!< Parameter: Motor dependent control gain */
_iq maxErr; /*!< Parameter: Motor dependent control max Error */
IirFoType lpfFlx; /*!< Internal Variable: The filter for electric flux calculation */
IirFoType lpfSpd; /*!< Internal Variable: The filter for electric speed calculation */
PidType pidVAs; /*!< Internal Variable: The Stationary d-axis stator voltage PID */
PidType pidVBs; /*!< Internal Variable: The Stationary q-axis stator voltage PID */
PidType pidPLL; /*!< Internal Variable: The PLL PID */
_iq rawSpeed_pu; /*!< Internal variable: The raw speed before filter in P.U. */
_iq rawWslip_pu; /*!< Internal variable: The raw slip speed before filter in P.U. */
_iq angle_pu; /*!< Output: The electric angle */
_iq speed_pu; /*!< Output: The filtered electric speed updated every electric period */
} ImefeType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the IMEFE object
*
* This function initalizes IMEFE by setting configuration parameters
*
* \param[in] obj : pointer to IMEFE instance
* \param[in] pParams : pointer to IMEFE configuration parameters
*/
extern int32_t Imefe_Init(ImefeType *obj, const Imefe_ParamsType *pParams);
/*! \brief Run the Angle Compensation
*
* This function runs IMEFE function, calculates Angle compensation value
*
* \param[in] obj : pointer to IMEFE instance
*/
extern int32_t Imefe_Run(ImefeType *obj);
/*! \brief Calculate the speed
* \note Might run slower than current control frequency
*
*
* \param[in] obj : pointer to IMEFE instance
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Imefe_CalcSpeed(ImefeType *obj);
/*! \brief Reset the IMEFE object
*
* This function resets the IMEFE relevant calculation parameters
*
* \param[in] obj : pointer to IMEFE instance
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Imefe_Reset(ImefeType *obj);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _IMEFE_H_ */

View File

@ -0,0 +1,39 @@
/*
* 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 "angle_comp.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void AngleComp_Init(AngleCompType *obj, const AngleComp_ParamsType *pParams)
{
obj->runFreq_kHz = pParams->runFreq_kHz;
obj->compFactor = _IQ(pParams->fBase_Hz * 0.001 / pParams->runFreq_kHz * pParams->delayCompFactor);
}

View File

@ -0,0 +1,117 @@
/*
* 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 _ANGLE_COMP_H_
#define _ANGLE_COMP_H_
/*! \brief Contains public interface to various functions related
* to the Angle Compensation (ANGLE_COMP) 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 ANGLE_COMP object
*/
typedef struct _AngleComp_ParamsType_
{
float runFreq_kHz; /*!< the frequency of running current loop in kHz */
float fBase_Hz; /*!< Base value of frequency used for P.U. */
float delayCompFactor; /*!< The factor used to compensate the delay caused by PWM generation. */
} AngleComp_ParamsType;
/*! \brief Defines the ANGLE_COMP object
*/
typedef struct _AngleCompType_
{
_iq speed_pu; /*!< Input: the electrical speed in P.U. */
_iq angleUncomp_pu; /*!< Input: the angle before compensation in P.U. */
_iq compFactor; /*!< Internal variable: The factor used to calculate delta angle */
float runFreq_kHz; /*!< Internal variable: The frequency of running current loop in kHz */
_iq angleComp_pu; /*!< Output: the angle after compensation in P.U. */
} AngleCompType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the ANGLE_COMP object
*
* This function initalizes ANGLE_COMP by setting configuration parameters
*
* \param[in] obj : pointer to Angle_Comp instance
* \param[in] pParams : pointer to Angle_Comp configuration parameters
*/
extern void AngleComp_Init(AngleCompType *obj, const AngleComp_ParamsType *pParams);
/*! \brief Run the Angle Compensation
*
* This function runs Angle_Comp function, calculates Angle compensation value
*
* \param[in] obj : pointer to Angle_Comp instance
*/
static inline void AngleComp_Run(AngleCompType *obj)
{
_iq angleTmp_pu = obj->angleUncomp_pu + _IQmpy(obj->compFactor, obj->speed_pu);
angleTmp_pu = _IQfrac(angleTmp_pu); /* get the fraction part */
if(angleTmp_pu < 0)
{
angleTmp_pu += _IQ(1.0);
}
obj->angleComp_pu = angleTmp_pu;
}
/*! \brief Update the Angle Compensation configuration parameters
*
* This function updates the Angle_Comp function configuration parameters
*
* \param[in] obj : pointer to Angle_Comp instance
* \param[in] runFreq_kHz : the frequency of running current loop
*/
static inline void AngleComp_UpdateParams(AngleCompType *obj, float runFreq_kHz)
{
obj->compFactor = _IQmpy(obj->compFactor, _IQ(obj->runFreq_kHz / runFreq_kHz));
obj->runFreq_kHz = runFreq_kHz;
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _ANGLE_COMP_H_ */

View File

@ -0,0 +1,39 @@
/*
* 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 "zero_offset.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void ZeroOffset_Init(ZeroOffsetType *obj, const ZeroOffset_ParamsType *pParams)
{
obj->scale = _IQ(pParams->delay_us * pParams->fBase_Hz / 1000000);
obj->offset = -_IQmpy(obj->scale, _IQ(pParams->calibBaseOnSpd_Hz / pParams->fBase_Hz));
}

View File

@ -0,0 +1,104 @@
/*
* 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 _ZERO_OFFSET_H_
#define _ZERO_OFFSET_H_
/*! \brief Contains public interface to various functions related
* to the Zero angle Offset (ZERO_OFFSET) 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 ZERO_OFFSET object
*/
typedef struct _ZeroOffset_ParamsType_
{
float calibBaseOnSpd_Hz; /*!< calibrate zero position base on speed in Hz */
float fBase_Hz; /*!< Base value of frequency used for P.U. */
float delay_us; /*!< The delay time for the current in */
} ZeroOffset_ParamsType;
/*! \brief Defines the ANGLE_COMP object
*/
typedef struct _ZeroOffsetType_
{
_iq speed_pu; /*!< Input: the electrical speed in P.U. */
_iq angleUncomp_pu; /*!< Input: the angle before compensation in P.U. */
_iq scale; /*!< Parameter: The scale for scale*speed+offset */
_iq offset; /*!< Parameter: The offset for scale*speed+offset */
_iq angleComp_pu; /*!< Output: the angle after compensation in P.U. */
} ZeroOffsetType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the ZERO_OFFSET object
*
* This function initalizes Zero_Offset by setting configuration parameters
*
* \param[in] obj : pointer to Zero_Offset instance
* \param[in] pParams : pointer to Zero_Offset configuration parameters
*/
extern void ZeroOffset_Init(ZeroOffsetType *obj, const ZeroOffset_ParamsType *pParams);
/*! \brief Run the ZERO_OFFSET Compensation
*
* This function runs Zero_Offset function, calculates zero offset value
*
* \param[in] obj : pointer to Zero_Offset instance
*/
static inline void ZeroOffset_Run(ZeroOffsetType *obj)
{
_iq angleTmp_pu = obj->angleUncomp_pu + _IQmpy(obj->scale, obj->speed_pu) + obj->offset;
angleTmp_pu = _IQfrac(angleTmp_pu); /* get the fraction part */
if(angleTmp_pu < 0)
{
angleTmp_pu += _IQ(1.0);
}
obj->angleComp_pu = angleTmp_pu;
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _ZERO_OFFSET_H_ */

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 _CLARKE_H_
#define _CLARKE_H_
/*! \brief Contains public interface to various functions related
* to the clarke modules
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Clarke prototype definition
*/
typedef struct _ClarkeType_
{
_iq As; /*!< phase A component */
_iq Bs; /*!< phase B component */
_iq Cs; /*!< phase C component */
_iq alpha; /*!< the alpha component */
_iq beta; /*!< the beta component */
} ClarkeType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Runs the clarke function
*
* This function runs clarke function, calculates clarke transforms value
*
* \param[in] obj : pointer to Clarke instance
*/
static inline void Clarke_Run(ClarkeType *obj)
{
obj->alpha = _IQmpy(_IQmpy2(obj->As) - (obj->Bs + obj->Cs), IQMATH_ONE_OVER_THREE);
obj->beta = _IQmpy((obj->Bs - obj->Cs), IQMATH_ONE_OVER_SQRT_THREE);
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _CLARKE_H_ */

View File

@ -0,0 +1,58 @@
/*
* 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 "clff.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void Clff_Init(ClffType *obj, const Clff_ParamsType *pParams)
{
/* Based value */
obj->RsBase_ohm = pParams->VBase_V / pParams->IBase_A;
obj->LBase_mH = pParams->VBase_V / pParams->IBase_A / (2 * MATH_PI * pParams->fBase_Hz) * 1000.0;
obj->PsiBase_Wb = pParams->VBase_V / (2 * MATH_PI * pParams->fBase_Hz);
/*init value */
_iq Vdc_pu = _IQ(pParams->ratedVdc_V / pParams->VBase_V);
obj->Kd = _IQdiv(_IQ(pParams->Ld_mH / obj->LBase_mH), Vdc_pu);
obj->Kq = _IQdiv(_IQ(pParams->Lq_mH / obj->LBase_mH), Vdc_pu);
obj->Kf = _IQdiv(_IQ(pParams->flux_Wb / obj->PsiBase_Wb), Vdc_pu);
obj->Kr = _IQdiv(_IQ(pParams->Rs_Ohm / obj->RsBase_ohm), Vdc_pu);
obj->minVdc_pu = _IQ(pParams->minVdc_V / pParams->VBase_V);
obj->maxVdc_pu = _IQ(pParams->maxVdc_V / pParams->VBase_V);
obj->Vd = 0;
obj->Vq = 0;
}

View File

@ -0,0 +1,152 @@
/*
* 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 _CLFF_H_
#define _CLFF_H_
/*! \brief Contains public interface to various functions related
* to the Current Loop Feed-Forward (CLFF) object
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines the initial parameters for CLFF object
*/
typedef struct _Clff_ParamsType_
{
float Rs_Ohm; /*!< Stationary resistance in Ohm */
float Ld_mH; /*!< Normal D-axis inductance in mH */
float Lq_mH; /*!< Normal Q-axis inductance in mH */
float flux_Wb; /*!< The flux of rotor */
float ratedVdc_V; /*!< Rated dc bus voltage */
float IBase_A; /*!< Base value of current used for P.U. */
float VBase_V; /*!< Base value of voltage used for P.U. */
float fBase_Hz; /*!< Base value of frequency used for P.U. */
float minVdc_V; /*!< Minimum DC voltage allowed */
float maxVdc_V; /*!< Maximum DC voltage allowed */
} Clff_ParamsType;
/*! \brief Defines the dynamic parameters used to update CLFF object
*/
typedef struct _Clff_DynamicParamsType_
{
float Rs_Ohm; /*!< Stationary resistance in Ohm */
float Ld_mH; /*!< Normal D-axis inductance in mH */
float Lq_mH; /*!< Normal Q-axis inductance in mH */
float flux_Wb; /*!< The flux of rotor */
_iq Vdc_pu; /*!< bus voltage in P.U. */
} Clff_DynamicParamsType;
/*! \brief Defines the CLFF object
*/
typedef struct _ClffType_
{
_iq Id_pu; /*!< Input: Id current in P.U. */
_iq Iq_pu; /*!< Input: Iq current in P.U. */
_iq eleFreq_pu; /*!< Input: electrical frequency in P.U. */
_iq Kf; /*!< Parameter: coefficient determined by Back EMF */
_iq Kd; /*!< Parameter: coefficient determined by Ld */
_iq Kq; /*!< Parameter: coefficient determined by Lq */
_iq Kr; /*!< Parameter: coefficient determined by Rs */
float RsBase_ohm; /*!< Parameter: Base value of resistance used for P.U. */
float LBase_mH; /*!< Parameter: Base value of Ls used for P.U. */
float PsiBase_Wb; /*!< Parameter: Base value of flux used for P.U. */
_iq minVdc_pu; /*!< Parameter: Minimum DC voltage allowed in P.U. */
_iq maxVdc_pu; /*!< Parameter: Maximum DC voltage allowed in P.U. */
_iq Vd; /*!< Output: theoretical Vd */
_iq Vq; /*!< Output: theoretical Vq */
} ClffType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the CLFF object
*
* This function initalizes CLFF by setting configuration parameters
*
* \param[in] obj : pointer to Clff instance
* \param[in] pParams : pointer to CLFF configuration parameters
*/
extern void Clff_Init(ClffType *obj, const Clff_ParamsType *pParams);
/*! \brief Calculate the theoretical Vd, Vq
*
* This function runs Clff function, calculates the theoretical Vd, Vq value
*
* \param[in] obj : pointer to Clff instance
*/
static inline void Clff_Calc(ClffType *obj)
{
obj->Vd = _IQmpy(obj->Kr, obj->Id_pu)
- _IQmpy(_IQmpy(obj->Kq, obj->Iq_pu), obj->eleFreq_pu);
obj->Vq = _IQmpy(obj->Kr, obj->Iq_pu)
+ _IQmpy(_IQmpy(obj->Kd, obj->Id_pu) + obj->Kf, obj->eleFreq_pu);
}
/*! \brief Update the parameters
*
* This function updates the Clff function configuration parameters dynamically
*
* \param[in] obj : pointer to Clff instance
* \param[in] pParams : pointer to Clff dynamic configuration parameters instance
*/
static inline void Clff_UpdateParams(ClffType *obj, const Clff_DynamicParamsType *pParams)
{
if(pParams->Vdc_pu >= obj->minVdc_pu && pParams->Vdc_pu <= obj->maxVdc_pu)
{
obj->Kd = _IQdiv(_IQ(pParams->Ld_mH / obj->LBase_mH), pParams->Vdc_pu);
obj->Kq = _IQdiv(_IQ(pParams->Lq_mH / obj->LBase_mH), pParams->Vdc_pu);
obj->Kf = _IQdiv(_IQ(pParams->flux_Wb / obj->PsiBase_Wb), pParams->Vdc_pu);
obj->Kr = _IQdiv(_IQ(pParams->Rs_Ohm / obj->RsBase_ohm), pParams->Vdc_pu);
}
else
{
obj->Kd = 0;
obj->Kq = 0;
obj->Kf = 0;
obj->Kr = 0;
}
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _CLFF_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.
*/
#ifndef _ESTIDC_H_
#define _ESTIDC_H_
/*! \brief Contains public interface to various functions related
* to the DC current Estimation (ESTIDC) object.
*
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines the phase enumeration
*/
typedef enum
{
ESTIDC_PHASE_A = 0,
ESTIDC_PHASE_B,
ESTIDC_PHASE_C,
ESTIDC_PHASE_U,
ESTIDC_PHASE_V,
ESTIDC_PHASE_W,
ESTIDC_PHASE_Num
} Estidc_PhaseType;
/*! \brief Defines all the parameters used to initialize ESTIDC object
*/
typedef struct _Estidc_ParamsType_
{
_iq Tdb; /*!< Percentage of dead-band */
uint8_t phaseNumber; /*!< Number of phase */
} Estidc_ParamsType;
/*! \brief data of each phase
*/
typedef struct _Estidc_PhaseDataType
{
_iq I; /*!< Current of ever phase */
_iq T; /*!< 100%-(duty of ever phase ) */
_iq prevI; /*!< The last Current of ever phase */
_iq prevT; /*!< The last 100%-(duty of ever phase) */
_iq prevPrevT; /*!< The previous last 100%-(duty of ever phase) */
} Estidc_PhaseDataType;
/*! \brief Defines the ESTIDC object
*/
typedef struct _EstidcType_
{
_iq Ia; /*!< Input: current of phase A */
_iq Ib; /*!< Input: current of phase B */
_iq Ic; /*!< Input: current of phase C */
_iq Iu; /*!< Input: current of phase U */
_iq Iv; /*!< Input: current of phase V */
_iq Iw; /*!< Input: current of phase W */
_iq Ta; /*!< Input: 100%-(duty) of phase A */
_iq Tb; /*!< Input: 100%-(duty) of phase B */
_iq Tc; /*!< Input: 100%-(duty) of phase C */
_iq Tu; /*!< Input: 100%-(duty) of phase U */
_iq Tv; /*!< Input: 100%-(duty) of phase V */
_iq Tw; /*!< Input: 100%-(duty) of phase W */
_iq Tdb; /*!< Parameter: Percentage of dead-band */
uint16_t phaseNumber; /*!< Parameter: Number of phase */
Estidc_PhaseDataType data[ESTIDC_PHASE_Num]; /*!< Internal Variable: data of each phase */
_iq estIdc; /*!< Output: The estimated DC current */
} EstidcType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the ESTIDC object
*
* This function initalizes Estidc by setting configuration parameters
*
* \param[in] obj : pointer to Estidc instance
* \param[in] pParams : pointer to Estidc configuration parameters
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Estidc_Init(EstidcType *obj, const Estidc_ParamsType *pParams);
/*! \brief Run the estimation
*
* This function runs Estidc function, calculates idc estimation value
*
* \param[in] obj : pointer to Estidc instance
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Estidc_Run(EstidcType *obj);
/*! \brief Update the parameters of ESTIDC object
*
* This function updates the Estidc function configuration parameters
*
* \param[in] obj : pointer to Estidc instance
* \param[in] Tdb : the percentage of dead-band
*/
extern void Estidc_UpdateParams(EstidcType *obj, _iq Tdb);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _ESTIDC_H_ */

View File

@ -0,0 +1,54 @@
/*
* 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 "esttrq_tf.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void EstTrqTf_Init(EstTrqTfType *obj, const EstTrqTf_ParamsType *pParams)
{
obj->torqueFactor_I = _IQ(1.5 * pParams->polePairs * pParams->IBase_A / pParams->torqueBase_Nm);
obj->torqueFactor_F = _IQ((pParams->Ld_mH - pParams->Lq_mH) * 0.001 * pParams->IBase_A);
obj->flux_Wb = pParams->flux_Wb;
obj->IBaseFactor = 0.001 * pParams->IBase_A;
}
void EstTrqTf_Calc(EstTrqTfType *obj)
{
obj->torque_pu = _IQmpy(_IQmpy(obj->filteredIqFdb_pu,
_IQmpy(obj->filteredIdFdb_pu, obj->torqueFactor_F) + obj->flux_Wb),
obj->torqueFactor_I);
}
void EstTrqTf_UpdateParams(EstTrqTfType *obj, float Ld_mH, float Lq_mH, float flux_Wb)
{
obj->torqueFactor_F = _IQ((Ld_mH - Lq_mH) * obj->IBaseFactor);
obj->flux_Wb = flux_Wb;
}

View File

@ -0,0 +1,110 @@
/*
* 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 _ESTTRQ_TF_H_
#define _ESTTRQ_TF_H_
/*! \brief Contains public interface to various functions related
* to the Torque Estimation using Torque Formula method.
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines all the parameters used to initialize ESTTRQ_TF object
*/
typedef struct _EstTrqTf_ParamsType_
{
float IBase_A; /*!< Base value of current used for P.U. */
float fBase_Hz; /*!< Base value of frequency used for P.U. */
float torqueBase_Nm; /*!< Base value of torque used for P.U. */
uint32_t polePairs; /*!< Pole pairs of the motor */
float Ld_mH; /*!< d-axis inductance in mH */
float Lq_mH; /*!< q-axis inductance in mH */
float flux_Wb; /*!< The flux of PM in Webers */
} EstTrqTf_ParamsType;
/*! \brief Defines the ESTTRQ_TF object
*/
typedef struct _EstTrqTfType_
{
_iq filteredIdFdb_pu; /*!< Input: The Id feedback in P.U. */
_iq filteredIqFdb_pu; /*!< Input: The Iq feedback in P.U. */
_iq flux_Wb; /*!< Parameter: The flux of PM in Webers */
_iq torqueFactor_I; /*!< Parameter: Current factor to calculate torque */
_iq torqueFactor_F; /*!< Parameter: Flux factor to calculate torque */
float IBaseFactor; /*!< Parameter: Base current factor to calculate torque */
_iq torque_pu; /*!< Output: The estimated torque */
} EstTrqTfType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the ESTTRQ_TF object
*
* This function initalizes Esttrq_Tf by setting configuration parameters
*
* \param[in] obj : pointer to Esttrq_Tf instance
* \param[in] pParams : pointer to parameters
*/
extern void EstTrqTf_Init(EstTrqTfType *obj, const EstTrqTf_ParamsType *pParams);
/*! \brief Run the Torque estimation
*
* This function runs Esttrq_Tf function, calculates torque estimation value
*
* \param[in] obj : pointer to Esttrq_Tf instance
*/
extern void EstTrqTf_Calc(EstTrqTfType *obj);
/*! \brief Update the parameters of ESTTRQ_TF object
*
* This function updates the Esttrq_Tf function configuration parameters
*
* \param[in] obj : pointer to Esttrq_Tf instance
* \param[in] Ld_mH : d-axis inductance in mH
* \param[in] Lq_mH : q-axis inductance in mH
* \param[in] flux_Wb : the flux of PM in Webers
*/
extern void EstTrqTf_UpdateParams(EstTrqTfType *obj, float Ld_mH, float Lq_mH, float flux_Wb);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _ESTTRQ_TF_H_ */

View File

@ -0,0 +1,44 @@
/*
* 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 "fag.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void Fag_Init(FagType *obj, float fBase_Hz, float runFreq_kHz)
{
obj->factor = _IQ(fBase_Hz / (runFreq_kHz * 1000.0));
obj->angle_pu = 0;
obj->frequency_pu = 0;
}

View File

@ -0,0 +1,116 @@
/*
* 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 _FAG_H_
#define _FAG_H_
/*! \brief Contains public interface to various functions related
* to the fag modules
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Fag prototype definition
*/
typedef struct _FagType_
{
_iq frequency_pu; /*!< Input: The electric frequency */
_iq factor; /*!< Internal Variable: The factor used to calculate the angle */
_iq angle_pu; /*!< Output: The angle generated */
} FagType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the FAG object
*
* This function initalizes Fag by setting configuration parameters
*
* \param[in] obj : pointer to Fag instance
* \param[in] fBase_Hz : the default maximum current base frequency
* \param[in] runFreq_kHz : the frequency of running current loop
*/
extern void Fag_Init(FagType *obj, float fBase_Hz, float runFreq_kHz);
/*! \brief Gets FAG calculation value
*
* This function gets Fag function calculation value
*
* \param[in] obj : pointer to Fag instance
*/
static inline _iq Fag_GetAngle(FagType *obj)
{
return (obj->angle_pu);
}
/*! \brief Sets the frequency of false angle
*
* This function Sets the frequency of false angle
*
* \param[in] obj : pointer to Fag instance
* \param[in] frequency : the desired frequency of false angle
*/
static inline void Fag_SetFrequency(FagType *obj, _iq frequency)
{
obj->frequency_pu = frequency;
}
/*! \brief Runs the FAG
*
* This function runs Fag function, calculates dynamic changing false angle value
*
* \param[in] obj : pointer to Fag instance
*/
static inline void Fag_Run(FagType *obj)
{
obj->angle_pu += _IQmpy(obj->frequency_pu, obj->factor);
obj->angle_pu = _IQfrac(obj->angle_pu); /* Get the fraction part */
if(obj->angle_pu < 0)
{
obj->angle_pu += _IQ(1.0);
}
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _FAG_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 _FAST_H_
#define _FAST_H_
/*! \brief Contains public interface to various functions related
* to the Flux, Angle, Speed, Torque estimation (FAST) modules
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include "common/iqmath/iqmath.h"
#include "common/pid/pid.h"
#include "common/filter/iir_fo.h"
#include "md_lib/clarke/clarke.h"
#include "md_lib/park/park.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Fast prototype definition
*/
typedef struct _Fast_ParamsType_
{
uint32_t polePairs; /*!< Pole pairs of the motor */
float runFreq_kHz; /*!< Frequency to run the process */
float Rs_Ohm; /*!< Stationary resistance in Ohm */
float Ld_mH; /*!< d-axis inductance in mH */
float Lq_mH; /*!< q-axis inductance in mH */
float fBase_Hz; /*!< Base value of frequency used for P.U. */
float VBase_V; /*!< Base value of voltage used for P.U. */
float IBase_A; /*!< Base value of current used for P.U. */
float torqueBase_Nm; /*!< Base value of torque used for P.U. */
float spdFilterPole_rps; /*!< Pole value of speed filter calculation */
float dirFilterPole_rps; /*!< Pole value of speed direction filter calculation */
float fluxFilterPole_rps; /*!< Pole value of flux filter calculation */
float ratedVdc_V; /*!< The rated phase-to-ground voltage */
float fstCalcFreq_kHz; /*!< The calculation frequency of flux, speed and torque */
float minElecFreq_Hz; /*!< The min speed supported in Hz */
float fluxBase_Wb; /*!< Base value of current used for P.U. */
float defaultFlux_Wb; /*!< The default value of flux in Wb */
float gain; /*!< Controller Gain (0.0 to 0.9999) */
float linearError; /*!< Controller Max allowed linear error (0.0 to 0.9999) */
float dampingFactor; /*!< Damping factor of controller */
} Fast_ParamsType;
/*! \brief Defines the dynamic parameters used to update Fast object
*/
typedef struct _Fast_DynamicParamsType_
{
float runFreq_kHz; /*!< Frequency to run the process */
float Rs_Ohm; /*!< Stationary resistance in Ohm */
float Ld_mH; /*!< d-axis inductance in mH */
float Lq_mH; /*!< q-axis inductance in mH */
float fBase_Hz; /*!< Base value of frequency used for P.U. */
float VBase_V; /*!< Base value of voltage used for P.U. */
float IBase_A; /*!< Base value of current used for P.U. */
} Fast_DynamicParamsType;
/*! \brief Defines the Fast type
*/
typedef struct _FastType_
{
_iq Ia_pu; /*!< Input: The Stationary current of phase A */
_iq Ib_pu; /*!< Input: The Stationary current of phase B */
_iq Ic_pu; /*!< Input: The Stationary current of phase C */
_iq Va_pu; /*!< Input: The Stationary voltage of phase A */
_iq Vb_pu; /*!< Input: The Stationary voltage of phase B */
_iq Vc_pu; /*!< Input: The Stationary voltage of phase C */
_iq Fdsmo; /*!< Parameter: Motor dependent control gain */
_iq Fqsmo; /*!< Parameter: Motor dependent control gain */
_iq Gdsmo; /*!< Parameter: Motor dependent control gain */
_iq Gqsmo; /*!< Parameter: Motor dependent control gain */
_iq Kdsmo; /*!< Parameter: Motor dependent control gain */
_iq Kqsmo; /*!< Parameter: Motor dependent control gain */
_iq Kslide; /*!< Parameter: Sliding control gain */
_iq maxError; /*!< Parameter: Maximum current error for linear SMC */
_iq angleFactor; /*!< Parameter: Factor to calculate angle from speed */
_iq fluxFactor; /*!< Parameter: Factor to calculate flux */
_iq torqueFactor_I; /*!< Parameter: Current factor to calculate torque */
_iq torqueFactor_F; /*!< Parameter: Flux factor to calculate torque */
_iq minSpd_pu; /*!< Parameter: Min electric speed in P.U. */
_iq defaultFlux_pu; /*!< Parameter: The default value of flux in P.U. */
_iq Vd; /*!< Internal Variable: The d-axis voltage */
_iq Vq; /*!< Internal Variable: The q-axis voltage */
_iq Zd; /*!< Internal Variable: Stationary d-axis sliding control */
_iq Zq; /*!< Internal Variable: Stationary q-axis sliding control */
_iq Eq; /*!< Internal Variable: Stationary q-axis back EMF */
ClarkeType clarkeI; /*!< Internal Variable: The clarke transform for current */
ClarkeType clarkeV; /*!< Internal Variable: The clarke transform for current */
ParkType parkI; /*!< Internal Variable: The park transform for current */
ParkType parkV; /*!< Internal Variable: The park transform for current */
PidType pidPLL; /*!< Internal Variable: The PLL PID */
_iq Id; /*!< Internal Variable: The d-axis current */
_iq Iq; /*!< Internal Variable: The q-axis current */
_iq IdEst; /*!< Internal Variable: Estimated d-axis current */
_iq IqEst; /*!< Internal Variable: Estimated q-axis current */
_iq IdError; /*!< Internal Variable: The d-axis current error */
_iq IqError; /*!< Internal Variable: The q-axis current error */
IirFoType filterSpd; /*!< Internal Variable: The filter for electric speed calculation */
IirFoType filterDir; /*!< Internal Variable: The filter for speed direction detection */
IirFoType filterFlux; /*!< Internal Variable: The filter for flux calculation */
int16_t spdDir; /*!< Internal Variable: The actual speed direction; 1:forward, -1:backward */
_iq rawSpeed_pu; /*!< Internal variable: The raw speed before filter in P.U. */
_iq currentAngle_pu; /*!< Internal variable: The angle for this control loop */
_iq nextAngle_pu; /*!< Internal variable: The angle for next control loop */
_iq angle_pu; /*!< Output: The electric angle */
_iq speed_pu; /*!< Output: The filtered electric speed updated every electric period */
_iq flux_pu; /*!< Output: The flux of PM in P.U. */
_iq torque_pu; /*!< Output: The electrical torque in P.U. */
} FastType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the FAST object
*
* This function initalizes Fast by setting configuration parameters
*
* \param[in] obj : pointer to Fast instance
* \param[in] pParams : pointer to Fast configuration parameters
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Fast_Init(FastType *obj, const Fast_ParamsType *pParams);
/*! \brief Run the FAST
*
* This function runs Fast function, calculates Fast relevant value
*
* \param[in] obj : pointer to Fast instance
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Fast_Run(FastType *obj);
/*! \brief Calculates current motor speed
*
* This function calculates current motor speed based on Fast estimation parameters
*
* \param[in] obj : pointer to Fast instance
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Fast_CalcSpeed(FastType *obj);
/*! \brief Calculates current motor parameters
*
* This function calculates current motor flux and torque
* based on Fast estimation parameters
*
* \param[in] obj : pointer to Fast instance
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Fast_CalcFluxAndTorque(FastType *obj);
/*! \brief Updates configuration parameters
*
* This function updates configuration parameters dynamically
*
* \param[in] obj : pointer to Fast instance
* \param[in] pParams : pointer to Fast configuration parameters
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Fast_UpdateParams(FastType *obj, const Fast_DynamicParamsType *pParams);
/*! \brief Reset the Fast object
*
* This function resets the Fast relevant calculation parameters
*
* \param[in] obj : pointer to Fast instance
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Fast_Reset(FastType *obj);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _FAST_H_ */

View File

@ -0,0 +1,240 @@
/*
* 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 _EFOC_H_
#define _EFOC_H_
/*! \brief Contains public interface to various functions related
* to the Enhanced Field-Oriented Control (EFOC) object
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include "common/iqmath/iqmath.h"
#include "md_lib/clarke/clarke.h"
#include "md_lib/park/park.h"
#include "md_lib/ipark/ipark.h"
#include "md_lib/svgen/svgen.h"
#include "md_lib/fullwave/fullwave.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines the control type of the EFOC
*/
typedef enum
{
EFOC_CTRLTYPE_VVVF = 0,
EFOC_CTRLTYPE_CURRENTLOOP,
EFOC_CTRLTYPE_FULLWAVE,
EFOC_CTRLTYPE_OFFLINE,
} EFoc_CtrlModeType;
/*! \brief Defines all the parameters used to initialize EFOC object
*/
typedef struct _EFoc_ParamsType_
{
float VsMax_pu; /*!< Max allowed Vs */
float VdMaxScale; /*!< Max allowed Vd scale factor based on Vs. */
float minVdc_V; /*!< Minimum DC voltage allowed */
float maxVdc_V; /*!< Maximum DC voltage allowed */
float Rs_Ohm; /*!< Stationary resistance in Ohm */
float Ld_mH; /*!< Normal D-axis inductance in mH */
float Lq_mH; /*!< Normal Q-axis inductance in mH */
float flux_Wb; /*!< The flux of rotor */
float runFreq_kHz; /*!< Frequency to run FOC */
float fBase_Hz; /*!< Base value of frequency used for P.U. */
float VBase_V; /*!< Base value of voltage used for P.U. */
float ratedVdc_V; /*!< Rated dc bus voltage */
float IBase_A; /*!< Base value of current used for P.U. */
EFoc_CtrlModeType ctrlType; /*!< Control type of FOC */
float switchTime_ms; /*!< The switch time between FOC and full wave */
float fullwaveBWScale; /*!< Current control run frequency / Bandwidth in full wave mode */
float lambda; /*!< Control parameter for the decouple network */
float alpha; /*!< Control parameter for the Ls */
float beta; /*!< Control parameter for the Rs */
} EFoc_ParamsType;
/*! \brief Defines the dynamic parameters used to update EFOC object
*/
typedef struct _EFoc_DynamicParamsType_
{
float Rs_Ohm; /*!< Stationary resistance in Ohm */
float Ld_mH; /*!< Normal D-axis inductance in mH */
float Lq_mH; /*!< Normal Q-axis inductance in mH */
float flux_Wb; /*!< The flux of rotor */
float runFreq_kHz; /*!< Frequency to run FOC */
_iq Vdc_pu; /*!< DC bus voltage */
float lambda; /*!< Control parameter for the decouple network */
float alpha; /*!< Control parameter for the Ls */
float beta; /*!< Control parameter for the Rs */
} EFoc_DynamicParamsType;
/*! \brief Defines the EFOC object
*/
typedef struct _EFocType_
{
_iq Ia_pu; /*!< Input: The phase-A current */
_iq Ib_pu; /*!< Input: The phase-B current */
_iq Ic_pu; /*!< Input: The phase-C current */
_iq parkSinTh; /*!< Input: The sin value for PARK transform */
_iq parkCosTh; /*!< Input: The cos value for PARK transform */
_iq iparkSinTh; /*!< Input: The sin value for IPARK transform */
_iq iparkCosTh; /*!< Input: The cos value for IPARK transform */
_iq Vref; /*!< Input: Only used in VVVF mode */
_iq IdRef; /*!< Input: The Id reference */
_iq IqRef; /*!< Input: The Iq reference */
_iq speed_pu; /*!< Input: Feedback speed in P.U. */
_iq compVd; /*!< Input: The compensation value of Vd, normally is 0 */
_iq compVq; /*!< Input: The compensation value of Vq, normally is 0 */
_iq VsMax; /*!< Parameters: Max value of Vs */
_iq VdMax; /*!< Parameters: Max value of Vd */
EFoc_CtrlModeType ctrlType; /*!< Parameters: Control type of FOC */
_iq minVdc_pu; /*!< Parameter: Minimum DC voltage allowed in P.U. */
_iq maxVdc_pu; /*!< Parameter: Maximum DC voltage allowed in P.U.*/
_iq Kr; /*!< Internal variable: coefficient determined by Rs */
_iq Kd_Vd; /*!< Internal variable: coefficient determined by Ld in Vd equation */
_iq Kq_Vd; /*!< Internal variable: coefficient determined by Lq in Vd equation */
_iq Kq_Vq; /*!< Internal variable: coefficient determined by Lq in Vq equation */
_iq Kd_Vq; /*!< Internal variable: coefficient determined by Ld in Vq equation */
_iq Kf; /*!< Internal variable: coefficient determined by flux in Vq equation */
float factorR; /*!< Internal variable: factor of IBase/VBase */
float factorL; /*!< Internal variable: factor of fBase*IBase/VBase */
float factorBemf; /*!< Internal variable: factor of fBase/VBase */
ClarkeType clarkeI; /*!< Internal variable: Clarke transform of current */
ParkType park; /*!< Internal variable: Part transform */
IparkType ipark; /*!< Internal variable: iPark transform */
SvgenType svgen; /*!< Internal variable: SVPWM generator */
FullWaveType fullwave; /*!< Internal variable: Full wave control */
_iq Vd; /*!< Internal variable: Vd */
_iq Vq; /*!< Internal variable: Vq */
_iq lastErrorId; /*!< Internal variable: Last error of Id */
_iq lastErrorIq; /*!< Internal variable: Last error of Iq */
_iq VdAccum; /*!< Internal variable: The accumulator of Vd */
_iq VqAccum; /*!< Internal variable: The accumulator of Vq */
_iq Vs; /*!< Output: Clarke transform of current */
} EFocType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the EFOC object
*
* This function initalizes EFoc by setting configuration parameters
*
* \param[in] obj : pointer to EFoc instance
* \param[in] pParams : pointer to EFoc configuration parameters
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t EFoc_Init(EFocType *obj, const EFoc_ParamsType *pParams);
/*! \brief Set the current feedback value
*
* This function sets current feedback value
*
* \param[in] obj : pointer to EFoc instance
* \param[in] Ia_pu : The phase-A current in P.U.
* \param[in] Ib_pu : The phase-B current in P.U.
* \param[in] Ic_pu : The phase-C current in P.U.
*/
static inline void EFoc_SetCurrentFdb(EFocType *obj, _iq Ia_pu, _iq Ib_pu, _iq Ic_pu)
{
obj->Ia_pu = Ia_pu;
obj->Ib_pu = Ib_pu;
obj->Ic_pu = Ic_pu;
}
/*! \brief The main process function of EFoc
*
* This function runs EFoc function, perform motor control functions
*
* \param[in] obj : pointer to EFoc instance
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t EFoc_Run(EFocType *obj);
/*! \brief Get the PWM compare value of EFoc
*
* This function gets three phase duty
*
* \param[in] obj : pointer to EFoc instance
* \param[out] Ta : the phase-A duty
* \param[out] Tb : the phase-B duty
* \param[out] Tc : the phase-C duty
*/
extern void EFoc_GetPwmCompareValue(EFocType *obj, _iq *Ta, _iq *Tb, _iq *Tc);
/*! \brief Reset the EFoc object
*
* This function resets the EFoc relevant calculation parameters
*
* \param[in] obj : pointer to EFoc instance
*/
extern void EFoc_Reset(EFocType *obj);
/*! \brief Update the parameters of EFoc
*
* This function updates the EFoc function configuration parameters
*
* \param[in] obj : pointer to EFoc instance
* \param[in] pParams : pointer to control configuration paramter
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t EFoc_UpdateParams(EFocType *obj, const EFoc_DynamicParamsType *pParams);
/*! \brief Change the control type of EFoc
*
* This function updates the EFoc function configuration parameters
*
* \param[in] obj : pointer to EFoc instance
* \param[in] ctrlType : the control type of the EFOC
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t EFoc_ChangeCtrlType(EFocType *obj, EFoc_CtrlModeType ctrlType);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _EFOC_H_ */

View File

@ -0,0 +1,241 @@
/*
* 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 "foc.h"
/*******************************************************************************
* the defines
******************************************************************************/
#define FULL_WAVE_VS (_IQ(0.66666)) /* The Vs used in full wave mode */
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void Foc_Init(FocType *obj, const Foc_ParamsType *pParams)
{
obj->ctrlType = pParams->ctrlType;
obj->minVdc_pu = _IQ(pParams->minVdc_V / pParams->VBase_V);
obj->maxVdc_pu = _IQ(pParams->maxVdc_V / pParams->VBase_V);
obj->factorKpKi = 2 * MATH_PI * pParams->IBase_A / pParams->VBase_V / pParams->bandWidthScale;
/* Calculate PID parameters */
_iq Ki_parallel = _IQ(2 * MATH_PI * pParams->Rs_Ohm / pParams->bandWidthScale
* pParams->IBase_A / pParams->ratedVdc_V);
_iq Kp_parallel = _IQ(2 * MATH_PI * pParams->Ld_mH * pParams->runFreq_kHz / pParams->bandWidthScale
* pParams->IBase_A / pParams->ratedVdc_V);
obj->VsMax = _IQ(pParams->VsMax_pu);
obj->VdMax = _IQ(pParams->VsMax_pu * pParams->VdMaxScale);
/* Apply to current PID, note that the pidIq limits will be set dynamically, so just set 0 when init */
Pid_Init(&obj->pidId, Kp_parallel, Ki_parallel, 0, -obj->VdMax, obj->VdMax);
Ki_parallel = _IQ(2 * MATH_PI * pParams->Rs_Ohm / pParams->bandWidthScale
* pParams->IBase_A / pParams->ratedVdc_V);
Kp_parallel = _IQ(2 * MATH_PI * pParams->Lq_mH * pParams->runFreq_kHz / pParams->bandWidthScale
* pParams->IBase_A / pParams->ratedVdc_V);
Pid_Init(&obj->pidIq, Kp_parallel, Ki_parallel, 0, 0, 0);
/* Full wave control */
FullWave_ParamsType fullwaveParams;
fullwaveParams.Rs_Ohm = pParams->Rs_Ohm;
fullwaveParams.Ld_mH = pParams->Ld_mH;
fullwaveParams.runFreq_kHz = pParams->runFreq_kHz;
fullwaveParams.ratedVdc_V = pParams->ratedVdc_V;
fullwaveParams.IBase_A = pParams->IBase_A;
fullwaveParams.VsMax = pParams->VsMax_pu;
fullwaveParams.VdMaxScale = pParams->VdMaxScale;
fullwaveParams.VsRampStep = FULL_WAVE_VS / (pParams->switchTime_ms * pParams->runFreq_kHz);
fullwaveParams.bandWidthScale = pParams->fullwaveBWScale;
FullWave_Init(&obj->fullwave, &fullwaveParams);
obj->svgen.mode = SVGEN_MODE_NORMAL;
obj->IdRef = 0;
obj->IqRef = 0;
obj->Vref = 0;
obj->Vdff = 0;
obj->Vqff = 0;
}
void Foc_Run(FocType *obj)
{
if(obj->ctrlType == FOC_CTRLTYPE_VVVF)
{
/* No current control */
obj->ipark.Ds = obj->Vref;
obj->ipark.Qs = 0;
}
else
{
/* Clarke transform */
obj->clarkeI.As = obj->Ia_pu;
obj->clarkeI.Bs = obj->Ib_pu;
obj->clarkeI.Cs = obj->Ic_pu;
Clarke_Run(&obj->clarkeI);
/* Park transform */
obj->park.alpha = obj->clarkeI.alpha;
obj->park.beta = obj->clarkeI.beta;
obj->park.sinTh = obj->parkSinTh;
obj->park.cosTh = obj->parkCosTh;
Park_Run(&obj->park);
if(obj->ctrlType == FOC_CTRLTYPE_CURRENTLOOP)
{
/* Id PID */
obj->pidId.ref = obj->IdRef;
obj->pidId.fdb = obj->park.Ds;
Pid_Run(&obj->pidId);
obj->Vd = _IQsat(obj->pidId.output + obj->Vdff, obj->VdMax, -obj->VdMax);
/* Vq limit calculation */
_iq VsMaxSqr = _IQmpy(obj->VsMax, obj->VsMax);
_iq VdSqr = _IQmpy(obj->Vd, obj->Vd);
_iq VqMaxSqr = VdSqr < VsMaxSqr ? VsMaxSqr - VdSqr : 0;
_iq VqMax = _IQsqrt(VqMaxSqr);
/* Iq PID */
obj->pidIq.outMax = VqMax;
obj->pidIq.outMin = -VqMax;
obj->pidIq.ref = obj->IqRef;
obj->pidIq.fdb = obj->park.Qs;
Pid_Run(&obj->pidIq);
obj->Vq = _IQsat(obj->pidIq.output + obj->Vqff, VqMax, -VqMax);
/* IPARK */
obj->ipark.Ds = obj->Vd;
obj->ipark.Qs = obj->Vq;
}
else if(obj->ctrlType == FOC_CTRLTYPE_FULLWAVE)
{
/* Full-wave control */
obj->fullwave.IqRef_pu = obj->IqRef;
obj->fullwave.Iq_pu = obj->park.Qs;
obj->fullwave.speed_pu = obj->speed_pu;
obj->fullwave.Vdff = obj->Vdff;
FullWave_Run(&obj->fullwave);
/* IPARK */
obj->ipark.Ds = obj->fullwave.Vd;
obj->ipark.Qs = obj->fullwave.Vq;
}
}
obj->ipark.sinTh = obj->iparkSinTh;
obj->ipark.cosTh = obj->iparkCosTh;
IPark_Run(&obj->ipark);
/* Calculate Vs */
obj->Vs = _IQmag(obj->ipark.Ds, obj->ipark.Qs);
/* SVGEN */
obj->svgen.Ualpha = obj->ipark.alpha;
obj->svgen.Ubeta = obj->ipark.beta;
Svgen_Run(&obj->svgen);
}
void Foc_GetPwmCompareValue(FocType *obj, _iq *Ta, _iq *Tb, _iq *Tc)
{
*Ta = obj->svgen.Ta;
*Tb = obj->svgen.Tb;
*Tc = obj->svgen.Tc;
}
void Foc_Reset(FocType *obj)
{
obj->IqRef = 0; /* Clear IqRef first just to be safe */
obj->IdRef = 0;
obj->pidId.Ui = 0;
obj->pidId.output = 0;
obj->pidIq.Ui = 0;
obj->pidIq.output = 0;
obj->Vd = 0;
obj->Vq = 0;
obj->ipark.Ds = 0;
obj->ipark.Qs = 0;
obj->Vdff = 0;
obj->Vqff = 0;
}
void Foc_UpdateParams(FocType *obj, const Foc_DynamicParamsType *pParams)
{
if(pParams->Vdc_pu >= obj->minVdc_pu && pParams->Vdc_pu <= obj->maxVdc_pu)
{
if(obj->ctrlType != FOC_CTRLTYPE_FULLWAVE)
{
obj->pidId.Kp = _IQdiv(_IQ(obj->factorKpKi * pParams->Ld_mH * pParams->runFreq_kHz), pParams->Vdc_pu);
obj->pidId.Ki = _IQdiv(_IQ(obj->factorKpKi * pParams->Rs_Ohm), pParams->Vdc_pu);
obj->pidIq.Kp = _IQdiv(_IQ(obj->factorKpKi * pParams->Lq_mH * pParams->runFreq_kHz), pParams->Vdc_pu);
obj->pidIq.Ki = obj->pidId.Ki;
}
else
{
FullWave_DynamicParamsType fullwaveDynamicParams;
fullwaveDynamicParams.Rs_Ohm = pParams->Rs_Ohm;
fullwaveDynamicParams.Ld_mH = pParams->Ld_mH;
fullwaveDynamicParams.runFreq_kHz = pParams->runFreq_kHz;
fullwaveDynamicParams.Vdc_pu = pParams->Vdc_pu;
FullWave_UpdateParams(&obj->fullwave, &fullwaveDynamicParams);
}
}
}
void Foc_ChangeCtrlType(FocType *obj, Foc_CtrlModeType ctrlType)
{
if(obj->ctrlType != FOC_CTRLTYPE_FULLWAVE
&& ctrlType == FOC_CTRLTYPE_FULLWAVE)
{ /* Switch to full wave control */
/* Remember the current Vd, Vq */
obj->fullwave.Vd = obj->ipark.Ds;
obj->fullwave.Vq = obj->ipark.Qs;
obj->fullwave.pidIq.output = -obj->fullwave.Vd;
obj->fullwave.pidIq.Ui = obj->fullwave.pidIq.output;
/* Change the target Vs */
FullWave_SetVsMax(&obj->fullwave, FULL_WAVE_VS);
obj->svgen.mode = SVGEN_MODE_SQUAREWAVE;
}
else if(obj->ctrlType == FOC_CTRLTYPE_FULLWAVE
&& ctrlType == FOC_CTRLTYPE_CURRENTLOOP)
{ /* Switch back to current loop */
/* Remember the current Vd, Vq */
obj->pidId.output = obj->ipark.Ds;
obj->pidId.Ui = obj->pidId.output;
obj->pidIq.output = obj->ipark.Qs;
obj->pidIq.Ui = obj->pidIq.output;
/* Change the target Vs */
FullWave_SetVsMax(&obj->fullwave, obj->VsMax);
obj->svgen.mode = SVGEN_MODE_NORMAL;
}
obj->ctrlType = ctrlType;
}

View File

@ -0,0 +1,212 @@
/*
* 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 _FOC_H_
#define _FOC_H_
/*! \brief Contains public interface to various functions related
* to the Field-Oriented Control (FOC) object
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include "common/iqmath/iqmath.h"
#include "common/pid/pid.h"
#include "md_lib/clarke/clarke.h"
#include "md_lib/park/park.h"
#include "md_lib/ipark/ipark.h"
#include "md_lib/svgen/svgen.h"
#include "md_lib/fullwave/fullwave.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines the control type of the FOC
*/
typedef enum
{
FOC_CTRLTYPE_VVVF = 0,
FOC_CTRLTYPE_CURRENTLOOP,
FOC_CTRLTYPE_FULLWAVE,
FOC_CTRLTYPE_OFFLINE,
} Foc_CtrlModeType;
/*! \brief Defines all the parameters used to initialize FOC object
*/
typedef struct _Foc_ParamsType_
{
float VsMax_pu; /*!< Max allowed Vs */
float VdMaxScale; /*!< Max allowed Vd scale factor based on Vs. */
float minVdc_V; /*!< Minimum DC voltage allowed */
float maxVdc_V; /*!< Maximum DC voltage allowed */
float Rs_Ohm; /*!< Stationary resistance in Ohm */
float Ld_mH; /*!< Normal D-axis inductance in mH */
float Lq_mH; /*!< Normal Q-axis inductance in mH */
float runFreq_kHz; /*!< Frequency to run FOC */
float fBase_Hz; /*!< Base value of frequency used for P.U. */
float ratedVdc_V; /*!< Rated dc bus voltage */
float VBase_V; /*!< Base value of voltage used for P.U. */
float IBase_A; /*!< Base value of current used for P.U. */
Foc_CtrlModeType ctrlType; /*!< Control type of FOC */
float switchTime_ms; /*!< The switch time between FOC and full wave */
float bandWidthScale; /*!< Current control run frequency / Bandwidth */
float fullwaveBWScale; /*!< Current control run frequency / Bandwidth in full wave mode */
} Foc_ParamsType;
/*! \brief Defines the dynamic parameters used to update FOC object
*/
typedef struct _Foc_DynamicParamsType_
{
float Rs_Ohm; /*!< Stationary resistance in Ohm */
float Ld_mH; /*!< Normal D-axis inductance in mH */
float Lq_mH; /*!< Normal Q-axis inductance in mH */
float runFreq_kHz; /*!< Frequency to run FOC */
_iq Vdc_pu; /*!< DC bus voltage */
} Foc_DynamicParamsType;
/*! \brief Defines the FOC object
*/
typedef struct _FocType_
{
_iq Ia_pu; /*!< Input: The phase-A current */
_iq Ib_pu; /*!< Input: The phase-B current */
_iq Ic_pu; /*!< Input: The phase-C current */
_iq parkSinTh; /*!< Input: The sin value for PARK transform */
_iq parkCosTh; /*!< Input: The cos value for PARK transform */
_iq iparkSinTh; /*!< Input: The sin value for IPARK transform */
_iq iparkCosTh; /*!< Input: The cos value for IPARK transform */
_iq Vref; /*!< Input: Only used in VVVF mode */
_iq IdRef; /*!< Input: The Id reference */
_iq IqRef; /*!< Input: The Iq reference */
_iq speed_pu; /*!< Input: Feedback speed in P.U. */
_iq Vdff; /*!< Input: Feed-forward Vd */
_iq Vqff; /*!< Input: Feed-forward Vq */
_iq VsMax; /*!< Parameter: Max value of Vs */
_iq VdMax; /*!< Parameter: Max value of Vd */
Foc_CtrlModeType ctrlType; /*!< Parameter: Control type of FOC */
float factorKpKi; /*!< Parameter: The factor to calculate Kp Ki in runtime */
_iq minVdc_pu; /*!< Parameter: Minimum DC voltage allowed in P.U. */
_iq maxVdc_pu; /*!< Parameter: Maximum DC voltage allowed in P.U. */
PidType pidId; /*!< Internal variable: The PID control of Id current */
PidType pidIq; /*!< Internal variable: The PID control of Iq current */
ClarkeType clarkeI; /*!< Internal variable: Clarke transform of current */
ParkType park; /*!< Internal variable: Part transform */
IparkType ipark; /*!< Internal variable: iPark transform */
SvgenType svgen; /*!< Internal variable: SVPWM generator */
FullWaveType fullwave; /*!< Internal variable: Full wave control */
_iq Vd; /*!< Internal variable: Vd */
_iq Vq; /*!< Internal variable: Vq */
_iq Vs; /*!< Output: Clarke transform of current */
} FocType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the FOC object
*
* This function initalizes Foc by setting configuration parameters
*
* \param[in] obj : pointer to Foc instance
* \param[in] pParams : pointer to Foc configuration parameters
*/
extern void Foc_Init(FocType *obj, const Foc_ParamsType *pParams);
/*! \brief Set the current feedback value
*
* This function runs Foc function, perform motor control functions
*
* \param[in] obj : pointer to Foc instance
* \param[in] Ia_pu : The phase-A current in P.U.
* \param[in] Ib_pu : The phase-B current in P.U.
* \param[in] Ic_pu : The phase-C current in P.U.
*/
static inline void Foc_SetCurrentFdb(FocType *obj, _iq Ia_pu, _iq Ib_pu, _iq Ic_pu)
{
obj->Ia_pu = Ia_pu;
obj->Ib_pu = Ib_pu;
obj->Ic_pu = Ic_pu;
}
/*! \brief The main process function of Foc
*
* This function runs Foc function, perform motor control functions
*
* \param[in] obj : pointer to Foc instance
*/
extern void Foc_Run(FocType *obj);
/*! \brief Get the PWM compare value of Foc
*
* This function gets three phase duty
*
* \param[in] obj : pointer to Foc instance
* \param[out] Ta : the phase-A duty
* \param[out] Tb : the phase-B duty
* \param[out] Tc : the phase-C duty
*/
extern void Foc_GetPwmCompareValue(FocType *obj, _iq *Ta, _iq *Tb, _iq *Tc);
/*! \brief Reset the Foc object
*
* This function resets the Foc relevant calculation parameters
*
* \param[in] obj : pointer to Foc instance
*/
extern void Foc_Reset(FocType *obj);
/*! \brief Update the parameters of Foc
*
* This function updates the Foc function configuration parameters
*
* \param[in] obj : pointer to Foc instance
* \param[in] pParams : pointer to control configuration paramter
*/
extern void Foc_UpdateParams(FocType *obj, const Foc_DynamicParamsType *pParams);
/*! \brief Change the control type of Foc
*
* This function updates the Foc function configuration parameters
*
* \param[in] obj : pointer to Foc instance
* \param[in] ctrlType : the control type of the FOC
*/
extern void Foc_ChangeCtrlType(FocType *obj, Foc_CtrlModeType ctrlType);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _FOC_H_ */

View File

@ -0,0 +1,150 @@
/*
* 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 _FULLWAVE_H_
#define _FULLWAVE_H_
/*! \brief Contains public interface to various functions related
* to the full-wave control (FULLWAVE) object.
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include "common/iqmath/iqmath.h"
#include "common/pid/pid.h"
#include "common/curve/ramp.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines all the parameters used to initialize FULLWAVE object
*/
typedef struct _FullWave_ParamsType_
{
float Rs_Ohm; /*!< Stationary resistance in Ohm */
float Ld_mH; /*!< Normal D-axis inductance in mH */
float runFreq_kHz; /*!< Frequency to run FOC */
float ratedVdc_V; /*!< Rated dc bus voltage */
float IBase_A; /*!< Base value of current used for P.U. */
float VBase_V; /*!< Base value of voltage used for P.U. */
float VsMax; /*!< Max allowed Vs */
float VdMaxScale; /*!< Max allowed Vd scale factor based on Vs. */
float VsRampStep; /*!< The step of changing the Vs */
float bandWidthScale; /*!< Current control run frequency / Bandwidth */
float minVdc_V; /*!< Minimum DC voltage allowed */
float maxVdc_V; /*!< Minimum DC voltage allowed */
} FullWave_ParamsType;
/*! \brief Defines the dynamic parameters used to update FULLWAVE object
*/
typedef struct _FullWave_DynamicParamsType_
{
float Rs_Ohm; /*!< Stationary resistance in Ohm */
float Ld_mH; /*!< Normal D-axis inductance in mH */
float runFreq_kHz; /*!< Frequency to run FOC */
_iq Vdc_pu; /*!< DC bus voltage */
} FullWave_DynamicParamsType;
/*! \brief Defines the FULLWAVE object
*/
typedef struct _FullWaveType_
{
_iq IqRef_pu; /*!< Input: Command Iq current in P.U. */
_iq Iq_pu; /*!< Input: Feedback Iq current in P.U. */
_iq speed_pu; /*!< Input: Feedback speed in P.U. */
_iq Vdff; /*!< Input: Feed-forward Vd */
float factorKpKi; /*!< Parameter: The factor to calculate Kp and Ki */
_iq minVdc_pu; /*!< Parameter: Minimum DC voltage allowed in P.U. */
_iq maxVdc_pu; /*!< Parameter: Maximum DC voltage allowed in P.U. */
PidType pidIq; /*!< Internal variable: The PID to tune Iq */
RampType rampVs; /*!< Internal variable: The ramp of changing the Vs */
_iq VdMaxScale; /*!< Internal variable: Max allowed Vd scale factor based on Vs. */
_iq VsMax; /*!< Internal variable: The Max ABS value of Vs */
_iq Vd; /*!< Output: Vd */
_iq Vq; /*!< Output: Vq */
} FullWaveType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the FullWave object
*
* This function initalizes FullWave by setting configuration parameters
*
* \param[in] obj : pointer to FullWave instance
* \param[in] pParams : pointer to FullWave configuration parameters
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t FullWave_Init(FullWaveType *obj, const FullWave_ParamsType *pParams);
/*! \brief Run the full wave control
*
* This function runs full wave control function, perform motor control functions
*
* \param[in] obj : pointer to FullWave instance
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t FullWave_Run(FullWaveType *obj);
/*! \brief Set the Vs max
*
* This function sets Vs max value
*
* \param[in] obj : pointer to FullWave instance
* \param[in] VsMax : Vs max value
*/
extern void FullWave_SetVsMax(FullWaveType *obj, _iq VsMax);
/*! \brief Update the parameters
*
* This function updates the FullWave function configuration parameters
*
* \param[in] obj : pointer to FullWave instance
* \param[in] pParams : pointer to control configuration paramter
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t FullWave_UpdateParams(FullWaveType *obj, const FullWave_DynamicParamsType *pParams);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _FULLWAVE_H_ */

View File

@ -0,0 +1,65 @@
/*
* 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 "fw.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*! \brief Defines the Field Weakening (FW) increment delta correction
*/
#define FW_INC_DELTA (0.00002)
/*! \brief Defines the Field Weakening (FW) decrement delta correction
*/
#define FW_DEC_DELTA (0.00002)
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void Fw_Init(FwType *obj, _iq maxNegIdRef)
{
obj->outMax = 0;
obj->outMin = maxNegIdRef;
obj->deltaInc = _IQ(FW_INC_DELTA);
obj->deltaDec = _IQ(FW_DEC_DELTA);
obj->output = 0;
}
void Fw_Run(FwType *obj)
{
if(obj->refValue > obj->fbackValue)
{
obj->output += obj->deltaInc;
}
else if(obj->refValue < obj->fbackValue)
{
obj->output -= obj->deltaDec;
}
obj->output = _IQsat(obj->output, obj->outMax, obj->outMin); /* Saturate the output */
}

View File

@ -0,0 +1,85 @@
/*
* 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 _FW_H_
#define _FW_H_
/*! \brief Contains public interface to various functions related
* to the Field Weakening (FW) object
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
typedef struct _FwType_
{
_iq refValue; /*!< Input: The reference value */
_iq fbackValue; /*!< Input: The feedback value */
_iq outMax; /*!< Parameter: Maximum output */
_iq outMin; /*!< Parameter: Minimum output */
_iq deltaInc; /*!< Parameter: The field weakening delta increment of Id reference */
_iq deltaDec; /*!< Parameter: The field weakening delta decrement of Id reference */
_iq output; /*!< Output: The output of field weakening */
} FwType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the Fw object
*
* This function initalizes Fw by setting configuration parameters
*
* \param[in] obj : pointer to Fw instance
* \param[in] maxNegIdRef : max -id reference value
*/
extern void Fw_Init(FwType *obj, _iq maxNegIdRef);
/*! \brief Run the field weakening control
*
* This function runs Fw function, perform motor control functions
*
* \param[in] obj : pointer to Fw instance
*/
extern void Fw_Run(FwType *obj);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _FW_H_ */

View File

@ -0,0 +1,80 @@
/*
* 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 _IPARK_H_
#define _IPARK_H_
/*! \brief Contains the public interface to the
* Park transform module routines
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines the IPARK object
*
*/
typedef struct _IparkType_
{
_iq sinTh; /*!< Input: sin value of rotating angle (pu) */
_iq cosTh; /*!< Input: cos value of rotating angle (pu) */
_iq Ds; /*!< Input: rotating d-axis stator variable */
_iq Qs; /*!< Input: rotating q-axis stator variable */
_iq alpha; /*!< Output: stationary alpha-axis stator variable */
_iq beta; /*!< Output: stationary beta-axis stator variable */
} IparkType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Process the IPARK algorithm
*
* This function runs IPARK function to calculate stationary axis variable
*
* \param[in] obj : pointer to Ipark instance
*/
static inline void IPark_Run(IparkType *obj)
{
obj->alpha = _IQmpy(obj->Ds, obj->cosTh) - _IQmpy(obj->Qs, obj->sinTh);
obj->beta = _IQmpy(obj->Qs, obj->cosTh) + _IQmpy(obj->Ds, obj->sinTh);
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _IPARK_H_ */

View File

@ -0,0 +1,125 @@
/*
* 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 _HFI_H_
#define _HFI_H_
/*! \brief Contains public interface to various functions related
* to the Initial Position Detection (IPD) using
* High Frequency Injection method (HFI) object.
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include "common/iqmath/iqmath.h"
#include "common/filter/bp_so.h"
#include "common/filter/iir_fo.h"
#include "common/pid/pid.h"
#include "md_lib/fag/fag.h"
#include "md_lib/park/park.h"
#include "md_lib/clarke/clarke.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines all the parameters used to initialize HFI object
*/
typedef struct _Hfi_ParamsType_
{
float runFreq_kHz; /*!< Frequency to run the process */
float injectFreq_kHz; /*!< The injected frequency in kHz */
float injectVd_pVdc; /*!< The injected frequency per Vdc */
float lpfPole_rps; /*!< Pole value of low pass filter in rad/s */
float pllPole_rps; /*!< Pole value of PLL in rad/s */
float Ld_mH; /*!< d-axis inductance in mH */
float Lq_mH; /*!< q-axis inductance in mH */
float ratedVdc_V; /*!< Rated DC bus voltage in Volts */
float fBase_Hz; /*!< Base value of frequency used for P.U. */
float compFactor; /*!< The factor to compensate the high-frequency voltage and current */
} Hfi_ParamsType;
/*! \brief Defines the HFI object
*/
typedef struct _HfiType_
{
_iq Ia_pu; /*!< Input: The phase-A current */
_iq Ib_pu; /*!< Input: The phase-B current */
_iq Ic_pu; /*!< Input: The phase-C current */
_iq VdAmplitude; /*!< Internal Variable: The amplitude of high-frequency Vd */
_iq compAngle_pu; /*!< Internal Variable: The compensation angle */
_iq angleFactor; /*!< Internal Variable: Factor to calculate angle from speed */
_iq nextAngle_pu; /*!< Internal variable: The angle for next control loop */
ClarkeType clarkeI; /*!< Internal Variable: The Clarke transform for current */
IirFoType lpf; /*!< Internal Variable: The low pass filter for the Iq */
BpSoType IalphaBpf; /*!< Internal Variable: The band-pass filter for the alpha-axis current */
BpSoType IbetaBpf; /*!< Internal Variable: The band-pass filter for the beta-axis current */
FagType fag; /*!< Internal Variable: The high-frequency angle generator */
ParkType park; /*!< Internal Variable: The PARK transform of the injected high-frequency current */
PidType pidPLL; /*!< Internal Variable: The PLL PID */
_iq Vd_hf; /*!< Output: The high-frequency Vd */
_iq estAngle; /*!< Output: The delta angle between the true angle and the one passed in from inputs */
} HfiType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the HFI object
*
* This function initalizes Hfi by setting configuration parameters
*
* \param[in] obj : pointer to Hfi instance
* \param[in] pParams : pointer to Hfi configuration parameters
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Hfi_Init(HfiType *obj, const Hfi_ParamsType *pParams);
/*! \brief Run the HFI process
*
* This function runs Hfi function to control motor
*
* \param[in] obj : pointer to Hfi instance
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Hfi_Run(HfiType *obj);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _HFI_H_ */

View File

@ -0,0 +1,108 @@
/*
* 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 "common/interp/interp2d.h"
#include "ipm_pte.h"
#include "ipm.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void Ipm_Init(IpmType *obj, const Ipm_ParamsType *pParams)
{
obj->type = pParams->type;
obj->maxRows = pParams->maxRows;
obj->maxColumns = pParams->maxColumns;
obj->defaultRs_Ohm = pParams->defaultRs_Ohm;
obj->defaultLd_mH = pParams->defaultLd_mH;
obj->defaultLq_mH = pParams->defaultLq_mH;
obj->defaultPsi_Wb = pParams->defaultPsi_Wb;
obj->Rs_Ohm = obj->defaultRs_Ohm;
if(obj->type == IPM_OUTPUTTYPE_FIXED)
{
obj->Ld_mH = obj->defaultLd_mH;
obj->Lq_mH = obj->defaultLq_mH;
obj->Psi_Wb = obj->defaultPsi_Wb;
}
else if(obj->type == IPM_OUTPUTTYPE_DYNAMIC)
{
Table_Init(&obj->paramTable, pParams->pContainer, obj->maxRows, obj->maxColumns);
/* Calculate row and column interval, the table must have at least 4 elements */
IpmPteType elem00;
IpmPteType elem01;
IpmPteType elem10;
Table_GetElement(&obj->paramTable, (void *)&elem00, sizeof(IpmPteType), 0, 0);
Table_GetElement(&obj->paramTable, (void *)&elem01, sizeof(IpmPteType), 0, 1);
Table_GetElement(&obj->paramTable, (void *)&elem10, sizeof(IpmPteType), 1, 0);
/*! \note The interval between rows and columns must the same for the whole table */
obj->rowInterval = _IQabs(elem10.absId_pu - elem00.absId_pu);
obj->columnInterval = _IQabs(elem01.absIq_pu - elem00.absIq_pu);
obj->oneOverRowIntvl = _IQdiv(_IQ(1.0), obj->rowInterval);
obj->oneOverColumnIntvl = _IQdiv(_IQ(1.0), obj->columnInterval);
}
}
void Ipm_Calc(IpmType *obj)
{
if(obj->type == IPM_OUTPUTTYPE_DYNAMIC)
{
/* The row and column index value should all be ABS */
obj->absId_pu = _IQabs(obj->Id_pu);
obj->absIq_pu = _IQabs(obj->Iq_pu);
/* Find row */
/*! \note The interval between rows must the same for the whole table */
uint16_t row = (uint16_t)(obj->absId_pu / obj->rowInterval);
row = (row > obj->maxRows - 2 ? obj->maxRows - 2 : row);
/* Find column */
/*! \note The interval between columns must the same for the whole table */
uint16_t column = (uint16_t)(obj->absIq_pu / obj->columnInterval);
column = (column > obj->maxColumns - 2 ? obj->maxColumns - 2 : column);
/* Find 4 elements */
IpmPteType topLeft;
IpmPteType topRight;
IpmPteType bottomLeft;
IpmPteType bottomRight;
Table_GetElement(&obj->paramTable, (void *)&topLeft, sizeof(IpmPteType), row, column);
Table_GetElement(&obj->paramTable, (void *)&topRight, sizeof(IpmPteType), row, column + 1);
Table_GetElement(&obj->paramTable, (void *)&bottomLeft, sizeof(IpmPteType), row + 1, column);
Table_GetElement(&obj->paramTable, (void *)&bottomRight, sizeof(IpmPteType), row + 1, column + 1);
_iq rowScale = _IQmpy(obj->absId_pu - topLeft.absId_pu, obj->oneOverRowIntvl);
rowScale = (rowScale > _IQ(1.0) ? _IQ(1.0) : (rowScale < 0 ? 0 : rowScale));
_iq columnScale = _IQmpy(obj->absIq_pu - topLeft.absIq_pu, obj->oneOverColumnIntvl);
columnScale = (columnScale > _IQ(1.0) ? _IQ(1.0) : (columnScale < 0 ? 0 : columnScale));
/* Calculate Ld */
obj->Ld_mH = Interp2d(topLeft.Ld_mH, topRight.Ld_mH, bottomLeft.Ld_mH, bottomRight.Ld_mH, rowScale, columnScale);
/* Calculate Lq */
obj->Lq_mH = Interp2d(topLeft.Lq_mH, topRight.Lq_mH, bottomLeft.Lq_mH, bottomRight.Lq_mH, rowScale, columnScale);
/* Calculate Psi */
obj->Psi_Wb = Interp2d(topLeft.Psi_wb, topRight.Psi_wb, bottomLeft.Psi_wb, bottomRight.Psi_wb, rowScale, columnScale);
}
}

View File

@ -0,0 +1,125 @@
/*
* 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 _IPM_H_
#define _IPM_H_
/*! \brief Contains public interface to various functions related
* to the Interior Permanent Magnet Motor (IPM)
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include "common/iqmath/iqmath.h"
#include "common/container/table.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines the motor object
*/
typedef enum
{
IPM_OUTPUTTYPE_FIXED,
IPM_OUTPUTTYPE_DYNAMIC,
} Ipm_ParamsModeType;
/*! \brief Defines the initial parameters for IPM object
*/
typedef struct _Ipm_ParamsType_
{
Ipm_ParamsModeType type; /*!< How the use motor parameters */
void *pContainer; /*!< Pointer to the table container */
uint16_t maxRows; /*!< Max row number of motor parameter 2-D table */
uint16_t maxColumns; /*!< Max column number of motor parameter 2-D table */
_iq defaultRs_Ohm; /*!< The default value of Rs */
_iq defaultLd_mH; /*!< The default value of Ld */
_iq defaultLq_mH; /*!< The default value of Lq */
_iq defaultPsi_Wb; /*!< The default value of Psi */
} Ipm_ParamsType;
/*! \brief Defines the motor object
*/
typedef struct _IpmType_
{
_iq temp_pu; /*!< Input: Motor temperature */
_iq Id_pu; /*!< Input: D-axis current */
_iq Iq_pu; /*!< Input: Q-axis current */
Ipm_ParamsModeType type; /*!< Parameter: How to use motor parameters */
uint16_t maxRows; /*!< Parameter: Max row number of motor parameter matrix */
uint16_t maxColumns; /*!< Parameter: Max column number of motor parameter matrix */
_iq defaultRs_Ohm; /*!< Parameter: The default value of Rs */
_iq defaultLd_mH; /*!< Parameter: The default value of Ld */
_iq defaultLq_mH; /*!< Parameter: The default value of Lq */
_iq defaultPsi_Wb; /*!< Parameter: The default value of Psi */
TableType paramTable; /*!< Internal variable: The motor parameter table */
_iq rowInterval; /*!< Internal variable: The interval between rows of motor parameter matrix */
_iq columnInterval; /*!< Internal variable: The interval between columns of motor parameter matrix */
_iq oneOverRowIntvl; /*!< Internal variable: Reciprocal of interval between rows of motor parameter matrix */
_iq oneOverColumnIntvl; /*!< Internal variable: Reciprocal of interval between columns of motor parameter matrix */
_iq absId_pu; /*!< Internal variable: ABS value of D-axis current */
_iq absIq_pu; /*!< Internal variable: ABS value of Q-axis current */
_iq Rs_Ohm; /*!< Output: The stator resistance in P.U. */
_iq Ld_mH; /*!< Output: The direct stator inductance in P.U. */
_iq Lq_mH; /*!< Output: The quadrature stator inductance in P.U. */
_iq Psi_Wb; /*!< Output: The permanent magnet flux in P.U. */
} IpmType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the IPM object
*
* This function initalizes Ipm by setting configuration parameters
*
* \param[in] obj : pointer to Ipm instance
* \param[in] pParams : pointer to Ipm configuration parameters
*/
extern void Ipm_Init(IpmType *obj, const Ipm_ParamsType *pParams);
/*! \brief Calculates and Gets the Ipm parameters
*
* This function calculates and gets the Ipm parameters from table data
*
* \param[in] obj : pointer to Ipm instance
*/
extern void Ipm_Calc(IpmType *obj);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _IPM_H_ */

View File

@ -0,0 +1,69 @@
/*
* 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 _IPM_PTE_H_
#define _IPM_PTE_H_
/*! \brief Contains public interface to various functions related
* to the Interior Permanent Magnet Motor (IPM)
* Parameters Table Element (PTE)
*/
/*******************************************************************************
* the includes
******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines the IPM parameters table element
* \note To make it simple we use the ABS value for the row and column,
* but actually the Id normally is negative, and Iq is irrelevant of
* the sign.
* \note The size must align to 4 bytes
*/
typedef struct _IpmPteType_
{
_iq absId_pu; /*!< Donate the row variable - ABS Id value in P.U. */
_iq absIq_pu; /*!< Donate the column variable - ABS Iq value in P.U. */
_iq Ld_mH; /*!< Donate the D-axis inductance in mH */
_iq Lq_mH; /*!< Donate the D-axis inductance in mH */
_iq Psi_wb; /*!< Donate the permanent magnet flux in Wb */
} IpmPteType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _IPM_PTE_H_ */

View File

@ -0,0 +1,79 @@
/*
* 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 _PARK_H_
#define _PARK_H_
/*! \brief Contains the public interface to the
* Park transform module routines
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines the PARK object
*/
typedef struct _ParkType_
{
_iq alpha; /*!< Input: stationary d-axis stator variable */
_iq beta; /*!< Input: stationary q-axis stator variable */
_iq sinTh; /*!< Input: sin value of rotating angle (pu) */
_iq cosTh; /*!< Input: cos value of rotating angle (pu) */
_iq Ds; /*!< Output: rotating d-axis stator variable */
_iq Qs; /*!< Output: rotating q-axis stator variable */
} ParkType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief The main process function of Park
*
* This function runs Park function to calculate rotating axis variable
*
* \param[in] obj : pointer to Park instance
*/
static inline void Park_Run(ParkType *obj)
{
obj->Ds = _IQmpy(obj->alpha, obj->cosTh) + _IQmpy(obj->beta, obj->sinTh);
obj->Qs = _IQmpy(obj->beta, obj->cosTh) - _IQmpy(obj->alpha, obj->sinTh);
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _PARK_H_ */

View File

@ -0,0 +1,106 @@
/*
* 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 _PCUD_H_
#define _PCUD_H_
/*! \brief Contains public interface to various functions related
* to the phase current unbalance detection (PCUD) 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 all the parameters used to initialize PCUD object
*/
typedef struct _Pcud_ParamsType_
{
float unbalanceTh; /*!< the threshold of unbalance, normally will be 1.2 (120%) */
float minDetectI_A; /*!< the minimum detect current in A */
float minDetectFreq_Hz; /*!< the minimum detect frequency in Hz */
float IBase_A; /*!< the current base value in A */
float fBase_Hz; /*!< the base value of frequency used for P.U. */
} Pcud_ParamsType;
/*! \brief Defines the PCUD object
*/
typedef struct _PcudType_
{
_iq Ia_rms; /*!< Input: phase A current */
_iq Ib_rms; /*!< Input: phase B current */
_iq Ic_rms; /*!< Input: phase C current */
_iq speed_pu; /*!< Input: speed feedback in P.U. */
_iq unbalanceTh; /*!< Parameter: The threshold of unbalance */
_iq minDetectI_pu; /*!< Parameter: The minimum detect current in P.U. */
_iq minDetectFreq_pu; /*!< Parameter: The minimum detect frequency in P.U. */
bool isUnbalance; /*!< Output: Whether is unbalanced */
} PcudType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the PCUD object
*
* This function initalizes Pcud by setting configuration parameters
*
* \param[in] obj : pointer to Pcud instance
* \param[in] pParams : pointer to Pcud configuration parameters
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Pcud_Init(PcudType *obj, const Pcud_ParamsType *pParams);
/*! \brief Run the PCUD process
*
* This function runs the phase current unbalance detection
*
* \param[in] obj : pointer to Pcud instance
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Pcud_Run(PcudType *obj);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _PCUD_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.
*/
#ifndef _PHLACK_H_
#define _PHLACK_H_
/*! \brief Contains public interface to various functions related
* to the Phase-lacking (PHLACK) 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 all the parameters used to initialize PHLACK object
*/
typedef struct _Phlack_ParamsType_
{
float runFreq_kHz; /*!< the frequency of running current loop in kHz */
float Vref; /*!< the reference voltage used to detect the current */
float detectFreq_Hz; /*!< the reference frequency used to detect the current */
float detectTime_ms; /*!< the time used to detect the phase lacking */
float currentTh_A; /*!< the current threshold used to determine the phase lacking */
float IBase_A; /*!< the base value of phase current in A */
float fBase_Hz; /*!< the frequency base value in Hz */
float VBase_V; /*!< the base value of voltage in V */
} Phlack_ParamsType;
typedef enum
{
PHLACK_STATUS_FINISH = 0,
PHLACK_STATUS_RUNNING,
} Phlack_StatusType;
/*! \brief Defines the PHLACK object
*/
typedef struct _PhlackType_
{
bool startCmd; /*!< Input: True to command to start, will set false when finished */
_iq Ia_pu; /*!< Input: The current of phase A */
_iq Ib_pu; /*!< Input: the current of phase B */
_iq Ic_pu; /*!< Input: the current of phase C */
_iq detectFreq_pu; /*!< Parameter: The reference frequency used to detect the current */
_iq detectVolt_pu; /*!< Parameter: The reference voltage used to detect the current */
_iq currentTh_pu; /*!< Parameter: The current threshold used to determine the phase lacking */
uint32_t scanCountMax; /*!< Parameter: The max value of count used for timing */
uint32_t scanCount; /*!< Internal variable: The count value used for scan timing */
Phlack_StatusType status; /*!< Internal variable: The status of the current process */
bool flagA; /*!< Internal variable: The phase lacking flag of phase A */
bool flagB; /*!< Internal variable: The phase lacking flag of phase B */
bool flagC; /*!< Internal variable: The phase lacking flag of phase C */
_iq Vref_pu; /*!< Output: The reference voltage in P.U. */
_iq freqRef_pu; /*!< Output: The reference frequency in P.U. */
bool lackingPhaseA; /*!< Output: The final flag output of lacking phase A */
bool lackingPhaseB; /*!< Output: The final flag output of lacking phase B */
bool lackingPhaseC; /*!< Output: The final flag output of lacking phase C */
} PhlackType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the PHLACK object
*
* This function initalizes Phlack by setting configuration parameters
*
* \param[in] obj : pointer to Phlack instance
* \param[in] pParams : pointer to Phlack configuration parameters
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Phlack_Init(PhlackType *obj, const Phlack_ParamsType *pParams);
/*! \brief Run the PHLACK process
*
* This function runs the phase-lacking detection
*
* \param[in] obj : pointer to Phlack instance
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Phlack_Run(PhlackType *obj);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _PHLACK_H_ */

View File

@ -0,0 +1,119 @@
/*
* 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 _PVCR_H_
#define _PVCR_H_
/*! \brief Contains public interface to various functions related
* Phase Voltage and Current Reconstruction (PVCR) object.
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines all the parameters used to initialize PVCR object
*/
typedef struct _Pvcr_ParamsType_
{
float Tdb; /*!< The percent taking account of dead-band time and rise/fall time */
} Pvcr_ParamsType;
/*! \brief Defines the PVCR object
*/
typedef struct _PvcrType_
{
_iq sensedIa; /*!< Input: The sampled current of phase A */
_iq sensedIb; /*!< Input: The sampled current of phase B */
_iq sensedIc; /*!< Input: The sampled current of phase C */
_iq Ta; /*!< Input: 100%-(duty of phase A) */
_iq Tb; /*!< Input: 100%-(duty of phase B) */
_iq Tc; /*!< Input: 100%-(duty of phase C) */
_iq Vdc; /*!< Input: Voltage of DC */
_iq Tdb; /*!< Parameter: The percent taking account of dead-band time and rise/fall time */
_iq offsetV; /*!< Internal variable: The offset voltage of 3 phases, note that all 3 phases's offset are the same */
_iq prevTa; /*!< Internal variable: The previous Ta */
_iq prevTb; /*!< Internal variable: The previous Tb */
_iq prevTc; /*!< Internal variable: The previous Tc */
_iq prevPrevTa; /*!< Internal variable: The previous of previous Ta */
_iq prevPrevTb; /*!< Internal variable: The previous of previous Tb */
_iq prevPrevTc; /*!< Internal variable: The previous of previous Tc; */
_iq prevIa; /*!< Internal variable: The previous Ia */
_iq prevIb; /*!< Internal variable: The previous Ib */
_iq prevIc; /*!< Internal variable: The previous Ic */
_iq Va; /*!< Output: The estimated phase A voltage at the middle of last PWM period */
_iq Vb; /*!< Output: The estimated phase B voltage at the middle of last PWM period */
_iq Vc; /*!< Output: The estimated phase C voltage at the middle of last PWM period */
_iq Ia; /*!< Output: The estimated phase A current at the middle of last PWM period */
_iq Ib; /*!< Output: The estimated phase A current at the middle of last PWM period */
_iq Ic; /*!< Output: The estimated phase A current at the middle of last PWM period */
} PvcrType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the PVCR object
*
* This function initalizes Pvcr by setting configuration parameters
*
* \param[in] obj : pointer to Pvcr instance
* \param[in] pParams : pointer to Pvcr configuration parameters
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Pvcr_Init(PvcrType *obj, const Pvcr_ParamsType *pParams);
/*! \brief Run the PVCR process
* \note The input must use the FOC control result from this loop
*
* This function runs the phase Voltage and current reconstruction function
*
* \param[in] obj : pointer to Pvcr instance
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Pvcr_Run(PvcrType *obj);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _PVCR_H_ */

View File

@ -0,0 +1,130 @@
/*
* 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 _PWMDBC_H_
#define _PWMDBC_H_
/*! \brief Contains public interface to various functions related
* to the PWM Dead-band Compensation (PWMDBC) object.
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines all the parameters used to initialize PWMDBC object
*/
typedef struct _Pwmdbc_ParamsType_
{
float Tdb; /*!< The percent taking account of dead-band time and rise/fall time */
float zeroCurrentTh_A; /*!< The threshold for zero current, in A */
float IBase_A; /*!< Base value of current used for P.U. */
float gain; /*!< Gain value for the compensation */
} Pwmdbc_ParamsType;
/*! \brief Defines the dynamic parameters used to update PWMDBC object
*/
typedef struct _Pwmdbc_DynamicParamsType_
{
float Tdb; /*!< The percent taking account of dead-band time and rise/fall time */
float zeroCurrentTh_A; /*!< The threshold for zero current, in A */
float gain; /*!< Gain value for the compensation */
} Pwmdbc_DynamicParamsType;
/*! \brief Defines the PWMDBC object
*/
typedef struct _PwmdbcType_
{
_iq TaUncomp; /*!< Input: (duty of phase A) - 50% before compensation */
_iq TbUncomp; /*!< Input: (duty of phase B) - 50% before compensation */
_iq TcUncomp; /*!< Input: (duty of phase C) - 50% before compensation */
_iq Ia_pu; /*!< Input: The sampled current of phase A */
_iq Ib_pu; /*!< Input: The sampled current of phase B */
_iq Ic_pu; /*!< Input: The sampled current of phase C */
_iq Tdb; /*!< Parameter: The percent taking account of dead-band time and rise/fall time */
_iq scale; /*!< Parameter: The scale of dead-band percent */
_iq zeroCurrentTh_pu; /*!< Parameter: The threshold for zero current, in P.U. */
float IBase_A; /*!< Parameter: Base value of current used for P.U. */
_iq TaComp; /*!< Input: (duty of phase A) - 50% after compensation */
_iq TbComp; /*!< Input: (duty of phase B) - 50% after compensation */
_iq TcComp; /*!< Input: (duty of phase C) - 50% after compensation */
} PwmdbcType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the PWMDBC object
*
* This function initalizes Pwmdbc by setting configuration parameters
*
* \param[in] obj : pointer to Pwmdbc instance
* \param[in] pParams : pointer to Pwmdbc configuration parameters
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Pwmdbc_Init(PwmdbcType *obj, const Pwmdbc_ParamsType *pParams);
/*! \brief Run the PWMDBC process
*
* This function runs the pwm dead-band compensation function
*
* \param[in] obj : pointer to Pwmdbc instance
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Pwmdbc_Run(PwmdbcType *obj);
/*! \brief Update the parameters of PWMDBC
*
* This function updates the Pwmdbc function configuration parameters
*
* \param[in] obj : pointer to Pwmdbc instance
* \param[in] pParams : pointer to control configuration paramter
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Pwmdbc_UpdateParams(PwmdbcType *obj, const Pwmdbc_DynamicParamsType *pParams);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _PWMDBC_H_ */

View File

@ -0,0 +1,133 @@
/*
* 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 _HALL_H_
#define _HALL_H_
/*! \brief Contains the public interface to the hall abstract class.
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "common/iqmath/iqmath.h"
#include "common/filter/iir_fo.h"
#include "../fag/fag.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines the hall parameters
*/
typedef struct _Hall_ParamsType_
{
float phaseCalcFreq_kHz; /*!< Frequency to run phase calculation */
float spdCalcFreq_kHz; /*!< Frequency to run speed calculation */
float fBase_Hz; /*!< Base value of frequency used for P.U. */
float spdFilterPole_rps; /*!< Pole value of speed filter calculation */
float stamptimerFreq_Hz; /*!< Base clock source frequency */
uint8_t* pForwardHalSqe; /*!< Hall value order */
float timeOutFreq_Hz; /*!< Timeout detection frequency */
} Hall_ParamsType;
/*! \brief Defines the hall object
*/
typedef struct _HallType_
{
uint8_t halValue; /*!< Input: Current hall value */
uint32_t timerCntDiff; /*!< Input: Time of change hall value */
uint32_t dirRef; /*!< Input: Desired direction at startup */
_iq hallAngleBuf_pu[7]; /*!< Parameter: Hall Angle value used for P.U */
uint16_t cntInCycle; /*!< Parameter: Mechanical commutation threshold value */
uint32_t timerOutCnt; /*!< Parameter: Time out count threshold value */
float spdCalCoef; /*!< Parameter: Coefficient of speed calculation*/
float spdCalFastCoef; /*!< Parameter: Coefficient of fast speed calculation*/
_iq halCalibAngle_pu; /*!< Internal variable: Current hall value angle used for P.U */
uint32_t timerCntDiffCycle; /*!< Internal variable: The time count after one turn of the electric angle */
uint8_t halValuePre; /*!< Internal variable: previous hall value */
bool reStartFlag; /*!< Internal variable: Start flag */
int16_t reStartCnt; /*!< Internal variable: Start flag */
uint16_t commutationCnt; /*!< Internal variable: Commutation count */
FagType hallEstObj; /*!< Internal variable: Angle estimation object */
FagType startAngleObj; /*!< Internal variable: Start Angle calculate object */
uint32_t timerCnt; /*!< Internal variable: Running time counter */
uint32_t reStartTimerCnt; /*!< Internal variable: Running time counter */
_iq rawSpeed_pu; /*!< Internal variable: The raw speed before filter in P.U. */
_iq rawSpeedFast_pu; /*!< Internal variable: The raw fast speed in P.U. */
IirFoType filterSpd; /*!< Internal Variable: The filter for electric speed calculation */
_iq angle_pu; /*!< Output: The electrical angle in P.U. */
uint8_t speedDir; /*!< Output: The electrical angle in P.U. */
_iq speed_pu; /*!< Output: The speed in P.U. */
} HallType;
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize hall
*
* This function Initialize hall object by setting configuration parameters
*
* \param[in] obj : pointer to hall instance
* \param[in] pParams : pointer to hall configuration parameters
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Hall_Init(HallType *obj, const Hall_ParamsType *pParams);
/*! \brief Calculate the angle for PARK and IPARK module
*
* \note Must run in the same frequency with current control loop
*
* \param[in] obj : pointer to hall instance
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Hall_EstAngle(HallType *obj);
/*! \brief Calculate the speed
*
* \note Might run slower than current control frequency
*
* \param[in] obj : pointer to Hall instance
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Hall_CalcSpeed(HallType *obj);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _HALL_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 _RESOLVER_H_
#define _RESOLVER_H_
/*! \brief Contains the public interface to the resolver
* abstract class. This would also cover the usage of
* MagnetoResistance position sensor
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "common/iqmath/iqmath.h"
#include "common/pid/pid.h"
#include "common/filter/iir_fo.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines the Resolver parameters
* \note The pole pair scale should not > 128
*/
typedef struct _Resolver_ParamsType_
{
float polePairScale; /*!< Pole pair of the motor / Pole pair of the resolver */
uint16_t reverseDir; /*!< Set this value other than 0 will reverse the positive direction, default to use 0 */
float phaseCalcFreq_kHz; /*!< Frequency to run phase calculation */
float spdCalcFreq_kHz; /*!< Frequency to run phase calculation */
float fBase_Hz; /*!< Base value of frequency used for P.U. */
float responseSpeed_rps; /*!< The response speed in rad/s */
float spdFilterPole_rps; /*!< Pole value of speed filter calculation */
} Resolver_ParamsType;
/*! \brief Defines the dynamic parameters used to update RESOLVER object
*/
typedef struct _Resolver_DynamicParamsType_
{
float phaseCalcFreq_kHz; /*!< Frequency to run phase calculation */
float spdCalcFreq_kHz; /*!< Frequency to run phase calculation */
} Resolver_DynamicParamsType;
/*! \brief Defines the Resolver object
*/
typedef struct _ResolverType_
{
_iq sin_pu; /*!< Input: The sin value in P.U. */
_iq cos_pu; /*!< Input: The cos value in P.U. */
_iq error; /*!< Parameter: error to calculate angle from speed */
_iq angleFactor; /*!< Parameter: Factor to calculate angle from speed */
_iq polePairScale; /*!< Parameter: Pole pair of the motor / Pole pair of the resolver */
uint16_t reverseDir; /*!< Parameter: Set this value other than 0 will reverse the positive direction, default to use 0 */
float phaseCalcFreq_kHz; /*!< Parameter: Frequency to run phase calculation */
float spdCalcFreq_kHz; /*!< Parameter: Frequency to run phase calculation */
uint16_t polePairScaleFactor; /*!< Internal variable: The factor for pole pair scale */
bool firstCalcStatus; /*!< Internal variable: The PLL PID first calculate status */
PidType pidPLL; /*!< Internal variable: The PLL PID */
IirFoType filterSpd; /*!< Internal Variable: The filter for electric speed calculation */
_iq rawSpeed_pu; /*!< Internal variable: The raw speed before filter in P.U. */
_iq currentAngle_pu; /*!< Internal variable: The angle represented by input */
_iq nextAngle_pu; /*!< Internal variable: The angle represented by input */
_iq angle_pu; /*!< Output: The electrical angle in P.U. */
_iq speed_pu; /*!< Output: The speed in P.U. */
} ResolverType;
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize resolver
*
* This function initalizes resolver by setting configuration parameters
*
* \param[in] obj : pointer to Resolver instance
* \param[in] pParams : pointer to Resolver configuration parameters
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Resolver_Init(ResolverType *obj, const Resolver_ParamsType *pParams);
/*! \brief Run the resolver the calculate the phase
* for PARK and IPARK module
* \note Must run in the same frequency with current control loop
*
* \param[in] obj : pointer to Resolver instance
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Resolver_CalcPhase(ResolverType *obj);
/*! \brief Calculate the speed
* \note Might run slower than current control frequency
*
*
* \param[in] obj : pointer to Resolver instance
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Resolver_CalcSpeed(ResolverType *obj);
/*! \brief Update the parameters of Resolver
*
* This function updates the Resolver function configuration parameters
*
* \param[in] obj : pointer to Resolver instance
* \param[in] pParams : pointer to control configuration paramter
* \return the MCUs authorized evaluation
* - -1 : Functions not available
* - 0 : Functions available
*/
extern int32_t Resolver_UpdateParams(ResolverType *obj, const Resolver_DynamicParamsType *pParams);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _RESOLVER_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.
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include "afwsc.h"
/*******************************************************************************
* the defines
******************************************************************************/
#define DAMPING_FACTOR (4)
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void Afwsc_Init(AfwscType *obj, Afwsc_ParamsType *pParams)
{
obj->speedRef = 0;
/* Calculate PID parameters */
_iq Ki_series = _IQ(pParams->spdFilterPole_rps / (DAMPING_FACTOR * DAMPING_FACTOR) * pParams->runFreq_kHz / 1000);
float K = 1.5 * pParams->polePairs * pParams->rotorFlux_Wb / pParams->inertia_kgm2;
_iq Kp_series = _IQ(pParams->spdFilterPole_rps / (K * DAMPING_FACTOR)
* 2 * MATH_PI * pParams->fBase_Hz / pParams->polePairs / pParams->IBase_A);
_iq Kp_parallel = Kp_series;
_iq Ki_parallel = _IQmpy(Ki_series, Kp_series);
Pid_Init(&obj->pidSpd, Kp_parallel, Ki_parallel, 0, _IQ(0), _IQ(pParams->maxCurrent_A / pParams->IBase_A));
Ramp_Init(&obj->spdRamp, _IQ(0.000005));
Fw_Init(&obj->fwObj, _IQ(pParams->minId_A / pParams->IBase_A));
}
void Afwsc_Run(AfwscType *obj)
{
/* Field weakening */
obj->fwObj.refValue = obj->VsRef;
obj->fwObj.fbackValue = obj->Vs;
Fw_Run(&obj->fwObj);
obj->IdRef = obj->fwObj.output;
/* Ramp for the reference */
obj->spdRamp.target = obj->speedRef;
Ramp_Calc(&obj->spdRamp);
/* PID for speed */
obj->pidSpd.ref = obj->spdRamp.output;
obj->pidSpd.fdb = obj->speed;
Pid_Run(&obj->pidSpd);
/* PID output is iq */
obj->IqRef = obj->pidSpd.output;
}
void Afwsc_Reset(AfwscType *obj)
{
obj->fwObj.output = 0;
obj->pidSpd.Ui = 0;
;
obj->IdRef = 0;
obj->IqRef = 0;
}

View File

@ -0,0 +1,115 @@
/*
* 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 _AFWSC_H_
#define _AFWSC_H_
/*! \brief Contains public interface to various functions related
* to the Auto Field-Weakening Speed Control of (AFWSC) object
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include "common/iqmath/iqmath.h"
#include "common/pid/pid.h"
#include "common/curve/ramp.h"
#include "md_lib/fw/fw.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines the initial parameters for AFWSC_IPM object
*/
typedef struct _Afwsc_ParamsType_
{
uint16_t polePairs; /*!< Pole pairs of the motor */
float runFreq_kHz; /*!< Frequency to run */
float fBase_Hz; /*!< Base value of frequency used for P.U. */
float IBase_A; /*!< Base value of current used for P.U. */
float inertia_kgm2; /*!< The inertia of the rotoring system */
float rotorFlux_Wb; /*!< The rotor flux, equal to BEMF in v*s/rad */
float spdFilterPole_rps; /*!< Pole value of speed filter calculation */
float minId_A; /*!< Max value of Id to prevent demagnetization for PM motors */
float maxCurrent_A; /*!< Max value of speed PID output */
} Afwsc_ParamsType;
/*! \brief Defines the AFWSC_IPM object
*/
typedef struct _AfwscType_
{
_iq speedRef; /*!< Input: The speed reference value of speed loop control */
_iq speed; /*!< Input: The speed feedback */
_iq VsRef; /*!< Input: The reference value of Vs */
_iq Vs; /*!< Input: The feedback value of Vs */
PidType pidSpd; /*!< Internal Variable: The PID for speed loop */
RampType spdRamp; /*!< Internal Variable: The ramp for speed reference value */
FwType fwObj; /*!< Internal Variable: The field-weakening object */
_iq IdRef; /*!< Output: The Id reference value */
_iq IqRef; /*!< Output: The Iq reference value */
} AfwscType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the Afwsc object
*
* This function initalizes Afwsc by setting configuration parameters
*
* \param[in] obj : pointer to Afwsc instance
* \param[in] pParams : pointer to Afwsc configuration parameters
*/
extern void Afwsc_Init(AfwscType *obj, Afwsc_ParamsType *pParams);
/*! \brief The main process function of Afwsc
*
* This function runs Afwsc function, perform motor control functions
*
* \param[in] obj : pointer to Svgen instance
*/
extern void Afwsc_Run(AfwscType *obj);
/*! \brief Reset the Afwsc object
*
* This function resets the Afwsc relevant calculation parameters
*
* \param[in] obj : pointer to Afwsc instance
*/
extern void Afwsc_Reset(AfwscType *obj);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _AFWSC_H_ */

View File

@ -0,0 +1,134 @@
/*
* 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 _GDGEN_H_
#define _GDGEN_H_
/*! \brief Contains the public interface to the
* GDPWM generator routines
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines the control mode of the GDGEN
*/
typedef enum
{
GDGEN_MODE_NORMAL = 0, /*!< Normal mode of sine and trapezoid */
GDGEN_MODE_SQUAREWAVE, /*!< Square wave mode */
} Gdgen_ModeType;
/*! \brief Defines the Space Vector Generator object
*/
typedef struct _GdgenType_
{
_iq Ualpha; /*!< Input: reference alpha-axis phase voltage */
_iq Ubeta; /*!< Input: reference beta-axis phase voltage */
Gdgen_ModeType mode; /*!< Parameter: the working mode */
_iq Ta; /*!< Output: reference phase-a switching function */
_iq Tb; /*!< Output: reference phase-b switching function */
_iq Tc; /*!< Output: reference phase-c switching function */
} GdgenType;
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief The main process function of Gdgen
*
* This function runs Gdgen function, perform motor control functions
*
* \param[in] obj : pointer to Gdgen instance
*/
static inline void Gdgen_Run(GdgenType *obj)
{
_iq Vmax, Vcom;
_iq Vref1, Vref2, Vref3;
_iq Va_tmp = -_IQdiv2(obj->Ualpha);
_iq Vb_tmp = _IQmpy(IQMATH_SQRT_THREE_OVER_TWO, obj->Ubeta);
Vref1 = obj->Ualpha; /*alpha */
Vref2 = Va_tmp + Vb_tmp; /*-0.5*alpha + sqrt(3)/2 * beta; */
Vref3 = Va_tmp - Vb_tmp; /*-0.5*alpha - sqrt(3)/2 * beta; */
Vmax = 0;
/* find Vmax, Vcom */
Vmax = (_IQabs(Vref1) > _IQabs(Vref2)) ? Vref1 : Vref2;
if(_IQabs(Vref3) > _IQabs(Vmax))
{
Vmax = Vref3;
}
Vcom = (Vmax > 0) ? (Vmax - _IQ(0.5)) : (Vmax + _IQ(0.5));
/* Subtract common-mode term to achieve GD modulation */
obj->Ta = (Vref1 - Vcom);
obj->Tb = (Vref2 - Vcom);
obj->Tc = (Vref3 - Vcom);
/* If in SquareWave mode, the outputs is not continuous */
if(obj->mode == GDGEN_MODE_SQUAREWAVE)
{
if(obj->Ta > 0)
{
obj->Ta = _IQ(0.5);
}
if(obj->Ta < 0)
{
obj->Ta = -_IQ(0.5);
}
if(obj->Tb > 0)
{
obj->Tb = _IQ(0.5);
}
if(obj->Tb < 0)
{
obj->Tb = -_IQ(0.5);
}
if(obj->Tc > 0)
{
obj->Tc = _IQ(0.5);
}
if(obj->Tc < 0)
{
obj->Tc = -_IQ(0.5);
}
}
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _GDGEN_H_ */

View File

@ -0,0 +1,155 @@
/*
* 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 _SVGEN_H_
#define _SVGEN_H_
/*! \brief Contains the public interface to the
* SVPWM generator routines
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include "common/iqmath/iqmath.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Defines the control mode of the SVGEN
*/
typedef enum
{
SVGEN_MODE_NORMAL = 0, /*!< Normal mode of sine and trapezoid */
SVGEN_MODE_SQUAREWAVE, /*!< Square wave mode */
} Svgen_ModeType;
/*! \brief Defines the Space Vector Generator object
*/
typedef struct _SvgenType_
{
_iq Ualpha; /*!< Input: reference alpha-axis phase voltage */
_iq Ubeta; /*!< Input: reference beta-axis phase voltage */
Svgen_ModeType mode; /*!< Parameter: the working mode */
_iq Ta; /*!< Output: reference phase-a switching function */
_iq Tb; /*!< Output: reference phase-b switching function */
_iq Tc; /*!< Output: reference phase-c switching function */
} SvgenType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief The main process function of Svgen
*
* This function runs Svgen function, perform motor control functions
*
* \param[in] obj : pointer to Svgen instance
*/
static inline void Svgen_Run(SvgenType *obj)
{
_iq Vmax, Vmin, Vcom;
_iq Vref1, Vref2, Vref3;
_iq Va_tmp = -_IQdiv2(obj->Ualpha);
_iq Vb_tmp = _IQmpy(IQMATH_SQRT_THREE_OVER_TWO, obj->Ubeta);
Vref1 = obj->Ualpha; /* alpha */
Vref2 = Va_tmp + Vb_tmp; /* -0.5*alpha + sqrt(3)/2 * beta; */
Vref3 = Va_tmp - Vb_tmp; /* -0.5*alpha - sqrt(3)/2 * beta; */
Vmax = 0;
Vmin = 0;
/* find order Vmin,Vmid,Vmax */
if(Vref1 > Vref2)
{
Vmax = Vref1;
Vmin = Vref2;
}
else
{
Vmax = Vref2;
Vmin = Vref1;
}
if(Vref3 > Vmax)
{
Vmax = Vref3;
}
else if(Vref3 < Vmin)
{
Vmin = Vref3;
}
Vcom = _IQmpy(Vmax + Vmin, _IQ(0.5));
/* Subtract common-mode term to achieve SV modulation */
obj->Ta = (Vref1 - Vcom);
obj->Tb = (Vref2 - Vcom);
obj->Tc = (Vref3 - Vcom);
/* If in SquareWave mode, the outputs is not continuous */
if(obj->mode == SVGEN_MODE_SQUAREWAVE)
{
if(obj->Ta > 0)
{
obj->Ta = _IQ(0.5);
}
if(obj->Ta < 0)
{
obj->Ta = -_IQ(0.5);
}
if(obj->Tb > 0)
{
obj->Tb = _IQ(0.5);
}
if(obj->Tb < 0)
{
obj->Tb = -_IQ(0.5);
}
if(obj->Tc > 0)
{
obj->Tc = _IQ(0.5);
}
if(obj->Tc < 0)
{
obj->Tc = -_IQ(0.5);
}
}
}
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _SVGEN_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,845 @@
/*
* 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(obj->blockSize > 0)
{
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 (1)
/*! \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 = 0x01,
NVM_STATUS_READ = 0x02,
NVM_STATUS_WRITE = 0x03,
NVM_STATUS_GC = 0x04,
NVM_STATUS_UNKNOW = 0x05,
NVM_STATUS_ERROR = 0x06,
} 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;
}
}

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