增加27内容

This commit is contained in:
sunbeam 2024-04-02 09:46:43 +08:00
parent bf1e492546
commit 96b572d62c
101 changed files with 1530 additions and 25739 deletions

View File

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

View File

@ -1,146 +0,0 @@
/*
* 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

@ -1,333 +0,0 @@
/*
* 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

@ -1,194 +0,0 @@
/*
* 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

@ -1,118 +0,0 @@
/*
* 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

@ -1,122 +0,0 @@
/*
* 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

@ -1,301 +0,0 @@
/*
* 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

@ -1,157 +0,0 @@
/*
* 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

@ -1,107 +0,0 @@
/*
* 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

@ -1,148 +0,0 @@
/*
* 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

@ -1,246 +0,0 @@
/*
* 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

@ -1,245 +0,0 @@
/*
* 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

@ -1,159 +0,0 @@
/*
* 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

@ -1,179 +0,0 @@
/*
* 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

@ -1,271 +0,0 @@
/*
* 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

@ -1,197 +0,0 @@
/*
* 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

@ -1,72 +0,0 @@
/*
* 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

@ -1,189 +0,0 @@
/*
* 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

@ -1,237 +0,0 @@
/*
* 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

@ -1,236 +0,0 @@
/*
* 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

@ -1,118 +0,0 @@
/*
* 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

@ -1,165 +0,0 @@
/*
* 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

@ -1,154 +0,0 @@
/*
* 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

@ -1,128 +0,0 @@
/*
* 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

@ -1,139 +0,0 @@
/*
* 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

@ -1,189 +0,0 @@
/*
* 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

@ -1,164 +0,0 @@
/*
* 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

@ -1,239 +0,0 @@
/*
* 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

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

View File

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

View File

@ -1,680 +0,0 @@
/*
* 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)
/*! \brief Network layer result code
*/
#define ISOTP_PROTOCOL_RESULT_OK (0)
#define ISOTP_PROTOCOL_RESULT_TIMEOUT_AS (-1)
#define ISOTP_PROTOCOL_RESULT_TIMEOUT_CS (-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_SetNad(byte, nad) (byte[0] = nad)
#define IsoTp_GetNad(byte) (byte[0])
#define IsoTp_SetPciType(byte, type) (byte[1] = (0xFF & ((((uint8_t)type) << 4) | 0x0f)))
#define IsoTp_GetPciType(byte) ((uint8_t)(byte[1] >> 4))
/*! \brief single frame
* +-------------------------+-----+
* | byte #1 | ... |
* +-------------------------+-----+
* | nibble #0 | nibble #1 | ... |
* +-------------+-----------+ ... +
* | PCIType = 0 | SF_DL | ... |
* +-------------+-----------+-----+
*/
#define IsoTp_SetSFDataLen(byte, len) (byte[1] &= (((uint8_t)len) | 0xf0))
#define IsoTp_GetSFDataLen(byte) (byte[1] & 0x0f)
/*! \brief first frame
* +-------------------------+-----------------------+-----+
* | byte #1 | byte #2 | ... |
* +-------------------------+-----------+-----------+-----+
* | nibble #0 | nibble #1 | nibble #2 | nibble #3 | ... |
* +-------------+-----------+-----------+-----------+-----+
* | PCIType = 1 | FF_DL | ... |
* +-------------+-----------+-----------------------+-----+
*/
#define IsoTp_SetFFDataLen(byte, len) \
do \
{ \
byte[1] &= ((len >> 8) | 0xf0); \
byte[2] = (len & 0xff); \
} while(0)
#define IsoTp_GetFFDataLen(byte) (((((uint16_t)byte[1]) & 0x0f) << 8) + byte[2])
/*! \brief consecutive frame
* +-------------------------+-----+
* | byte #1 | ... |
* +-------------------------+-----+
* | nibble #0 | nibble #1 | ... |
* +-------------+-----------+ ... +
* | PCIType = 2 | SN | ... |
* +-------------+-----------+-----+
*/
#define IsoTp_SetCFSn(byte, sn) (byte[1] &= (((uint8_t)sn) | 0xf0))
#define IsoTp_GetCFSn(byte) (byte[1] & 0x0f)
/*******************************************************************************
* 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
******************************************************************************/
static int8_t IsoTp_SendSingleFrame(IsoTpType *obj)
{
int8_t ret;
uint8_t i = 0;
uint8_t index = 0;
IsoTp_MsgType msg;
/* Setup message */
IsoTp_SetNad(msg.byte, obj->physNad);
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 + 2] = obj->sendBuffer[index];
}
/* All pad with 0 */
for(i = 0; i < 6 - obj->sendSize; ++i)
{
msg.byte[i + obj->sendSize + 2] = 0;
}
/* Send message */
ret = obj->sendLinMsg(msg.byte, 8);
return ret;
}
static int8_t IsoTp_SendFirstFrame(IsoTpType *obj)
{
int8_t ret;
uint8_t index = 0;
IsoTp_MsgType msg;
/* Setup message */
IsoTp_SetNad(msg.byte, obj->physNad);
IsoTp_SetPciType(msg.byte, ISOTP_PCI_TYPE_FIRST_FRAME);
IsoTp_SetFFDataLen(msg.byte, obj->sendSize);
for(index = 0; index < 5; ++index) /* 6 data bytes for the first frame */
{
msg.byte[index + 3] = obj->sendBuffer[index];
}
/* Send message */
ret = obj->sendLinMsg(msg.byte, 8);
if(ISOTP_RET_OK == ret)
{
obj->sendOffset += 5; /* 5 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_SetNad(msg.byte, obj->physNad);
IsoTp_SetPciType(msg.byte, ISOTP_PCI_TYPE_CONSECUTIVE_FRAME);
IsoTp_SetCFSn(msg.byte, obj->sendSN);
dataLength = obj->sendSize - obj->sendOffset;
if(dataLength > 6) /* Max 6 data bytes for the consecutive frame */
{
dataLength = 6;
}
for(index = 0; index < dataLength; ++index)
{
msg.byte[index + 2] = obj->sendBuffer[obj->sendOffset + index];
}
/* All pad with 0 */
uint8_t i = 0;
for(i = 0; i < 6 - dataLength; ++i)
{
msg.byte[i + 2 + dataLength] = 0;
}
/* Send message */
ret = obj->sendLinMsg(msg.byte, 8);
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;
uint8_t nad = IsoTp_GetNad(pMsg->byte);
/* Check NAD */
if((nad != obj->physNad) && (nad != obj->funcNad) && (nad != obj->broadcastNad))
{
if(obj->debug != NULL)
{
obj->debug("Single-frame NAD is not match.");
}
return ISOTP_RET_WRONG_NAD;
}
/* Check data length */
if((0 == IsoTp_GetSFDataLen(pMsg->byte))
|| (IsoTp_GetSFDataLen(pMsg->byte) > (len - 2)))
{
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 + 2];
}
/* 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;
uint8_t nad = IsoTp_GetNad(pMsg->byte);
/* Check NAD */
if((nad != obj->physNad) && (nad != obj->funcNad) && (nad != obj->broadcastNad))
{
if(obj->debug != NULL)
{
obj->debug("Single-frame NAD is not match.");
}
return ISOTP_RET_WRONG_NAD;
}
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 <= 6)
{
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 < 5; ++index) /* 5 data bytes for the first frame */
{
obj->receiveBuffer[index] = pMsg->byte[index + 3];
}
obj->receiveOffset = 5; /* 5 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;
uint8_t nad = IsoTp_GetNad(pMsg->byte);
/* Check NAD */
if(nad != obj->receiveArbitrationNad)
{
if(obj->debug != NULL)
{
obj->debug("Single-frame NAD is not match.");
}
return ISOTP_RET_WRONG_NAD;
}
/* 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 > 6) /* Max 6 data bytes for the consecutive frame */
{
remaining_bytes = 6;
}
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 + 2];
}
obj->receiveOffset += remaining_bytes;
if(++(obj->receiveSN) > 0x0F)
{
obj->receiveSN = 0;
}
return ISOTP_RET_OK;
}
int8_t IsoTp_Send(IsoTpType *obj, const uint8_t payload[], uint16_t size)
{
int8_t ret = ISOTP_RET_OK;
uint8_t i = 0;
if(obj == NULL)
{
return ISOTP_RET_ERROR;
}
if((obj->receiveArbitrationNad == obj->funcNad) || (obj->receiveArbitrationNad == obj->broadcastNad))
{
return ISOTP_RET_OK;
}
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 < 7)
{
/* 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)
{
/* Refresh AS timer */
obj->sendTimerAs = obj->getTimeMs() + ISOTP_DEFAULT_CONFIRM_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_HandleIncomingLinMsg(IsoTpType *obj, const uint8_t *data, uint8_t len)
{
int8_t ret;
uint8_t i = 0;
IsoTp_MsgType msg;
if(len < 2 || len > 8)
{
return;
}
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->receiveArbitrationNad = IsoTp_GetNad(msg.byte);
/* 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;
break;
}
/* If receive successful */
if(ISOTP_RET_OK == ret)
{
obj->receiveArbitrationNad = IsoTp_GetNad(msg.byte);
/* Change status */
obj->receiveStatus = ISOTP_RECEIVE_STATUS_INPROGRESS;
/* 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(IsoTp_GetNad(msg.byte) != obj->receiveArbitrationNad)
{
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;
}
}
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->receiveArbitrationNad == link->funcNad) ? 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->physNad = pParams->physNad;
obj->funcNad = pParams->funcNad;
obj->broadcastNad = pParams->broadcastNad;
obj->sendBuffer = pParams->sendBuf;
obj->sendBufferSize = pParams->sendBufSize;
obj->sendSize = 0;
obj->sendOffset = 0;
obj->sendSN = 0;
obj->sendTimerAs = 0;
obj->sendTimerSeptime = 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->receiveTimerCr = 0;
obj->receiveProtocolResult = ISOTP_PROTOCOL_RESULT_OK;
obj->receiveStatus = ISOTP_RECEIVE_STATUS_IDLE;
obj->debug = pParams->debug;
obj->sendLinMsg = pParams->sendLinMsg;
obj->isLinSendComplete = pParams->isLinSendComplete;
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(obj->isLinSendComplete())
{
ret = IsoTp_SendConsecutiveFrame(obj);
if(ISOTP_RET_OK == ret)
{
/* 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->sendTimerAs))
{
obj->sendProtocolResult = ISOTP_PROTOCOL_RESULT_TIMEOUT_AS;
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

@ -1,209 +0,0 @@
/*
* 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 17987-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)
#define ISOTP_RET_WRONG_NAD (-8)
/*! \brief The default timeout to use when waiting for a response during a multi-frame receive.
*/
#define ISOTP_DEFAULT_RESPONSE_TIMEOUT (1000)
/*! \brief The default timeout to use when waiting for a frame send confirmed.
*/
#define ISOTP_DEFAULT_CONFIRM_TIMEOUT (1000)
/*******************************************************************************
* 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_SendLinMsgShim)(const uint8_t *pData, const uint8_t size);
/*! \brief User implemented, get whether send complete or not
*/
typedef bool (*IsoTp_IsLinSendComplete)(void);
/*! \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_
{
uint8_t physNad; /*!< physical addressing id */
uint8_t funcNad; /*!< functional addressing id */
uint8_t broadcastNad; /*!< functional addressing id */
uint8_t *sendBuf; /*!< message send buffer */
uint16_t sendBufSize; /*!< the size of send buffer */
uint8_t *recvBuf; /*!< message receive buffer */
uint16_t recvBufSize; /*!< the size of receive buffer */
IsoTp_DebugShim debug; /*!< the adapter of debug function */
IsoTp_SendLinMsgShim sendLinMsg; /*!< the adapter of lin-send-message function */
IsoTp_IsLinSendComplete isLinSendComplete; /*!< the adapter of is-lin-send-complete function
return value:
false--data is sending or waiting send
true--data send complete or no data need to send */
IsoTp_GetTimeShimMs getTimeMs; /*!< the adapter of get-time-stamp function */
} 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_
{
uint8_t physNad; /*!< physical addressing id */
uint8_t funcNad; /*!< functional addressing id */
uint8_t broadcastNad; /*!< functional addressing id */
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 */
int64_t sendTimerAs; /*!< Time until of the Frame N_PDU start at send start end at send confirmed */
int64_t sendTimerSeptime; /*!< Last time send consecutive frame */
int sendProtocolResult; /*!< the result of send protocol */
uint8_t sendStatus; /*!< the send status */
uint8_t receiveArbitrationNad; /*! 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 */
int64_t receiveTimerCr; /*!< Time until reception of the next ConsecutiveFrame N_PDU start at receive FF or CF end at receive CF */
int8_t receiveProtocolResult; /*!< the result of receive protocol */
uint8_t receiveStatus; /*!< the receive status */
IsoTp_DebugShim debug; /*!< the adapter of debug function */
IsoTp_SendLinMsgShim sendLinMsg; /*!< the adapter of lin-send-message function */
IsoTp_IsLinSendComplete isLinSendComplete; /*!< the adapter of is-lin-send-complete function
return value:
false--data is sending waiting send
true--data send complete or no data need to send */
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] pData : pointer to data of incoming CAN frame
* \param[in] len : the length of data of incoming CAN frame
*/
extern void IsoTp_HandleIncomingLinMsg(IsoTpType *obj, 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 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

@ -1,49 +0,0 @@
/*
* 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 <string.h>
#include "lin_cfg.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
const Lin_CfgType gLin_Cfg = {
.protocolVersion = LINCFG_PROTOCOL_VER,
.productId = 0x112233,
.linSpeed = LINCFG_BAUDRATE,
.configNad = 0x03,
.initialNad = 0x03,
.p2Min = 50,
.stMin = 1,
.timeoutNAs = 1000,
.timeoutNCr = 1000};
/*******************************************************************************
* the functions
******************************************************************************/

View File

@ -1,181 +0,0 @@
/*
* 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 _LIN_CFG_H_
#define _LIN_CFG_H_
/*! \brief Contains public interface to various functions related
* to the lin module
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
/*! \addtogroup lin_cfg
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/* LIN Communication protocol version */
#define LIN_PROTOCOL_VER_22 (0x22u)
#define LIN_PROTOCOL_VER_21 (0x21u)
#define LIN_PROTOCOL_VER_20 (0x20u)
#define LIN_PROTOCOL_VER_13 (0x13u)
#define LIN_PROTOCOL_VER_12 (0x12u)
#define LIN_PROTOCOL_VER_11 (0x11u)
#define LINCFG_PROTOCOL_VER LIN_PROTOCOL_VER_22
#define LINCFG_NODE_ADDRESS (0x00)
/* Lin communication baudrate */
#define LINCFG_BAUDRATE (19200u)
/* Node address for sleep command */
#define LINCFG_NAD_FOR_SLEEP (0u)
/* Node feature type select, be used as master or slave node */
#define LINCFG_NODE_MASTER (1u)
#define LINCFG_NODE_SLAVE (0u)
#define LINCFG_NODE_USED LINCFG_NODE_MASTER
/* the actual physical channel in MCU that be supported to be used as lin bus */
#define LINCFG_CH_IDX_0 (0u)
#define LINCFG_CH_IDX_1 (1u)
#define LINCFG_CH_IDX_2 (2u)
#define LINCFG_CH_IDX_3 (3u)
/* Define how many hard physical channel are used */
#define LINCFG_CH_ACTIVE (1u)
#define LINCFG_CH_INACTIVE (0u)
/* Select the physical channel as master used */
#if LINCFG_NODE_USED == LINCFG_NODE_MASTER
/* Define the actual channel is used by master node, the rest channels are used for slave node */
#define LINCFG_CH0_USED (LINCFG_CH_ACTIVE)
#define LINCFG_CH1_USED (LINCFG_CH_INACTIVE)
#define LINCFG_CH2_USED (LINCFG_CH_INACTIVE)
#define LINCFG_CH3_USED (LINCFG_CH_INACTIVE)
#define LINCFG_CH_NUM (LINCFG_CH0_USED + LINCFG_CH1_USED + LINCFG_CH2_USED + LINCFG_CH3_USED)
#define LINCFG_MASTER_CH_IDX LINCFG_CH_IDX_0
#else
/* Define the actual channel is used by master node, the rest channels are used for slave node */
#define LINCFG_CH0_USED (LINCFG_CH_ACTIVE)
#define LINCFG_CH1_USED (LINCFG_CH_INACTIVE)
#define LINCFG_CH2_USED (LINCFG_CH_INACTIVE)
#define LINCFG_CH3_USED (LINCFG_CH_INACTIVE)
#define LINCFG_CH_NUM (LINCFG_CH0_USED + LINCFG_CH1_USED + LINCFG_CH2_USED + LINCFG_CH3_USED)
/* Select the physical channel as slave used if more than one channels are used in the current slave node, should select one channel as a wakeup source,
No need all channels send the wakeup signal if the internal requirement
*/
#define LINCFG_SLAVE_CH_AS_WAKEUP_IDX LINCFG_CH_IDX_0
#endif
/* Define the feature of hardware detected break with sync signal together */
#if LINCFG_NODE_USED == LINCFG_NODE_MASTER
#define LINCFG_AUTO_SYNC_EN (0u)
#else
#define LINCFG_AUTO_SYNC_EN (1u)
#endif
/* Frame time slot base tick = 1ms */
#define LINCFG_TICK_BASE (1u)
/* When node is as a subscriber, no response from last received data is more than this time, timeout is existed */
#define LINCFG_RESP_BYTE_TIMEOUT_MAX_CNT (LINCFG_TICK_BASE * 5u)
/* Define the wakeup signal duration time, unit: ms default value: 2ms */
#define LINCFG_WAKEUP_SIGNAL_CHECK_VALID_MIN_CNT (2u)
#define LINCFG_WAKEUP_SIGNAL_DURATION_MIN_CNT (4u)
/* Define the duration to start communication after wakeup by bus or by self, unit: ms */
#define LINCFG_START_COM_AFTER_WKP_CNT (10u)
/* After idle timeout , bus enter into sleep mode, unit: ms */
#define LINCFG_BUS_IDLE_TICK_CNT (10000u)
/* Define the first received header for slave node after be wakeup by bus */
#define LINCFG_FAST_WAKEUP_PERIOD (100u)
/* The delay time of retry wakeup bus again after failed to wakeup bus that is up to 3 times, unit: ms */
#define LINCFG_SLOW_WAKEUP_PEIROD (1500u)
/* Define the value of retry to wakeup the bus */
#define LINCFG_WAKEUP_RETRY_MAX_CNT (3u)
/* If slave node wakeup the bus actively, but in the period, no valid header is received from master, the slave can retry to wakeup */
#define LINCFG_WAKEUP_FAILED_TIMEOUT (200u)
/*******************************************************************************
* the typedefs
******************************************************************************/
typedef struct
{
uint32_t protocolVersion;
uint8_t configNad;
uint8_t initialNad;
uint32_t productId;
uint32_t p2Min;
uint32_t stMin;
uint32_t timeoutNAs;
uint32_t timeoutNCr;
uint32_t linSpeed;
} Lin_CfgType;
#if LINCFG_CH0_USED == LINCFG_CH_ACTIVE
#endif
#if LINCFG_CH1_USED == LINCFG_CH_ACTIVE
#endif
#if LINCFG_CH2_USED == LINCFG_CH_ACTIVE
#endif
#if LINCFG_CH3_USED == LINCFG_CH_ACTIVE
#endif
/*******************************************************************************
* the globals
******************************************************************************/
extern const Lin_CfgType gLin_Cfg;
/*******************************************************************************
* the function prototypes
******************************************************************************/
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _LIN_CFG_H_ */

View File

@ -1,197 +0,0 @@
/*
* 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 <string.h>
#include "lin_schedule.h"
#include "lin_com.h"
#include "lin_nm.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
Lin_FrameDataType *pLinCom_CurrentFrameData = 0;
/*******************************************************************************
* the functions
******************************************************************************/
/*! \brief Get the link data buffer pointer according to pid index
*
* This function execute to initialize the communication module
*
* \param[in] pidIdx: frame index
* \param[in] dataBufferPtr: the data buffer which be stored in upper layer
* \return: void
*/
Lin_FrameDataType *LinCom_GetFramePointer(uint8_t pidIdx)
{
return &pLinCom_CurrentFrameData[pidIdx];
}
/*! \brief Initialize the communication module
*
* This function execute to initialize the communication module
*
* \param[in] dataBufferPtr: the data buffer which be stored in upper layer
* \param[in] frameNum: the total frame num in the upper layer be used
* \return: void
*/
void LinCom_Init(Lin_FrameDataType *dataBufferPtr, uint8_t frameNum)
{
pLinCom_CurrentFrameData = dataBufferPtr;
}
/*! \brief Update the tx signal
*
* This function execute to update the tx signal from local to lower lay frame buffer
*
* \param[in] pidIdx: pid index
* \return: void
*/
void linCom_BusTxSignalUpdate(uint8_t pidIdx)
{
Lin_FrameAccessStateType frameAccessState;
frameAccessState = LinSchedule_GetFrameAccessState(pidIdx);
if((frameAccessState == LIN_FRAME_ACCESS_STATE_IDLE) || (frameAccessState == LIN_FRAME_ACCESS_STATE_UPDATED))
{
Lin_FrameDataType *pFrameDataPtr = 0;
pFrameDataPtr = LinSchedule_GetFrameBufferPtr(pidIdx);
if(pFrameDataPtr != 0u)
{
if(memcmp(&pLinCom_CurrentFrameData[pidIdx], pFrameDataPtr, sizeof(Lin_FrameDataType)) != 0u)
{
LinSchedule_SetFrameAccessState(pidIdx, LIN_FRAME_ACCESS_STATE_WRITING_IN);
memcpy(pFrameDataPtr, &pLinCom_CurrentFrameData[pidIdx], sizeof(Lin_FrameDataType));
/* Indicate the data has changed values */
LinSchedule_SetFrameAccessState(pidIdx, LIN_FRAME_ACCESS_STATE_UPDATED);
}
}
}
}
/*! \brief Update the rx signal
*
* This function execute to update the received data from lower layer frame buffer to local
*
* \param[in] channelIdx: which physical channel is used
* \param[in] pidIdx: pid index
* \return: void
*/
void linCom_BusRxSignalUpdate(uint8_t channelIdx, uint8_t pidIdx)
{
Lin_FrameAccessStateType frameAccessState;
/* These frames are received by slave node */
frameAccessState = LinSchedule_GetFrameAccessState(pidIdx);
if(frameAccessState == LIN_FRAME_ACCESS_STATE_UPDATED || frameAccessState == LIN_FRAME_ACCESS_STATE_OVER_RECEIVED)
{
Lin_FrameDataType *pFrameDataPtr = NULL;
Lin_FrametypeType frameType = LIN_FRAME_TYPE_RESERVED;
/* Process the received data from bus */
frameType = LinSchedule_GetFrameType(channelIdx, pidIdx);
pFrameDataPtr = LinSchedule_GetFrameBufferPtr(pidIdx);
if(pFrameDataPtr != NULL)
{
/* Update the event trigger data into the associated unconditional frame */
if(frameType == LIN_FRAME_TYPE_EVENT_TRIGGER)
{
uint8_t linkPidIdx = 0;
linkPidIdx = LinSchedule_GetPidIdx(pFrameDataPtr->poyload.eventBytes.pid);
if((pFrameDataPtr != NULL) && (linkPidIdx != LIN_DATA_INVALID))
{
memcpy(&pLinCom_CurrentFrameData[pidIdx], pFrameDataPtr, sizeof(Lin_FrameDataType));
LinSchedule_SetFrameAccessState(pidIdx, LIN_FRAME_ACCESS_STATE_IDLE);
}
}
else
{
memcpy(&pLinCom_CurrentFrameData[pidIdx], pFrameDataPtr, sizeof(Lin_FrameDataType));
LinSchedule_SetFrameAccessState(pidIdx, LIN_FRAME_ACCESS_STATE_IDLE);
if(LinSchedule_GetPid(pidIdx) == LIN_STACK_PID_MRF)
{
#if LINCFG_NODE_USED == LINCFG_NODE_SLAVE
if(pLinCom_CurrentFrameData[pidIdx].poyload.diagBytes.nad == LINCFG_NAD_FOR_SLEEP)
{
/* Get the sleep command from the bus */
LinNm_RequestSleep(true);
}
else
{
/* TODO: Call out TP */
}
#else
/* TODO: Call out TP */
#endif
}
else if(LinSchedule_GetPid(pidIdx) == LIN_STACK_PID_SRF)
{
/* TODO: Call out TP */
}
}
}
}
}
/*! \brief Process the local signal of tx or rx
*
* This function execute to update local tx to lower frame buffer or update rx from lower to rx local
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
void LinCom_MainFunction(uint8_t channelIdx)
{
Lin_FrameCtrlType frameCtrl;
uint8_t i = 0, tempFrameNum = 0;
tempFrameNum = LinSchedule_GetFrameNum(channelIdx);
for(i = 0; i < tempFrameNum; i++)
{
frameCtrl = LinSchedule_GetFrameCtrl(channelIdx, i);
if(frameCtrl == LIN_FRAME_CTRL_PUBLISH)
{
/* These frames are transmit by slave node */
linCom_BusTxSignalUpdate(i);
}
else if(frameCtrl == LIN_FRAME_CTRL_SUBSCRIBER)
{
linCom_BusRxSignalUpdate(channelIdx, i);
}
}
}

View File

@ -1,118 +0,0 @@
/*
* 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 _LIN_COM_H_
#define _LIN_COM_H_
/*! \brief his file exports Lin communication
*
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "lin_type.h"
#include "lin_cfg.h"
/*! \addtogroup lin_com
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
typedef struct
{
Lin_FrameDataType *pCurrentFrameData;
uint32_t counter;
} LinCom_FrameInfoType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the communication module
*
* This function execute to initialize the communication module
*
* \param[in] dataBufferPtr: the data buffer which be stored in upper layer
* \param[in] frameNum: the total frame num in the upper layer be used
* \return: void
*/
extern void LinCom_Init(Lin_FrameDataType *dataBufferPtr, uint8_t frameNum);
/*! \brief Get the link data buffer pointer according to pid index
*
* This function execute to initialize the communication module
*
* \param[in] pidIdx: frame index
* \param[in] dataBufferPtr: the data buffer which be stored in upper layer
* \return: void
*/
extern Lin_FrameDataType *LinCom_GetFramePointer(uint8_t pidIdx);
/*! \brief Update the tx signal
*
* This function execute to update the tx signal from local to lower lay frame buffer
*
* \param[in] pidIdx: pid index
* \return: void
*/
extern void linCom_BusTxSignalUpdate(uint8_t pidIdx);
/*! \brief Update the rx signal
*
* This function execute to update the received data from lower layer frame buffer to local
*
* \param[in] channelIdx: which physical channel is used
* \param[in] pidIdx: pid index
* \return: void
*/
extern void linCom_BusRxSignalUpdate(uint8_t channelIdx, uint8_t pidIdx);
/*! \brief Process the local signal of tx or rx
*
* This function execute to update local tx to lower frame buffer or update rx from lower to rx local
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
extern void LinCom_MainFunction(uint8_t channelIdx);
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _LIN_COM_H_ */

View File

@ -1,778 +0,0 @@
/*
* 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 <string.h>
#include "lin_if.h"
#include "lin_schedule.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
static LinIf_CtrlInfoType sLinIf_CtrlInfo;
/*******************************************************************************
* the functions
******************************************************************************/
/*! \brief Convert frame id to pid
*
* This function execute to convert the frame id to protected id
*
* \param[in] frameId: Frame id, this includes the low 6bit
* \return: the result of convert pid
*/
uint8_t LinIf_ConvertFrameIdToPid(uint8_t frameId)
{
uint8_t ret = frameId;
uint8_t i = 0, tempP0 = 0, tempP1 = 0, tempBit = 0;
for(i = 0; i < 6; i++)
{
if(((frameId >> i) & 0x01) != 0u)
{
tempBit = 1;
}
else
{
tempBit = 0;
}
if((i == 0) || (i == 2))
{
/* P0 */
if(i == 0)
{
tempP0 = tempBit;
}
else
{
tempP0 = tempP0 ^ tempBit;
}
}
else if((i == 3) || (i == 5))
{
/* P1 */
tempP1 = tempP1 ^ tempBit;
if(i == 5)
{
if(tempP1 == 0x01)
{
tempP1 = 0x00;
}
else
{
tempP1 = 0x01;
}
}
}
else
{
/* P1 */
if(i == 1)
{
tempP1 = tempBit;
}
else
{
tempP1 = tempP1 ^ tempBit;
}
tempP0 = tempP0 ^ tempBit;
}
}
ret = (ret | (tempP0 << 6));
ret = (ret | (tempP1 << 7));
return ret;
}
/*! \brief Convert pid to frame id
*
* This function execute to convert pid to frame id
*
* \param[in] pid: protected id
* \return: the result of convert frame id
*/
uint8_t LinIf_ConvertPidToFrameId(uint8_t pid)
{
uint8_t ret = LIN_DATA_INVALID, tempPid = pid;
uint8_t i = 0, tempP0 = 0, tempP1 = 0, tempBit = 0;
for(i = 0; i < 6; i++)
{
if(((tempPid >> i) & 0x01) != 0u)
{
tempBit = 1;
}
else
{
tempBit = 0;
}
if((i == 0) || (i == 2))
{
/* P0 */
if(i == 0)
{
tempP0 = tempBit;
}
else
{
tempP0 = tempP0 ^ tempBit;
}
}
else if((i == 3) || (i == 5))
{
/* P1 */
tempP1 = tempP1 ^ tempBit;
if(i == 5)
{
if(tempP1 == 0x01)
{
tempP1 = 0x00;
}
else
{
tempP1 = 0x01;
}
}
}
else
{
tempP0 = tempP0 ^ tempBit;
/* P1 */
if(i == 1)
{
tempP1 = tempBit;
}
else
{
tempP1 = tempP1 ^ tempBit;
}
}
}
if(tempP0 == ((tempPid >> 6) & 0x01))
{
if(tempP1 == ((tempPid >> 7) & 0x01))
{
ret = (pid & 0x3F);
}
}
if((tempP0 == ((tempPid >> 6) & 0x01)) && (tempP1 == ((tempPid >> 7) & 0x01)))
{
ret = (pid & 0x3F);
}
return ret;
}
/*! \brief Set the sleep request indication flag
*
* This function execute to sleep request indication, Indication Upper layer that go to sleep cmd is doing
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
void LinIf_SetSleepRequestIndication(uint8_t channelIdx)
{
sLinIf_CtrlInfo.pduState[channelIdx].sleepReqIndication = true;
}
/*! \brief Clear the sleep request
*
* This function execute to clear the sleep reqeust indication
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
void LinIf_ClearSleepRequestIndication(uint8_t channelIdx)
{
sLinIf_CtrlInfo.pduState[channelIdx].sleepReqIndication = false;
}
/*! \brief Get the sleep request indication
*
* This function execute to get the sleep request indication after enter into prepare sleep mode
*
* \param[in] channelIdx: which physical channel is used
* \return: bool
*/
bool LinIf_GetSleepRequestIndication(uint8_t channelIdx)
{
bool ret = false;
ret = sLinIf_CtrlInfo.pduState[channelIdx].sleepReqIndication;
return ret;
}
/*! \brief Request transmit the frame
*
* This function execute to request transmit the frame, the function is only used by master node
*
* \param[in] channelIdx: which physical channel is used
* \param[in] frameInfoPtr: the pointer of frame
* \return: true: request transmit successfully
* false: request transmit failed
*/
bool LinIf_ReqTransmit(uint8_t channelIdx, const Lin_FrameInfoType *frameInfoPtr)
{
bool ret = false;
sLinIf_CtrlInfo.pduState[channelIdx].opStatusInfo = LIN_STATUS_READY;
sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameCtrl = frameInfoPtr->frameCtrl;
sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameType = frameInfoPtr->frameType;
sLinIf_CtrlInfo.pduState[channelIdx].pdu.pid = frameInfoPtr->pid;
sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx = LinSchedule_GetPidIdx(frameInfoPtr->pid);
sLinIf_CtrlInfo.pduState[channelIdx].pdu.checkSumType = LinSchedule_GetCheckSumType(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pid);
if(sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameCtrl == LIN_FRAME_CTRL_PUBLISH)
{
sLinIf_CtrlInfo.pduState[channelIdx].pdu.dataLen = frameInfoPtr->dataLen;
if((LinSchedule_GetFrameAccessState(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx) == LIN_FRAME_ACCESS_STATE_IDLE) || (LinSchedule_GetFrameAccessState(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx) == LIN_FRAME_ACCESS_STATE_UPDATED))
{
/* Copy pdu to local buffer */
memcpy(&sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameData, frameInfoPtr->pFrameData, sizeof(Lin_FrameDataType));
sLinIf_CtrlInfo.pduState[channelIdx].pdu.checkSum = sLinIf_CtrlInfo.pLinIf_CallBackFuncListPtr->pLinIf_CalculateChecksumFunction(sLinIf_CtrlInfo.pduState[channelIdx].pdu.checkSumType,
sLinIf_CtrlInfo.pduState[channelIdx].pdu.pid,
(const uint8_t *)&sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameData.poyload.byteData[0],
sLinIf_CtrlInfo.pduState[channelIdx].pdu.dataLen);
LinSchedule_SetFrameAccessState(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx, LIN_FRAME_ACCESS_STATE_IDLE);
ret = sLinIf_CtrlInfo.pLinIf_CallBackFuncListPtr->pLinIf_SendFrameFunction(channelIdx, &sLinIf_CtrlInfo.pduState[channelIdx].pdu);
}
}
else if(sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameCtrl == LIN_FRAME_CTRL_SUBSCRIBER)
{
/* If the current frame is an event-trigger, then the datalen is get from the next step, not in current step, just set with the max value to it */
if(sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameType == LIN_FRAME_TYPE_EVENT_TRIGGER)
{
sLinIf_CtrlInfo.pduState[channelIdx].pdu.dataLen = 8;
}
else
{
sLinIf_CtrlInfo.pduState[channelIdx].pdu.dataLen = frameInfoPtr->dataLen;
}
if(LinSchedule_GetFrameAccessState(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx) == LIN_FRAME_ACCESS_STATE_IDLE)
{
if(sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameCtrl == LIN_FRAME_CTRL_SUBSCRIBER)
{
LinSchedule_SetFrameAccessState(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx, LIN_FRAME_ACCESS_STATE_READING_OUT);
}
sLinIf_CtrlInfo.pduState[channelIdx].upperLevelFrameDataPtr = LinSchedule_GetFrameBufferPtr(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx);
ret = sLinIf_CtrlInfo.pLinIf_CallBackFuncListPtr->pLinIf_SendFrameFunction(channelIdx, &sLinIf_CtrlInfo.pduState[channelIdx].pdu);
}
}
else if(sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameCtrl == LIN_FRAME_CTRL_NO_ACTION)
{
sLinIf_CtrlInfo.pduState[channelIdx].pdu.dataLen = 0;
if(LinSchedule_GetFrameAccessState(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx) == LIN_FRAME_ACCESS_STATE_IDLE)
{
sLinIf_CtrlInfo.pduState[channelIdx].upperLevelFrameDataPtr = LinSchedule_GetFrameBufferPtr(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx);
ret = sLinIf_CtrlInfo.pLinIf_CallBackFuncListPtr->pLinIf_SendFrameFunction(channelIdx, &sLinIf_CtrlInfo.pduState[channelIdx].pdu);
}
}
else
{
}
return ret;
}
/*! \brief The call-back function when received valid header
*
* This function execute to process the pdu attribute by received pid, this function is only used by slave node, this is called by isr
*
* \param[in] uint8_t channelIdx: which physical channel is used
* \param[in] pid: the received pid
* \param[in] pduInfoPtr: the local pdu pointer
* \return: true: the current received pid is valid and the frame control is not the no-action type
* false; the pid is invalid or not supported or the frame control is the no-action type
*/
bool LinIf_HeaderIndication(uint8_t channelIdx, uint8_t pid, Lin_PduType **pduInfoPtr)
{
bool ret = false;
uint8_t pidIdx = LIN_DATA_INVALID;
pidIdx = LinSchedule_GetPidIdx(pid);
if(pidIdx != LIN_DATA_INVALID)
{
/* Tell the low level the data address that stored in Interface Level */
*pduInfoPtr = &sLinIf_CtrlInfo.pduState[channelIdx].pdu;
sLinIf_CtrlInfo.pduState[channelIdx].pdu.pid = pid;
sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx = pidIdx;
sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameType = LinSchedule_GetFrameType(channelIdx, pidIdx);
if(sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameType == LIN_FRAME_TYPE_EVENT_TRIGGER)
{
uint8_t linkTblIdx = 0;
const LinSchedule_ScheduleTblListType *tblPtr = NULL;
uint8_t i = 0, subscriberCnt = 0;
Lin_FrameCtrlType frameCtrl = LIN_FRAME_CTRL_NO_ACTION;
/* Use the normal table, in slave mode, there is only one normal schedule table */
linkTblIdx = LinSchedule_GetLinkTblIdx(channelIdx, 1, sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx);
tblPtr = (const LinSchedule_ScheduleTblListType *)LinSchedule_GetLinkScheduleTblPtr(channelIdx, linkTblIdx);
sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameCtrl = LIN_FRAME_CTRL_NO_ACTION;
if(tblPtr != NULL)
{
for(i = 0; i < tblPtr->frameNum; i++)
{
pidIdx = LinSchedule_GetPidIdxInSchedulerTbl(channelIdx, linkTblIdx, i);
frameCtrl = LinSchedule_GetFrameCtrl(channelIdx, pidIdx);
if(frameCtrl == LIN_FRAME_CTRL_PUBLISH)
{
sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameCtrl = LIN_FRAME_CTRL_PUBLISH;
break;
}
else
{
if(frameCtrl == LIN_FRAME_CTRL_SUBSCRIBER)
{
subscriberCnt++;
}
}
}
}
if(sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameCtrl == LIN_FRAME_CTRL_NO_ACTION)
{
if(subscriberCnt > 0u)
{
sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameCtrl = LIN_FRAME_CTRL_SUBSCRIBER;
}
}
/* Get all frames in the associated collision table, if there are at least one frame that need to be transmit by this node, the node is set to be in publisher, nor to be set as subscriber */
if(sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameCtrl != LIN_FRAME_CTRL_NO_ACTION)
{
sLinIf_CtrlInfo.pduState[channelIdx].pdu.checkSumType = LinSchedule_GetCheckSumType(pid);
if(sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameCtrl == LIN_FRAME_CTRL_PUBLISH)
{
uint8_t i = 0;
/* If the current pid is a event trigger frame, but local buffer data is not diffirent with last value, so no response to bus */
if(LinSchedule_GetFrameAccessState(pidIdx) == LIN_FRAME_ACCESS_STATE_UPDATED)
{
LinSchedule_SetFrameAccessState(pidIdx, LIN_FRAME_ACCESS_STATE_WRITING_IN);
/* Get the upper level data to store in local pdu buffer */
sLinIf_CtrlInfo.pduState[channelIdx].upperLevelFrameDataPtr = LinSchedule_GetFrameBufferPtr(pidIdx);
sLinIf_CtrlInfo.pduState[channelIdx].pdu.dataLen = LinSchedule_GetFrameDataLen(pidIdx);
sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameData.poyload.eventBytes.pid = LinSchedule_GetPid(pidIdx);
for(i = 1; i < sLinIf_CtrlInfo.pduState[channelIdx].pdu.dataLen; i++)
{
sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameData.poyload.byteData[i] = sLinIf_CtrlInfo.pduState[channelIdx].upperLevelFrameDataPtr->poyload.byteData[i];
}
sLinIf_CtrlInfo.pduState[channelIdx].pdu.checkSum = sLinIf_CtrlInfo.pLinIf_CallBackFuncListPtr->pLinIf_CalculateChecksumFunction(sLinIf_CtrlInfo.pduState[channelIdx].pdu.checkSumType,
sLinIf_CtrlInfo.pduState[channelIdx].pdu.pid,
(const uint8_t *)&sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameData.poyload.byteData[0],
sLinIf_CtrlInfo.pduState[channelIdx].pdu.dataLen);
LinSchedule_SetFrameAccessState(pidIdx, LIN_FRAME_ACCESS_STATE_IDLE);
sLinIf_CtrlInfo.pduState[channelIdx].txTimeOutCnt = 0;
ret = true;
}
}
else if(sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameCtrl == LIN_FRAME_CTRL_SUBSCRIBER)
{
/* With the default data length, the actual length is set in the next step */
sLinIf_CtrlInfo.pduState[channelIdx].pdu.dataLen = 8;
if(LinSchedule_GetFrameAccessState(pidIdx) == LIN_FRAME_ACCESS_STATE_IDLE)
{
LinSchedule_SetFrameAccessState(pidIdx, LIN_FRAME_ACCESS_STATE_READING_OUT);
}
/* Get the upper level data address to store the received data from low level */
sLinIf_CtrlInfo.pduState[channelIdx].upperLevelFrameDataPtr = LinSchedule_GetFrameBufferPtr(pidIdx);
ret = true;
}
else
{
if(LinSchedule_GetFrameAccessState(pidIdx) == LIN_FRAME_ACCESS_STATE_IDLE)
{
LinSchedule_SetFrameAccessState(pidIdx, LIN_FRAME_ACCESS_STATE_WRITING_IN);
}
}
}
else
{
sLinIf_CtrlInfo.pduState[channelIdx].opStatusInfo = LIN_STATUS_IDLE;
}
}
else
{
sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameCtrl = LinSchedule_GetFrameCtrl(channelIdx, sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx);
if(sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameCtrl != LIN_FRAME_CTRL_NO_ACTION)
{
sLinIf_CtrlInfo.pduState[channelIdx].pdu.dataLen = LinSchedule_GetFrameDataLen(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx);
sLinIf_CtrlInfo.pduState[channelIdx].pdu.checkSumType = LinSchedule_GetCheckSumType(pid);
if(sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameCtrl == LIN_FRAME_CTRL_PUBLISH)
{
uint8_t i = 0;
/* If the current pid is a event trigger frame, but local buffer data is not diffirent with last value, so no response to bus */
if((LinSchedule_GetFrameAccessState(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx) == LIN_FRAME_ACCESS_STATE_UPDATED) || (LinSchedule_GetFrameAccessState(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx) == LIN_FRAME_ACCESS_STATE_IDLE))
{
LinSchedule_SetFrameAccessState(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx, LIN_FRAME_ACCESS_STATE_WRITING_IN);
/* Get the upper level data to store in local pdu buffer */
sLinIf_CtrlInfo.pduState[channelIdx].upperLevelFrameDataPtr = LinSchedule_GetFrameBufferPtr(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx);
for(i = 0; i < sLinIf_CtrlInfo.pduState[channelIdx].pdu.dataLen; i++)
{
sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameData.poyload.byteData[i] = sLinIf_CtrlInfo.pduState[channelIdx].upperLevelFrameDataPtr->poyload.byteData[i];
}
sLinIf_CtrlInfo.pduState[channelIdx].pdu.checkSum = sLinIf_CtrlInfo.pLinIf_CallBackFuncListPtr->pLinIf_CalculateChecksumFunction(sLinIf_CtrlInfo.pduState[channelIdx].pdu.checkSumType,
sLinIf_CtrlInfo.pduState[channelIdx].pdu.pid,
(const uint8_t *)&sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameData.poyload.byteData[0],
sLinIf_CtrlInfo.pduState[channelIdx].pdu.dataLen);
LinSchedule_SetFrameAccessState(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx, LIN_FRAME_ACCESS_STATE_IDLE);
sLinIf_CtrlInfo.pduState[channelIdx].txTimeOutCnt = 0;
}
}
else if(sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameCtrl == LIN_FRAME_CTRL_SUBSCRIBER)
{
if(LinSchedule_GetFrameAccessState(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx) == LIN_FRAME_ACCESS_STATE_IDLE)
{
LinSchedule_SetFrameAccessState(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx, LIN_FRAME_ACCESS_STATE_READING_OUT);
}
/* Get the upper level data address to store the received data from low level */
sLinIf_CtrlInfo.pduState[channelIdx].upperLevelFrameDataPtr = LinSchedule_GetFrameBufferPtr(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx);
}
else
{
if(LinSchedule_GetFrameAccessState(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx) == LIN_FRAME_ACCESS_STATE_IDLE)
{
LinSchedule_SetFrameAccessState(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx, LIN_FRAME_ACCESS_STATE_WRITING_IN);
}
}
ret = true;
}
else
{
sLinIf_CtrlInfo.pduState[channelIdx].opStatusInfo = LIN_STATUS_IDLE;
}
}
}
return ret;
}
/*! \brief Process the frame data length
*
* This function execute to process the link data length by the event-trigger frame id, this is called by isr
*
* \param[in] channelIdx: which physical channel is used
* \param[in] pid: the first data in the response of event trigger frame, the event frame is link to one unconditional frame, the first data in payload is pid
* \param[in] pDataLen: the pointer of data length
* \param[in] nodeType: node type
* \return: void
*/
void LinIf_EventFrameDataLenIndication(uint8_t channelIdx, uint8_t pid, uint8_t *pDataLen, Lin_NodeType nodeType)
{
uint8_t pidIdx = LIN_DATA_INVALID;
uint8_t dataLen = 0;
if(nodeType == LIN_NODE_IS_MASTER)
{
pidIdx = LinSchedule_GetPidIdx(pid);
dataLen = LinSchedule_GetFrameDataLen(pidIdx);
*pDataLen = dataLen;
}
else
{
pidIdx = LinSchedule_GetPidIdx(pid);
dataLen = LinSchedule_GetFrameDataLen(pidIdx);
*pDataLen = dataLen;
}
}
/*! \brief Received indication
*
* This function execute to indicate the upper layer that one new received frame is done, this is called by isr
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
void LinIf_RxIndication(uint8_t channelIdx)
{
Lin_FrameAccessStateType accessState = LinSchedule_GetFrameAccessState(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx);
if(accessState == LIN_FRAME_ACCESS_STATE_READING_OUT)
{
LinSchedule_SetFrameAccessState(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx, LIN_FRAME_ACCESS_STATE_UPDATED);
}
else if(accessState == LIN_FRAME_ACCESS_STATE_UPDATED)
{
LinSchedule_SetFrameAccessState(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx, LIN_FRAME_ACCESS_STATE_OVER_RECEIVED);
}
memcpy(sLinIf_CtrlInfo.pduState[channelIdx].upperLevelFrameDataPtr, &sLinIf_CtrlInfo.pduState[channelIdx].pdu.frameData, sizeof(Lin_FrameDataType));
}
/*! \brief Transfer confirmed
*
* This function execute to tell upper layer that one transfer is done successfully,, this is called by isr
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
void LinIf_TxConfirmation(uint8_t channelIdx)
{
/* Nothing to do */
}
/*! \brief Transfer or receive indicate
*
* This function execute to indicate that one data is received or one data is transmitted, then to clear the timeout counter,, this is called by isr
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
void LinIf_TRxIndication(uint8_t channelIdx)
{
switch(sLinIf_CtrlInfo.pduState[channelIdx].opStatusInfo)
{
case LIN_STATUS_TX_DATA_BUSY:
sLinIf_CtrlInfo.pduState[channelIdx].txTimeOutCnt = 0;
break;
case LIN_STATUS_HEADER_BUSY:
sLinIf_CtrlInfo.pduState[channelIdx].rxTimeOutCnt = 0;
break;
case LIN_STATUS_RX_DATA_BUSY:
sLinIf_CtrlInfo.pduState[channelIdx].rxTimeOutCnt = 0;
break;
default:
break;
}
}
/*! \brief Send wake-up signal
*
* This function execute to send wake-up signal
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
void LinIf_SendWakeUpSignal(uint8_t channelIdx)
{
sLinIf_CtrlInfo.pLinIf_CallBackFuncListPtr->pLinIf_SendWakeUpSignalFunction(channelIdx);
}
/*! \brief Get the signal of wake-up
*
* This function execute to get the signal of wake-up
*
* \param[in] channelIdx: which physical channel of lin to be selected
* \return: true: wake-up signal is valid
* false: wake-up signal is invalid
*/
bool LinIf_GetWakeupSignal(uint8_t channelIdx)
{
return sLinIf_CtrlInfo.pLinIf_CallBackFuncListPtr->pLinIf_GetWakeupSignalFunction(channelIdx);
}
/*! \brief Get the transfer operated status
*
* This function execute to get the current transfer status
*
* \param[in] channelIdx: which physical channel is used
* \return: the status of current transfer operation
*/
Lin_OpStatusType LinIf_GetTransferOperateStatus(uint8_t channelIdx)
{
return sLinIf_CtrlInfo.pduState[channelIdx].opStatusInfo;
}
/*! \brief Indicate error information
*
* This function execute to report the error information, this is called by isr
*
* \param[in] channelIdx: which physical channel is used
* \param[in] errStatus: the current error information
* \return: void
*/
void LinIf_ErrorIndication(uint8_t channelIdx, Lin_OpStatusType errStatus)
{
sLinIf_CtrlInfo.pduState[channelIdx].opStatusInfo = errStatus;
switch(errStatus)
{
case LIN_STATUS_TX_DATA_BUSY:
sLinIf_CtrlInfo.pduState[channelIdx].txTimeOutCnt = 0;
break;
case LIN_STATUS_HEADER_BUSY:
case LIN_STATUS_RX_DATA_BUSY:
sLinIf_CtrlInfo.pduState[channelIdx].rxTimeOutCnt = 0;
break;
default:
if(errStatus >= LIN_STATUS_ERR_BIT)
{
LinSchedule_SetFrameAccessState(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx, LIN_FRAME_ACCESS_STATE_IDLE);
}
sLinIf_CtrlInfo.pduState[channelIdx].txTimeOutCnt = 0;
sLinIf_CtrlInfo.pduState[channelIdx].rxTimeOutCnt = 0;
break;
}
}
/*! \brief Process the current transfer operation timeout
*
* This function execute to calculate the current transfer is timeout or not
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
void LinIf_MainFunction(uint8_t channelIdx)
{
switch(sLinIf_CtrlInfo.pduState[channelIdx].opStatusInfo)
{
case LIN_STATUS_TX_DATA_BUSY:
/* Tx Timeout */
sLinIf_CtrlInfo.pduState[channelIdx].txTimeOutCnt++;
if(sLinIf_CtrlInfo.pduState[channelIdx].txTimeOutCnt >= LINCFG_RESP_BYTE_TIMEOUT_MAX_CNT)
{
sLinIf_CtrlInfo.pduState[channelIdx].txTimeOutCnt = 0;
sLinIf_CtrlInfo.pduState[channelIdx].opStatusInfo = LIN_STATUS_ERR_TIMEOUT;
sLinIf_CtrlInfo.pLinIf_CallBackFuncListPtr->pLinIf_ResetFunction(channelIdx);
}
break;
case LIN_STATUS_HEADER_BUSY:
case LIN_STATUS_RX_DATA_BUSY:
/* Rx Timeout */
sLinIf_CtrlInfo.pduState[channelIdx].rxTimeOutCnt++;
if(sLinIf_CtrlInfo.pduState[channelIdx].rxTimeOutCnt >= LINCFG_RESP_BYTE_TIMEOUT_MAX_CNT)
{
sLinIf_CtrlInfo.pduState[channelIdx].rxTimeOutCnt = 0;
sLinIf_CtrlInfo.pduState[channelIdx].opStatusInfo = LIN_STATUS_ERR_TIMEOUT;
LinSchedule_SetFrameAccessState(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx, LIN_FRAME_ACCESS_STATE_IDLE);
sLinIf_CtrlInfo.pLinIf_CallBackFuncListPtr->pLinIf_ResetFunction(channelIdx);
}
break;
case LIN_STATUS_READY: /* Tx Timeout */
sLinIf_CtrlInfo.pduState[channelIdx].txTimeOutCnt++;
if(sLinIf_CtrlInfo.pduState[channelIdx].txTimeOutCnt >= LINCFG_RESP_BYTE_TIMEOUT_MAX_CNT)
{
sLinIf_CtrlInfo.pduState[channelIdx].txTimeOutCnt = 0;
sLinIf_CtrlInfo.pduState[channelIdx].opStatusInfo = LIN_STATUS_ERR_TIMEOUT;
LinSchedule_SetFrameAccessState(sLinIf_CtrlInfo.pduState[channelIdx].pdu.pidIdx, LIN_FRAME_ACCESS_STATE_IDLE);
sLinIf_CtrlInfo.pLinIf_CallBackFuncListPtr->pLinIf_ResetFunction(channelIdx);
}
break;
default:
sLinIf_CtrlInfo.pduState[channelIdx].rxTimeOutCnt = 0;
sLinIf_CtrlInfo.pduState[channelIdx].txTimeOutCnt = 0;
break;
}
}
/*! \brief Install the call back function
*
* This function execute to initialize the lin interface
*
* \param[in] callbackList: the call back interface from lin driver in lin interface layer
* \return: void
*/
void LinIf_CallbackInit(const LinIf_CallBackFuncListType *callbackList)
{
uint8_t i = 0;
for(i = 0; i < LINCFG_CH_NUM; i++)
{
memset(&sLinIf_CtrlInfo.pduState[i], 0, sizeof(LinIf_StateType));
}
sLinIf_CtrlInfo.callBackInstalled = true;
sLinIf_CtrlInfo.pLinIf_CallBackFuncListPtr = callbackList;
}
/*! \brief Initialize the Lin Interface
*
* This function execute to initialize the lin interface
*
* \param[in] channelIdx: which physical channel is used
* \param[in] nodeType: the current node type
* \param[in] callbackList: the call back interface from lin driver in lin interface layer
* \return: void
*/
void LinIf_Init(uint8_t channelIdx, Lin_NodeType nodeType)
{
memset(&sLinIf_CtrlInfo.pduState[channelIdx], 0, sizeof(LinIf_StateType));
sLinIf_CtrlInfo.pLinIf_CallBackFuncListPtr->pLinIf_InitFunction(channelIdx, nodeType);
}
/*! \brief DeInitialize the Lin Interface
*
* This function execute to initialize the lin interface
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
void LinIf_DeInit(uint8_t channelIdx)
{
memset(&sLinIf_CtrlInfo.pduState[channelIdx], 0, sizeof(LinIf_StateType));
sLinIf_CtrlInfo.pLinIf_CallBackFuncListPtr->pLinIf_DeInitFunction(channelIdx);
}

View File

@ -1,284 +0,0 @@
/*
* 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 _LIN_INTERFACE_H_
#define _LIN_INTERFACE_H_
/*! \brief his file exports Lin interface defnitions
*
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "lin_type.h"
#include "lin_cfg.h"
/*! \addtogroup lin_interface
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
typedef bool (*pLinIf_SendFrameFunctionPtr)(uint8_t channelIdx, const Lin_PduType *pduInfoPtr);
typedef uint8_t (*pLinIf_CalculateChecksumFunctionPtr)(Lin_CheckSumType checkSumType, uint8_t pid, const uint8_t *sduPtr, uint8_t dataLen);
typedef void (*pLinIf_SendWakeUpSignalFunctionPtr)(uint8_t channelIdx);
typedef bool (*pLinIf_GetWakeupSignalFunctionPtr)(uint8_t channelIdx);
typedef void (*pLinIf_ResetFunctionPtr)(uint8_t channelIdx);
typedef void (*pLinIf_InitFunctionPtr)(uint8_t channelIdx, Lin_NodeType nodeType);
typedef void (*pLinIf_DeInitFunctionPtr)(uint8_t channelIdx);
typedef struct
{
pLinIf_InitFunctionPtr pLinIf_InitFunction;
pLinIf_DeInitFunctionPtr pLinIf_DeInitFunction;
pLinIf_ResetFunctionPtr pLinIf_ResetFunction;
pLinIf_SendFrameFunctionPtr pLinIf_SendFrameFunction;
pLinIf_SendWakeUpSignalFunctionPtr pLinIf_SendWakeUpSignalFunction;
pLinIf_GetWakeupSignalFunctionPtr pLinIf_GetWakeupSignalFunction;
pLinIf_CalculateChecksumFunctionPtr pLinIf_CalculateChecksumFunction;
} LinIf_CallBackFuncListType;
typedef struct
{
Lin_PduType pdu; /* local pdu */
Lin_OpStatusType opStatusInfo;
Lin_FrameDataType *upperLevelFrameDataPtr; /* Upper pdu pointer */
uint32_t rxTimeOutCnt;
uint32_t txTimeOutCnt;
bool sleepReqIndication;
LinIf_CallBackFuncListType *pLinIf_CallBackFuncListPtr;
} LinIf_StateType;
typedef struct
{
LinIf_StateType pduState[LINCFG_CH_NUM];
bool callBackInstalled;
const LinIf_CallBackFuncListType *pLinIf_CallBackFuncListPtr;
}LinIf_CtrlInfoType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Install the call back function
*
* This function execute to initialize the lin interface
*
* \param[in] callbackList: the call back interface from lin driver in lin interface layer
* \return: void
*/
extern void LinIf_CallbackInit(const LinIf_CallBackFuncListType *callbackList);
/*! \brief Initialize the Lin Interface
*
* This function execute to initialize the lin interface
*
* \param[in] channelIdx: which physical channel is used
* \param[in] nodeType: the current node type
* \return: void
*/
extern void LinIf_Init(uint8_t channelIdx, Lin_NodeType nodeType);
/*! \brief DeInitialize the Lin Interface
*
* This function execute to initialize the lin interface
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
extern void LinIf_DeInit(uint8_t channelIdx);
/*! \brief Convert frame id to pid
*
* This function execute to convert the frame id to protected id
*
* \param[in] frameId: Frame id, this includes the low 6bit
* \return: the result of convert pid
*/
extern uint8_t LinIf_ConvertFrameIdToPid(uint8_t frameId);
/*! \brief Convert pid to frame id
*
* This function execute to convert pid to frame id
*
* \param[in] pid: protected id
* \return: the result of convert frame id
*/
extern uint8_t LinIf_ConvertPidToFrameId(uint8_t pid);
/*! \brief Request transmit the frame
*
* This function execute to request transmit the frame, the function is only used by master node
*
* \param[in] channelIdx: which physical channel is used
* \param[in] frameInfoPtr: the pointer of frame
* \return: true: request transmit successfully
* false: request transmit failed
*/
extern bool LinIf_ReqTransmit(uint8_t channelIdx, const Lin_FrameInfoType *frameInfoPtr);
/*! \brief Get the transfer operated status
*
* This function execute to get the current transfer status
*
* \param[in] channelIdx: which physical channel is used
* \return: the status of current transfer operation
*/
extern Lin_OpStatusType LinIf_GetTransferOperateStatus(uint8_t channelIdx);
/*! \brief Send wake-up signal
*
* This function execute to send wake-up signal
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
extern void LinIf_SendWakeUpSignal(uint8_t channelIdx);
/*! \brief Get the signal of wake-up
*
* This function execute to get the signal of wake-up
*
* \param[in] channelIdx: which physical channel of lin to be selected
* \return: true: wake-up signal is valid
* false: wake-up signal is invalid
*/
extern bool LinIf_GetWakeupSignal(uint8_t channelIdx);
/*! \brief Set the sleep request indication flag
*
* This function execute to sleep request indication, Indication Upper layer that go to sleep cmd is doing
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
extern void LinIf_SetSleepRequestIndication(uint8_t channelIdx);
/*! \brief Clear the sleep request
*
* This function execute to clear the sleep reqeust indication
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
extern void LinIf_ClearSleepRequestIndication(uint8_t channelIdx);
/*! \brief Get the sleep request indication
*
* This function execute to get the sleep request indication after enter into prepare sleep mode
*
* \param[in] channelIdx: which physical channel is used
* \return: bool
*/
extern bool LinIf_GetSleepRequestIndication(uint8_t channelIdx);
/*! \brief Process the current transfer operation timeout
*
* This function execute to calculate the current transfer is timeout or not
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
extern void LinIf_MainFunction(uint8_t channelIdx);
/*! \brief The call-back function when received valid header
*
* This function execute to process the pdu attribute by received pid, this function is only used by slave node, this is called by isr
*
* \param[in] uint8_t channelIdx: which physical channel is used
* \param[in] pid: the received pid
* \param[in] pduInfoPtr: the local pdu pointer
* \return: true: the current received pid is valid and the frame control is not the no-action type
* false; the pid is invalid or not supported or the frame control is the no-action type
*/
extern bool LinIf_HeaderIndication(uint8_t channelIdx, uint8_t pid, Lin_PduType **pduInfoPtr);
/*! \brief Received indication
*
* This function execute to indicate the upper layer that one new received frame is done, this is called by isr
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
extern void LinIf_RxIndication(uint8_t channelIdx);
/*! \brief Transfer confirmed
*
* This function execute to tell upper layer that one transfer is done successfully,, this is called by isr
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
extern void LinIf_TxConfirmation(uint8_t channelIdx);
/*! \brief Transfer or receive indicate
*
* This function execute to indicate that one data is received or one data is transmitted, then to clear the timeout counter,, this is called by isr
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
extern void LinIf_TRxIndication(uint8_t channelIdx);
/*! \brief Indicate error information
*
* This function execute to report the error information, this is called by isr
*
* \param[in] channelIdx: which physical channel is used
* \param[in] errStatus: the current error information
* \return: void
*/
extern void LinIf_ErrorIndication(uint8_t channelIdx, Lin_OpStatusType errStatus);
/*! \brief Process the frame data length
*
* This function execute to process the link data length by the event-trigger frame id, this is called by isr
*
* \param[in] channelIdx: which physical channel is used
* \param[in] pid: the first data in the response of event trigger frame, the event frame is link to one unconditional frame, the first data in payload is pid
* \param[in] pDataLen: the pointer of data length
* \param[in] nodeType: node type
* \return: void
*/
extern void LinIf_EventFrameDataLenIndication(uint8_t channelIdx, uint8_t pid, uint8_t *pDataLen, Lin_NodeType nodeType);
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _LIN_INTERFACE_H_ */

View File

@ -1,889 +0,0 @@
/*
* 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 <string.h>
#include "lin_type.h"
#include "lin_if.h"
#include "lin_schedule.h"
#include "lin_cfg.h"
#include "lin_com.h"
#include "lin_nm.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
static void LinNm_InitStateProc(void);
static void LinNm_RunningStateProc(void);
static void LinNm_PrepareSleepStateProc(void);
static void LinNm_ReadySleepStateProc(void);
static void LinNm_SleepStateProc(void);
/*******************************************************************************
* the globals
******************************************************************************/
LinNm_StateType LinNm_State;
/*******************************************************************************
* the functions
******************************************************************************/
/*! \brief Initialize the communication manager
*
* This function execute to initialize the communication manager
*
* \param[in] cpuClockFrequency: cpu lock frequency
* \return: void
*/
void LinNm_Init(uint32_t cpuClockFrequency)
{
memset(&LinNm_State, 0, sizeof(LinNm_State));
}
/*! \brief Get the state of the bus
*
* This function execute to get the bus state
*
* \param[in] void:
* \return: bool
*/
static bool LinNm_GetBusIsInIdle(void)
{
bool ret = false;
Lin_OpStatusType tempOpStatus = LIN_STATUS_IDLE;
/* All node is idle or not in busy state */
#if LINCFG_CH0_USED == LINCFG_CH_ACTIVE
tempOpStatus = LinIf_GetTransferOperateStatus(0);
#endif
#if LINCFG_CH1_USED == LINCFG_CH_ACTIVE
tempOpStatus = LinIf_GetTransferOperateStatus(1);
#endif
#if LINCFG_CH2_USED == LINCFG_CH_ACTIVE
tempOpStatus = LinIf_GetTransferOperateStatus(2);
#endif
#if LINCFG_CH3_USED == LINCFG_CH_ACTIVE
tempOpStatus = LinIf_GetTransferOperateStatus(2);
#endif
if((tempOpStatus == LIN_STATUS_IDLE) || (tempOpStatus > LIN_STATUS_TX_DATA_BUSY))
{
ret = true;
}
return ret;
}
/*! \brief Set the communication mode
*
* This function execute to set the communication mode
*
* \param[in] targeMode: target mode
* \return: void
*/
void LinNm_SetComMode(LinNm_ModeType targeMode)
{
bool busIsInIdle = false;
LinNm_State.targetComMode = targeMode;
busIsInIdle = LinNm_GetBusIsInIdle();
/* Only all node are in idle or not in busy, then can change the current communication mode */
if(busIsInIdle == true)
{
LinNm_State.currentComMode = LinNm_State.targetComMode;
}
}
/*! \brief Get the communication mode
*
* This function execute to get the communication mode
*
* \param[in] void:
* \return: the communication mode
*/
LinNm_ModeType LinNm_GetComMode(void)
{
return LinNm_State.currentComMode;
}
/*! \brief Set sleep request
*
* This function execute to request to enter into sleep mode
*
* \param[in] void:
* \return: void
*/
static void LinNm_SetSleepRequest(void)
{
LinNm_State.requestSleep = true;
}
/*! \brief Get the request of sleep
*
* This function execute to get the request of sleep
*
* \param[in] void:
* \return: true: requested the sleep
* false: no request the sleep
*/
static bool LinNm_GetSleepRequest(void)
{
return LinNm_State.requestSleep;
}
/*! \brief Clear the request of sleep
*
* This function execute to clear the request of sleep
*
* \param[in] void:
* \return: void
*/
static void LinNm_ClearSleepRequest(void)
{
LinNm_State.requestSleep = false;
}
/*! \brief Set the sleep indication
*
* This function execute to set the sleep indication after enter into sleep
*
* \param[in] void:
* \return: void
*/
static void LinNm_SetSleepIndication(void)
{
LinNm_State.sleepIndication = true;
}
/*! \brief Get the sleep indication
*
* This function execute to get the sleep indication
*
* \param[in] void:
* \return: true: in sleep mode
* false: not in sleep mode
*/
static bool LinNm_GetSleepIndication(void)
{
return LinNm_State.sleepIndication;
}
/*! \brief Clear the sleep indication
*
* This function execute to clear the sleep indication after exist from sleep mode
*
* \param[in] void:
* \return: void
*/
static void LinNm_ClearSleepIndication(void)
{
LinNm_State.sleepIndication = false;
}
/*! \brief Request sleep
*
* This function execute to request sleep
*
* \param[in] sleepRequest: request sleep
* \return: void
*/
void LinNm_RequestSleep(bool sleepRequest)
{
if(sleepRequest == true)
{
LinNm_SetSleepRequest();
}
else
{
LinNm_ClearSleepRequest();
}
}
/*! \brief Set the active wake up request
*
* This function execute to set active wake-up request if the local condition is match to exist from sleep
*
* \param[in] void:
* \return: void
*/
void LinNm_SetActiveRequestWakeUp(void)
{
LinNm_State.activeWakeUpReq = true;
}
/*! \brief Get the active wakeup request
*
* This function execute to get the active wakeup request
*
* \param[in] void:
* \return: true: active wakeup request is enabled
* false: active wakeup request is disabled
*/
static bool LinNm_GetActiveRequestWakeUp(void)
{
return LinNm_State.activeWakeUpReq;
}
/*! \brief Clear the active request of wakeup
*
* This function execute to clear the active request of wakeup
*
* \param[in] void:
* \return: void
*/
static void LinNm_ClearActiveRequestWakeUp(void)
{
LinNm_State.activeWakeUpReq = false;
}
/*! \brief Check the passive wakeup signal
*
* This function execute to get the passive wake-up signal from bus
*
* \param[in] uint8_t channelIdx: which physical channel is used
* \return: true: passive wakeup signal is valid
* false: passive wakup signal is invalid
*/
bool LinNm_CheckPassiveWakeUpSignal(uint8_t channelIdx)
{
bool ret = false;
if((LinNm_GetSleepIndication() == true) && (LinNm_GetActiveRequestWakeUp() == false))
{
if(LinIf_GetWakeupSignal(channelIdx) == true)
{
if(LinNm_State.wakeUpSignalValidTickCnt > LINCFG_WAKEUP_SIGNAL_CHECK_VALID_MIN_CNT)
{
LinNm_State.passiveWakeUpConfirm = true;
}
else
{
LinNm_State.wakeUpSignalValidTickCnt++;
LinNm_State.passiveWakeUpConfirm = false;
}
}
else
{
if(LinNm_State.passiveWakeUpConfirm == true)
{
LinNm_State.passiveWakeUpConfirm = false;
ret = true;
}
LinNm_State.wakeUpSignalValidTickCnt = 0;
}
}
return ret;
}
/*! \brief Set the error response bit
*
* This function execute to update the response error bit
*
* \param[in] errBit: err
* \return: void
*/
void LinNm_SetErrResponseBit(bool errBit)
{
LinNm_State.responseError = errBit;
}
/*! \brief Get the error response bit
*
* This function execute to get the error response bit
*
* \param[in] void:
* \return: true: error is happen
* false: error is not happen
*/
bool LinNm_GetErrResponseBit(void)
{
return LinNm_State.responseError;
}
/*! \brief Set the transfer successful bit
*
* This function execute
*
* \param[in] successfullBit: true or false
* \return: void
*/
void LinNm_SetSuccessfulTransferBit(bool successfulBit)
{
LinNm_State.transferSuccessful = successfulBit;
}
/*! \brief Get the transfer successful bit
*
* This function execute to get the transfer successful bit
*
* \param[in] void:
* \return: true: transfer successfully
* false: transfer failed
*/
bool LinNm_GetSuccessfulTransferBit(void)
{
return LinNm_State.transferSuccessful;
}
/*! \brief Process the idle state of communication manager
*
* This function execute to process the idle state of communication manager
*
* \param[in] void:
* \return: void
*/
static void LinNm_IdleStateProc(void)
{
#if LINCFG_NODE_USED == LINCFG_NODE_MASTER
if(LinNm_GetActiveRequestWakeUp() == false)
{
uint8_t defaultScheduleIdx = LINSCH_SCHEDULE_TABLE_NULL;
defaultScheduleIdx = LinSchedule_GetDefaultScheduleTblIdx(LINCFG_MASTER_CH_IDX);
LinIf_Init(LINCFG_MASTER_CH_IDX, LIN_NODE_IS_MASTER);
LinSchedule_Init(LINCFG_MASTER_CH_IDX);
LinSchedule_ReqSwitchScheduleTbl(LINCFG_MASTER_CH_IDX, defaultScheduleIdx);
LinIf_ClearSleepRequestIndication(LINCFG_MASTER_CH_IDX);
#if LINCFG_CH0_USED == LINCFG_CH_ACTIVE && LINCFG_MASTER_CH_IDX != LINCFG_CH_IDX_0
LinIf_Init(0, LIN_NODE_IS_SLAVE);
#endif
#if LINCFG_CH1_USED == LINCFG_CH_ACTIVE && LINCFG_MASTER_CH_IDX != LINCFG_CH_IDX_1
LinIf_Init(1, LIN_NODE_IS_SLAVE);
#endif
#if LINCFG_CH2_USED == LINCFG_CH_ACTIVE && LINCFG_MASTER_CH_IDX != LINCFG_CH_IDX_2
LinIf_Init(2, LIN_NODE_IS_SLAVE);
#endif
#if LINCFG_CH3_USED == LINCFG_CH_ACTIVE && LINCFG_MASTER_CH_IDX != LINCFG_CH_IDX_3
LinIf_Init(3, LIN_NODE_IS_SLAVE);
#endif
LinNm_ClearSleepRequest();
LinNm_SetComMode(LINNM_MODE_INIT);
}
else
{
LinNm_State.wakeUpSignalValidTickCnt++;
if(LinNm_State.wakeUpSignalValidTickCnt > LINCFG_WAKEUP_SIGNAL_DURATION_MIN_CNT)
{
uint8_t defaultScheduleIdx = LINSCH_SCHEDULE_TABLE_NULL;
defaultScheduleIdx = LinSchedule_GetDefaultScheduleTblIdx(LINCFG_MASTER_CH_IDX);
LinNm_State.wakeUpSignalValidTickCnt = 0;
LinIf_Init(LINCFG_MASTER_CH_IDX, LIN_NODE_IS_MASTER);
LinSchedule_Init(LINCFG_MASTER_CH_IDX);
LinSchedule_ReqSwitchScheduleTbl(LINCFG_MASTER_CH_IDX, defaultScheduleIdx);
LinNm_ClearSleepRequest();
LinNm_SetComMode(LINNM_MODE_INIT);
}
}
#else
if(LinNm_GetActiveRequestWakeUp() == false)
{
#if LINCFG_CH0_USED == LINCFG_CH_ACTIVE
LinIf_Init(0, LIN_NODE_IS_SLAVE);
#endif
#if LINCFG_CH1_USED == LINCFG_CH_ACTIVE
LinIf_Init(1, LIN_NODE_IS_SLAVE);
#endif
#if LINCFG_CH2_USED == LINCFG_CH_ACTIVE
LinIf_Init(2, LIN_NODE_IS_SLAVE);
#endif
#if LINCFG_CH3_USED == LINCFG_CH_ACTIVE
LinIf_Init(3, LIN_NODE_IS_SLAVE);
#endif
LinNm_ClearSleepRequest();
LinNm_SetComMode(LINNM_MODE_INIT);
}
else
{
LinNm_State.wakeUpSignalValidTickCnt++;
if(LinNm_State.wakeUpSignalValidTickCnt > LINCFG_WAKEUP_SIGNAL_DURATION_MIN_CNT)
{
LinNm_State.wakeUpSignalValidTickCnt = 0;
#if LINCFG_CH0_USED == LINCFG_CH_ACTIVE
LinIf_Init(0, LIN_NODE_IS_SLAVE);
#endif
#if LINCFG_CH1_USED == LINCFG_CH_ACTIVE
LinIf_Init(1, LIN_NODE_IS_SLAVE);
#endif
#if LINCFG_CH2_USED == LINCFG_CH_ACTIVE
LinIf_Init(2, LIN_NODE_IS_SLAVE);
#endif
#if LINCFG_CH3_USED == LINCFG_CH_ACTIVE
LinIf_Init(3, LIN_NODE_IS_SLAVE);
#endif
LinNm_ClearSleepRequest();
LinNm_SetComMode(LINNM_MODE_INIT);
}
}
#endif
}
/*! \brief Process the initialize state of communication manager
*
* This function execute to process the initialize state of communication manager
*
* \param[in] void:
* \return: void
*/
static void LinNm_InitStateProc(void)
{
#if LINCFG_NODE_USED == LINCFG_NODE_MASTER
if(LinNm_GetActiveRequestWakeUp() == false)
{
LinNm_State.busIdleTickCnt = 0;
LinNm_SetComMode(LINNM_MODE_RUNNING);
}
else
{
LinNm_State.delayCommunicateTickCnt++;
if(LinNm_State.delayCommunicateTickCnt > LINCFG_START_COM_AFTER_WKP_CNT)
{
LinNm_State.delayCommunicateTickCnt = 0;
LinNm_ClearActiveRequestWakeUp();
LinNm_State.wakeUpSignalValidTickCnt = 0;
LinNm_State.busIdleTickCnt = 0;
LinNm_SetComMode(LINNM_MODE_RUNNING);
}
}
#else
if(LinNm_GetActiveRequestWakeUp() == false)
{
LinNm_State.busIdleTickCnt = 0;
LinNm_State.wakeUpTimeOutTickCnt = 0;
LinNm_State.retryWakeUpCnt = 0;
LinNm_SetComMode(LINNM_MODE_RUNNING);
}
else
{
LinNm_State.wakeUpTimeOutTickCnt++;
if(LinNm_State.retryWakeUpCnt >= LINCFG_WAKEUP_RETRY_MAX_CNT)
{
if(LinNm_State.wakeUpTimeOutTickCnt > LINCFG_SLOW_WAKEUP_PEIROD)
{
LinNm_State.wakeUpTimeOutTickCnt = 0;
LinIf_SendWakeUpSignal(LINCFG_SLAVE_CH_AS_WAKEUP_IDX);
LinNm_State.wakeUpSignalValidTickCnt = 0;
LinNm_SetComMode(LINNM_MODE_IDLE);
}
else
{
bool busIsInIdle = false;
busIsInIdle = LinNm_GetBusIsInIdle();
if(busIsInIdle == false)
{
LinNm_ClearActiveRequestWakeUp();
LinNm_State.busIdleTickCnt = 0;
LinNm_State.wakeUpTimeOutTickCnt = 0;
LinNm_State.retryWakeUpCnt = 0;
LinNm_SetComMode(LINNM_MODE_RUNNING);
}
}
}
else
{
if(LinNm_State.wakeUpTimeOutTickCnt > LINCFG_FAST_WAKEUP_PERIOD)
{
LinNm_State.wakeUpTimeOutTickCnt = 0;
LinNm_State.retryWakeUpCnt++;
LinIf_SendWakeUpSignal(LINCFG_SLAVE_CH_AS_WAKEUP_IDX);
LinNm_State.wakeUpSignalValidTickCnt = 0;
LinNm_SetComMode(LINNM_MODE_IDLE);
}
else
{
bool busIsInIdle = false;
busIsInIdle = LinNm_GetBusIsInIdle();
if(busIsInIdle == false)
{
LinNm_ClearActiveRequestWakeUp();
LinNm_State.busIdleTickCnt = 0;
LinNm_State.wakeUpTimeOutTickCnt = 0;
LinNm_State.retryWakeUpCnt = 0;
LinNm_SetComMode(LINNM_MODE_RUNNING);
}
}
}
}
#endif
}
/*! \brief Process the running state of communication manager
*
* This function execute to process the running state of communication manager
*
* \param[in] void:
* \return: void
*/
static void LinNm_RunningStateProc(void)
{
#if LINCFG_NODE_USED == LINCFG_NODE_MASTER
if(LinNm_GetSleepRequest() == false)
{
bool busIsInIdle = false;
busIsInIdle = LinNm_GetBusIsInIdle();
if(busIsInIdle == true)
{
/* If all node are in idle or not in busy state, and the time is out, then can enter into sleep */
if(LinNm_State.busIdleTickCnt >= LINCFG_BUS_IDLE_TICK_CNT)
{
uint8_t pidIdx = LinSchedule_GetPidIdx(LIN_STACK_PID_MRF);
Lin_FrameDataType *pFrameInfoPtr = LinCom_GetFramePointer(pidIdx);
uint8_t tableIdx = 0;
pFrameInfoPtr->poyload.diagBytes.nad = LINCFG_NODE_ADDRESS;
pFrameInfoPtr->poyload.diagBytes.data[0] = 0xFF;
pFrameInfoPtr->poyload.diagBytes.data[1] = 0xFF;
pFrameInfoPtr->poyload.diagBytes.data[2] = 0xFF;
pFrameInfoPtr->poyload.diagBytes.data[3] = 0xFF;
pFrameInfoPtr->poyload.diagBytes.data[4] = 0xFF;
pFrameInfoPtr->poyload.diagBytes.data[5] = 0xFF;
pFrameInfoPtr->poyload.diagBytes.data[6] = 0xFF;
linCom_BusTxSignalUpdate(pidIdx);
tableIdx = LinSchedule_GetScheduleTblIdxByTableType(LINSCH_TBL_TYPE_GO_TO_SLEEP);
if(LinSchedule_ReqSwitchScheduleTbl(LINCFG_MASTER_CH_IDX, tableIdx) == true)
{
LinNm_State.busIdleTickCnt = 0;
LinNm_SetSleepRequest();
LinNm_SetComMode(LINNM_MODE_SLEEP_PREPARE);
}
}
else
{
LinNm_State.busIdleTickCnt++;
}
}
else
{
LinNm_State.busIdleTickCnt = 0;
}
}
else
{
uint8_t pidIdx = LinSchedule_GetPidIdx(LIN_STACK_PID_MRF);
Lin_FrameDataType *pFrameInfoPtr = LinCom_GetFramePointer(pidIdx);
uint8_t tableIdx = 0;
pFrameInfoPtr->poyload.diagBytes.nad = LINCFG_NODE_ADDRESS;
pFrameInfoPtr->poyload.diagBytes.data[0] = 0xFF;
pFrameInfoPtr->poyload.diagBytes.data[1] = 0xFF;
pFrameInfoPtr->poyload.diagBytes.data[2] = 0xFF;
pFrameInfoPtr->poyload.diagBytes.data[3] = 0xFF;
pFrameInfoPtr->poyload.diagBytes.data[4] = 0xFF;
pFrameInfoPtr->poyload.diagBytes.data[5] = 0xFF;
pFrameInfoPtr->poyload.diagBytes.data[6] = 0xFF;
linCom_BusTxSignalUpdate(pidIdx);
tableIdx = LinSchedule_GetScheduleTblIdxByTableType(LINSCH_TBL_TYPE_GO_TO_SLEEP);
if(LinSchedule_ReqSwitchScheduleTbl(LINCFG_MASTER_CH_IDX, tableIdx) == true)
{
LinNm_SetSleepRequest();
LinNm_SetComMode(LINNM_MODE_SLEEP_PREPARE);
}
}
#else
if(LinNm_GetSleepRequest() == false)
{
bool busIsInIdle = false;
busIsInIdle = LinNm_GetBusIsInIdle();
if(busIsInIdle == true)
{
LinNm_State.busIdleTickCnt++;
/* If all node are in idle or not in busy state, and the time is out, then can enter into sleep */
if(LinNm_State.busIdleTickCnt >= LINCFG_BUS_IDLE_TICK_CNT)
{
LinNm_State.busIdleTickCnt = 0;
LinNm_SetSleepRequest();
LinNm_SetComMode(LINNM_MODE_SLEEP_READY);
}
}
else
{
LinNm_State.busIdleTickCnt = 0;
}
}
else
{
LinNm_State.busIdleTickCnt = 0;
LinNm_SetComMode(LINNM_MODE_SLEEP_READY);
}
#endif
}
/*! \brief Process the prepare sleep state of communication manager
*
* This function execute to process the prepare sleep state of communication manager
*
* \param[in] void:
* \return: void
*/
static void LinNm_PrepareSleepStateProc(void)
{
#if LINCFG_NODE_USED == LINCFG_NODE_MASTER
if(LinNm_GetSleepRequest() == true)
{
if(LinIf_GetSleepRequestIndication(LINCFG_MASTER_CH_IDX) == true)
{
bool busIsInIdle = false;
busIsInIdle = LinNm_GetBusIsInIdle();
if(busIsInIdle == true)
{
LinIf_ClearSleepRequestIndication(LINCFG_MASTER_CH_IDX);
LinNm_SetComMode(LINNM_MODE_SLEEP_READY);
}
}
}
#else
/* Slave node does not have this state */
#endif
}
/*! \brief Process the ready sleep state of communication manager
*
* This function execute to process the ready sleep state of communication manager
*
* \param[in] void:
* \return: void
*/
static void LinNm_ReadySleepStateProc(void)
{
#if LINCFG_NODE_USED == LINCFG_NODE_MASTER
if(LinNm_GetSleepRequest() == true)
{
bool busIsInIdle = false;
busIsInIdle = LinNm_GetBusIsInIdle();
if(busIsInIdle == true)
{
/* If sleep request is by node self or from bus , then can enter into sleep */
LinNm_SetComMode(LINNM_MODE_SLEEP);
/* Before enter sleep mode, re-configurate the lin driver into low-power or idle mode */
#if LINCFG_CH0_USED == LINCFG_CH_ACTIVE
LinIf_DeInit(0);
#endif
#if LINCFG_CH1_USED == LINCFG_CH_ACTIVE
LinIf_DeInit(1);
#endif
#if LINCFG_CH2_USED == LINCFG_CH_ACTIVE
LinIf_DeInit(2);
#endif
#if LINCFG_CH3_USED == LINCFG_CH_ACTIVE
LinIf_DeInit(3);
#endif
}
}
else
{
bool busIsInIdle = false;
busIsInIdle = LinNm_GetBusIsInIdle();
if(busIsInIdle == true)
{
LinNm_SetComMode(LINNM_MODE_IDLE);
}
}
#else
if(LinNm_GetSleepRequest() == true)
{
/* If sleep request is by node self or from bus , then can enter into sleep */
LinNm_SetComMode(LINNM_MODE_SLEEP);
/* Before enter sleep mode, re-configurate the lin driver into low-power or idle mode */
#if LINCFG_CH0_USED == LINCFG_CH_ACTIVE
LinIf_DeInit(0);
#endif
#if LINCFG_CH1_USED == LINCFG_CH_ACTIVE
LinIf_DeInit(1);
#endif
#if LINCFG_CH2_USED == LINCFG_CH_ACTIVE
LinIf_DeInit(2);
#endif
#if LINCFG_CH3_USED == LINCFG_CH_ACTIVE
LinIf_DeInit(3);
#endif
}
#endif
}
/*! \brief Process the sleep state of communication manager
*
* This function execute to process the sleep state of communication manager
*
* \param[in] void:
* \return: void
*/
static void LinNm_SleepStateProc(void)
{
#if LINCFG_NODE_USED == LINCFG_NODE_MASTER
if(LinNm_GetSleepRequest() == true)
{
LinNm_ClearSleepRequest();
LinNm_SetSleepIndication();
}
else
{
if(LinNm_GetSleepIndication() == true)
{
if(LinNm_GetActiveRequestWakeUp() == true)
{
LinNm_State.wakeUpSignalValidTickCnt = 0;
LinNm_ClearSleepIndication();
/* The internal logic to wakeup the bus */
LinIf_SendWakeUpSignal(LINCFG_MASTER_CH_IDX);
LinNm_SetComMode(LINNM_MODE_IDLE);
}
else
{
if(LinNm_CheckPassiveWakeUpSignal(LINCFG_MASTER_CH_IDX) == true)
{
LinNm_ClearSleepIndication();
LinNm_SetComMode(LINNM_MODE_IDLE);
}
}
}
}
#else
if(LinNm_GetSleepRequest() == true)
{
LinNm_ClearSleepRequest();
LinNm_SetSleepIndication();
}
else
{
if(LinNm_GetSleepIndication() == true)
{
if(LinNm_GetActiveRequestWakeUp() == true)
{
LinNm_State.wakeUpSignalValidTickCnt = 0;
LinNm_ClearSleepIndication();
LinIf_SendWakeUpSignal(LINCFG_SLAVE_CH_AS_WAKEUP_IDX);
LinNm_SetComMode(LINNM_MODE_IDLE);
}
else
{
if(LinNm_CheckPassiveWakeUpSignal(LINCFG_SLAVE_CH_AS_WAKEUP_IDX) == true)
{
LinNm_ClearSleepIndication();
LinNm_SetComMode(LINNM_MODE_IDLE);
}
}
}
}
#endif
}
/*! \brief Process the communication manager
*
* This function execute to process the communication manager
*
* \param[in] void:
* \return: void
*/
void LinNm_MainFunction(void)
{
if(LinNm_State.currentComMode != LinNm_State.targetComMode)
{
bool busIsInIdle = false;
busIsInIdle = LinNm_GetBusIsInIdle();
/* Only all node are in idle or not in busy, then can change the current communication mode */
if(busIsInIdle == true)
{
LinNm_State.currentComMode = LinNm_State.targetComMode;
}
}
else
{
switch(LinNm_State.currentComMode)
{
case LINNM_MODE_IDLE:
LinNm_IdleStateProc();
break;
case LINNM_MODE_INIT:
LinNm_InitStateProc();
break;
case LINNM_MODE_RUNNING:
LinNm_RunningStateProc();
break;
case LINNM_MODE_SLEEP_PREPARE:
LinNm_PrepareSleepStateProc();
break;
case LINNM_MODE_SLEEP_READY:
LinNm_ReadySleepStateProc();
break;
case LINNM_MODE_SLEEP:
LinNm_SleepStateProc();
break;
default:
break;
}
}
}

View File

@ -1,185 +0,0 @@
/*
* 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 _LIN_NM_H_
#define _LIN_NM_H_
/*! \brief his file exports Lin communication manager
*
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
/*! \addtogroup lin_com_manager
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
typedef enum
{
LINNM_MODE_IDLE = 0u,
LINNM_MODE_INIT,
LINNM_MODE_RUNNING,
LINNM_MODE_SLEEP_PREPARE,
LINNM_MODE_SLEEP_READY,
LINNM_MODE_SLEEP,
LINNM_MODE_NUM
} LinNm_ModeType;
typedef struct
{
bool transferSuccessful;
bool responseError;
uint32_t wakeUpSignalValidTickCnt;
uint32_t delayCommunicateTickCnt;
uint32_t busIdleTickCnt;
uint32_t wakeUpTimeOutTickCnt;
uint8_t retryWakeUpCnt;
bool requestSleep;
bool sleepIndication;
bool activeWakeUpReq;
bool passiveWakeUpConfirm;
LinNm_ModeType currentComMode;
LinNm_ModeType targetComMode;
} LinNm_StateType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the communication manager
*
* This function execute to initialize the communication manager
*
* \param[in] cpuClockFrequency: cpu lock frequency
* \return: void
*/
extern void LinNm_Init(uint32_t cpuClockFrequency);
/*! \brief Get the communication mode
*
* This function execute to get the communication mode
*
* \param[in] void:
* \return: the communication mode
*/
extern LinNm_ModeType LinNm_GetComMode(void);
/*! \brief Request sleep
*
* This function execute to request sleep
*
* \param[in] sleepRequest: request sleep
* \return: void
*/
extern void LinNm_RequestSleep(bool sleepRequest);
/*! \brief Set the active wake up request
*
* This function execute to set active wake-up request if the local condition is match to exist from sleep
*
* \param[in] void:
* \return: void
*/
extern void LinNm_SetActiveRequestWakeUp(void);
/*! \brief Check the passive wakeup signal
*
* This function execute to get the passive wake-up signal from bus
*
* \param[in] uint8_t channelIdx: which physical channel is used
* \return: true: passive wakeup signal is valid
* false: passive wakup signal is invalid
*/
extern bool LinNm_CheckPassiveWakeUpSignal(uint8_t channelIdx);
/*! \brief Process the communication manager
*
* This function execute to process the communication manager
*
* \param[in] void:
* \return: void
*/
extern void LinNm_MainFunction(void);
/*! \brief Set the error response bit
*
* This function execute to update the response error bit
*
* \param[in] errBit: err
* \return: void
*/
extern void LinNm_SetErrResponseBit(bool errBit);
/*! \brief Get the error response bit
*
* This function execute to get the error response bit
*
* \param[in] void:
* \return: true: error is happen
* false: error is not happen
*/
extern bool LinNm_GetErrResponseBit(void);
/*! \brief Set the transfer successful bit
*
* This function execute
*
* \param[in] successfullBit: true or false
* \return: void
*/
extern void LinNm_SetSuccessfulTransferBit(bool successfulBit);
/*! \brief Get the transfer successful bit
*
* This function execute to get the transfer successful bit
*
* \param[in] void:
* \return: true: transfer successfully
* false: transfer failed
*/
extern bool LinNm_GetSuccessfulTransferBit(void);
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _LIN_COM_MANAGER_H_ */

View File

@ -1,902 +0,0 @@
/*
* 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 <string.h>
#include "lin_cfg.h"
#include "lin_type.h"
#include "lin_schedule.h"
#include "lin_if.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
LinSchedule_CtrlType LinSchedule_Ctrl;
/*******************************************************************************
* the functions
******************************************************************************/
/*! \brief Initialize the schedule state information
*
* This function execute to initialize the schedule state information
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
void LinSchedule_Init(uint8_t channelIdx)
{
uint8_t i = 0, defaultScheduleIdx = LINSCH_SCHEDULE_TABLE_NULL;
defaultScheduleIdx = LinSchedule_Ctrl.chxState[channelIdx].defaultScheduleTblIdx;
memset(&LinSchedule_Ctrl.chxState[channelIdx], 0, sizeof(LinSchedule_StateType));
LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx = LINSCH_SCHEDULE_TABLE_NULL;
LinSchedule_Ctrl.chxState[channelIdx].prevScheduleTblIdx = LINSCH_SCHEDULE_TABLE_NULL;
LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr = NULL;
LinSchedule_Ctrl.chxState[channelIdx].defaultScheduleTblIdx = defaultScheduleIdx;
for(i = 0; i < LinSchedule_Ctrl.pLinSchedule_TblInfo->frameGeneralityNum; i++)
{
memset(&LinSchedule_Ctrl.pLinSchedule_TblInfo->pFrameGenerality[i].pFrameDataPtr[i], 0u, sizeof(Lin_FrameDataType));
*LinSchedule_Ctrl.pLinSchedule_TblInfo->pFrameGenerality[i].pFrameAccessStatePtr = LIN_FRAME_ACCESS_STATE_IDLE;
}
}
/*! \brief Initialize the schedule table information
*
* This function execute to initialize the schedule table information
*
* \param[in] pTblInfo: table information pointer
* \return: void
*/
void LinSchedule_TblInit(const LinSchedule_TblInfoType *pTblInfo)
{
uint8_t i = 0;
memset(&LinSchedule_Ctrl, 0, sizeof(LinSchedule_Ctrl));
LinSchedule_Ctrl.pLinSchedule_TblInfo = pTblInfo;
for(i = 0; i < LINCFG_CH_NUM; i++)
{
LinSchedule_Init(i);
}
}
/*! \brief Get the support frame number in the LIN BUS
*
* This function execute to get the frame number
*
* \param[in] uint8_t channelIdx: which physical channel is used
* \return: the frame number
*/
uint8_t LinSchedule_GetFrameNum(uint8_t channelIdx)
{
uint8_t ret = 0;
ret = LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo[channelIdx].chxFrameAttributeNum;
return ret;
}
/*! \brief Get the frame number in the current schedule table
*
* This function execute to get the frame number in the current schedule table
*
* \param[in] channelIdx: which physical channel is used
* \param[in] linkTblIdx: which schedule table is to be check
* \return: the frame number in the current schedule table
*/
uint8_t LinSchedule_GetFrameNumInScheduleTbl(uint8_t channelIdx, uint8_t linkTblIdx)
{
uint8_t ret = 0;
ret = LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo[channelIdx].pChxScheduleTblList[linkTblIdx].frameNum;
return ret;
}
/*! \brief Get the pid by the pid index
*
* This function execute to get the pid in the support pid list
*
* \param[in] pidIdx: pid index
* \return: pid
*/
uint8_t LinSchedule_GetPid(uint8_t pidIdx)
{
uint8_t ret = LIN_DATA_INVALID;
if(pidIdx < LinSchedule_Ctrl.pLinSchedule_TblInfo->frameGeneralityNum)
{
ret = LinSchedule_Ctrl.pLinSchedule_TblInfo->pFrameGenerality[pidIdx].pid;
}
return ret;
}
/*! \brief Get the pid index by pid
*
* This function execute to get the pid by the pid index in the support pid list
*
* \param[in] pid: pid
* \return: pid index
*/
uint8_t LinSchedule_GetPidIdx(uint8_t pid)
{
uint8_t frameIdx = LIN_DATA_INVALID;
uint8_t i = 0;
for(i = 0; i < LinSchedule_Ctrl.pLinSchedule_TblInfo->frameGeneralityNum; i++)
{
if(pid == LinSchedule_Ctrl.pLinSchedule_TblInfo->pFrameGenerality[i].pid)
{
frameIdx = i;
break;
;
}
}
return frameIdx;
}
/*! \brief Get the frame type
*
* This function execute to get the frame type by the pid index
*
* \param[in] channelIdx: : which physical channel is used
* \param[in] pidIdx: pid index
* \return: the frame type
*/
Lin_FrametypeType LinSchedule_GetFrameType(uint8_t channelIdx, uint8_t pidIdx)
{
Lin_FrametypeType ret = LIN_FRAME_TYPE_RESERVED;
if(pidIdx != LIN_DATA_INVALID)
{
if(pidIdx < LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo[channelIdx].chxFrameAttributeNum)
{
ret = LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo[channelIdx].pChxFrameAttribute[pidIdx].frameType;
}
}
return ret;
}
/*! \brief Get the frame control
*
* This function execute to get the frame control
*
* \param[in] channelIdx: : which physical channel is used
* \param[in] pidIdx: pid index
* \return: frame control type
*/
Lin_FrameCtrlType LinSchedule_GetFrameCtrl(uint8_t channelIdx, uint8_t pidIdx)
{
Lin_FrameCtrlType ret = LIN_FRAME_CTRL_NO_ACTION;
if(pidIdx != LIN_DATA_INVALID)
{
if(pidIdx < LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo[channelIdx].chxFrameAttributeNum)
{
ret = LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo[channelIdx].pChxFrameAttribute[pidIdx].frameCtrl;
}
}
return ret;
}
/*! \brief Get the frame data length by pid index
*
* This function execute to get the frame data length by pid index
*
* \param[in] pidIdx: pid index
* \return: the length of the frame data
*/
uint8_t LinSchedule_GetFrameDataLen(uint8_t pidIdx)
{
uint8_t ret = 0;
if(pidIdx < LinSchedule_Ctrl.pLinSchedule_TblInfo->frameGeneralityNum)
{
ret = LinSchedule_Ctrl.pLinSchedule_TblInfo->pFrameGenerality[pidIdx].frameLen;
}
return ret;
}
/*! \brief Get the checksum type
*
* This function execute to get the checksum type
*
* \param[in] pid: pid
* \return: the type of check sum
*/
Lin_CheckSumType LinSchedule_GetCheckSumType(uint8_t pid)
{
Lin_CheckSumType ret = LIN_CHECKSUM_CLASSIC;
if((pid != LIN_STACK_PID_MRF) && (pid != LIN_STACK_PID_SRF))
{
#if LINCFG_PROTOCOL_VER >= LIN_PROTOCOL_VER_20
ret = LIN_CHECKSUM_ENHANCED;
#endif
}
return ret;
}
/*! \brief Get the frame buffer pointer
*
* This function execute to get the frame buffer pointer, each frame has their own buffer
*
* \param[in] pidIdx: pid index
* \return: the pointer of frame buffer
*/
Lin_FrameDataType *LinSchedule_GetFrameBufferPtr(uint8_t pidIdx)
{
Lin_FrameDataType *ret = 0;
if(pidIdx != LIN_DATA_INVALID)
{
ret = (Lin_FrameDataType *)(LinSchedule_Ctrl.pLinSchedule_TblInfo->pFrameGenerality[pidIdx].pFrameDataPtr);
}
return ret;
}
/*! \brief Sect the frame access state
*
* This function execute to set the frame access state, allow or not allow to readout from the frame buffer or write data into frame buffer
*
* \param[in] pidIdx: pid index
* \param[in] accessState: access state
* \return: void
*/
void LinSchedule_SetFrameAccessState(uint8_t pidIdx, Lin_FrameAccessStateType accessState)
{
if(pidIdx != LIN_DATA_INVALID)
{
*(LinSchedule_Ctrl.pLinSchedule_TblInfo->pFrameGenerality[pidIdx].pFrameAccessStatePtr) = accessState;
}
}
/*! \brief Get the frame access state
*
* This function execute
*
* \param[in] uint8_t pidIdx:
* \return: Lin_FrameAccessStateType
*/
Lin_FrameAccessStateType LinSchedule_GetFrameAccessState(uint8_t pidIdx)
{
Lin_FrameAccessStateType ret = LIN_FRAME_ACCESS_STATE_IDLE;
if(pidIdx != LIN_DATA_INVALID)
{
ret = *LinSchedule_Ctrl.pLinSchedule_TblInfo->pFrameGenerality[pidIdx].pFrameAccessStatePtr;
}
return ret;
}
/*! \brief Get the frame slot tick
*
* This function execute to get the frame slot tick in the special schedule table by pid
*
* \param[in] channelIdx: : which physical channel is used
* \param[in] scheduleTblIdx: the target schedule table index
* \param[in] pidIdx: pid index
* \return: the frame slot tick
*/
uint16_t LinSchedule_GetFrameSlotTick(uint8_t channelIdx, uint8_t scheduleTblIdx, uint8_t pidIdx)
{
uint16_t ret = 0;
uint8_t i = 0;
if(scheduleTblIdx < LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo->chxScheduleTblNum)
{
for(i = 0; i < LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo->pChxScheduleTblList[scheduleTblIdx].frameNum; i++)
{
if(pidIdx == LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo->pChxScheduleTblList[scheduleTblIdx].pScheduleTblInfo[i].pidIdx)
{
ret = LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo->pChxScheduleTblList[scheduleTblIdx].pScheduleTblInfo[pidIdx].frameSlotTick;
break;
}
}
}
return ret;
}
/*! \brief Get the type of current operated schedule table
*
* This function execute to get the type of current operated schedule table
*
* \param[in] channelIdx: : which physical channel is used
* \param[in] scheduleTblIdx: schedule table index
* \return: the type of schedule table
*/
LinSchedule_TableType LinSchedule_GetScheduleTableType(uint8_t channelIdx, uint8_t scheduleTblIdx)
{
LinSchedule_TableType ret = LINSCH_TBL_TYPE_NULL;
uint8_t i = 0;
for(i = 0; i < LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo->chxScheduleTblNum; i++)
{
if(scheduleTblIdx == LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo->pChxScheduleTblList[i].tblIdx)
{
ret = LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo->pChxScheduleTblList[i].tblType;
break;
}
}
return ret;
}
/*! \brief Get the schedule table index by table type
*
* This function execute to get the type of current operated schedule table
*
* \param[in] tableType: : the type of schedule table
* \return: return the first match table index in the schedule table list
*/
uint8_t LinSchedule_GetScheduleTblIdxByTableType(LinSchedule_TableType tableType)
{
uint8_t i = 0, ret = 0;
for(i = 0; i < LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo->chxScheduleTblNum; i++)
{
if(tableType == LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo->pChxScheduleTblList[i].tblType)
{
ret = i;
break;
}
}
return ret;
}
/*! \brief Get the link schedule table pointer
*
* This function execute to get the link schedule table pointer
*
* \param[in] channelIdx: which physical channel is used
* \param[in] linkTblIdx: the link schedule table index
* \return: the link schedule table pointer
*/
LinSchedule_ScheduleTblListType *LinSchedule_GetLinkScheduleTblPtr(uint8_t channelIdx, uint8_t linkTblIdx)
{
LinSchedule_ScheduleTblListType *ret = NULL;
uint8_t i = 0;
for(i = 0; i < LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo->chxScheduleTblNum; i++)
{
if(linkTblIdx == LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo->pChxScheduleTblList[i].tblIdx)
{
ret = (LinSchedule_ScheduleTblListType *)&LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo->pChxScheduleTblList[i];
break;
}
}
return ret;
}
/*! \brief Get the pid index in the target schedule table
*
* This function execute to get the pid index in the target schedule table by frame index
*
* \param[in] channelIdx: which physical channel is used
* \param[in] linkTblIdx: link schedule table index
* \param[in] frameIdx: the frame index in schedule table
* \return: pid index
*/
uint8_t LinSchedule_GetPidIdxInSchedulerTbl(uint8_t channelIdx, uint8_t linkTblIdx, uint8_t frameIdx)
{
uint8_t ret = LINSCH_FRAMEID_IDX_INVALID;
if((linkTblIdx < LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo->chxScheduleTblNum) && (frameIdx < LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo->pChxScheduleTblList[linkTblIdx].frameNum))
{
if(LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo->pChxScheduleTblList[linkTblIdx].pScheduleTblInfo != NULL)
{
ret = LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo->pChxScheduleTblList[linkTblIdx].pScheduleTblInfo[frameIdx].pidIdx;
}
}
return ret;
}
/*! \brief Get the link schedule table index
*
* This function execute to get the link schedule table index by the pid index in current schedule table
*
* \param[in] channelIdx: which physical channel is used
* \param[in] tblIdx: the current schedule table index
* \param[in] pidIdx: the pid index
* \return: the link schedule table index
*/
uint8_t LinSchedule_GetLinkTblIdx(uint8_t channelIdx, uint8_t tblIdx, uint8_t pidIdx)
{
uint8_t ret = LINSCH_SCHEDULE_TABLE_NULL;
uint8_t i = 0;
if(tblIdx < LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo->chxScheduleTblNum)
{
if(LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo->pChxScheduleTblList[tblIdx].pScheduleTblInfo != NULL)
{
for(i = 0; i < LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo->pChxScheduleTblList[tblIdx].frameNum; i++)
{
if(pidIdx == LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo->pChxScheduleTblList[tblIdx].pScheduleTblInfo[i].pidIdx)
{
ret = LinSchedule_Ctrl.pLinSchedule_TblInfo->chxTableInfo->pChxScheduleTblList[tblIdx].pScheduleTblInfo[pidIdx].linkTblIdx;
break;
}
}
}
}
return ret;
}
#if LINCFG_NODE_USED == LINCFG_NODE_MASTER
/*! \brief Get the default schedule table index
*
* This function execute to get the default schedule table index
*
* \param[in] channelIdx: which physical channel is used
* \return: the default schedule table index
*/
uint8_t LinSchedule_GetDefaultScheduleTblIdx(uint8_t channelIdx)
{
return LinSchedule_Ctrl.chxState[channelIdx].defaultScheduleTblIdx;
}
/*! \brief Set the default schedule table index
*
* This function execute to set the default schedule table index
*
* \param[in] channelIdx: which physical channel is used
* \param[in]: the default schedule table index
*/
void LinSchedule_SetDefaultScheduleTblIdx(uint8_t channelIdx, uint8_t defaultScheduleTblIdx)
{
LinSchedule_Ctrl.chxState[channelIdx].defaultScheduleTblIdx = defaultScheduleTblIdx;
}
/*! \brief Request to switch schedule table
*
* This function execute to request to switch to target schedule table
*
* \param[in] channelIdx: which physical channel is used
* \param[in] targetScheduleTblIdx: target schedule index
* \return: true: switch to target schedule table successfully
* false: switch to target schedule table failed
*/
bool LinSchedule_ReqSwitchScheduleTbl(uint8_t channelIdx, uint8_t targetScheduleTblIdx)
{
bool ret = false;
if((targetScheduleTblIdx != LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx) && (LinSchedule_Ctrl.chxState[channelIdx].scheduleTblSwitchReqEn == false))
{
LinSchedule_Ctrl.chxState[channelIdx].targetScheduleTblIdx = targetScheduleTblIdx;
LinSchedule_Ctrl.chxState[channelIdx].scheduleTblSwitchReqEn = true;
ret = true;
}
return ret;
}
#endif
#if LINCFG_NODE_USED == LINCFG_NODE_MASTER
/*! \brief Go on to transmit the frame in the current schedule table
*
* This function execute to go on to transmit the frame in the current schedule table
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
static void LinSchedule_ContinueTransmitProc(uint8_t channelIdx)
{
/* If transmit frame are not all transmitted and no the action of switch table request is exist, continue to transmit the frames in the current table */
bool txReq = false;
uint8_t pidIdx = LINSCH_FRAMEID_IDX_INVALID;
/* Check the current frame in the current schedule table is a sporadic or not */
if(LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].frameType != LIN_FRAME_TYPE_SPORADIC)
{
/* Transmit the next frame */
LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl = LinSchedule_Ctrl.chxState[channelIdx].txFrameCnt;
pidIdx = LinSchedule_GetPidIdxInSchedulerTbl(channelIdx, LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx, LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl);
if(pidIdx != LINSCH_FRAMEID_IDX_INVALID)
{
Lin_FrameAccessStateType accessState;
accessState = LinSchedule_GetFrameAccessState(pidIdx);
if((accessState == LIN_FRAME_ACCESS_STATE_IDLE) || (accessState == LIN_FRAME_ACCESS_STATE_UPDATED))
{
txReq = true;
}
}
}
else
{
uint8_t linkTblIdx = LINSCH_SCHEDULE_TABLE_NULL, i = 0;
linkTblIdx = LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].linkTblIdx;
if(linkTblIdx != LINSCH_SCHEDULE_TABLE_NULL)
{
/* Before switch to new table, store the current table information */
LinSchedule_Ctrl.chxState[channelIdx].prevScheduleTblIdx = LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx;
LinSchedule_Ctrl.chxState[channelIdx].prevFrameIdxInScheduleTbl = LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl;
/* Switch to the new schedule table */
LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx = linkTblIdx;
LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr = (const LinSchedule_ScheduleTblListType *)LinSchedule_GetLinkScheduleTblPtr(channelIdx, linkTblIdx);
LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl = 0;
LinSchedule_Ctrl.chxState[channelIdx].txFrameCnt = 0;
if(LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr != NULL)
{
uint8_t frameNum = 0;
frameNum = LinSchedule_GetFrameNumInScheduleTbl(channelIdx, linkTblIdx);
for(i = 0; i < frameNum; i++)
{
/* Check the upper data are changed or not */
LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl = i;
LinSchedule_Ctrl.chxState[channelIdx].frameSlotTick = LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[i].frameSlotTick;
if(LinSchedule_GetFrameAccessState(LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[i].pidIdx) == LIN_FRAME_ACCESS_STATE_UPDATED)
{
txReq = true;
break;
}
else
{
LinSchedule_Ctrl.chxState[channelIdx].txFrameCnt++;
}
}
}
}
}
if(txReq == true)
{
Lin_FrameInfoType frameInfo;
uint8_t pidIdx = 0;
pidIdx = LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].pidIdx;
LinSchedule_Ctrl.chxState[channelIdx].frameSlotTick = LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].frameSlotTick;
frameInfo.frameType = LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].frameType;
frameInfo.pid = LinSchedule_GetPid(pidIdx);
frameInfo.pFrameData = LinSchedule_GetFrameBufferPtr(pidIdx);
frameInfo.dataLen = LinSchedule_GetFrameDataLen(pidIdx);
frameInfo.frameCtrl = LinSchedule_GetFrameCtrl(channelIdx, pidIdx);
if(LinIf_ReqTransmit(channelIdx, &frameInfo) == true)
{
/* Nothing to do */
}
LinSchedule_Ctrl.chxState[channelIdx].txFrameCnt++;
}
}
#endif
#if LINCFG_NODE_USED == LINCFG_NODE_MASTER
/*! \brief The main function of schedule table process
*
* This function execute to process the schedule table
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
void LinSchedule_MainFunction(uint8_t channelIdx)
{
if(LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr != NULL)
{
if(LinSchedule_Ctrl.chxState[channelIdx].frameSlotTick > LINCFG_TICK_BASE)
{
LinSchedule_Ctrl.chxState[channelIdx].frameSlotTick -= LINCFG_TICK_BASE;
}
else
{
Lin_OpStatusType linOpStatus;
linOpStatus = LinIf_GetTransferOperateStatus(channelIdx);
if((linOpStatus == LIN_STATUS_IDLE) || (linOpStatus == LIN_STATUS_TX_OK) || (linOpStatus == LIN_STATUS_RX_OK) || ((linOpStatus >= LIN_STATUS_ERR_BIT) && (LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].frameType == LIN_FRAME_TYPE_UNCONDITIONAL)) || ((linOpStatus == LIN_STATUS_ERR_TIMEOUT) && (LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].frameType == LIN_FRAME_TYPE_EVENT_TRIGGER)))
{
/* Check the current table , all frame in the table have been transmitted */
if(LinSchedule_Ctrl.chxState[channelIdx].txFrameCnt < LinSchedule_GetFrameNumInScheduleTbl(channelIdx, LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx))
{
if(linOpStatus >= LIN_STATUS_ERR_BIT)
{
linOpStatus = LIN_STATUS_IDLE;
}
/* If transmit frame are not all transmitted, then before transmit the next frame, need to check if there is the action of request schedule table to switch */
if(LinSchedule_Ctrl.chxState[channelIdx].scheduleTblSwitchReqEn == true)
{
/* If the target schedule is different with the current schedult table, switch to the target schedule table */
if(LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx != LinSchedule_Ctrl.chxState[channelIdx].targetScheduleTblIdx)
{
/* If the current schedult table is normal type, then allow to switch target table , if not, continue to transmit the frame in the current table, until finished transmit all frame */
if(LinSchedule_GetScheduleTableType(channelIdx, LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx) == LINSCH_TBL_TYPE_NORM)
{
uint8_t pidIdx = LINSCH_FRAMEID_IDX_INVALID;
LinSchedule_Ctrl.chxState[channelIdx].scheduleTblSwitchReqEn = false;
LinSchedule_Ctrl.chxState[channelIdx].prevFrameIdxInScheduleTbl = LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl;
LinSchedule_Ctrl.chxState[channelIdx].prevScheduleTblIdx = LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx;
LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx = LinSchedule_Ctrl.chxState[channelIdx].targetScheduleTblIdx;
LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr = (const LinSchedule_ScheduleTblListType *)LinSchedule_GetLinkScheduleTblPtr(channelIdx, LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx);
LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl = 0;
LinSchedule_Ctrl.chxState[channelIdx].txFrameCnt = 0;
/* Read out from the new schedule table */
pidIdx = LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].pidIdx;
if(pidIdx != LINSCH_FRAMEID_IDX_INVALID)
{
Lin_FrameAccessStateType accessState;
accessState = LinSchedule_GetFrameAccessState(pidIdx);
if((accessState == LIN_FRAME_ACCESS_STATE_IDLE) || (accessState == LIN_FRAME_ACCESS_STATE_UPDATED))
{
Lin_FrameInfoType frameInfo;
LinSchedule_Ctrl.chxState[channelIdx].frameSlotTick = LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].frameSlotTick;
frameInfo.frameType = LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].frameType;
frameInfo.dataLen = LinSchedule_GetFrameDataLen(pidIdx);
frameInfo.pid = LinSchedule_GetPid(pidIdx);
frameInfo.frameCtrl = LinSchedule_GetFrameCtrl(channelIdx, pidIdx);
frameInfo.pFrameData = LinSchedule_GetFrameBufferPtr(pidIdx);
if(LinIf_ReqTransmit(channelIdx, &frameInfo) == true)
{
/* Indication Upper layer that go to sleep cmd is doing */
if(LinSchedule_GetScheduleTableType(channelIdx, LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx) == LINSCH_TBL_TYPE_GO_TO_SLEEP)
{
LinIf_SetSleepRequestIndication(LINCFG_MASTER_CH_IDX);
}
}
LinSchedule_Ctrl.chxState[channelIdx].txFrameCnt++;
}
}
}
else
{
LinSchedule_ContinueTransmitProc(channelIdx);
}
}
}
else
{
LinSchedule_ContinueTransmitProc(channelIdx);
}
}
else
{
/* The current schedule table, all frames are transmitted, need to transmit from the header of the current table, if there is no action of switch schedule table */
if(LinSchedule_Ctrl.chxState[channelIdx].scheduleTblSwitchReqEn == true)
{
if(LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx != LinSchedule_Ctrl.chxState[channelIdx].targetScheduleTblIdx)
{
uint8_t pidIdx = LINSCH_FRAMEID_IDX_INVALID;
LinSchedule_Ctrl.chxState[channelIdx].prevFrameIdxInScheduleTbl = LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl;
LinSchedule_Ctrl.chxState[channelIdx].prevScheduleTblIdx = LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx;
LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx = LinSchedule_Ctrl.chxState[channelIdx].targetScheduleTblIdx;
LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr = (const LinSchedule_ScheduleTblListType *)LinSchedule_GetLinkScheduleTblPtr(channelIdx, LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx);
LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl = 0;
LinSchedule_Ctrl.chxState[channelIdx].txFrameCnt = 0;
pidIdx = LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].pidIdx;
if(pidIdx != LINSCH_FRAMEID_IDX_INVALID)
{
Lin_FrameAccessStateType accessState;
accessState = LinSchedule_GetFrameAccessState(pidIdx);
if((accessState == LIN_FRAME_ACCESS_STATE_IDLE) || (accessState == LIN_FRAME_ACCESS_STATE_UPDATED))
{
Lin_FrameInfoType frameInfo;
LinSchedule_Ctrl.chxState[channelIdx].frameSlotTick = LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].frameSlotTick;
frameInfo.frameType = LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].frameType;
frameInfo.dataLen = LinSchedule_GetFrameDataLen(pidIdx);
frameInfo.pid = LinSchedule_GetPid(pidIdx);
frameInfo.frameCtrl = LinSchedule_GetFrameCtrl(channelIdx, pidIdx);
frameInfo.pFrameData = LinSchedule_GetFrameBufferPtr(pidIdx);
if(LinIf_ReqTransmit(channelIdx, &frameInfo) == true)
{
/* Indication Upper layer that go to sleep cmd is doing */
if(LinSchedule_GetScheduleTableType(channelIdx, LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx) == LINSCH_TBL_TYPE_GO_TO_SLEEP)
{
LinIf_SetSleepRequestIndication(LINCFG_MASTER_CH_IDX);
}
}
LinSchedule_Ctrl.chxState[channelIdx].txFrameCnt++;
}
}
}
LinSchedule_Ctrl.chxState[channelIdx].scheduleTblSwitchReqEn = false;
}
else
{
bool txReq = false;
uint8_t pidIdx = LINSCH_FRAMEID_IDX_INVALID;
/* If the current schedule table is the same as the previous table */
if(LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx == LinSchedule_Ctrl.chxState[channelIdx].prevScheduleTblIdx)
{
LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl = 0;
LinSchedule_Ctrl.chxState[channelIdx].txFrameCnt = 0;
pidIdx = LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].pidIdx;
if(pidIdx != LINSCH_FRAMEID_IDX_INVALID)
{
Lin_FrameAccessStateType accessState;
accessState = LinSchedule_GetFrameAccessState(pidIdx);
if((accessState == LIN_FRAME_ACCESS_STATE_IDLE) || (accessState == LIN_FRAME_ACCESS_STATE_UPDATED))
{
txReq = true;
}
}
}
else
{
/* If the current schedule table is different with the previous table, restore the previous table from the break frame index to continue to transmit */
LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx = LinSchedule_Ctrl.chxState[channelIdx].prevScheduleTblIdx;
LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl = LinSchedule_Ctrl.chxState[channelIdx].prevFrameIdxInScheduleTbl + 1u;
LinSchedule_Ctrl.chxState[channelIdx].txFrameCnt = LinSchedule_Ctrl.chxState[channelIdx].prevFrameIdxInScheduleTbl + 1u;
LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr = (const LinSchedule_ScheduleTblListType *)LinSchedule_GetLinkScheduleTblPtr(channelIdx, LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx);
pidIdx = LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].pidIdx;
if(pidIdx != LINSCH_FRAMEID_IDX_INVALID)
{
Lin_FrameAccessStateType accessState;
accessState = LinSchedule_GetFrameAccessState(pidIdx);
if((accessState == LIN_FRAME_ACCESS_STATE_IDLE) || (accessState == LIN_FRAME_ACCESS_STATE_UPDATED))
{
txReq = true;
}
}
}
if(txReq == true)
{
Lin_FrameInfoType frameInfo;
uint8_t pidIdx = LINSCH_FRAMEID_IDX_INVALID;
pidIdx = LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].pidIdx;
LinSchedule_Ctrl.chxState[channelIdx].frameSlotTick = LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].frameSlotTick;
frameInfo.frameType = LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].frameType;
frameInfo.dataLen = LinSchedule_GetFrameDataLen(pidIdx);
frameInfo.pid = LinSchedule_GetPid(pidIdx);
frameInfo.frameCtrl = LinSchedule_GetFrameCtrl(channelIdx, pidIdx);
frameInfo.pFrameData = LinSchedule_GetFrameBufferPtr(pidIdx);
if(LinIf_ReqTransmit(channelIdx, &frameInfo) == true)
{
/* Nothing to do */
}
LinSchedule_Ctrl.chxState[channelIdx].txFrameCnt++;
}
}
}
}
else if(linOpStatus >= LIN_STATUS_ERR_BIT)
{
/* If the current frame type is event trigger frame, allow to exist the error of timeout */
if(linOpStatus < LIN_STATUS_ERR_TIMEOUT)
{
/* If the error happen, indicate the arbitration of bus is exist, need to switch to collision table */
if(LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].frameType == LIN_FRAME_TYPE_EVENT_TRIGGER)
{
uint8_t linkTblIdx = LINSCH_SCHEDULE_TABLE_NULL;
/* Get the associated schedule table of the current event trigger frame, means to switch the associated collision schedule table */
linkTblIdx = LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].linkTblIdx;
if(linkTblIdx != LINSCH_SCHEDULE_TABLE_NULL)
{
uint8_t pidIdx = LINSCH_FRAMEID_IDX_INVALID;
LinSchedule_Ctrl.chxState[channelIdx].prevScheduleTblIdx = LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx;
LinSchedule_Ctrl.chxState[channelIdx].prevFrameIdxInScheduleTbl = LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl;
LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx = linkTblIdx;
LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr = (const LinSchedule_ScheduleTblListType *)LinSchedule_GetLinkScheduleTblPtr(channelIdx, linkTblIdx);
LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl = 0;
LinSchedule_Ctrl.chxState[channelIdx].txFrameCnt = 0;
pidIdx = LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].pidIdx;
if(pidIdx != LINSCH_FRAMEID_IDX_INVALID)
{
Lin_FrameAccessStateType accessState;
accessState = LinSchedule_GetFrameAccessState(pidIdx);
if(accessState == LIN_FRAME_ACCESS_STATE_UPDATED)
{
Lin_FrameInfoType frameInfo;
LinSchedule_Ctrl.chxState[channelIdx].frameSlotTick = LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].frameSlotTick;
frameInfo.frameType = LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr->pScheduleTblInfo[LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl].frameType;
frameInfo.dataLen = LinSchedule_GetFrameDataLen(pidIdx);
frameInfo.pid = LinSchedule_GetPid(pidIdx);
frameInfo.frameCtrl = LinSchedule_GetFrameCtrl(channelIdx, pidIdx);
frameInfo.pFrameData = LinSchedule_GetFrameBufferPtr(pidIdx);
if(LinIf_ReqTransmit(channelIdx, &frameInfo) == true)
{
/* Nothing to do */
}
LinSchedule_Ctrl.chxState[channelIdx].txFrameCnt++;
}
}
}
}
}
}
}
}
else
{
/* If the current schedule is empty, if exist the action of request to switch new table , switch to new schedule table */
if(LinSchedule_Ctrl.chxState[channelIdx].scheduleTblSwitchReqEn == true)
{
LinSchedule_Ctrl.chxState[channelIdx].scheduleTblSwitchReqEn = false;
LinSchedule_Ctrl.chxState[channelIdx].currentFrameSlotTickCnt = 0;
LinSchedule_Ctrl.chxState[channelIdx].frameSlotTick = 0;
LinSchedule_Ctrl.chxState[channelIdx].txFrameCnt = 0;
LinSchedule_Ctrl.chxState[channelIdx].currentFrameIdxInScheduleTbl = 0;
LinSchedule_Ctrl.chxState[channelIdx].prevFrameIdxInScheduleTbl = 0;
LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx = LinSchedule_Ctrl.chxState[channelIdx].targetScheduleTblIdx;
LinSchedule_Ctrl.chxState[channelIdx].prevScheduleTblIdx = LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx;
LinSchedule_Ctrl.chxState[channelIdx].pCurrentScheduleTblPtr = (const LinSchedule_ScheduleTblListType *)LinSchedule_GetLinkScheduleTblPtr(channelIdx, LinSchedule_Ctrl.chxState[channelIdx].currentScheduleTblIdx);
}
}
}
#endif

View File

@ -1,347 +0,0 @@
/*
* 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 _LIN_SCHEDULE_H_
#define _LIN_SCHEDULE_H_
/*! \brief his file exports Lin schedule table information
*
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "lin_type.h"
#include "lin_cfg.h"
/*! \addtogroup lin_schedule
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
#define LINSCH_SCHEDULE_TABLE_NULL (0x00u)
#define LINSCH_FRAMEID_IDX_INVALID (0xFF)
/*******************************************************************************
* the typedefs
******************************************************************************/
/* define the application communication frame schedule table type */
typedef enum
{
LINSCH_TBL_TYPE_NULL = LINSCH_SCHEDULE_TABLE_NULL, /* Run nothing */
LINSCH_TBL_TYPE_NORM, /* Normal schedule table */
LINSCH_TBL_TYPE_DIAG, /* Diagnostic schedule table */
LINSCH_TBL_TYPE_GO_TO_SLEEP, /* Goto sleep schedule table */
LINSCH_TBL_TYPE_COLL_RESOLV, /* Collision resolving schedule table */
LINSCH_TBL_TYPE_SPORADIC, /* Sporadic schedule table */
LINSCH_TBL_TYPE_NUM
} LinSchedule_TableType;
typedef struct
{
uint8_t pidIdx;
Lin_FrametypeType frameType;
Lin_FrameCtrlType frameCtrl;
} LinSchedule_FrameAttributeType;
typedef struct
{
uint8_t pidIdx;
Lin_FrametypeType frameType;
uint16_t frameSlotTick;
uint8_t linkTblIdx;
} LinSchedule_ScheduleTblInfoType;
typedef struct
{
uint8_t tblIdx;
LinSchedule_TableType tblType;
const LinSchedule_ScheduleTblInfoType *pScheduleTblInfo;
uint8_t frameNum;
} LinSchedule_ScheduleTblListType;
typedef struct
{
const LinSchedule_ScheduleTblListType *pCurrentScheduleTblPtr;
uint8_t defaultScheduleTblIdx;
uint8_t currentScheduleTblIdx;
uint8_t prevScheduleTblIdx;
uint8_t targetScheduleTblIdx;
bool scheduleTblSwitchReqEn;
uint8_t prevFrameIdxInScheduleTbl;
uint8_t currentFrameIdxInScheduleTbl;
uint8_t txFrameCnt;
uint16_t frameSlotTick;
uint16_t currentFrameSlotTickCnt;
} LinSchedule_StateType;
typedef struct
{
const LinSchedule_FrameAttributeType *pChxFrameAttribute;
uint8_t chxFrameAttributeNum;
const LinSchedule_ScheduleTblListType *pChxScheduleTblList;
uint8_t chxScheduleTblNum;
} LinSchedule_ChxTableInfoType;
typedef struct
{
const Lin_FrameGeneralityType *pFrameGenerality;
uint8_t frameGeneralityNum;
const LinSchedule_ChxTableInfoType chxTableInfo[LINCFG_CH_NUM];
} LinSchedule_TblInfoType;
typedef struct
{
const LinSchedule_TblInfoType *pLinSchedule_TblInfo;
LinSchedule_StateType chxState[LINCFG_CH_NUM];
} LinSchedule_CtrlType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the schedule table information
*
* This function execute to initialize the schedule table information
*
* \param[in] pTblInfo: table information pointer
* \return: void
*/
extern void LinSchedule_TblInit(const LinSchedule_TblInfoType *pTblInfo);
/*! \brief Initialize the schedule table information
*
* This function execute to initialize the schedule table information
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
extern void LinSchedule_Init(uint8_t channelIdx);
/*! \brief Get the support frame number in the LIN BUS
*
* This function execute to get the frame number
*
* \param[in] uint8_t channelIdx: which physical channel is used
* \return: the frame number
*/
extern uint8_t LinSchedule_GetFrameNum(uint8_t channelIdx);
/*! \brief Get the pid by the pid index
*
* This function execute to get the pid in the support pid list
*
* \param[in] pidIdx: pid index
* \return: pid
*/
extern uint8_t LinSchedule_GetPid(uint8_t pidIdx);
/*! \brief Get the pid index by pid
*
* This function execute to get the pid by the pid index in the support pid list
*
* \param[in] pid: pid
* \return: pid index
*/
extern uint8_t LinSchedule_GetPidIdx(uint8_t pid);
/*! \brief Get the pid index in the target schedule table
*
* This function execute to get the pid index in the target schedule table by frame index
*
* \param[in] channelIdx: which physical channel is used
* \param[in] linkTblIdx: link schedule table index
* \param[in] frameIdx: the frame index in schedule table
* \return: pid index
*/
extern uint8_t LinSchedule_GetPidIdxInSchedulerTbl(uint8_t channelIdx, uint8_t linkTblIdx, uint8_t frameIdx);
/*! \brief Get the frame type
*
* This function execute to get the frame type by the pid index
*
* \param[in] channelIdx: : which physical channel is used
* \param[in] pidIdx: pid index
* \return: the frame type
*/
extern Lin_FrametypeType LinSchedule_GetFrameType(uint8_t channelIdx, uint8_t pidIdx);
/*! \brief Get the frame control
*
* This function execute to get the frame control
*
* \param[in] channelIdx: : which physical channel is used
* \param[in] pidIdx: pid index
* \return: frame control type
*/
extern Lin_FrameCtrlType LinSchedule_GetFrameCtrl(uint8_t channelIdx, uint8_t pidIdx);
/*! \brief Get the frame data length by pid index
*
* This function execute to get the frame data length by pid index
*
* \param[in] pidIdx: pid index
* \return: the length of the frame data
*/
extern uint8_t LinSchedule_GetFrameDataLen(uint8_t pidIdx);
/*! \brief Get the checksum type
*
* This function execute to get the checksum type
*
* \param[in] pid: pid
* \return: the type of check sum
*/
extern Lin_CheckSumType LinSchedule_GetCheckSumType(uint8_t pid);
/*! \brief Get the frame buffer pointer
*
* This function execute to get the frame buffer pointer, each frame has their own buffer
*
* \param[in] pidIdx: pid index
* \return: the pointer of frame buffer
*/
extern Lin_FrameDataType *LinSchedule_GetFrameBufferPtr(uint8_t pidIdx);
/*! \brief Get the frame access state
*
* This function execute
*
* \param[in] uint8_t pidIdx:
* \return: Lin_FrameAccessStateType
*/
extern Lin_FrameAccessStateType LinSchedule_GetFrameAccessState(uint8_t pidIdx);
/*! \brief Sect the frame access state
*
* This function execute to set the frame access state, allow or not allow to readout from the frame buffer or write data into frame buffer
*
* \param[in] pidIdx: pid index
* \param[in] accessState: access state
* \return: void
*/
extern void LinSchedule_SetFrameAccessState(uint8_t pidIdx, Lin_FrameAccessStateType accessState);
#if LINCFG_NODE_USED == LINCFG_NODE_MASTER
/*! \brief Get the schedule table index by table type
*
* This function execute to get the type of current operated schedule table
*
* \param[in] tableType: : the type of schedule table
* \return: return the first match table index in the schedule table list
*/
extern uint8_t LinSchedule_GetScheduleTblIdxByTableType(LinSchedule_TableType tableType);
/*! \brief Set the default schedule table index
*
* This function execute to set the default schedule table index
*
* \param[in] channelIdx: which physical channel is used
* \param[in]: the default schedule table index
*/
extern void LinSchedule_SetDefaultScheduleTblIdx(uint8_t channelIdx, uint8_t defaultScheduleTblIdx);
/*! \brief Get the default schedule table index
*
* This function execute to get the default schedule table index
*
* \param[in] channelIdx: which physical channel is used
* \return: the default schedule table index
*/
extern uint8_t LinSchedule_GetDefaultScheduleTblIdx(uint8_t channelIdx);
/*! \brief Request to switch schedule table
*
* This function execute to request to switch to target schedule table
*
* \param[in] channelIdx: which physical channel is used
* \param[in] targetScheduleTblIdx: target schedule index
* \return: true: switch to target schedule table successfully
* false: switch to target schedule table failed
*/
extern bool LinSchedule_ReqSwitchScheduleTbl(uint8_t channelIdx, uint8_t targetScheduleTblIdx);
/*! \brief The main function of schedule table process
*
* This function execute to process the schedule table
*
* \param[in] channelIdx: which physical channel is used
* \return: void
*/
extern void LinSchedule_MainFunction(uint8_t channelIdx);
#endif
/*! \brief Get the link schedule table index
*
* This function execute to get the link schedule table index by the pid index in current schedule table
*
* \param[in] channelIdx: which physical channel is used
* \param[in] tblIdx: the current schedule table index
* \param[in] pidIdx: the pid index
* \return: the link schedule table index
*/
extern uint8_t LinSchedule_GetLinkTblIdx(uint8_t channelIdx, uint8_t tblIdx, uint8_t pidIdx);
/*! \brief Get the frame number in the current schedule table
*
* This function execute to get the frame number in the current schedule table
*
* \param[in] channelIdx: which physical channel is used
* \param[in] linkTblIdx: which schedule table is to be check
* \return: the frame number in the current schedule table
*/
extern uint8_t LinSchedule_GetFrameNumInScheduleTbl(uint8_t channelIdx, uint8_t linkTblIdx);
/*! \brief Get the link schedule table pointer
*
* This function execute to get the link schedule table pointer
*
* \param[in] channelIdx: which physical channel is used
* \param[in] linkTblIdx: the link schedule table index
* \return: the link schedule table pointer
*/
extern LinSchedule_ScheduleTblListType *LinSchedule_GetLinkScheduleTblPtr(uint8_t channelIdx, uint8_t linkTblIdx);
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _LIN_SCHEDULE_H_ */

View File

@ -1,203 +0,0 @@
/*
* 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 _LIN_TYPE_H_
#define _LIN_TYPE_H_
/*! \brief his file exports Lin interface Type defnitions
*
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
/*! \addtogroup lin_type
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
#define LIN_DATA_INVALID 0xFF
/* Master Request Frame */
#define LIN_STACK_PID_MRF 0x3C
/* Slave Response Frame */
#define LIN_STACK_PID_SRF 0x7D
/* DATA[8] + Checksum */
#define LIN_FRAME_RESP_DATA_BYTES_MAX 8u
#define LIN_FRAME_RESP_BYTES_MAX (LIN_FRAME_RESP_DATA_BYTES_MAX + 1u)
/*******************************************************************************
* the typedefs
******************************************************************************/
typedef enum
{
LIN_NODE_IS_MASTER = 0u,
LIN_NODE_IS_SLAVE,
LIN_NODE_IS_NUM
} Lin_NodeType;
typedef enum
{
LIN_FRAME_TYPE_UNCONDITIONAL = 0u,
LIN_FRAME_TYPE_EVENT_TRIGGER,
LIN_FRAME_TYPE_SPORADIC,
LIN_FRAME_TYPE_DIAG,
LIN_FRAME_TYPE_USER_DEFINED,
LIN_FRAME_TYPE_RESERVED,
LIN_FRAME_TYPE_NUM
} Lin_FrametypeType;
typedef enum
{
LIN_FRAME_CTRL_IDLE = 0u,
LIN_FRAME_CTRL_NO_ACTION,
LIN_FRAME_CTRL_PUBLISH,
LIN_FRAME_CTRL_SUBSCRIBER,
LIN_FRAME_CTRL_NUM
} Lin_FrameCtrlType;
typedef enum
{
LIN_CHECKSUM_CLASSIC = 0u,
LIN_CHECKSUM_ENHANCED,
LIN_CHECKSUM_NUM
} Lin_CheckSumType;
typedef enum
{
LIN_STATUS_IDLE = 0u,
LIN_STATUS_READY,
LIN_STATUS_HEADER_BUSY,
LIN_STATUS_RX_DATA_BUSY,
LIN_STATUS_TX_DATA_BUSY,
LIN_STATUS_TX_OK,
LIN_STATUS_RX_OK,
/* The next are all error information */
LIN_STATUS_ERR_BIT,
LIN_STATUS_ERR_BREAK,
LIN_STATUS_ERR_SYNC,
LIN_STATUS_ERR_PID,
LIN_STATUS_ERR_DATA,
LIN_STATUS_ERR_CHKSUM,
LIN_STATUS_ERR_FRAME,
LIN_STATUS_ERR_PHY_BUS,
LIN_STATUS_ERR_TX_CHECK_ERR,
LIN_STATUS_ERR_RX_ERR,
LIN_STATUS_ERR_TIMEOUT,
} Lin_OpStatusType;
typedef struct
{
union
{
uint8_t byteData[LIN_FRAME_RESP_DATA_BYTES_MAX];
struct
{
uint8_t data[LIN_FRAME_RESP_DATA_BYTES_MAX];
} unContionalBytes;
struct
{
uint8_t data[LIN_FRAME_RESP_DATA_BYTES_MAX];
} sporadicBytes;
struct
{
uint8_t pid;
uint8_t data[LIN_FRAME_RESP_DATA_BYTES_MAX - 1u];
} eventBytes;
struct
{
uint8_t nad;
uint8_t data[LIN_FRAME_RESP_DATA_BYTES_MAX - 1u];
} diagBytes;
} poyload;
} Lin_FrameDataType;
typedef enum
{
LIN_FRAME_ACCESS_STATE_IDLE = 0u,
LIN_FRAME_ACCESS_STATE_READING_OUT,
LIN_FRAME_ACCESS_STATE_WRITING_IN,
LIN_FRAME_ACCESS_STATE_UPDATED,
LIN_FRAME_ACCESS_STATE_OVER_RECEIVED,
} Lin_FrameAccessStateType;
typedef struct
{
Lin_FrametypeType frameType;
Lin_FrameCtrlType frameCtrl;
Lin_CheckSumType checkSumType;
uint8_t dataLen;
uint8_t pid;
uint8_t pidIdx;
Lin_FrameDataType frameData;
uint8_t checkSum;
uint32_t cycleCnt;
} Lin_PduType;
typedef struct
{
Lin_FrametypeType frameType;
Lin_FrameCtrlType frameCtrl;
uint8_t dataLen;
uint8_t pid;
const Lin_FrameDataType *pFrameData;
} Lin_FrameInfoType;
typedef struct
{
uint8_t pid;
uint8_t frameLen;
Lin_FrameDataType *pFrameDataPtr;
Lin_FrameAccessStateType *pFrameAccessStatePtr;
} Lin_FrameGeneralityType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _LIN_TYPE_H_ */

View File

@ -1,893 +0,0 @@
/*
* 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

@ -1,136 +0,0 @@
/*
* 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

@ -1,223 +0,0 @@
/*
* 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

@ -1,147 +0,0 @@
/*
* 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

@ -1,271 +0,0 @@
/*
* 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

@ -1,74 +0,0 @@
/*
* 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

@ -1,205 +0,0 @@
/*
* 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

@ -1,884 +0,0 @@
/*
* 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

@ -1,113 +0,0 @@
/*
* 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

@ -1,204 +0,0 @@
/*
* 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

@ -1,86 +0,0 @@
/*
* 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

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

@ -1,189 +0,0 @@
/*
* 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

@ -1,404 +0,0 @@
/*
* 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

@ -1,181 +0,0 @@
/*
* 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

@ -1,149 +0,0 @@
/*
* Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
* All rights reserved.
*
* Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
* exclusively with CVA's microcontroller products. This file can be freely
* distributed within development tools that are supporting such microcontroller
* products.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
* OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*/
#ifndef _NVM_EXTRA_H_
#define _NVM_EXTRA_H_
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
/*! \addtogroup NVRAM Manager
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*! \brief Define N-byte aligned macros.
*/
#ifndef ALIGNBYTE
#define ALIGNBYTE(size, n) ((size + n - 1) & ~(n - 1))
#endif
/*! \brief Define 4-byte aligned macros.
*/
#ifndef ALIGN4BYTE
#define ALIGN4BYTE(size) (ALIGNBYTE(size, 4))
#endif
/*! \brief Define 8-byte aligned macros.
*/
#ifndef ALIGN8BYTE
#define ALIGN8BYTE(size) (ALIGNBYTE(size, 8))
#endif
/*! \brief Define 64-byte aligned macros.
*/
#ifndef ALIGN64BYTE
#define ALIGN64BYTE(size) (ALIGNBYTE(size, 64))
#endif
/*! \brief Define address aligned macros.
*/
#ifndef ALIGNED
#define ALIGNED(val, alncnt) (((uint32_t)val) & ~(alncnt - 1))
#endif
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Define the type of the Notification return value.
*/
typedef enum
{
NVM_JOBFINISHNOTIFICATION = 0x00,
NVM_JOBERRORNOTIFICATION = 0x01,
} NVM_NotificationType;
/*! \brief Define the type of return value for lower level module operations.
*/
typedef enum
{
NVM_JOB_RESULT_OK = 0x00,
NVM_JOB_RESULT_NOT_OK = 0x01,
NVM_JOB_RESULT_PENDING = 0x02,
NVM_JOB_RESULT_BL_INCONSISTENT = 0x03,
NVM_JOB_RESULT_BL_INVALID = 0x04,
} NVM_JobResultType;
/*! \brief Define the type of return value for lower level module status.
*/
typedef enum
{
NVM_STATUS_IDLE = 0x00,
NVM_STATUS_READ = 0x01,
NVM_STATUS_WRITE = 0x02,
NVM_STATUS_GC = 0x03,
NVM_STATUS_UNKNOW = 0x04,
NVM_STATUS_ERROR = 0x05,
} Nvm_StatusType;
/*! \brief Define the type of virtual function for Notification.
*/
typedef void (*NvmNotificationPtrType)(NVM_NotificationType notificationNumber);
/*! \brief Define the type of virtual function for writing lower level module operations.
*/
typedef bool (*Nvm_writeMethodType)(uint16_t blockNumber, uint8_t *dataBuffer, NvmNotificationPtrType notificationPtr);
/*! \brief Define virtual function types for read lower level module operations.
*/
typedef bool (*Nvm_readMethodType)(uint16_t blockNumber, uint16_t blockOffset, uint8_t *dataBuffer, NvmNotificationPtrType notificationPtr);
/*! \brief Define virtual function types for calculating crc8.
*/
typedef uint8_t (*Nvm_calcCrc8Type)(void *sAddr, uint32_t size);
/*! \brief Define virtual function types for lower level module job handle result.
*/
typedef NVM_JobResultType (*Nvm_getJobResultType)(void);
/*! \brief Define virtual function types for lower level module module status.
*/
typedef Nvm_StatusType (*Nvm_GetStatusType)(void);
/*! \brief Define the type of the nvm operation lower level module method.
*/
typedef struct _Nvm_MethodType_
{
Nvm_writeMethodType write;
Nvm_readMethodType read;
Nvm_calcCrc8Type crc8;
Nvm_getJobResultType getJobResult;
Nvm_GetStatusType getStatus;
} Nvm_MethodType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
#ifdef __cplusplus
}
#endif /* extern "C" */
/*! @}*/
#endif /* _NVM_EXTRA_H_ */

View File

@ -1,196 +0,0 @@
/*
* 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

@ -1,89 +0,0 @@
/*
* 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

@ -1,908 +0,0 @@
/*
* 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

@ -1,78 +0,0 @@
/*
* 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

@ -1,419 +0,0 @@
/*
* 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

@ -1,84 +0,0 @@
/*
* 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

@ -1,147 +0,0 @@
/*
* 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

@ -1,132 +0,0 @@
/*
* 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

@ -1,250 +0,0 @@
/*
* 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 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;
} Uds_DidType;
/*! \brief The definition of UDS DID table
*/
typedef Uds_DidType *Uds_DidTable;
/*! \brief Forward declaration of UDS object
*/
struct _UdsType_;
typedef struct _UdsType_ UdsType;
/*! \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

@ -1,90 +0,0 @@
/*
* Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
* All rights reserved.
*
* Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
* exclusively with CVA's microcontroller products. This file can be freely
* distributed within development tools that are supporting such microcontroller
* products.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
* OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include "uds_service10.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the constants
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void UdsService10_SessionControl(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen)
{
uint8_t subFunction;
uint8_t rspBuffer[8] = {0}; /* polyspace DEFECT:PARTIALLY_ACCESSED_ARRAY [No action planned:Low] "Still keep default though member6~7 is not written" */
if(msgLen != obj->seviceTable[obj->curServiceIdx].minLen)
{
Uds_NegativeResponse(obj, 0x10, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
subFunction = UDS_GET_SUB_FUNCTION (msgBuf[1]);
rspBuffer[0] = UDS_GET_POSITIVE_RSP(0x10);
rspBuffer[1] = subFunction;
rspBuffer[2] = (uint8_t)(obj->p2Server_ms >> 8);
rspBuffer[3] = (uint8_t)(obj->p2Server_ms & 0x00ff);
rspBuffer[4] = (uint8_t)(obj->p2xServer_10ms >> 8);
rspBuffer[5] = (uint8_t)(obj->p2xServer_10ms & 0x00ff);
switch(subFunction)
{
case UDS_SESSION_DEFAULT:
obj->securityLevel = UDS_SA_NONE;
obj->session = subFunction;
Uds_PositiveResponse(obj, rspBuffer, 6);
break;
case UDS_SESSION_EXTENDED:
obj->securityLevel = UDS_SA_NONE;
obj->session = subFunction;
Uds_PositiveResponse(obj, rspBuffer, 6);
break;
case UDS_SESSION_PROGRAMMING:
obj->securityLevel = UDS_SA_NONE;
obj->session = subFunction;
Uds_PositiveResponse(obj, rspBuffer, 6);
break;
case UDS_SESSION_SAFTY:
obj->securityLevel = UDS_SA_NONE;
obj->session = subFunction;
Uds_PositiveResponse(obj, rspBuffer, 6);
break;
default:
Uds_NegativeResponse(obj, 0x10, NRC_SUBFUNCTION_NOT_SUPPORTED);
break;
}
}

View File

@ -1,60 +0,0 @@
/*
* Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
* All rights reserved.
*
* Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
* exclusively with CVA's microcontroller products. This file can be freely
* distributed within development tools that are supporting such microcontroller
* products.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
* OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*/
#ifndef _UDS_SERVICE10_H_
#define _UDS_SERVICE10_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS service 10
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "../stack/uds.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Uds Service 10 processing
*/
extern void UdsService10_SessionControl(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_SERVICE10_H_ */

View File

@ -1,91 +0,0 @@
/*
* Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
* All rights reserved.
*
* Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
* exclusively with CVA's microcontroller products. This file can be freely
* distributed within development tools that are supporting such microcontroller
* products.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
* OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include "uds_service11.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief The Reset type definition of Uds
*/
typedef enum _UdsResetType_
{
UDS_RESET_NONE = 0,
UDS_RESET_HARD,
UDS_RESET_KEYOFFON,
UDS_RESET_SOFT
} UdsResetType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the constants
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void UdsService11_ResetEcu(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen)
{
uint8_t subFunction;
uint8_t rspBuffer[8] = {0}; /* polyspace DEFECT:PARTIALLY_ACCESSED_ARRAY [No action planned:Low] "Still keep default though member3~7 is not written" */
uint8_t powerDownTime = 0xFF;
if(msgLen != obj->seviceTable[obj->curServiceIdx].minLen)
{
Uds_NegativeResponse(obj, 0x11, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
subFunction = UDS_GET_SUB_FUNCTION(msgBuf[1]);
rspBuffer[0] = UDS_GET_POSITIVE_RSP(0x11);
rspBuffer[1] = subFunction;
rspBuffer[2] = powerDownTime;
switch(subFunction)
{
case UDS_RESET_HARD:
Uds_PositiveResponse(obj, rspBuffer, 3);
/*add hardware reset code*/
break;
case UDS_RESET_KEYOFFON:
Uds_PositiveResponse(obj, rspBuffer, 3);
/*add keyoffon reset code*/
break;
case UDS_RESET_SOFT:
Uds_PositiveResponse(obj, rspBuffer, 3);
/*add software reset code*/
break;
default:
Uds_NegativeResponse(obj, 0x11, NRC_SUBFUNCTION_NOT_SUPPORTED);
break;
}
}

View File

@ -1,59 +0,0 @@
/*
* Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
* All rights reserved.
*
* Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
* exclusively with CVA's microcontroller products. This file can be freely
* distributed within development tools that are supporting such microcontroller
* products.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
* OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*/
#ifndef _UDS_SERVICE11_H_
#define _UDS_SERVICE11_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS service 11
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "../stack/uds.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Uds Service 11 processing
*/
extern void UdsService11_ResetEcu(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_SERVICE11_H_ */

View File

@ -1,213 +0,0 @@
/*
* Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
* All rights reserved.
*
* Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
* exclusively with CVA's microcontroller products. This file can be freely
* distributed within development tools that are supporting such microcontroller
* products.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
* OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <string.h>
#include "uds_service27.h"
/*******************************************************************************
* the defines
******************************************************************************/
#define SUPPORT_LEVEL_NUM 4 /* supported security level number */
#define MAX_ALLOW_ERROR_NUM 5 /* the max allow number of key error */
#define STARTUP_DELAY_MS 2000 /* the service allow access time delay after UDS start */
#define ERR_EXCEED_DELAY_MS 10000 /* the service allow access time delay after error number exceed */
/*******************************************************************************
* the typedefs
******************************************************************************/
typedef struct _SecurityLevel_Param_
{
uint8_t level;
uint8_t keyErrorCnt;
uint8_t maxErrNum;
int64_t MaxErrTimeStamp;
} SecurityLevel_Param;
/*******************************************************************************
* the globals
******************************************************************************/
SecurityLevel_Param scrtParam[SUPPORT_LEVEL_NUM] = {
{UDS_SA_LEVEL_1, 0, MAX_ALLOW_ERROR_NUM, 0},
{UDS_SA_LEVEL_3, 0, MAX_ALLOW_ERROR_NUM, 0},
{UDS_SA_LEVEL_11, 0, MAX_ALLOW_ERROR_NUM, 0},
{UDS_SA_LEVEL_63, 0, MAX_ALLOW_ERROR_NUM, 0},
};
/*******************************************************************************
* the constants
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
static void UdsSecurityAccess_GenerateSeed(UdsType *obj, uint8_t newLevel, uint8_t *outData, uint8_t outBufsize, uint16_t *outLen)
{
/* seed is defined by user, It's usually a random value */
uint8_t seed[4] = {1, 2, 3, 4};
if(outBufsize < sizeof(seed))
{
return;
}
*outLen = sizeof(seed);
if(newLevel == obj->securityLevel)
{
memset(outData, 0, sizeof(seed));
}
else
{
memcpy(outData, seed, sizeof(seed));
}
}
static bool UdsSecurityAccess_ValidateKey(uint8_t seedLevel, const uint8_t *seed, uint16_t seedLen, const uint8_t *key, uint16_t keyLen)
{
/* The encryption algorithm is provided by the vehicle manufacturer */
return true;
}
void UdsService27_SecurityAccess(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen)
{
static uint8_t seedLevel = 0;
static uint8_t seedValue[8] = {0};
static uint16_t seedLen = 0;
uint8_t subFunction;
uint8_t udx = 0;
uint8_t rspBuffer[8] = {0};
uint16_t dataLen = 0, remainSize = 0;
bool ret = false;
if(msgLen < obj->seviceTable[obj->curServiceIdx].minLen)
{
Uds_NegativeResponse(obj, 0x27, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
if(obj->session == UDS_SESSION_DEFAULT)
{
Uds_NegativeResponse(obj, 0x27, NRC_CONDITIONS_NOT_CORRECT);
return;
}
if(obj->timeStamp_ms < STARTUP_DELAY_MS)
{
Uds_NegativeResponse(obj, 0x27, NRC_REQUIRED_TIME_DELAY_NOT_EXPIRED);
return;
}
subFunction = UDS_GET_SUB_FUNCTION(msgBuf[1]);
rspBuffer[0] = UDS_GET_POSITIVE_RSP(0x27);
rspBuffer[1] = subFunction;
if(subFunction % 2)
{
seedLevel = 0;
for(udx = 0; udx < SUPPORT_LEVEL_NUM; udx++)
{
if(subFunction == scrtParam[udx].level)
{
if(scrtParam[udx].keyErrorCnt > scrtParam[udx].maxErrNum)
{
if(obj->timeStamp_ms - scrtParam[udx].MaxErrTimeStamp < ERR_EXCEED_DELAY_MS)
{
Uds_NegativeResponse(obj, 0x27, NRC_EXCEEDED_NUMBER_OF_ATTEMPTS);
return;
}
else
{
scrtParam[udx].keyErrorCnt = 0;
}
}
break;
}
}
if(udx >= SUPPORT_LEVEL_NUM)
{
Uds_NegativeResponse(obj, 0x27, NRC_REQUEST_OUT_OF_RANGE);
return;
}
remainSize = sizeof(rspBuffer) - 2;
UdsSecurityAccess_GenerateSeed(obj, subFunction, &rspBuffer[2], remainSize, &dataLen);
if(dataLen > 0)
{
Uds_PositiveResponse(obj, rspBuffer, dataLen + 2);
seedLevel = subFunction;
seedLen = dataLen;
memcpy(seedValue, &rspBuffer[2], dataLen);
}
else
{
Uds_NegativeResponse(obj, 0x27, NRC_REQUEST_OUT_OF_RANGE);
}
}
else
{
if(subFunction != seedLevel + 1)
{
Uds_NegativeResponse(obj, 0x27, NRC_REQUEST_SEQUENCE_ERROR);
return;
}
/* polyspace-begin DEFECT:DEAD_CODE [No action planned:Low] "Still reserve though it's maybe unreachable" */
ret = UdsSecurityAccess_ValidateKey(seedLevel, seedValue, seedLen, &msgBuf[2], msgLen - 2);
if(ret == true)
{
Uds_PositiveResponse(obj, rspBuffer, 2);
seedLevel = 0;
obj->securityLevel = subFunction - 1;
for(udx = 0; udx < SUPPORT_LEVEL_NUM; udx++)
{
if(subFunction == scrtParam[udx].level)
{
scrtParam[udx].keyErrorCnt = 0;
}
}
}
else
{
Uds_NegativeResponse(obj, 0x27, NRC_INVALID_KEY);
for(udx = 0; udx < SUPPORT_LEVEL_NUM; udx++)
{
if(seedLevel == scrtParam[udx].level)
{
scrtParam[udx].keyErrorCnt++;
if(scrtParam[udx].keyErrorCnt > scrtParam[udx].maxErrNum)
{
scrtParam[udx].MaxErrTimeStamp = obj->timeStamp_ms;
}
}
}
}
/* polyspace-end DEFECT:DEAD_CODE [No action planned:Low] "Still reserve though it's maybe unreachable" */
}
}

View File

@ -1,60 +0,0 @@
/*
* Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
* All rights reserved.
*
* Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
* exclusively with CVA's microcontroller products. This file can be freely
* distributed within development tools that are supporting such microcontroller
* products.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
* OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*/
#ifndef _UDS_SERVICE27_H_
#define _UDS_SERVICE27_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS service 27
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "../stack/uds.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Uds Service 27 processing
*/
extern void UdsService27_SecurityAccess(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_SERVICE27_H_ */

View File

@ -1,278 +0,0 @@
/*
* Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
* All rights reserved.
*
* Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
* exclusively with CVA's microcontroller products. This file can be freely
* distributed within development tools that are supporting such microcontroller
* products.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
* OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include "uds_service31.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief The Uds routine control type
*/
typedef enum _UdsRoutineCtrlType_
{
UDS_ROUTINE_CTRL_NONE = 0,
UDS_ROUTINE_CTRL_START = 0x01,
UDS_ROUTINE_CTRL_STOP = 0x02,
UDS_ROUTINE_CTRL_REQUEST_RESULT = 0x03
} UdsRoutineCtrlType;
/*! \brief The Uds routine control status
*/
typedef enum _UdsRtnCtrlStatus_
{
UDS_RTN_ST_IDLE = 0x00,
UDS_RTN_ST_RUNNING = 0x01,
} UdsRtnCtrlStatus;
/*! \brief The Uds routine control struct
*/
typedef struct _Uds_RtnCtrl_
{
uint16_t rtnCtrlId;
uint8_t sessionLevel;
uint8_t securityLevel;
UdsRtnCtrlStatus rtnStatus;
void (*Routine_Start)(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
void (*Routine_Stop)(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
void (*Routine_Result)(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
} Uds_RtnCtrl;
/*******************************************************************************
* the constants
******************************************************************************/
static void Routine_StartEreaseMemory(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
static void Routine_StopEreaseMemory(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
static void Routine_EreaseMemoryResult(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
static void Routine_StartCheckProgramDependencies(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
static void Routine_StopCheckProgramDependencies(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
static void Routine_CheckProgramDependenciesResult(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
static void Routine_StartEreaseMirrorMemDtcs(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
static void Routine_StopEreaseMirrorMemDtcs(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
static void Routine_EreaseMirrorMemDtcsResult(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen);
/*******************************************************************************
* the globals
******************************************************************************/
Uds_RtnCtrl udsRtnCtrlTable[] = {
{0xFF00, UDS_SESSION_EXTENDED, UDS_SA_LEVEL_1, UDS_RTN_ST_IDLE, &Routine_StartEreaseMemory, &Routine_StopEreaseMemory, &Routine_EreaseMemoryResult },
{0xFF01, UDS_SESSION_EXTENDED, UDS_SA_LEVEL_1, UDS_RTN_ST_IDLE, &Routine_StartCheckProgramDependencies, &Routine_StopCheckProgramDependencies, &Routine_CheckProgramDependenciesResult},
{0xFF02, UDS_SESSION_EXTENDED, UDS_SA_LEVEL_1, UDS_RTN_ST_IDLE, &Routine_StartEreaseMirrorMemDtcs, &Routine_StopEreaseMirrorMemDtcs, &Routine_EreaseMirrorMemDtcsResult },
};
/*******************************************************************************
* the functions
******************************************************************************/
void Routine_StatusInit(uint16_t routineId)
{
uint8_t rtnIndex = 0;
uint8_t rntNum = sizeof(udsRtnCtrlTable) / sizeof(Uds_RtnCtrl);
for(rtnIndex = 0; rtnIndex < rntNum; rtnIndex++)
{
if(udsRtnCtrlTable[rtnIndex].rtnCtrlId == routineId)
{
udsRtnCtrlTable[rtnIndex].rtnStatus = UDS_RTN_ST_IDLE;
}
}
}
static void Routine_StartEreaseMemory(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen)
{
if(pdata == NULL)
{
return;
}
/* user add start erease memory code */
}
static void Routine_StopEreaseMemory(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen)
{
if(pdata == NULL)
{
return;
}
/* user add stop erease memory code */
}
static void Routine_EreaseMemoryResult(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen)
{
if(pdata == NULL)
{
return;
}
/* user add erease memory result code */
}
static void Routine_StartCheckProgramDependencies(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen)
{
if(pdata == NULL)
{
return;
}
/* user add start check program dependencies code */
}
static void Routine_StopCheckProgramDependencies(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen)
{
if(pdata == NULL)
{
return;
}
/* user add stop check program dependencies code */
}
static void Routine_CheckProgramDependenciesResult(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen)
{
if(pdata == NULL)
{
return;
}
/* user add check program dependencies result code */
}
static void Routine_StartEreaseMirrorMemDtcs(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen)
{
if(pdata == NULL)
{
return;
}
/* user add start erease mirror memory Dtcs code */
}
static void Routine_StopEreaseMirrorMemDtcs(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen)
{
if(pdata == NULL)
{
return;
}
/* user add stop erease mirror memory Dtcs code */
}
static void Routine_EreaseMirrorMemDtcsResult(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen)
{
if(pdata == NULL)
{
return;
}
/* user add erease mirror memory Dtcs resultl code */
}
void UdsService31_RoutineControl(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen)
{
const uint8_t *pOptionParam = NULL;
uint8_t subFunction = 0;
uint16_t optionParamLen = 0;
uint16_t routineId = 0;
uint8_t rtnIndex = 0;
uint8_t rntNum = sizeof(udsRtnCtrlTable) / sizeof(Uds_RtnCtrl);
uint8_t rspBuffer[UDS_RSP_LEN_MAX] = {0};
uint16_t rspLen = 0;
if(msgLen < obj->seviceTable[obj->curServiceIdx].minLen)
{
Uds_NegativeResponse(obj, 0x31, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
subFunction = UDS_GET_SUB_FUNCTION(msgBuf[1]);
routineId = ((uint16_t)msgBuf[2] << 8) + msgBuf[3];
optionParamLen = msgLen - 4;
if(optionParamLen > 0)
{
pOptionParam = &msgBuf[4];
}
for(rtnIndex = 0; rtnIndex < rntNum; rtnIndex++)
{
if(udsRtnCtrlTable[rtnIndex].rtnCtrlId == routineId)
{
if(obj->session == udsRtnCtrlTable[rtnIndex].sessionLevel)
{
if((udsRtnCtrlTable[rtnIndex].securityLevel != UDS_SA_NONE) && (udsRtnCtrlTable[rtnIndex].securityLevel != obj->securityLevel))
{
Uds_NegativeResponse(obj, 0x31, NRC_SECURITY_ACCESS_DENIED);
return;
}
break;
}
else
{
Uds_NegativeResponse(obj, 0x31, NRC_CONDITIONS_NOT_CORRECT);
return;
}
}
}
if(rtnIndex >= rntNum)
{
Uds_NegativeResponse(obj, 0x31, NRC_REQUEST_OUT_OF_RANGE);
return;
}
memset(rspBuffer, 0, UDS_RSP_LEN_MAX);
switch(subFunction)
{
case UDS_ROUTINE_CTRL_START:
udsRtnCtrlTable[rtnIndex].Routine_Start(pOptionParam, optionParamLen, rspBuffer, UDS_RSP_LEN_MAX, &rspLen);
udsRtnCtrlTable[rtnIndex].rtnStatus = UDS_RTN_ST_RUNNING;
break;
case UDS_ROUTINE_CTRL_STOP:
if(udsRtnCtrlTable[rtnIndex].rtnStatus != UDS_RTN_ST_IDLE)
{
udsRtnCtrlTable[rtnIndex].Routine_Stop(pOptionParam, optionParamLen, rspBuffer, UDS_RSP_LEN_MAX, &rspLen);
udsRtnCtrlTable[rtnIndex].rtnStatus = UDS_RTN_ST_IDLE;
}
break;
case UDS_ROUTINE_CTRL_REQUEST_RESULT:
if(udsRtnCtrlTable[rtnIndex].rtnStatus != UDS_RTN_ST_IDLE)
{
udsRtnCtrlTable[rtnIndex].Routine_Result(pOptionParam, optionParamLen, rspBuffer, UDS_RSP_LEN_MAX, &rspLen);
}
break;
default:
Uds_NegativeResponse(obj, 0x31, NRC_SUBFUNCTION_NOT_SUPPORTED);
return;
}
/* polyspace-begin DEFECT:DEAD_CODE [No action planned:Low] "Still reserve though it's maybe unreachable" */
if((rspLen >= 4) && (rspBuffer[0] == UDS_GET_POSITIVE_RSP(0x31)))
{
Uds_PositiveResponse(obj, rspBuffer, rspLen);
}
else if((rspLen == 3) && (rspBuffer[0] == NEGATIVE_RSP))
{
Uds_NegativeResponse(obj, 0x31, rspBuffer[2]);
}
else
{
Uds_NegativeResponse(obj, 0x31, NRC_REQUEST_SEQUENCE_ERROR);
}
/* polyspace-end DEFECT:DEAD_CODE [No action planned:Low] "Still reserve though it's maybe unreachable" */
}

View File

@ -1,62 +0,0 @@
/*
* Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
* All rights reserved.
*
* Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
* exclusively with CVA's microcontroller products. This file can be freely
* distributed within development tools that are supporting such microcontroller
* products.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
* OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*/
#ifndef _UDS_SERVICE31_H_
#define _UDS_SERVICE31_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS service 31
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include "../stack/uds.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Uds Service 31 processing
*/
extern void UdsService31_RoutineControl(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen);
/*! \brief Routine status init
*/
extern void Routine_StatusInit(uint16_t routineId);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_SERVICE31_H_ */

View File

@ -1,146 +0,0 @@
/*
* Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
* All rights reserved.
*
* Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
* exclusively with CVA's microcontroller products. This file can be freely
* distributed within development tools that are supporting such microcontroller
* products.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
* OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include "uds_service34.h"
#include "uds_service36.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the constants
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
uint32_t Uds_GetMaxfBlockSize(void)
{
/* user add code to get max num of block length */
return 128;
}
uint8_t Uds_GetValidBytesNumOfData(uint32_t data)
{
uint8_t index = 0;
uint8_t bytesNum = 0;
for(index = 1; index <= 4; index++)
{
if(data >> ((4 - index) * 8))
{
bytesNum = 4 - index + 1;
break;
}
}
return bytesNum;
}
void UdsService34_RequestDownload(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen)
{
uint32_t memAddress = 0;
uint8_t memAddrLen = 0;
uint32_t memSize = 0;
uint8_t memSizeLen = 0;
uint8_t maxBlockSizeLen = 0;
uint32_t maxBlockSize = 0;
uint8_t index = 0;
uint16_t rspLen = 0;
uint8_t rspBuffer[8];
if(obj->session == UDS_SESSION_DEFAULT)
{
Uds_NegativeResponse(obj, 0x34, NRC_CONDITIONS_NOT_CORRECT);
return;
}
if(msgLen < obj->seviceTable[obj->curServiceIdx].minLen)
{
Uds_NegativeResponse(obj, 0x34, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
memAddrLen = msgBuf[2] & 0x0F;
memSizeLen = msgBuf[2] >> 4;
if((memAddrLen == 0) || (memAddrLen > sizeof(memAddress)) || (memSizeLen == 0) || (memSizeLen > sizeof(memSize)))
{
Uds_NegativeResponse(obj, 0x34, NRC_REQUEST_OUT_OF_RANGE);
return;
}
for(index = 0; index < memAddrLen; index++)
{
memAddress <<= 8;
memAddress += msgBuf[3 + index];
}
for(index = 0; index < memSizeLen; index++)
{
memSize <<= 8;
memSize += msgBuf[3 + memAddrLen + index];
}
if(memSize == 0)
{
Uds_NegativeResponse(obj, 0x34, NRC_CONDITIONS_NOT_CORRECT);
return;
}
/* user add judge code for the security level */
if(0)
{
Uds_NegativeResponse(obj, 0x34, NRC_SECURITY_ACCESS_DENIED);
return;
}
Uds_SetMemAddr(memAddress);
Uds_SetMemSize(memSize);
Uds_SetDataTransferDirect(UDS_TRANSFER_DIR_DOWNLOAD);
maxBlockSize = Uds_GetMaxfBlockSize();
maxBlockSizeLen = Uds_GetValidBytesNumOfData(maxBlockSize);
rspBuffer[rspLen++] = UDS_GET_POSITIVE_RSP(0x34);
rspBuffer[rspLen++] = maxBlockSizeLen << 4;
for(index = 1; index <= maxBlockSizeLen; index++)
{
rspBuffer[rspLen++] = maxBlockSize >> (8 * (maxBlockSizeLen - index));
}
Uds_PositiveResponse(obj, rspBuffer, rspLen);
}

View File

@ -1,61 +0,0 @@
/*
* Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
* All rights reserved.
*
* Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
* exclusively with CVA's microcontroller products. This file can be freely
* distributed within development tools that are supporting such microcontroller
* products.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
* OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*/
#ifndef _UDS_SERVICE34_H_
#define _UDS_SERVICE34_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS service 34
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "../stack/uds.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Uds Service 34 processing
*/
extern void UdsService34_RequestDownload(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_SERVICE34_H_ */

View File

@ -1,160 +0,0 @@
/*
* Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
* All rights reserved.
*
* Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
* exclusively with CVA's microcontroller products. This file can be freely
* distributed within development tools that are supporting such microcontroller
* products.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
* OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include "uds_service36.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
static uint32_t s_memAddr = 0;
static uint32_t s_memSize = 0;
static UdsTransDirType s_dataTransDir = UDS_TRANSFER_DIR_NONE;
static uint8_t s_curRcvSequence = 0;
static uint8_t s_lastRcvSqunce = 0;
static uint32_t s_rcvDataTotalLen = 0;
/*******************************************************************************
* the constants
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void Uds_SetMemAddr(uint32_t addr)
{
s_memAddr = addr;
}
uint32_t Uds_GetMemAddr(void)
{
return s_memAddr;
}
void Uds_SetMemSize(uint32_t size)
{
s_memSize = size;
}
uint32_t Uds_GetMemSize(void)
{
return s_memSize;
}
void Uds_SetDataTransferDirect(UdsTransDirType dirType)
{
s_dataTransDir = dirType;
/* clear sequence number */
s_lastRcvSqunce = 0x00;
s_curRcvSequence = 0x00;
/* clear receive data total number */
s_rcvDataTotalLen = 0x00;
}
UdsTransDirType Uds_GetDataTransferDirect(void)
{
return s_dataTransDir;
}
uint32_t Uds_GetRcvDataTotalLen(void)
{
return s_rcvDataTotalLen;
}
void UdsService36_TransferData(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen)
{
uint16_t rspLen = 0;
uint8_t rspBuffer[UDS_RSP_LEN_MAX] = {0}; /* polyspace DEFECT:PARTIALLY_ACCESSED_ARRAY [No action planned:Low] "Still reserve though member2~511 is not written" */
if(obj->session == UDS_SESSION_DEFAULT)
{
Uds_NegativeResponse(obj, 0x36, NRC_CONDITIONS_NOT_CORRECT);
return;
}
if(msgLen < obj->seviceTable[obj->curServiceIdx].minLen)
{
Uds_NegativeResponse(obj, 0x36, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT);
return;
}
switch(s_dataTransDir)
{
case UDS_TRANSFER_DIR_DOWNLOAD:
s_curRcvSequence = msgBuf[1];
if((s_curRcvSequence != s_lastRcvSqunce) && (s_curRcvSequence != ((uint8_t)(s_lastRcvSqunce + 1))))
{
Uds_NegativeResponse(obj, 0x36, NRC_WRONG_BLOCK_SEQUENCE_COUNTER);
return;
}
rspBuffer[rspLen++] = UDS_GET_POSITIVE_RSP(0x36);
rspBuffer[rspLen++] = msgBuf[1];
if(s_curRcvSequence == s_lastRcvSqunce)
{
Uds_PositiveResponse(obj, rspBuffer, rspLen);
return;
}
if((s_rcvDataTotalLen + msgLen - 2) > s_memSize)
{
Uds_NegativeResponse(obj, 0x36, NRC_TRANSFER_DATA_SUSPENDED);
return;
}
/* user add code to deal with download data */
/* polyspace-begin DEFECT:DEAD_CODE [No action planned:Low] "Still reserve though it's maybe unreachable" */
if(1) /* deal success */
{
s_rcvDataTotalLen += msgLen - 2;
s_lastRcvSqunce = s_curRcvSequence;
Uds_PositiveResponse(obj, rspBuffer, rspLen);
}
else
{
Uds_NegativeResponse(obj, 0x36, NRC_GENERAL_PROGRAMMING_FAILURE);
}
/* polyspace-end DEFECT:DEAD_CODE [No action planned:Low] "Still reserve though it's maybe unreachable" */
break;
case UDS_TRANSFER_DIR_UPLOAD:
Uds_NegativeResponse(obj, 0x36, NRC_REQUEST_OUT_OF_RANGE);
break;
default:
Uds_NegativeResponse(obj, 0x36, NRC_REQUEST_SEQUENCE_ERROR);
break;
}
}

View File

@ -1,97 +0,0 @@
/*
* Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
* All rights reserved.
*
* Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
* exclusively with CVA's microcontroller products. This file can be freely
* distributed within development tools that are supporting such microcontroller
* products.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
* OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*/
#ifndef _UDS_SERVICE36_H_
#define _UDS_SERVICE36_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS service 36
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "../stack/uds.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief The Uds IO control type
*/
typedef enum _UdsTransDirType_
{
UDS_TRANSFER_DIR_NONE = 0x00,
UDS_TRANSFER_DIR_DOWNLOAD = 0x01,
UDS_TRANSFER_DIR_UPLOAD = 0x02,
} UdsTransDirType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief set memery start address
*/
extern void Uds_SetMemAddr(uint32_t addr);
/*! \brief get memery start address
*/
extern uint32_t Uds_GetMemAddr(void);
/*! \brief set memery size
*/
extern void Uds_SetMemSize(uint32_t size);
/*! \brief get memery size
*/
extern uint32_t Uds_GetMemSize(void);
/*! \brief set data transfer direct
*/
extern void Uds_SetDataTransferDirect(UdsTransDirType dirType);
/*! \brief get data transfer direct
*/
extern UdsTransDirType Uds_GetDataTransferDirect(void);
/*! \brief get receive data total len
*/
extern uint32_t Uds_GetRcvDataTotalLen(void);
/*! \brief Uds Service 10 processing
*/
extern void UdsService36_TransferData(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_SERVICE36_H_ */

View File

@ -1,179 +0,0 @@
/*
* Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
* All rights reserved.
*
* Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
* exclusively with CVA's microcontroller products. This file can be freely
* distributed within development tools that are supporting such microcontroller
* products.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
* OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include "uds_user.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief The Data-by-ID definition of UDS
*/
typedef struct _Uds_DidBuffer_
{
uint8_t buffer_F113[4];
uint8_t buffer_F180[16];
uint8_t buffer_F186[1];
uint8_t buffer_F18A[6];
uint8_t buffer_F195[16];
uint8_t buffer_F1A0[8];
uint8_t buffer_F1A1[8];
uint8_t buffer_F1A2[8];
uint8_t buffer_F1A5[8];
uint8_t buffer_F1AE[16];
uint8_t buffer_4F53[1];
uint8_t buffer_4F80[2];
uint8_t buffer_4F65[1];
uint8_t buffer_4F66[1];
uint8_t buffer_4F67[2];
uint8_t buffer_F19E[32];
uint8_t buffer_F1AA[8];
uint8_t buffer_F1AB[8];
uint8_t buffer_F112[8];
uint8_t buffer_F190[17];
uint8_t buffer_F191[16];
uint8_t buffer_F193[16];
uint8_t buffer_F197[8];
uint8_t buffer_F198[16];
uint8_t buffer_F199[4];
uint8_t buffer_F19D[4];
uint8_t buffer_DFEF[64];
uint8_t buffer_F101[4];
uint8_t buffer_F110[8];
uint8_t buffer_4F51[16];
uint8_t buffer_4F54[16];
uint8_t buffer_F18C[24];
uint8_t buffer_F18B[4];
uint8_t buffer_0200[1];
uint8_t buffer_0201[1];
uint8_t buffer_F187[10];
uint8_t buffer_F189[16];
uint8_t buffer_FD01[1];
uint8_t buffer_FD02[1];
uint8_t buffer_FD03[1];
} Uds_DidBuffer;
/*******************************************************************************
* the globals
******************************************************************************/
Uds_DidBuffer udsDidBuf;
/*******************************************************************************
* the constants
******************************************************************************/
static const Uds_ServiceType udsServiceTable[UDS_SERVICE_NUM] = {
{0x10, 2, true, UdsService10_SessionControl },
{0x11, 2, true, UdsService11_ResetEcu },
{0x27, 2, true, UdsService27_SecurityAccess },
{0x28, 3, true, UdsService28_CommunicationControl },
{0x3E, 2, true, UdsService3E_TesterPresent },
{0x85, 2, true, UdsService85_ControlDtcSetting },
{0x22, 3, false, UdsService22_ReadDataByIdentifier },
{0x2E, 4, false, UdsService2E_WriteDataByIdentifier},
{0x14, 4, false, UdsService14_ClearDiagInfo },
{0x19, 3, true, UdsService19_ReadDtcInformation },
{0x2F, 3, false, UdsService2F_InputOutputCtrlById },
{0x31, 4, true, UdsService31_RoutineControl },
{0x34, 5, false, UdsService34_RequestDownload },
{0x36, 2, false, UdsService36_TransferData },
{0x37, 1, false, UdsService37_RequestTransferExit },
};
static const bool udsSecurityTable[UDS_SERVICE_NUM][UDS_SA_LEVEL_NUM] = {
{false, false, false}, /* 0x10 */
{false, false, false}, /* 0x11 */
{false, false, false}, /* 0x27 */
{false, false, false}, /* 0x28 */
{false, false, false}, /* 0x3E */
{false, false, false}, /* 0x85 */
{false, false, false}, /* 0x22 */
{false, false, false}, /* 0x2E */
{false, false, false}, /* 0x14 */
{false, false, false}, /* 0x19 */
{false, false, false}, /* 0x2F */
{false, false, false}, /* 0x31 */
{false, false, false}, /* 0x34 */
{false, false, false}, /* 0x36 */
{false, false, false}, /* 0x37 */
};
Uds_DidType udsDidTable[] = {
{0xF113, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_F113, BYTES_OF(udsDidBuf.buffer_F113)},
{0xF180, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_F180, BYTES_OF(udsDidBuf.buffer_F180)},
{0xF186, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_F186, BYTES_OF(udsDidBuf.buffer_F186)},
{0xF18A, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_F18A, BYTES_OF(udsDidBuf.buffer_F18A)},
{0xF195, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_F195, BYTES_OF(udsDidBuf.buffer_F195)},
{0xF1A0, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_F1A0, BYTES_OF(udsDidBuf.buffer_F1A0)},
{0xF1A1, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_F1A1, BYTES_OF(udsDidBuf.buffer_F1A1)},
{0xF1A2, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_F1A2, BYTES_OF(udsDidBuf.buffer_F1A2)},
{0xF1A5, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_F1A5, BYTES_OF(udsDidBuf.buffer_F1A5)},
{0xF1AE, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_F1AE, BYTES_OF(udsDidBuf.buffer_F1AE)},
{0x4F53, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_4F53, BYTES_OF(udsDidBuf.buffer_4F53)},
{0x4F80, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_4F80, BYTES_OF(udsDidBuf.buffer_4F80)},
{0x4F65, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_4F65, BYTES_OF(udsDidBuf.buffer_4F65)},
{0x4F66, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_4F66, BYTES_OF(udsDidBuf.buffer_4F66)},
{0x4F67, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_4F67, BYTES_OF(udsDidBuf.buffer_4F67)},
{0xF19E, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_F19E, BYTES_OF(udsDidBuf.buffer_F19E)},
{0xF1AA, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_F1AA, BYTES_OF(udsDidBuf.buffer_F1AA)},
{0xF1AB, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT, UDS_SA_NONE, udsDidBuf.buffer_F1AB, BYTES_OF(udsDidBuf.buffer_F1AB)},
{0xF112, UDS_DID_TYPE_NVM_RW, UDS_SESSION_EXTENDED, UDS_SA_LEVEL_1, udsDidBuf.buffer_F112, BYTES_OF(udsDidBuf.buffer_F112)},
{0xF190, UDS_DID_TYPE_NVM_RW, UDS_SESSION_EXTENDED, UDS_SA_LEVEL_1, udsDidBuf.buffer_F190, BYTES_OF(udsDidBuf.buffer_F190)},
{0xF191, UDS_DID_TYPE_NVM_RO, UDS_SESSION_SUPPLIER, UDS_SA_LEVEL_63, udsDidBuf.buffer_F191, BYTES_OF(udsDidBuf.buffer_F191)},
{0xF193, UDS_DID_TYPE_NVM_RO, UDS_SESSION_SUPPLIER, UDS_SA_LEVEL_63, udsDidBuf.buffer_F193, BYTES_OF(udsDidBuf.buffer_F193)},
{0xF197, UDS_DID_TYPE_NVM_RW, UDS_SESSION_EXTENDED, UDS_SA_LEVEL_1, udsDidBuf.buffer_F197, BYTES_OF(udsDidBuf.buffer_F197)},
{0xF198, UDS_DID_TYPE_NVM_RO, UDS_SESSION_SUPPLIER, UDS_SA_LEVEL_63, udsDidBuf.buffer_F198, BYTES_OF(udsDidBuf.buffer_F198)},
{0xF199, UDS_DID_TYPE_NVM_RO, UDS_SESSION_SUPPLIER, UDS_SA_LEVEL_63, udsDidBuf.buffer_F199, BYTES_OF(udsDidBuf.buffer_F199)},
{0xF19D, UDS_DID_TYPE_NVM_RW, UDS_SESSION_EXTENDED, UDS_SA_LEVEL_1, udsDidBuf.buffer_F19D, BYTES_OF(udsDidBuf.buffer_F19D)},
{0xDFEF, UDS_DID_TYPE_NVM_RW, UDS_SESSION_EXTENDED, UDS_SA_LEVEL_1, udsDidBuf.buffer_DFEF, BYTES_OF(udsDidBuf.buffer_DFEF)},
{0xF101, UDS_DID_TYPE_NVM_RW, UDS_SESSION_EXTENDED, UDS_SA_LEVEL_1, udsDidBuf.buffer_F101, BYTES_OF(udsDidBuf.buffer_F101)},
{0xF110, UDS_DID_TYPE_NVM_RO, UDS_SESSION_EXTENDED, UDS_SA_LEVEL_1, udsDidBuf.buffer_F110, BYTES_OF(udsDidBuf.buffer_F110)},
{0x4F51, UDS_DID_TYPE_NVM_WO, UDS_SESSION_EXTENDED, UDS_SA_LEVEL_1, udsDidBuf.buffer_4F51, BYTES_OF(udsDidBuf.buffer_4F51)},
{0x4F54, UDS_DID_TYPE_NVM_WO, UDS_SESSION_EXTENDED, UDS_SA_LEVEL_1, udsDidBuf.buffer_4F54, BYTES_OF(udsDidBuf.buffer_4F54)},
{0xF18C, UDS_DID_TYPE_NVM_RO, UDS_SESSION_SUPPLIER, UDS_SA_LEVEL_63, udsDidBuf.buffer_F18C, BYTES_OF(udsDidBuf.buffer_F18C)},
{0xF18B, UDS_DID_TYPE_NVM_RO, UDS_SESSION_SUPPLIER, UDS_SA_LEVEL_63, udsDidBuf.buffer_F18B, BYTES_OF(udsDidBuf.buffer_F18B)},
{0x0200, UDS_DID_TYPE_NVM_RO, UDS_SESSION_EXTENDED, UDS_SA_LEVEL_1, udsDidBuf.buffer_0200, BYTES_OF(udsDidBuf.buffer_0200)},
{0x0201, UDS_DID_TYPE_NVM_RO, UDS_SESSION_EXTENDED, UDS_SA_LEVEL_1, udsDidBuf.buffer_0201, BYTES_OF(udsDidBuf.buffer_0201)},
{0xF187, UDS_DID_TYPE_NVM_RO, UDS_SESSION_SUPPLIER, UDS_SA_LEVEL_63, udsDidBuf.buffer_F187, BYTES_OF(udsDidBuf.buffer_F187)},
{0xF189, UDS_DID_TYPE_NVM_RO, UDS_SESSION_SUPPLIER, UDS_SA_LEVEL_63, udsDidBuf.buffer_F189, BYTES_OF(udsDidBuf.buffer_F189)},
{0xFD01, UDS_DID_TYPE_NVM_RO, UDS_SESSION_SUPPLIER, UDS_SA_LEVEL_63, udsDidBuf.buffer_FD01, BYTES_OF(udsDidBuf.buffer_FD01)},
{0xFD02, UDS_DID_TYPE_NVM_RO, UDS_SESSION_SUPPLIER, UDS_SA_LEVEL_63, udsDidBuf.buffer_FD02, BYTES_OF(udsDidBuf.buffer_FD02)},
{0xFD03, UDS_DID_TYPE_NVM_RO, UDS_SESSION_SUPPLIER, UDS_SA_LEVEL_63, udsDidBuf.buffer_FD03, BYTES_OF(udsDidBuf.buffer_FD03)},
};
/*******************************************************************************
* the functions
******************************************************************************/
void Uds_UserInit(UdsType *obj, const Uds_ParamsType *pParams)
{
Uds_Init(obj, pParams);
obj->seviceTable = udsServiceTable;
obj->securityTable = &udsSecurityTable[0][0];
obj->serviceNum = UDS_SERVICE_NUM;
obj->didTable = udsDidTable;
obj->didNum = sizeof(udsDidTable) / sizeof(Uds_DidType);
}

View File

@ -1,76 +0,0 @@
/*
* Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
* All rights reserved.
*
* Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
* exclusively with CVA's microcontroller products. This file can be freely
* distributed within development tools that are supporting such microcontroller
* products.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
* OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*/
#ifndef _UDS_USER_H_
#define _UDS_USER_H_
/*! \brief Contains public interface to various functions related
* to the user-defined UDS application
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "../stack/uds.h"
#include "uds_service10.h"
#include "uds_service11.h"
#include "uds_service14.h"
#include "uds_service19.h"
#include "uds_service22.h"
#include "uds_service27.h"
#include "uds_service28.h"
#include "uds_service2E.h"
#include "uds_service2F.h"
#include "uds_service31.h"
#include "uds_service34.h"
#include "uds_service36.h"
#include "uds_service37.h"
#include "uds_service3E.h"
#include "uds_service85.h"
#include "uds_dtc.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initialize the UDS object
*/
extern void Uds_UserInit(UdsType *obj, const Uds_ParamsType *pParams);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _UDS_USER_H_ */

View File

@ -1,338 +0,0 @@
/*
* Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
* All rights reserved.
*
* Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
* exclusively with CVA's microcontroller products. This file can be freely
* distributed within development tools that are supporting such microcontroller
* products.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
* OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*/
#ifndef _CVM014X_FEATURES_H_
#define _CVM014X_FEATURES_H_
/*! \brief Contains public interface to various functions related
* to the features definition of CVM014x series chips
*/
/*******************************************************************************
* the includes
******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
#if defined(MCU_CVM0146FMLQ) || defined(MCU_CVM0146LMLQ)
#ifdef FEATURE_PFLASH_SIZE
#undef FEATURE_PFLASH_SIZE
#endif
#define FEATURE_PFLASH_SIZE (0x100000)
#ifdef FEATURE_RAM_SIZE
#undef FEATURE_RAM_SIZE
#endif
#define FEATURE_RAM_SIZE (0x20000)
#ifdef FEATURE_DFLASH_SIZE
#undef FEATURE_DFLASH_SIZE
#endif
#define FEATURE_DFLASH_SIZE (0x20000)
#ifdef FEATURE_EEPROM_SIZE
#undef FEATURE_EEPROM_SIZE
#endif
#define FEATURE_EEPROM_SIZE (0x1000)
#ifdef FEATURE_CAN_FD_INSTANCE_NUM
#undef FEATURE_CAN_FD_INSTANCE_NUM
#endif
#define FEATURE_CAN_FD_INSTANCE_NUM (4)
#ifdef FEATURE_MFT_INSTANCE_NUM
#undef FEATURE_MFT_INSTANCE_NUM
#endif
#define FEATURE_MFT_INSTANCE_NUM (6)
#ifdef FEATURE_UART_INSTANCE_NUM
#undef FEATURE_UART_INSTANCE_NUM
#endif
#define FEATURE_UART_INSTANCE_NUM (4)
#ifdef FEATURE_SPI_INSTANCE_NUM
#undef FEATURE_SPI_INSTANCE_NUM
#endif
#define FEATURE_SPI_INSTANCE_NUM (4)
#ifdef FEATURE_LAST_IRQn
#undef FEATURE_LAST_IRQn
#endif
#define FEATURE_LAST_IRQn (CAN3_EdgeWakeup_IRQn)
#elif defined(MCU_CVM0146FMLL) || defined(MCU_CVM0146LMLL)
#ifdef FEATURE_PFLASH_SIZE
#undef FEATURE_PFLASH_SIZE
#endif
#define FEATURE_PFLASH_SIZE (0x100000)
#ifdef FEATURE_RAM_SIZE
#undef FEATURE_RAM_SIZE
#endif
#define FEATURE_RAM_SIZE (0x20000)
#ifdef FEATURE_DFLASH_SIZE
#undef FEATURE_DFLASH_SIZE
#endif
#define FEATURE_DFLASH_SIZE (0x20000)
#ifdef FEATURE_EEPROM_SIZE
#undef FEATURE_EEPROM_SIZE
#endif
#define FEATURE_EEPROM_SIZE (0x1000)
#ifdef FEATURE_CAN_FD_INSTANCE_NUM
#undef FEATURE_CAN_FD_INSTANCE_NUM
#endif
#define FEATURE_CAN_FD_INSTANCE_NUM (4)
#ifdef FEATURE_MFT_INSTANCE_NUM
#undef FEATURE_MFT_INSTANCE_NUM
#endif
#define FEATURE_MFT_INSTANCE_NUM (6)
#ifdef FEATURE_UART_INSTANCE_NUM
#undef FEATURE_UART_INSTANCE_NUM
#endif
#define FEATURE_UART_INSTANCE_NUM (4)
#ifdef FEATURE_SPI_INSTANCE_NUM
#undef FEATURE_SPI_INSTANCE_NUM
#endif
#define FEATURE_SPI_INSTANCE_NUM (4)
#ifdef FEATURE_LAST_IRQn
#undef FEATURE_LAST_IRQn
#endif
#define FEATURE_LAST_IRQn (CAN3_EdgeWakeup_IRQn)
#elif defined(MCU_CVM0146FMLH) || defined(MCU_CVM0146LMLH)
#ifdef FEATURE_PFLASH_SIZE
#undef FEATURE_PFLASH_SIZE
#endif
#define FEATURE_PFLASH_SIZE (0x100000)
#ifdef FEATURE_RAM_SIZE
#undef FEATURE_RAM_SIZE
#endif
#define FEATURE_RAM_SIZE (0x20000)
#ifdef FEATURE_DFLASH_SIZE
#undef FEATURE_DFLASH_SIZE
#endif
#define FEATURE_DFLASH_SIZE (0x20000)
#ifdef FEATURE_EEPROM_SIZE
#undef FEATURE_EEPROM_SIZE
#endif
#define FEATURE_EEPROM_SIZE (0x1000)
#ifdef FEATURE_CAN_FD_INSTANCE_NUM
#undef FEATURE_CAN_FD_INSTANCE_NUM
#endif
#define FEATURE_CAN_FD_INSTANCE_NUM (3)
#ifdef FEATURE_MFT_INSTANCE_NUM
#undef FEATURE_MFT_INSTANCE_NUM
#endif
#define FEATURE_MFT_INSTANCE_NUM (4)
#ifdef FEATURE_UART_INSTANCE_NUM
#undef FEATURE_UART_INSTANCE_NUM
#endif
#define FEATURE_UART_INSTANCE_NUM (3)
#ifdef FEATURE_SPI_INSTANCE_NUM
#undef FEATURE_SPI_INSTANCE_NUM
#endif
#define FEATURE_SPI_INSTANCE_NUM (3)
#ifdef FEATURE_LAST_IRQn
#undef FEATURE_LAST_IRQn
#endif
#define FEATURE_LAST_IRQn (CAN2_EdgeWakeup_IRQn)
#elif defined(MCU_CVM0144FMLL) || defined(MCU_CVM0144LMLL)
#ifdef FEATURE_PFLASH_SIZE
#undef FEATURE_PFLASH_SIZE
#endif
#define FEATURE_PFLASH_SIZE (0x80000)
#ifdef FEATURE_RAM_SIZE
#undef FEATURE_RAM_SIZE
#endif
#define FEATURE_RAM_SIZE (0x20000)
#ifdef FEATURE_DFLASH_SIZE
#undef FEATURE_DFLASH_SIZE
#endif
#define FEATURE_DFLASH_SIZE (0x10000)
#ifdef FEATURE_EEPROM_SIZE
#undef FEATURE_EEPROM_SIZE
#endif
#define FEATURE_EEPROM_SIZE (0x1000)
#ifdef FEATURE_CAN_FD_INSTANCE_NUM
#undef FEATURE_CAN_FD_INSTANCE_NUM
#endif
#define FEATURE_CAN_FD_INSTANCE_NUM (4)
#ifdef FEATURE_MFT_INSTANCE_NUM
#undef FEATURE_MFT_INSTANCE_NUM
#endif
#define FEATURE_MFT_INSTANCE_NUM (4)
#ifdef FEATURE_UART_INSTANCE_NUM
#undef FEATURE_UART_INSTANCE_NUM
#endif
#define FEATURE_UART_INSTANCE_NUM (4)
#ifdef FEATURE_SPI_INSTANCE_NUM
#undef FEATURE_SPI_INSTANCE_NUM
#endif
#define FEATURE_SPI_INSTANCE_NUM (4)
#ifdef FEATURE_LAST_IRQn
#undef FEATURE_LAST_IRQn
#endif
#define FEATURE_LAST_IRQn (CAN3_EdgeWakeup_IRQn)
#elif defined(MCU_CVM0144FMLH) || defined(MCU_CVM0144LMLH)
#ifdef FEATURE_PFLASH_SIZE
#undef FEATURE_PFLASH_SIZE
#endif
#define FEATURE_PFLASH_SIZE (0x80000)
#ifdef FEATURE_RAM_SIZE
#undef FEATURE_RAM_SIZE
#endif
#define FEATURE_RAM_SIZE (0x20000)
#ifdef FEATURE_DFLASH_SIZE
#undef FEATURE_DFLASH_SIZE
#endif
#define FEATURE_DFLASH_SIZE (0x10000)
#ifdef FEATURE_EEPROM_SIZE
#undef FEATURE_EEPROM_SIZE
#endif
#define FEATURE_EEPROM_SIZE (0x1000)
#ifdef FEATURE_CAN_FD_INSTANCE_NUM
#undef FEATURE_CAN_FD_INSTANCE_NUM
#endif
#define FEATURE_CAN_FD_INSTANCE_NUM (3)
#ifdef FEATURE_MFT_INSTANCE_NUM
#undef FEATURE_MFT_INSTANCE_NUM
#endif
#define FEATURE_MFT_INSTANCE_NUM (4)
#ifdef FEATURE_UART_INSTANCE_NUM
#undef FEATURE_UART_INSTANCE_NUM
#endif
#define FEATURE_UART_INSTANCE_NUM (3)
#ifdef FEATURE_SPI_INSTANCE_NUM
#undef FEATURE_SPI_INSTANCE_NUM
#endif
#define FEATURE_SPI_INSTANCE_NUM (3)
#ifdef FEATURE_LAST_IRQn
#undef FEATURE_LAST_IRQn
#endif
#define FEATURE_LAST_IRQn (CAN2_EdgeWakeup_IRQn)
#elif defined(MCU_CVM0142FMLH) || defined(MCU_CVM0142LMLH)
#ifdef FEATURE_PFLASH_SIZE
#undef FEATURE_PFLASH_SIZE
#endif
#define FEATURE_PFLASH_SIZE (0x40000)
#ifdef FEATURE_RAM_SIZE
#undef FEATURE_RAM_SIZE
#endif
#define FEATURE_RAM_SIZE (0x10000)
#ifdef FEATURE_DFLASH_SIZE
#undef FEATURE_DFLASH_SIZE
#endif
#define FEATURE_DFLASH_SIZE (0x10000)
#ifdef FEATURE_EEPROM_SIZE
#undef FEATURE_EEPROM_SIZE
#endif
#define FEATURE_EEPROM_SIZE (0x1000)
#ifdef FEATURE_CAN_FD_INSTANCE_NUM
#undef FEATURE_CAN_FD_INSTANCE_NUM
#endif
#define FEATURE_CAN_FD_INSTANCE_NUM (3)
#ifdef FEATURE_MFT_INSTANCE_NUM
#undef FEATURE_MFT_INSTANCE_NUM
#endif
#define FEATURE_MFT_INSTANCE_NUM (4)
#ifdef FEATURE_UART_INSTANCE_NUM
#undef FEATURE_UART_INSTANCE_NUM
#endif
#define FEATURE_UART_INSTANCE_NUM (3)
#ifdef FEATURE_SPI_INSTANCE_NUM
#undef FEATURE_SPI_INSTANCE_NUM
#endif
#define FEATURE_SPI_INSTANCE_NUM (3)
#ifdef FEATURE_LAST_IRQn
#undef FEATURE_LAST_IRQn
#endif
#define FEATURE_LAST_IRQn (CAN2_EdgeWakeup_IRQn)
#else
#error "No correct chip defined"
#endif
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _CVM014X_FEATURES_H_ */

View File

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

View File

@ -20,7 +20,7 @@
#include "irq_drv.h"
#include "../cva/CVM014x.h"
#include "../../../CVM014x_features.h"
#include "CVM014x_features.h"
/*******************************************************************************
* the defines

View File

@ -21,7 +21,7 @@
#include "startup.h"
#include <stdint.h>
#include "../cva/CVM014x.h"
#include "../../../CVM014x_features.h"
#include "CVM014x_features.h"
/*******************************************************************************

View File

@ -1,188 +0,0 @@
/*
* 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 "mcu.h"
#include "drivers/cpu/startup/system_M014x.h"
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the functions
******************************************************************************/
void Mcu_Init(McuType *obj)
{
/* Initialize ADC driver */
AdcDrv_InitParamsType adcInitParams;
adcInitParams.adcNumber = ADCDRV_INSTANCE_0;
AdcDrv_Init(&obj->adc0Drv, ADC0, SIM, &adcInitParams);
adcInitParams.adcNumber = ADCDRV_INSTANCE_1;
AdcDrv_Init(&obj->adc1Drv, ADC1, SIM, &adcInitParams);
/* Initialize clock driver */
ClockDrv_InitParamsType clockInitParams;
clockInitParams.fircFreq = CPU_INT_FAST_CLK_HZ;
clockInitParams.sircFreq = CPU_INT_SLOW_CLK_HZ;
clockInitParams.xtalClkFreq = CPU_XTAL_CLK_HZ;
clockInitParams.rtcClkInFreq = 0;
clockInitParams.tclkFreq[0] = 0;
clockInitParams.tclkFreq[1] = 0;
clockInitParams.tclkFreq[2] = 0;
ClockDrv_Init(&obj->clockDrv, ACG, APC, SCG, PCC, &clockInitParams);
/* Initialize CMP driver */
CmpDrv_Init(&obj->cmpDrv, CMP);
/* Initialize CMU driver */
CmuDrv_Init(&obj->cmuFirc, CMU_FIRC);
CmuDrv_Init(&obj->cmuPll, CMU_PLL);
CmuDrv_Init(&obj->cmuSosc, CMU_SOSC);
/* Initialize CRC driver */
CrcDrv_Init(&obj->crcDrv, CRC);
/* Initialize CSE driver */
CseDrv_Init(&obj->cseDrv, CSE);
/* Initialize EDMA driver */
EDmaDrv_Init(&obj->edmaDrv, DMA, DMAMUX);
/* Initialize EIM driver */
EimDrv_Init(&obj->eimDrv, EIM);
/* Initialize ERM driver */
ErmDrv_Init(&obj->ermDrv, ERM);
/* Initialize EWM driver */
EwmDrv_Init(&obj->ewmDrv, EWM);
/* Initialize FCCU driver */
FccuDrv_Init(&obj->fccuDrv, FCCU, SIM);
/* Initialize Flash driver */
FlashDrv_Init(&obj->flashDrv, FTFC);
/* Initialize flexCAN driver */
FlexCanDrv_InitHwParType canInitHwPar;
canInitHwPar.canInstanceIdx = 0;
canInitHwPar.canRamNum = 3;
FlexCanDrv_Init(&obj->flexCanDrv0, CAN0, PCC, SCG, SIM, &canInitHwPar);
canInitHwPar.canInstanceIdx = 1;
canInitHwPar.canRamNum = 2;
FlexCanDrv_Init(&obj->flexCanDrv1, CAN1, PCC, SCG, SIM, &canInitHwPar);
canInitHwPar.canInstanceIdx = 2;
canInitHwPar.canRamNum = 1;
FlexCanDrv_Init(&obj->flexCanDrv2, CAN2, PCC, SCG, SIM, &canInitHwPar);
#if FEATURE_CAN_FD_INSTANCE_NUM == 4
canInitHwPar.canInstanceIdx = 3;
canInitHwPar.canRamNum = 1;
FlexCanDrv_Init(&obj->flexCanDrv3, CAN3, PCC, SCG, SIM, &canInitHwPar);
#endif
/* Initialize I2C driver */
I2cDrv_Init(&obj->i2cDrv0, I2C);
/* Initialize I2SM driver */
I2smDrv_Init(&obj->i2smDrv, I2SM, SIM);
/* Initialize I2SS driver */
I2ssDrv_Init(&obj->i2ssDrv, I2SS, SIM);
/* Initialize LPIT driver */
LpitDrv_Init(&obj->lpitDrv, LPIT);
/* Initialize LPTMR driver */
LptmrDrv_Init(&obj->lptmrDrv, LPTMR);
/* Initialize MFT drivers */
MftDrv_Init(&obj->mftDrv0, MFT0);
MftDrv_Init(&obj->mftDrv1, MFT1);
MftDrv_Init(&obj->mftDrv2, MFT2);
MftDrv_Init(&obj->mftDrv3, MFT3);
#if FEATURE_MFT_INSTANCE_NUM == 6
MftDrv_Init(&obj->mftDrv4, MFT4);
MftDrv_Init(&obj->mftDrv5, MFT5);
#endif
/* Initialize MPU driver */
MpuDrv_Init(&obj->mpuDrv, MPU);
/* Initialize PDB driver */
PdbDrv_Init(&obj->pdb0Drv, PDB0, SIM);
PdbDrv_Init(&obj->pdb1Drv, PDB1, SIM);
/* Initialize PINS driver */
PinsDrv_Init(&obj->pta, PORTA, GPIOA);
PinsDrv_Init(&obj->ptb, PORTB, GPIOB);
PinsDrv_Init(&obj->ptc, PORTC, GPIOC);
PinsDrv_Init(&obj->ptd, PORTD, GPIOD);
PinsDrv_Init(&obj->pte, PORTE, GPIOE);
/* Initialize POWER driver */
PowerDrv_Init(&obj->powerDrv, PMC, ACG);
/* Initialize PRNG driver */
PrngDrv_Init(&obj->prngDrv, PRNG);
/* Initialize PWMLITE driver */
PwmLiteDrv_Init(&obj->pwmLiteDrv0, PWMLITE0, SIM);
PwmLiteDrv_Init(&obj->pwmLiteDrv1, PWMLITE1, SIM);
PwmLiteDrv_Init(&obj->pwmLiteDrv2, PWMLITE2, SIM);
PwmLiteDrv_Init(&obj->pwmLiteDrv3, PWMLITE3, SIM);
PwmLiteDrv_Init(&obj->pwmLiteDrv4, PWMLITE4, SIM);
/* Initialize reset driver */
ResetDrv_Init(&obj->resetDrv, RCM, PCC, APC);
/* Initialize RTC driver */
RtcDrv_Init(&obj->rtcDrv, RTC);
/* Initialize SPI driver */
SpiDrv_Init(&obj->spiDrv0, SPI0);
SpiDrv_Init(&obj->spiDrv1, SPI1);
SpiDrv_Init(&obj->spiDrv2, SPI2);
#if FEATURE_SPI_INSTANCE_NUM == 4
SpiDrv_Init(&obj->spiDrv3, SPI3);
#endif
/* Initialize TRGMUX driver */
TrgMuxDrv_Init(&obj->trgMuxDrv, TRGMUX, SIM);
/* Initialize UART driver */
UartDrv_Init(&obj->uartDrv0, UART0);
UartDrv_Init(&obj->uartDrv1, UART1);
UartDrv_Init(&obj->uartDrv2, UART2);
#if FEATURE_UART_INSTANCE_NUM == 4
UartDrv_Init(&obj->uartDrv3, UART3);
#endif
/* Initialize watchdog driver */
WdgDrv_Init(&obj->wdgDrv, WDG);
}

View File

@ -1,166 +0,0 @@
/*
* 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 _MCU_H_
#define _MCU_H_
/*! \brief Contains public interface to various functions related
* to the MCAL (MCU Abstract Layer) module
*/
/*******************************************************************************
* the includes
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "CVM014x_features.h"
#include "drivers/adc/adc_drv.h"
#include "drivers/clock/clock_drv.h"
#include "drivers/cmp/cmp_drv.h"
#include "drivers/cmu/cmu_drv.h"
#include "drivers/cpu/cpu_drv.h"
#include "drivers/crc/crc_drv.h"
#include "drivers/cse/cse_drv.h"
#include "drivers/edma/edma_drv.h"
#include "drivers/eim/eim_drv.h"
#include "drivers/erm/erm_drv.h"
#include "drivers/ewm/ewm_drv.h"
#include "drivers/fccu/fccu_drv.h"
#include "drivers/flash/flash_drv.h"
#include "drivers/flexcan/flexcan_drv.h"
#include "drivers/i2c/i2c_drv.h"
#include "drivers/i2sm/i2sm_drv.h"
#include "drivers/i2ss/i2ss_drv.h"
#include "drivers/lpit/lpit_drv.h"
#include "drivers/lptmr/lptmr_drv.h"
#include "drivers/mft/mft_drv.h"
#include "drivers/mpu/mpu_drv.h"
#include "drivers/pdb/pdb_drv.h"
#include "drivers/pins/pins_drv.h"
#include "drivers/power/power_drv.h"
#include "drivers/prng/prng_drv.h"
#include "drivers/pwmlite/pwmlite_drv.h"
#include "drivers/reset/reset_drv.h"
#include "drivers/rtc/rtc_drv.h"
#include "drivers/spi/spi_drv.h"
#include "drivers/trgmux/trgmux_drv.h"
#include "drivers/uart/uart_drv.h"
#include "drivers/wdg/wdg_drv.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* the defines
******************************************************************************/
/*******************************************************************************
* the typedefs
******************************************************************************/
/*! \brief Definition of MCU prototype
*/
typedef struct _McuType_
{
AdcDrvType adc0Drv;
AdcDrvType adc1Drv;
ClockDrvType clockDrv;
CmpDrvType cmpDrv;
CmuDrvType cmuFirc;
CmuDrvType cmuPll;
CmuDrvType cmuSosc;
CrcDrvType crcDrv;
CseDrvType cseDrv;
EDmaDrvType edmaDrv;
EimDrvType eimDrv;
ErmDrvType ermDrv;
EwmDrvType ewmDrv;
FccuDrvType fccuDrv;
FlashDrvType flashDrv;
FlexCanDrvType flexCanDrv0;
FlexCanDrvType flexCanDrv1;
FlexCanDrvType flexCanDrv2;
FlexCanDrvType flexCanDrv3;
I2cDrvType i2cDrv0;
I2smDrvType i2smDrv;
I2ssDrvType i2ssDrv;
LpitDrvType lpitDrv;
LptmrDrvType lptmrDrv;
MftDrvType mftDrv0;
MftDrvType mftDrv1;
MftDrvType mftDrv2;
MftDrvType mftDrv3;
#if FEATURE_MFT_INSTANCE_NUM == 6
MftDrvType mftDrv4;
MftDrvType mftDrv5;
#endif
MpuDrvType mpuDrv;
PdbDrvType pdb0Drv;
PdbDrvType pdb1Drv;
PinsDrvType pta;
PinsDrvType ptb;
PinsDrvType ptc;
PinsDrvType ptd;
PinsDrvType pte;
PowerDrvType powerDrv;
PrngDrvType prngDrv;
PwmLiteDrvType pwmLiteDrv0;
PwmLiteDrvType pwmLiteDrv1;
PwmLiteDrvType pwmLiteDrv2;
PwmLiteDrvType pwmLiteDrv3;
PwmLiteDrvType pwmLiteDrv4;
ResetDrvType resetDrv;
RtcDrvType rtcDrv;
SpiDrvType spiDrv0;
SpiDrvType spiDrv1;
SpiDrvType spiDrv2;
#if FEATURE_SPI_INSTANCE_NUM == 4
SpiDrvType spiDrv3;
#endif
TrgMuxDrvType trgMuxDrv;
UartDrvType uartDrv0;
UartDrvType uartDrv1;
UartDrvType uartDrv2;
#if FEATURE_UART_INSTANCE_NUM == 4
UartDrvType uartDrv3;
#endif
WdgDrvType wdgDrv;
} McuType;
/*******************************************************************************
* the globals
******************************************************************************/
/*******************************************************************************
* the function prototypes
******************************************************************************/
/*! \brief Initializes the MCU
*
* This function initializes MCU by setting up all the peripheral drivers
*
* \param[in] obj : pointer to MCU instance
*/
extern void Mcu_Init(McuType *obj);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif /* _MCU_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -2152,27 +2152,6 @@
<name>$PROJ_DIR$\SDK\platform\devices\CVM014x\drivers\adc\adc_drv.h</name>
</file>
</group>
<group>
<name>clock</name>
<excluded>
<configuration>Debug</configuration>
<configuration>Release</configuration>
</excluded>
<file>
<name>$PROJ_DIR$\SDK\platform\devices\CVM014x\drivers\clock\clock_drv.c</name>
<excluded>
<configuration>Debug</configuration>
<configuration>Release</configuration>
</excluded>
</file>
<file>
<name>$PROJ_DIR$\SDK\platform\devices\CVM014x\drivers\clock\clock_drv.h</name>
<excluded>
<configuration>Debug</configuration>
<configuration>Release</configuration>
</excluded>
</file>
</group>
<group>
<name>cmp</name>
<file>
@ -2578,9 +2557,6 @@
</group>
<group>
<name>lib</name>
<file>
<name>$PROJ_DIR$\..\..\..\..\lib\shared\common\stimer\stimer.h</name>
</file>
</group>
<group>
<name>linker</name>
@ -2590,50 +2566,8 @@
</group>
<group>
<name>middleware</name>
<group>
<name>isotp</name>
<excluded>
<configuration>Debug</configuration>
<configuration>Release</configuration>
</excluded>
<file>
<name>$PROJ_DIR$\SDK\middleware\isotp\isotp.c</name>
<excluded>
<configuration>Debug</configuration>
<configuration>Release</configuration>
</excluded>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\isotp\isotp.h</name>
<excluded>
<configuration>Debug</configuration>
<configuration>Release</configuration>
</excluded>
</file>
</group>
<group>
<name>uds</name>
<group>
<name>stack</name>
<excluded>
<configuration>Debug</configuration>
<configuration>Release</configuration>
</excluded>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\stack\uds.c</name>
<excluded>
<configuration>Debug</configuration>
<configuration>Release</configuration>
</excluded>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\stack\uds.h</name>
<excluded>
<configuration>Debug</configuration>
<configuration>Release</configuration>
</excluded>
</file>
</group>
<group>
<name>user</name>
<file>
@ -2642,34 +2576,6 @@
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_dtc.h</name>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service10.c</name>
<excluded>
<configuration>Debug</configuration>
<configuration>Release</configuration>
</excluded>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service10.h</name>
<excluded>
<configuration>Debug</configuration>
<configuration>Release</configuration>
</excluded>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service11.c</name>
<excluded>
<configuration>Debug</configuration>
<configuration>Release</configuration>
</excluded>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service11.h</name>
<excluded>
<configuration>Debug</configuration>
<configuration>Release</configuration>
</excluded>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service14.c</name>
</file>
@ -2720,48 +2626,6 @@
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service2F.h</name>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service31.c</name>
<excluded>
<configuration>Debug</configuration>
<configuration>Release</configuration>
</excluded>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service31.h</name>
<excluded>
<configuration>Debug</configuration>
<configuration>Release</configuration>
</excluded>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service34.c</name>
<excluded>
<configuration>Debug</configuration>
<configuration>Release</configuration>
</excluded>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service34.h</name>
<excluded>
<configuration>Debug</configuration>
<configuration>Release</configuration>
</excluded>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service36.c</name>
<excluded>
<configuration>Debug</configuration>
<configuration>Release</configuration>
</excluded>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service36.h</name>
<excluded>
<configuration>Debug</configuration>
<configuration>Release</configuration>
</excluded>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service37.c</name>
</file>
@ -2780,20 +2644,6 @@
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service85.h</name>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_user.c</name>
<excluded>
<configuration>Debug</configuration>
<configuration>Release</configuration>
</excluded>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_user.h</name>
<excluded>
<configuration>Debug</configuration>
<configuration>Release</configuration>
</excluded>
</file>
</group>
</group>
</group>

View File

@ -2398,15 +2398,6 @@
<name>$PROJ_DIR$\SDK\platform\devices\CVM014x\drivers\adc\adc_drv.h</name>
</file>
</group>
<group>
<name>clock</name>
<file>
<name>$PROJ_DIR$\SDK\platform\devices\CVM014x\drivers\clock\clock_drv.c</name>
</file>
<file>
<name>$PROJ_DIR$\SDK\platform\devices\CVM014x\drivers\clock\clock_drv.h</name>
</file>
</group>
<group>
<name>cmp</name>
<file>
@ -2812,9 +2803,6 @@
</group>
<group>
<name>lib</name>
<file>
<name>$PROJ_DIR$\..\..\..\..\lib\shared\common\stimer\stimer.h</name>
</file>
</group>
<group>
<name>linker</name>
@ -2824,26 +2812,8 @@
</group>
<group>
<name>middleware</name>
<group>
<name>isotp</name>
<file>
<name>$PROJ_DIR$\SDK\middleware\isotp\isotp.c</name>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\isotp\isotp.h</name>
</file>
</group>
<group>
<name>uds</name>
<group>
<name>stack</name>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\stack\uds.c</name>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\stack\uds.h</name>
</file>
</group>
<group>
<name>user</name>
<file>
@ -2852,18 +2822,6 @@
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_dtc.h</name>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service10.c</name>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service10.h</name>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service11.c</name>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service11.h</name>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service14.c</name>
</file>
@ -2906,24 +2864,6 @@
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service2F.h</name>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service31.c</name>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service31.h</name>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service34.c</name>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service34.h</name>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service36.c</name>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service36.h</name>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service37.c</name>
</file>
@ -2942,12 +2882,6 @@
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_service85.h</name>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_user.c</name>
</file>
<file>
<name>$PROJ_DIR$\SDK\middleware\uds\user\uds_user.h</name>
</file>
</group>
</group>
</group>

View File

@ -25,7 +25,7 @@ if not "%~1" == "" goto debugFile
@echo on
"E:\IAR Systems\Embedded Workbench 8.3\common\bin\cspybat" -f "F:\FCB_project\RP-01\REF\can_bootloader\cva_bootloader_m0146\settings\cva_bootloader_m0146.Debug.general.xcl" --backend -f "F:\FCB_project\RP-01\REF\can_bootloader\cva_bootloader_m0146\settings\cva_bootloader_m0146.Debug.driver.xcl"
"E:\IAR Systems\Embedded Workbench 8.3\common\bin\cspybat" -f "F:\FCB_project\RP-01\CODE\cva_bootloader_m0146\settings\cva_bootloader_m0146.Debug.general.xcl" --backend -f "F:\FCB_project\RP-01\CODE\cva_bootloader_m0146\settings\cva_bootloader_m0146.Debug.driver.xcl"
@echo off
goto end
@ -34,7 +34,7 @@ goto end
@echo on
"E:\IAR Systems\Embedded Workbench 8.3\common\bin\cspybat" -f "F:\FCB_project\RP-01\REF\can_bootloader\cva_bootloader_m0146\settings\cva_bootloader_m0146.Debug.general.xcl" "--debug_file=%~1" --backend -f "F:\FCB_project\RP-01\REF\can_bootloader\cva_bootloader_m0146\settings\cva_bootloader_m0146.Debug.driver.xcl"
"E:\IAR Systems\Embedded Workbench 8.3\common\bin\cspybat" -f "F:\FCB_project\RP-01\CODE\cva_bootloader_m0146\settings\cva_bootloader_m0146.Debug.general.xcl" "--debug_file=%~1" --backend -f "F:\FCB_project\RP-01\CODE\cva_bootloader_m0146\settings\cva_bootloader_m0146.Debug.driver.xcl"
@echo off
:end

View File

@ -23,9 +23,9 @@
if ($debugfile -eq "")
{
& "E:\IAR Systems\Embedded Workbench 8.3\common\bin\cspybat" -f "F:\FCB_project\RP-01\REF\can_bootloader\cva_bootloader_m0146\settings\cva_bootloader_m0146.Debug.general.xcl" --backend -f "F:\FCB_project\RP-01\REF\can_bootloader\cva_bootloader_m0146\settings\cva_bootloader_m0146.Debug.driver.xcl"
& "E:\IAR Systems\Embedded Workbench 8.3\common\bin\cspybat" -f "F:\FCB_project\RP-01\CODE\cva_bootloader_m0146\settings\cva_bootloader_m0146.Debug.general.xcl" --backend -f "F:\FCB_project\RP-01\CODE\cva_bootloader_m0146\settings\cva_bootloader_m0146.Debug.driver.xcl"
}
else
{
& "E:\IAR Systems\Embedded Workbench 8.3\common\bin\cspybat" -f "F:\FCB_project\RP-01\REF\can_bootloader\cva_bootloader_m0146\settings\cva_bootloader_m0146.Debug.general.xcl" --debug_file=$debugfile --backend -f "F:\FCB_project\RP-01\REF\can_bootloader\cva_bootloader_m0146\settings\cva_bootloader_m0146.Debug.driver.xcl"
& "E:\IAR Systems\Embedded Workbench 8.3\common\bin\cspybat" -f "F:\FCB_project\RP-01\CODE\cva_bootloader_m0146\settings\cva_bootloader_m0146.Debug.general.xcl" --debug_file=$debugfile --backend -f "F:\FCB_project\RP-01\CODE\cva_bootloader_m0146\settings\cva_bootloader_m0146.Debug.driver.xcl"
}

View File

@ -2,7 +2,7 @@
"E:\IAR Systems\Embedded Workbench 8.3\arm\bin\armjlink2.dll"
"F:\FCB_project\RP-01\REF\can_bootloader\cva_bootloader_m0146\Debug_FLASH\Exe\bootloader_m146.out"
"F:\FCB_project\RP-01\CODE\cva_bootloader_m0146\Debug_FLASH\Exe\bootloader_m146.out"
--plugin="E:\IAR Systems\Embedded Workbench 8.3\arm\bin\armbat.dll"

View File

@ -125,6 +125,12 @@
<ShowTimeSum>1</ShowTimeSum>
<SumSortOrder>0</SumSortOrder>
</EventLog>
<DisassembleMode>
<mode>0</mode>
</DisassembleMode>
<Breakpoints2>
<Count>0</Count>
</Breakpoints2>
<TermIOLog>
<LoggingEnabled>_ 0</LoggingEnabled>
<LogFile>_ ""</LogFile>
@ -134,19 +140,13 @@
<LogFile>_ ""</LogFile>
<Category>_ 0</Category>
</LogFile>
<Aliases>
<Count>0</Count>
<SuppressDialog>0</SuppressDialog>
</Aliases>
<PowerProbe>
<Frequency>10000</Frequency>
<Probe0>I0</Probe0>
<ProbeSetup0>2 1 1 2 0 0</ProbeSetup0>
</PowerProbe>
<DisassembleMode>
<mode>0</mode>
</DisassembleMode>
<Breakpoints2>
<Count>0</Count>
</Breakpoints2>
<Aliases>
<Count>0</Count>
<SuppressDialog>0</SuppressDialog>
</Aliases>
</settings>

View File

@ -50,7 +50,7 @@
<item>33054</item>
<item>0</item>
<item>33035</item>
<item>33036</item>
<item>33037</item>
<item>34399</item>
<item>0</item>
<item>33038</item>
@ -69,6 +69,7 @@
<ExpandedNode>cva_bootloader_m0146</ExpandedNode>
<ExpandedNode>cva_bootloader_m0146/Output</ExpandedNode>
<ExpandedNode>cva_bootloader_m0146/src</ExpandedNode>
<ExpandedNode>cva_bootloader_m0146/src/lib</ExpandedNode>
</NodeDict>
</IarPane-34063>
<ControlBarVersion>
@ -83,11 +84,11 @@
<RecentlyUsedMenus>1</RecentlyUsedMenus>
<MenuShadows>1</MenuShadows>
<ShowAllMenusAfterDelay>1</ShowAllMenusAfterDelay>
<CommandsUsage>13000000080010860000010000000C8100000D00000055840000010000005E860000010000000E81000003000000118600000200000005810000020000004681000001000000</CommandsUsage>
<CommandsUsage>31000000080010860000010000000C8100002B00000055840000010000000E810000030000005E86000001000000058100000200000011860000020000004681000001000000</CommandsUsage>
</MFCToolBarParameters>
<CommandManager>
<CommandsWithoutImages>57000D8400000F84000008840000FFFFFFFF54840000328100001C810000098400003C8400003D840000408400004C8400003E8400004B8400004D8400003F8400003A8400003B8400005A8400005B840000D6840000D7840000D8840000D9840000DA840000DB840000DC840000DD840000DE840000DF840000E0840000E1840000E2840000EA840000248100000C84000033840000788400001184000020DE000021DE000026DE000028DE000023DE000022DE000024DE000027DE000025DE000020920000289200002992000037920000389200003492000033920000259200001E9200001D92000045DE000008800000098000000A8000000B8000000C800000158000000A81000001E8000004840000068400003284000077840000078400003084000002840000038400000E8400001084000005840000318400000A840000808C000044D5000055840000568400005984000012810000D2840000</CommandsWithoutImages>
<MenuUserImages>140004810000180000002681000029000000239200000000000020810000270000000F8100001F0000000C8100001C000000098100001A000000008400000B00000044920000100000001F810000260000000E8100001E0000001F9200000D0000002D9200000F0000000B8100001B000000D18400000C000000058100001900000035E100004000000002E10000330000000D8100001D0000002C9200000E000000</MenuUserImages>
<CommandsWithoutImages>59000D8400000F84000008840000FFFFFFFF54840000328100001C810000098400003C8400003D840000408400004C8400003E8400004B8400004D8400003F8400003A8400003B8400005A8400005B840000D6840000D7840000D8840000D9840000DA840000DB840000DC840000DD840000DE840000DF840000E0840000E1840000E2840000EA840000248100000C84000033840000788400001184000020DE000021DE000026DE000028DE000023DE000022DE000024DE000027DE000025DE000020920000289200002992000037920000389200003492000033920000259200001E9200001D92000045DE000008800000098000000A8000000B8000000C800000158000000A81000001E8000032840000778400000784000002840000038400001084000005840000318400000A840000808C000044D5000055840000568400005984000012810000D284000053840000818400007D840000828400008384000084840000</CommandsWithoutImages>
<MenuUserImages>1800048400004C0000002681000029000000048100001800000023920000000000000F8100001F00000020810000270000000C8100001C000000098100001A000000068400004E000000008400000B00000030840000520000000E8400005000000044920000100000001F9200000D0000000E8100001E0000001F810000260000000B8100001F0000002D9200000F000000D18400000C00000005810000190000000D8100002100000002E100003300000035E10000400000002C9200000E000000</MenuUserImages>
</CommandManager>
<Pane-59393>
<ID>0</ID>
@ -340,7 +341,7 @@
</BasePane-34049>
<MFCToolBar-34050>
<Name>Main</Name>
<Buttons>00200000010000002000FFFF01001100434D4643546F6F6C426172427574746F6E00E100000000000031000000FFFEFF000000000000000000000000000100000001000000018001E100000000000032000000FFFEFF000000000000000000000000000100000001000000018003E100000000040034000000FFFEFF0000000000000000000000000001000000010000000180008100000000000015000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF000000000000000000000000000100000001000000018007E100000000040037000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF000000000000000000000000000100000001000000018023E100000000040039000000FFFEFF000000000000000000000000000100000001000000018022E100000000000038000000FFFEFF000000000000000000000000000100000001000000018025E10000000004003B000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF00000000000000000000000000010000000100000001802BE10000000004003E000000FFFEFF00000000000000000000000000010000000100000001802CE10000000004003F000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF000000000000000000000000000100000001000000FFFF01001900434D4643546F6F6C426172436F6D626F426F78427574746F6E4281000000000400FFFFFFFFFFFEFF0000000000000000000100000000000000010000007800000002002050FFFFFFFFFFFEFF00960000000000000000000180218100000000040028000000FFFEFF000000000000000000000000000100000001000000018024E10000000004003A000000FFFEFF000000000000000000000000000100000001000000018028E10000000004003C000000FFFEFF000000000000000000000000000100000001000000018029E10000000004003D000000FFFEFF0000000000000000000000000001000000010000000180028100000000040017000000FFFEFF000000000000000000000000000100000001000000018029810000000004002C000000FFFEFF000000000000000000000000000100000001000000018027810000000004002A000000FFFEFF000000000000000000000000000100000001000000018028810000000004002B000000FFFEFF00000000000000000000000000010000000100000001801D8100000000040024000000FFFEFF00000000000000000000000000010000000100000001801E8100000000040025000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF00000000000000000000000000010000000100000001800B810000000004001B000000FFFEFF00000000000000000000000000010000000100000001800C810000000000001C000000FFFEFF00000000000000000000000000010000000100000001805F8600000000000030000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF00000000000000000000000000010000000100000001800E810000000000001E000000FFFEFF00000000000000000000000000010000000100000001800F810000000000001F000000FFFEFF00000000000000000000000000010000000100000000000000FFFEFF044D00610069006E00E8020000</Buttons>
<Buttons>00200000010000002000FFFF01001100434D4643546F6F6C426172427574746F6E00E100000000000031000000FFFEFF000000000000000000000000000100000001000000018001E100000000000032000000FFFEFF000000000000000000000000000100000001000000018003E100000000000034000000FFFEFF0000000000000000000000000001000000010000000180008100000000000015000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF000000000000000000000000000100000001000000018007E100000000000037000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF000000000000000000000000000100000001000000018023E100000000040039000000FFFEFF000000000000000000000000000100000001000000018022E100000000040038000000FFFEFF000000000000000000000000000100000001000000018025E10000000000003B000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF00000000000000000000000000010000000100000001802BE10000000004003E000000FFFEFF00000000000000000000000000010000000100000001802CE10000000004003F000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF000000000000000000000000000100000001000000FFFF01001900434D4643546F6F6C426172436F6D626F426F78427574746F6E4281000000000000FFFFFFFFFFFEFF0001000000000000000100000000000000010000007800000002002050FFFFFFFFFFFEFF00960000000000000000000180218100000000040028000000FFFEFF000000000000000000000000000100000001000000018024E10000000000003A000000FFFEFF000000000000000000000000000100000001000000018028E10000000004003C000000FFFEFF000000000000000000000000000100000001000000018029E10000000000003D000000FFFEFF0000000000000000000000000001000000010000000180028100000000000017000000FFFEFF000000000000000000000000000100000001000000018029810000000000002C000000FFFEFF000000000000000000000000000100000001000000018027810000000000002A000000FFFEFF000000000000000000000000000100000001000000018028810000000000002B000000FFFEFF00000000000000000000000000010000000100000001801D8100000000000024000000FFFEFF00000000000000000000000000010000000100000001801E8100000000040025000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF00000000000000000000000000010000000100000001800B810000000000001B000000FFFEFF00000000000000000000000000010000000100000001800D810000000000001D000000FFFEFF00000000000000000000000000010000000100000001805F8600000000000030000000FFFEFF00000000000000000000000000010000000100000001800000000001000000FFFFFFFFFFFEFF00000000000000000000000000010000000100000001800E810000000000001E000000FFFEFF00000000000000000000000000010000000100000001800F810000000000001F000000FFFEFF00000000000000000000000000010000000100000000000000FFFEFF044D00610069006E00E8020000</Buttons>
</MFCToolBar-34050>
<Pane-34050>
<ID>34050</ID>
@ -378,7 +379,7 @@
</ChildIdMap>
<MDIWindows>
<MDIClientArea-0>
<MDITabsState>010000000300000001000000000000000000000001000000010000000200000000000000010000000100000000000000280000002800000001000000020000000100000001000000FFFEFF2A2400570053005F0044004900520024005C006C0069006E006B00650072005C0062006F006F0074006C006F0061006400650072005F006D0030003100340036005F0066006C006100730068002E0069006300660001000000FFFF010014004966436F6E74656E7453746F72616765496D706CFFFEFF00FFFEFFFF24013C003F0078006D006C002000760065007200730069006F006E003D00220031002E0030002200200065006E0063006F00640069006E0067003D0022005500540046002D00380022003F003E000A003C0052006F006F0074003E000A0020002000200020003C004E0075006D0052006F00770073003E0031003C002F004E0075006D0052006F00770073003E000A0020002000200020003C004E0075006D0043006F006C0073003E0031003C002F004E0075006D0043006F006C0073003E000A0020002000200020003C00580050006F0073003E0030003C002F00580050006F0073003E000A0020002000200020003C00590050006F0073003E0030003C002F00590050006F0073003E000A0020002000200020003C00530065006C00530074006100720074003E0030003C002F00530065006C00530074006100720074003E000A0020002000200020003C00530065006C0045006E0064003E0030003C002F00530065006C0045006E0064003E000A0020002000200020003C00580050006F00730032003E0030003C002F00580050006F00730032003E000A0020002000200020003C00590050006F00730032003E0030003C002F00590050006F00730032003E000A0020002000200020003C00530065006C005300740061007200740032003E003300340034003C002F00530065006C005300740061007200740032003E000A0020002000200020003C00530065006C0045006E00640032003E003300340034003C002F00530065006C0045006E00640032003E000A003C002F0052006F006F0074003E000A00FFFEFF1A62006F006F0074006C006F0061006400650072005F006D0030003100340036005F0066006C006100730068002E0069006300660000000000FFFFFFFFFFFFFFFFFFFEFF132400570053005F0044004900520024005C007300720063005C006D00610069006E002E006300010000000180FFFEFF00FFFEFFFF2A013C003F0078006D006C002000760065007200730069006F006E003D00220031002E0030002200200065006E0063006F00640069006E0067003D0022005500540046002D00380022003F003E000A003C0052006F006F0074003E000A0020002000200020003C004E0075006D0052006F00770073003E0031003C002F004E0075006D0052006F00770073003E000A0020002000200020003C004E0075006D0043006F006C0073003E0031003C002F004E0075006D0043006F006C0073003E000A0020002000200020003C00580050006F0073003E0030003C002F00580050006F0073003E000A0020002000200020003C00590050006F0073003E0030003C002F00590050006F0073003E000A0020002000200020003C00530065006C00530074006100720074003E0030003C002F00530065006C00530074006100720074003E000A0020002000200020003C00530065006C0045006E0064003E0030003C002F00530065006C0045006E0064003E000A0020002000200020003C00580050006F00730032003E0030003C002F00580050006F00730032003E000A0020002000200020003C00590050006F00730032003E003700370032003C002F00590050006F00730032003E000A0020002000200020003C00530065006C005300740061007200740032003E00320031003900380033003C002F00530065006C005300740061007200740032003E000A0020002000200020003C00530065006C0045006E00640032003E00320031003900380033003C002F00530065006C0045006E00640032003E000A003C002F0052006F006F0074003E000A00FFFEFF066D00610069006E002E00630000000000FFFFFFFFFFFFFFFF0000000010000000C5D4F200FFDC7800BECEA100F0A0A100BCA8E1009CC1B600F7B88600D9ADC200A5C2D700B3A6BE00EAD6A300F6FA7D00B5E99D005FC3CF00C1838300CACAD50001000000010000000200000043010000490000000006000019020000</MDITabsState>
<MDITabsState>010000000300000001000000000000000000000001000000010000000200000000000000010000000100000000000000280000002800000001000000030000000200000001000000FFFEFF2A2400570053005F0044004900520024005C006C0069006E006B00650072005C0062006F006F0074006C006F0061006400650072005F006D0030003100340036005F0066006C006100730068002E0069006300660001000000FFFF010014004966436F6E74656E7453746F72616765496D706CFFFEFF00FFFEFFFF24013C003F0078006D006C002000760065007200730069006F006E003D00220031002E0030002200200065006E0063006F00640069006E0067003D0022005500540046002D00380022003F003E000A003C0052006F006F0074003E000A0020002000200020003C004E0075006D0052006F00770073003E0031003C002F004E0075006D0052006F00770073003E000A0020002000200020003C004E0075006D0043006F006C0073003E0031003C002F004E0075006D0043006F006C0073003E000A0020002000200020003C00580050006F0073003E0030003C002F00580050006F0073003E000A0020002000200020003C00590050006F0073003E0030003C002F00590050006F0073003E000A0020002000200020003C00530065006C00530074006100720074003E0030003C002F00530065006C00530074006100720074003E000A0020002000200020003C00530065006C0045006E0064003E0030003C002F00530065006C0045006E0064003E000A0020002000200020003C00580050006F00730032003E0030003C002F00580050006F00730032003E000A0020002000200020003C00590050006F00730032003E0030003C002F00590050006F00730032003E000A0020002000200020003C00530065006C005300740061007200740032003E003300340034003C002F00530065006C005300740061007200740032003E000A0020002000200020003C00530065006C0045006E00640032003E003300340034003C002F00530065006C0045006E00640032003E000A003C002F0052006F006F0074003E000A00FFFEFF1A62006F006F0074006C006F0061006400650072005F006D0030003100340036005F0066006C006100730068002E0069006300660000000000FFFFFFFFFFFFFFFFFFFEFF132400570053005F0044004900520024005C007300720063005C006D00610069006E002E006300010000000180FFFEFF00FFFEFFFF2A013C003F0078006D006C002000760065007200730069006F006E003D00220031002E0030002200200065006E0063006F00640069006E0067003D0022005500540046002D00380022003F003E000A003C0052006F006F0074003E000A0020002000200020003C004E0075006D0052006F00770073003E0031003C002F004E0075006D0052006F00770073003E000A0020002000200020003C004E0075006D0043006F006C0073003E0031003C002F004E0075006D0043006F006C0073003E000A0020002000200020003C00580050006F0073003E0030003C002F00580050006F0073003E000A0020002000200020003C00590050006F0073003E0030003C002F00590050006F0073003E000A0020002000200020003C00530065006C00530074006100720074003E0030003C002F00530065006C00530074006100720074003E000A0020002000200020003C00530065006C0045006E0064003E0030003C002F00530065006C0045006E0064003E000A0020002000200020003C00580050006F00730032003E0030003C002F00580050006F00730032003E000A0020002000200020003C00590050006F00730032003E003500310035003C002F00590050006F00730032003E000A0020002000200020003C00530065006C005300740061007200740032003E00310034003400320039003C002F00530065006C005300740061007200740032003E000A0020002000200020003C00530065006C0045006E00640032003E00310034003400320039003C002F00530065006C0045006E00640032003E000A003C002F0052006F006F0074003E000A00FFFEFF066D00610069006E002E00630000000000FFFFFFFFFFFFFFFFFFFEFF342400570053005F0044004900520024005C007300720063005C0070007200690076006100740065005F006400720069007600650072005C007500640073005C0075007300650072005C007500640073005F007300650072007600690063006500320037002E006300010000000180FFFEFF00FFFEFFFF27013C003F0078006D006C002000760065007200730069006F006E003D00220031002E0030002200200065006E0063006F00640069006E0067003D0022005500540046002D00380022003F003E000A003C0052006F006F0074003E000A0020002000200020003C004E0075006D0052006F00770073003E0031003C002F004E0075006D0052006F00770073003E000A0020002000200020003C004E0075006D0043006F006C0073003E0031003C002F004E0075006D0043006F006C0073003E000A0020002000200020003C00580050006F0073003E0030003C002F00580050006F0073003E000A0020002000200020003C00590050006F0073003E0030003C002F00590050006F0073003E000A0020002000200020003C00530065006C00530074006100720074003E0030003C002F00530065006C00530074006100720074003E000A0020002000200020003C00530065006C0045006E0064003E0030003C002F00530065006C0045006E0064003E000A0020002000200020003C00580050006F00730032003E0030003C002F00580050006F00730032003E000A0020002000200020003C00590050006F00730032003E00380035003C002F00590050006F00730032003E000A0020002000200020003C00530065006C005300740061007200740032003E0033003700330036003C002F00530065006C005300740061007200740032003E000A0020002000200020003C00530065006C0045006E00640032003E0033003700330036003C002F00530065006C0045006E00640032003E000A003C002F0052006F006F0074003E000A00FFFEFF0F7500640073005F007300650072007600690063006500320037002E00630000000000FFFFFFFFFFFFFFFF0000000010000000C5D4F200FFDC7800BECEA100F0A0A100BCA8E1009CC1B600F7B88600D9ADC200A5C2D700B3A6BE00EAD6A300F6FA7D00B5E99D005FC3CF00C1838300CACAD50001000000010000000200000043010000490000000006000019020000</MDITabsState>
</MDIClientArea-0>
</MDIWindows>
</WindowStorage>

View File

@ -521,6 +521,15 @@ static int8_t FlexCanBoot_TxMessage(uint32_t msgId, const uint8_t *pData, uint8_
return 0;
}
static uint8_t testdata[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
void TxTestMsg (uint8_t * data)
{
for (uint8_t i = 0; i < 8; i++)
{
testdata[i] = data[i];
}
FlexCanBoot_TxMessage(UDS_TEXT_TX_MSG_ID,testdata,8);
}
void FlexCanBoot_Init(void)
{
@ -728,7 +737,7 @@ static void Bootloader_SetGlobalIsr(bool isEnabled)
}
}
uint8_t testdata[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
int main(void)
{
FlexCan_FrameStructureType rxMsg;

View File

@ -69,7 +69,7 @@ extern "C" {
#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_09 (0x09)
#define UDS_SA_LEVEL_63 (0x63)
#define UDS_SESSION_DEFAULT (0x01)
@ -187,7 +187,7 @@ struct _UdsType_
/*******************************************************************************
* the function prototypes
******************************************************************************/
extern void TxTestMsg (uint8_t * data);
/*! \brief Initializes the UDS object.
*/
extern void Uds_Init(UdsType *obj, const Uds_ParamsType *pParams);

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