initial commit

This commit is contained in:
2022-10-23 23:45:43 -07:00
commit e190fa5193
6450 changed files with 8626944 additions and 0 deletions
@@ -0,0 +1,53 @@
/*************************************************************************************************/
/*!
* \file wsf_assert.c
*
* \brief Assert implementation.
*
* $Date: 2014-04-17 16:13:59 -0700 (Thu, 17 Apr 2014) $
* $Revision: 1398 $
*
* Copyright (c) 2009 Wicentric, Inc., all rights reserved.
* Wicentric confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact Wicentric, Inc. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#include "wsf_types.h"
#include "wsf_assert.h"
#include "wsf_os.h"
/*************************************************************************************************/
/*!
* \def WsfAssert
*
* \brief Perform an assert action.
*
* \param pFile Name of file originating assert.
* \param line Line number of assert statement.
*/
/*************************************************************************************************/
void WsfAssert(const char *pFile, uint16_t line)
{
volatile uint8_t escape=0;
/* spin forever if fatal error occurred */
for(;;)
{
/*
* However, you can exit with a debugger by setting variable 'escape'.
* Handy to see where the assert happened if you cannot view the call stack.
*/
if (escape)
{
break;
}
}
}
@@ -0,0 +1,71 @@
/*************************************************************************************************/
/*!
* \file wsf_assert.h
*
* \brief Assert macro.
*
* $Date: 2011-10-14 21:35:03 -0700 (Fri, 14 Oct 2011) $
* $Revision: 191 $
*
* Copyright (c) 2009 Wicentric, Inc., all rights reserved.
* Wicentric confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact Wicentric, Inc. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#ifndef WSF_ASSERT_H
#define WSF_ASSERT_H
#ifdef __cplusplus
extern "C" {
#endif
/**************************************************************************************************
Function Prototypes
**************************************************************************************************/
void WsfAssert(const char *pFile, uint16_t line);
/**************************************************************************************************
Macros
**************************************************************************************************/
/*************************************************************************************************/
/*!
* \def WSF_ASSERT
*
* \brief Run-time assert macro. The assert executes when the expression is FALSE.
*
* \param expr Boolean expression to be tested.
*/
/*************************************************************************************************/
#if WSF_ASSERT_ENABLED == TRUE
#define WSF_ASSERT(expr) if (!(expr)) {WsfAssert(__FILE__, (uint16_t) __LINE__);}
#else
#define WSF_ASSERT(expr)
#endif
/*************************************************************************************************/
/*!
* \def WSF_CT_ASSERT
*
* \brief Compile-time assert macro. This macro causes a compiler error when the
* expression is FALSE. Note that this macro is generally used at file scope to
* test constant expressions. Errors may result of it is used in executing code.
*
* \param expr Boolean expression to be tested.
*/
/*************************************************************************************************/
#define WSF_CT_ASSERT(expr) extern char wsf_ct_assert[(expr) ? 1 : -1]
#ifdef __cplusplus
};
#endif
#endif /* WSF_ASSERT_H */
@@ -0,0 +1,484 @@
/*************************************************************************************************/
/*!
* \file wsf_buf.c
*
* \brief Buffer pool service.
*
* $Date: 2017-03-04 13:45:34 -0600 (Sat, 04 Mar 2017) $
* $Revision: 11379 $
*
* Copyright (c) 2009-2017 ARM Ltd., all rights reserved.
* ARM Ltd. confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact ARM Ltd. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#include "wsf_types.h"
#include "wsf_buf.h"
#include "wsf_assert.h"
#include "wsf_math.h"
#include "wsf_trace.h"
#include "wsf_cs.h"
/**************************************************************************************************
Configuration
**************************************************************************************************/
/* check if trying to free a buffer that is already free */
#ifndef WSF_BUF_FREE_CHECK
#define WSF_BUF_FREE_CHECK TRUE
#endif
/* assert on best-fit buffer allocation failure */
#ifndef WSF_BUF_ALLOC_BEST_FIT_FAIL_ASSERT
#define WSF_BUF_ALLOC_BEST_FIT_FAIL_ASSERT FALSE
#endif
/* assert on buffer allocation failure */
#ifndef WSF_BUF_ALLOC_FAIL_ASSERT
#define WSF_BUF_ALLOC_FAIL_ASSERT TRUE
#endif
/* buffer allocation stats */
#ifndef WSF_BUF_STATS
#define WSF_BUF_STATS FALSE
#endif
/* buffer histogram stats */
#ifndef WSF_BUF_STATS_HIST
#define WSF_BUF_STATS_HIST FALSE
#endif
/**************************************************************************************************
Macros
**************************************************************************************************/
/* magic number used to check for free buffer */
#define WSF_BUF_FREE_NUM 0xFAABD00D
/**************************************************************************************************
Data Types
**************************************************************************************************/
/* Unit of memory storage-- a structure containing a pointer */
typedef struct wsfBufMem_tag
{
struct wsfBufMem_tag *pNext;
#if WSF_BUF_FREE_CHECK == TRUE
uint32_t free;
#endif
} wsfBufMem_t;
/* Internal buffer pool */
typedef struct
{
wsfBufPoolDesc_t desc; /* number of buffers and length */
wsfBufMem_t *pStart; /* start of pool */
wsfBufMem_t *pFree; /* first free buffer in pool */
#if WSF_BUF_STATS == TRUE
uint8_t numAlloc; /* number of buffers currently allocated from pool */
uint8_t maxAlloc; /* maximum buffers ever allocated from pool */
uint16_t maxReqLen; /* maximum request length from pool. */
#endif
} wsfBufPool_t;
/**************************************************************************************************
Global Variables
**************************************************************************************************/
/* Number of pools */
uint8_t wsfBufNumPools;
/* Memory used for pools */
wsfBufMem_t *wsfBufMem = NULL;
/* Currently use for debugging only */
uint16_t wsfBufMemLen;
#if WSF_BUF_STATS_HIST == TRUE
/* Buffer allocation counter */
uint8_t wsfBufAllocCount[WSF_BUF_STATS_MAX_LEN];
#endif
#if WSF_OS_DIAG == TRUE
/* WSF buffer diagnostic callback function */
static wsfBufDiagCback_t wsfBufDiagCback = NULL;
#endif
/*************************************************************************************************/
/*!
* \fn WsfBufInit
*
* \brief Initialize the buffer pool service. This function should only be called once
* upon system initialization.
*
* \param bufMemLen Length of free memory
* \param pBufMem Free memory buffer for building buffer pools
* \param numPools Number of buffer pools.
* \param pDesc Array of buffer pool descriptors, one for each pool.
*
* \return Amount of pBufMem used or 0 for failures.
*/
/*************************************************************************************************/
uint16_t WsfBufInit(uint16_t bufMemLen, uint8_t *pBufMem, uint8_t numPools, wsfBufPoolDesc_t *pDesc)
{
wsfBufPool_t *pPool;
wsfBufMem_t *pStart;
uint16_t len;
uint8_t i;
wsfBufMem = (wsfBufMem_t *) pBufMem;
pPool = (wsfBufPool_t *) wsfBufMem;
/* buffer storage starts after the pool structs */
pStart = (wsfBufMem_t *) (pPool + numPools);
wsfBufNumPools = numPools;
/* create each pool; see loop exit condition below */
while (TRUE)
{
/* verify we didn't overrun memory; if we did, abort */
if (pStart > &wsfBufMem[bufMemLen / sizeof(wsfBufMem_t)])
{
WSF_ASSERT(FALSE);
return 0;
}
/* exit loop after verification check */
if (numPools-- == 0)
{
break;
}
/* adjust pool lengths for minimum size and alignment */
if (pDesc->len < sizeof(wsfBufMem_t))
{
pPool->desc.len = sizeof(wsfBufMem_t);
}
else if ((pDesc->len % sizeof(wsfBufMem_t)) != 0)
{
pPool->desc.len = pDesc->len + sizeof(wsfBufMem_t) - (pDesc->len % sizeof(wsfBufMem_t));
}
else
{
pPool->desc.len = pDesc->len;
}
pPool->desc.num = pDesc->num;
pDesc++;
pPool->pStart = pStart;
pPool->pFree = pStart;
#if WSF_BUF_STATS == TRUE
pPool->numAlloc = 0;
pPool->maxAlloc = 0;
pPool->maxReqLen = 0;
#endif
WSF_TRACE_INFO2("Creating pool len=%u num=%u", pPool->desc.len, pPool->desc.num);
WSF_TRACE_INFO1(" pStart=0x%x", (uint32_t)pPool->pStart);
/* initialize free list */
len = pPool->desc.len / sizeof(wsfBufMem_t);
for (i = pPool->desc.num; i > 1; i--)
{
/* verify we didn't overrun memory; if we did, abort */
if (pStart > &wsfBufMem[bufMemLen / sizeof(wsfBufMem_t)])
{
WSF_ASSERT(FALSE);
return 0;
}
/* pointer to the next free buffer is stored in the buffer itself */
pStart->pNext = pStart + len;
pStart += len;
}
/* verify we didn't overrun memory; if we did, abort */
if (pStart > &wsfBufMem[bufMemLen / sizeof(wsfBufMem_t)])
{
WSF_ASSERT(FALSE);
return 0;
}
/* last one in list points to NULL */
pStart->pNext = NULL;
pStart += len;
/* next pool */
pPool++;
}
wsfBufMemLen = (uint8_t *) pStart - (uint8_t *) wsfBufMem;
WSF_TRACE_INFO1("Created buffer pools; using %u bytes", wsfBufMemLen);
return wsfBufMemLen;
}
/*************************************************************************************************/
/*!
* \fn WsfBufAlloc
*
* \brief Allocate a buffer.
*
* \param len Length of buffer to allocate.
*
* \return Pointer to allocated buffer or NULL if allocation fails.
*/
/*************************************************************************************************/
void *WsfBufAlloc(uint16_t len)
{
wsfBufPool_t *pPool;
wsfBufMem_t *pBuf;
uint8_t i;
WSF_CS_INIT(cs);
WSF_ASSERT(len > 0);
pPool = (wsfBufPool_t *) wsfBufMem;
for (i = wsfBufNumPools; i > 0; i--, pPool++)
{
/* if buffer is big enough */
if (len <= pPool->desc.len)
{
/* enter critical section */
WSF_CS_ENTER(cs);
/* if buffers available */
if (pPool->pFree != NULL)
{
/* allocation succeeded */
pBuf = pPool->pFree;
/* next free buffer is stored inside current free buffer */
pPool->pFree = pBuf->pNext;
#if WSF_BUF_FREE_CHECK == TRUE
pBuf->free = 0;
#endif
#if WSF_BUF_STATS_HIST == TRUE
/* increment count for buffers of this length */
if (len < WSF_BUF_STATS_MAX_LEN)
{
wsfBufAllocCount[len]++;
}
else
{
wsfBufAllocCount[0]++;
}
#endif
#if WSF_BUF_STATS == TRUE
if (++pPool->numAlloc > pPool->maxAlloc)
{
pPool->maxAlloc = pPool->numAlloc;
}
pPool->maxReqLen = WSF_MAX(pPool->maxReqLen, len);
#endif
/* exit critical section */
WSF_CS_EXIT(cs);
WSF_TRACE_ALLOC2("WsfBufAlloc len:%u pBuf:%08x", pPool->desc.len, pBuf);
return pBuf;
}
/* exit critical section */
WSF_CS_EXIT(cs);
#if WSF_BUF_ALLOC_BEST_FIT_FAIL_ASSERT == TRUE
WSF_ASSERT(FALSE);
#endif
}
}
/* allocation failed */
#if WSF_OS_DIAG == TRUE
if (wsfBufDiagCback != NULL)
{
WsfBufDiag_t info;
info.type = WSF_BUF_ALLOC_FAILED;
info.param.alloc.taskId = WSF_OS_GET_ACTIVE_HANDLER_ID();
info.param.alloc.len = len;
wsfBufDiagCback(&info);
}
else
{
WSF_TRACE_WARN2("WsfBufAlloc failed len:%u - task:%u", len, WSF_OS_GET_ACTIVE_HANDLER_ID());
}
#else
WSF_TRACE_WARN1("WsfBufAlloc failed len:%u", len);
#endif
#if WSF_BUF_ALLOC_FAIL_ASSERT == TRUE
WSF_ASSERT(FALSE);
#endif
return NULL;
}
/*************************************************************************************************/
/*!
* \fn WsfBufFree
*
* \brief Free a buffer.
*
* \param pBuf Buffer to free.
*
* \return None.
*/
/*************************************************************************************************/
void WsfBufFree(void *pBuf)
{
wsfBufPool_t *pPool;
wsfBufMem_t *p = pBuf;
WSF_CS_INIT(cs);
/* verify pointer is within range */
#if WSF_BUF_FREE_CHECK == TRUE
WSF_ASSERT(p >= ((wsfBufPool_t *) wsfBufMem)->pStart);
WSF_ASSERT(p < (wsfBufMem_t *)(((uint8_t *) wsfBufMem) + wsfBufMemLen));
#endif
/* iterate over pools starting from last pool */
pPool = (wsfBufPool_t *) wsfBufMem + (wsfBufNumPools - 1);
while (pPool >= (wsfBufPool_t *) wsfBufMem)
{
/* if the buffer memory is located inside this pool */
if (p >= pPool->pStart)
{
/* enter critical section */
WSF_CS_ENTER(cs);
#if WSF_BUF_FREE_CHECK == TRUE
WSF_ASSERT(p->free != WSF_BUF_FREE_NUM);
p->free = WSF_BUF_FREE_NUM;
#endif
#if WSF_BUF_STATS == TRUE
pPool->numAlloc--;
#endif
/* pool found; put buffer back in free list */
p->pNext = pPool->pFree;
pPool->pFree = p;
/* exit critical section */
WSF_CS_EXIT(cs);
WSF_TRACE_FREE2("WsfBufFree len:%u pBuf:%08x", pPool->desc.len, pBuf);
return;
}
/* next pool */
pPool--;
}
/* should never get here */
WSF_ASSERT(FALSE);
return;
}
/*************************************************************************************************/
/*!
* \fn WsfBufGetAllocStats
*
* \brief Diagnostic function to get the buffer allocation statistics.
*
* \return Buffer allocation statistics array.
*/
/*************************************************************************************************/
uint8_t *WsfBufGetAllocStats(void)
{
#if WSF_BUF_STATS_HIST == TRUE
return wsfBufAllocCount;
#else
return NULL;
#endif
}
/*************************************************************************************************/
/*!
* \fn WsfBufGetNumPool
*
* \brief Get number of pools.
*
* \return Number of pools.
*/
/*************************************************************************************************/
uint8_t WsfBufGetNumPool(void)
{
return wsfBufNumPools;
}
/*************************************************************************************************/
/*!
* \fn WsfBufGetPoolStats
*
* \brief Get statistics for each pool.
*
* \param pBuf Buffer to store the statistics.
* \param poolId Pool ID.
*
* \return None.
*/
/*************************************************************************************************/
void WsfBufGetPoolStats(WsfBufPoolStat_t *pStat, uint8_t poolId)
{
wsfBufPool_t *pPool;
if (poolId >= wsfBufNumPools)
{
pStat->bufSize = 0;
return;
}
WSF_CS_INIT(cs);
WSF_CS_ENTER(cs);
pPool = (wsfBufPool_t *) wsfBufMem;
pStat->bufSize = pPool[poolId].desc.len;
pStat->numBuf = pPool[poolId].desc.num;
#if WSF_BUF_STATS == TRUE
pStat->numAlloc = pPool[poolId].numAlloc;
pStat->maxAlloc = pPool[poolId].maxAlloc;
pStat->maxReqLen = pPool[poolId].maxReqLen;
#else
pStat->numAlloc = 0;
pStat->maxAlloc = 0;
pStat->maxReqLen = 0;
#endif
/* exit critical section */
WSF_CS_EXIT(cs);
}
/*************************************************************************************************/
/*!
* \fn WsfBufDiagRegister
*
* \brief Called to register the buffer diagnostics callback function.
*
* \param pCallback Pointer to the callback function.
*
* \return None.
*/
/*************************************************************************************************/
void WsfBufDiagRegister(wsfBufDiagCback_t callback)
{
#if WSF_OS_DIAG == TRUE
wsfBufDiagCback = callback;
#endif
}
@@ -0,0 +1,78 @@
/*************************************************************************************************/
/*!
* \file wsf_cs.h
*
* \brief Critical section macros.
*
* $Date: 2012-11-20 00:27:38 -0800 (Tue, 20 Nov 2012) $
* $Revision: 377 $
*
* Copyright (c) 2009 Wicentric, Inc., all rights reserved.
* Wicentric confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact Wicentric, Inc. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#ifndef WSF_CS_H
#define WSF_CS_H
#include "wsf_os.h"
#ifdef __cplusplus
extern "C" {
#endif
/**************************************************************************************************
Macros
**************************************************************************************************/
/*************************************************************************************************/
/*!
* \def WSF_CS_INIT
*
* \brief Initialize critical section. This macro may define a variable.
*
* \param cs Critical section variable to be defined.
*/
/*************************************************************************************************/
#define WSF_CS_INIT(cs)
/*************************************************************************************************/
/*!
* \def WSF_CS_ENTER
*
* \brief Enter a critical section.
*
* \param cs Critical section variable.
*/
/*************************************************************************************************/
#define WSF_CS_ENTER(cs) WsfCsEnter()
/*************************************************************************************************/
/*!
* \def WSF_CS_EXIT
*
* \brief Exit a critical section.
*
* \param cs Critical section variable.
*/
/*************************************************************************************************/
#define WSF_CS_EXIT(cs) WsfCsExit()
/**************************************************************************************************
Function Declarations
**************************************************************************************************/
void WsfCsEnter(void);
void WsfCsExit(void);
#ifdef __cplusplus
};
#endif
#endif /* WSF_CS_H */
@@ -0,0 +1,681 @@
/*************************************************************************************************/
/*!
* \file wsf_efs.c
*
* \brief Embedded File System service.
*
* $Date: 2017-03-09 12:18:38 -0600 (Thu, 09 Mar 2017) $
* $Revision: 11460 $
*
* Copyright (c) 2014-2017 ARM Ltd., all rights reserved.
* ARM Ltd. confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact ARM Ltd. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#include <string.h>
#include "wsf_types.h"
#include "wsf_efs.h"
#include "wsf_assert.h"
#include "wsf_trace.h"
#include "wsf_cs.h"
#include "bstream.h"
/* Media Control Block */
static pWsfEfsMedia_t wsfEfsMediaTbl[WSF_EFS_MAX_MEDIA];
/* File Control Block */
static wsfEfsControl_t wsfEfsFileTbl[WSF_EFS_MAX_FILES];
/*************************************************************************************************/
/*!
* \fn wsfEfsMediaValid
*
* \brief Checks if the given physical media identifier has been registered with the file system.
*
* \param media The physical media identifier
*
* \return TRUE if valid, else FALSE.
*/
/*************************************************************************************************/
static bool_t wsfEfsMediaValid(uint8_t media)
{
if (media < WSF_EFS_MAX_MEDIA && wsfEfsMediaTbl[media])
{
return TRUE;
}
return FALSE;
}
/*************************************************************************************************/
/*!
* \fn WsfEfsGetFileByHandle
*
* \brief Returns the file control block for the given handle.
*
* \param handle Handle of the file
*
* \return File control block, or NULL.
*/
/*************************************************************************************************/
wsfEfsControl_t *WsfEfsGetFileByHandle(wsfEfsHandle_t handle)
{
if ((handle < WSF_EFS_MAX_FILES) &&
(wsfEfsFileTbl[handle].maxSize != WSF_EFS_INVALID_SIZE))
{
return &wsfEfsFileTbl[handle];
}
return NULL;
}
/*************************************************************************************************/
/*!
* \fn wsfEfsFileOverlap
*
* \brief Checks if the given offset and size overlaps with a given file.
*
* \param handle The handle of the file to check against
* \param media The physical medium the new file will be in
* \param address The starting address in the physical medium
* \param size The max size of the file
*
* \return TRUE if overlap, else FALSE.
*/
/*************************************************************************************************/
static bool_t wsfEfsFileOverlap(wsfEfsHandle_t handle, uint8_t media, uint32_t address, uint32_t size)
{
if (wsfEfsMediaValid(media))
{
/* Check if the table entry is in use and the physical media are the same */
if (size && (wsfEfsFileTbl[handle].maxSize) &&
(wsfEfsFileTbl[handle].maxSize != WSF_EFS_INVALID_SIZE) &&
(wsfEfsFileTbl[handle].media == media))
{
/* Calculate the top and bottom addresses of the files */
uint32_t top1 = wsfEfsFileTbl[handle].address;
uint32_t bottom1 = wsfEfsFileTbl[handle].address + wsfEfsFileTbl[handle].maxSize - 1;
uint32_t top2 = address;
uint32_t bottom2 = address + size - 1;
/* Check for overlap */
if ((top2 >= top1) && (top2 <= bottom1))
return TRUE;
if ((bottom2 >= top1) && (bottom2 <= bottom1))
return TRUE;
}
}
return FALSE;
}
/*************************************************************************************************/
/*!
* \fn wsfEfsFindAvailableOffset
*
* \brief Finds the offset of an unused area of the physical media big enough for a file
* of the given size.
*
* \param media The physical medium
* \param size The max size of the file
*
* \return The next available offset.
*/
/*************************************************************************************************/
static uint32_t wsfEfsFindAvailableOffset(uint8_t media, uint32_t size)
{
if (wsfEfsMediaValid(media))
{
int8_t i;
uint32_t address = wsfEfsMediaTbl[media]->startAddress;
for (i=0; i<WSF_EFS_MAX_FILES; i++)
{
if (wsfEfsFileOverlap(i, media, address, size))
{
/* The offset overlaps another file. Move the offset to the end of the overlapping */
/* file and retest. */
address = wsfEfsFileTbl[i].address + wsfEfsFileTbl[i].maxSize;
address += address % wsfEfsMediaTbl[media]->pageSize;
i = -1;
if (address + size > wsfEfsMediaTbl[media]->endAddress)
return WSF_EFS_INVALID_OFFSET;
}
}
return address;
}
return WSF_EFS_INVALID_OFFSET;
}
/*************************************************************************************************/
/*!
* \fn WsfEfsInit
*
* \brief Initialize the embedded file system.
*
* \return none.
*/
/*************************************************************************************************/
void WsfEfsInit(void)
{
int8_t i;
/* Clear control structures */
memset((void *) wsfEfsMediaTbl, 0, sizeof(wsfEfsMediaTbl));
/* Set maxSize to invalid indicating file is unused */
for (i=0; i<WSF_EFS_MAX_FILES; i++)
{
wsfEfsFileTbl[i].maxSize = WSF_EFS_INVALID_SIZE;
}
}
/*************************************************************************************************/
/*!
* \fn WsfEfsAddFile
*
* \brief Create a file in the embedded file system.
*
* \param maxSize Number of bytes to reserve for the file.
* \param media Identifier of the media where the file is stored.
* \param pAttr Attributes of the file
* \param offset Offset address of the file in the memory space.
*
* \return File Handle, or WSF_EFS_INVALID_HANDLE if the operation failed.
*/
/*************************************************************************************************/
wsfEfsHandle_t WsfEfsAddFile(uint32_t maxSize, uint8_t media, wsfEsfAttributes_t *pAttr, uint32_t offset)
{
wsfEfsHandle_t handle;
uint32_t address = offset;
wsfEfsControl_t *pFile = NULL;
if (wsfEfsMediaValid(media))
{
/* Find an available slot in the file table (wsfEfsFileTbl) */
for (handle = 0; handle < WSF_EFS_MAX_FILES; handle++)
{
if (wsfEfsFileTbl[handle].maxSize == WSF_EFS_INVALID_SIZE)
{
pFile = &wsfEfsFileTbl[handle];
break;
}
}
if (pFile)
{
if (address == WSF_EFS_FILE_OFFSET_ANY)
{
address = wsfEfsFindAvailableOffset(media, maxSize);
if (address == WSF_EFS_INVALID_OFFSET)
return WSF_EFS_INVALID_HANDLE;
}
else
{
int i;
/* The user specifies a zero based offset when adding a file */
/* This offset must be incremented by the media StartAddress */
/* to become the file's address in the wsfEfsMediaTbl. */
address += wsfEfsMediaTbl[media]->startAddress;
/* Increment the address to a page boundry */
if (wsfEfsMediaTbl[media]->pageSize)
{
address += address % wsfEfsMediaTbl[media]->pageSize;
}
/* Verify the given offset doesn't overlap another file */
for (i=0; i<WSF_EFS_MAX_FILES; i++)
{
if (wsfEfsFileOverlap(i, media, address, maxSize) == TRUE)
return WSF_EFS_INVALID_HANDLE;
}
}
/* Fill in the file control structure */
pFile->size = 0;
pFile->media = media;
pFile->address = address;
memcpy(&pFile->attributes, pAttr, sizeof(wsfEsfAttributes_t));
/* Set the maxSize, and increment the maxSize such that it */
/* occupies a full page in the physical medium */
pFile->maxSize = maxSize;
if (wsfEfsMediaTbl[media]->pageSize)
{
pFile->maxSize += maxSize % wsfEfsMediaTbl[media]->pageSize;
}
return handle;
}
}
return WSF_EFS_INVALID_HANDLE;
}
/*************************************************************************************************/
/*!
* \fn WsfEfsRemoveFile
*
* \brief Deletes a file in the embedded file system.
*
* \param handle Handle identifying the file.
*
* \return WSF_EFS_SUCCESS or WSF_EFS_FAILURE.
*/
/*************************************************************************************************/
uint8_t WsfEfsRemoveFile(wsfEfsHandle_t handle)
{
if (handle < WSF_EFS_MAX_FILES)
{
wsfEfsFileTbl[handle].maxSize = WSF_EFS_INVALID_SIZE;
return WSF_EFS_SUCCESS;
}
return WSF_EFS_FAILURE;
}
/*************************************************************************************************/
/*!
* \fn WsfEfsErase
*
* \brief Clears the contents of a file without deleting the file.
*
* \param handle Handle identifying the file.
*
* \return WSF_EFS_SUCCESS or WSF_EFS_FAILURE.
*/
/*************************************************************************************************/
uint8_t WsfEfsErase(wsfEfsHandle_t handle)
{
uint8_t status = WSF_EFS_FAILURE;
wsfEfsControl_t *pFile;
if ((pFile = WsfEfsGetFileByHandle(handle)) != NULL)
{
if (pFile->attributes.permissions & (WSF_EFS_REMOTE_ERASE_PERMITTED | WSF_EFS_LOCAL_ERASE_PERMITTED))
{
uint8_t media = pFile->media;
if (wsfEfsMediaTbl[media]->erase)
{
uint32_t address = pFile->address;
uint32_t size = pFile->maxSize;
status = wsfEfsMediaTbl[media]->erase(address, size);
pFile->size = 0;
}
}
}
return status;
}
/*************************************************************************************************/
/*!
* \fn WsfEfsGetAttributes
*
* \brief Gets the attributes of a file.
*
* \param handle Handle identifying the file.
* \param pAttr Pointer to memory to store the attributes.
*
* \return WSF_EFS_SUCCESS or WSF_EFS_FAILURE.
*/
/*************************************************************************************************/
uint8_t WsfEfsGetAttributes(wsfEfsHandle_t handle, wsfEsfAttributes_t *pAttr)
{
wsfEfsControl_t *pFile;
if (((pFile = WsfEfsGetFileByHandle(handle)) != NULL) && pAttr)
{
memcpy(pAttr, &pFile->attributes, sizeof(wsfEsfAttributes_t));
return WSF_EFS_SUCCESS;
}
return WSF_EFS_FAILURE;
}
/*************************************************************************************************/
/*!
* \fn WsfEfsSetAttributes
*
* \brief Updates the attributes of a file.
*
* \param handle Handle identifying the file.
* \param pAttr Pointer to memory to with the new attributes.
*
* \return WSF_EFS_SUCCESS or WSF_EFS_FAILURE.
*/
/*************************************************************************************************/
uint8_t WsfEfsSetAttributes(wsfEfsHandle_t handle, wsfEsfAttributes_t *pAttr)
{
wsfEfsControl_t *pFile;
if (((pFile = WsfEfsGetFileByHandle(handle)) != NULL) && pAttr)
{
memcpy(&pFile->attributes, pAttr, sizeof(wsfEsfAttributes_t));
return WSF_EFS_SUCCESS;
}
return WSF_EFS_FAILURE;
}
/*************************************************************************************************/
/*!
* \fn WsfEfsGet
*
* \brief Copies data from a file.
*
* \param handle Handle identifying the file.
* \param offset Offset into the file to begin copying from.
* \param pBuffer Location to copy the data to.
* \param len Number of bytes to copy into pBuffer.
*
* \return The number of bytes read from the file.
*/
/*************************************************************************************************/
uint16_t WsfEfsGet(wsfEfsHandle_t handle, uint32_t offset, uint8_t *pBuffer, uint16_t len)
{
wsfEfsControl_t *pFile;
if (((pFile = WsfEfsGetFileByHandle(handle)) != NULL) && pBuffer)
{
if (pFile->attributes.permissions & (WSF_EFS_REMOTE_GET_PERMITTED | WSF_EFS_LOCAL_GET_PERMITTED))
{
uint8_t media = pFile->media;
if (wsfEfsMediaTbl[media]->read)
{
if (pFile->attributes.type == WSF_EFS_FILE_TYPE_STREAM)
{
wsfEfsMediaTbl[media]->read(pBuffer, 0, len);
return len;
}
else if (offset < pFile->size)
{
uint32_t address = pFile->address + offset;
if (offset + len > pFile->size)
{
len = (uint16_t) (pFile->size - offset);
}
wsfEfsMediaTbl[media]->read(pBuffer, address, len);
return len;
}
}
}
}
return 0;
}
/*************************************************************************************************/
/*!
* \fn WsfEfsPut
*
* \brief Writes data to a file.
*
* \param handle Handle identifying the file.
* \param offset Offset into the file to begin writing to.
* \param pBuffer Data to write to the file.
* \param len Number of bytes to write to the file.
*
* \return The number of bytes written to the file
*/
/*************************************************************************************************/
uint16_t WsfEfsPut(wsfEfsHandle_t handle, uint32_t offset, const uint8_t *pBuffer, uint16_t len)
{
wsfEfsControl_t *pFile;
if (((pFile = WsfEfsGetFileByHandle(handle)) != NULL) && pBuffer)
{
if (pFile->attributes.permissions & (WSF_EFS_REMOTE_PUT_PERMITTED | WSF_EFS_LOCAL_PUT_PERMITTED))
{
uint8_t media = pFile->media;
if (wsfEfsMediaTbl[media]->write)
{
if (pFile->attributes.type == WSF_EFS_FILE_TYPE_STREAM)
{
wsfEfsMediaTbl[media]->write(pBuffer, 0, len);
return len;
}
else if (offset < pFile->maxSize)
{
uint32_t address = pFile->address + offset;
if (offset + len > pFile->maxSize)
{
len = (uint16_t) (pFile->maxSize - offset);
}
wsfEfsMediaTbl[media]->write(pBuffer, address, len);
/* If writing to the end of the file, update the file size */
if (offset + len > pFile->size)
{
pFile->size = offset + len;
}
return len;
}
}
}
}
return 0;
}
/*************************************************************************************************/
/*!
* \fn WsfEfsGetFileName
*
* \brief Get the name of a file.
*
* \param handle File Handle.
*
* \return Filename string of a file.
*/
/*************************************************************************************************/
char *WsfEfsGetFileName(wsfEfsHandle_t handle)
{
wsfEfsControl_t *pFile;
if (((pFile = WsfEfsGetFileByHandle(handle)) != NULL))
{
return pFile->attributes.name;
}
return "Unknown";
}
/*************************************************************************************************/
/*!
* \fn WsfEfsGetFileVersion
*
* \brief Get the version of a file.
*
* \param handle File Handle.
*
* \return Version string of a file.
*/
/*************************************************************************************************/
char *WsfEfsGetFileVersion(wsfEfsHandle_t handle)
{
wsfEfsControl_t *pFile;
if (((pFile = WsfEfsGetFileByHandle(handle)) != NULL))
{
return pFile->attributes.version;
}
return "Unknown";
}
/*************************************************************************************************/
/*!
* \fn WsfEfsGetFileMaxSize
*
* \brief Get the number of bytes of memory reserved for use by a file.
*
* \param handle File Handle.
*
* \return Max size of the file.
*/
/*************************************************************************************************/
uint32_t WsfEfsGetFileMaxSize(wsfEfsHandle_t handle)
{
wsfEfsControl_t *pFile;
if (((pFile = WsfEfsGetFileByHandle(handle)) != NULL))
{
return pFile->maxSize;
}
return 0;
}
/*************************************************************************************************/
/*!
* \fn WsfEfsGetFileSize
*
* \brief Get the size of a file.
*
* \param handle File Handle.
*
* \return Size of the file.
*/
/*************************************************************************************************/
uint32_t WsfEfsGetFileSize(wsfEfsHandle_t handle)
{
wsfEfsControl_t *pFile;
if (((pFile = WsfEfsGetFileByHandle(handle)) != NULL))
{
return pFile->size;
}
return 0;
}
/*************************************************************************************************/
/*!
* \fn WsfEfsGetFileType
*
* \brief Get the type of a file.
*
* \param handle File Handle.
*
* \return Type of file (bulk or stream).
*/
/*************************************************************************************************/
uint8_t WsfEfsGetFileType(wsfEfsHandle_t handle)
{
wsfEfsControl_t *pFile;
if (((pFile = WsfEfsGetFileByHandle(handle)) != NULL))
{
return pFile->attributes.type;
}
return WSF_EFS_FILE_TYPE_BULK;
}
/*************************************************************************************************/
/*!
* \fn WsfEfsGetFilePermissions
*
* \brief Get the permissions of a file.
*
* \param handle File Handle.
*
* \return Permissions of the file.
*/
/*************************************************************************************************/
uint16_t WsfEfsGetFilePermissions(wsfEfsHandle_t handle)
{
wsfEfsControl_t *pFile;
if (((pFile = WsfEfsGetFileByHandle(handle)) != NULL))
{
return pFile->attributes.permissions;
}
return 0;
}
/*************************************************************************************************/
/*!
* \fn WsfEfsMediaSpecificCommand
*
* \brief Execute a media specific command on a file.
*
* \param handle File Handle.
* \param cmd Media specific command identifier.
* \param param Ccommand specific parameter.
*
* \return Status of the operation.
*/
/*************************************************************************************************/
uint8_t WsfEfsMediaSpecificCommand(wsfEfsHandle_t handle, uint8_t cmd, uint32_t param)
{
if (WsfEfsGetFileByHandle(handle))
{
uint8_t media = wsfEfsFileTbl[handle].media;
/* Call the command handler if it exists */
if (wsfEfsMediaTbl[media]->handleCmd)
{
return wsfEfsMediaTbl[media]->handleCmd(cmd, param);
}
}
return FALSE;
}
/*************************************************************************************************/
/*!
* \fn WsfEfsRegisterMedia
*
* \brief Registers a File Storage Medium with the Embedded File System.
*
* \param pMedia Pointer to the media control structure.
* \param mediaID Identifier of the media.
*
* \return WSF_EFS_SUCCESS or WSF_EFS_FAILURE.
*/
/*************************************************************************************************/
uint8_t WsfEfsRegisterMedia(const wsfEfsMedia_t *pMediaCtrl, uint8_t mediaID)
{
if (mediaID < WSF_EFS_MAX_MEDIA && pMediaCtrl)
{
wsfEfsMediaTbl[mediaID] = pMediaCtrl;
/* Call the initialization function for the media */
if (pMediaCtrl->init)
{
pMediaCtrl->init();
}
return WSF_EFS_SUCCESS;
}
return WSF_EFS_FAILURE;
}
@@ -0,0 +1,123 @@
/*************************************************************************************************/
/*!
* \file wsf_intrinsic.h
*
* \brief CPU core intrinsic functions.
*
* $Date: 2013-05-22 15:52:25 -0700 (Wed, 22 May 2013) $
* $Revision: 660 $
*
* Copyright (c) 2009 Wicentric, Inc., all rights reserved.
* Wicentric confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact Wicentric, Inc. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#ifndef WSF_INTRINSIC_H
#define WSF_INTRINSIC_H
#ifdef __arm__
#include "device_cm3.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**************************************************************************************************
Macros
**************************************************************************************************/
/*************************************************************************************************/
/*!
* \def WsfLeadingMsbZeros
*
* \brief Count leading MSB zero.
*
* \param value Value to count leading zeros.
*
* \return Number of leading zeros.
*/
/*************************************************************************************************/
#ifdef __arm__
#define WsfClzMsb(v) __CLZ(v)
#else
static inline uint8_t WsfClzMsb(uint32_t value)
{
/* Stub for platform specific implementation. */
return 0;
}
#endif
/*************************************************************************************************/
/*!
* \def WsfLeadingMsbOnes
*
* \brief Count leading MSB ones.
*
* \param value Value to count leading ones.
*
* \return Number of leading ones.
*/
/*************************************************************************************************/
#ifdef __arm__
#define WsfCloMsb(v) __CLZ(~v)
#else
static inline uint8_t WsfCloMsb(uint32_t value)
{
return WsfClzMsb(~value);
}
#endif
/*************************************************************************************************/
/*!
* \def WsfLeadingLsbZeros
*
* \brief Count leading LSB zero.
*
* \param value Value to count leading zeros.
*
* \return Number of leading zeros.
*/
/*************************************************************************************************/
#ifdef __arm__
#define WsfClzLsb(v) __CLZ(__REV(v))
#else
static inline uint8_t WsfClzLsb(uint32_t value)
{
/* Stub for platform specific implementation. */
return 0;
}
#endif
/*************************************************************************************************/
/*!
* \def WsfLeadingLsbOnes
*
* \brief Count leading LSB ones.
*
* \param value Value to count leading ones.
*
* \return Number of leading ones.
*/
/*************************************************************************************************/
#ifdef __arm__
#define WsfCloLsb(v) __CLZ(__REV(~v))
#else
static inline uint8_t WsfCloLsb(uint32_t value)
{
return WsfClzLsb(~value);
}
#endif
#ifdef __cplusplus
};
#endif
#endif /* WSF_INTRINSIC_H */
@@ -0,0 +1,97 @@
/*************************************************************************************************/
/*!
* \file wsf_math.c
*
* \brief Common math utilities generic implementation file.
*
* $Date: 2014-09-16 13:19:18 -0700 (Tue, 16 Sep 2014) $
* $Revision: 1816 $
*
* Copyright (c) 2013 Wicentric, Inc., all rights reserved.
* Wicentric confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact Wicentric, Inc. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#include "wsf_math.h"
#include <string.h>
/**************************************************************************************************
Global Variables
**************************************************************************************************/
static uint32_t wsfRngW = 88675123;
static uint32_t wsfRngX = 123456789;
static uint32_t wsfRngY = 362436069;
static uint32_t wsfRngZ = 521288629;
/*************************************************************************************************/
/*!
* \fn WsfMathInit
*
* \brief Initialize math routines.
*
* \return None.
*/
/*************************************************************************************************/
void WsfMathInit(void)
{
/* Seed PRNG. */
wsfRngW = 88675123;
wsfRngX = 123456789;
wsfRngY = 362436069;
wsfRngZ = 521288629;
}
/*************************************************************************************************/
/*!
* \fn WsfRandNum
*
* \brief Generate random number.
*
* \return 32-bit random number.
*
* This software implementation uses a xorshift random number generator.
* George Marsaglia (2003), "Xorshift RNGs", Journal of Statistical Software
*
* \note This routine is not a cryptographic grade random number generator.
*/
/*************************************************************************************************/
uint32_t WsfRandNum(void)
{
uint32_t t;
t = wsfRngX ^ (wsfRngX << 11);
wsfRngX = wsfRngY;
wsfRngY = wsfRngZ;
wsfRngZ = wsfRngW;
wsfRngW = wsfRngW ^ (wsfRngW >> 19) ^ (t ^ (t >> 8));
return wsfRngW;
}
/*************************************************************************************************/
/*!
* \fn WsfAesEcb
*
* \brief Calculate AES ECB.
*
* \param pKey Encryption key.
* \param pOut Output data.
* \param pIn Input data.
*
* \return None.
*/
/*************************************************************************************************/
void WsfAesEcb(const uint8_t *pKey, uint8_t *pOut, const uint8_t *pIn)
{
/* TODO implementation required. */
const unsigned int KEY_LEN = 16;
memcpy(pOut, pIn, KEY_LEN);
}
@@ -0,0 +1,204 @@
/*************************************************************************************************/
/*!
* \file wsf_msg.c
*
* \brief Message passing service.
*
* $Date: 2017-03-10 14:08:37 -0600 (Fri, 10 Mar 2017) $
* $Revision: 11501 $
*
* Copyright (c) 2009-2017 ARM Ltd., all rights reserved.
* ARM Ltd. confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact ARM Ltd. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#include "wsf_types.h"
#include "wsf_msg.h"
#include "wsf_assert.h"
#include "wsf_buf.h"
#include "wsf_queue.h"
#include "wsf_trace.h"
#include "wsf_os.h"
/**************************************************************************************************
Data Types
**************************************************************************************************/
/* Internal message buf structure */
typedef struct wsfMsg_tag
{
struct wsfMsg_tag *pNext;
wsfHandlerId_t handlerId;
} wsfMsg_t;
/*************************************************************************************************/
/*!
* \fn WsfMsgDataAlloc
*
* \brief Allocate a data message buffer to be sent with WsfMsgSend().
*
* \param len Message length in bytes.
* \param tailroom Tailroom length in bytes.
*
* \return Pointer to data message buffer or NULL if allocation failed.
*/
/*************************************************************************************************/
void *WsfMsgDataAlloc(uint16_t len, uint8_t tailroom)
{
return WsfMsgAlloc(len + tailroom);
}
/*************************************************************************************************/
/*!
* \fn WsfMsgAlloc
*
* \brief Allocate a message buffer to be sent with WsfMsgSend().
*
* \param len Message length in bytes.
*
* \return Pointer to message buffer or NULL if allocation failed.
*/
/*************************************************************************************************/
void *WsfMsgAlloc(uint16_t len)
{
wsfMsg_t *pMsg;
pMsg = WsfBufAlloc(len + sizeof(wsfMsg_t));
/* hide header */
if (pMsg != NULL)
{
pMsg++;
}
return pMsg;
}
/*************************************************************************************************/
/*!
* \fn WsfMsgFree
*
* \brief Free a message buffer allocated with WsfMsgAlloc().
*
* \param pMsg Pointer to message buffer.
*
* \return None.
*/
/*************************************************************************************************/
void WsfMsgFree(void *pMsg)
{
WsfBufFree(((wsfMsg_t *) pMsg) - 1);
}
/*************************************************************************************************/
/*!
* \fn WsfMsgSend
*
* \brief Send a message to an event handler.
*
* \param handlerId Event handler ID.
* \param pMsg Pointer to message buffer.
*
* \return None.
*/
/*************************************************************************************************/
void WsfMsgSend(wsfHandlerId_t handlerId, void *pMsg)
{
WSF_TRACE_MSG1("WsfMsgSend handlerId:%u", handlerId);
/* get queue for this handler and enqueue message */
WsfMsgEnq(WsfTaskMsgQueue(handlerId), handlerId, pMsg);
/* set task for this handler as ready to run */
WsfTaskSetReady(handlerId, WSF_MSG_QUEUE_EVENT);
}
/*************************************************************************************************/
/*!
* \fn WsfMsgEnq
*
* \brief Enqueue a message.
*
* \param pQueue Pointer to queue.
* \param handerId Set message handler ID to this value.
* \param pElem Pointer to message buffer.
*
* \return None.
*/
/*************************************************************************************************/
void WsfMsgEnq(wsfQueue_t *pQueue, wsfHandlerId_t handlerId, void *pMsg)
{
wsfMsg_t *p;
WSF_ASSERT(pMsg != NULL);
/* get message header */
p = ((wsfMsg_t *) pMsg) - 1;
/* set handler ID */
p->handlerId = handlerId;
WsfQueueEnq(pQueue, p);
}
/*************************************************************************************************/
/*!
* \fn WsfMsgDeq
*
* \brief Dequeue a message.
*
* \param pQueue Pointer to queue.
* \param pHandlerId Handler ID of returned message; this is a return parameter.
*
* \return Pointer to message that has been dequeued or NULL if queue is empty.
*/
/*************************************************************************************************/
void *WsfMsgDeq(wsfQueue_t *pQueue, wsfHandlerId_t *pHandlerId)
{
wsfMsg_t *pMsg;
if ((pMsg = WsfQueueDeq(pQueue)) != NULL)
{
*pHandlerId = pMsg->handlerId;
/* hide header */
pMsg++;
}
return pMsg;
}
/*************************************************************************************************/
/*!
* \fn WsfMsgPeek
*
* \brief Get the next message without removing it from the queue.
*
* \param pQueue Pointer to queue.
* \param pHandlerId Handler ID of returned message; this is a return parameter.
*
* \return Pointer to the next message on the queue or NULL if queue is empty.
*/
/*************************************************************************************************/
void *WsfMsgPeek(wsfQueue_t *pQueue, wsfHandlerId_t *pHandlerId)
{
wsfMsg_t *pMsg = pQueue->pHead;
if (pMsg != NULL)
{
*pHandlerId = pMsg->handlerId;
/* hide header */
pMsg++;
}
return pMsg;
}
@@ -0,0 +1,426 @@
/*************************************************************************************************/
/*!
* \file wsf_os.c
*
* \brief Software foundation OS main module.
*
* $Date: 2015-09-09 09:35:06 -0700 (Wed, 09 Sep 2015) $
* $Revision: 3809 $
*
* Copyright (c) 2009 Wicentric, Inc., all rights reserved.
* Wicentric confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact Wicentric, Inc. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#ifdef __IAR_SYSTEMS_ICC__
#include <intrinsics.h>
#endif
#include <string.h>
#include "wsf_types.h"
#include "wsf_os.h"
#include "wsf_assert.h"
#include "wsf_trace.h"
#include "wsf_timer.h"
#include "wsf_queue.h"
#include "wsf_buf.h"
#include "wsf_msg.h"
#include "wsf_cs.h"
/**************************************************************************************************
Compile time assert checks
**************************************************************************************************/
WSF_CT_ASSERT(sizeof(uint8_t) == 1);
WSF_CT_ASSERT(sizeof(uint16_t) == 2);
WSF_CT_ASSERT(sizeof(uint32_t) == 4);
/**************************************************************************************************
Macros
**************************************************************************************************/
/* maximum number of event handlers per task */
#ifndef WSF_MAX_HANDLERS
#define WSF_MAX_HANDLERS 9
#endif
/**************************************************************************************************
Data Types
**************************************************************************************************/
/* Task structure */
typedef struct
{
wsfEventHandler_t handler[WSF_MAX_HANDLERS];
wsfEventMask_t handlerEventMask[WSF_MAX_HANDLERS];
wsfQueue_t msgQueue;
wsfTaskEvent_t taskEventMask;
uint8_t numHandler;
} wsfOsTask_t;
/* OS structure */
typedef struct
{
wsfOsTask_t task;
} wsfOs_t;
/**************************************************************************************************
Local Variables
**************************************************************************************************/
uint8_t csNesting = 0;
wsfOs_t wsfOs;
#include "FreeRTOS.h"
#include "event_groups.h"
EventGroupHandle_t xRadioTaskEventObject = NULL;
/*************************************************************************************************/
/*!
* \fn WsfCsEnter
*
* \brief Enter a critical section.
*
* \return None.
*/
/*************************************************************************************************/
void WsfCsEnter(void)
{
if (csNesting == 0)
{
#ifdef __IAR_SYSTEMS_ICC__
__disable_interrupt();
#endif
#ifdef __GNUC__
__asm volatile ("cpsid i");
#endif
#ifdef __CC_ARM
__disable_irq();
#endif
}
csNesting++;
}
/*************************************************************************************************/
/*!
* \fn WsfCsEnter
*
* \brief Enter a critical section.
*
* \return None.
*/
/*************************************************************************************************/
void WsfCsExit(void)
{
WSF_ASSERT(csNesting != 0);
csNesting--;
if (csNesting == 0)
{
#ifdef __IAR_SYSTEMS_ICC__
__enable_interrupt();
#endif
#ifdef __GNUC__
__asm volatile ("cpsie i");
#endif
#ifdef __CC_ARM
__enable_irq();
#endif
}
}
/*************************************************************************************************/
/*!
* \fn WsfTaskLock
*
* \brief Lock task scheduling.
*
* \return None.
*/
/*************************************************************************************************/
void WsfTaskLock(void)
{
WsfCsEnter();
}
/*************************************************************************************************/
/*!
* \fn WsfTaskUnlock
*
* \brief Unock task scheduling.
*
* \return None.
*/
/*************************************************************************************************/
void WsfTaskUnlock(void)
{
WsfCsExit();
}
void WsfSetOsSpecificEvent(void)
{
if(xRadioTaskEventObject != NULL)
{
BaseType_t xHigherPriorityTaskWoken, xResult;
if(xPortIsInsideInterrupt() == pdTRUE) {
//
// Send an event to the main radio task
//
xHigherPriorityTaskWoken = pdFALSE;
xResult = xEventGroupSetBitsFromISR(xRadioTaskEventObject, 1,
&xHigherPriorityTaskWoken);
//
// If the radio task is higher-priority than the context we're currently
// running from, we should yield now and run the radio task.
//
if ( xResult != pdFAIL )
{
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
else {
xResult = xEventGroupSetBits(xRadioTaskEventObject, 1);
//
// If the radio task is higher priority than the context we're currently
// running from, we should yield now and run the radio task.
//
if ( xResult != pdFAIL )
{
portYIELD();
}
}
}
}
/*************************************************************************************************/
/*!
* \fn WsfSetEvent
*
* \brief Set an event for an event handler.
*
* \param handlerId Handler ID.
* \param event Event or events to set.
*
* \return None.
*/
/*************************************************************************************************/
void WsfSetEvent(wsfHandlerId_t handlerId, wsfEventMask_t event)
{
WSF_CS_INIT(cs);
WSF_ASSERT(WSF_HANDLER_FROM_ID(handlerId) < WSF_MAX_HANDLERS);
WSF_TRACE_INFO2("WsfSetEvent handlerId:%u event:%u", handlerId, event);
WSF_CS_ENTER(cs);
wsfOs.task.handlerEventMask[WSF_HANDLER_FROM_ID(handlerId)] |= event;
wsfOs.task.taskEventMask |= WSF_HANDLER_EVENT;
WSF_CS_EXIT(cs);
/* set event in OS */
WsfSetOsSpecificEvent();
}
/*************************************************************************************************/
/*!
* \fn WsfTaskSetReady
*
* \brief Set the task used by the given handler as ready to run.
*
* \param handlerId Event handler ID.
* \param event Task event mask.
*
* \return None.
*/
/*************************************************************************************************/
void WsfTaskSetReady(wsfHandlerId_t handlerId, wsfTaskEvent_t event)
{
/* Unused parameter */
(void)handlerId;
WSF_CS_INIT(cs);
WSF_CS_ENTER(cs);
wsfOs.task.taskEventMask |= event;
WSF_CS_EXIT(cs);
/* set event in OS */
WsfSetOsSpecificEvent();
}
/*************************************************************************************************/
/*!
* \fn WsfTaskMsgQueue
*
* \brief Return the message queue used by the given handler.
*
* \param handlerId Event handler ID.
*
* \return Task message queue.
*/
/*************************************************************************************************/
wsfQueue_t *WsfTaskMsgQueue(wsfHandlerId_t handlerId)
{
/* Unused parameter */
(void)handlerId;
return &(wsfOs.task.msgQueue);
}
/*************************************************************************************************/
/*!
* \fn WsfOsSetNextHandler
*
* \brief Set the next WSF handler function in the WSF OS handler array. This function
* should only be called as part of the stack initialization procedure.
*
* \param handler WSF handler function.
*
* \return WSF handler ID for this handler.
*/
/*************************************************************************************************/
wsfHandlerId_t WsfOsSetNextHandler(wsfEventHandler_t handler)
{
wsfHandlerId_t handlerId = wsfOs.task.numHandler++;
WSF_ASSERT(handlerId < WSF_MAX_HANDLERS);
wsfOs.task.handler[handlerId] = handler;
return handlerId;
}
/*************************************************************************************************/
/*!
* \fn wsfOsReadyToSleep
*
* \brief Check if WSF is ready to sleep. This function should be called when interrupts
* are disabled.
*
* \param None.
*
* \return Return TRUE if there are no pending WSF task events set, FALSE otherwise.
*/
/*************************************************************************************************/
bool_t wsfOsReadyToSleep(void)
{
return (wsfOs.task.taskEventMask == 0);
}
/*************************************************************************************************/
/*!
* \brief Initialize OS control structure.
*
* \return None.
*/
/*************************************************************************************************/
void WsfOsInit(void)
{
memset(&wsfOs, 0, sizeof(wsfOs));
if( xRadioTaskEventObject == NULL)
{
xRadioTaskEventObject = xEventGroupCreate();
WSF_ASSERT(xRadioTaskEventObject != NULL);
}
}
/*************************************************************************************************/
/*!
* \fn wsfOsDispatcher
*
* \brief Event dispatched. Designed to be called repeatedly from infinite loop.
*
* \param None.
*
* \return None.
*/
/*************************************************************************************************/
void wsfOsDispatcher(void)
{
wsfOsTask_t *pTask;
void *pMsg;
wsfTimer_t *pTimer;
wsfEventMask_t eventMask;
wsfTaskEvent_t taskEventMask;
wsfHandlerId_t handlerId;
uint8_t i;
WSF_CS_INIT(cs);
pTask = &wsfOs.task;
WsfTimerUpdateTicks();
while (pTask->taskEventMask)
{
/* get and then clear task event mask */
WSF_CS_ENTER(cs);
taskEventMask = pTask->taskEventMask;
pTask->taskEventMask = 0;
WSF_CS_EXIT(cs);
if (taskEventMask & WSF_MSG_QUEUE_EVENT)
{
/* handle msg queue */
while ((pMsg = WsfMsgDeq(&pTask->msgQueue, &handlerId)) != NULL)
{
WSF_ASSERT(handlerId < WSF_MAX_HANDLERS);
(*pTask->handler[handlerId])(0, pMsg);
WsfMsgFree(pMsg);
}
}
if (taskEventMask & WSF_TIMER_EVENT)
{
/* service timers */
while ((pTimer = WsfTimerServiceExpired(0)) != NULL)
{
WSF_ASSERT(pTimer->handlerId < WSF_MAX_HANDLERS);
(*pTask->handler[pTimer->handlerId])(0, &pTimer->msg);
}
}
if (taskEventMask & WSF_HANDLER_EVENT)
{
/* service handlers */
for (i = 0; i < WSF_MAX_HANDLERS; i++)
{
if ((pTask->handlerEventMask[i] != 0) && (pTask->handler[i] != NULL))
{
WSF_CS_ENTER(cs);
eventMask = pTask->handlerEventMask[i];
pTask->handlerEventMask[i] = 0;
WSF_CS_EXIT(cs);
(*pTask->handler[i])(eventMask, NULL);
}
}
}
}
xEventGroupWaitBits(xRadioTaskEventObject, 1, pdTRUE,
pdFALSE, portMAX_DELAY);
}
@@ -0,0 +1,118 @@
/*************************************************************************************************/
/*!
* \file wsf_os_int.h
*
* \brief Software foundation OS platform-specific interface file.
*
* $Date: 2012-10-01 13:53:07 -0700 (Mon, 01 Oct 2012) $
* $Revision: 357 $
*
* Copyright (c) 2009 Wicentric, Inc., all rights reserved.
* Wicentric confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact Wicentric, Inc. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#ifndef WSF_OS_INT_H
#define WSF_OS_INT_H
#ifdef __cplusplus
extern "C" {
#endif
/**************************************************************************************************
Macros
**************************************************************************************************/
/* Task events */
#define WSF_MSG_QUEUE_EVENT 0x01 /* Message queued for event handler */
#define WSF_TIMER_EVENT 0x02 /* Timer expired for event handler */
#define WSF_HANDLER_EVENT 0x04 /* Event set for event handler */
/* Derive task from handler ID */
#define WSF_TASK_FROM_ID(handlerID) (((handlerID) >> 4) & 0x0F)
/* Derive handler from handler ID */
#define WSF_HANDLER_FROM_ID(handlerID) ((handlerID) & 0x0F)
/**************************************************************************************************
Data Types
**************************************************************************************************/
/* Event handler ID data type */
typedef uint8_t wsfHandlerId_t;
/* Event handler event mask data type */
typedef uint8_t wsfEventMask_t;
/* Task ID data type */
typedef wsfHandlerId_t wsfTaskId_t;
/* Task event mask data type */
typedef uint8_t wsfTaskEvent_t;
/**************************************************************************************************
Function Declarations
**************************************************************************************************/
/*************************************************************************************************/
/*!
* \fn wsfOsReadyToSleep
*
* \brief Check if WSF is ready to sleep.
*
* \param None.
*
* \return Return TRUE if there are no pending WSF task events set, FALSE otherwise.
*/
/*************************************************************************************************/
bool_t wsfOsReadyToSleep(void);
/*************************************************************************************************/
/*!
* \fn WsfOsInit
*
* \brief Initialized WsfOs module.
*
* \param None.
*
* \return None.
*/
/*************************************************************************************************/
void WsfOsInit(void);
/*************************************************************************************************/
/*!
* \fn wsfOsDispatcher
*
* \brief Event dispatched. Designed to be called repeatedly from infinite loop.
*
* \param None.
*
* \return None.
*/
/*************************************************************************************************/
void wsfOsDispatcher(void);
/*************************************************************************************************/
/*!
* \fn WsfOsShutdown
*
* \brief Shutdown OS.
*
* \return None.
*/
/*************************************************************************************************/
void WsfOsShutdown(void);
#ifdef __cplusplus
};
#endif
#endif /* WSF_OS_INT_H */
@@ -0,0 +1,329 @@
/*************************************************************************************************/
/*!
* \file wsf_queue.c
*
* \brief General purpose queue service.
*
* $Date: 2017-01-06 13:47:48 -0600 (Fri, 06 Jan 2017) $
* $Revision: 10864 $
*
* Copyright (c) 2009-2017 ARM Ltd., all rights reserved.
* ARM Ltd. confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact ARM Ltd. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#include "wsf_types.h"
#include "wsf_queue.h"
#include "wsf_assert.h"
#include "wsf_cs.h"
/**************************************************************************************************
Macros
**************************************************************************************************/
/* Get next queue element */
#define WSF_QUEUE_NEXT(p) (((wsfQueueElem_t *)(p))->pNext)
/**************************************************************************************************
Data Types
**************************************************************************************************/
/* Queue element */
typedef struct wsfQueueElem_tag
{
struct wsfQueueElem_tag *pNext; /* pointer to next element */
} wsfQueueElem_t;
/*************************************************************************************************/
/*!
* \fn WsfQueueEnq
*
* \brief Enqueue and element to the tail of a queue.
*
* \param pQueue Pointer to queue.
* \param pElem Pointer to element.
*
* \return None.
*/
/*************************************************************************************************/
void WsfQueueEnq(wsfQueue_t *pQueue, void *pElem)
{
WSF_CS_INIT(cs);
WSF_ASSERT(pQueue != NULL);
WSF_ASSERT(pElem != NULL);
/* initialize next pointer */
WSF_QUEUE_NEXT(pElem) = NULL;
/* enter critical section */
WSF_CS_ENTER(cs);
/* if queue empty */
if (pQueue->pHead == NULL)
{
pQueue->pHead = pElem;
pQueue->pTail = pElem;
}
/* else enqueue element to the tail of queue */
else
{
WSF_QUEUE_NEXT(pQueue->pTail) = pElem;
pQueue->pTail = pElem;
}
/* exit critical section */
WSF_CS_EXIT(cs);
}
/*************************************************************************************************/
/*!
* \fn WsfQueueDeq
*
* \brief Dequeue and element from the head of a queue.
*
* \param pQueue Pointer to queue.
*
* \return Pointer to element that has been dequeued or NULL if queue is empty.
*/
/*************************************************************************************************/
void *WsfQueueDeq(wsfQueue_t *pQueue)
{
wsfQueueElem_t *pElem;
WSF_CS_INIT(cs);
WSF_ASSERT(pQueue != NULL);
/* enter critical section */
WSF_CS_ENTER(cs);
pElem = pQueue->pHead;
/* if queue is not empty */
if (pElem != NULL)
{
/* set head to next element in queue */
pQueue->pHead = WSF_QUEUE_NEXT(pElem);
/* check for empty queue */
if (pQueue->pHead == NULL)
{
pQueue->pTail = NULL;
}
}
/* exit critical section */
WSF_CS_EXIT(cs);
return pElem;
}
/*************************************************************************************************/
/*!
* \fn WsfQueuePush
*
* \brief Push and element to the head of a queue.
*
* \param pQueue Pointer to queue.
* \param pElem Pointer to element.
*
* \return None.
*/
/*************************************************************************************************/
void WsfQueuePush(wsfQueue_t *pQueue, void *pElem)
{
WSF_CS_INIT(cs);
WSF_ASSERT(pQueue != NULL);
WSF_ASSERT(pElem != NULL);
/* enter critical section */
WSF_CS_ENTER(cs);
/* else push element to head of queue */
WSF_QUEUE_NEXT(pElem) = pQueue->pHead;
/* if queue was empty set tail */
if (pQueue->pHead == NULL)
{
pQueue->pTail = pElem;
}
/* set head */
pQueue->pHead = pElem;
/* exit critical section */
WSF_CS_EXIT(cs);
}
/*************************************************************************************************/
/*!
* \fn WsfQueueInsert
*
* \brief Insert an element into a queue. This function is typically used when iterating
* over a queue.
*
* \param pQueue Pointer to queue.
* \param pElem Pointer to element to be inserted.
* \param pPrev Pointer to previous element in the queue before element to be inserted.
* Note: set pPrev to NULL if pElem is first element in queue.
* \return None.
*/
/*************************************************************************************************/
void WsfQueueInsert(wsfQueue_t *pQueue, void *pElem, void *pPrev)
{
WSF_CS_INIT(cs);
WSF_ASSERT(pQueue != NULL);
WSF_ASSERT(pElem != NULL);
/* enter critical section */
WSF_CS_ENTER(cs);
/* if queue empty or inserting at tail */
if (pQueue->pHead == NULL || pPrev == pQueue->pTail)
{
/* queue as normal */
WsfQueueEnq(pQueue, pElem);
}
/* else if inserting at head */
else if (pPrev == NULL)
{
/* push to head */
WsfQueuePush(pQueue, pElem);
}
else
{
/* insert in middle of queue */
WSF_QUEUE_NEXT(pElem) = WSF_QUEUE_NEXT(pPrev);
WSF_QUEUE_NEXT(pPrev) = pElem;
}
/* exit critical section */
WSF_CS_EXIT(cs);
}
/*************************************************************************************************/
/*!
* \fn WsfQueueRemove
*
* \brief Remove an element from a queue. This function is typically used when iterating
* over a queue.
*
* \param pQueue Pointer to queue.
* \param pElem Pointer to element to be removed.
* \param pPrev Pointer to previous element in the queue before element to be removed.
* Note: set pPrev to NULL if pElem is first element in queue.
* \return None.
*/
/*************************************************************************************************/
void WsfQueueRemove(wsfQueue_t *pQueue, void *pElem, void *pPrev)
{
WSF_CS_INIT(cs);
WSF_ASSERT(pQueue != NULL);
WSF_ASSERT(pQueue->pHead != NULL);
WSF_ASSERT(pElem != NULL);
/* enter critical section */
WSF_CS_ENTER(cs);
/* if first element */
if (pElem == pQueue->pHead)
{
/* remove from head of queue */
pQueue->pHead = WSF_QUEUE_NEXT(pElem);
}
else if (pPrev)
{
/* remove from middle of queue, pPrev will never be null */
WSF_QUEUE_NEXT(pPrev) = WSF_QUEUE_NEXT(pElem);
}
/* if last element */
if (pElem == pQueue->pTail)
{
/* update tail */
pQueue->pTail = pPrev;
}
/* exit critical section */
WSF_CS_EXIT(cs);
}
/*************************************************************************************************/
/*!
* \fn WsfQueueCount
*
* \brief Count the number of elements in a queue.
*
* \param pQueue Pointer to queue.
*
* \return Number of elements in queue.
*/
/*************************************************************************************************/
uint16_t WsfQueueCount(wsfQueue_t *pQueue)
{
wsfQueueElem_t *pElem;
uint16_t count = 0;
WSF_CS_INIT(cs);
WSF_ASSERT(pQueue != NULL);
/* enter critical section */
WSF_CS_ENTER(cs);
pElem = pQueue->pHead;
/* iterate over queue */
while (pElem != NULL)
{
count++;
pElem = pElem->pNext;
}
/* exit critical section */
WSF_CS_EXIT(cs);
return count;
}
/*************************************************************************************************/
/*!
* \fn WsfQueueEmpty
*
* \brief Return TRUE if queue is empty.
*
* \param pQueue Pointer to queue.
*
* \return TRUE if queue is empty, FALSE otherwise.
*/
/*************************************************************************************************/
bool_t WsfQueueEmpty(wsfQueue_t *pQueue)
{
bool_t empty;
WSF_CS_INIT(cs);
WSF_ASSERT(pQueue != NULL);
/* enter critical section */
WSF_CS_ENTER(cs);
empty = (pQueue->pHead == NULL);
/* exit critical section */
WSF_CS_EXIT(cs);
return empty;
}
@@ -0,0 +1,407 @@
/*************************************************************************************************/
/*!
* \file wsf_timer.c
*
* \brief Timer service.
*
* $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $
* $Revision: 10805 $
*
* Copyright (c) 2009-2017 ARM Ltd., all rights reserved.
* ARM Ltd. confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact ARM Ltd. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#include "wsf_types.h"
#include "wsf_queue.h"
#include "wsf_timer.h"
#include "wsf_assert.h"
#include "wsf_trace.h"
#include "FreeRTOS.h"
#include "timers.h"
/**************************************************************************************************
Macros
**************************************************************************************************/
/* convert seconds to timer ticks */
#define WSF_TIMER_SEC_TO_TICKS(sec) ((1000 / WSF_MS_PER_TICK) * (sec))
/* convert milliseconds to timer ticks */
#define WSF_TIMER_MS_TO_TICKS(ms) ((ms) / WSF_MS_PER_TICK)
#define CLK_TICKS_PER_WSF_TICKS (WSF_MS_PER_TICK*configTICK_RATE_HZ/1000)
/**************************************************************************************************
Global Variables
**************************************************************************************************/
wsfQueue_t wsfTimerTimerQueue; /*!< Timer queue */
TimerHandle_t xWsfTimer;
static uint32_t g_ui32LastTime = 0;
/*************************************************************************************************/
/*!
* \fn wsfTimerRemove
*
* \brief Remove a timer from queue. Note this function does not lock task scheduling.
*
* \param pTimer Pointer to timer.
*
* \return None.
*/
/*************************************************************************************************/
static void wsfTimerRemove(wsfTimer_t *pTimer)
{
wsfTimer_t *pElem;
wsfTimer_t *pPrev = NULL;
pElem = (wsfTimer_t *) wsfTimerTimerQueue.pHead;
/* find timer in queue */
while (pElem != NULL)
{
if (pElem == pTimer)
{
break;
}
pPrev = pElem;
pElem = pElem->pNext;
}
/* if timer found remove from queue */
if (pElem != NULL)
{
WsfQueueRemove(&wsfTimerTimerQueue, pTimer, pPrev);
pTimer->isStarted = FALSE;
}
}
/*************************************************************************************************/
/*!
* \fn wsfTimerInsert
*
* \brief Insert a timer into the queue sorted by the timer expiration.
*
* \param pTimer Pointer to timer.
* \param ticks Timer ticks until expiration.
*
* \return None.
*/
/*************************************************************************************************/
static void wsfTimerInsert(wsfTimer_t *pTimer, wsfTimerTicks_t ticks)
{
wsfTimer_t *pElem;
wsfTimer_t *pPrev = NULL;
/* task schedule lock */
WsfTaskLock();
/* if timer is already running stop it first */
if (pTimer->isStarted)
{
wsfTimerRemove(pTimer);
}
pTimer->isStarted = TRUE;
pTimer->ticks = ticks;
pElem = (wsfTimer_t *) wsfTimerTimerQueue.pHead;
/* find insertion point in queue */
while (pElem != NULL)
{
if (pTimer->ticks < pElem->ticks)
{
break;
}
pPrev = pElem;
pElem = pElem->pNext;
}
/* insert timer into queue */
WsfQueueInsert(&wsfTimerTimerQueue, pTimer, pPrev);
/* task schedule unlock */
WsfTaskUnlock();
}
static void WsfTimer_handler(TimerHandle_t xTimer)
{
WsfTaskSetReady(0, WSF_TIMER_EVENT);
}
/*************************************************************************************************/
/*!
* \fn WsfTimerInit
*
* \brief Initialize the timer service. This function should only be called once
* upon system initialization.
*
* \return None.
*/
/*************************************************************************************************/
void WsfTimerInit(void)
{
WSF_QUEUE_INIT(&wsfTimerTimerQueue);
if(xWsfTimer == NULL)
{
xWsfTimer = xTimerCreate("WSF Timer", pdMS_TO_TICKS(WSF_MS_PER_TICK),
pdFALSE, NULL, WsfTimer_handler);
configASSERT(xWsfTimer);
}
}
/*************************************************************************************************/
/*!
* \fn WsfTimerStartSec
*
* \brief Start a timer in units of seconds.
*
* \param pTimer Pointer to timer.
* \param sec Seconds until expiration.
*
* \return None.
*/
/*************************************************************************************************/
void WsfTimerStartSec(wsfTimer_t *pTimer, wsfTimerTicks_t sec)
{
WSF_TRACE_INFO2("WsfTimerStartSec pTimer:0x%x ticks:%u", (uint32_t)pTimer, WSF_TIMER_SEC_TO_TICKS(sec));
/* insert timer into queue */
wsfTimerInsert(pTimer, WSF_TIMER_SEC_TO_TICKS(sec));
}
/*************************************************************************************************/
/*!
* \fn WsfTimerStartMs
*
* \brief Start a timer in units of milliseconds.
*
* \param pTimer Pointer to timer.
* \param ms Milliseconds until expiration.
*
* \return None.
*/
/*************************************************************************************************/
void WsfTimerStartMs(wsfTimer_t *pTimer, wsfTimerTicks_t ms)
{
WSF_TRACE_INFO2("WsfTimerStartMs pTimer:0x%x ticks:%u", (uint32_t)pTimer, WSF_TIMER_MS_TO_TICKS(ms));
/* insert timer into queue */
wsfTimerInsert(pTimer, WSF_TIMER_MS_TO_TICKS(ms));
}
/*************************************************************************************************/
/*!
* \fn WsfTimerStop
*
* \brief Stop a timer.
*
* \param pTimer Pointer to timer.
*
* \return None.
*/
/*************************************************************************************************/
void WsfTimerStop(wsfTimer_t *pTimer)
{
WSF_TRACE_INFO1("WsfTimerStop pTimer:0x%x", pTimer);
/* task schedule lock */
WsfTaskLock();
wsfTimerRemove(pTimer);
/* task schedule unlock */
WsfTaskUnlock();
}
/*************************************************************************************************/
/*!
* \fn WsfTimerUpdate
*
* \brief Update the timer service with the number of elapsed ticks.
*
* \param ticks Number of ticks since last update.
*
* \return None.
*/
/*************************************************************************************************/
void WsfTimerUpdate(wsfTimerTicks_t ticks)
{
wsfTimer_t *pElem;
/* task schedule lock */
WsfTaskLock();
pElem = (wsfTimer_t *) wsfTimerTimerQueue.pHead;
/* iterate over timer queue */
while (pElem != NULL)
{
/* decrement ticks while preventing underflow */
if (pElem->ticks > ticks)
{
pElem->ticks -= ticks;
}
else
{
pElem->ticks = 0;
/* timer expired; set task for this timer as ready */
WsfTaskSetReady(pElem->handlerId, WSF_TIMER_EVENT);
}
pElem = pElem->pNext;
}
/* task schedule unlock */
WsfTaskUnlock();
}
/*************************************************************************************************/
/*!
* \fn WsfTimerNextExpiration
*
* \brief Return the number of ticks until the next timer expiration. Note that this
* function can return zero even if a timer is running, indicating a timer
* has expired but has not yet been serviced.
*
* \param pTimerRunning Returns TRUE if a timer is running, FALSE if no timers running.
*
* \return The number of ticks until the next timer expiration.
*/
/*************************************************************************************************/
wsfTimerTicks_t WsfTimerNextExpiration(bool_t *pTimerRunning)
{
wsfTimerTicks_t ticks;
/* task schedule lock */
WsfTaskLock();
if (wsfTimerTimerQueue.pHead == NULL)
{
*pTimerRunning = FALSE;
ticks = 0;
}
else
{
*pTimerRunning = TRUE;
ticks = ((wsfTimer_t *) wsfTimerTimerQueue.pHead)->ticks;
}
/* task schedule unlock */
WsfTaskUnlock();
return ticks;
}
/*************************************************************************************************/
/*!
* \fn WsfTimerServiceExpired
*
* \brief Service expired timers for the given task.
*
* \param taskId Task ID.
*
* \return Pointer to timer or NULL.
*/
/*************************************************************************************************/
wsfTimer_t *WsfTimerServiceExpired(wsfTaskId_t taskId)
{
wsfTimer_t *pElem;
wsfTimer_t *pPrev = NULL;
/* Unused parameters */
(void)taskId;
/* task schedule lock */
WsfTaskLock();
/* find expired timers in queue */
if (((pElem = (wsfTimer_t *) wsfTimerTimerQueue.pHead) != NULL) &&
(pElem->ticks == 0))
{
/* remove timer from queue */
WsfQueueRemove(&wsfTimerTimerQueue, pElem, pPrev);
pElem->isStarted = FALSE;
/* task schedule unlock */
WsfTaskUnlock();
WSF_TRACE_INFO1("Timer expired pTimer:0x%x", pElem);
/* return timer */
return pElem;
}
/* task schedule unlock */
WsfTaskUnlock();
return NULL;
}
//*****************************************************************************
//
// Calculate the elapsed time, and update the WSF software timers.
//
//*****************************************************************************
void WsfTimerUpdateTicks(void)
{
uint32_t ui32CurrentTime, ui32ElapsedTime;
bool_t bTimerRunning;
wsfTimerTicks_t xNextExpiration;
//
// Read the continuous timer.
//
ui32CurrentTime = xTaskGetTickCount();
//
// Figure out how long it has been since the last time we've read the
// continuous timer. We should be reading often enough that we'll never
// have more than one overflow.
//
ui32ElapsedTime = ui32CurrentTime - g_ui32LastTime;
//
// Check to see if any WSF ticks need to happen.
//
if ( (ui32ElapsedTime / CLK_TICKS_PER_WSF_TICKS) > 0 )
{
//
// Update the WSF timers and save the current time as our "last
// update".
//
WsfTimerUpdate(ui32ElapsedTime / CLK_TICKS_PER_WSF_TICKS);
g_ui32LastTime = ui32CurrentTime;
}
//
// Check to see when the next timer expiration should happen.
//
xNextExpiration = WsfTimerNextExpiration(&bTimerRunning);
//
// If there's a pending WSF timer event, set an interrupt to wake us up in
// time to service it.
//
if ( xNextExpiration )
{
configASSERT(pdPASS == xTimerChangePeriod( xWsfTimer,
pdMS_TO_TICKS(xNextExpiration*CLK_TICKS_PER_WSF_TICKS), 100)) ;
}
}
@@ -0,0 +1,219 @@
/*************************************************************************************************/
/*!
* \file wsf_trace.c
*
* \brief Trace message implementation.
*
* $Date: 2014-08-06 15:13:15 -0700 (Wed, 06 Aug 2014) $
* $Revision: 1708 $
*
* Copyright (c) 2009 Wicentric, Inc., all rights reserved.
* Wicentric confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact Wicentric, Inc. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#include "wsf_types.h"
#include "wsf_trace.h"
#include "wsf_assert.h"
#include "wsf_cs.h"
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdbool.h>
#include "am_util_debug.h"
#include "am_util_stdio.h"
/**************************************************************************************************
Macros
**************************************************************************************************/
#ifndef WSF_RING_BUF_SIZE
/*! \brief Size of token ring buffer (multiple of 2^N). */
#define WSF_RING_BUF_SIZE 32
#endif
/*! \brief Ring buffer flow control condition detected. */
#define WSF_TOKEN_FLAG_FLOW_CTRL (1 << 28)
/**************************************************************************************************
Data types
**************************************************************************************************/
#if WSF_TOKEN_ENABLED
/*! \brief Trace control block. */
struct
{
struct
{
uint32_t token; /*!< Token. */
uint32_t param; /*!< Parameter. */
} ringBuf[WSF_RING_BUF_SIZE]; /*!< Tokenized tracing ring buffer. */
volatile uint32_t prodIdx; /*!< Ring buffer producer index. */
volatile uint32_t consIdx; /*!< Ring buffer consumer index. */
WsfTokenHandler_t pendCback; /*!< Pending event handler. */
bool_t ringBufEmpty; /*!< Ring buffer state. */
} wsfTraceCb;
#endif
#if WSF_TRACE_ENABLED == TRUE
/*************************************************************************************************/
/*!
* \fn WsfPacketTrace
*
* \brief Print raw HCI data as a trace message.
*
* \param ui8Type HCI packet type byte
* \param ui32Len Length of the HCI packet
* \param pui8Buf Pointer to the buffer of HCI data
*
* \return None.
*/
/*************************************************************************************************/
void WsfPacketTrace(uint8_t ui8Type, uint32_t ui32Len, uint8_t *pui8Buf)
{
uint32_t i;
am_util_debug_printf("%02X ", ui8Type);
for(i = 0; i < ui32Len; i++)
{
if ((i % 8) == 0)
{
am_util_debug_printf("\n");
}
am_util_debug_printf("%02X ", *pui8Buf++);
}
am_util_debug_printf("\n\n");
}
/*************************************************************************************************/
/*!
* \fn WsfTrace
*
* \brief Print a trace message.
*
* \param pStr Message format string
* \param ... Additional aguments, printf-style
*
* \return None.
*/
/*************************************************************************************************/
void WsfTrace(const char *pStr, ...)
{
char pTraceMsg[AM_PRINTF_BUFSIZE];
uint32_t ui32NumChars;
va_list args;
va_start(args, pStr);
am_util_stdio_vsprintf(pTraceMsg, pStr, args);
//vprintf(pStr, args);
va_end(args);
ui32NumChars = am_util_debug_printf(pTraceMsg);
if (!(ui32NumChars < AM_PRINTF_BUFSIZE))
WsfAssert(__FILE__, (uint16_t) __LINE__);
am_util_debug_printf("\n");
}
#elif WSF_TOKEN_ENABLED == TRUE
/*************************************************************************************************/
/*!
* \fn WsfToken
*
* \brief Output tokenized message.
*
* \param tok Token
* \param var Variable
*
* \return None.
*/
/*************************************************************************************************/
void WsfToken(uint32_t tok, uint32_t var)
{
static uint32_t flags = 0;
WSF_CS_INIT(cs);
WSF_CS_ENTER(cs);
uint32_t prodIdx = (wsfTraceCb.prodIdx + 1) & (WSF_RING_BUF_SIZE - 1);
if (prodIdx != wsfTraceCb.consIdx)
{
wsfTraceCb.ringBuf[wsfTraceCb.prodIdx].token = tok | flags;
wsfTraceCb.ringBuf[wsfTraceCb.prodIdx].param = var;
wsfTraceCb.prodIdx = prodIdx;
flags = 0;
}
else
{
flags = WSF_TOKEN_FLAG_FLOW_CTRL;
}
WSF_CS_EXIT(cs);
if (wsfTraceCb.pendCback && wsfTraceCb.ringBufEmpty)
{
wsfTraceCb.ringBufEmpty = FALSE;
wsfTraceCb.pendCback();
}
}
/*************************************************************************************************/
/*!
* \fn wsfTokenService
*
* \brief Service the trace ring buffer.
*
* \return TRUE if trace messages pending, FALSE otherwise.
*
* This routine is called in the main loop for a "push" type trace systems.
*/
/*************************************************************************************************/
bool_t WsfTokenService(void)
{
static uint8_t outBuf[sizeof(wsfTraceCb.ringBuf[0])];
static uint8_t outBufIdx = sizeof(wsfTraceCb.ringBuf[0]);
if (outBufIdx < sizeof(wsfTraceCb.ringBuf[0]))
{
outBufIdx += WsfTokenIOWrite(outBuf + outBufIdx, sizeof(wsfTraceCb.ringBuf[0]) - outBufIdx);
if (outBufIdx < sizeof(wsfTraceCb.ringBuf[0]))
{
/* I/O device is flow controlled. */
return TRUE;
}
}
if (wsfTraceCb.consIdx != wsfTraceCb.prodIdx)
{
memcpy(&outBuf, &wsfTraceCb.ringBuf[wsfTraceCb.consIdx], sizeof(wsfTraceCb.ringBuf[0]));
outBufIdx = 0;
wsfTraceCb.consIdx = (wsfTraceCb.consIdx + 1) & (WSF_RING_BUF_SIZE - 1);
return TRUE;
}
return FALSE;
}
#endif
@@ -0,0 +1,252 @@
/*************************************************************************************************/
/*!
* \file wsf_trace.h
*
* \brief Trace message interface.
*
* $Date: 2015-08-11 07:08:51 -0700 (Tue, 11 Aug 2015) $
* $Revision: 3555 $
*
* Copyright (c) 2009 Wicentric, Inc., all rights reserved.
* Wicentric confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact Wicentric, Inc. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#ifndef WSF_TRACE_H
#define WSF_TRACE_H
/**************************************************************************************************
Data Types
**************************************************************************************************/
/*! \brief Token event handler. */
typedef void (*WsfTokenHandler_t)(void);
/**************************************************************************************************
Function Prototypes
**************************************************************************************************/
void WsfTrace(const char *pStr, ...);
void WsfToken(uint32_t tok, uint32_t var);
void WsfPacketTrace(uint8_t ui8Type, uint32_t ui32Len, uint8_t *pui8Buf);
/* Token management. */
bool_t WsfTokenService(void);
uint8_t WsfTokenIOWrite(uint8_t *pBuf, uint8_t len);
/**************************************************************************************************
Macros
**************************************************************************************************/
#ifdef WSF_TRACE_ENABLED
#ifndef AM_DEBUG_PRINTF
#undef WSF_TRACE_ENABLED
#warning "AM_DEBUG_PRINTF is needed when WSF_TRACE_ENABLED is defined"
#endif
#endif
#ifdef TOKEN_GENERATION
#define WSF_TOKEN(subsys, stat, msg) \
__WSF_TOKEN_DEFINE__( \
/* token: */ MODULE_ID, __LINE__, \
/* origin: */ __FILE__, subsys, \
/* message: */ stat, msg)
#define WSF_TRACE0(subsys, stat, msg) WSF_TOKEN(subsys, stat, msg)
#define WSF_TRACE1(subsys, stat, msg, var1) WSF_TOKEN(subsys, stat, msg)
#define WSF_TRACE2(subsys, stat, msg, var1, var2) WSF_TOKEN(subsys, stat, msg)
#define WSF_TRACE3(subsys, stat, msg, var1, var2, var3) WSF_TOKEN(subsys, stat, msg)
#define PACKET_TRACE(type, len, buf)
#elif WSF_TRACE_ENABLED == TRUE
#define WSF_TRACE0(subsys, stat, msg) WsfTrace(msg)
#define WSF_TRACE1(subsys, stat, msg, var1) WsfTrace(msg, var1)
#define WSF_TRACE2(subsys, stat, msg, var1, var2) WsfTrace(msg, var1, var2)
#define WSF_TRACE3(subsys, stat, msg, var1, var2, var3) WsfTrace(msg, var1, var2, var3)
#define PACKET_TRACE(type, len, buf) WsfPacketTrace(type, len, buf)
#elif WSF_TOKEN_ENABLED == TRUE
#define WSF_TRACE0(subsys, stat, msg) \
WsfToken(((__LINE__ & 0xFFF) << 16) | MODULE_ID, 0)
#define WSF_TRACE1(subsys, stat, msg, var1) \
WsfToken(((__LINE__ & 0xFFF) << 16) | MODULE_ID, (uint32_t)(var1))
#define WSF_TRACE2(subsys, stat, msg, var1, var2) \
WsfToken(((__LINE__ & 0xFFF) << 16) | MODULE_ID, (uint32_t)(((var2) << 16) | ((var1) & 0xFFFF)))
#define WSF_TRACE3(subsys, stat, msg, var1, var2, var3) \
WsfToken(((__LINE__ & 0xFFF) << 16) | MODULE_ID, (uint32_t)((((var3) & 0xFF) << 16) | (((var2) & 0xFF) << 8) | ((var1) & 0xFF)))
#define PACKET_TRACE(type, len, buf)
#else
#define WSF_TRACE0(subsys, stat, msg)
#define WSF_TRACE1(subsys, stat, msg, var1)
#define WSF_TRACE2(subsys, stat, msg, var1, var2)
#define WSF_TRACE3(subsys, stat, msg, var1, var2, var3)
#define PACKET_TRACE(type, len, buf)
#endif
#define WSF_TRACE_INFO0(msg)
#define WSF_TRACE_INFO1(msg, var1)
#define WSF_TRACE_INFO2(msg, var1, var2)
#define WSF_TRACE_INFO3(msg, var1, var2, var3)
#define WSF_TRACE_WARN0(msg) WSF_TRACE0("WSF", "WARN", msg)
#define WSF_TRACE_WARN1(msg, var1) WSF_TRACE1("WSF", "WARN", msg, var1)
#define WSF_TRACE_WARN2(msg, var1, var2) WSF_TRACE2("WSF", "WARN", msg, var1, var2)
#define WSF_TRACE_WARN3(msg, var1, var2, var3) WSF_TRACE3("WSF", "WARN", msg, var1, var2, var3)
#define WSF_TRACE_ERR0(msg) WSF_TRACE0("WSF", "ERR", msg)
#define WSF_TRACE_ERR1(msg, var1) WSF_TRACE1("WSF", "ERR", msg, var1)
#define WSF_TRACE_ERR2(msg, var1, var2) WSF_TRACE2("WSF", "ERR", msg, var1, var2)
#define WSF_TRACE_ERR3(msg, var1, var2, var3) WSF_TRACE3("WSF", "ERR", msg, var1, var2, var3)
#define WSF_TRACE_ALLOC0(msg)
#define WSF_TRACE_ALLOC1(msg, var1)
#define WSF_TRACE_ALLOC2(msg, var1, var2)
#define WSF_TRACE_ALLOC3(msg, var1, var2, var3)
#define WSF_TRACE_FREE0(msg)
#define WSF_TRACE_FREE1(msg, var1)
#define WSF_TRACE_FREE2(msg, var1, var2)
#define WSF_TRACE_FREE3(msg, var1, var2, var3)
#define WSF_TRACE_MSG0(msg)
#define WSF_TRACE_MSG1(msg, var1)
#define WSF_TRACE_MSG2(msg, var1, var2)
#define WSF_TRACE_MSG3(msg, var1, var2, var3)
#ifdef HCI_TRACE_ENABLED
#define HCI_TRACE_INFO0(msg) WSF_TRACE0("HCI", "INFO", msg)
#define HCI_TRACE_INFO1(msg, var1) WSF_TRACE1("HCI", "INFO", msg, var1)
#define HCI_TRACE_INFO2(msg, var1, var2) WSF_TRACE2("HCI", "INFO", msg, var1, var2)
#define HCI_TRACE_INFO3(msg, var1, var2, var3) WSF_TRACE3("HCI", "INFO", msg, var1, var2, var3)
#define HCI_TRACE_WARN0(msg) WSF_TRACE0("HCI", "WARN", msg)
#define HCI_TRACE_WARN1(msg, var1) WSF_TRACE1("HCI", "WARN", msg, var1)
#define HCI_TRACE_WARN2(msg, var1, var2) WSF_TRACE2("HCI", "WARN", msg, var1, var2)
#define HCI_TRACE_WARN3(msg, var1, var2, var3) WSF_TRACE3("HCI", "WARN", msg, var1, var2, var3)
#define HCI_TRACE_ERR0(msg) WSF_TRACE0("HCI", "ERR", msg)
#define HCI_TRACE_ERR1(msg, var1) WSF_TRACE1("HCI", "ERR", msg, var1)
#define HCI_TRACE_ERR2(msg, var1, var2) WSF_TRACE2("HCI", "ERR", msg, var1, var2)
#define HCI_TRACE_ERR3(msg, var1, var2, var3) WSF_TRACE3("HCI", "ERR", msg, var1, var2, var3)
#define HCI_PDUMP_CMD(len, pBuf) PACKET_TRACE(0x1, len, pBuf)
#define HCI_PDUMP_EVT(len, pBuf) PACKET_TRACE(0x4, len, pBuf)
#define HCI_PDUMP_TX_ACL(len, pBuf) PACKET_TRACE(0x2, len, pBuf)
#define HCI_PDUMP_RX_ACL(len, pBuf) PACKET_TRACE(0x2, len, pBuf)
#else
#define HCI_TRACE_INFO0(msg)
#define HCI_TRACE_INFO1(msg, var1)
#define HCI_TRACE_INFO2(msg, var1, var2)
#define HCI_TRACE_INFO3(msg, var1, var2, var3)
#define HCI_TRACE_WARN0(msg)
#define HCI_TRACE_WARN1(msg, var1)
#define HCI_TRACE_WARN2(msg, var1, var2)
#define HCI_TRACE_WARN3(msg, var1, var2, var3)
#define HCI_TRACE_ERR0(msg)
#define HCI_TRACE_ERR1(msg, var1)
#define HCI_TRACE_ERR2(msg, var1, var2)
#define HCI_TRACE_ERR3(msg, var1, var2, var3)
#define HCI_PDUMP_CMD(len, pBuf)
#define HCI_PDUMP_EVT(len, pBuf)
#define HCI_PDUMP_TX_ACL(len, pBuf)
#define HCI_PDUMP_RX_ACL(len, pBuf)
#endif //HCI_TRACE_ENABLED
#define DM_TRACE_INFO0(msg) WSF_TRACE0("DM", "INFO", msg)
#define DM_TRACE_INFO1(msg, var1) WSF_TRACE1("DM", "INFO", msg, var1)
#define DM_TRACE_INFO2(msg, var1, var2) WSF_TRACE2("DM", "INFO", msg, var1, var2)
#define DM_TRACE_INFO3(msg, var1, var2, var3) WSF_TRACE3("DM", "INFO", msg, var1, var2, var3)
#define DM_TRACE_WARN0(msg) WSF_TRACE0("DM", "WARN", msg)
#define DM_TRACE_WARN1(msg, var1) WSF_TRACE1("DM", "WARN", msg, var1)
#define DM_TRACE_WARN2(msg, var1, var2) WSF_TRACE2("DM", "WARN", msg, var1, var2)
#define DM_TRACE_WARN3(msg, var1, var2, var3) WSF_TRACE3("DM", "WARN", msg, var1, var2, var3)
#define DM_TRACE_ERR0(msg) WSF_TRACE0("DM", "ERR", msg)
#define DM_TRACE_ERR1(msg, var1) WSF_TRACE1("DM", "ERR", msg, var1)
#define DM_TRACE_ERR2(msg, var1, var2) WSF_TRACE2("DM", "ERR", msg, var1, var2)
#define DM_TRACE_ERR3(msg, var1, var2, var3) WSF_TRACE3("DM", "ERR", msg, var1, var2, var3)
#define DM_TRACE_ALLOC0(msg) WSF_TRACE0("DM", "ALLOC", msg)
#define DM_TRACE_ALLOC1(msg, var1) WSF_TRACE1("DM", "ALLOC", msg, var1)
#define DM_TRACE_ALLOC2(msg, var1, var2) WSF_TRACE2("DM", "ALLOC", msg, var1, var2)
#define DM_TRACE_ALLOC3(msg, var1, var2, var3) WSF_TRACE3("DM", "ALLOC", msg, var1, var2, var3)
#define DM_TRACE_FREE0(msg) WSF_TRACE0("DM", "FREE", msg)
#define DM_TRACE_FREE1(msg, var1) WSF_TRACE1("DM", "FREE", msg, var1)
#define DM_TRACE_FREE2(msg, var1, var2) WSF_TRACE2("DM", "FREE", msg, var1, var2)
#define DM_TRACE_FREE3(msg, var1, var2, var3) WSF_TRACE3("DM", "FREE", msg, var1, var2, var3)
#define L2C_TRACE_INFO0(msg) WSF_TRACE0("L2C", "INFO", msg)
#define L2C_TRACE_INFO1(msg, var1) WSF_TRACE1("L2C", "INFO", msg, var1)
#define L2C_TRACE_INFO2(msg, var1, var2) WSF_TRACE2("L2C", "INFO", msg, var1, var2)
#define L2C_TRACE_INFO3(msg, var1, var2, var3) WSF_TRACE3("L2C", "INFO", msg, var1, var2, var3)
#define L2C_TRACE_WARN0(msg) WSF_TRACE0("L2C", "WARN", msg)
#define L2C_TRACE_WARN1(msg, var1) WSF_TRACE1("L2C", "WARN", msg, var1)
#define L2C_TRACE_WARN2(msg, var1, var2) WSF_TRACE2("L2C", "WARN", msg, var1, var2)
#define L2C_TRACE_WARN3(msg, var1, var2, var3) WSF_TRACE3("L2C", "WARN", msg, var1, var2, var3)
#define L2C_TRACE_ERR0(msg) WSF_TRACE0("L2C", "ERR", msg)
#define L2C_TRACE_ERR1(msg, var1) WSF_TRACE1("L2C", "ERR", msg, var1)
#define L2C_TRACE_ERR2(msg, var1, var2) WSF_TRACE2("L2C", "ERR", msg, var1, var2)
#define L2C_TRACE_ERR3(msg, var1, var2, var3) WSF_TRACE3("L2C", "ERR", msg, var1, var2, var3)
#define ATT_TRACE_INFO0(msg) WSF_TRACE0("ATT", "INFO", msg)
#define ATT_TRACE_INFO1(msg, var1) WSF_TRACE1("ATT", "INFO", msg, var1)
#define ATT_TRACE_INFO2(msg, var1, var2) WSF_TRACE2("ATT", "INFO", msg, var1, var2)
#define ATT_TRACE_INFO3(msg, var1, var2, var3) WSF_TRACE3("ATT", "INFO", msg, var1, var2, var3)
#define ATT_TRACE_WARN0(msg) WSF_TRACE0("ATT", "WARN", msg)
#define ATT_TRACE_WARN1(msg, var1) WSF_TRACE1("ATT", "WARN", msg, var1)
#define ATT_TRACE_WARN2(msg, var1, var2) WSF_TRACE2("ATT", "WARN", msg, var1, var2)
#define ATT_TRACE_WARN3(msg, var1, var2, var3) WSF_TRACE3("ATT", "WARN", msg, var1, var2, var3)
#define ATT_TRACE_ERR0(msg) WSF_TRACE0("ATT", "ERR", msg)
#define ATT_TRACE_ERR1(msg, var1) WSF_TRACE1("ATT", "ERR", msg, var1)
#define ATT_TRACE_ERR2(msg, var1, var2) WSF_TRACE2("ATT", "ERR", msg, var1, var2)
#define ATT_TRACE_ERR3(msg, var1, var2, var3) WSF_TRACE3("ATT", "ERR", msg, var1, var2, var3)
#define SMP_TRACE_INFO0(msg) WSF_TRACE0("SMP", "INFO", msg)
#define SMP_TRACE_INFO1(msg, var1) WSF_TRACE1("SMP", "INFO", msg, var1)
#define SMP_TRACE_INFO2(msg, var1, var2) WSF_TRACE2("SMP", "INFO", msg, var1, var2)
#define SMP_TRACE_INFO3(msg, var1, var2, var3) WSF_TRACE3("SMP", "INFO", msg, var1, var2, var3)
#define SMP_TRACE_WARN0(msg) WSF_TRACE0("SMP", "WARN", msg)
#define SMP_TRACE_WARN1(msg, var1) WSF_TRACE1("SMP", "WARN", msg, var1)
#define SMP_TRACE_WARN2(msg, var1, var2) WSF_TRACE2("SMP", "WARN", msg, var1, var2)
#define SMP_TRACE_WARN3(msg, var1, var2, var3) WSF_TRACE3("SMP", "WARN", msg, var1, var2, var3)
#define SMP_TRACE_ERR0(msg) WSF_TRACE0("SMP", "ERR", msg)
#define SMP_TRACE_ERR1(msg, var1) WSF_TRACE1("SMP", "ERR", msg, var1)
#define SMP_TRACE_ERR2(msg, var1, var2) WSF_TRACE2("SMP", "ERR", msg, var1, var2)
#define SMP_TRACE_ERR3(msg, var1, var2, var3) WSF_TRACE3("SMP", "ERR", msg, var1, var2, var3)
#define APP_TRACE_INFO0(msg) WSF_TRACE0("APP", "INFO", msg)
#define APP_TRACE_INFO1(msg, var1) WSF_TRACE1("APP", "INFO", msg, var1)
#define APP_TRACE_INFO2(msg, var1, var2) WSF_TRACE2("APP", "INFO", msg, var1, var2)
#define APP_TRACE_INFO3(msg, var1, var2, var3) WSF_TRACE3("APP", "INFO", msg, var1, var2, var3)
#define APP_TRACE_WARN0(msg) WSF_TRACE0("APP", "WARN", msg)
#define APP_TRACE_WARN1(msg, var1) WSF_TRACE1("APP", "WARN", msg, var1)
#define APP_TRACE_WARN2(msg, var1, var2) WSF_TRACE2("APP", "WARN", msg, var1, var2)
#define APP_TRACE_WARN3(msg, var1, var2, var3) WSF_TRACE3("APP", "WARN", msg, var1, var2, var3)
#define APP_TRACE_ERR0(msg) WSF_TRACE0("APP", "ERR", msg)
#define APP_TRACE_ERR1(msg, var1) WSF_TRACE1("APP", "ERR", msg, var1)
#define APP_TRACE_ERR2(msg, var1, var2) WSF_TRACE2("APP", "ERR", msg, var1, var2)
#define APP_TRACE_ERR3(msg, var1, var2, var3) WSF_TRACE3("APP", "ERR", msg, var1, var2, var3)
#define LL_TRACE_INFO0(msg) WSF_TRACE0("LL", "INFO", msg)
#define LL_TRACE_INFO1(msg, var1) WSF_TRACE1("LL", "INFO", msg, var1)
#define LL_TRACE_INFO2(msg, var1, var2) WSF_TRACE2("LL", "INFO", msg, var1, var2)
#define LL_TRACE_INFO3(msg, var1, var2, var3) WSF_TRACE3("LL", "INFO", msg, var1, var2, var3)
#define LL_TRACE_WARN0(msg) WSF_TRACE0("LL", "WARN", msg)
#define LL_TRACE_WARN1(msg, var1) WSF_TRACE1("LL", "WARN", msg, var1)
#define LL_TRACE_WARN2(msg, var1, var2) WSF_TRACE2("LL", "WARN", msg, var1, var2)
#define LL_TRACE_WARN3(msg, var1, var2, var3) WSF_TRACE3("LL", "WARN", msg, var1, var2, var3)
#define LL_TRACE_ERR0(msg) WSF_TRACE0("LL", "ERR", msg)
#define LL_TRACE_ERR1(msg, var1) WSF_TRACE1("LL", "ERR", msg, var1)
#define LL_TRACE_ERR2(msg, var1, var2) WSF_TRACE2("LL", "ERR", msg, var1, var2)
#define LL_TRACE_ERR3(msg, var1, var2, var3) WSF_TRACE3("LL", "ERR", msg, var1, var2, var3)
#endif /* WSF_TRACE_H */
@@ -0,0 +1,62 @@
/*************************************************************************************************/
/*!
* \file wsf_types.h
*
* \brief Platform-independent data types.
*
* $Date: 2015-05-14 14:58:23 -0700 (Thu, 14 May 2015) $
* $Revision: 2837 $
*
* Copyright (c) 2009 Wicentric, Inc., all rights reserved.
* Wicentric confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact Wicentric, Inc. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#ifndef WSF_TYPES_H
#define WSF_TYPES_H
/**************************************************************************************************
Macros
**************************************************************************************************/
#ifndef NULL
#define NULL 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/**************************************************************************************************
Data Types
**************************************************************************************************/
/* Integer data types */
#if ((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) && \
(!defined(__ICC8051__) || (__ICC8051__ == 0)))
#include <stdint.h>
#else
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed long int32_t;
typedef unsigned long uint32_t;
typedef unsigned long long uint64_t;
#endif
/* Boolean data type */
typedef uint8_t bool_t;
#endif /* WSF_TYPES_H */
@@ -0,0 +1,127 @@
/*************************************************************************************************/
/*!
* \file bda.c
*
* \brief Bluetooth device address utilities.
*
* $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $
* $Revision: 10805 $
*
* Copyright (c) 2009-2017 ARM Ltd., all rights reserved.
* ARM Ltd. confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact ARM Ltd. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#include <string.h>
#include "wsf_types.h"
#include "bda.h"
/*************************************************************************************************/
/*!
* \fn BdaCpy
*
* \brief Copy a BD address from source to destination.
*
* \param pDst Pointer to destination.
* \param pSrc Pointer to source.
*
* \return None.
*/
/*************************************************************************************************/
void BdaCpy(uint8_t *pDst, const uint8_t *pSrc)
{
memcpy(pDst, pSrc, BDA_ADDR_LEN);
}
/*************************************************************************************************/
/*!
* \fn BdaCmp
*
* \brief Compare two BD addresses.
*
* \param pAddr1 First address.
* \param pAddr2 Second address.
*
* \return TRUE if addresses match, FALSE otherwise.
*/
/*************************************************************************************************/
bool_t BdaCmp(const uint8_t *pAddr1, const uint8_t *pAddr2)
{
return (memcmp(pAddr1, pAddr2, BDA_ADDR_LEN) == 0);
}
/*************************************************************************************************/
/*!
* \fn BdaClr
*
* \brief Set a BD address to all zeros.
*
* \param pDst Pointer to destination.
*
* \return pDst + BDA_ADDR_LEN
*/
/*************************************************************************************************/
uint8_t *BdaClr(uint8_t *pDst)
{
memset(pDst, 0, BDA_ADDR_LEN);
return (pDst + BDA_ADDR_LEN);
}
/*************************************************************************************************/
/*!
* \fn BdaIsZeros
*
* \brief Check if a BD address is all zeros.
*
* \param pAddr Pointer to address.
*
* \return TRUE if address is all zeros, FALSE otherwise.
*/
/*************************************************************************************************/
bool_t BdaIsZeros(const uint8_t *pAddr)
{
uint8_t addrZeros[BDA_ADDR_LEN] = { 0 };
return (memcmp(pAddr, addrZeros, BDA_ADDR_LEN) == 0);
}
/*************************************************************************************************/
/*!
* \fn Bda2Str
*
* \brief Convert a BD address to a string.
*
* \param pAddr Pointer to BD address.
*
* \return Pointer to string.
*/
/*************************************************************************************************/
char *Bda2Str(const uint8_t *pAddr)
{
static const char hex[] = "0123456789ABCDEF";
static char str[BDA_ADDR_STR_LEN + 1];
char *pStr = str;
/* address is little endian so copy in reverse */
pAddr += BDA_ADDR_LEN;
while (pStr < &str[BDA_ADDR_STR_LEN])
{
*pStr++ = hex[*--pAddr >> 4];
*pStr++ = hex[*pAddr & 0x0F];
}
/* null terminate string */
*pStr = 0;
return str;
}
@@ -0,0 +1,140 @@
/*************************************************************************************************/
/*!
* \file bda.h
*
* \brief Bluetooth device address utilities.
*
* $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $
* $Revision: 10805 $
*
* Copyright (c) 2009-2017 ARM Ltd., all rights reserved.
* ARM Ltd. confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact ARM Ltd. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#ifndef BDA_H
#define BDA_H
#ifdef __cplusplus
extern "C" {
#endif
/**************************************************************************************************
Macros
**************************************************************************************************/
/*! \brief BD address length */
#define BDA_ADDR_LEN 6
/*! \brief BD address string length */
#define BDA_ADDR_STR_LEN (BDA_ADDR_LEN * 2)
/*! \brief BDA RPA check */
#define BDA_ADDR_IS_RPA(bda) (((bda)[5] & 0xC0) == 0x40)
/*! \brief BDA NRPA check */
#define BDA_ADDR_IS_NRPA(bda) (((bda)[5] & 0xC0) == 0x00)
/*! \brief BDA static random check */
#define BDA_ADDR_IS_STATIC(bda) (((bda)[5] & 0xC0) == 0xC0)
/*! \brief BDA64 RPA check */
#define BDA64_ADDR_IS_RPA(bda64) ((((bda64) >> 40) & 0xC0) == 0x40)
/*! \brief BDA64 NRPA check */
#define BDA64_ADDR_IS_NRPA(bda64) ((((bda64) >> 40) & 0xC0) == 0x00)
/*! \brief BDA64 static random check */
#define BDA64_ADDR_IS_STATIC(bda64) ((((bda64) >> 40) & 0xC0) == 0xC0)
/**************************************************************************************************
Data Types
**************************************************************************************************/
/*! \brief BD address data type */
typedef uint8_t bdAddr_t[BDA_ADDR_LEN];
/**************************************************************************************************
Function Declarations
**************************************************************************************************/
/*************************************************************************************************/
/*!
* \fn BdaCpy
*
* \brief Copy a BD address from source to destination.
*
* \param pDst Pointer to destination.
* \param pSrc Pointer to source.
*
* \return None.
*/
/*************************************************************************************************/
void BdaCpy(uint8_t *pDst, const uint8_t *pSrc);
/*************************************************************************************************/
/*!
* \fn BdaCmp
*
* \brief Compare two BD addresses.
*
* \param pAddr1 First address.
* \param pAddr2 Second address.
*
* \return TRUE if addresses match, FALSE otherwise.
*/
/*************************************************************************************************/
bool_t BdaCmp(const uint8_t *pAddr1, const uint8_t *pAddr2);
/*************************************************************************************************/
/*!
* \fn BdaClr
*
* \brief Set a BD address to all zeros.
*
* \param pDst Pointer to destination.
*
* \return pDst + BDA_ADDR_LEN
*/
/*************************************************************************************************/
uint8_t *BdaClr(uint8_t *pDst);
/*************************************************************************************************/
/*!
* \fn BdaIsZeros
*
* \brief Check if a BD address is all zeros.
*
* \param pAddr Pointer to address.
*
* \return TRUE if address is all zeros, FALSE otherwise.
*/
/*************************************************************************************************/
bool_t BdaIsZeros(const uint8_t *pAddr);
/*************************************************************************************************/
/*!
* \fn Bda2Str
*
* \brief Convert a BD address to a string.
*
* \param pAddr Pointer to BD address.
*
* \return Pointer to string.
*/
/*************************************************************************************************/
char *Bda2Str(const uint8_t *pAddr);
#ifdef __cplusplus
};
#endif
#endif /* BDA_H */
@@ -0,0 +1,106 @@
/*************************************************************************************************/
/*!
* \file bstream.h
*
* \brief Byte stream to integer conversion functions.
*
* $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $
* $Revision: 10805 $
*
* Copyright (c) 2009-2017 ARM Ltd., all rights reserved.
* ARM Ltd. confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact ARM Ltd. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#include "wsf_types.h"
#include "bstream.h"
/*************************************************************************************************/
/*!
* \brief Convert bstream to uint64_t.
*
* \param p Bstream pointer.
*
* \return Resulting uint64_t number.
*/
/*************************************************************************************************/
uint64_t BstreamToUint64(const uint8_t *p)
{
return ((uint64_t)p[0] << 0) |
((uint64_t)p[1] << 8) |
((uint64_t)p[2] << 16) |
((uint64_t)p[3] << 24) |
((uint64_t)p[4] << 32) |
((uint64_t)p[5] << 40) |
((uint64_t)p[6] << 48) |
((uint64_t)p[7] << 56);
}
/*************************************************************************************************/
/*!
* \brief Convert uint64_t to bstream.
*
* \param p Bstream pointer.
* \param n uint64_t number.
*
* \return None.
*/
/*************************************************************************************************/
void Uint64ToBstream(uint8_t *p, uint64_t n)
{
p[0] = (uint8_t)(n >> 0);
p[1] = (uint8_t)(n >> 8);
p[2] = (uint8_t)(n >> 16);
p[3] = (uint8_t)(n >> 24);
p[4] = (uint8_t)(n >> 32);
p[5] = (uint8_t)(n >> 40);
p[6] = (uint8_t)(n >> 48);
p[7] = (uint8_t)(n >> 56);
}
/*************************************************************************************************/
/*!
* \brief Convert bstream to BDA64.
*
* \param p Bstream pointer.
*
* \return Resulting BDA64 number.
*/
/*************************************************************************************************/
uint64_t BstreamToBda64(const uint8_t *p)
{
return (uint64_t)p[0] << 0 |
(uint64_t)p[1] << 8 |
(uint64_t)p[2] << 16 |
(uint64_t)p[3] << 24 |
(uint64_t)p[4] << 32 |
(uint64_t)p[5] << 40;
}
/*************************************************************************************************/
/*!
* \brief Convert BDA64 to bstream.
*
* \param p Bstream pointer.
* \param bda uint64_t BDA.
*
* \return None.
*/
/*************************************************************************************************/
void Bda64ToBstream(uint8_t *p, uint64_t bda)
{
p[0] = (uint8_t)(bda >> 0);
p[1] = (uint8_t)(bda >> 8);
p[2] = (uint8_t)(bda >> 16);
p[3] = (uint8_t)(bda >> 24);
p[4] = (uint8_t)(bda >> 32);
p[5] = (uint8_t)(bda >> 40);
}
@@ -0,0 +1,149 @@
/*************************************************************************************************/
/*!
* \file bstream.h
*
* \brief Byte stream to integer conversion macros.
*
* $Date: 2017-02-06 19:25:09 -0600 (Mon, 06 Feb 2017) $
* $Revision: 11104 $
*
* Copyright (c) 2009-2017 ARM Ltd., all rights reserved.
* ARM Ltd. confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact ARM Ltd. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#ifndef BSTREAM_H
#define BSTREAM_H
#include "bda.h"
#ifdef __cplusplus
extern "C" {
#endif
/**************************************************************************************************
Macros
**************************************************************************************************/
/*!
* Macros for converting a little endian byte buffer to integers.
*/
#define BYTES_TO_UINT16(n, p) {n = ((uint16_t)(p)[0] + ((uint16_t)(p)[1] << 8));}
#define BYTES_TO_UINT24(n, p) {n = ((uint16_t)(p)[0] + ((uint16_t)(p)[1] << 8) + \
((uint16_t)(p)[2] << 16));}
#define BYTES_TO_UINT32(n, p) {n = ((uint32_t)(p)[0] + ((uint32_t)(p)[1] << 8) + \
((uint32_t)(p)[2] << 16) + ((uint32_t)(p)[3] << 24));}
#define BYTES_TO_UINT40(n, p) {n = ((uint64_t)(p)[0] + ((uint64_t)(p)[1] << 8) + \
((uint64_t)(p)[2] << 16) + ((uint64_t)(p)[3] << 24) + \
((uint64_t)(p)[4] << 32));}
#define BYTES_TO_UINT64(n, p) {n = ((uint64_t)(p)[0] + ((uint64_t)(p)[1] << 8) + \
((uint64_t)(p)[2] << 16) + ((uint64_t)(p)[3] << 24) + \
((uint64_t)(p)[4] << 32) + ((uint64_t)(p)[5] << 40) + \
((uint64_t)(p)[6] << 48) + ((uint64_t)(p)[7] << 56));}
/*!
* Macros for converting little endian integers to array of bytes
*/
#define UINT16_TO_BYTES(n) ((uint8_t) (n)), ((uint8_t)((n) >> 8))
#define UINT32_TO_BYTES(n) ((uint8_t) (n)), ((uint8_t)((n) >> 8)), ((uint8_t)((n) >> 16)), ((uint8_t)((n) >> 24))
/*!
* Macros for converting little endian integers to single bytes
*/
#define UINT16_TO_BYTE0(n) ((uint8_t) (n))
#define UINT16_TO_BYTE1(n) ((uint8_t) ((n) >> 8))
#define UINT32_TO_BYTE0(n) ((uint8_t) (n))
#define UINT32_TO_BYTE1(n) ((uint8_t) ((n) >> 8))
#define UINT32_TO_BYTE2(n) ((uint8_t) ((n) >> 16))
#define UINT32_TO_BYTE3(n) ((uint8_t) ((n) >> 24))
/*!
* Macros for converting a little endian byte stream to integers, with increment.
*/
#define BSTREAM_TO_INT8(n, p) {n = (int8_t)(*(p)++);}
#define BSTREAM_TO_UINT8(n, p) {n = (uint8_t)(*(p)++);}
#define BSTREAM_TO_UINT16(n, p) {BYTES_TO_UINT16(n, p); p += 2;}
#define BSTREAM_TO_UINT24(n, p) {BYTES_TO_UINT24(n, p); p += 3;}
#define BSTREAM_TO_UINT32(n, p) {BYTES_TO_UINT32(n, p); p += 4;}
#define BSTREAM_TO_UINT40(n, p) {BYTES_TO_UINT40(n, p); p += 5;}
#define BSTREAM_TO_UINT64(n, p) {n = BstreamToUint64(p); p += 8;}
#define BSTREAM_TO_BDA(bda, p) {BdaCpy(bda, p); p += BDA_ADDR_LEN;}
#define BSTREAM_TO_BDA64(bda, p) {bda = BstreamToBda64(p); p += BDA_ADDR_LEN;}
/*!
* Macros for converting integers to a little endian byte stream, with increment.
*/
#define UINT8_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n);}
#define UINT16_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n); *(p)++ = (uint8_t)((n) >> 8);}
#define UINT24_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n); *(p)++ = (uint8_t)((n) >> 8); \
*(p)++ = (uint8_t)((n) >> 16);}
#define UINT32_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n); *(p)++ = (uint8_t)((n) >> 8); \
*(p)++ = (uint8_t)((n) >> 16); *(p)++ = (uint8_t)((n) >> 24);}
#define UINT40_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n); *(p)++ = (uint8_t)((n) >> 8); \
*(p)++ = (uint8_t)((n) >> 16); *(p)++ = (uint8_t)((n) >> 24); \
*(p)++ = (uint8_t)((n) >> 32);}
#define UINT64_TO_BSTREAM(p, n) {Uint64ToBstream(p, n); p += sizeof(uint64_t);}
#define BDA_TO_BSTREAM(p, bda) {BdaCpy(p, bda); p += BDA_ADDR_LEN;}
#define BDA64_TO_BSTREAM(p, bda) {Bda64ToBstream(p, bda); p += BDA_ADDR_LEN;}
/*!
* Macros for converting integers to a little endian byte stream, without increment.
*/
#define UINT16_TO_BUF(p, n) {(p)[0] = (uint8_t)(n); (p)[1] = (uint8_t)((n) >> 8);}
#define UINT24_TO_BUF(p, n) {(p)[0] = (uint8_t)(n); (p)[1] = (uint8_t)((n) >> 8); \
(p)[2] = (uint8_t)((n) >> 16);}
#define UINT32_TO_BUF(p, n) {(p)[0] = (uint8_t)(n); (p)[1] = (uint8_t)((n) >> 8); \
(p)[2] = (uint8_t)((n) >> 16); (p)[3] = (uint8_t)((n) >> 24);}
#define UINT40_TO_BUF(p, n) {(p)[0] = (uint8_t)(n); (p)[1] = (uint8_t)((n) >> 8); \
(p)[2] = (uint8_t)((n) >> 16); (p)[3] = (uint8_t)((n) >> 24);\
(p)[4] = (uint8_t)((n) >> 32);}
/*!
* Macros for comparing a little endian byte buffer to integers.
*/
#define BYTES_UINT16_CMP(p, n) ((p)[1] == UINT16_TO_BYTE1(n) && (p)[0] == UINT16_TO_BYTE0(n))
/*!
* Macros for IEEE FLOAT type: exponent = byte 3, mantissa = bytes 2-0
*/
#define FLT_TO_UINT32(m, e) ((m) | ((int32_t)(e) << 24))
#define UINT32_TO_FLT(m, e, n) {m = UINT32_TO_FLT_M(n); e = UINT32_TO_FLT_E(n);}
#define UINT32_TO_FLT_M(n) ((((n) & 0x00FFFFFF) >= 0x00800000) ? \
((int32_t)(((n) | 0xFF000000))) : ((int32_t)((n) & 0x00FFFFFF)))
#define UINT32_TO_FLT_E(n) ((int8_t)(n >> 24))
/*!
* Macros for IEEE SFLOAT type: exponent = bits 15-12, mantissa = bits 11-0
*/
#define SFLT_TO_UINT16(m, e) ((m) | ((int16_t)(e) << 12))
#define UINT16_TO_SFLT(m, e, n) {m = UINT16_TO_SFLT_M(n); e = UINT16_TO_SFLT_E(n);}
#define UINT16_TO_SFLT_M(n) ((((n) & 0x0FFF) >= 0x0800) ? \
((int16_t)(((n) | 0xF000))) : ((int16_t)((n) & 0x0FFF)))
#define UINT16_TO_SFLT_E(n) (((n >> 12) >= 0x0008) ? \
((int8_t)(((n >> 12) | 0xF0))) : ((int8_t)(n >> 12)))
/**************************************************************************************************
Function Declarations
**************************************************************************************************/
uint64_t BstreamToBda64(const uint8_t *p);
uint64_t BstreamToUint64(const uint8_t *p);
void Bda64ToBstream(uint8_t *p, uint64_t bda);
void Uint64ToBstream(uint8_t *p, uint64_t n);
#ifdef __cplusplus
};
#endif
#endif /* BSTREAM_H */
@@ -0,0 +1,92 @@
/*************************************************************************************************/
/*!
* \file calc128.c
*
* \brief 128-bit integer utilities.
*
* $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $
* $Revision: 10805 $
*
* Copyright (c) 2010-2017 ARM Ltd., all rights reserved.
* ARM Ltd. confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact ARM Ltd. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#include <string.h>
#include "wsf_types.h"
#include "calc128.h"
/**************************************************************************************************
Global Variables
**************************************************************************************************/
/* 128-bit zero value */
const uint8_t calc128Zeros[CALC128_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
/**************************************************************************************************
Function Declarations
**************************************************************************************************/
/*************************************************************************************************/
/*!
* \fn Calc128Cpy
*
* \brief Copy a 128-bit integer from source to destination.
*
* \param pDst Pointer to destination.
* \param pSrc Pointer to source.
*
* \return None.
*/
/*************************************************************************************************/
void Calc128Cpy(uint8_t *pDst, uint8_t *pSrc)
{
memcpy(pDst, pSrc, CALC128_LEN);
}
/*************************************************************************************************/
/*!
* \fn Calc128Cpy64
*
* \brief Copy a 64-bit integer from source to destination.
*
* \param pDst Pointer to destination.
* \param pSrc Pointer to source.
*
* \return None.
*/
/*************************************************************************************************/
void Calc128Cpy64(uint8_t *pDst, uint8_t *pSrc)
{
memcpy(pDst, pSrc, CALC128_LEN/2);
}
/*************************************************************************************************/
/*!
* \fn Calc128Xor
*
* \brief Exclusive-or two 128-bit integers and return the result in pDst.
*
* \param pDst Pointer to destination.
* \param pSrc Pointer to source.
*
* \return None.
*/
/*************************************************************************************************/
void Calc128Xor(uint8_t *pDst, uint8_t *pSrc)
{
uint8_t i;
for (i = CALC128_LEN; i > 0; i--)
{
*pDst++ ^= *pSrc++;
}
}
@@ -0,0 +1,93 @@
/*************************************************************************************************/
/*!
* \file calc128.h
*
* \brief 128-bit integer utilities.
*
* $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $
* $Revision: 10805 $
*
* Copyright (c) 2010-2017 ARM Ltd., all rights reserved.
* ARM Ltd. confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact ARM Ltd. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#ifndef CALC128_H
#define CALC128_H
#ifdef __cplusplus
extern "C" {
#endif
/**************************************************************************************************
Macros
**************************************************************************************************/
/*! 128-bit integer length in bytes */
#define CALC128_LEN 16
/**************************************************************************************************
Global Variables
**************************************************************************************************/
/*! 128-bit zero value */
extern const uint8_t calc128Zeros[CALC128_LEN];
/**************************************************************************************************
Function Declarations
**************************************************************************************************/
/*************************************************************************************************/
/*!
* \fn Calc128Cpy
*
* \brief Copy a 128-bit integer from source to destination.
*
* \param pDst Pointer to destination.
* \param pSrc Pointer to source.
*
* \return None.
*/
/*************************************************************************************************/
void Calc128Cpy(uint8_t *pDst, uint8_t *pSrc);
/*************************************************************************************************/
/*!
* \fn Calc128Cpy64
*
* \brief Copy a 64-bit integer from source to destination.
*
* \param pDst Pointer to destination.
* \param pSrc Pointer to source.
*
* \return None.
*/
/*************************************************************************************************/
void Calc128Cpy64(uint8_t *pDst, uint8_t *pSrc);
/*************************************************************************************************/
/*!
* \fn Calc128Xor
*
* \brief Exclusive-or two 128-bit integers and return the result in pDst.
*
* \param pDst Pointer to destination.
* \param pSrc Pointer to source.
*
* \return None.
*/
/*************************************************************************************************/
void Calc128Xor(uint8_t *pDst, uint8_t *pSrc);
#ifdef __cplusplus
};
#endif
#endif /* CALC128_H */
@@ -0,0 +1,128 @@
/*************************************************************************************************/
/*!
* \file crc32.c
*
* \brief CRC-32 utilities.
*
* $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $
* $Revision: 10805 $
*
* Copyright (c) 2010-2017 ARM Ltd., all rights reserved.
* ARM Ltd. confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact ARM Ltd. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#include "wsf_types.h"
#include "crc32.h"
/**************************************************************************************************
Local Variables
**************************************************************************************************/
static const uint32_t crc32Table[256] =
{
0x00000000U, 0x77073096U, 0xEE0E612CU, 0x990951BAU,
0x076DC419U, 0x706AF48FU, 0xE963A535U, 0x9E6495A3U,
0x0EDB8832U, 0x79DCB8A4U, 0xE0D5E91EU, 0x97D2D988U,
0x09B64C2BU, 0x7EB17CBDU, 0xE7B82D07U, 0x90BF1D91U,
0x1DB71064U, 0x6AB020F2U, 0xF3B97148U, 0x84BE41DEU,
0x1ADAD47DU, 0x6DDDE4EBU, 0xF4D4B551U, 0x83D385C7U,
0x136C9856U, 0x646BA8C0U, 0xFD62F97AU, 0x8A65C9ECU,
0x14015C4FU, 0x63066CD9U, 0xFA0F3D63U, 0x8D080DF5U,
0x3B6E20C8U, 0x4C69105EU, 0xD56041E4U, 0xA2677172U,
0x3C03E4D1U, 0x4B04D447U, 0xD20D85FDU, 0xA50AB56BU,
0x35B5A8FAU, 0x42B2986CU, 0xDBBBC9D6U, 0xACBCF940U,
0x32D86CE3U, 0x45DF5C75U, 0xDCD60DCFU, 0xABD13D59U,
0x26D930ACU, 0x51DE003AU, 0xC8D75180U, 0xBFD06116U,
0x21B4F4B5U, 0x56B3C423U, 0xCFBA9599U, 0xB8BDA50FU,
0x2802B89EU, 0x5F058808U, 0xC60CD9B2U, 0xB10BE924U,
0x2F6F7C87U, 0x58684C11U, 0xC1611DABU, 0xB6662D3DU,
0x76DC4190U, 0x01DB7106U, 0x98D220BCU, 0xEFD5102AU,
0x71B18589U, 0x06B6B51FU, 0x9FBFE4A5U, 0xE8B8D433U,
0x7807C9A2U, 0x0F00F934U, 0x9609A88EU, 0xE10E9818U,
0x7F6A0DBBU, 0x086D3D2DU, 0x91646C97U, 0xE6635C01U,
0x6B6B51F4U, 0x1C6C6162U, 0x856530D8U, 0xF262004EU,
0x6C0695EDU, 0x1B01A57BU, 0x8208F4C1U, 0xF50FC457U,
0x65B0D9C6U, 0x12B7E950U, 0x8BBEB8EAU, 0xFCB9887CU,
0x62DD1DDFU, 0x15DA2D49U, 0x8CD37CF3U, 0xFBD44C65U,
0x4DB26158U, 0x3AB551CEU, 0xA3BC0074U, 0xD4BB30E2U,
0x4ADFA541U, 0x3DD895D7U, 0xA4D1C46DU, 0xD3D6F4FBU,
0x4369E96AU, 0x346ED9FCU, 0xAD678846U, 0xDA60B8D0U,
0x44042D73U, 0x33031DE5U, 0xAA0A4C5FU, 0xDD0D7CC9U,
0x5005713CU, 0x270241AAU, 0xBE0B1010U, 0xC90C2086U,
0x5768B525U, 0x206F85B3U, 0xB966D409U, 0xCE61E49FU,
0x5EDEF90EU, 0x29D9C998U, 0xB0D09822U, 0xC7D7A8B4U,
0x59B33D17U, 0x2EB40D81U, 0xB7BD5C3BU, 0xC0BA6CADU,
0xEDB88320U, 0x9ABFB3B6U, 0x03B6E20CU, 0x74B1D29AU,
0xEAD54739U, 0x9DD277AFU, 0x04DB2615U, 0x73DC1683U,
0xE3630B12U, 0x94643B84U, 0x0D6D6A3EU, 0x7A6A5AA8U,
0xE40ECF0BU, 0x9309FF9DU, 0x0A00AE27U, 0x7D079EB1U,
0xF00F9344U, 0x8708A3D2U, 0x1E01F268U, 0x6906C2FEU,
0xF762575DU, 0x806567CBU, 0x196C3671U, 0x6E6B06E7U,
0xFED41B76U, 0x89D32BE0U, 0x10DA7A5AU, 0x67DD4ACCU,
0xF9B9DF6FU, 0x8EBEEFF9U, 0x17B7BE43U, 0x60B08ED5U,
0xD6D6A3E8U, 0xA1D1937EU, 0x38D8C2C4U, 0x4FDFF252U,
0xD1BB67F1U, 0xA6BC5767U, 0x3FB506DDU, 0x48B2364BU,
0xD80D2BDAU, 0xAF0A1B4CU, 0x36034AF6U, 0x41047A60U,
0xDF60EFC3U, 0xA867DF55U, 0x316E8EEFU, 0x4669BE79U,
0xCB61B38CU, 0xBC66831AU, 0x256FD2A0U, 0x5268E236U,
0xCC0C7795U, 0xBB0B4703U, 0x220216B9U, 0x5505262FU,
0xC5BA3BBEU, 0xB2BD0B28U, 0x2BB45A92U, 0x5CB36A04U,
0xC2D7FFA7U, 0xB5D0CF31U, 0x2CD99E8BU, 0x5BDEAE1DU,
0x9B64C2B0U, 0xEC63F226U, 0x756AA39CU, 0x026D930AU,
0x9C0906A9U, 0xEB0E363FU, 0x72076785U, 0x05005713U,
0x95BF4A82U, 0xE2B87A14U, 0x7BB12BAEU, 0x0CB61B38U,
0x92D28E9BU, 0xE5D5BE0DU, 0x7CDCEFB7U, 0x0BDBDF21U,
0x86D3D2D4U, 0xF1D4E242U, 0x68DDB3F8U, 0x1FDA836EU,
0x81BE16CDU, 0xF6B9265BU, 0x6FB077E1U, 0x18B74777U,
0x88085AE6U, 0xFF0F6A70U, 0x66063BCAU, 0x11010B5CU,
0x8F659EFFU, 0xF862AE69U, 0x616BFFD3U, 0x166CCF45U,
0xA00AE278U, 0xD70DD2EEU, 0x4E048354U, 0x3903B3C2U,
0xA7672661U, 0xD06016F7U, 0x4969474DU, 0x3E6E77DBU,
0xAED16A4AU, 0xD9D65ADCU, 0x40DF0B66U, 0x37D83BF0U,
0xA9BCAE53U, 0xDEBB9EC5U, 0x47B2CF7FU, 0x30B5FFE9U,
0xBDBDF21CU, 0xCABAC28AU, 0x53B39330U, 0x24B4A3A6U,
0xBAD03605U, 0xCDD70693U, 0x54DE5729U, 0x23D967BFU,
0xB3667A2EU, 0xC4614AB8U, 0x5D681B02U, 0x2A6F2B94U,
0xB40BBE37U, 0xC30C8EA1U, 0x5A05DF1BU, 0x2D02EF8DU
};
/*************************************************************************************************/
/*!
* \fn CalcCrc32
*
* \brief Calculate the CRC-32 of the given buffer.
*
* \param crcInit Initial value of the CRC.
* \param len Length of the buffer.
* \param pBuf Buffer to compute the CRC.
*
* \return None.
*
* This routine was originally generated with crcmod.py using the following parameters:
* - polynomial 0x104C11DB7
* - bit reverse algorithm
*/
/*************************************************************************************************/
uint32_t CalcCrc32(uint32_t crcInit, uint32_t len, uint8_t *pBuf)
{
uint32_t crc = crcInit;
while (len > 0)
{
crc = crc32Table[*pBuf ^ (uint8_t)crc] ^ (crc >> 8);
pBuf++;
len--;
}
crc = crc ^ 0xFFFFFFFFU;
return crc;
}
@@ -0,0 +1,52 @@
/*************************************************************************************************/
/*!
* \file crc32.h
*
* \brief CRC-32 utilities.
*
* $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $
* $Revision: 10805 $
*
* Copyright (c) 2010-2017 ARM Ltd., all rights reserved.
* ARM Ltd. confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact ARM Ltd. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#ifndef CRC32_H
#define CRC32_H
#ifdef __cplusplus
extern "C" {
#endif
/*************************************************************************************************/
/*!
* \fn CalcCrc32
*
* \brief Calculate the CRC-32 of the given buffer.
*
* \param crcInit Initial value of the CRC.
* \param len Length of the buffer.
* \param pBuf Buffer to compute the CRC.
*
* \return None.
*
* This routine was originally generated with crcmod.py using the following parameters:
* - polynomial 0x104C11DB7
* - bit reverse algorithm
*/
/*************************************************************************************************/
uint32_t CalcCrc32(uint32_t crcInit, uint32_t len, uint8_t *pBuf);
#ifdef __cplusplus
};
#endif
#endif /* CRC32_H */
@@ -0,0 +1,308 @@
/*************************************************************************************************/
/*!
* \file print.c
*
* \brief Utility functions.
*
* $Date: 2016-03-29 14:55:12 -0700 (Tue, 29 Mar 2016) $
* $Revision: 6524 $
*
* Copyright (c) 2015-2017 ARM Ltd., all rights reserved.
* ARM confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact ARM Ltd. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#include <string.h>
#include "print.h"
/**************************************************************************************************
Macros
**************************************************************************************************/
/*! \brief Detect hexadecimal digits. */
#define PRINT_IS_XDIGIT(c) (((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'f')) || \
((c >= 'A') && (c <= 'F')))
/*! \brief Convert hexadecimal digit to integer. */
#define PRINT_XDIGIT_TO_INT(c) (((c >= '0') && (c <= '9')) ? (uint8_t)(c - '0') : \
((c >= 'a') && (c <= 'f')) ? (uint8_t)(c - 'a' + 10u) : \
((c >= 'A') && (c <= 'F')) ? (uint8_t)(c - 'A' + 10u) : 0u)
/*************************************************************************************************/
/*!
* \fn printFmtInt
*
* \brief Format an integer.
*
* \param pStr Storage for formatted integer.
* \param maxLen Maximum number of characters to store.
* \param i Integer to format.
* \param base Integer base.
* \param sign TRUE if sign should be printed.
* \param width Width of field.
*
* \return Number of characters stored.
*/
/*************************************************************************************************/
static int printFmtInt(char *pStr, int maxLen, int i, uint8_t base, bool_t sign, int width)
{
char *s, *p = pStr;
unsigned int u = (unsigned int) i;
uint8_t use_width;
int t;
use_width = width;
if (i == 0)
{
s = "0\0";
width--;
goto almost;
}
if (sign && base == 10 && i < 0)
{
*pStr++ = '-';
u = (unsigned int)-i;
width--;
}
s = pStr + maxLen - 1;
*s = '\0';
while (u && (!use_width || (width > 0)))
{
t = (unsigned int)u % base;
if (t >= 10)
{
t += 'A' - '0' - 10;
}
*--s = (char)(t + '0');
u /= base;
width--;
}
almost:
while (width > 0)
{
*pStr++ = '0';
width--;
}
strcpy(pStr, s);
return strlen(p);
}
/*************************************************************************************************/
/*!
* \fn printParseInt
*
* \brief Parse an integer from a string.
*
* \param pStr String to parse.
* \param pInt Storage for parsed integer.
* \param base Integer base.
*
* \return Number of characters consumed.
*/
/*************************************************************************************************/
static int32_t printParseInt(const char *pStr, uint32_t *pInt, uint32_t base)
{
int32_t r = 0;
if (base == 0)
{
if (*pStr == '0')
{
if (((*(pStr + 1) == 'x') || (*(pStr + 1) == 'X')) && PRINT_IS_XDIGIT(*(pStr + 2)))
{
r += 2;
pStr += 2;
base = 16;
}
else
{
base = 8;
}
}
else
{
base = 10;
}
}
else if (base == 16)
{
if (*pStr == '0')
{
if (((*(pStr + 1) == 'x') || (*(pStr + 1) == 'X')) && PRINT_IS_XDIGIT(*(pStr + 2)))
{
r += 2;
pStr += 2;
}
}
}
/* One character is required; all characters must be consumed. */
*pInt = 0;
do
{
char c;
uint8_t t;
c = *pStr++;
if (!PRINT_IS_XDIGIT(c))
{
break;
}
t = PRINT_XDIGIT_TO_INT(c);
if (t >= base)
{
break;
}
*pInt *= base;
*pInt += t;
r++;
} while (*pStr != '\0');
return r;
}
/*************************************************************************************************/
/*!
* \fn PrintVsn
*
* \brief Print a trace message.
*
* \param pStr Storage for formatted string.
* \param size Maximum number of characters to store.
* \param pFmt Format string.
* \param ap Arguments.
*
* \return Number of characters stored.
*/
/*************************************************************************************************/
uint32_t PrintVsn(char *pStr, uint32_t size, const char *pFmt, va_list ap)
{
size_t len = 0;
*pStr = 0;
size--; /* Ensure we null-terminate within our buffer */
while ((*pFmt != '\0') && (len < size))
{
uint32_t width = 0;
/* normal */
if (*pFmt != '%')
{
*pStr++ = *pFmt++;
len++;
continue;
}
pFmt++;
if (*pFmt == '%')
{
*pStr++ = '%';
len++;
pFmt++;
continue;
}
/* width */
if (*pFmt == '0')
{
pFmt += printParseInt(pFmt, &width, 10u);
}
/* long (ignore) */
if (*pFmt == 'l')
{
pFmt++;
}
switch(*pFmt)
{
/* character */
case 'c':
{
char tmp = va_arg(ap, int);
*pStr++ = tmp;
len++;
break;
}
/* unsigned decimal integer */
case 'u':
{
unsigned int tmp = va_arg(ap, unsigned int);
uint8_t lenTmp = printFmtInt(pStr, size - len, tmp, 10, 0, width);
pStr += lenTmp;
len += lenTmp;
break;
}
/* signed decimal integer */
case 'd':
{
int tmp = va_arg(ap, int);
uint8_t lenTmp = printFmtInt(pStr, size - len, tmp, 10, 1, width);
pStr += lenTmp;
len += lenTmp;
break;
}
/* pointer */
case 'p':
{
unsigned long tmp = va_arg(ap, unsigned long);
uint8_t lenTmp = printFmtInt(pStr, size - len, tmp, 16, 1, 8u);
pStr += lenTmp;
len += lenTmp;
break;
}
/* unsigned hexadecimal integer */
case 'x':
case 'X':
{
unsigned int tmp = va_arg(ap, unsigned int);
uint8_t lenTmp = printFmtInt(pStr, size - len, tmp, 16, 0, width);
pStr += lenTmp;
len += lenTmp;
break;
}
/* string */
case 's':
{
char *tmp = va_arg(ap, char *);
while ((tmp != NULL) && (*tmp != '\0') && (len < size))
{
*pStr++ = *tmp++;
len++;
}
break;
}
default:
break;
}
pFmt++;
}
/* Null-terminate output. */
*pStr = 0;
if (len > size)
{
/* Compensate for -1 earlier. */
return size + 2;
}
return len;
}
@@ -0,0 +1,57 @@
/*************************************************************************************************/
/*!
* \file print.h
*
* \brief Print functions.
*
* $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $
* $Revision: 10805 $
*
* Copyright (c) 2015-2017 ARM Ltd., all rights reserved.
* ARM confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact ARM Ltd. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#ifndef PRINT_H
#define PRINT_H
#include <stdarg.h>
#include "wsf_types.h"
/**************************************************************************************************
Macros
**************************************************************************************************/
/*! \brief Print function attributes. */
#if defined(__GNUC__) || defined(__CC_ARM)
#define PRINT_ATTRIBUTE(a, b) __attribute__((format(printf, a, b)))
#else
#define PRINT_ATTRIBUTE(a, b)
#endif
/*************************************************************************************************/
/*!
* \fn UtilVsnPrintf
*
* \brief Print a trace message.
*
* \param pStr Storage for formatted string.
* \param size Maximum number of characters to store.
* \param pFmt Format string.
* \param ap Arguments.
*
* \return Number of characters stored.
*/
/*************************************************************************************************/
uint32_t PrintVsn(char *pStr, uint32_t size, const char *pFmt, va_list ap) PRINT_ATTRIBUTE(3, 0);
#endif /* PRINT_H */
@@ -0,0 +1,532 @@
/*************************************************************************************************/
/*!
* \file terminal.c
*
* \brief Terminal handler.
*
* $Date: 2016-03-29 14:55:12 -0700 (Tue, 29 Mar 2016) $
* $Revision: 6524 $
*
* Copyright (c) 2015-2017 ARM Ltd., all rights reserved.
* ARM confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact ARM Ltd. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "terminal.h"
#include "print.h"
#include "wsf_types.h"
#include "wsf_assert.h"
#include "wsf_trace.h"
#include "bstream.h"
/**************************************************************************************************
Macros
**************************************************************************************************/
#define TERMINAL_IS_SPACE(c) ((c == '\n') || (c == '\t') || (c == '\r') || (c == ' ') || (c == '\v') || (c == '\f'))
#define TERMINAL_IS_PRINT(c) ((c >= 0x20) && (c != 0x7F))
/*! \brief Terminal events. */
enum
{
TERMINAL_EVENT_COMMAND_RX = (1 << 0)
};
/**************************************************************************************************
Data Types
**************************************************************************************************/
/*! \brief Control block for terminal. */
typedef struct
{
wsfHandlerId_t handlerId; /*!< Handler ID for TerminalHandler(). */
terminalCommand_t *pFirstCommand; /*!< Pointer to first command. */
char buf[TERMINAL_MAX_COMMAND_LEN + 1]; /*!< Command buffer. */
bool_t isExecuting; /*!< TRUE if command in buffer is executing. */
bool_t doEcho; /*!< TRUE if input should be echoed. */
uint32_t bufOffset; /*!< Offset within buffer. */
terminalUartTx_t terminalTx; /*!< Function to transmit via UART. */
} terminalCtrlBlk_t;
/**************************************************************************************************
Local Function Prototypes
**************************************************************************************************/
/*! \brief Help Command Handler */
static uint8_t terminalCommandHelpHandler(uint32_t argc, char **argv);
/*! \brief Echo Command Handler */
static uint8_t terminalCommandEchoHandler(uint32_t argc, char **argv);
/**************************************************************************************************
Local Variables
**************************************************************************************************/
/*! \brief Control block for terminal. */
static terminalCtrlBlk_t terminalCb;
/*! \brief Help command. */
static terminalCommand_t terminalCommandHelp = { NULL, "help", "help", terminalCommandHelpHandler };
/*! \brief Echo command. */
static terminalCommand_t terminalCommandEcho = { NULL, "echo", "echo <on|off>", terminalCommandEchoHandler };
/*************************************************************************************************/
/*!
* \fn TerminalInit
*
* \brief Initialize terminal.
*
* \param handlerId Handler ID for TerminalHandler().
*
* \return None.
*/
/*************************************************************************************************/
void TerminalInit(wsfHandlerId_t handlerId)
{
APP_TRACE_INFO0("terminal: init");
terminalCb.handlerId = handlerId;
terminalCb.pFirstCommand = NULL;
terminalCb.isExecuting = FALSE;
terminalCb.doEcho = TRUE;
terminalCb.bufOffset = 0;
TerminalRegisterCommand(&terminalCommandHelp);
TerminalRegisterCommand(&terminalCommandEcho);
}
/*************************************************************************************************/
/*!
* \fn TerminalRegisterUartTxFunc
*
* \brief Register the UART Tx Function for the platform.
*
* \return None.
*/
/*************************************************************************************************/
void TerminalRegisterUartTxFunc(terminalUartTx_t uartTxFunc)
{
terminalCb.terminalTx = uartTxFunc;
}
/*************************************************************************************************/
/*!
* \fn TerminalRegisterCommand
*
* \brief Register command with terminal.
*
* \param pCommand Command.
*
* \return None.
*/
/*************************************************************************************************/
void TerminalRegisterCommand(terminalCommand_t *pCommand)
{
terminalCommand_t *pCommandTemp = terminalCb.pFirstCommand;
if (pCommandTemp == NULL)
{
terminalCb.pFirstCommand = pCommand;
}
else
{
while (pCommandTemp->pNext != NULL)
{
pCommandTemp = pCommandTemp->pNext;
}
pCommandTemp->pNext = pCommand;
}
pCommand->pNext = NULL;
}
/*************************************************************************************************/
/*!
* \fn terminalExecute
*
* \brief Execute a received command.
*
* \param pBuf Command string.
*
* \return None.
*/
/*************************************************************************************************/
static void terminalExecute(char *pBuf)
{
uint32_t argc = 0;
char *argv[TERMINAL_MAX_ARGC + 1];
uint32_t length;
char *pBufCur;
int state;
enum
{
STATE_OUTSIDE_OF_ARG,
STATE_JUST_GOT_QUOTE,
STATE_INSIDE_OF_ARG,
STATE_INSIDE_OF_ARG_IN_QUOTES
};
/* Parse arguments in command */
state = STATE_OUTSIDE_OF_ARG;
length = strlen(pBuf);
for (pBufCur = pBuf; pBufCur < pBuf + length; pBufCur++)
{
switch (state)
{
case STATE_OUTSIDE_OF_ARG:
{
if (*pBufCur == '\"')
{
state = STATE_JUST_GOT_QUOTE;
}
else if (!TERMINAL_IS_SPACE(*pBufCur))
{
state = STATE_INSIDE_OF_ARG;
if (argc < TERMINAL_MAX_ARGC)
{
argv[argc] = pBufCur;
}
argc++;
}
break;
}
case STATE_JUST_GOT_QUOTE:
{
if (argc < TERMINAL_MAX_ARGC)
{
argv[state] = pBufCur;
}
argc++;
if (*pBufCur == '\"')
{
state = STATE_OUTSIDE_OF_ARG;
*pBufCur = '\0';
}
else
{
state = STATE_INSIDE_OF_ARG_IN_QUOTES;
}
break;
}
case STATE_INSIDE_OF_ARG:
{
if (TERMINAL_IS_SPACE(*pBufCur))
{
state = STATE_OUTSIDE_OF_ARG;
*pBufCur = '\0';
}
else if (*pBufCur == '\"')
{
state = STATE_JUST_GOT_QUOTE;
*pBufCur = '\0';
}
break;
}
case STATE_INSIDE_OF_ARG_IN_QUOTES:
{
if (*pBufCur == '\"')
{
state = STATE_OUTSIDE_OF_ARG;
*pBufCur = '\0';
}
break;
}
}
}
/* Find & invoke command. */
if (argc > TERMINAL_MAX_ARGC)
{
TerminalTxStr(TERMINAL_STRING_ERROR "too many arguments" TERMINAL_STRING_NEW_LINE);
}
else if (argc > 0)
{
terminalCommand_t *pCommand = terminalCb.pFirstCommand;
while (pCommand != NULL)
{
if (strcmp(pCommand->pName, argv[0]) == 0)
{
break;
}
pCommand = pCommand->pNext;
}
if (pCommand == NULL)
{
TerminalTxStr(TERMINAL_STRING_ERROR "unrecognized command \"");
TerminalTxStr(argv[0]);
TerminalTxStr("\"" TERMINAL_STRING_NEW_LINE);
}
else
{
uint8_t r = pCommand->handler(argc, argv);
switch (r)
{
case TERMINAL_ERROR_EXEC:
case TERMINAL_ERROR_OK:
break;
case TERMINAL_ERROR_BAD_ARGUMENTS:
TerminalTxStr(TERMINAL_STRING_ERROR "Invalid argument(s)" TERMINAL_STRING_NEW_LINE);
break;
case TERMINAL_ERROR_TOO_FEW_ARGUMENTS:
TerminalTxStr(TERMINAL_STRING_ERROR "Too few arguments" TERMINAL_STRING_NEW_LINE);
break;
case TERMINAL_ERROR_TOO_MANY_ARGUMENTS:
TerminalTxStr(TERMINAL_STRING_ERROR "Too many arguments" TERMINAL_STRING_NEW_LINE);
break;
default:
TerminalTxStr(TERMINAL_STRING_ERROR "Unknown error" TERMINAL_STRING_NEW_LINE);
break;
}
}
}
}
/*************************************************************************************************/
/*!
* \fn TerminalHandler
*
* \brief Handler for terminal messages.
*
* \param event WSF event mask.
* \param pMsg WSF message.
*
* \return None.
*/
/*************************************************************************************************/
void TerminalHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg)
{
if ((event & TERMINAL_EVENT_COMMAND_RX) != 0)
{
terminalExecute(terminalCb.buf);
TerminalTxStr(TERMINAL_STRING_PROMPT);
terminalCb.bufOffset = 0;
terminalCb.isExecuting = FALSE;
}
}
/*************************************************************************************************/
/*!
* \fn TerminalRx
*
* \brief Called by application when a data byte is received.
*
* \param dataByte Received byte.
*
* \return None.
*/
/*************************************************************************************************/
void TerminalRx(uint8_t dataByte)
{
/* Hands off buf if command is executing. */
if (!terminalCb.isExecuting)
{
/* If this is the end of a line, signal task. */
if ((dataByte == '\n') || (dataByte == '\r'))
{
TerminalTxStr(TERMINAL_STRING_NEW_LINE);
terminalCb.buf[terminalCb.bufOffset] = '\0';
WsfSetEvent(terminalCb.handlerId, TERMINAL_EVENT_COMMAND_RX);
terminalCb.isExecuting = TRUE;
}
/* Check for delete. */
else if (dataByte == 0x7F)
{
if (terminalCb.bufOffset > 0)
{
terminalCb.bufOffset--;
if (terminalCb.doEcho)
{
TerminalTxStr("\b \b");
}
}
}
/* If we still have room in the buf, put it in buf. Othewise ignore it. */
else if (terminalCb.bufOffset < TERMINAL_MAX_COMMAND_LEN)
{
/* Ignore non-printable characters. */
if (TERMINAL_IS_PRINT(dataByte))
{
terminalCb.buf[terminalCb.bufOffset] = dataByte;
terminalCb.bufOffset++;
if (terminalCb.doEcho)
{
TerminalTxChar(dataByte);
}
}
}
}
}
/*************************************************************************************************/
/*!
* \fn TerminalTxStr
*
* \brief Called by application to transmit string.
*
* \param pStr String.
*
* \return None.
*/
/*************************************************************************************************/
void TerminalTxStr(const char *pStr)
{
TerminalTx((const uint8_t *)pStr, strlen(pStr));
}
/*************************************************************************************************/
/*!
* \fn TerminalTxChar
*
* \brief Called by application to transmit character.
*
* \param c Character.
*
* \return None.
*/
/*************************************************************************************************/
void TerminalTxChar(char c)
{
TerminalTx((const uint8_t *)&c, 1);
}
/*************************************************************************************************/
/*!
* \fn TerminalTxPrint
*
* \brief Called by application to print formatted data.
*
* \param pStr Message format string
* \param ... Additional arguments, printf-style
*
* \return None.
*/
/*************************************************************************************************/
void TerminalTxPrint(const char *pStr, ...)
{
uint32_t len;
char buf[TERMINAL_PRINTF_MAX_LEN];
va_list args;
va_start(args, pStr);
len = PrintVsn(buf, TERMINAL_PRINTF_MAX_LEN, pStr, args);
va_end(args);
TerminalTx((uint8_t *)buf, len);
}
/*************************************************************************************************/
/*!
* \fn terminalCommandHelpHandler
*
* \brief Handler for a terminal command.
*
* \param argc The number of arguments passed to the command.
* \param argv The array of arguments; the 0th argument is the command.
*
* \return Error code.
*/
/*************************************************************************************************/
static uint8_t terminalCommandHelpHandler(uint32_t argc, char **argv)
{
terminalCommand_t *pCommand = terminalCb.pFirstCommand;
if (argc > 1)
{
return TERMINAL_ERROR_TOO_MANY_ARGUMENTS;
}
while (pCommand != NULL)
{
TerminalTxStr(pCommand->pHelpStr);
TerminalTxStr(TERMINAL_STRING_NEW_LINE);
pCommand = pCommand->pNext;
}
TerminalTxStr(TERMINAL_STRING_NEW_LINE);
return TERMINAL_ERROR_OK;
}
/*************************************************************************************************/
/*!
* \fn TerminalTx
*
* \brief Transmit buffer on platform UART.
*
* \param pBuf Buffer to transmit.
* \param len Length of buffer in octets.
*
* \return None.
*/
/*************************************************************************************************/
void TerminalTx(const uint8_t *pData, uint16_t len)
{
WSF_ASSERT(terminalCb.terminalTx);
(*terminalCb.terminalTx)(pData, len);
}
/*************************************************************************************************/
/*!
* \fn terminalCommandEchoHandler
*
* \brief Handler for a terminal command.
*
* \param argc The number of arguments passed to the command.
* \param argv The array of arguments; the 0th argument is the command.
*
* \return Error code.
*/
/*************************************************************************************************/
static uint8_t terminalCommandEchoHandler(uint32_t argc, char **argv)
{
if (argc < 2)
{
return TERMINAL_ERROR_TOO_FEW_ARGUMENTS;
}
else if (argc == 2)
{
if (strcmp(argv[1], "on") == 0)
{
terminalCb.doEcho = TRUE;
TerminalTxStr("echo on" TERMINAL_STRING_NEW_LINE);
}
else if (strcmp(argv[1], "off") == 0)
{
terminalCb.doEcho = FALSE;
TerminalTxStr("echo off" TERMINAL_STRING_NEW_LINE);
}
else
{
return TERMINAL_ERROR_BAD_ARGUMENTS;
}
}
else
{
return TERMINAL_ERROR_TOO_MANY_ARGUMENTS;
}
return TERMINAL_ERROR_OK;
}
@@ -0,0 +1,212 @@
/*************************************************************************************************/
/*!
* \file terminal.h
*
* \brief Terminal handler.
*
* $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $
* $Revision: 10805 $
*
* Copyright (c) 2015-2017 ARM Ltd., all rights reserved.
* ARM confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact ARM Ltd. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#ifndef TERMINAL_H
#define TERMINAL_H
#include <stdarg.h>
#include "wsf_types.h"
#include "wsf_os.h"
/**************************************************************************************************
Macros
**************************************************************************************************/
#define TERMINAL_MAX_ARGC 8u /*!< Maximum number of arguments to any command. */
#define TERMINAL_MAX_COMMAND_LEN 100u /*!< Maximum length of command line. */
#define TERMINAL_PRINTF_MAX_LEN 128u /*!< Maximum length of any printed output. */
#define TERMINAL_STRING_PROMPT "> " /*!< Prompt string. */
#define TERMINAL_STRING_ERROR "ERROR: " /*!< Error prefix. */
#define TERMINAL_STRING_USAGE "USAGE: " /*!< Usage prefix. */
#define TERMINAL_STRING_NEW_LINE "\r\n" /*!< New line string. */
/*! \brief Terminal command error codes. */
enum
{
TERMINAL_ERROR_OK = 0, /*!< Command completed. */
TERMINAL_ERROR_BAD_ARGUMENTS = 1, /*!< ERROR: Invalid argument(s) */
TERMINAL_ERROR_TOO_FEW_ARGUMENTS = 2, /*!< ERROR: Too few arguments */
TERMINAL_ERROR_TOO_MANY_ARGUMENTS = 3, /*!< ERROR: Too many arguments */
TERMINAL_ERROR_EXEC = 4 /*!< Command completed with execution error. */
};
/**************************************************************************************************
Data Types
**************************************************************************************************/
/*************************************************************************************************/
/*!
* \brief Handler for a terminal command.
*
* \param argc The number of arguments passed to the command.
* \param argv The array of arguments; the 0th argument is the command.
*
* \return Error code.
*/
/*************************************************************************************************/
typedef uint8_t (*terminalHandler_t)(uint32_t argc, char **argv);
/*************************************************************************************************/
/*!
* \brief Handler for transmit.
*
* \param pBuf Buffer to transmit.
* \param len Number of bytes to transmit.
*
* \return None.
*/
/*************************************************************************************************/
typedef void (*terminalUartTx_t)(const uint8_t *pBuf, uint32_t len);
/*! \brief Terminal command. */
typedef struct terminalCommand_tag
{
struct terminalCommand_tag *pNext; /*!< Pointer to next command in list. */
const char *pName; /*!< Name of command. */
const char *pHelpStr; /*!< Help String for command. */
terminalHandler_t handler; /*!< Handler for command. */
} terminalCommand_t;
/**************************************************************************************************
Function Prototypes
**************************************************************************************************/
/*************************************************************************************************/
/*!
* \fn TerminalInit
*
* \brief Initialize terminal.
*
* \param handlerId Handler ID for TerminalHandler().
*
* \return None.
*/
/*************************************************************************************************/
void TerminalInit(wsfHandlerId_t handlerId);
/*************************************************************************************************/
/*!
* \fn TerminalRegisterUartTxFunc
*
* \brief Register the UART Tx Function for the platform.
*
* \return None.
*/
/*************************************************************************************************/
void TerminalRegisterUartTxFunc(terminalUartTx_t uartTxFunc);
/*************************************************************************************************/
/*!
* \fn TerminalRegisterCommand
*
* \brief Register command with terminal.
*
* \param pCommand Command.
*
* \return None.
*/
/*************************************************************************************************/
void TerminalRegisterCommand(terminalCommand_t *pCommand);
/*************************************************************************************************/
/*!
* \fn TerminalHandler
*
* \brief Handler for terminal messages.
*
* \param event WSF event mask.
* \param pMsg WSF message.
*
* \return None.
*/
/*************************************************************************************************/
void TerminalHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg);
/*************************************************************************************************/
/*!
* \fn TerminalRx
*
* \brief Called by application when a data byte is received.
*
* \param dataByte received byte
*
* \return None.
*/
/*************************************************************************************************/
void TerminalRx(uint8_t dataByte);
/*************************************************************************************************/
/*!
* \fn TerminalTxStr
*
* \brief Called by application to transmit string.
*
* \param pStr String.
*
* \return None.
*/
/*************************************************************************************************/
void TerminalTxStr(const char *pStr);
/*************************************************************************************************/
/*!
* \fn TerminalTxChar
*
* \brief Called by application to transmit character.
*
* \param c Character.
*
* \return None.
*/
/*************************************************************************************************/
void TerminalTxChar(char c);
/*************************************************************************************************/
/*!
* \fn TerminalTxPrint
*
* \brief Called by application to print formatted data.
*
* \param pStr Message format string
* \param ... Additional arguments, printf-style
*
* \return None.
*/
/*************************************************************************************************/
void TerminalTxPrint(const char *pStr, ...);
/*************************************************************************************************/
/*!
* \fn TerminalTx
*
* \brief Application function to transmit data..
*
* \param pData Data.
* \param len Length of data, in bytes.
*
* \return None.
*/
/*************************************************************************************************/
void TerminalTx(const uint8_t *pData, uint16_t len);
#endif /* TERMINAL_H */
@@ -0,0 +1,98 @@
/*************************************************************************************************/
/*!
* \file wstr.c
*
* \brief String manipulation functions.
*
* $Date: 2017-02-14 15:31:43 -0600 (Tue, 14 Feb 2017) $
* $Revision: 11184 $
*
* Copyright (c) 2014-2017 ARM Ltd., all rights reserved.
* ARM Ltd. confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact ARM Ltd. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#include <string.h>
#include "wsf_types.h"
#include "wstr.h"
/*************************************************************************************************/
/*!
* \fn WstrnCpy
*
* \brief Copy a string and zero out space after the string length.
*
* \return none.
*/
/*************************************************************************************************/
void WstrnCpy(char *pBuf, const char *pData, uint8_t n)
{
uint8_t i;
uint8_t zeroing = FALSE;
for (i=0; i<n; i++)
{
if (!zeroing && pData[i] == '\0')
zeroing = TRUE;
if (zeroing)
*pBuf++ = 0;
else
*pBuf++ = pData[i];
}
}
/*************************************************************************************************/
/*!
* \fn WStrReverseCpy
*
* \brief Byte by byte reverse and copy a buffer.
*
* \param pBuf1 Buffer to hold reversed copy.
* \param pBuf2 Buffer to copy.
* \param len Size of pBuf1 and pBuf2 in bytes.
*
* \return None.
*/
/*************************************************************************************************/
void WStrReverseCpy(uint8_t *pBuf1, const uint8_t *pBuf2, uint16_t len)
{
int16_t i;
for (i=0; i<len; i++)
{
pBuf1[len-1-i] = pBuf2[i];
}
}
/*************************************************************************************************/
/*!
* \fn WStrReverse
*
* \brief Byte by byte reverse a buffer.
*
* \param pBuf Buffer to reverse.
* \param len size of pBuf in bytes.
*
* \return None.
*/
/*************************************************************************************************/
void WStrReverse(uint8_t *pBuf, uint8_t len)
{
uint8_t i, temp;
for (i=0; i<len/2; i++)
{
temp = pBuf[len-i-1];
pBuf[len-i-1] = pBuf[i];
pBuf[i] = temp;
}
}
@@ -0,0 +1,78 @@
/*************************************************************************************************/
/*!
* \file wstr.h
*
* \brief String manipulation functions.
*
* $Date: 2017-02-14 15:31:43 -0600 (Tue, 14 Feb 2017) $
* $Revision: 11184 $
*
* Copyright (c) 2014-2017 ARM Ltd., all rights reserved.
* ARM Ltd. confidential and proprietary.
*
* IMPORTANT. Your use of this file is governed by a Software License Agreement
* ("Agreement") that must be accepted in order to download or otherwise receive a
* copy of this file. You may not use or copy this file for any purpose other than
* as described in the Agreement. If you do not agree to all of the terms of the
* Agreement do not use this file and delete all copies in your possession or control;
* if you do not have a copy of the Agreement, you must contact ARM Ltd. prior
* to any use, copying or further distribution of this software.
*/
/*************************************************************************************************/
#ifndef WSTR_H
#define WSTR_H
#ifdef __cplusplus
extern "C" {
#endif
/*************************************************************************************************/
/*!
* \fn WstrnCpy
*
* \brief Copies a string up to a given length.
*
* \param pBuf Pointer to buffer to copy to.
* \param pData Pointer to the string to copy.
* \param n Size of pBuf in bytes.
*
* \return none.
*/
/*************************************************************************************************/
void WstrnCpy(char *pBuf, const char *pData, uint8_t n);
/*************************************************************************************************/
/*!
* \fn WStrReverseCpy
*
* \brief Byte by byte reverse and copy a buffer.
*
* \param pBuf1 Buffer to hold reversed copy.
* \param pBuf2 Buffer to copy.
* \param len Size of pBuf1 and pBuf2 in bytes.
*
* \return None.
*/
/*************************************************************************************************/
void WStrReverseCpy(uint8_t *pBuf1, const uint8_t *pBuf2, uint16_t len);
/*************************************************************************************************/
/*!
* \fn WStrReverse
*
* \brief Byte by byte reverse a buffer.
*
* \param pBuf Buffer to reverse.
* \param len size of pBuf in bytes.
*
* \return None.
*/
/*************************************************************************************************/
void WStrReverse(uint8_t *pBuf, uint8_t len);
#ifdef __cplusplus
}
#endif
#endif /* WSTR_H */